20240909-DXSPX-emb/Src/Usr/Driver/DrvSdSpi.c

358 lines
9.8 KiB
C
Raw Permalink Normal View History

#include "DrvSdSpi.h"
#include "BSPSpi.h"
#include <string.h>
static uint8_t sd_type = 0; // SD卡的类型
static unsigned char gSDCsd[16] = {0};
// SD片选
static uint8_t Drv_SdSelect(void);
static void Drv_SdDisselect(void);
void Drv_SdSpiCs(uint8_t value);
uint8_t Drv_SdSpiRWByte(uint8_t data);
void Drv_SdSpiSetSpeed(uint8_t mode);
// 数据指令收发函数
static uint8_t Drv_SdSendCmd(uint8_t cmd, uint32_t arg, uint8_t crc);
static unsigned char Drv_SDGetResponse(unsigned char response);
static unsigned char Drv_SDRecvData(unsigned char *buf, unsigned short len);
static unsigned char Drv_SDSendBlock(unsigned char *buf, unsigned char cmd);
static unsigned char Drv_SDGetCsd(unsigned char *csd_data);
// sd等待卡片准备好
uint8_t Drv_SdWaitReady(void);
// SD卡初始化
uint8_t Drv_SdInit(void);
// 读取和写入SD卡
unsigned char Drv_SdReadDisk(unsigned char *buf, unsigned int sector, unsigned char cnt);
unsigned char Drv_SdWriteDisk(unsigned char *buf, unsigned int sector, unsigned char cnt);
// 获取SD卡总扇区数
unsigned int Drv_SdGetSectorCount(void);
// 向SD卡发送指令
static uint8_t Drv_SdSendCmd(uint8_t cmd, uint32_t arg, uint8_t crc)
{
uint8_t response;
uint8_t retry_limit = 0x1f;
Drv_SdDisselect();
if (Drv_SdSelect() != 0) {
return 0xff;
}
Drv_SdSpiRWByte(cmd | 0x40);
for (int shift = 24; shift >= 0; shift -= 8) {
Drv_SdSpiRWByte((uint8_t)((arg >> shift) & 0xff));
}
Drv_SdSpiRWByte(crc);
if (cmd == CMD12) {
Drv_SdSpiRWByte(0xff);
}
do {
response = Drv_SdSpiRWByte(0xff);
} while ((response & 0x80) && retry_limit--);
return response;
}
// sd等待卡片准备好
uint8_t Drv_SdWaitReady(void)
{
uint8_t rec;
uint32_t retry_time = 0;
do {
rec = Drv_SdSpiRWByte(0xff);
if (0xff == rec) {
return 0;
}
retry_time++;
if (retry_time % 0xffffff == 0) {
/* 长时间没有成功,进行重新初始化 */
Bsp_SpiInit(BSP_SPI3);
Drv_SdSpiCs(1);
}
} while (retry_time < 0xfffffff);
return 1;
}
// SD片选
static uint8_t Drv_SdSelect(void)
{
Drv_SdSpiCs(0);
if (Drv_SdWaitReady() == 0) {
return 0;
}
Drv_SdDisselect();
return 1;
}
// SD取消片选
static void Drv_SdDisselect(void)
{
Drv_SdSpiCs(1);
Drv_SdSpiRWByte(0xff);
}
void Drv_SdSpiCs(unsigned char value)
{
Bsp_SpiCS(BSP_SPI3, value);
}
// 设置SD通信速度
void Drv_SdSpiSetSpeed(uint8_t mode)
{
uint32_t speed;
if (mode == USR_DRV_SD_LOW_SPEED_MODE) {
speed = USR_DRV_SD_LOW_SPEED;
} else if (mode == USR_DRV_SD_HIGH_SPEED_MODE) {
speed = USR_DRV_SD_HIGH_SPEED;
}
Bsp_SpiSetSpeed(BSP_SPI3, speed);
}
// 设置SD读写函数
uint8_t Drv_SdSpiRWByte(uint8_t data)
{
return Bsp_RWByte(BSP_SPI3, data);
}
// 从SD卡读取一个数据包的内容
static unsigned char Drv_SDRecvData(unsigned char *buf, unsigned short len)
{
if (Drv_SDGetResponse(0xfe)) {
return 1;
}
while (len--) {
*buf = Drv_SdSpiRWByte(0xff);
buf++;
}
Drv_SdSpiRWByte(0xff);
Drv_SdSpiRWByte(0xff);
return 0;
}
// 向SD卡写入一个数据包的内容512字节
static unsigned char Drv_SDSendBlock(unsigned char *buf, unsigned char cmd)
{
unsigned char rt;
unsigned short i;
rt = Drv_SdWaitReady();
if (0 != rt) {
return 1;
}
Drv_SdSpiRWByte(cmd);
if (cmd != 0xfd) {
for (i = 0; i < 512; i++) {
Drv_SdSpiRWByte(buf[i]);
}
Drv_SdSpiRWByte(0xff);
Drv_SdSpiRWByte(0xff);
rt = Drv_SdSpiRWByte(0xff);
if ((rt & 0x1F) != 0x05) {
return 2;
}
}
return 0;
}
// 等待SD回应
static unsigned char Drv_SDGetResponse(unsigned char response)
{
unsigned short count = 0xffff;
while ((Drv_SdSpiRWByte(0xff) != response) && count) {
count--;
}
if (count == 0) {
return MSD_RESPONSE_FAILURE;
} else {
return 0;
}
}
// 获取SD卡的CSD信息包括容量和速度信息
static unsigned char Drv_SDGetCsd(unsigned char *csd_data)
{
unsigned char rt;
rt = Drv_SdSendCmd(CMD9, 0, 0x01);
if (rt == 0x00) {
rt = Drv_SDRecvData(csd_data, 16);
}
Drv_SdDisselect();
if (rt != 0x00) {
return 1;
}
return 0;
}
// 获取SD卡总扇区数
unsigned int Drv_SdGetSectorCount(void)
{
unsigned int capacity; // 记录扇区数量
unsigned char n;
unsigned short csize;
memset(gSDCsd, 0, sizeof(gSDCsd));
/* 获取CSD信息 */
if (Drv_SDGetCsd(gSDCsd) != 0x00) {
return 0;
}
if ((gSDCsd[0] & 0xc0) == 0x40) {
csize = gSDCsd[9] + ((unsigned short)gSDCsd[8] << 8) + 1;
capacity = (unsigned int)csize << 10;
} else {
n = (gSDCsd[5] & 15) + ((gSDCsd[10] & 128) >> 7) + ((gSDCsd[9] & 3) << 1) + 2;
csize = (gSDCsd[8] >> 6) + ((unsigned short)gSDCsd[7] << 2) + ((unsigned short)(gSDCsd[6] & 3) << 10) + 1;
capacity = (unsigned int)csize << (n - 9);
}
return capacity;
}
// SD卡初始化
uint8_t Drv_SdInit(void)
{
unsigned char RxData; // 返回值
unsigned short RetryTime; // 用来进行超时计数
unsigned char buf[4];
unsigned short i;
Bsp_SpiInit(BSP_SPI3);
Drv_SdSpiCs(0);
Drv_SdSpiSetSpeed(USR_DRV_SD_LOW_SPEED_MODE); // 初始化的时候要是低速模式
for(i = 0; i < 100; i++) {
RxData = Drv_SdSpiRWByte(0xff); // 发送最少74个脉冲保守起见多发送一点
}
/* 格式化命令 */
Drv_SdSpiRWByte(CMD0 | 0x40);
Drv_SdSpiRWByte((unsigned char)((0 >> 24) & 0xff));
Drv_SdSpiRWByte((unsigned char)((0 >> 16) & 0xff));
Drv_SdSpiRWByte((unsigned char)((0 >> 8) & 0xff));
Drv_SdSpiRWByte((unsigned char)(0 & 0xff));
Drv_SdSpiRWByte(0x95);
RetryTime = 20;
do {
RxData = Drv_SdSendCmd(CMD0, 0, 0x95);//
} while((RxData != 0x01) && RetryTime--);
sd_type = 0; // 设置默认没有卡
if(RxData == 0x01) {
if(Drv_SdSendCmd(CMD8, 0x1AA, 0x87) == 1) // SD 协议版本V2.0
{
for(i = 0; i < 4; i++) {
buf[i] = Drv_SdSpiRWByte(0xff);
}
if(buf[2] == 0x01 && buf[3] == 0xaa) // 判断卡是否支持2.7V~3.6V
{
RetryTime = 0xfffe;
do {
Drv_SdSendCmd(CMD55, 0, 0x01);
RxData = Drv_SdSendCmd(ACMD41, 0x40000000, 0x01);
} while(RxData && RetryTime--);
if(RetryTime && (Drv_SdSendCmd(CMD58, 0, 0x01)) == 0) // 鉴别SD2.0卡版本
{
for(i = 0; i < 4; i++) {
buf[i] = Drv_SdSpiRWByte(0xff); // 得到OCR值
}
// 检查CSS
if (buf[0] & 0x40) {
sd_type = SD_TYPE_V2HC;
}
else {
sd_type = SD_TYPE_V2;
}
}
}
} else { // SD V1.x/ MMC V3
Drv_SdSendCmd(CMD55, 0, 0X01);
RxData = Drv_SdSendCmd(ACMD41, 0, 0X01);
if(RxData <= 1) {
sd_type = SD_TYPE_V1;
RetryTime = 0xfffe;
do { // 等待退出IDLE模式
Drv_SdSendCmd(CMD55, 0, 0X01);
RxData = Drv_SdSendCmd(ACMD41, 0, 0X01);
} while(RxData && RetryTime--);
} else { // MMC卡不支持CMD55余CMD41识别
sd_type = SD_TYPE_MMC; // MMC V3
RetryTime = 0xfffe;
do { // 等待退出IDLE模式
RxData = Drv_SdSendCmd(CMD1, 0, 0X01);
} while(RxData && RetryTime--);
}
if((RetryTime == 0) || (Drv_SdSendCmd(CMD16, 512, 0X01) != 0)) {
sd_type = SD_TYPE_ERR; // 错误的卡,未能识别
}
}
}
Drv_SdDisselect();
Drv_SdSpiSetSpeed(USR_DRV_SD_HIGH_SPEED_MODE);
if(sd_type != 0) {
return 0;
} else if(RxData != 0) {
return RxData;
}
return 0xaa; // 其他错误
}
// 读取SD卡
unsigned char Drv_SdReadDisk(unsigned char *buf, unsigned int sector, unsigned char cnt)
{
unsigned char rt;
if(sd_type != SD_TYPE_V2HC) {
sector <<= 9; // 转换为字节地址
}
if(cnt == 1) {
rt = Drv_SdSendCmd(CMD17, sector, 0x01); // 读命令
if (rt == 0) // 指令发送成功
{
rt = Drv_SDRecvData(buf, 512); // 接收512个字节
}
} else {
rt = Drv_SdSendCmd(CMD18, sector, 0X01); // 连续读命令
do
{
rt = Drv_SDRecvData(buf, 512); // 接收512个字节
buf += 512;
} while(--cnt && rt == 0);
Drv_SdSendCmd(CMD12, 0, 0X01); // 发送停止命令
}
Drv_SdDisselect(); // 取消片选
return rt;
}
// 写入SD卡
unsigned char Drv_SdWriteDisk(unsigned char *buf, unsigned int sector, unsigned char cnt)
{
unsigned char rt;
if(sd_type != SD_TYPE_V2HC) {
sector *= 512; // 转换为字节地址
}
if (cnt == 1) {
rt = Drv_SdSendCmd(CMD24, sector, 0x01);
if(rt == 0) {
rt = Drv_SDSendBlock(buf, 0xfe);
}
} else {
if(sd_type != SD_TYPE_MMC) {
Drv_SdSendCmd(CMD55, 0, 0X01);
Drv_SdSendCmd(CMD23, cnt, 0X01);
}
rt = Drv_SdSendCmd(CMD25, sector, 0X01); // 连续读取
if(rt == 0) {
do {
rt = Drv_SDSendBlock(buf, 0xfc); // 接收512个字节
buf += 512;
} while(--cnt && rt == 0);
rt = Drv_SDSendBlock(0, 0xfd); // 接收512个字节
}
}
Drv_SdDisselect();
return rt;
}