bsp_SD.cpp
D:/gitt/MicrochipFor32/bsp_Device/bsp_SPI/bsp_SD.cpp
浏览该文件的文档.00001 /*----------------------------------------------------------------------------------------------------
00002 #
00003 # Copyright (c) 2022 Yuankang Liang(XerolySkinner)
00004 #
00005 # 本软件按原样提供,无任何明示或暗示
00006 # 在任何情况下,作者都不承担任何损害赔偿责任
00007 #
00008 # 使用的许可声明:
00009 # 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件.
00010 # 2. 免费授予以任何目的,前提是版权声明出现在所有副本中.
00011 # 并且版权声明和许可声明同时出现.
00012 # 3. 你有使用,复制,修改,分发,和销售本软件的许可.
00013 # 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的.
00014 # 5. 本通知不得从任何来源删除或更改.
00015 #
00016 # Yuankang Liang(XerolySkinner)
00017 # E-mail:zabbcccbbaz@163.com
00018 # QQ:2715099320
00019 # Mobile Phone:13005636215
00020 #
00021 # All rights reserved.
00022 */
00023
00034 #include "bsp_SD.h"
00036 //----------------------------------------------------------------------------------------------------
00037 // 程序
00038 //
00043 void bsp_SD::SD_CS(u8 p){
00044 HAL_GPIO_WritePin(GPIOx_CS, GPIO_Pin_CS, p == 0 ? GPIO_PIN_SET: GPIO_PIN_RESET);}
00045 //----------------------------------------------------------------------------------------------------
00053 u32 bsp_SD::SD_sendcmd(u8 cmd, u32 arg, u8 crc){
00054 u8 r1;
00055 u8 retry;
00056 SD_CS(0);
00057 __nop();
00058 SD_CS(1);
00059 do retry = spi_readwrite(DFF);while(retry != 0xFF);
00060 spi_readwrite(cmd | 0x40);
00061 spi_readwrite(arg >> 24);
00062 spi_readwrite(arg >> 16);
00063 spi_readwrite(arg >> 8);
00064 spi_readwrite(arg);
00065 spi_readwrite(crc);
00066 if (cmd == CMD12) spi_readwrite(DFF);
00067 do r1 = spi_readwrite(0xFF);while(r1 & 0X80);
00068 return r1;}
00069 //----------------------------------------------------------------------------------------------------
00074 u8 bsp_SD::SD_init(void){
00075 u8 r1;
00076 u8 buff[6] = {0};
00077 u16 retry;
00078 u8 i;
00079 // MX_SPI3_Init();
00080 SPI_setspeed(SPI_BAUDRATEPRESCALER_256);
00081 SD_CS(0);
00082 for (retry = 0; retry < 10; retry++) spi_readwrite(DFF);
00083 // SD卡进入IDLE状态
00084 do r1 = SD_sendcmd(CMD0, 0, 0x95);while(r1 != 0x01);
00085 // 查看SD卡的类型
00086 SD_TYPE = 0;
00087 r1 = SD_sendcmd(CMD8, 0x1AA, 0x87);
00088 if (r1 == 0x01) {
00089 for (i = 0; i < 4; i++) buff[i] = spi_readwrite(DFF); //Get trailing return value of R7 resp
00090 if (buff[2] == 0X01 && buff[3] == 0XAA) { //卡是否支持2.7~3.6V
00091 retry = 0XFFFE;
00092 do {
00093 SD_sendcmd(CMD55, 0, 0X01); //发送CMD55
00094 r1 = SD_sendcmd(CMD41, 0x40000000, 0X01); //发送CMD41
00095 }while(r1 && retry--);
00096 if (retry && SD_sendcmd(CMD58, 0, 0X01) == 0) { //鉴别SD2.0卡版本开始
00097 for (i = 0; i < 4; i++) buff[i] = spi_readwrite(0XFF); //得到OCR值
00098 if (buff[0] &0x40) SD_TYPE = V2HC;
00099 else SD_TYPE = V2;}}
00100 else {
00101 SD_sendcmd(CMD55, 0, 0X01); //发送CMD55
00102 r1 = SD_sendcmd(CMD41, 0, 0X01); //发送CMD41
00103 if (r1 <= 1) {
00104 SD_TYPE = V1;
00105 retry = 0XFFFE;
00106 do { //等待退出IDLE模式
00107 SD_sendcmd(CMD55, 0, 0X01); //发送CMD55
00108 r1 = SD_sendcmd(CMD41, 0, 0X01); //发送CMD41
00109 }while(r1 && retry--);}
00110 else { //MMC卡不支持CMD55+CMD41识别
00111 SD_TYPE = MMC; //MMC V3
00112 retry = 0XFFFE;
00113 do r1 = SD_sendcmd(CMD1, 0, 0X01);while(r1 && retry--);} //等待退出IDLE模式
00114 if (retry == 0 || SD_sendcmd(CMD16, 512, 0X01) != 0) SD_TYPE = ERR;} //错误的卡
00115 }
00116 SD_CS(0);
00117 SPI_setspeed(SPI_BAUDRATEPRESCALER_2);
00118 if (SD_TYPE) return 0;
00119 else return 1;}
00120 //----------------------------------------------------------------------------------------------------
00127 u8 bsp_SD::SD_ReceiveData(u8 * data, u16 len){
00128 u8 r1;
00129 SD_CS(1);
00130 do {
00131 r1 = spi_readwrite(0xFF);
00132 __nop();
00133 }while(r1 != 0xFE);
00134 while (len--) {
00135 *data = spi_readwrite(0xFF);
00136 data++;}
00137 spi_readwrite(0xFF);
00138 spi_readwrite(0xFF);
00139 return 0;}
00140 //----------------------------------------------------------------------------------------------------
00147 u8 bsp_SD::SD_SendBlock(u8 * buf, u8 cmd){
00148 u16 t;
00149 u8 r1;
00150 do r1 = spi_readwrite(0xFF);while(r1 != 0xFF);
00151 spi_readwrite(cmd);
00152 if (cmd != 0XFD) { //不是结束指令
00153 for (t = 0; t < 512; t++) spi_readwrite(buf[t]); //提高速度,减少函数传参时间
00154 spi_readwrite(0xFF); //忽略crc
00155 spi_readwrite(0xFF);
00156 t = spi_readwrite(0xFF); //接收响应
00157 if ((t & 0x1F) != 0x05) return 2;} //响应错误
00158 return 0;} //写入成功
00159 //----------------------------------------------------------------------------------------------------
00164 u8 bsp_SD::SD_GETCID(u8 * cid_data){
00165 u8 r1;
00166 r1 = SD_sendcmd(CMD10, 0, 0x01); //读取CID寄存器
00167 if (r1 == 0x00) r1 = SD_ReceiveData(cid_data, 16);
00168 SD_CS(0);
00169 if (r1) return 1;
00170 else return 0;}
00171 //----------------------------------------------------------------------------------------------------
00176 u8 bsp_SD::SD_GETCSD(u8 * csd_data){
00177 u8 r1;
00178 r1 = SD_sendcmd(CMD9, 0, 0x01); //发CMD9命令,读CSD寄存器
00179 if (r1 == 0) r1 = SD_ReceiveData(csd_data, 16); //接收16个字节的数据
00180 SD_CS(0); //取消片选
00181 if (r1) return 1;
00182 else return 0;}
00183 //----------------------------------------------------------------------------------------------------
00188 u32 bsp_SD::SD_GetSectorCount(void){
00189 u8 csd[16];
00190 u32 Capacity;
00191 u8 n;
00192 u16 csize;
00193 //取CSD信息,如果期间出错,返回0
00194 if (SD_GETCSD(csd) != 0) return 0;
00195 //如果为SDHC卡,按照下面方式计算
00196 if ((csd[0] &0xC0) == 0x40) { //V2.00的卡
00197 csize = csd[9] + ((u16) csd[8] << 8) + 1;
00198 Capacity = (u32)
00199 csize << 10;} //得到扇区数
00200 else { //V1.XX的卡
00201 n = (csd[5] &15) + ((csd[10] &128) >> 7) + ((csd[9] &3) << 1) + 2;
00202 csize = (csd[8] >> 6) + ((u16) csd[7] << 2) + ((u16) (csd[6] &3) << 10) + 1;
00203 Capacity = (u32)
00204 csize << (n - 9);} //得到扇区数
00205 return Capacity;}
00206 //----------------------------------------------------------------------------------------------------
00207 int bsp_SD::MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo){
00208 u8 r1;
00209 u8 CSD_Tab[16];
00210 u8 CID_Tab[16];
00211 /* Send CMD9, Read CSD */
00212 r1 = SD_sendcmd(CMD9, 0, 0xFF);
00213 if (r1 != 0x00) return r1;
00214 if (SD_ReceiveData(CSD_Tab, 16)) return 1;
00215 /* Send CMD10, Read CID */
00216 r1 = SD_sendcmd(CMD10, 0, 0xFF);
00217 if (r1 != 0x00) return r1;
00218 if (SD_ReceiveData(CID_Tab, 16)) return 2;
00219 /* Byte 0 */
00220 SD0_CardInfo->CSD.CSDStruct = (CSD_Tab[0] &0xC0) >> 6;
00221 SD0_CardInfo->CSD.SysSpecVersion = (CSD_Tab[0] &0x3C) >> 2;
00222 SD0_CardInfo->CSD.Reserved1 = CSD_Tab[0] &0x03;
00223 /* Byte 1 */
00224 SD0_CardInfo->CSD.TAAC = CSD_Tab[1];
00225 /* Byte 2 */
00226 SD0_CardInfo->CSD.NSAC = CSD_Tab[2];
00227 /* Byte 3 */
00228 SD0_CardInfo->CSD.MaxBusClkFrec = CSD_Tab[3];
00229 /* Byte 4 */
00230 SD0_CardInfo->CSD.CardComdClasses = CSD_Tab[4] << 4;
00231 /* Byte 5 */
00232 SD0_CardInfo->CSD.CardComdClasses |= (CSD_Tab[5] &0xF0) >> 4;
00233 SD0_CardInfo->CSD.RdBlockLen = CSD_Tab[5] &0x0F;
00234 /* Byte 6 */
00235 SD0_CardInfo->CSD.PartBlockRead = (CSD_Tab[6] &0x80) >> 7;
00236 SD0_CardInfo->CSD.WrBlockMisalign = (CSD_Tab[6] &0x40) >> 6;
00237 SD0_CardInfo->CSD.RdBlockMisalign = (CSD_Tab[6] &0x20) >> 5;
00238 SD0_CardInfo->CSD.DSRImpl = (CSD_Tab[6] &0x10) >> 4;
00239 SD0_CardInfo->CSD.Reserved2 = 0; /* Reserved */
00240 SD0_CardInfo->CSD.DeviceSize = (CSD_Tab[6] &0x03) << 10;
00241 /* Byte 7 */
00242 SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[7]) << 2;
00243 /* Byte 8 */
00244 SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[8] &0xC0) >> 6;
00245 SD0_CardInfo->CSD.MaxRdCurrentVDDMin = (CSD_Tab[8] &0x38) >> 3;
00246 SD0_CardInfo->CSD.MaxRdCurrentVDDMax = (CSD_Tab[8] &0x07);
00247 /* Byte 9 */
00248 SD0_CardInfo->CSD.MaxWrCurrentVDDMin = (CSD_Tab[9] &0xE0) >> 5;
00249 SD0_CardInfo->CSD.MaxWrCurrentVDDMax = (CSD_Tab[9] &0x1C) >> 2;
00250 SD0_CardInfo->CSD.DeviceSizeMul = (CSD_Tab[9] &0x03) << 1;
00251 /* Byte 10 */
00252 SD0_CardInfo->CSD.DeviceSizeMul |= (CSD_Tab[10] &0x80) >> 7;
00253 SD0_CardInfo->CSD.EraseGrSize = (CSD_Tab[10] &0x7C) >> 2;
00254 SD0_CardInfo->CSD.EraseGrMul = (CSD_Tab[10] &0x03) << 3;
00255 /* Byte 11 */
00256 SD0_CardInfo->CSD.EraseGrMul |= (CSD_Tab[11] &0xE0) >> 5;
00257 SD0_CardInfo->CSD.WrProtectGrSize = (CSD_Tab[11] &0x1F);
00258 /* Byte 12 */
00259 SD0_CardInfo->CSD.WrProtectGrEnable = (CSD_Tab[12] &0x80) >> 7;
00260 SD0_CardInfo->CSD.ManDeflECC = (CSD_Tab[12] &0x60) >> 5;
00261 SD0_CardInfo->CSD.WrSpeedFact = (CSD_Tab[12] &0x1C) >> 2;
00262 SD0_CardInfo->CSD.MaxWrBlockLen = (CSD_Tab[12] &0x03) << 2;
00263 /* Byte 13 */
00264 SD0_CardInfo->CSD.MaxWrBlockLen |= (CSD_Tab[13] &0xc0) >> 6;
00265 SD0_CardInfo->CSD.WriteBlockPaPartial = (CSD_Tab[13] &0x20) >> 5;
00266 SD0_CardInfo->CSD.Reserved3 = 0;
00267 SD0_CardInfo->CSD.ContentProtectAppli = (CSD_Tab[13] &0x01);
00268 /* Byte 14 */
00269 SD0_CardInfo->CSD.FileFormatGrouop = (CSD_Tab[14] &0x80) >> 7;
00270 SD0_CardInfo->CSD.CopyFlag = (CSD_Tab[14] &0x40) >> 6;
00271 SD0_CardInfo->CSD.PermWrProtect = (CSD_Tab[14] &0x20) >> 5;
00272 SD0_CardInfo->CSD.TempWrProtect = (CSD_Tab[14] &0x10) >> 4;
00273 SD0_CardInfo->CSD.FileFormat = (CSD_Tab[14] &0x0C) >> 2;
00274 SD0_CardInfo->CSD.ECC = (CSD_Tab[14] &0x03);
00275 /* Byte 15 */
00276 SD0_CardInfo->CSD.CSD_CRC = (CSD_Tab[15] &0xFE) >> 1;
00277 SD0_CardInfo->CSD.Reserved4 = 1;
00278 if (SD0_CardInfo->CardType == V2HC) {
00279 /* Byte 7 */
00280 SD0_CardInfo->CSD.DeviceSize = (u16) (CSD_Tab[8]) * 256;
00281 /* Byte 8 */
00282 SD0_CardInfo->CSD.DeviceSize += CSD_Tab[9];}
00283 SD0_CardInfo->Capacity = SD0_CardInfo->CSD.DeviceSize * MSD_BLOCKSIZE * 1024;
00284 SD0_CardInfo->BlockSize = MSD_BLOCKSIZE;
00285 /* Byte 0 */
00286 SD0_CardInfo->CID.ManufacturerID = CID_Tab[0];
00287 /* Byte 1 */
00288 SD0_CardInfo->CID.OEM_AppliID = CID_Tab[1] << 8;
00289 /* Byte 2 */
00290 SD0_CardInfo->CID.OEM_AppliID |= CID_Tab[2];
00291 /* Byte 3 */
00292 SD0_CardInfo->CID.ProdName1 = CID_Tab[3] << 24;
00293 /* Byte 4 */
00294 SD0_CardInfo->CID.ProdName1 |= CID_Tab[4] << 16;
00295 /* Byte 5 */
00296 SD0_CardInfo->CID.ProdName1 |= CID_Tab[5] << 8;
00297 /* Byte 6 */
00298 SD0_CardInfo->CID.ProdName1 |= CID_Tab[6];
00299 /* Byte 7 */
00300 SD0_CardInfo->CID.ProdName2 = CID_Tab[7];
00301 /* Byte 8 */
00302 SD0_CardInfo->CID.ProdRev = CID_Tab[8];
00303 /* Byte 9 */
00304 SD0_CardInfo->CID.ProdSN = CID_Tab[9] << 24;
00305 /* Byte 10 */
00306 SD0_CardInfo->CID.ProdSN |= CID_Tab[10] << 16;
00307 /* Byte 11 */
00308 SD0_CardInfo->CID.ProdSN |= CID_Tab[11] << 8;
00309 /* Byte 12 */
00310 SD0_CardInfo->CID.ProdSN |= CID_Tab[12];
00311 /* Byte 13 */
00312 SD0_CardInfo->CID.Reserved1 |= (CID_Tab[13] &0xF0) >> 4;
00313 /* Byte 14 */
00314 SD0_CardInfo->CID.ManufactDate = (CID_Tab[13] &0x0F) << 8;
00315 /* Byte 15 */
00316 SD0_CardInfo->CID.ManufactDate |= CID_Tab[14];
00317 /* Byte 16 */
00318 SD0_CardInfo->CID.CID_CRC = (CID_Tab[15] &0xFE) >> 1;
00319 SD0_CardInfo->CID.Reserved2 = 1;
00320 return 0;}
00321 //----------------------------------------------------------------------------------------------------
00329 u8 bsp_SD::SD_WriteDisk(u8 * buf, u32 sector, u8 cnt){
00330 u8 r1;
00331 if (SD_TYPE != V2HC) sector *= 512; //转换为字节地址
00332 if (cnt == 1){
00333 r1 = SD_sendcmd(CMD24, sector, 0X01); //读命令
00334 if (r1 == 0) //指令发送成功
00335 r1 = SD_SendBlock(buf, 0xFE);} //写512个字节
00336 else {
00337 if (SD_TYPE != MMC) {
00338 SD_sendcmd(CMD55, 0, 0X01);
00339 SD_sendcmd(CMD23, cnt, 0X01);} //发送指令
00340 r1 = SD_sendcmd(CMD25, sector, 0X01); //连续读命令
00341 if (r1 == 0) {
00342 do {
00343 r1 = SD_SendBlock(buf, 0xFC); //接收512个字节
00344 buf += 512;}while(--cnt && r1 == 0);
00345 r1 = SD_SendBlock(0, 0xFD);}} //接收512个字节
00346 SD_CS(0); //取消片选
00347 return r1;}
00348 //----------------------------------------------------------------------------------------------------
00356 u8 bsp_SD::SD_ReadDisk(u8 * buf, u32 sector, u8 cnt){
00357 u8 r1;
00358 if (SD_TYPE != V2HC) sector <<= 9; //转换为字节地址
00359 if (cnt == 1) {
00360 r1 = SD_sendcmd(CMD17, sector, 0X01); //读命令
00361 if (r1 == 0) //指令发送成功
00362 r1 = SD_ReceiveData(buf, 512);} //接收512个字节
00363 else {
00364 r1 = SD_sendcmd(CMD18, sector, 0X01); //连续读命令
00365 do {
00366 r1 = SD_ReceiveData(buf, 512); //接收512个字节
00367 buf += 512;}
00368 while(--cnt && r1 == 0);
00369 SD_sendcmd(CMD12, 0, 0X01);} //发送停止命令
00370 SD_CS(0); //取消片选
00371 return r1;}
00372 //----------------------------------------------------------------------------------------------------
00373 u8 bsp_SD::spi_readwrite(u8 Txdata){
00374 u8 Rxdata;
00375 HAL_SPI_TransmitReceive(hspi, &Txdata, &Rxdata, 1, 0xFF);
00376 return Rxdata;}
00377 //----------------------------------------------------------------------------------------------------
00383 void bsp_SD::SPI_setspeed(u8 speed){
00384 hspi->Init.BaudRatePrescaler = speed;}
00385 //----------------------------------------------------------------------------------------------------
00393 u8 bsp_SD::offsetWrite(u64 offset,u8* dat,u64 datlen) {
00394 u8 sectorBuff[512] = { 0 };
00395 u64 sectorBuffptr = 0;
00396
00397 u64 sectorSour = offset / 512; // 起始扇
00398 u64 sectorSourlen = offset % 512; // 起始扇内位
00399
00400 // 填入数据
00401 SD_ReadDisk(sectorBuff,sectorSour,1);
00402 sectorBuffptr = sectorSourlen;
00403 for (u64 i = 0; i < datlen; i++) {
00404 // 写入数据
00405 sectorBuff[sectorBuffptr] = dat[i];
00406 sectorBuffptr++;
00407 // 扇区回写
00408 if (sectorBuffptr == 512 || i == datlen - 1) {
00409 SD_WriteDisk(sectorBuff,sectorSour,1);
00410 sectorBuffptr = 0;
00411 sectorSour++;
00412 if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}}
00413 return 0;
00414 }
00415 //----------------------------------------------------------------------------------------------------
00423 u8 bsp_SD::offsetRead(u64 offset,u8* dat,u64 datlen) {
00424 u8 sectorBuff[512] = { 0 };
00425 u64 sectorBuffptr = 0;
00426
00427 u64 sectorSour = offset / 512; // 起始扇
00428 u64 sectorSourlen = offset % 512; // 起始扇内位
00429
00430 // 填入数据
00431 SD_ReadDisk(sectorBuff,sectorSour,1);
00432 sectorBuffptr = sectorSourlen;
00433 for (u64 i = 0; i < datlen; i++) {
00434 // 写入数据
00435 dat[i]=sectorBuff[sectorBuffptr];
00436 sectorBuffptr++;
00437 // 扇区回写
00438 if (sectorBuffptr == 512 || i == datlen - 1) {
00439 sectorBuffptr = 0;
00440 sectorSour++;
00441 if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}}
00442 return 0;}
00444 //----------------------------------------------------------------------------------------------------
00445 // 构造函数
00446 //
00447 bsp_SD::bsp_SD(
00448 SPI_HandleTypeDef *hspi,
00449 GPIO_TypeDef *GPIOx_CS,
00450 uint16_t GPIO_Pin_CS){
00451 bsp_SD::hspi=hspi;
00452 bsp_SD::GPIOx_CS=GPIOx_CS;
00453 bsp_SD::GPIO_Pin_CS=GPIO_Pin_CS;
00454 bsp_SD::DFF=0xFF;
00455 bsp_SD::SD_TYPE=0x00;}