本节介绍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;
}
上一篇:STM8学习笔记---串口uart1
下一篇:MSP430F5438A单片机基于SPI的FatFs移植笔记
推荐阅读
史海拾趣
GSI Technology公司成立于1995年3月,总部位于加利福尼亚州的圣何塞(硅谷),自创立之初便专注于提供领先的电信和网络解决方案。公司采用先进的CMOS工艺技术,如0.25、0.15和0.13微米等,致力于开发低功耗、全功能、高性能的SRAM产品。通过不断的技术创新和产品优化,GSI Technology逐渐在高性能存储器市场占据了一席之地,为后续的快速发展奠定了坚实的基础。
随着国内市场的饱和,Bellin Dynamic Systems开始寻求国际化发展的道路。公司首先在欧洲设立了研发中心,以更好地了解当地市场需求和技术趋势。随后,公司又在美国和亚洲等地建立了生产基地和销售网络。通过这一系列的国际化战略举措,Bellin Dynamic Systems成功打开了国际市场,实现了业务的快速增长。
在快速变化的电子市场中,大雅智能始终保持敏锐的市场洞察力。通过深入研究市场需求和消费者行为,大雅智能准确把握市场趋势,及时调整产品策略。例如,在智能家居市场兴起之际,大雅智能迅速推出了一系列智能家居产品,成功抢占了市场先机。这种对市场趋势的敏锐洞察和快速响应能力,让大雅智能在电子行业中不断取得新的突破。
普芯达电子自创立之初,就立志成为国产高品质、高性价比的IC产品供应商。在成立初期,公司面临着资金紧张、技术积累不足以及市场竞争激烈等多重挑战。然而,凭借着创始人对集成电路行业的深厚理解和坚定信念,普芯达电子逐步克服了这些困难,通过引进优秀人才、加大研发投入以及不断优化产品质量,逐渐在市场上崭露头角。
在1924年,大金工业株式会社成功合成了碳氟化合物,并在随后的18年里,这项技术逐渐成熟并开始批量生产。这一突破性的技术不仅为大金在化学领域奠定了坚实的基础,也为公司后续在家用空调市场的进军提供了技术支持。
我自己在学arm7,不小心在网上看到这篇文章,内容如题,自我感觉他写的不错,因此帖上来供菜鸟们参考,高手就不用看了 该文章作者不详,我在此只转载未做任何修改: 1.抓住51开发ARM 这几个月来我一直都爬在51的问题,自己都有一点笑自己了,用了4 ...… 查看全部问答∨ |
|
uboot上使用flash_eraseall /dev/mtd3时出现大量坏块怎么解决 之前做jffs2文件系统的时候还挺好的 现在不知道为什么出现这个情况 我开始使用nfs登陆,接着就用flash_eraseall这个命令,在擦除的时候出现下面的情况 Skipping bad block at 0x032b0000 Erasing 16 Kibyte @ 32b4000 -- 97 % comple ...… 查看全部问答∨ |
|
由于公司要求让实现一个圆弧型的滑动条并且要求是圆形的滑块,还有点击滑块时滑动条颜色也变化,由于小弟刚接触不太知道怎么自己画控件,希望哪位大哥有相关源代码给我发一下E-mail:weir1983@163.com… 查看全部问答∨ |
|
我想用430单片机使用外部ADC 选择了ADS805E 因为英语不行额 ADS805E的手册 看的不是很清楚 希望大家帮帮忙啊~谢谢了 希望大家能给个 f169和ADS805E的接口电路 最好有相应程序解析 谢谢各位了~~… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 有奖直播|TI 工业多协议通信应用中的优化解决方案
- 【泰有聊】系列技术文章连载1:示波器“芯”升级,聊一聊TEK061/041 ASIC创新平台
- 逛工业自动化展TE Connectivity网上展厅,答题赢好礼!
- 免费申请测评:超小型 Linux 开发套件:Quantum Tiny Linux(带 SoM 和扩展板)
- 【已结束】PI 直播【适合工业市场辅助电源的碳化硅和氮化镓 IC】(9:30入场)
- 【欢乐新年精彩共享】优秀主题/回复活动第19期如期到来啦~~
- ADI有奖下载活动之9 电机控制解决方案—伺服控制
- ADI & 世健 新基建系列第一期——工业以太网 答题赢好礼!
- 【Molex莫仕工业通讯与安全解决方案】
- “我画你猜”变身快乐大儿童吧!