457 lines
15 KiB
C++
457 lines
15 KiB
C++
|
|
/*----------------------------------------------------------------------------------------------------
|
|||
|
|
#
|
|||
|
|
# Copyright (c) 2022 Yuankang Liang(XerolySkinner)
|
|||
|
|
#
|
|||
|
|
# <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ṩ,<2C><><EFBFBD>κ<EFBFBD><CEBA><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ʾ
|
|||
|
|
# <09><><EFBFBD>κ<EFBFBD><CEBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD>е<EFBFBD><D0B5>κ<EFBFBD><CEBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⳥<EFBFBD><E2B3A5><EFBFBD><EFBFBD>
|
|||
|
|
#
|
|||
|
|
# ʹ<>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
|
|||
|
|
# 1. <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ,<2C>㲻<EFBFBD><E3B2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>ԭʼ<D4AD><CABC><EFBFBD><EFBFBD>.
|
|||
|
|
# 2. <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD>Ŀ<EFBFBD><C4BF>,ǰ<><C7B0><EFBFBD>ǰ<EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
|
# <09><><EFBFBD>Ұ<EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD>.
|
|||
|
|
# 3. <09><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>,<2C><><EFBFBD><EFBFBD>,<2C><EFBFBD>,<2C>ַ<EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD>۱<EFBFBD><DBB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
|
# 4. <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>Ʒ<EFBFBD><C6B7>ʹ<EFBFBD><CAB9>,<2C><>Ʒ<EFBFBD>ĵ<EFBFBD><C4B5>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵ĵ<CDB5><C4B5><EFBFBD><EFBFBD>DZ<EFBFBD><C7B1><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
|
# 5. <09><>֪ͨ<CDA8><D6AA><EFBFBD>ô<EFBFBD><C3B4>κ<EFBFBD><CEBA><EFBFBD>Դɾ<D4B4><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
|||
|
|
#
|
|||
|
|
# Yuankang Liang(XerolySkinner)
|
|||
|
|
# E-mail:zabbcccbbaz@163.com
|
|||
|
|
# QQ:2715099320
|
|||
|
|
# Mobile Phone:13005636215
|
|||
|
|
#
|
|||
|
|
# All rights reserved.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @file bsp_SD.cpp
|
|||
|
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>SD<EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>
|
|||
|
|
* @mainpage <EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ϣ
|
|||
|
|
* @author Yuankang Liang(XerolySkinner)
|
|||
|
|
* @email zabbcccbbaz@163.com
|
|||
|
|
* @version V1.0.0
|
|||
|
|
* @date 2022-11-22 03:50
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#include "bsp_SD.h"
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
// <09><><EFBFBD><EFBFBD>
|
|||
|
|
//
|
|||
|
|
/**
|
|||
|
|
* @brief Ƭѡ<EFBFBD>ź<EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD>
|
|||
|
|
*/
|
|||
|
|
void bsp_SD::SD_CS(u8 p){
|
|||
|
|
HAL_GPIO_WritePin(GPIOx_CS, GPIO_Pin_CS, p == 0 ? GPIO_PIN_SET: GPIO_PIN_RESET);}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief дSD<EFBFBD><EFBFBD>
|
|||
|
|
* @param cmd <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param arg
|
|||
|
|
* @param crc У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @return
|
|||
|
|
*/
|
|||
|
|
u32 bsp_SD::SD_sendcmd(u8 cmd, u32 arg, u8 crc){
|
|||
|
|
u8 r1;
|
|||
|
|
u8 retry;
|
|||
|
|
SD_CS(0);
|
|||
|
|
__nop();
|
|||
|
|
SD_CS(1);
|
|||
|
|
do retry = spi_readwrite(DFF);while(retry != 0xFF);
|
|||
|
|
spi_readwrite(cmd | 0x40);
|
|||
|
|
spi_readwrite(arg >> 24);
|
|||
|
|
spi_readwrite(arg >> 16);
|
|||
|
|
spi_readwrite(arg >> 8);
|
|||
|
|
spi_readwrite(arg);
|
|||
|
|
spi_readwrite(crc);
|
|||
|
|
if (cmd == CMD12) spi_readwrite(DFF);
|
|||
|
|
do r1 = spi_readwrite(0xFF);while(r1 & 0X80);
|
|||
|
|
return r1;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>SD<EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ:0,ok;<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʧ<EFBFBD><EFBFBD>.
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::SD_init(void){
|
|||
|
|
u8 r1;
|
|||
|
|
u8 buff[6] = {0};
|
|||
|
|
u16 retry;
|
|||
|
|
u8 i;
|
|||
|
|
// MX_SPI3_Init();
|
|||
|
|
SPI_setspeed(SPI_BAUDRATEPRESCALER_256);
|
|||
|
|
SD_CS(0);
|
|||
|
|
for (retry = 0; retry < 10; retry++) spi_readwrite(DFF);
|
|||
|
|
// SD<53><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IDLE״̬
|
|||
|
|
do r1 = SD_sendcmd(CMD0, 0, 0x95);while(r1 != 0x01);
|
|||
|
|
// <09>鿴SD<53><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
SD_TYPE = 0;
|
|||
|
|
r1 = SD_sendcmd(CMD8, 0x1AA, 0x87);
|
|||
|
|
if (r1 == 0x01) {
|
|||
|
|
for (i = 0; i < 4; i++) buff[i] = spi_readwrite(DFF); //Get trailing return value of R7 resp
|
|||
|
|
if (buff[2] == 0X01 && buff[3] == 0XAA) { //<2F><><EFBFBD>Ƿ<EFBFBD>֧<EFBFBD><D6A7>2.7~3.6V
|
|||
|
|
retry = 0XFFFE;
|
|||
|
|
do {
|
|||
|
|
SD_sendcmd(CMD55, 0, 0X01); //<2F><><EFBFBD><EFBFBD>CMD55
|
|||
|
|
r1 = SD_sendcmd(CMD41, 0x40000000, 0X01); //<2F><><EFBFBD><EFBFBD>CMD41
|
|||
|
|
}while(r1 && retry--);
|
|||
|
|
if (retry && SD_sendcmd(CMD58, 0, 0X01) == 0) { //<2F><><EFBFBD><EFBFBD>SD2.0<EFBFBD><EFBFBD><EFBFBD>汾<EFBFBD><EFBFBD>ʼ
|
|||
|
|
for (i = 0; i < 4; i++) buff[i] = spi_readwrite(0XFF); //<2F>õ<EFBFBD>OCRֵ
|
|||
|
|
if (buff[0] &0x40) SD_TYPE = V2HC;
|
|||
|
|
else SD_TYPE = V2;}}
|
|||
|
|
else {
|
|||
|
|
SD_sendcmd(CMD55, 0, 0X01); //<2F><><EFBFBD><EFBFBD>CMD55
|
|||
|
|
r1 = SD_sendcmd(CMD41, 0, 0X01); //<2F><><EFBFBD><EFBFBD>CMD41
|
|||
|
|
if (r1 <= 1) {
|
|||
|
|
SD_TYPE = V1;
|
|||
|
|
retry = 0XFFFE;
|
|||
|
|
do { //<2F>ȴ<EFBFBD><C8B4>˳<EFBFBD>IDLEģʽ
|
|||
|
|
SD_sendcmd(CMD55, 0, 0X01); //<2F><><EFBFBD><EFBFBD>CMD55
|
|||
|
|
r1 = SD_sendcmd(CMD41, 0, 0X01); //<2F><><EFBFBD><EFBFBD>CMD41
|
|||
|
|
}while(r1 && retry--);}
|
|||
|
|
else { //MMC<4D><43><EFBFBD><EFBFBD>֧<EFBFBD><D6A7>CMD55+CMD41ʶ<31><CAB6>
|
|||
|
|
SD_TYPE = MMC; //MMC V3
|
|||
|
|
retry = 0XFFFE;
|
|||
|
|
do r1 = SD_sendcmd(CMD1, 0, 0X01);while(r1 && retry--);} //<2F>ȴ<EFBFBD><C8B4>˳<EFBFBD>IDLEģʽ
|
|||
|
|
if (retry == 0 || SD_sendcmd(CMD16, 512, 0X01) != 0) SD_TYPE = ERR;} //<2F><><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>
|
|||
|
|
}
|
|||
|
|
SD_CS(0);
|
|||
|
|
SPI_setspeed(SPI_BAUDRATEPRESCALER_2);
|
|||
|
|
if (SD_TYPE) return 0;
|
|||
|
|
else return 1;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>ȡSD<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
|||
|
|
* @param *data <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param len <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ:0,ok;<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʧ<EFBFBD><EFBFBD>.
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::SD_ReceiveData(u8 * data, u16 len){
|
|||
|
|
u8 r1;
|
|||
|
|
SD_CS(1);
|
|||
|
|
do {
|
|||
|
|
r1 = spi_readwrite(0xFF);
|
|||
|
|
__nop();
|
|||
|
|
}while(r1 != 0xFE);
|
|||
|
|
while (len--) {
|
|||
|
|
*data = spi_readwrite(0xFF);
|
|||
|
|
data++;}
|
|||
|
|
spi_readwrite(0xFF);
|
|||
|
|
spi_readwrite(0xFF);
|
|||
|
|
return 0;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>SD<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param *buf <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param cmd <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ:0,ok;<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʧ<EFBFBD><EFBFBD>.
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::SD_SendBlock(u8 * buf, u8 cmd){
|
|||
|
|
u16 t;
|
|||
|
|
u8 r1;
|
|||
|
|
do r1 = spi_readwrite(0xFF);while(r1 != 0xFF);
|
|||
|
|
spi_readwrite(cmd);
|
|||
|
|
if (cmd != 0XFD) { //<2F><><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD>ָ<EFBFBD><D6B8>
|
|||
|
|
for (t = 0; t < 512; t++) spi_readwrite(buf[t]); //<2F><><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>,<2C><><EFBFBD>ٺ<EFBFBD><D9BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
spi_readwrite(0xFF); //<2F><><EFBFBD><EFBFBD>crc
|
|||
|
|
spi_readwrite(0xFF);
|
|||
|
|
t = spi_readwrite(0xFF); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ
|
|||
|
|
if ((t & 0x1F) != 0x05) return 2;} //<2F><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
|
|||
|
|
return 0;} //д<><D0B4><EFBFBD>ɹ<EFBFBD>
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>ȡCID<EFBFBD><EFBFBD>Ϣ
|
|||
|
|
* @return CID<EFBFBD><EFBFBD>Ϣ
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::SD_GETCID(u8 * cid_data){
|
|||
|
|
u8 r1;
|
|||
|
|
r1 = SD_sendcmd(CMD10, 0, 0x01); //<2F><>ȡCID<49>Ĵ<EFBFBD><C4B4><EFBFBD>
|
|||
|
|
if (r1 == 0x00) r1 = SD_ReceiveData(cid_data, 16);
|
|||
|
|
SD_CS(0);
|
|||
|
|
if (r1) return 1;
|
|||
|
|
else return 0;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>ȡCSD<EFBFBD><EFBFBD>Ϣ
|
|||
|
|
* @return CSD<EFBFBD><EFBFBD>Ϣ
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::SD_GETCSD(u8 * csd_data){
|
|||
|
|
u8 r1;
|
|||
|
|
r1 = SD_sendcmd(CMD9, 0, 0x01); //<2F><>CMD9<44><39><EFBFBD><EFBFBD><EEA3AC>CSD<53>Ĵ<EFBFBD><C4B4><EFBFBD>
|
|||
|
|
if (r1 == 0) r1 = SD_ReceiveData(csd_data, 16); //<2F><><EFBFBD><EFBFBD>16<31><36><EFBFBD>ֽڵ<D6BD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
SD_CS(0); //ȡ<><C8A1>Ƭѡ
|
|||
|
|
if (r1) return 1;
|
|||
|
|
else return 0;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>ȡSD<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
*/
|
|||
|
|
u32 bsp_SD::SD_GetSectorCount(void){
|
|||
|
|
u8 csd[16];
|
|||
|
|
u32 Capacity;
|
|||
|
|
u8 n;
|
|||
|
|
u16 csize;
|
|||
|
|
//ȡCSD<53><44>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><DABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
|
|||
|
|
if (SD_GETCSD(csd) != 0) return 0;
|
|||
|
|
//<2F><><EFBFBD><EFBFBD>ΪSDHC<48><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>淽ʽ<E6B7BD><CABD><EFBFBD><EFBFBD>
|
|||
|
|
if ((csd[0] &0xC0) == 0x40) { //V2.00<EFBFBD>Ŀ<EFBFBD>
|
|||
|
|
csize = csd[9] + ((u16) csd[8] << 8) + 1;
|
|||
|
|
Capacity = (u32)
|
|||
|
|
csize << 10;} //<2F>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
else { //V1.XX<58>Ŀ<EFBFBD>
|
|||
|
|
n = (csd[5] &15) + ((csd[10] &128) >> 7) + ((csd[9] &3) << 1) + 2;
|
|||
|
|
csize = (csd[8] >> 6) + ((u16) csd[7] << 2) + ((u16) (csd[6] &3) << 10) + 1;
|
|||
|
|
Capacity = (u32)
|
|||
|
|
csize << (n - 9);} //<2F>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
return Capacity;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
int bsp_SD::MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo){
|
|||
|
|
u8 r1;
|
|||
|
|
u8 CSD_Tab[16];
|
|||
|
|
u8 CID_Tab[16];
|
|||
|
|
/* Send CMD9, Read CSD */
|
|||
|
|
r1 = SD_sendcmd(CMD9, 0, 0xFF);
|
|||
|
|
if (r1 != 0x00) return r1;
|
|||
|
|
if (SD_ReceiveData(CSD_Tab, 16)) return 1;
|
|||
|
|
/* Send CMD10, Read CID */
|
|||
|
|
r1 = SD_sendcmd(CMD10, 0, 0xFF);
|
|||
|
|
if (r1 != 0x00) return r1;
|
|||
|
|
if (SD_ReceiveData(CID_Tab, 16)) return 2;
|
|||
|
|
/* Byte 0 */
|
|||
|
|
SD0_CardInfo->CSD.CSDStruct = (CSD_Tab[0] &0xC0) >> 6;
|
|||
|
|
SD0_CardInfo->CSD.SysSpecVersion = (CSD_Tab[0] &0x3C) >> 2;
|
|||
|
|
SD0_CardInfo->CSD.Reserved1 = CSD_Tab[0] &0x03;
|
|||
|
|
/* Byte 1 */
|
|||
|
|
SD0_CardInfo->CSD.TAAC = CSD_Tab[1];
|
|||
|
|
/* Byte 2 */
|
|||
|
|
SD0_CardInfo->CSD.NSAC = CSD_Tab[2];
|
|||
|
|
/* Byte 3 */
|
|||
|
|
SD0_CardInfo->CSD.MaxBusClkFrec = CSD_Tab[3];
|
|||
|
|
/* Byte 4 */
|
|||
|
|
SD0_CardInfo->CSD.CardComdClasses = CSD_Tab[4] << 4;
|
|||
|
|
/* Byte 5 */
|
|||
|
|
SD0_CardInfo->CSD.CardComdClasses |= (CSD_Tab[5] &0xF0) >> 4;
|
|||
|
|
SD0_CardInfo->CSD.RdBlockLen = CSD_Tab[5] &0x0F;
|
|||
|
|
/* Byte 6 */
|
|||
|
|
SD0_CardInfo->CSD.PartBlockRead = (CSD_Tab[6] &0x80) >> 7;
|
|||
|
|
SD0_CardInfo->CSD.WrBlockMisalign = (CSD_Tab[6] &0x40) >> 6;
|
|||
|
|
SD0_CardInfo->CSD.RdBlockMisalign = (CSD_Tab[6] &0x20) >> 5;
|
|||
|
|
SD0_CardInfo->CSD.DSRImpl = (CSD_Tab[6] &0x10) >> 4;
|
|||
|
|
SD0_CardInfo->CSD.Reserved2 = 0; /* Reserved */
|
|||
|
|
SD0_CardInfo->CSD.DeviceSize = (CSD_Tab[6] &0x03) << 10;
|
|||
|
|
/* Byte 7 */
|
|||
|
|
SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[7]) << 2;
|
|||
|
|
/* Byte 8 */
|
|||
|
|
SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[8] &0xC0) >> 6;
|
|||
|
|
SD0_CardInfo->CSD.MaxRdCurrentVDDMin = (CSD_Tab[8] &0x38) >> 3;
|
|||
|
|
SD0_CardInfo->CSD.MaxRdCurrentVDDMax = (CSD_Tab[8] &0x07);
|
|||
|
|
/* Byte 9 */
|
|||
|
|
SD0_CardInfo->CSD.MaxWrCurrentVDDMin = (CSD_Tab[9] &0xE0) >> 5;
|
|||
|
|
SD0_CardInfo->CSD.MaxWrCurrentVDDMax = (CSD_Tab[9] &0x1C) >> 2;
|
|||
|
|
SD0_CardInfo->CSD.DeviceSizeMul = (CSD_Tab[9] &0x03) << 1;
|
|||
|
|
/* Byte 10 */
|
|||
|
|
SD0_CardInfo->CSD.DeviceSizeMul |= (CSD_Tab[10] &0x80) >> 7;
|
|||
|
|
SD0_CardInfo->CSD.EraseGrSize = (CSD_Tab[10] &0x7C) >> 2;
|
|||
|
|
SD0_CardInfo->CSD.EraseGrMul = (CSD_Tab[10] &0x03) << 3;
|
|||
|
|
/* Byte 11 */
|
|||
|
|
SD0_CardInfo->CSD.EraseGrMul |= (CSD_Tab[11] &0xE0) >> 5;
|
|||
|
|
SD0_CardInfo->CSD.WrProtectGrSize = (CSD_Tab[11] &0x1F);
|
|||
|
|
/* Byte 12 */
|
|||
|
|
SD0_CardInfo->CSD.WrProtectGrEnable = (CSD_Tab[12] &0x80) >> 7;
|
|||
|
|
SD0_CardInfo->CSD.ManDeflECC = (CSD_Tab[12] &0x60) >> 5;
|
|||
|
|
SD0_CardInfo->CSD.WrSpeedFact = (CSD_Tab[12] &0x1C) >> 2;
|
|||
|
|
SD0_CardInfo->CSD.MaxWrBlockLen = (CSD_Tab[12] &0x03) << 2;
|
|||
|
|
/* Byte 13 */
|
|||
|
|
SD0_CardInfo->CSD.MaxWrBlockLen |= (CSD_Tab[13] &0xc0) >> 6;
|
|||
|
|
SD0_CardInfo->CSD.WriteBlockPaPartial = (CSD_Tab[13] &0x20) >> 5;
|
|||
|
|
SD0_CardInfo->CSD.Reserved3 = 0;
|
|||
|
|
SD0_CardInfo->CSD.ContentProtectAppli = (CSD_Tab[13] &0x01);
|
|||
|
|
/* Byte 14 */
|
|||
|
|
SD0_CardInfo->CSD.FileFormatGrouop = (CSD_Tab[14] &0x80) >> 7;
|
|||
|
|
SD0_CardInfo->CSD.CopyFlag = (CSD_Tab[14] &0x40) >> 6;
|
|||
|
|
SD0_CardInfo->CSD.PermWrProtect = (CSD_Tab[14] &0x20) >> 5;
|
|||
|
|
SD0_CardInfo->CSD.TempWrProtect = (CSD_Tab[14] &0x10) >> 4;
|
|||
|
|
SD0_CardInfo->CSD.FileFormat = (CSD_Tab[14] &0x0C) >> 2;
|
|||
|
|
SD0_CardInfo->CSD.ECC = (CSD_Tab[14] &0x03);
|
|||
|
|
/* Byte 15 */
|
|||
|
|
SD0_CardInfo->CSD.CSD_CRC = (CSD_Tab[15] &0xFE) >> 1;
|
|||
|
|
SD0_CardInfo->CSD.Reserved4 = 1;
|
|||
|
|
if (SD0_CardInfo->CardType == V2HC) {
|
|||
|
|
/* Byte 7 */
|
|||
|
|
SD0_CardInfo->CSD.DeviceSize = (u16) (CSD_Tab[8]) * 256;
|
|||
|
|
/* Byte 8 */
|
|||
|
|
SD0_CardInfo->CSD.DeviceSize += CSD_Tab[9];}
|
|||
|
|
SD0_CardInfo->Capacity = SD0_CardInfo->CSD.DeviceSize * MSD_BLOCKSIZE * 1024;
|
|||
|
|
SD0_CardInfo->BlockSize = MSD_BLOCKSIZE;
|
|||
|
|
/* Byte 0 */
|
|||
|
|
SD0_CardInfo->CID.ManufacturerID = CID_Tab[0];
|
|||
|
|
/* Byte 1 */
|
|||
|
|
SD0_CardInfo->CID.OEM_AppliID = CID_Tab[1] << 8;
|
|||
|
|
/* Byte 2 */
|
|||
|
|
SD0_CardInfo->CID.OEM_AppliID |= CID_Tab[2];
|
|||
|
|
/* Byte 3 */
|
|||
|
|
SD0_CardInfo->CID.ProdName1 = CID_Tab[3] << 24;
|
|||
|
|
/* Byte 4 */
|
|||
|
|
SD0_CardInfo->CID.ProdName1 |= CID_Tab[4] << 16;
|
|||
|
|
/* Byte 5 */
|
|||
|
|
SD0_CardInfo->CID.ProdName1 |= CID_Tab[5] << 8;
|
|||
|
|
/* Byte 6 */
|
|||
|
|
SD0_CardInfo->CID.ProdName1 |= CID_Tab[6];
|
|||
|
|
/* Byte 7 */
|
|||
|
|
SD0_CardInfo->CID.ProdName2 = CID_Tab[7];
|
|||
|
|
/* Byte 8 */
|
|||
|
|
SD0_CardInfo->CID.ProdRev = CID_Tab[8];
|
|||
|
|
/* Byte 9 */
|
|||
|
|
SD0_CardInfo->CID.ProdSN = CID_Tab[9] << 24;
|
|||
|
|
/* Byte 10 */
|
|||
|
|
SD0_CardInfo->CID.ProdSN |= CID_Tab[10] << 16;
|
|||
|
|
/* Byte 11 */
|
|||
|
|
SD0_CardInfo->CID.ProdSN |= CID_Tab[11] << 8;
|
|||
|
|
/* Byte 12 */
|
|||
|
|
SD0_CardInfo->CID.ProdSN |= CID_Tab[12];
|
|||
|
|
/* Byte 13 */
|
|||
|
|
SD0_CardInfo->CID.Reserved1 |= (CID_Tab[13] &0xF0) >> 4;
|
|||
|
|
/* Byte 14 */
|
|||
|
|
SD0_CardInfo->CID.ManufactDate = (CID_Tab[13] &0x0F) << 8;
|
|||
|
|
/* Byte 15 */
|
|||
|
|
SD0_CardInfo->CID.ManufactDate |= CID_Tab[14];
|
|||
|
|
/* Byte 16 */
|
|||
|
|
SD0_CardInfo->CID.CID_CRC = (CID_Tab[15] &0xFE) >> 1;
|
|||
|
|
SD0_CardInfo->CID.Reserved2 = 1;
|
|||
|
|
return 0;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief дSD<EFBFBD><EFBFBD>
|
|||
|
|
* @param *buf <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param sector <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param cnt <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ:0,ok;<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʧ<EFBFBD><EFBFBD>.
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::SD_WriteDisk(u8 * buf, u32 sector, u8 cnt){
|
|||
|
|
u8 r1;
|
|||
|
|
if (SD_TYPE != V2HC) sector *= 512; //ת<><D7AA>Ϊ<EFBFBD>ֽڵ<D6BD>ַ
|
|||
|
|
if (cnt == 1){
|
|||
|
|
r1 = SD_sendcmd(CMD24, sector, 0X01); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
if (r1 == 0) //ָ<><EFBFBD>ͳɹ<CDB3>
|
|||
|
|
r1 = SD_SendBlock(buf, 0xFE);} //д512<31><32><EFBFBD>ֽ<EFBFBD>
|
|||
|
|
else {
|
|||
|
|
if (SD_TYPE != MMC) {
|
|||
|
|
SD_sendcmd(CMD55, 0, 0X01);
|
|||
|
|
SD_sendcmd(CMD23, cnt, 0X01);} //<2F><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
|||
|
|
r1 = SD_sendcmd(CMD25, sector, 0X01); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
if (r1 == 0) {
|
|||
|
|
do {
|
|||
|
|
r1 = SD_SendBlock(buf, 0xFC); //<2F><><EFBFBD><EFBFBD>512<31><32><EFBFBD>ֽ<EFBFBD>
|
|||
|
|
buf += 512;}while(--cnt && r1 == 0);
|
|||
|
|
r1 = SD_SendBlock(0, 0xFD);}} //<2F><><EFBFBD><EFBFBD>512<31><32><EFBFBD>ֽ<EFBFBD>
|
|||
|
|
SD_CS(0); //ȡ<><C8A1>Ƭѡ
|
|||
|
|
return r1;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>SD<EFBFBD><EFBFBD>
|
|||
|
|
* @param *buf <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param sector <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param cnt <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ:0,ok;<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʧ<EFBFBD><EFBFBD>.
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::SD_ReadDisk(u8 * buf, u32 sector, u8 cnt){
|
|||
|
|
u8 r1;
|
|||
|
|
if (SD_TYPE != V2HC) sector <<= 9; //ת<><D7AA>Ϊ<EFBFBD>ֽڵ<D6BD>ַ
|
|||
|
|
if (cnt == 1) {
|
|||
|
|
r1 = SD_sendcmd(CMD17, sector, 0X01); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
if (r1 == 0) //ָ<><EFBFBD>ͳɹ<CDB3>
|
|||
|
|
r1 = SD_ReceiveData(buf, 512);} //<2F><><EFBFBD><EFBFBD>512<31><32><EFBFBD>ֽ<EFBFBD>
|
|||
|
|
else {
|
|||
|
|
r1 = SD_sendcmd(CMD18, sector, 0X01); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
do {
|
|||
|
|
r1 = SD_ReceiveData(buf, 512); //<2F><><EFBFBD><EFBFBD>512<31><32><EFBFBD>ֽ<EFBFBD>
|
|||
|
|
buf += 512;}
|
|||
|
|
while(--cnt && r1 == 0);
|
|||
|
|
SD_sendcmd(CMD12, 0, 0X01);} //<2F><><EFBFBD><EFBFBD>ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD>
|
|||
|
|
SD_CS(0); //ȡ<><C8A1>Ƭѡ
|
|||
|
|
return r1;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
u8 bsp_SD::spi_readwrite(u8 Txdata){
|
|||
|
|
u8 Rxdata;
|
|||
|
|
HAL_SPI_TransmitReceive(hspi, &Txdata, &Rxdata, 1, 0xFF);
|
|||
|
|
return Rxdata;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>SPI<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param speed <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD>
|
|||
|
|
*/
|
|||
|
|
void bsp_SD::SPI_setspeed(u8 speed){
|
|||
|
|
hspi->Init.BaudRatePrescaler = speed;}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param offset д<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>
|
|||
|
|
* @param *dat <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param datlen д<EFBFBD>볤<EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ:0,ok;<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʧ<EFBFBD><EFBFBD>.
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::offsetWrite(u64 offset,u8* dat,u64 datlen) {
|
|||
|
|
u8 sectorBuff[512] = { 0 };
|
|||
|
|
u64 sectorBuffptr = 0;
|
|||
|
|
|
|||
|
|
u64 sectorSour = offset / 512; // <09><>ʼ<EFBFBD><CABC>
|
|||
|
|
u64 sectorSourlen = offset % 512; // <09><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>λ
|
|||
|
|
|
|||
|
|
// <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
SD_ReadDisk(sectorBuff,sectorSour,1);
|
|||
|
|
sectorBuffptr = sectorSourlen;
|
|||
|
|
for (u64 i = 0; i < datlen; i++) {
|
|||
|
|
// д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
sectorBuff[sectorBuffptr] = dat[i];
|
|||
|
|
sectorBuffptr++;
|
|||
|
|
// <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д
|
|||
|
|
if (sectorBuffptr == 512 || i == datlen - 1) {
|
|||
|
|
SD_WriteDisk(sectorBuff,sectorSour,1);
|
|||
|
|
sectorBuffptr = 0;
|
|||
|
|
sectorSour++;
|
|||
|
|
if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}}
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
/**
|
|||
|
|
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param offset <EFBFBD><EFBFBD>ȡλ<EFBFBD><EFBFBD>
|
|||
|
|
* @param *dat <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @param datlen <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ:0,ok;<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ʧ<EFBFBD><EFBFBD>.
|
|||
|
|
*/
|
|||
|
|
u8 bsp_SD::offsetRead(u64 offset,u8* dat,u64 datlen) {
|
|||
|
|
u8 sectorBuff[512] = { 0 };
|
|||
|
|
u64 sectorBuffptr = 0;
|
|||
|
|
|
|||
|
|
u64 sectorSour = offset / 512; // <09><>ʼ<EFBFBD><CABC>
|
|||
|
|
u64 sectorSourlen = offset % 512; // <09><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>λ
|
|||
|
|
|
|||
|
|
// <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
SD_ReadDisk(sectorBuff,sectorSour,1);
|
|||
|
|
sectorBuffptr = sectorSourlen;
|
|||
|
|
for (u64 i = 0; i < datlen; i++) {
|
|||
|
|
// д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
dat[i]=sectorBuff[sectorBuffptr];
|
|||
|
|
sectorBuffptr++;
|
|||
|
|
// <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д
|
|||
|
|
if (sectorBuffptr == 512 || i == datlen - 1) {
|
|||
|
|
sectorBuffptr = 0;
|
|||
|
|
sectorSour++;
|
|||
|
|
if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}}
|
|||
|
|
return 0;}
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
//----------------------------------------------------------------------------------------------------
|
|||
|
|
// <09><><EFBFBD>캯<EFBFBD><ECBAAF>
|
|||
|
|
//
|
|||
|
|
bsp_SD::bsp_SD(
|
|||
|
|
SPI_HandleTypeDef *hspi,
|
|||
|
|
GPIO_TypeDef *GPIOx_CS,
|
|||
|
|
uint16_t GPIO_Pin_CS){
|
|||
|
|
bsp_SD::hspi=hspi;
|
|||
|
|
bsp_SD::GPIOx_CS=GPIOx_CS;
|
|||
|
|
bsp_SD::GPIO_Pin_CS=GPIO_Pin_CS;
|
|||
|
|
bsp_SD::DFF=0xFF;
|
|||
|
|
bsp_SD::SD_TYPE=0x00;}
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|