******************** * SD卡驱动程序设计 * ******************** ------《ecos增值包》之SD卡驱动 2006/09/17 asdjf@163.com www.armecos.com
------------ SD卡驱动测试 ------------
SmartARM2200平台
一张512M的SD卡,格式化成FAT32,创建两个文本文件: a.txt 1234567890 b.txt abcdefghijklmn 用winhex软件分析,FAT1位于32扇区,a.txt文件位于1980扇区,b.txt文件位于1988扇区,当然启动部分就固定在0扇区。 下面是用SD卡驱动读出的识别信息CID、CSD、0扇区数据、32扇区数据、1980扇区数据、1988扇区数据,和winhex的数据对比,完全一致。
SD卡先关电源再打开,初始化硬件,检测卡是否插入,接着发送复位命令、激活初始化处理命令、读取并解析CID、读取并解析CSD、设置SPI时钟为最大值、设置读写块长度。(其他如OCR、SCR、CRC校验等省略。)每个命令都给出了命令、参数、应答信息,同时给出编码封装后的字节序。每个命令都超时等待应答成功,有写命令的应答带有返回数据。
SD卡测试程序分析了MBR信息,准确读出了几个特定扇区的数据。接着向指定的100扇区强制写入固定数据,再读出来,结果数据一致。在完成写入命令后,还需要等待数据写入完成,写入扇区需要相对比较长的时间,这里使用忙等待模式(更快的可以使用异步模式,完成写命令后先处理其他任务,不必一直等待写数据完成)。
经测试,寄存器读、数据读写均正确完成。
test by yangyi 2007/09/17
+
******************************* * SD Card Test * *******************************
Power down! Power up!
Card insert
Request 40 00 00 00 00 95 ff Sent command cmd = 00 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 01 Request 41 00 00 00 00 ff ff Sent command cmd = 01 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 01 Request 41 00 00 00 00 ff ff Sent command cmd = 01 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 01 Request 41 00 00 00 00 ff ff Sent command cmd = 01 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 01 Request 41 00 00 00 00 ff ff Sent command cmd = 01 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 01 Request 41 00 00 00 00 ff ff Sent command cmd = 01 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 Request 4a 00 00 00 00 ff ff Sent command cmd = 0a arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_data(): got data and CRC 4a 36
CID data: 27 50 48 53 44 35 31 32 11 21 f0 56 01 00 68 ab CID data: register : Manufacturer ID : MID = 0x27 : OEM/Application ID : OID = 0x5048 : Product name : PNM = SD512 : Product revision : PRV = hwrev(0x01) fwrev(0x01) : Product serial number : PSN = 0x21f05601 : Manufacturing date : MDT = 2006-08
Request 49 00 00 00 00 ff ff Sent command cmd = 09 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_data(): got data and CRC 53 78
CSD data: 00 4f 00 32 5f 59 83 ca f6 db 7f 87 8a 40 00 2d CID data: register : Data read time parameter1 : TAAC = 40000000ns : Data read time parameter2 : NSAC = 0 : Max data transfer rate : TRAN_SPEED = 25000000Hz : Card command class : CCC = 5f5 : Card capacity : C_SIZE、C_SIZE_MULT = 994304 Blocks (485MB) : Max read data length : READ_BL_LEN = 9 : Read block partial enable : READ_BL_PARTIAL = 1 : Write block misalign : WRITE_BLK_MISALIGN = 0 : Read block misalign : READ_BLK_MISALIGN = 0 : Write speed factor : R2W_FACTOR = 1 : Max write data length : WRITE_BL_LEN = 9 : Write block partial enable: WRITE_BL_PARTIAL = 0
mmc_spi_read_disk_block(0): sending command Request 51 00 00 00 00 ff ff Sent command cmd = 11 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_disk_block(0): reading data token/data/crc mmc_spi_read_data(): got data and CRC 96 bc
MBR dump 0000: eb 58 90 4d 53 44 4f 53 35 2e 30 00 02 08 20 00 0010: 02 00 00 00 00 f8 00 00 3f 00 ff 00 00 00 00 00 0020: 00 2c 0f 00 ca 03 00 00 00 00 00 00 02 00 00 00 0030: 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 0040: 00 00 29 cb 90 87 a8 4e 4f 20 4e 41 4d 45 20 20 0050: 20 20 46 41 54 33 32 20 20 20 33 c9 8e d1 bc f4 0060: 7b 8e c1 8e d9 bd 00 7c 88 4e 02 8a 56 40 b4 08 0070: cd 13 73 05 b9 ff ff 8a f1 66 0f b6 c6 40 66 0f 0080: b6 d1 80 e2 3f f7 e2 86 cd c0 ed 06 41 66 0f b7 0090: c9 66 f7 e1 66 89 46 f8 83 7e 16 00 75 38 83 7e 00a0: 2a 00 77 32 66 8b 46 1c 66 83 c0 0c bb 00 80 b9 00b0: 01 00 e8 2b 00 e9 48 03 a0 fa 7d b4 7d 8b f0 ac 00c0: 84 c0 74 17 3c ff 74 09 b4 0e bb 07 00 cd 10 eb 00d0: ee a0 fb 7d eb e5 a0 f9 7d eb e0 98 cd 16 cd 19 00e0: 66 60 66 3b 46 f8 0f 82 4a 00 66 6a 00 66 50 06 00f0: 53 66 68 10 00 01 00 80 7e 02 00 0f 85 20 00 b4 0100: 41 bb aa 55 8a 56 40 cd 13 0f 82 1c 00 81 fb 55 0110: aa 0f 85 14 00 f6 c1 01 0f 84 0d 00 fe 46 02 b4 0120: 42 8a 56 40 8b f4 cd 13 b0 f9 66 58 66 58 66 58 0130: 66 58 eb 2a 66 33 d2 66 0f b7 4e 18 66 f7 f1 fe 0140: c2 8a ca 66 8b d0 66 c1 ea 10 f7 76 1a 86 d6 8a 0150: 56 40 8a e8 c0 e4 06 0a cc b8 01 02 cd 13 66 61 0160: 0f 82 54 ff 81 c3 00 02 66 40 49 0f 85 71 ff c3 0170: 4e 54 4c 44 52 20 20 20 20 20 20 00 00 00 00 00 0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01a0: 00 00 00 00 00 00 00 00 00 00 00 00 0d 0a 4e 54 01b0: 4c 44 52 20 69 73 20 6d 69 73 73 69 6e 67 ff 0d 01c0: 0a 44 69 73 6b 20 65 72 72 6f 72 ff 0d 0a 50 72 01d0: 65 73 73 20 61 6e 79 20 6b 65 79 20 74 6f 20 72 01e0: 65 73 74 61 72 74 0d 0a 00 00 00 00 00 00 00 00 01f0: 00 00 00 00 00 00 00 00 00 ac bf cc 00 00 55 aa Read block 0 (partition table) Signature 0x55 0xaa, should be 0x55 0xaa Partition 0: boot ff, first sector 0d 0a 44, file system 69, last sector 73 6b 20 : first sector (linear) 6f 72 72 65, sector count 0a 0d ff 72 Partition 1: boot 50, first sector 72 65 73, file system 73, last sector 20 61 6e : first sector (linear) 65 6b 20 79, sector count 6f 74 20 79 Partition 2: boot 20, first sector 72 65 73, file system 74, last sector 61 72 74 : first sector (linear) 00 00 0a 0d, sector count 00 00 00 00 Partition 3: boot 00, first sector 00 00 00, file system 00, last sector 00 00 00 : first sector (linear) ac 00 00 00, sector count 00 00 cc bf
mmc_spi_read_disk_block(0): sending command Request 51 00 00 00 00 ff ff Sent command cmd = 11 arg = 0: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_disk_block(0): reading data token/data/crc mmc_spi_read_data(): got data and CRC 96 bc
Sector info(0 sec : boot): ----------------------------------------------------------------
0 eb 58 90 4d 53 44 4f 53 35 2e 30 0 2 8 20 0 10 2 0 0 0 0 f8 0 0 3f 0 ff 0 0 0 0 0 20 0 2c f 0 ca 3 0 0 0 0 0 0 2 0 0 0 30 1 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 0 29 cb 90 87 a8 4e 4f 20 4e 41 4d 45 20 20 50 20 20 46 41 54 33 32 20 20 20 33 c9 8e d1 bc f4 60 7b 8e c1 8e d9 bd 0 7c 88 4e 2 8a 56 40 b4 8 70 cd 13 73 5 b9 ff ff 8a f1 66 f b6 c6 40 66 f 80 b6 d1 80 e2 3f f7 e2 86 cd c0 ed 6 41 66 f b7 90 c9 66 f7 e1 66 89 46 f8 83 7e 16 0 75 38 83 7e a0 2a 0 77 32 66 8b 46 1c 66 83 c0 c bb 0 80 b9 b0 1 0 e8 2b 0 e9 48 3 a0 fa 7d b4 7d 8b f0 ac c0 84 c0 74 17 3c ff 74 9 b4 e bb 7 0 cd 10 eb d0 ee a0 fb 7d eb e5 a0 f9 7d eb e0 98 cd 16 cd 19 e0 66 60 66 3b 46 f8 f 82 4a 0 66 6a 0 66 50 6 f0 53 66 68 10 0 1 0 80 7e 2 0 f 85 20 0 b4 100 41 bb aa 55 8a 56 40 cd 13 f 82 1c 0 81 fb 55 110 aa f 85 14 0 f6 c1 1 f 84 d 0 fe 46 2 b4 120 42 8a 56 40 8b f4 cd 13 b0 f9 66 58 66 58 66 58 130 66 58 eb 2a 66 33 d2 66 f b7 4e 18 66 f7 f1 fe 140 c2 8a ca 66 8b d0 66 c1 ea 10 f7 76 1a 86 d6 8a 150 56 40 8a e8 c0 e4 6 a cc b8 1 2 cd 13 66 61 160 f 82 54 ff 81 c3 0 2 66 40 49 f 85 71 ff c3 170 4e 54 4c 44 52 20 20 20 20 20 20 0 0 0 0 0 180 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1a0 0 0 0 0 0 0 0 0 0 0 0 0 d a 4e 54 1b0 4c 44 52 20 69 73 20 6d 69 73 73 69 6e 67 ff d 1c0 a 44 69 73 6b 20 65 72 72 6f 72 ff d a 50 72 1d0 65 73 73 20 61 6e 79 20 6b 65 79 20 74 6f 20 72 1e0 65 73 74 61 72 74 d a 0 0 0 0 0 0 0 0 1f0 0 0 0 0 0 0 0 0 0 ac bf cc 0 0 55 aa
----------------------------------------------------------------
mmc_spi_read_disk_block(32): sending command Request 51 00 00 40 00 ff ff Sent command cmd = 11 arg = 16384: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_disk_block(32): reading data token/data/crc mmc_spi_read_data(): got data and CRC 76 3a
Sector info(32 sec : root dir): ----------------------------------------------------------------
0 f8 ff ff ff ff ff ff ff ff ff ff f ff ff ff f 10 ff ff ff f 0 0 0 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 a0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 d0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 e0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 110 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 120 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 140 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 150 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 180 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1a0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1b0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1c0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1d0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1e0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
----------------------------------------------------------------
mmc_spi_read_disk_block(1980): sending command Request 51 00 0f 78 00 ff ff Sent command cmd = 11 arg = 1013760: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_disk_block(1980): reading data token/data/crc mmc_spi_read_data(): got data and CRC 9a 31
Sector info(1980 sec : a.txt): ----------------------------------------------------------------
0 31 32 33 34 35 36 37 38 39 30 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 a0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 d0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 e0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 110 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 120 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 140 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 150 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 180 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1a0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1b0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1c0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1d0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1e0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
----------------------------------------------------------------
mmc_spi_read_disk_block(1988): sending command Request 51 00 0f 88 00 ff ff Sent command cmd = 11 arg = 1017856: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_disk_block(1988): reading data token/data/crc mmc_spi_read_data(): got data and CRC 67 a2
Sector info(1988 sec : b.txt): ----------------------------------------------------------------
0 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 a0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 d0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 e0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 110 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 120 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 140 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 150 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 180 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1a0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1b0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1c0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1d0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1e0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1f0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
----------------------------------------------------------------
Write test mmc_spi_write_disk_block(), sending command Request 58 00 00 c8 00 ff ff Sent command cmd = 18 arg = 51200: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_write_disk_block(): sending data token/data/crc mmc_spi_write_disk_block(): got data response token e5 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 00 mmc_spi_write_disk_block(), polling for ! busy, got response 01 mmc_spi_read_disk_block(100): sending command Request 51 00 00 c8 00 ff ff Sent command cmd = 11 arg = 51200: reply bytes ff ff ff ff ff ff ff loop 0, additional reply 00 mmc_spi_read_disk_block(100): reading data token/data/crc mmc_spi_read_data(): got data and CRC 40 da
Sector info(100 sec : test): ----------------------------------------------------------------
0 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 100 0 1 2 3 4 5 6 7 8 9 a b c d e f 110 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 120 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 130 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 140 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 150 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 160 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 170 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 180 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 190 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f 1a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af 1b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf 1c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf 1d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df 1e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef 1f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
---------------------------------------------------------------- ******************** * SD卡驱动程序设计 * ******************** ------《ecos增值包》之SD卡驱动 2006/09/17 asdjf@163.com www.armecos.com
《ecos增值包》提供了SD/MMC卡驱动程序。SD/MMC卡是体积小(24mm * 32mm * 1.4mm),重量轻(<2克)的非易失性大容量存储设备。典型的卡容量为16MB、128MB、256MB、512MB直至4GB。 硬件级别有两种方式访问SD卡:专用SD总线或者SPI总线。在使用时软件会选择使用其中一种接口。SD总线在性能上优于SPI总线,但需要增加额外硬件。 SD卡一般被格式化为PC兼容的格式,第一块保存分区表,其余部分存放一个单独的FAT文件系统。 SD卡可以在任何时间插入和拔出,设备驱动程序在下一次I/O操作时将检测到拔出事件并通过发送错误码ENODEV向更高层软件汇报,不过,高层代码不保证系统能从这个错误恢复。期望的正确做法是应用代码在尝试访问文件I/O前显式地调用mount挂装SD卡,在卡移除前调用unmount。在mount和unmount之间,系统倾向于在缓存中保存数据块,以便提升性能。如果在unmount前移除SD卡,就会破坏文件系统正确性,导致文件系统处于不稳定状态。定期使用同步sync将减少文件系统被破坏的风险。 SD卡驱动的主要内容是:硬件初始化、SPI时钟速率设置/恢复、寄存器读写、数据块读写擦、电源开关控制、卡在位检测、卡变动识别。 最重要的代码之一是mmc_spi_send_command_start(...),完成命令的组装发送应答。如代码所示,首先将命令、参数和CRC校验组装成6字节命令封装,第7字节的FF是为了获得紧接着的卡应答目的设置的。前面MMC_SPI_BACKGROUND_WRITES条件编译里的代码是为后台模式写操作准备的,用于继续等待前一次写操作命令完成后的数据写入扇区延时,这么做可以在写命令完成后立即做别的工作,不必等待写扇区完成,在下一次写操作前会判断上一次写是否完成,若没有完成则继续等待。 接下来就是SPI总线上的操作了,如《SPI驱动程序设计》一节所述,首先要调用cyg_spi_transaction_begin开始SPI传输过程,这个函数完成总线锁定,避免多个线程同时访问同一个SPI总线。然后调用cyg_spi_transaction_transfer发送命令和接收应答。由于《ecos增值包》的驱动程序可以同时驱动多个SPI总线,所以第一个参数必须提供设备识别dev,以便区分是哪个SPI总线设备。cyg_mmc_spi_polled参数用于选择工作模式(查询/中断),此处应该选择中断模式,以便提高CPU工作效率。SMARTARM2200的SPI是全双工的,收发同时进行,给出发送缓冲、接收缓冲和传输数量,此函数就能自动完成命令发送和应答接收。可能响应不是立即的,此时需要不断查询有效的卡响应。当然应该提供超时退出机制。 数据块读写与此类似,主要是调用SPI总线驱动,按照SD卡访问流程操作,配套书上已经讲得非常详细了,在此不再赘述,请读者举一反三。 CID和CSD是两个比较重要的寄存器,解码程序见后面示例。 SD卡驱动程序总流程: 硬件初始化(切记一定要断开JP7的ATA_INT跳线,因为SSEL需要设置为主机模式,需要上拉。如果不断开ATA_INT,会干扰上拉,导致SPI主机工作不正常。) 至少延时74个时钟周期 复位SD卡命令 激活初始化处理命令 读取并解析CID 读取并解析CSD 设置SPI时钟为最大值 设置读写块长度 ---数据块读写擦--- static cyg_uint32 mmc_spi_send_command_start(cyg_mmc_spi_disk_info_t* disk, cyg_uint32 command, cyg_uint32 arg) { cyg_spi_device* dev = disk->mmc_spi_dev; cyg_uint8 request[7]; cyg_uint8 response[7]; cyg_uint8 reply; int i;
#ifdef MMC_SPI_BACKGROUND_WRITES if (disk->mmc_writing) { DEBUG2("mmc_spi_send_command_start(): polling for completion of previous write
"); disk->mmc_writing = 0; response[0] = 0x00; for (i = 0; (i < MMC_SPI_WRITE_BUSY_RETRIES) && (0x00FF != response[0]); i++) { cyg_spi_transfer(dev, cyg_mmc_spi_polled, 1, mmc_spi_ff_data, response); } } #endif request[0] = command | 0x0040; request[1] = (arg >> 24) & 0x00FF; request[2] = (arg >> 16) & 0x00FF; request[3] = (arg >> 8) & 0x00FF; request[4] = arg & 0x00FF; request[5] = (command == 0x00) ? 0x0095 : 0x00ff; request[6] = 0x00ff;
cyg_spi_transaction_begin(dev); |