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函数
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中定义
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")之类的函数来访问文件系统了.
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显示的方式.
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即可
2 return SD_ChkCard();
3 }
4.FS_GetMediaStartSec
这个函数用来获取MBR的信息,从主引导记录或者分区表获得逻辑起始sector地址
具体的参数与FAT文件系统有关
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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获得逻辑起始地址
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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来进行数据的读操作,将读到的数据放到参数传递的缓冲区中.
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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地址的偏移量.
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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文件系统的信息
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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是否正常工作
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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