历史上的今天

今天是:2024年09月16日(星期一)

2018年09月16日 | MSP430 SD卡SPI读写操作(4) —— FatFs文件系统实现

发布者:theta18 来源: eefocus关键字:MSP430  SD卡  SPI读写操  FatFs文件系统 手机看文章 扫描二维码
随时随地手机看文章

本节介绍MSP430F5438A FatFs文件系统的移植。


FatFs是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。FatFs模块与IO是分开的,因此移植时需要实现下面几个底层函数:



DSTATUS disk_initialize (BYTE drv); //初始化存储器

DSTATUS disk_status (BYTE drv); //获取存储器状态

DRESULT disk_read (BYTE drv, BYTE* buff, DWORD sector, UINT count); //读存储器

DRESULT disk_write (BYTE drv, const BYTE* buff, DWORD sector, UINT count); //写存储器

DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void* buff); //额外功能

DWORD get_fattime (void); //获取时间(此函数可以没有,和FatFs模块配置有关)


根据不同的处理器平台,需要修改 integer.h 相应的数据类型定义。

修改 ffconf.h 可以配置FatFs的功能。


下面是本人实现的MSP430F5438A平台的移植,使用官方函数库msp430_driverlib_2_60_00_02,使用IAR for msp430 6.3通过编译。


本节代码对SD卡进行了区分,程序在金士顿 8GB SDHC microSD卡经过验证可以正常运行。




diskio.h


/*-----------------------------------------------------------------------/

/  Low level disk interface modlue include file   (C)ChaN, 2014          /

/-----------------------------------------------------------------------*/

 

#ifndef _DISKIO_DEFINED

#define _DISKIO_DEFINED

 

#ifdef __cplusplus

extern "C" {

#endif

 

#include "integer.h"

 

 

/* Status of Disk Functions */

typedef BYTE    DSTATUS;

 

/* Results of Disk Functions */

typedef enum {

    RES_OK = 0,     /* 0: Successful */

    RES_ERROR,      /* 1: R/W Error */

    RES_WRPRT,      /* 2: Write Protected */

    RES_NOTRDY,     /* 3: Not Ready */

    RES_PARERR      /* 4: Invalid Parameter */

} DRESULT;

 

#define SD_INIT_CLK 125000

#define SD_HIGH_CLK 3125000

#define SD_CS_PORT GPIO_PORT_P9

#define SD_CS_PIN  GPIO_PIN0

 

/* MMC/SD command (SPI mode) */

#define CMD0 (0)           /* GO_IDLE_STATE */

#define CMD1 (1)           /* SEND_OP_COND */

#define ACMD41 (0x80+41)   /* SEND_OP_COND (SDC) */

#define CMD8 (8)           /* SEND_IF_COND */

#define CMD9 (9)           /* SEND_CSD */

#define CMD10 (10)         /* SEND_CID */

#define CMD12 (12)         /* STOP_TRANSMISSION */

#define CMD13 (13)         /* SEND_STATUS */

#define ACMD13 (0x80+13)   /* SD_STATUS (SDC) */

#define CMD16 (16)         /* SET_BLOCKLEN */

#define CMD17 (17)         /* READ_SINGLE_BLOCK */

#define CMD18 (18)         /* READ_MULTIPLE_BLOCK */

#define CMD23 (23)         /* SET_BLOCK_COUNT */

#define ACMD23 (0x80+23)   /* SET_WR_BLK_ERASE_COUNT (SDC) */

#define CMD24 (24)         /* WRITE_BLOCK */

#define CMD25 (25)         /* WRITE_MULTIPLE_BLOCK */

#define CMD32 (32)         /* ERASE_ER_BLK_START */

#define CMD33 (33)         /* ERASE_ER_BLK_END */

#define CMD38 (38)         /* ERASE */

#define CMD55 (55)         /* APP_CMD */

#define CMD58 (58)         /* READ_OCR */

/*---------------------------------------*/

/* Prototypes for disk control functions */

 

 

DSTATUS disk_initialize (BYTE drv);

DSTATUS disk_status (BYTE drv);

DRESULT disk_read (BYTE drv, BYTE* buff, DWORD sector, UINT count);

DRESULT disk_write (BYTE drv, const BYTE* buff, DWORD sector, UINT count);

DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void* buff);

 

 

/* Disk Status Bits (DSTATUS) */

 

#define STA_NOINIT      0x01    /* Drive not initialized */

#define STA_NODISK      0x02    /* No medium in the drive */

#define STA_PROTECT     0x04    /* Write protected */

 

 

/* Command code for disk_ioctrl fucntion */

 

/* Generic command (Used by FatFs) */

#define CTRL_SYNC           0   /* Complete pending write process (needed at _FS_READONLY == 0) */

#define GET_SECTOR_COUNT    1   /* Get media size (needed at _USE_MKFS == 1) */

#define GET_SECTOR_SIZE     2   /* Get sector size (needed at _MAX_SS != _MIN_SS) */

#define GET_BLOCK_SIZE      3   /* Get erase block size (needed at _USE_MKFS == 1) */

#define CTRL_TRIM           4   /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */

 

/* Generic command (Not used by FatFs) */

#define CTRL_POWER          5   /* Get/Set power status */

#define CTRL_LOCK           6   /* Lock/Unlock media removal */

#define CTRL_EJECT          7   /* Eject media */

#define CTRL_FORMAT         8   /* Create physical format on the media */

 

/* MMC/SDC specific ioctl command */

#define MMC_GET_TYPE        10  /* Get card type */

#define MMC_GET_CSD         11  /* Get CSD */

#define MMC_GET_CID         12  /* Get CID */

#define MMC_GET_OCR         13  /* Get OCR */

#define MMC_GET_SDSTAT      14  /* Get SD status */

#define ISDIO_READ          55  /* Read data form SD iSDIO register */

#define ISDIO_WRITE         56  /* Write data to SD iSDIO register */

#define ISDIO_MRITE         57  /* Masked write data to SD iSDIO register */

 

/* ATA/CF specific ioctl command */

#define ATA_GET_REV         20  /* Get F/W revision */

#define ATA_GET_MODEL       21  /* Get model name */

#define ATA_GET_SN          22  /* Get serial number */

 

/* MMC card type flags (MMC_GET_TYPE) */

#define CT_MMC      0x01        /* MMC ver 3 */

#define CT_SD1      0x02        /* SD ver 1 */

#define CT_SD2      0x04        /* SD ver 2 */

#define CT_SDC      (CT_SD1|CT_SD2) /* SD */

#define CT_BLOCK    0x08        /* Block addressing */

 

#ifdef __cplusplus

}

#endif

 

#endif


diskio.c


/*-----------------------------------------------------------------------*/

/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2016        */

/*-----------------------------------------------------------------------*/

#include "driverlib.h"

#include "../gateway_clk.h"

#include "diskio.h"

 

DSTATUS Stat = STA_NOINIT;

BYTE CardType;

 

static

void SD_csInit(void)

{

  GPIO_setAsOutputPin(SD_CS_PORT,SD_CS_PIN);

}

 

static

uint8_t SD_writeByte(BYTE data)

{

  USCI_B_SPI_transmitData(USCI_B2_BASE,data);

  while(USCI_B_SPI_isBusy(USCI_B2_BASE));

  data = USCI_B_SPI_receiveData(USCI_B2_BASE);

  return data;

}

 

static

BYTE SD_waitReady(void)

{

  WORD tmr;

  for(tmr = 5000; tmr; tmr--)

  {

    if(SD_writeByte(0xFF) == 0xFF) break;

    delay_us(100);

  }

  return tmr ? 1 : 0;

}

 

static

void SD_csDisable(void)

{

  GPIO_setOutputHighOnPin(SD_CS_PORT,SD_CS_PIN);

  SD_writeByte(0xFF);

}

 

static

int SD_csEnable(void)

{

  GPIO_setOutputLowOnPin(SD_CS_PORT,SD_CS_PIN);

  SD_writeByte(0xFF);

  if(SD_waitReady()) return 1;

  SD_csDisable();

  return 0;

}

 

static

void SD_spiInit(void)

{

  GPIO_setAsPeripheralModuleFunctionInputPin(

     GPIO_PORT_P9,

     GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3

  );

   

  //Initialize Master

  USCI_B_SPI_initMasterParam param = {0};

  param.selectClockSource = USCI_B_SPI_CLOCKSOURCE_SMCLK;

  param.clockSourceFrequency = UCS_getSMCLK();

  param.desiredSpiClock = SD_INIT_CLK;

  param.msbFirst = USCI_B_SPI_MSB_FIRST;

  param.clockPhase = USCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT;

  param.clockPolarity = USCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH;

  USCI_B_SPI_initMaster(USCI_B2_BASE, ¶m);

}

 

static

void SD_spiEnable(void)

{

  USCI_B_SPI_enable(USCI_B2_BASE);

}

 

static

void SD_spiDisable(void)

{

  USCI_B_SPI_disable(USCI_B2_BASE);

}

 

static

void SD_spiSetSpeed(DWORD speed)

{

  USCI_B_SPI_changeMasterClockParam clockparam = {0};

  clockparam.clockSourceFrequency = UCS_getSMCLK();

  clockparam.desiredSpiClock = speed;

  USCI_B_SPI_changeMasterClock(USCI_B2_BASE, &clockparam);

}

 

static

BYTE SD_getResponse(void)

{

  BYTE retrytime = 0;

  BYTE response;

   

  while(retrytime <= 240)

  {

    response = SD_writeByte(0xFF);

    if(response == 0x00) break;

    if(response == 0x01) break;

    if(response == 0xFE) break;

    retrytime++;

  }

  return response;

}

 

static

BYTE SD_sendCmd(BYTE cmd,DWORD arg,const BYTE crc)

{

  BYTE rec;

  if(cmd & 0x80)

  {

    cmd &= 0x7F;

    rec = SD_sendCmd(CMD55,0,0xFF);

    if(rec > 1) return rec;

  }

   

  if(cmd != CMD12)

  {

    SD_csDisable();

    if(!SD_csEnable()) return 0xFF;

  }

   

  SD_writeByte((cmd & 0x3F) | 0x40);

  SD_writeByte(arg >> 24);

  SD_writeByte(arg >> 16);

  SD_writeByte(arg >> 8);

  SD_writeByte(arg);

  SD_writeByte(crc);

  rec = SD_getResponse(); 

  return rec;

}

 

/*-----------------------------------------------------------------------*/

/* Receive a data packet from the card                                   */

/*-----------------------------------------------------------------------*/

static

int SD_readBlock (BYTE *buff, UINT btr)

{

  BYTE d[2];

  UINT tmr;

  for (tmr = 1000; tmr; tmr--) 

  {

    if ((d[0] = SD_writeByte(0xFF)) != 0xFF) break;

    delay_us(100);

  }

  if (d[0] != 0xFE) return 0;

  do

  {

    *buff++ = SD_writeByte(0xFF);

  } while(-- btr);

  SD_writeByte(0xFF);

  SD_writeByte(0xFF);

  return 1;

}

 

/*-----------------------------------------------------------------------*/

/* Send a data packet to the card                                        */

/*-----------------------------------------------------------------------*/

static

int SD_writeBlock (const BYTE *buff, BYTE token)

{

  BYTE d;

  UINT tmr;

  if (!SD_waitReady()) return 0;

  SD_writeByte(token);

  if (token != 0xFD)

  {

    tmr = 512;

    do

    {

      SD_writeByte(*buff ++);

    } while(-- tmr);

    SD_writeByte(0xFF);

    SD_writeByte(0xFF);

    d = SD_writeByte(0xFF);

    if ((d & 0x1F) != 0x05)

    return 0;

  }

  return 1;

}

 

/*-----------------------------------------------------------------------*/

/* Get Drive Status                                                      */

/*-----------------------------------------------------------------------*/

DSTATUS disk_status (BYTE drv)

{

  if(drv) return STA_NOINIT;

  return Stat;

}

 

/*-----------------------------------------------------------------------*/

/* Inidialize a Drive                                                    */

/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (BYTE drv)

{

  BYTE n,ty,cmd,buf[4];

  UINT tmr;

  DSTATUS s;

  if(drv) return RES_NOTRDY;

   

  SD_spiInit();

  SD_spiEnable();

  SD_csInit();

  SD_csDisable();

   

  for(n = 0;n < 16;n++)

  {

    SD_writeByte(0xFF);

  } //send 128 clocks for normal voltage and sync

   

  ty = 0;

  if(SD_sendCmd(CMD0,0,0x95) == 1) //enter idle state

  {

    if(SD_sendCmd(CMD8,0x1AA,0x87) == 1) //SDV2

    {

      buf[0] = SD_writeByte(0xFF);

      buf[1] = SD_writeByte(0xFF);

      buf[2] = SD_writeByte(0xFF);

      buf[3] = SD_writeByte(0xFF);

      if(buf[2] == 0x01 && buf[3] == 0xAA)

      {

        for(tmr = 1000;tmr;tmr--)

        {

          if(SD_sendCmd(ACMD41,0x40000000,0xFF) == 0) break;

          delay_ms(1);

        }

        if(tmr && SD_sendCmd(CMD58,0,0xFF) == 0)

        {

          buf[0] = SD_writeByte(0xFF);

          buf[1] = SD_writeByte(0xFF);

          buf[2] = SD_writeByte(0xFF);

          buf[3] = SD_writeByte(0xFF);

          ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;    /* SDv2 */

    }

      }

    }

    else

    {

      if(SD_sendCmd(ACMD41,0,0xFF) <= 1) //SDV1

      {

        ty = CT_SD1;

        cmd = ACMD41;

      }

      else //MMCv3

      {

        ty = CT_MMC;

        cmd = CMD1;

      }

      for(tmr = 1000; tmr; tmr--)

      {

        if(SD_sendCmd(cmd,0,0xFF) == 0) break;

    delay_ms(1);

      }

      if(!tmr || SD_sendCmd(CMD16,512,0xFF) != 0)

        ty = 0;

    }

  }

   

  CardType = ty;

  s = ty ? 0 : STA_NOINIT;

  Stat = s;

   

  SD_csDisable();

  //SPI HIGH SPEED

  SD_spiSetSpeed(SD_HIGH_CLK);

  return s;

}

 

/*-----------------------------------------------------------------------*/

/* Read Sector(s)                                                        */

/*-----------------------------------------------------------------------*/

DRESULT disk_read (BYTE drv,BYTE *buff,DWORD sector,UINT count)

{

  BYTE cmd;

  if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;

  if (!(CardType & CT_BLOCK)) sector *= 512;

  cmd = count > 1 ? CMD18 : CMD17;

  if (SD_sendCmd(cmd, sector, 0xFF) == 0)

  {

    do

    {

      if (!SD_readBlock(buff, 512)) break;

      buff += 512;

    } while (--count);

    if (cmd == CMD18) SD_sendCmd(CMD12, 0, 0xFF);

  }

  SD_csDisable();

  return count ? RES_ERROR : RES_OK;

}

 

/*-----------------------------------------------------------------------*/

/* Write Sector(s)                                                       */

/*-----------------------------------------------------------------------*/

DRESULT disk_write (BYTE drv,const BYTE *buff,DWORD sector,UINT count)

{

  if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;

  if (!(CardType & CT_BLOCK)) sector *= 512;

  if (count == 1) 

  {

    if ((SD_sendCmd(CMD24, sector, 0xFF) == 0) && SD_writeBlock(buff, 0xFE))

    count = 0;

  }

  else

  {

    if (CardType & CT_SDC) SD_sendCmd(ACMD23, count, 0xFF);

    if (SD_sendCmd(CMD25, sector, 0xFF) == 0) 

    {

      do

      {

        if (!SD_writeBlock(buff, 0xFC)) break;

        buff += 512;

      } while (--count);

      if (!SD_writeBlock(0, 0xFD))

      count = 1;

    }

  }

  SD_csDisable();

  return count ? RES_ERROR : RES_OK;

}

 

/*-----------------------------------------------------------------------*/

/* Miscellaneous Functions                                               */

/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (BYTE drv,BYTE ctrl,void *buff)

{

  DRESULT res;

  BYTE n, csd[16];

  DWORD cs;

   

  if (disk_status(drv) & STA_NOINIT) return RES_NOTRDY;

   

  res = RES_ERROR;

  switch (ctrl)

  {

    case CTRL_SYNC :

      if (SD_csEnable()) res = RES_OK;

      break;

    case GET_SECTOR_COUNT :

      if ((SD_sendCmd(CMD9, 0, 0xFF) == 0) && SD_readBlock(csd, 16))

      {

        if ((csd[0] >> 6) == 1) //SDV2

        {

          cs = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;

          *(DWORD*)buff = cs << 10;

        }

        else //SDV1 or MMC

        {

          n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;

          cs = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;

          *(DWORD*)buff = cs << (n - 9);

        }

        res = RES_OK;

      }

      break;

    case GET_BLOCK_SIZE :

      *(DWORD*)buff = 128;

      res = RES_OK;

      break;

    default:

      res = RES_PARERR;

      break;

  }

  SD_csDisable();

  return res;

}


关键字:MSP430  SD卡  SPI读写操  FatFs文件系统 引用地址:MSP430 SD卡SPI读写操作(4) —— FatFs文件系统实现

上一篇:STM8学习笔记---串口uart1
下一篇:MSP430F5438A单片机基于SPI的FatFs移植笔记

推荐阅读

// STM32输入AB相脉冲的编码器程序// 程序中使用TIM5计数器计数AB相脉冲,如果将TIM5修改成其他定时器也能适用。// PA0和PA1分别作为A、B相脉冲输入// 可以另外再使用一个定时器,定时读出脉冲数TIM5->CNT// 作者: bjtea // http://blog.csdn.net/bjtea/article/details/8528389// 以下程序摘自本人做的一个项目,因此可以放心代码的使用 #inclu...
9月16日消息,小胖机器人与青岛市政府达成战略合作,青岛即墨区政府5亿元注资小胖机器人,同时,小胖机器人将入驻青岛即墨区,建设机器人产业研发生产基地,并将以此基地为启动轴心,面向全国输出机器人技术与全系产品,全力打造中国服务机器人龙头品牌。小胖机器人CEO魏然介绍说,我们的战略是做机器人的实用化,服务于AI+教育领域,目标是走进千家万户,...
项目名称:A_基于乐拓示波器调试can通信产品过程本贴基于上次开箱,引入一个调整示波器探头的调谐电容,从而会影响示波器信号波形的采集,我们来分析下基本原理:上图a为直连模式,此时相当于直接用两根导线将待测信号和示波器探头连接起来。上图b为我们最常用到的示波器探头,即无源探头,探头内部是有衰减电阻和输入等效电容,常见带宽都是500MHz以下,...
9月14日,景嘉微发布公告称,公司新一代图形处理芯片已完成流片、封装阶段工作,该产品尚未完成测试工作,尚未形成量产和对外销售,不会对公司当期业绩产生较大影响。景嘉微表示,此次新一代图形处理芯片为JM9系列,JM9系列图形处理芯片作为公司2018年非公开发行股票募投项目之一,目前已成功取得阶段性成果。公告称,JM9系列图形处理芯片将进一步丰富景嘉...

史海拾趣

问答坊 | AI 解惑

转载:<<ARM入门最好的文章>>,适合菜鸟

我自己在学arm7,不小心在网上看到这篇文章,内容如题,自我感觉他写的不错,因此帖上来供菜鸟们参考,高手就不用看了 该文章作者不详,我在此只转载未做任何修改: 1.抓住51开发ARM     这几个月来我一直都爬在51的问题,自己都有一点笑自己了,用了4 ...…

查看全部问答∨

语音控制迷你小车全部资料

基于凌阳十六位单片机的语音控制小车。…

查看全部问答∨

一些关于运放的文章

本人最近正在学习运放电路,找到一些文章与大家分享 一切资源来自网络 [ 本帖最后由 6bt 于 2008-10-29 01:45 编辑 ]…

查看全部问答∨

谁有TFT屏的图片HEX转换软件,

我以前传过这个软件,现在却找不到了,就是把彩色图片转换为各种点阵的HEX文件.…

查看全部问答∨

matlab第五课-符号变量的微分方程

解微分方程就靠他了啊 dsolve…

查看全部问答∨

uboot上使用flash_eraseall /dev/mtd3时出现大量坏块怎么解决

之前做jffs2文件系统的时候还挺好的  现在不知道为什么出现这个情况 我开始使用nfs登陆,接着就用flash_eraseall这个命令,在擦除的时候出现下面的情况 Skipping bad block at 0x032b0000 Erasing 16 Kibyte @ 32b4000 -- 97 % comple ...…

查看全部问答∨

evc 头文件包含

对于nkintr.h,pm.h,windev.h这样的系统头文件如果要在evc下包含应该如何设置?在smdk2440的bsp中没有找到对应的头文件啊,请高手回答…

查看全部问答∨

菜鸟问题2::EVC中关于滑动条控件slider的问题!

由于公司要求让实现一个圆弧型的滑动条并且要求是圆形的滑块,还有点击滑块时滑动条颜色也变化,由于小弟刚接触不太知道怎么自己画控件,希望哪位大哥有相关源代码给我发一下E-mail:weir1983@163.com…

查看全部问答∨

STM32F103奇怪的问题

                                 我用PA.4,PA.5,PA.6采集开关量,都有上拉电阻,GPIO设置为输入上拉模式或者输入浮空模式,不接外部开关量的时候, ...…

查看全部问答∨

关于430F169 和ADS805E的接口电路的程序

我想用430单片机使用外部ADC 选择了ADS805E  因为英语不行额 ADS805E的手册 看的不是很清楚  希望大家帮帮忙啊~谢谢了  希望大家能给个 f169和ADS805E的接口电路 最好有相应程序解析  谢谢各位了~~…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved