📄 sd_mmc_spi.c
字号:
/* Define to prevent recursive inclusion -------------------------------------*/
#include "sd_mmc_spi.h"
#define SD_MMC_SPI_SELECT() GPIO_ResetBits(SD_MMC_SPI_CS, SD_MMC_SPI_CS_Pin_CS)
#define SD_MMC_SPI_DESELECT() GPIO_SetBits(SD_MMC_SPI_CS, SD_MMC_SPI_CS_Pin_CS)
#if !SD_RAW_SAVE_RAM
// static data buffer for acceleration
static u8 raw_block[512];
// offset where the data within raw_block lies on the card
static u32 raw_block_address;
#if SD_RAW_WRITE_BUFFERING
// flag to remember if raw_block was written to the card
static u8 raw_block_written;
#endif
#endif
/*******************************************************************************
* Function Name : SD_MMC_SPI_Init
* Description : SD_MMC_SPI_Init
* Input : None
* Output : None
* Return : False init error, True init successerror
*******************************************************************************/
u8 SD_MMC_SPI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable SPI1 and GPIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA |
RCC_APB2Periph_SD_MMC_SPI_CS, ENABLE);
/* Configure SPI1 pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure SD_MMC_SPI_CS */
GPIO_InitStructure.GPIO_Pin = SD_MMC_SPI_CS_Pin_CS;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SD_MMC_SPI_CS, &GPIO_InitStructure);
/* Configure SD power pins: PD.10 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
//////////////////////////////////////////////////////////////////////////////
SD_MMC_Power_On_Off(On); //开启SD MMC电源
SD_MMC_Low_Speed(); // 使用低速SPI
/* 最少发送 74 时钟启动SD卡 */
for(u8 i = 0; i < 10; ++i)
{
SD_MMC_ReadWrite_Byte(0x00);
}
SD_MMC_SPI_SELECT(); //使能SD卡的SPI总线
/* reset SD卡 */
u8 response;
for(u16 i = 0; ; ++i)
{
response = SD_MMC_Send_Command(CMD_GO_IDLE_STATE , 0 );
if( response == 0x01 ) // 当返回 0x01时 重启成功
break;
if(i == 0x1ff) // 当超时 退出 初始化失败
{
SD_MMC_SPI_DESELECT();
SD_MMC_Power_On_Off(Off);
return False;
}
}
/* 等待 SD卡 准备好 */
for(u16 i = 0; ; ++i)
{
response = SD_MMC_Send_Command(CMD_SEND_OP_COND, 0);
if( !(response & (1 << R1_IDLE_STATE)) ) // 当返回 0x01时 SD卡准备好
break;
if(i == 0x7fff) // 当超时 退出 初始化失败
{
SD_MMC_SPI_DESELECT();
SD_MMC_Power_On_Off(Off);
return False;
}
}
/* 设置 512个字节为一个 BLOCK */
if(SD_MMC_Send_Command(CMD_SET_BLOCKLEN, 512))
{
SD_MMC_SPI_DESELECT();
return False;
}
SD_MMC_High_Speed();// 使用高速SPI
/* 不使用 crc 校验 */
if(SD_MMC_Send_Command(59, 0))
{
SD_MMC_SPI_DESELECT();
return False;
}
SD_MMC_SPI_DESELECT();//失能SD卡的SPI总线
////////////////////////////////////////////////////////////////////////////////
//添加原来文件系统
#if !SD_RAW_SAVE_RAM
// the first block is likely to be accessed first, so precache it here
//很可能首先访问第一块,所以在这里预先初始化缓存
raw_block_address = 0xffffffff;
#if SD_RAW_WRITE_BUFFERING
raw_block_written = 1;
#endif
//if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0;
#endif
return True;
}
/*******************************************************************************
* Function Name : SPI_SendByte
* Description : Sends a byte through the SPI interface and return the byte
* received from the SPI bus.
* Input : byte : byte to send.
* Output : None
* Return : The value of the received byte.
*******************************************************************************/
u8 SPI1_SendByte(u8 byte)
{
/* 等待发送寄存器空 */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
/* 发送一个字节到 SPI1 */
SPI_I2S_SendData(SPI1, byte);
/* 等待接收到一个字节 */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
/* 返回接收到的字节 */
return SPI_I2S_ReceiveData(SPI1);
}
/*******************************************************************************
* Function Name : SD_MMC_ReadWrite_Byte
* Description : SD_MMC_ReadWrite_Byte
* Input : the char to send
* Output : None
* Return : the char received
*******************************************************************************/
u8 SD_MMC_ReadWrite_Byte(u8 ch)
{
return (SPI1_SendByte(ch));
}
/*******************************************************************************
* Function Name : SD_MMC_Low_Speed
* Description : SD_MMC_Low_Speed
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SD_MMC_Low_Speed(void)
{
SPI_InitTypeDef SPI_InitStructure;
/* SPI1 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* SPI1 enable */
SPI_Cmd(SPI1, ENABLE);
}
/*******************************************************************************
* Function Name : SD_MMC_High_Speed
* Description : SD_MMC_High_Speed
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SD_MMC_High_Speed(void)
{
SPI_InitTypeDef SPI_InitStructure;
/* SPI1 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* SPI1 enable */
SPI_Cmd(SPI1, ENABLE);
}
/*******************************************************************************
* Function Name : SD_MMC_Send_Command
* Description : SD_MMC_Send_Command
* Input : None
* Output : None
* Return : None
*******************************************************************************/
u8 SD_MMC_Send_Command(u8 cmd, u32 arg)
{
u8 Response;
u8 Retry = 0;
SD_MMC_ReadWrite_Byte(0xff);
SD_MMC_SPI_SELECT();
//分别写入命令
SD_MMC_ReadWrite_Byte(cmd | 0x40);
SD_MMC_ReadWrite_Byte(arg >> 24);
SD_MMC_ReadWrite_Byte(arg >> 16);
SD_MMC_ReadWrite_Byte(arg >> 8);
SD_MMC_ReadWrite_Byte(arg);
SD_MMC_ReadWrite_Byte(0x95);
do{
// 等待响应,响应的开始位为0
Response = SD_MMC_ReadWrite_Byte(0xff);
Retry++;
}while( ((Response&0x80)!=0) && (Retry < 200) );
SD_MMC_SPI_DESELECT();
return Response; //返回状态值
}
/*******************************************************************************
* Function Name : SD_MMC_Read_Single_Block
* Description : SD_MMC_Read_Single_Block
* Input : sector number and buffer data point
* Output : None
* Return : zero success, non-zero error
*******************************************************************************/
u8 SD_MMC_Read_Single_Block(u32 sector, u8* buffer)
{
u8 Response;
u16 i;
u16 Retry = 0;
//读命令 send read command
Response = SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, sector<<9);
if(Response != 0x00)
return Response;
SD_MMC_SPI_SELECT();
// start byte 0xfe
while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe)
{
if(++Retry > 0xfffe)
{
SD_MMC_SPI_DESELECT();
return 1; //timeout
}
}
for(i = 0; i < 512; ++i)
{
//读512个数据
*buffer++ = SD_MMC_ReadWrite_Byte(0xff);
}
SD_MMC_ReadWrite_Byte(0xff); //伪crc
SD_MMC_ReadWrite_Byte(0xff); //伪crc
SD_MMC_SPI_DESELECT();
SD_MMC_ReadWrite_Byte(0xff); // extra 8 CLK
return 0;
}
/*******************************************************************************
* Function Name : SD_MMC_Write_Single_Block
* Description : SD_MMC_Write_Single_Block
* Input : sector number and buffer data point
* Output : None
* Return : zero success, non-zero error.
*******************************************************************************/
u8 SD_MMC_Write_Single_Block(u32 sector, u8* buffer)
{
u8 Response;
u16 i;
u16 retry=0;
//写命令 send write command
Response = SD_MMC_Send_Command(CMD_WRITE_SINGLE_BLOCK, sector<<9);
if(Response != 0x00)
return Response;
SD_MMC_SPI_SELECT();
SD_MMC_ReadWrite_Byte(0xff);
SD_MMC_ReadWrite_Byte(0xff);
SD_MMC_ReadWrite_Byte(0xff);
//发开始符 start byte 0xfe
SD_MMC_ReadWrite_Byte(0xfe);
//送512字节数据 send 512 bytes data
for(i=0; i<512; i++)
{
SD_MMC_ReadWrite_Byte(*buffer++);
}
SD_MMC_ReadWrite_Byte(0xff); //dummy crc
SD_MMC_ReadWrite_Byte(0xff); //dummy crc
Response = SD_MMC_ReadWrite_Byte(0xff);
//等待是否成功 judge if it successful
if( (Response&0x1f) != 0x05)
{
SD_MMC_SPI_DESELECT();
return Response;
}
//等待操作完 wait no busy
while(SD_MMC_ReadWrite_Byte(0xff) != 0x00)
{
if(retry++ > 0xfffe)
{
SD_MMC_SPI_DESELECT();
return 1;
}
}
SD_MMC_SPI_DESELECT();
SD_MMC_ReadWrite_Byte(0xff);// extra 8 CLK
return 0;
}
/*******************************************************************************
* Function Name : SD_MMC_Power_On_Off
* Description : SD_MMC_Power_On_Off
* Input : On or Off
* Output : None
* Return : None
*******************************************************************************/
void SD_MMC_Power_On_Off(u8 On_Off)
{
// 0 power on 1 power off
if( On_Off == On )
GPIO_ResetBits(GPIOD, GPIO_Pin_10);
else
GPIO_SetBits(GPIOD, GPIO_Pin_10);
}
/////////////////////////////////////////////////////////////////////////////////////////////
//static void SD_MMC_ReadWrite_Byte(u8 b);
//static u8 SD_MMC_ReadWrite_Byte();
//static u8 SD_MMC_Send_Command(u8 command, u32 arg);
/*******************************************************************************
* Function Name : SD_Raw_Available
* Description : 检测SD卡是否插入卡槽
* Input : None
* Output : None
* Return : 0 --- 无卡 1 -- 有卡
*******************************************************************************/
u8 SD_Raw_Available()
{
return 1;//get_pin_available() == 0x00;
}
/*******************************************************************************
* Function Name : SD_Raw_Locked
* Description : 检测SD卡是否写保护状态
* Input : None
* Output : None
* Return : 0 --- 写保护 1 -- 无保护
*******************************************************************************/
u8 SD_Raw_Locked()
{
return 1;//get_pin_locked() == 0x00;
}
/*******************************************************************************
* Function Name : SD_Raw_Read
* Description : SD_Raw_Read
* Input : None
* Output : None
* Return : 0 --- fail 1 -- OK
*******************************************************************************/
u8 SD_Raw_Read(u32 offset, u8* buffer, u16 length)
{
u32 block_address;
u16 block_offset;
u16 read_length;
while(length > 0)
{
/* determine byte count to read at once */
block_address = offset & 0xfffffe00;
block_offset = offset & 0x01ff;
read_length = 512 - block_offset; /* read up to block border */
if(read_length > length)
read_length = length;
#if !SD_RAW_SAVE_RAM
/* check if the requested data is cached */
if(block_address != raw_block_address)
#endif
{
#if SD_RAW_WRITE_BUFFERING
if(!raw_block_written)
{
if(!SD_Raw_Write(raw_block_address, raw_block, sizeof(raw_block)))
return 0;
}
#endif
//这两个次序很重要 begin
/* send single block request */
if(SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, block_address))
{
SD_MMC_SPI_DESELECT();
return 0;
}
/* address card */
SD_MMC_SPI_SELECT();
//这两个次序很重要 end
/* wait for data block (start byte 0xfe) */
while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe);
#if SD_RAW_SAVE_RAM
/* read byte block */
u16 read_to = block_offset + read_length;
for(u16 i = 0; i < 512; ++i)
{
u8 b = SD_MMC_ReadWrite_Byte(0xff);
if(i >= block_offset && i < read_to)
*buffer++ = b;
}
#else
/* read byte block */
u8* cache = raw_block;
for(u16 i = 0; i < 512; ++i)
*cache++ = SD_MMC_ReadWrite_Byte(0xff);
raw_block_address = block_address;
memcpy(buffer, raw_block + block_offset, read_length);
buffer += read_length;
#endif
/* read crc16 */
SD_MMC_ReadWrite_Byte(0xff);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -