[原创].关于SD卡的隐藏分区的认识过程及结果

[原创][连载].基于SOPC的简易数码相框 – Nios II SBTE部分(软件部分) – SD卡(SPI模式)驱动

上一次我用Nios II驱动SD卡(SPI模式),使用的是金斯顿的卡。然后void SD_CARD_Read_Data_LBAu32 LBA,u16 n_bytes,u8 *buf);读取的扇区与使用winhex查看的逻辑扇区的内容,其偏移地址和内容是一样的。这一次,我使用nuc1xx来驱动SD卡,简单的把上次用IO模拟的部分,换成了SPI核来操作,一直很顺利,读取的CSD和CID也是吻合的。但不巧的是,这次我手上只有一张CANAN DV上面的SD卡,使用void SD_CARD_Read_Data_LBAu32 LBA,u16 n_bytes,u8 *buf);读取的扇区和winhex查看的逻辑扇区内容是不一致的。

SD卡读取代码片段

void SD_CARD_DEMOvoid)
{
    uint16_t i;
    uint8_t buf[512];
    
    SD_CARD_DEBUG"\r");    
    SD_CARD_DEBUG"开始读取SD卡信息\r");   
    SD_CARD_Get_Info); // 读取CID和CSD
    SD_CARD_DEBUG"SD卡信息读取完毕\r");
    
    SD_CARD_DEBUG"\r");
    SD_CARD_DEBUG"开始读取SD卡的第一个块(扇区)\r");
    SD_CARD_Read_Data_LBA0,512,buf); // 读取SD卡的第一个块(扇区)
    fori=0; i<512; i++) {
        ifi%16 == 0) SD_CARD_DEBUG"0x%.3X ", i);
        SD_CARD_DEBUG"%.2X ", buf[i]);
        ifi+1) % 8 == 0) SD_CARD_DEBUG" ");
        ifi+1) % 16 == 0) SD_CARD_DEBUG"\r");
    }
    SD_CARD_DEBUG"读取SD卡的第一个块(扇区)完毕\r");
}

使用串口调试所显示的数据

SD卡初始化完成

开始读取SD卡信息
SD-CARD CID:
    Manufacturer IDMID): 0x88
    OEM/Application IDOLD): 
    Product NamePNM): NCard
    Product Revision: 0x10
    Serial NumberPSN): 0x00000286
    Manufacture Date CodeMDT): 0x0AC
    CRC-7 ChecksumCRC7):0x11
SD-CARD CSD:
    max.read data block length: 1024
    device size: 3821
    device size multiplier: 7
    device capacity: 1911 MB
SD卡信息读取完毕

开始读取SD卡的第一个块(扇区)
0x000 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x010 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x020 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x030 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x040 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x050 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x060 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x070 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x080 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x090 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x0A0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x0B0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x0C0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x0D0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x0E0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x0F0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x100 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x110 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x120 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x130 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x140 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x150 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x160 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x170 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x180 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x190 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x1A0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x1B0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 02  
0x1C0 04 00 06 2A EA CA 81 00  00 00 7F B7 3B 00 00 00  
0x1D0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x1E0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
0x1F0 00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 AA  
读取SD卡的第一个块(扇区)完毕

而使用winhex读取的内容却不一样,一时间我就蒙了。

image

image

image

图1 使用winhex读取的SD卡的逻辑扇区0内容

为何读取的内容不对呢?

在ourdev上面逛,找到如下资料。

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3849969

【3楼】 greenwoods

积分:140
派别:
等级:——
来自:
猜测一下,逻辑地址=物理地址+保留的扇区数,DBR可能在物理地址的零扇区,也可能不在零扇区。
如果不在零扇区,在零扇区的 0x1c6 有保留的扇区数。
用WinHex观察时,如果装入的是physical media就应该是物理地址。可能格式化后,保留的扇区数与原来不一样,所以逻辑地址改变。

__________________________
Across the greatwall we can reach every corner in the world.

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4348878

【5楼】 zxs2000
积分:141
派别:
等级:——
来自:
谢谢!
该扇区有两个重要信息:
一、在0x1ca开始的四个字节代表该SD卡有个扇区
二、在0x1c6开始的四个字节表示引导扇区在哪个扇区。

于是我对比用串口读出来的数据,从0x1C6起的4个字节为0x00 00 00 81=129,从0x1CA起的4个字节内容为0x00 3B B7 7F=3913599

注意上面图1imageimage

再一次使用winhex读取SD卡,不过这一次我们要读取物理扇区0的内容。

image

image

图2 使用winhex读取的SD卡的物理扇区0内容

图2所示与SD卡所读完全一致。这说明,我上次使用nios ii读取金士顿的卡,属于“走运”,碰巧物理扇区核逻辑扇区重叠。

注意观察,图2image 和图一image对比,是不是3913728-3713599=129。

SD卡读取代码片段

void SD_CARD_DEMOvoid)
{
    uint16_t i;
    uint8_t buf[512];
    
    SD_CARD_DEBUG"\r");    
    SD_CARD_DEBUG"开始读取SD卡信息\r");   
    SD_CARD_Get_Info); // 读取CID和CSD
    SD_CARD_DEBUG"SD卡信息读取完毕\r");
    
    SD_CARD_DEBUG"\r");
    SD_CARD_DEBUG"开始读取SD卡的第一个块(扇区)\r");
    SD_CARD_Read_Data_LBA129,512,buf); // 读取SD卡的第129个块(扇区)
    fori=0; i<512; i++) {
        ifi%16 == 0) SD_CARD_DEBUG"0x%.3X ", i);
        SD_CARD_DEBUG"%.2X ", buf[i]);
        ifi+1) % 8 == 0) SD_CARD_DEBUG" ");
        ifi+1) % 16 == 0) SD_CARD_DEBUG"\r");
    }
    SD_CARD_DEBUG"读取SD卡的第129个块(扇区)完毕\r");
}

使用串口调试所显示的数据

SD卡初始化完成

开始读取SD卡信息
SD-CARD CID:
    Manufacturer IDMID): 0x88
    OEM/Application IDOLD): 
    Product NamePNM): NCard
    Product Revision: 0x10
    Serial NumberPSN): 0x00000286
    Manufacture Date CodeMDT): 0x0AC
    CRC-7 ChecksumCRC7):0x11
SD-CARD CSD:
    max.read data block length: 1024
    device size: 3821
    device size multiplier: 7
    device capacity: 1911 MB
SD卡信息读取完毕

开始读取SD卡的第129个块(扇区)
0x000 EB 3C 90 4D 53 44 4F 53  35 2E 30 00 02 40 02 00  
0x010 02 00 02 00 00 F8 EF 00  3F 00 FF 00 81 00 00 00  
0x020 7F B7 3B 00 00 00 29 DD  DF CE AC 4E 4F 20 4E 41  
0x030 4D 45 20 20 20 20 46 41  54 31 36 20 20 20 33 C9  
0x040 8E D1 BC F0 7B 8E D9 B8  00 20 8E C0 FC BD 00 7C  
0x050 38 4E 24 7D 24 8B C1 99  E8 3C 01 72 1C 83 EB 3A  
0x060 66 A1 1C 7C 26 66 3B 07  26 8A 57 FC 75 06 80 CA  
0x070 02 88 56 02 80 C3 10 73  EB 33 C9 8A 46 10 98 F7  
0x080 66 16 03 46 1C 13 56 1E  03 46 0E 13 D1 8B 76 11  
0x090 60 89 46 FC 89 56 FE B8  20 00 F7 E6 8B 5E 0B 03  
0x0A0 C3 48 F7 F3 01 46 FC 11  4E FE 61 BF 00 00 E8 E6  
0x0B0 00 72 39 26 38 2D 74 17  60 B1 0B BE A1 7D F3 A6  
0x0C0 61 74 32 4E 74 09 83 C7  20 3B FB 72 E6 EB DC A0  
0x0D0 FB 7D B4 7D 8B F0 AC 98  40 74 0C 48 74 13 B4 0E  
0x0E0 BB 07 00 CD 10 EB EF A0  FD 7D EB E6 A0 FC 7D EB  
0x0F0 E1 CD 16 CD 19 26 8B 55  1A 52 B0 01 BB 00 00 E8  
0x100 3B 00 72 E8 5B 8A 56 24  BE 0B 7C 8B FC C7 46 F0  
0x110 3D 7D C7 46 F4 29 7D 8C  D9 89 4E F2 89 4E F6 C6  
0x120 06 96 7D CB EA 03 00 00  20 0F B6 C8 66 8B 46 F8  
0x130 66 03 46 1C 66 8B D0 66  C1 EA 10 EB 5E 0F B6 C8  
0x140 4A 4A 8A 46 0D 32 E4 F7  E2 03 46 FC 13 56 FE EB  
0x150 4A 52 50 06 53 6A 01 6A  10 91 8B 46 18 96 92 33  
0x160 D2 F7 F6 91 F7 F6 42 87  CA F7 76 1A 8A F2 8A E8  
0x170 C0 CC 02 0A CC B8 01 02  80 7E 02 0E 75 04 B4 42  
0x180 8B F4 8A 56 24 CD 13 61  61 72 0B 40 75 01 42 03  
0x190 5E 0B 49 75 06 F8 C3 41  BB 00 00 60 66 6A 00 EB  
0x1A0 B0 4E 54 4C 44 52 20 20  20 20 20 20 0D 0A 52 65  
0x1B0 6D 6F 76 65 20 64 69 73  6B 73 20 6F 72 20 6F 74  
0x1C0 68 65 72 20 6D 65 64 69  61 2E FF 0D 0A 44 69 73  
0x1D0 6B 20 65 72 72 6F 72 FF  0D 0A 50 72 65 73 73 20  
0x1E0 61 6E 79 20 6B 65 79 20  74 6F 20 72 65 73 74 61  
0x1F0 72 74 0D 0A 00 00 00 00  00 00 00 AC CB D8 55 AA  
读取SD卡的第129个块(扇区)完毕

与winhex的逻辑0扇区内容一致。回头看上面计算的数据

从0x1C6起的4个字节为0x00 00 00 81=129,从0x1CA起的4个字节内容为0x00 3B B7 7F=3913599

原来我现在使用的这张SD卡,隐藏扇区大小为129个扇区,可用逻辑扇区大小为3713599=0x00 3B B7 7F个扇区,而本卡所有的扇区数为3913728=0x00 3B B7 7F +0x00 00 00 81。

虽然知道了这些,我还是很沮丧,因为我不晓得用代码来做,怎样才能直接访问到逻辑扇区?难道是靠碰运气?每次都拿winhex对比一下?求解答。

 安德鲁® / CC BY 2.5
    FPGA Run!

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注