历史上的今天
今天是:2024年11月25日(星期一)
2021年11月25日 | SD卡扇区擦除之整卡擦除(以及一些细节问题和疑惑)
2021-11-25 来源:eefocus
前言
其实这个博文是强迫症的产物,对产物;如果要在一个SD卡上建立文件系统FATFS,我带从这张卡的第0个字节,清除到最后一个字节,确保卡上“无残留”,从而不会影响我后续的工作;当整张卡被清除的那一刻,开心!!!
文章中的例程包含标准容量卡SDSC的和高容量卡SDHC的例程;
以我16G的金士顿SD卡为例;
流程
首先你需要获取SD卡上的CSD寄存器值,从而计算出当前卡的准确容量,可以看我下面这个博客:https://blog.csdn.net/wuyuzun/article/details/90581825
这里为啥说当前卡的准确容量,来看下面这个图片比较:
计算机显示我的内存卡的总容量如下

通过STM32的 SD_GetCardStatus() 函数获取SD卡容量,计算过程看上面我那个博客就行。通过串口打印出来如下:

显然:15707668480 != 15690891264;但是两个差值= 16777216 = 16KB;难道这是主引导区MBR?这就是我异或得地方,这是怎么回事?如果有知道的朋友,还麻烦给告诉一下,不胜感激;
所以这里我们以大的15707668480值为此16GSD卡的字节内存空间;
执行命令
图片来源于SD卡V2.0使用手册

SDSC卡 (0~2G,包含2G)是以字节位单位擦除;
ERASE_WR_BLK_START和ERASE_WR_BLK_END是以字节位单位的物理地址;
地址范围:[ERASE_WR_BLK_START,ERASE_WR_BLK_END] == [0,0x001FFFFF]
SDHC卡(2-32G,包括32G)以块为单位进行擦除(固定为512字节);
ERASE_WR_BLK_START和ERASE_WR_BLK_END是以字节位单位的块物理地址;
地址范围: ERASE_WR_BLK_START,ERASE_WR_BLK_END] == [0,0x01FF FFFF];(16G);
4G: [0,0xFFFF FFFF]
8G: [0,0x00FF FFFF]
32G: [0,0x03FF FFFF]
当然上面这都是理论值;实际值是以 15707668480字节为基准的 [0,0x01D41FFF],这里的这个实际也是本文讨论的重点;
相关代码如下
代码是移植于STM32的SD卡例程
/**
* @brief Allows to erase memory Block area specified for the given card.
* @param Block_startaddr: Sets the address of the first write block to be erased.
* @param Block_endaddr: Sets the address of the last write block of the continuous range to be erased.
* @retval SD_Error: SD Card Error code.
*注意:参数里的起始地址和中止地址都是以块地址为单位;可以擦除整个16G空间;
这里有几个值一定要特别注意:
0x01D42000是我的16G的SD卡,以512字节位块单位,状态寄存器返回的内存空间大小,但是这个值并不能作为擦除空间的endaddr;
0x01D3E000是电脑显示的16GSD卡的以512字节位块单位的地址空间,可以作为endaddr;
0x0x01D41FFF才是能作为最终endaddr的值;
*/
SD_Error SD_Block_Erase(uint32_t Block_startaddr, uint32_t Block_endaddr)
{
SD_Error errorstatus = SD_OK;
uint32_t delay = 0;
__IO uint32_t maxdelay = 0;
uint8_t cardstate = 0;
/*!< Check if the card coomnd class supports erase command */
if (((CSD_Tab[1] >> 20) & SD_CCCC_ERASE) == 0) //0x00000020
{
errorstatus = SD_REQUEST_NOT_APPLICABLE;
return(errorstatus);
}
maxdelay = 120000 / ((SDIO->CLKCR & 0xFF) + 2);
if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)
{
errorstatus = SD_LOCK_UNLOCK_FAILED;
return(errorstatus);
}
/*!< According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */
if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))
{
/*!< Send CMD32 SD_ERASE_GRP_START with argument as addr */
SDIO_CmdInitStructure.SDIO_Argument = Block_startaddr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_START;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_START);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
/*!< Send CMD33 SD_ERASE_GRP_END with argument as addr */
SDIO_CmdInitStructure.SDIO_Argument = Block_endaddr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_END;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_END);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
}
/*!< Send CMD38 ERASE */
SDIO_CmdInitStructure.SDIO_Argument = 0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ERASE;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_ERASE);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
for (delay = 0; delay < maxdelay; delay++)
{}
/*!< Wait till the card is in programming state */
errorstatus = IsCardProgramming(&cardstate);
while ((errorstatus == SD_OK) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate)))
{
errorstatus = IsCardProgramming(&cardstate);
}
return(errorstatus);
}
上一篇:解决STM32 SD卡官方库移植时 获取不到SD Status寄存器值的问题
下一篇:错误:error: #268:declaration may not appear after executable statement in
史海拾趣
|
急需!!! 电子技术研发设计开发方案!!! 急需!!! 方案!!! 公司拓展,急需方案,请拥有方案或部分技术的公司和个人迅速与我联系, 邮箱 rdeasy@yahoo.cn 请注明公司全名或个人的姓,详细准确的联系方式和方案,否则不予考。 ...… 查看全部问答> |
|
目 录 第一篇 低压开关柜二次线路的设计安装、 运行维护总论 ( ) ………………… 第一章 配电网络和配电设备概述 ( ) ………………………………………………… 第二章 配电变压器的设计安装、 运行维护 ( ) …………………………………… ...… 查看全部问答> |
|
我做一个232的通讯,希望传一个16进制数比如0XFE到PC,然后PC端通过DELPHI写的程序能读出这个16进制数.哪位有这个例子,PC端怎么读(是通过自己写程序,还是有现成的调试工具)我到现在还不知道呢,哪位讲下啊… 查看全部问答> |
|
就我个人经历,大家在无线选型上常会有的一些误区: 1,通信速率,比如很多公司是这样宣传的NRF2401速率是1MBPS, 但,实际上这只是发射速率,而实际真正完成一次发送速率需要涉及到具体的功能,因为功能越复杂,完成一次数据采集的 ...… 查看全部问答> |
|
所在公司的一个项目,比较类似于手持gps。 大致上硬件环境就是FPGA的开发板,Altera的2c系列,采用nios的软核cpu。 开发环境就是NIOSII 6.1,c语言。 具体要实现的具体功能已经部分有一些代码,测试功能用。 现在想加操作系统,需要高手帮忙。 ...… 查看全部问答> |
|
内容摘要: 结合红外防盗报警和ZigBee技术这两大热点课题,利用TI公司的单芯片CC2430和RE200B红外传感器,完成了基于ZigBee技术无线红外防盗报警系统的硬件设计和软件开发,解决了现有无线报警系统存在的误报警,成本高等问题。经过对系统的硬件软件电 ...… 查看全部问答> |




