📄 sddriver.c
字号:
#include <stdio.h>
#include <sys/unistd.h>
#include <io.h>
#include <string.h>
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "sdconfig.h"
#include "sdhal.h"
#include "SDCmd.h"
#include "sddriver.h"
// SD卡信息结构体变量
sd_struct sds;
// 超时时间单位表(单位:0.000000001ns)
const INT32U time_unit[8] = {1000000000,100000000,10000000,
1000000,100000,10000,1000,100};
// 超时时间表
const INT8U time_value[16] = {0,10,12,13,15,20,25,30,
35,40,45,50,55,60,70,80};
// 超时时间因数表
const INT8U r2w_fator[6] = {1,2,4,8,16,32};
//初始化SD卡
INT8U SD_Initialize(void)
{
INT8U recbuf[4],ret;
SD_HardWareInit();
if (SD_ChkCard() != 1)
return SD_ERR_NO_CARD;
SPI_CS_Assert();
SD_SPIDelay(25);
SPI_CS_Deassert();
SD_SPIDelay(2);
ret = SD_ResetSD();
if (ret != SD_NO_ERR)
return ret;
ret = SD_ActiveInit();
if (ret != SD_NO_ERR)
return ret;
ret = SD_ReadOCR(4, recbuf);
if (ret != SD_NO_ERR)
return ret;
if ((recbuf[1] & MSK_OCR_33) != MSK_OCR_33)
return SD_ERR_VOL_NOTSUSP;
SPI_ClkToMax();
#if SD_CRC_EN
ret = SD_EnableCRC(1);
if (ret != SD_NO_ERR)
return ret;
#endif
ret = SD_SetBlockLen(SD_BLOCKSIZE);
if (ret != SD_NO_ERR)
return ret;
return (SD_GetCardInfo());
}
//从SD卡中读一个块
INT8U SD_ReadBlock(INT32U blockaddr, INT8U *recbuf)
{
INT8U ret;
if (blockaddr > sds.block_num)
return SD_ERR_OVER_CARDRANGE;
ret = SD_ReadSingleBlock(blockaddr);
if (ret != SD_NO_ERR)
return ret;
return (SD_ReadBlockData(SD_BLOCKSIZE, recbuf));
}
//从SD卡中读多个块
#if SD_ReadMultiBlock_EN
INT8U SD_ReadMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *recbuf)
{
INT32U i;
INT8U ret;
if ((blockaddr + blocknum) > sds.block_num)
return SD_ERR_OVER_CARDRANGE;
ret = SD_ReadMultipleBlock(blockaddr);
if (ret != SD_NO_ERR)
return ret;
for (i = 0; i < blocknum; i++)
{
ret = SD_ReadBlockData(SD_BLOCKSIZE, recbuf);
if (ret == SD_NO_ERR)
recbuf = recbuf + SD_BLOCKSIZE;
else
return ret;
}
return (SD_StopTransmission());
}
#endif
//向SD卡中写入一个块
INT8U SD_WriteBlock(INT32U blockaddr, INT8U *sendbuf)
{
INT8U ret,tmp[2];
if (blockaddr > sds.block_num)
return SD_ERR_OVER_CARDRANGE;
if (SD_ChkCardWP() == 1)
return SD_ERR_WRITE_PROTECT;
ret = SD_WriteSingleBlock(blockaddr);
if (ret != SD_NO_ERR)
return ret;
ret = SD_WriteBlockData(0, SD_BLOCKSIZE, sendbuf);
if (ret == SD_NO_ERR)
{
ret = SD_ReadCard_Status(2,tmp);
if (ret != SD_NO_ERR)
return ret;
if((tmp[0] != 0) || (tmp[1] != 0))
ret = SD_ERR_WRITE_BLK;
}
return ret;
}
//向SD卡中写入多个块
#if SD_WriteMultiBlock_EN
INT8U SD_WriteMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *sendbuf)
{
INT32U i;
INT8U ret;
if ((blockaddr + blocknum) > sds.block_num)
return SD_ERR_OVER_CARDRANGE;
if (SD_ChkCardWP() == 1)
return SD_ERR_WRITE_PROTECT;
ret = SD_WriteMultipleBlock(blockaddr);
if (ret != SD_NO_ERR)
return ret;
for (i = 0; i < blocknum; i++)
{
ret = SD_WriteBlockData(1, SD_BLOCKSIZE, sendbuf);
if (ret == SD_NO_ERR)
sendbuf = sendbuf + SD_BLOCKSIZE;
else
{
SD_StopTransmission();
SD_WaitBusy(SD_WAIT_WRITE);
return ret;
}
}
SD_StopMultiToken();
ret = SD_WaitBusy(SD_WAIT_WRITE);
if (ret != SD_NO_ERR)
return SD_ERR_TIMEOUT_WRITE;
ret = SD_GetNumWRBlcoks(&i);
if (ret != SD_NO_ERR)
return ret;
if(i != blocknum)
return SD_ERR_WRITE_BLKNUMS;
return SD_NO_ERR;
}
#endif
//擦除SD卡中的块 Function: Erase the block of sd card
#if SD_EraseBlock_EN
INT8U SD_EraseBlock(INT32U startaddr, INT32U blocknum)
{
INT32 tmp;
INT8U ret;
if ((startaddr + blocknum) > sds.block_num)
return SD_ERR_OVER_CARDRANGE;
if (SD_ChkCardWP() == 1)
return SD_ERR_WRITE_PROTECT;
tmp = blocknum - sds.erase_unit;
while(tmp >= 0)
{
ret = SD_EraseStartBlock(startaddr);
if (ret != SD_NO_ERR)
return ret;
ret = SD_EraseEndBlock(startaddr + sds.erase_unit - 1);
if (ret != SD_NO_ERR)
return ret;
ret = SD_EraseSelectedBlock();
if (ret != SD_NO_ERR)
return ret;
startaddr += sds.erase_unit;
blocknum -= sds.erase_unit;
tmp = blocknum - sds.erase_unit;
};
if (blocknum > 0)
{
ret = SD_EraseStartBlock(startaddr);
if (ret != SD_NO_ERR)
return ret;
ret = SD_EraseEndBlock(startaddr + blocknum - 1);
if (ret != SD_NO_ERR)
return ret;
ret = SD_EraseSelectedBlock();
if (ret != SD_NO_ERR)
return ret;
}
return SD_NO_ERR;
}
#endif
//获得SD卡的信息
INT8U SD_GetCardInfo()
{
INT32U tmp;
INT8U csdbuf[16],ret;
ret = SD_ReadCSD(16,csdbuf);
if (ret != SD_NO_ERR)
return ret;
SD_CalTimeout(csdbuf);
/* 计算块的最大长度 */
sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK);
/* 计算卡中块的个数 */
sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
(csdbuf[C_SIZE_POS2] << 2) +
((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1;
tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +
((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2;
/* 获得卡中块的数量 */
sds.block_num = sds.block_num * (1 << tmp);
/* 计算扇区大小 */
sds.erase_unit = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +
((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1;
return SD_NO_ERR;
}
//计算读/写/擦超时时间
void SD_CalTimeout(INT8U *csdbuf)
{
INT32U tmp;
INT8U time_u,time_v,fator;
sds.timeout_read = READ_TIMEOUT_100MS;
sds.timeout_write = WRITE_TIMEOUT_250MS;
sds.timeout_erase = WRITE_TIMEOUT_250MS;
time_u = (csdbuf[TAAC_POS] & TAAC_MSK);
time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3;
fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2;
if(time_v == 0) return;
if(fator >= 6) return;
tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u];
tmp = tmp + csdbuf[NSAC_POS] * 100;
sds.timeout_read = tmp;
sds.timeout_write = tmp * r2w_fator[fator];
sds.timeout_read = sds.timeout_read * 100 / 8;
sds.timeout_write = sds.timeout_write * 100 / 8;
if (sds.timeout_read > READ_TIMEOUT_100MS)
sds.timeout_read = READ_TIMEOUT_100MS;
if (sds.timeout_write > WRITE_TIMEOUT_250MS)
sds.timeout_write = WRITE_TIMEOUT_250MS;
sds.timeout_erase = sds.timeout_write;
}
//计算读/写/擦超时时间
INT8U SD_ActiveInit(void)
{
INT8U param[4] = {0,0,0,0},resp[5],ret;
INT32U i = 0;
do
{
ret = SD_SendCmd(CMD1, param, CMD1_R, resp);
if (ret != SD_NO_ERR)
return ret;
i++;
}while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i < SD_IDLE_WAIT_MAX));
if (i >= SD_IDLE_WAIT_MAX)
return SD_ERR_TIMEOUT_WAITIDLE;
return SD_NO_ERR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -