SMARTARM2200 ADS工程在IAR EWARM 5.3上的移植(9)-uCFS的移植(uCFS在SD上的移植)

SD卡驱动完成之后接下来就是实现uCFS与SD卡的接口.主要代码实现在DEVICE\SDMMC\sd_drv.c中.
整个工程代码可在http://download.csdn.net/source/1796291下载到.

1.添加对MMC/SD的支持配置
在fs_conf.h中打开对MMC和uCOSII的支持
#define FS_OS_UCOS_II                1    /* 1 = use uC/OS-II */
#define FS_USE_MMC_DRIVER       1    /* MMC/SD card driver */
其他配置可参考例子工程,大部分按照默认配置,具体含义可参考注释

2.增加文件系统与SD驱动的接口
在uCFS中通过FS__device_type的结构体来声明,该结构体原型为:
定义了读写,状态还有ioctl函数

1 typedef struct {
2 FS_FARCHARPTR name;
3 int (*dev_status)(FS_u32 id);
4 int (*dev_read)(FS_u32 id, FS_u32 block, void *buffer);
5 int (*dev_write)(FS_u32 id, FS_u32 block, void *buffer);
6 int (*dev_ioctl)(FS_u32 id, FS_i32 cmd, FS_i32 aux, void *buffer);
7 } FS__device_type;

在sd_drv.c中定义

1 const FS__device_type FS__mmcdevice_driver = {
2 "mmc",
3 _FS_MMC_DevStatus,
4 _FS_MMC_DevRead,
5 _FS_MMC_DevWrite,
6 _FS_MMC_DevIoCtl
7 };

注意该驱动的名称必须为mmc,否则无法正常工作.因为在fs_info.c中定义了如下的结构,而uCFS正式通过FS__pDevInfo来访问设备,因此必须保证命名的一致性,除非两处名称修改成同一个名称.这样就可以通过FS_FOpen("mmc:\\flash.txt", "rb")之类的函数来访问文件系统了.

1 #define FS_DEVINFO_DEVMMC { "mmc", &FS__fat_functable, &FS__mmcdevice_driver, FS_CACHEINFO_MMC_DRIVER 0 },
2  #define FS_DEVINFO FS_DEVINFO_DEVSMC FS_DEVINFO_DEVMMC FS_DEVINFO_DEVIDE FS_DEVINFO_DEVFLASH FS_DEVINFO_DEVWINDRV FS_DEVINFO_DEVRAM
3  const FS__devinfo_type _FS__devinfo[] = { FS_DEVINFO };
4
5  const FS__devinfo_type *const FS__pDevInfo = _FS__devinfo;

3.FS_MMC_HW_X_BusyLedOff和FS_MMC_HW_X_BusyLedOn
这个两个函数是显示MMC状态的,这里采用LED显示的方式.

1 static void FS_MMC_HW_X_BusyLedOff (FS_u8 Unit) {
2 BSP_LED_Off(LED_3_BIT);
3 }
4
5  static void FS_MMC_HW_X_BusyLedOn(FS_u8 Unit) {
6 BSP_LED_On(LED_3_BIT);
7 }

还有一个函数FS_MMC_HW_X_IsPresent用来检测SD卡是否插入,调用之前实现的SD_ChkCard即可

1 static char FS_MMC_HW_X_IsPresent(FS_u8 Unit) {
2 return SD_ChkCard();
3 }

4.FS_GetMediaStartSec
这个函数用来获取MBR的信息,从主引导记录或者分区表获得逻辑起始sector地址
具体的参数与FAT文件系统有关

FS_GetMediaStartSec
1 static FS_u32 FS_GetMediaStartSec(const FS_u8 *pBuffer) {
2 FS_u8 c;
3 FS_u32 StartSec;
4
5 c = pBuffer[0x1FE]; /* check first part of the signature */
6 if (c != FS__DEV_MBRSECTORFLAG_L) {
7 return 0xFFFFFFFF;
8 }
9
10 c = pBuffer[0x1FF]; /* check second part of the signature */
11 if (c != FS__DEV_MBRSECTORFLAG_H) {
12 return 0xFFFFFFFF;
13 }
14
15 c = pBuffer[0x000]; /* check if boot or partition record */
16 if (c == FS__DEV_MBRFLAG_JUMP1) {
17 return 0; /* if first byte is a jump command, there is no partition table */
18 }
19
20 if (c == FS__DEV_MBRFLAG_JUMP2) {
21 return 0; /* if first byte is a jump command, there is no partition table */
22 } /* this calculation makes sure big/little endian system get the right value from the table */
23 /* read first entry of the partition table */
24 StartSec = (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 11] & 0xFFUL;
25 StartSec <<= 8;
26 StartSec += (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 10] & 0xFFUL;
27 StartSec <<= 8;
28 StartSec += (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 9] & 0xFFUL;
29 StartSec <<= 8;
30 StartSec += (FS_u32)pBuffer[FS__DEV_PART_0_TABLE + 8] & 0xFFUL;
31
32 return StartSec;
33 }

5._FS_MMC_DevStatus
这个函数来获得SD卡的状态,首先进行一些状态的检测,输出,设置标志,接着初始化SD卡,然后读取SD卡的第一块,调用上面的FS_GetMediaStartSec获得逻辑起始地址

_FS_MMC_DevStatus
1 static int _FS_MMC_DevStatus(FS_u32 Unit) {
2 static int init = 0;
3 int x;
4 char a;
5 FS_u32 ul;
6 FS_MMC_HW_X_BusyLedOn(1);
7 if (!init) {
8 /*
9 The function is called the first time. For each unit,
10 the flag for 'diskchange' is set. That makes sure, that
11 FS_LBL_MEDIACHANGED is returned, if there is already a
12 media in the reader.
13 */
14 for (init = 0; init < FS_MMC_MAXUNIT; init++) {
15 _FS_mmc_diskchange[init] = 1;
16 }
17 init = 1;
18 }
19 if (Unit >= FS_MMC_MAXUNIT) {
20 print_string("No MMC/SD card found!\r\n");
21 return -1; /* No valid unit number */
22 }
23 a = FS_MMC_HW_X_IsPresent(Unit);/* Check if a card is present */
24 if (!a) {
25 return -1; /* No card in reader */
26 }
27 /* When you get here, then there is a card in the reader */
28 a = _FS_mmc_diskchange[Unit]; /* Check if the media has changed */
29 if (a) {
30 /*
31 A diskchange took place. The following code reads the MBR of the
32 card to get its partition information.
33 */
34 _FS_mmc_diskchange[Unit] = 0; /* Reset 'diskchange' flag */
35 x = SD_Initialize();
36 if (x > 0) {
37 print_string("SD_Initialize error! CODE: 0x%02X\r\n", x);
38 return -1;
39 }
40 x = SD_ReadBlock(0, (FS_u8*)&_FS_mmc_mbrbuffer[0]);
41 if (x > 0) {
42 print_string("SD_ReadBlock error! CODE: 0x%02X\r\n", x);
43 return -1;
44 }
45 /* Calculate start sector of the first partition */
46 ul = FS_GetMediaStartSec((FS_u8*)&_FS_mmc_mbrbuffer[0]);
47 if (ul == 0xFFFFFFFF) { /* check if MBR was invalid */
48 return -1;
49 }
50 _FS_mmc_logicalstart[Unit] = ul;
51 return FS_LBL_MEDIACHANGED;
52 }
53 FS_MMC_HW_X_BusyLedOff(1);
54 return 0;
55 }

6._FS_MMC_DevRead
这个函数实现读SD卡的操作,主要就是调用SD_ReadBlock来进行数据的读操作,将读到的数据放到参数传递的缓冲区中.

_FS_MMC_DevRead
1 static int _FS_MMC_DevRead(FS_u32 Unit, FS_u32 Sector, void *pBuffer){
2 int x;
3 if (Unit >= FS_MMC_MAXUNIT) {
4 return -1; /* No valid unit number */
5 }
6 FS_MMC_HW_X_BusyLedOn(1);
7 x = SD_ReadBlock(Sector+_FS_mmc_logicalstart[Unit], (FS_u8*)pBuffer);
8 if(x > 0) {
9 print_string("SD_ReadBlock error! CODE: 0x%02X\r\n", x);
10 x = -1;
11 }
12 else {
13 x = 0;
14 }
15 FS_MMC_HW_X_BusyLedOff(1);
16 return x;
17 }

7._FS_MMC_DevWrite
这个函数实现写SD卡的操作.实现方式与读相似,调用SD_WriteBlock将数据写到指定的sector中.实际写时加了一个起始sector地址的偏移量.

_FS_MMC_DevWrite
1 static int _FS_MMC_DevWrite(FS_u32 Unit, FS_u32 Sector, void *pBuffer){
2
3 int x;
4
5 if (Unit >= FS_MMC_MAXUNIT) {
6 return -1; /* No valid unit number */
7 }
8 FS_MMC_HW_X_BusyLedOn(1);
9 x = SD_WriteBlock(Sector+_FS_mmc_logicalstart[Unit], (FS_u8*)pBuffer);
10 if (x > 0) {
11 print_string("SD_WriteBlock error! CODE: 0x%02X\r\n", x);
12 x = -1;
13 }
14 else {
15 x = 0;
16 }
17 FS_MMC_HW_X_BusyLedOff(1);
18 return x;
19 }

8._FS_MMC_DevIoCtl
这个函数用来实现不同的命令,主要实现了FS_CMD_GET_DEVINFO命令,来获得存储设备信息
主要过程就是首先读第一个SD块分析出起始逻辑sector地址,然后读该sector内容获得FAT文件系统的信息

代码
1 case FS_CMD_GET_DEVINFO:
2 print_string("FS_CMD_GET_DEVINFO\r\n");
3 if (!pBuffer) {
4 print_string("pBuffer is NULL...\r\n");
5 return -1;
6 }
7 info = pBuffer;
8 x = SD_Initialize();
9 if (x > 0) {
10 print_string("SD_Initialize failed...\r\n");
11 return -1;
12 }
13 x = SD_ReadBlock(0, (FS_u8*)&_FS_mmc_mbrbuffer[0]);
14 if (x > 0) {
15 return -1;
16 }
17 ul = FS_GetMediaStartSec((FS_u8*)&_FS_mmc_mbrbuffer[0]);
18 if (ul == 0xFFFFFFFF) { /* check if MBR was invalid */
19 return -1;
20 }
21 if (ul != 0) {
22 /* READ (1) 512 BYTE SECTOR */
23 x = SD_ReadBlock(ul, (FS_u8*)&_FS_mmc_mbrbuffer[0]);
24 (x > 0) {
25 return -1;
26
27 }
28 /* hidden */
29 *info = _FS_mmc_mbrbuffer[0x1c6];
30 *info += (0x100UL * _FS_mmc_mbrbuffer[0x1c7]);
31 *info += (0x10000UL * _FS_mmc_mbrbuffer[0x1c8]);
32 *info += (0x1000000UL * _FS_mmc_mbrbuffer[0x1c9]);
33 info++;
34 /* head */
35 *info = _FS_mmc_mbrbuffer[0x1c3];
36 info++;
37 /* sec per track */
38 *info = _FS_mmc_mbrbuffer[0x1c4];
39 info++;
40 /* size */
41 *info = _FS_mmc_mbrbuffer[0x1ca];
42 *info += (0x100UL * _FS_mmc_mbrbuffer[0x1cb]);
43 *info += (0x10000UL * _FS_mmc_mbrbuffer[0x1cc]);
44 *info += (0x1000000UL * _FS_mmc_mbrbuffer[0x1cd]);
45 break;

9.一个简单的测试代码,测试uCFS是否正常工作

代码
1 char _sRAMText[] = "Text on SD card";
2 char _acBuffer[80];
3 void TaskuCFS_Test(void *p_arg)
4 {
5 FS_Init();
6 //如果有必要先进行格式化
7 FS_IoCtl("mmc:",FS_CMD_FORMAT_MEDIA,FS_MEDIA_SD_128MB,buffer);//format SD card
8
9 _pFile = FS_FOpen("mmc:\\flash.txt", "w+b");
10 if(_pFile)
11 {
12 i = FS_FWrite(_sRAMText, 1, strlen(_sRAMText), _pFile);
13 FS_FClose(_pFile);
14 print_string("write file ok %d bytes written\r\n", i);
15 }
16
17 _pFile = FS_FOpen("mmc:\\flash.txt", "rb");
18 if(_pFile)
19 {
20 i = FS_FRead(_acBuffer, 1, 29, _pFile);
21 FS_FClose(_pFile);
22 print_string("%d bytes read,file data is:\r\n%s\r\n", i, _acBuffer);
23 }
24 }
25

 

如果运行成功,会输出如下的信息:


发表于 @ 2009年11月05日

posted on 2010-03-23 14:59  shevsten  阅读(1090)  评论(0编辑  收藏  举报