📄 sd_mmc_spi.c
字号:
/****************************************Copyright (c)**************************************************
** 思 蜕 盟 豆 皮 开 发 小 组
** stmfans 论坛
**
** QQ 群: 65081316 StmFans思蜕盟 1组
** QQ 群: 68584951 StmFans思蜕盟 2组
** http://www.stmfans.com/bbs/
**
** This program was produced by the
** IAR Embedded Workbench 4.0 Kickstart 442
** Copyright 2008-2009 stmfans
** Chip type : STM32F103VB
** Program type : Application
** Clock frequency : 8.000000 MHz
** Memory model :
** External SRAM size :
** Data Stack size :
**--------------文件信息--------------------------------------------------------------------------------
**文 件 名: sd_mmc_spi.c
**创 建 人: 陈海
**最后修改日期: 2008年10月23日
**描 述: 豆皮开发板教程
**
**--------------历史版本信息----------------------------------------------------------------------------
** 创建人: 陈海
** 版 本: v0.01
** 日 期: 2008年10月23日
** 描 述: 原始版本
**
**--------------当前版本信息----------------------------------------------------------------------------
** 创建人: 陈海
** 版 本: v0.01
** 日 期: 2008年10月23日
** 描 述: 当前版本
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
////////////////////////////////////////////////////////////////////////
/* Define to prevent recursive inclusion -------------------------------------*/
#include "sd_mmc_spi.h"
#include "string.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 : non-zero init success, zero init error (迁就原系统 优化时修改)
*******************************************************************************/
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 |RCC_APB2Periph_SD_MMC_SPI_POWER, ENABLE);
/* Configure SD_MMC_SPI_POWER */
GPIO_InitStructure.GPIO_Pin = SD_MMC_SPI_POWER_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SD_MMC_SPI_POWER, &GPIO_InitStructure);
//关闭SD卡电源
GPIO_SetBits(SD_MMC_SPI_POWER, SD_MMC_SPI_POWER_Pin);
Delay_Ms(3000);
/* 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_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SD_MMC_SPI_CS, &GPIO_InitStructure);
GPIO_ResetBits(SD_MMC_SPI_POWER, SD_MMC_SPI_POWER_Pin);
Delay_Ms(100);
//////////////////////////////////////////////////////////////////////////////
/* initialize SPI with lowest frequency */
SD_MMC_Low_Speed();
/* card needs 74 cycles minimum to start up */
// for(u8 i = 0; i < 10; ++i)
for(u8 i = 0; i < 0x20; ++i)
{
/* wait 8 clock cycles */
SD_MMC_ReadWrite_Byte(0xff);
}
/* address card */
SD_MMC_SPI_SELECT();
/* reset card */
u8 response;
for(u16 i = 0; ; ++i)
{
response = SD_MMC_Send_Command(CMD_GO_IDLE_STATE , 0 );
if( response == 0x01 )
break;
if(i == 0xfff)
{
SD_MMC_SPI_DESELECT();
return 0;
}
}
/* wait for card to get ready */
for(u16 i = 0; ; ++i)
{
response = SD_MMC_Send_Command(CMD_SEND_OP_COND, 0);
if(!(response & (1 << R1_IDLE_STATE)))
break;
if(i == 0x7fff)
{
SD_MMC_SPI_DESELECT();
return 0;
}
}
/* set block size to 512 bytes */
if(SD_MMC_Send_Command(CMD_SET_BLOCKLEN, 512))
{
SD_MMC_SPI_DESELECT();
return 0;
}
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
/* deaddress card */
SD_MMC_SPI_DESELECT();
/* switch to highest SPI frequency possible */
SD_MMC_High_Speed();
//添加原来文件系统
#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 1;
//////////////////////////////////////////////////////////////////////////////
}
/*******************************************************************************
* 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)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(SPI1, ch);
/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI1);
}
/*******************************************************************************
* 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;
/* wait some clock cycles */
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(cmd == CMD_GO_IDLE_STATE ? 0x95 : 0xff);
/* receive response */
for(u8 i = 0; i < 20; ++i)
{
response = SD_MMC_ReadWrite_Byte(0xff);
if(response != 0xff)
break;
}
//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;
}
/////////////////////////////////////////////////////////////////////////////////////////////
//static void SD_MMC_ReadWrite_Byte(u8 b);
//static u8 SD_MMC_ReadWrite_Byte();
//static u8 SD_MMC_Send_Command(u8 command, u32 arg);
/**
* \ingroup sd_raw
* Checks wether a memory card is located in the slot.
*
* \returns 1 if the card is available, 0 if it is not.
*/
u8 sd_raw_available()
{
return 1;//get_pin_available() == 0x00;
}
/**
* \ingroup sd_raw
* Checks wether the memory card is locked for write access.
*
* \returns 1 if the card is locked, 0 if it is not.
*/
u8 sd_raw_locked()
{
return 1;//get_pin_locked() == 0x00;
}
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
/* address card */
SD_MMC_SPI_SELECT();
/* send single block request */
if(SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, block_address))
{
SD_MMC_SPI_DESELECT();
return 0;
}
/* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -