SMARTARM2200 ADS工程在IAR EWARM 5.3上的移植(8)-uCFS的移植(SD卡驱动简析)

接下来就是实现文件系统,uCFS在SD卡上的移植.我用的还是1.34.01版本,网上到处都是.不过更高版本的很难找到,谁有的愿与我分享会非常感谢.
SMARTARM2200上SD卡通过SPI与处理器通信,另外3根IO用来控制供电,插入检测,写保护检测.SD驱动代码从ZLG的工程中获得用来移植到IAR上.移植好的工程请见http://download.csdn.net/source/1796291大部分代码来源于网络,我做了些整合和修改.
SD驱动共有9个文件:
1.sdconfig.h
定义了一些宏,包括配置参数及初始化SPI/SD引脚
2.sdhal.c,sdhal.h
SD卡底层的处理函数,如果电源初始化,SPI初始化,设置SPI时钟,SPI读写函数,SD卡检测
3.sdcmd.c,sdcmd.h
SD命令函数
4.sdcrc.c,sdcrc.h
CRC校验
5.sddriver.c,sddriver.h
SD较高层的驱动,如SD初始化,读写SD Block函数

接下来就sddriver.c中的一些代码进行简要分析.
1.SD_Initialize

ContractedBlock.gif ExpandedBlockStart.gif SD_Initialize
 
   
1 INT8U SD_Initialize( void )
2 {
3 INT8U recbuf[ 4 ],ret;
4 /* 创建访问SD/MMC卡信号量 create SD/MMC semaphore */
5   #if SD_UCOSII_EN
6 if (pSemSD == NULL)
7 {
8 pSemSD = OSSemCreate( 1 );
9 if (pSemSD == NULL)
10 return SD_ERR_CREATE_SEMSD;
11 }
12   #endif
13 /* 等待信号量 */
14 SD_StartSD();
15 /* 初始化读写SD卡的硬件条件 */
16 SD_HardWareInit();
17 /* 检查卡是否插入 */
18 if (SD_ChkCard() != 1 )
19 {
20 ret = SD_ERR_NO_CARD;
21 goto SD_ERR;
22 }
23 /* 1. 置CS为低 */
24 SPI_CS_Assert();
25 /* 2. 至少延时 74 clock */
26 SD_SPIDelay( 25 );
27 /* 3. 置CS为高 dessert CS */
28 SPI_CS_Deassert();
29 /* 4. 延时2(8 clock) delay 2(8 clock) */
30 SD_SPIDelay( 2 );
31 /* 5. 发出CMDO命令复位SD卡 */
32 ret = SD_ResetSD();
33 if (ret != SD_NO_ERR)
34 goto SD_ERR;
35 /* 6. 激活卡进入初始化过程 */
36 ret = SD_ActiveInit();
37 if (ret != SD_NO_ERR)
38 goto SD_ERR;
39 /* 7. 读OCR寄存器,查询卡支持的电压值 */
40 ret = SD_ReadOCR( 4 , recbuf);
41 if (ret != SD_NO_ERR)
42 goto SD_ERR;
43 /* 不支持3.3V,返回错误码 */
44 if ((recbuf[ 1 ] & MSK_OCR_33) != MSK_OCR_33)
45 {
46 ret = SD_ERR_VOL_NOTSUSP; goto SD_ERR;
47 }
48 /* 8. 设置SPI时钟到最大值 */
49 SPI_ClkToMax();
50 /* 使能CRC校验 */
51 #if SD_CRC_EN
52 ret = SD_EnableCRC( 1 );
53 if (ret != SD_NO_ERR)
54 goto SD_ERR;
55 #endif
56 /* 9. 设置块的长度: 512Bytes */
57 ret = SD_SetBlockLen(SD_BLOCKSIZE);
58 if (ret != SD_NO_ERR)
59 goto SD_ERR;
60 /* 10. 读CSD寄存器,获取SD卡信息 */
61 ret = SD_GetCardInfo();
62 if (ret != SD_NO_ERR)
63 goto SD_ERR;
64
65 SD_EndSD();
66 /* 初始化成功 initialize sucessfully */
67 return SD_NO_ERR;
68
69 SD_ERR:
70 SD_EndSD();
71 return ret;
72 }

2.SD_ReadBlock

ContractedBlock.gif ExpandedBlockStart.gif SD_ReadBlock
 
   
1 INT8U SD_ReadBlock(INT32U blockaddr, INT8U * recbuf)
2 {
3 INT8U ret;
4 /* 向OS申请访问卡信号量 */
5 SD_StartSD();
6 if (SD_ChkCard() != 1 )
7 {
8 SD_EndSD();
9 /* 卡没完全插入卡中 */
10 return SD_ERR_NO_CARD;
11 }
12
13 if (blockaddr > sds.block_num)
14 {
15 SD_EndSD();
16 /* 操作超出卡容量范围 */
17 return SD_ERR_OVER_CARDRANGE;
18 }
19 /* 读单块命令 */
20 ret = SD_ReadSingleBlock(blockaddr);
21 if (ret != SD_NO_ERR)
22 {
23 SD_EndSD();
24 return ret;
25 }
26 /* 读出数据 */
27 ret = SD_ReadBlockData(SD_BLOCKSIZE, recbuf);
28 /* 归还访问卡信号量 */
29 SD_EndSD();
30
31 return ret;
32 }

3.SD_WriteBlock

ContractedBlock.gif ExpandedBlockStart.gif SD_WriteBlock
 
   
1 INT8U SD_WriteBlock(INT32U blockaddr, INT8U * sendbuf)
2 {
3 INT8U ret,tmp[ 2 ];
4 /* 向OS申请访问卡信号量 */
5 SD_StartSD();
6 if (SD_ChkCard() != 1 )
7 {
8 SD_EndSD();
9 /* 卡没完全插入卡中 */
10 return SD_ERR_NO_CARD;
11 }
12
13 if (blockaddr > sds.block_num)
14 {
15 /* 操作超出卡容量范围 */
16 SD_EndSD();
17 return SD_ERR_OVER_CARDRANGE;
18 }
19
20 if (SD_ChkCardWP() == 1 )
21 {
22 /* 卡有写保护 */
23 SD_EndSD();
24 return SD_ERR_WRITE_PROTECT;
25 }
26 /* 写单块命令 */
27 ret = SD_WriteSingleBlock(blockaddr);
28 if (ret != SD_NO_ERR)
29 {
30 SD_EndSD();
31 return ret;
32 }
33 /* 写入数据 */
34 ret = SD_WriteBlockData( 0 , SD_BLOCKSIZE, sendbuf);
35 /* 读Card Status寄存器, 检查写入是否成功 */
36 if (ret == SD_NO_ERR)
37 {
38 ret = SD_ReadCard_Status( 2 , tmp);
39 if (ret != SD_NO_ERR)
40 {
41 /* 读寄存器失败 */
42 SD_EndSD();
43 return ret;
44 }
45 if ((tmp[ 0 ] != 0 ) || (tmp[ 1 ] != 0 ))
46 {
47 /* 响应指示写失败 */
48 SD_EndSD();
49 ret = SD_ERR_WRITE_BLK;
50 }
51 }
52 SD_EndSD();
53 /* 返回写入结果 */
54 return ret;
55 }

4.SD_ReadMultiBlock
   SD_WriteMultiBlock
处理流程与读写单个Block类似,就是多调用了SD_ReadMultipleBlock和SD_WriteMultipleBlock发送读写多个Block的命令,详细代码请参考上传的工程
5.SD_EraseBlock

ContractedBlock.gif ExpandedBlockStart.gif SD_EraseBlock
 
   
1 INT8U SD_EraseBlock(INT32U startaddr, INT32U blocknum)
2 {
3 INT32 tmp;
4 INT8U ret;
5
6 SD_StartSD();
7 if (SD_ChkCard() != 1 )
8 {
9 SD_EndSD();
10 return SD_ERR_NO_CARD;
11 }
12 if ((startaddr + blocknum) > sds.block_num)
13 {
14 SD_EndSD();
15 return SD_ERR_OVER_CARDRANGE;
16 }
17 if (SD_ChkCardWP() == 1 )
18 {
19 SD_EndSD();
20 return SD_ERR_WRITE_PROTECT;
21 }
22
23 tmp = blocknum - sds.erase_unit;
24 /* 每次擦除扇区 */
25 while (tmp >= 0 )
26 {
27 /* 选择起始块地址 */
28 ret = SD_EraseStartBlock(startaddr);
29 if (ret != SD_NO_ERR)
30 {
31 SD_EndSD();
32 return ret;
33 }
34 /* 选择终止块地址 */
35 ret = SD_EraseEndBlock(startaddr + sds.erase_unit - 1 );
36 if (ret != SD_NO_ERR)
37 {
38 SD_EndSD();
39 return ret;
40 }
41 /* 擦除所选的块 */
42 ret = SD_EraseSelectedBlock();
43 if (ret != SD_NO_ERR)
44 {
45 SD_EndSD();
46 return ret;
47 }
48 /* 起始地址递增 */
49 startaddr += sds.erase_unit;
50 blocknum -= sds.erase_unit;
51 tmp = blocknum - sds.erase_unit;
52 };
53 /* 擦除不够once_erase块 */
54 if (blocknum > 0 )
55 {
56 ret = SD_EraseStartBlock(startaddr);
57 if (ret != SD_NO_ERR)
58 {
59 SD_EndSD();
60 return ret;
61 }
62 ret = SD_EraseEndBlock(startaddr + blocknum - 1 );
63 if (ret != SD_NO_ERR)
64 {
65 SD_EndSD();
66 return ret;
67 }
68 ret = SD_EraseSelectedBlock();
69 if (ret != SD_NO_ERR)
70 {
71 SD_EndSD();
72 return ret;
73 }
74 }
75 SD_EndSD();
76 return SD_NO_ERR;
77 }

6.SD_GetCardInfo

ContractedBlock.gif ExpandedBlockStart.gif SD_GetCardInfo
 
   
1 INT8U SD_GetCardInfo()
2 {
3 INT32U tmp;
4 INT8U csdbuf[ 16 ],ret;
5 /* 读CSD寄存器 */
6 ret = SD_ReadCSD( 16 , csdbuf);
7 if (ret != SD_NO_ERR)
8 return ret;
9 /* 计算超时时间值 */
10 SD_CalTimeout(csdbuf);
11 /* 计算块的最大长度 */
12 sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK); /* (2 ^ READ_BL_LEN) */
13 /* 计算卡中块的个数 */
14 sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10 ) +
15 (csdbuf[C_SIZE_POS2] << 2 ) +
16 ((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6 ) + 1 ; /* (C_SIZE + 1) */
17 tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1 ) +
18 ((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7 ) + 2 ; /* (C_SIZE_MULT + 2) */
19 /* 获得卡中块的数量 */
20 sds.block_num = sds.block_num * ( 1 << tmp); /* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
21 /* 计算擦除的单位(单位: 块) */
22 if (sds.card_type == CARDTYPE_MMC)
23 {
24 tmp = ((csdbuf[ERASE_GRP_SIZE_POS] & ERASE_GRP_SIZE_MSK) >> 2 ) + 1 ; /* (ERASE_GRP_SIZE + 1) */
25 /* (ERASE_GRP_SIZE + 1) * (ERASE_GRP_MULTI + 1) */
26 tmp *= ((csdbuf[ERASE_GRP_MULTI_POS1] & ERASE_GRP_MULTI_MSK1) << 3 ) +
27 ((csdbuf[ERASE_GRP_MULTI_POS2] & ERASE_GRP_MULTI_MSK2) >> 5 ) + 1 ;
28 }
29 else /* calculate the size of sector */
30 tmp = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1 ) +
31 ((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7 ) + 1 ; /* SD: SECTOR_SIZE */
32 /* 擦除单位(块) */
33 sds.erase_unit = tmp;
34 return SD_NO_ERR;
35 }

读到的CSD对应数据的字节位置如下:

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 #define TAAC_POS 1 // TACC
2 #define NSAC_POS 2 // NSAC
3
4 #define READ_BL_LEN_POS 5 // READ_BL_LEN
5
6 #define C_SIZE_POS1 6 // C_SIZE upper 2-bit
7 #define C_SIZE_POS2 7 // C_SIZE middle 8-bit
8 #define C_SIZE_POS3 8 // C_SIZE lower 2-bit
9
10 #define C_SIZE_MULT_POS1 9 // C_SIZE_MULT upper 2-bit
11 #define C_SIZE_MULT_POS2 10 // C_SIZE_MULT lower 1-bit
12
13 #define SECTOR_SIZE_POS1 10 // SECTOR_SIZE upper 5-bit
14 #define SECTOR_SIZE_POS2 11 // SECTOR_SIZE lower 2-bit
15
16 #define R2WFACTOR_POS 12 // R2WFACTOR_POS
17
18 #define ERASE_GRP_SIZE_POS 10 // MMC卡 ERASE_GRP_SIZE 5-bit
19 #define ERASE_GRP_MULTI_POS1 10 // MMC卡 ERASE_GRP_MULTI 2-bit
20 #define ERASE_GRP_MULTI_POS2 11 // MMC卡 ERASE_GRP_MULTI 3-bit

更底层的SD SPI命令实现请参考sdcmd.c,sdcmd.h,以下列举了一些SD命令:

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 /* 设置块的长度 Set the block length */
2 #define CMD16 16
3 #define CMD16_R R1
4
5 /* 读单块 Read a single block */
6 #define CMD17 17
7 #define CMD17_R R1
8
9 /* 读多块,直至主机发送CMD12为止 Read multiple blocks until a CMD12 */
10 #define CMD18 18
11 #define CMD18_R R1
12 /* 写单块 Write a block of the size selected with CMD16 */
13 #define CMD24 24
14 #define CMD24_R R1
15
16 /* 写多块 Multiple block write until a CMD12 */
17 #define CMD25 25
18 #define CMD25_R R1

接下来介绍uCFS的在SD上的移植.

发表于 @ 2009年10月27日

转载于:https://www.cnblogs.com/shevsten/articles/1692593.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值