提交 8421ecfa 编写于 作者: wuyangyong's avatar wuyangyong

update SD card driver: use RT-Thread SPI driver.

上级 5c17c2e6
......@@ -4,6 +4,15 @@ from building import *
cwd = os.path.join(str(Dir('#')), 'drivers')
src = Glob('*.c')
# remove no need file.
if GetDepend('RT_USING_LWIP') == False:
SrcRemove(src, 'stm32_eth.c')
if GetDepend('RT_USING_SPI') == False:
SrcRemove(src, 'rt_stm32f10x_spi.c')
SrcRemove(src, 'msd.c')
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
......
......@@ -14,7 +14,6 @@
#include <rthw.h>
#include <rtthread.h>
#include "board.h"
/**
......@@ -45,15 +44,15 @@ void NVIC_Configuration(void)
* This is the timer interrupt service routine.
*
*/
void rt_hw_timer_handler(void)
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
/* enter interrupt */
rt_interrupt_enter();
rt_tick_increase();
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
/* leave interrupt */
rt_interrupt_leave();
}
/**
......
......@@ -40,6 +40,9 @@
#define STM32_SRAM_SIZE 64
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
#define RT_USING_UART1
#define RT_USING_SPI1
void rt_hw_board_init(void);
void rt_hw_usart_init(void);
......
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : msd.c
* Author : MCD Application Team
* Version : V2.1
* Date : 05/30/2008
* Description : MSD card driver source file.
* Pin assignment:
* ----------------------------------------------
* | STM32F10x | MSD Pin |
* ----------------------------------------------
* | P0.4 | ChipSelect 1 |
* | P0.1 / MOSI | DataIn 2 |
* | | GND 3 (0 V) |
* | | VDD 4 (3.3 V) |
* | P0.2 / SCLK | Clock 5 |
* | | GND 6 (0 V) |
* | P0.0 / MISO | DataOut 7 |
* -----------------------------------------------
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
/*
* File : msd.c
* SPI mode SD Card Driver
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-04-17 Bernard first version.
* 2010-07-15 aozima Modify read/write according new block driver interface.
* 2012-02-01 aozima use new RT-Thread SPI drivers.
* 2012-04-11 aozima get max. data transfer rate from CSD[TRAN_SPEED].
* 2012-05-21 aozima update MMC card support.
*/
#include <string.h>
#include "msd.h"
#include <stm32f10x_spi.h>
#include <rtthread.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Select MSD Card: ChipSelect pin low */
#define MSD_CS_LOW() GPIO_ResetBits(GPIOA, GPIO_Pin_4)
/* Deselect MSD Card: ChipSelect pin high */
#define MSD_CS_HIGH() GPIO_SetBits(GPIOA, GPIO_Pin_4)
#define MSD_SPI SPI1
#define MSD_RCC_SPI RCC_APB2Periph_SPI1
/* Private function prototypes -----------------------------------------------*/
static void SPI_Config(void);
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : MSD_Init
* Description : Initializes the MSD/SD communication.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_Init(void)
//#define MSD_TRACE
#ifdef MSD_TRACE
#define MSD_DEBUG(...) rt_kprintf("[MSD] %d ", rt_tick_get()); rt_kprintf(__VA_ARGS__);
#else
#define MSD_DEBUG(...)
#endif /* #ifdef MSD_TRACE */
#define DUMMY 0xFF
#define CARD_NCR_MAX 8
#define CARD_NRC 1
#define CARD_NCR 1
static struct msd_device _msd_device;
/* function define */
static rt_bool_t rt_tick_timeout(rt_tick_t tick_start, rt_tick_t tick_long);
static rt_err_t MSD_take_owner(struct rt_spi_device* spi_device);
static void MSD_take_cs(struct rt_spi_device* device);
static void MSD_release_cs(struct rt_spi_device* device);
static rt_err_t _wait_token(struct rt_spi_device* device, uint8_t token);
static rt_err_t _wait_ready(struct rt_spi_device* device);
static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size);
static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);
static rt_size_t rt_msd_sdhc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);
static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size);
static rt_err_t MSD_take_owner(struct rt_spi_device* spi_device)
{
u32 i = 0;
/* Initialize SPI */
SPI_Config();
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte 0xFF, 10 times with CS high*/
/* rise CS and MOSI for 80 clocks cycles */
for (i = 0; i < 10; i++)
{
/* Send dummy byte 0xFF */
MSD_WriteByte(DUMMY);
}
/*------------Put MSD in SPI mode--------------*/
/* MSD initialized and set to SPI mode properly */
return (MSD_GoIdleState());
rt_err_t result;
result = rt_mutex_take(&(spi_device->bus->lock), RT_WAITING_FOREVER);
if(result == RT_EOK)
{
if (spi_device->bus->owner != spi_device)
{
/* not the same owner as current, re-configure SPI bus */
result = spi_device->bus->ops->configure(spi_device, &spi_device->config);
if (result == RT_EOK)
{
/* set SPI bus owner */
spi_device->bus->owner = spi_device;
}
}
}
return result;
}
static void MSD_take_cs(struct rt_spi_device* device)
{
struct rt_spi_message message;
/* initial message */
message.send_buf = RT_NULL;
message.recv_buf = RT_NULL;
message.length = 0;
message.cs_take = 1;
message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
}
/*******************************************************************************
* Function Name : MSD_WriteBlock
* Description : Writes a block on the MSD
* Input : - pBuffer : pointer to the buffer containing the data to be
* written on the MSD.
* - WriteAddr : address to write on.
* - NumByteToWrite: number of data to write
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
static void MSD_release_cs(struct rt_spi_device* device)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD24 (MSD_WRITE_BLOCK) to write multiple block */
MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr, 0xFF);
/* Check if the MSD acknowledged the write block command: R1 response (0x00: no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
/* Send a dummy byte */
MSD_WriteByte(DUMMY);
/* Send the data token to signify the start of the data */
MSD_WriteByte(0xFE);
/* Write the block data to MSD : write count data by block */
for (i = 0; i < NumByteToWrite; i++)
{
/* Send the pointed byte */
MSD_WriteByte(*pBuffer);
/* Point to the next location where the byte read will be saved */
pBuffer++;
struct rt_spi_message message;
/* initial message */
message.send_buf = RT_NULL;
message.recv_buf = RT_NULL;
message.length = 0;
message.cs_take = 0;
message.cs_release = 1;
/* transfer message */
device->bus->ops->xfer(device, &message);
}
static rt_bool_t rt_tick_timeout(rt_tick_t tick_start, rt_tick_t tick_long)
{
rt_tick_t tick_end = tick_start + tick_long;
rt_tick_t tick_now = rt_tick_get();
rt_bool_t result = RT_FALSE;
if(tick_end >= tick_start)
{
if (tick_now >= tick_end)
{
result = RT_TRUE;
}
else
{
result = RT_FALSE;
}
}
/* Put CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Read data response */
if (MSD_GetDataResponse() == MSD_DATA_OK)
else
{
rvalue = MSD_RESPONSE_NO_ERROR;
if ((tick_now < tick_start ) && (tick_now >= tick_end) )
{
result = RT_TRUE;
}
else
{
result = RT_FALSE;
}
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
return result;
}
/*******************************************************************************
* Function Name : MSD_ReadBlock
* Description : Reads a block of data from the MSD.
* Input : - pBuffer : pointer to the buffer that receives the data read
* from the MSD.
* - ReadAddr : MSD's internal address to read from.
* - NumByteToRead : number of bytes to read from the MSD.
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
static uint8_t crc7(const uint8_t *buf, int len)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */
MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF);
/* Check if the MSD acknowledged the read block command: R1 response (0x00: no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
/* Now look for the data token to signify the start of the data */
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
/* Read the MSD block data : read NumByteToRead data */
for (i = 0; i < NumByteToRead; i++)
{
/* Save the received data */
*pBuffer = MSD_ReadByte();
/* Point to the next location where the byte read will be saved */
pBuffer++;
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
unsigned char i, j, crc, ch, ch2, ch3;
crc = 0;
for (i = 0; i < len; i ++)
{
ch = buf[i];
for (j = 0; j < 8; j ++, ch <<= 1)
{
ch2 = (crc & 0x40) ? 1 : 0;
ch3 = (ch & 0x80) ? 1 : 0;
if (ch2 ^ ch3)
{
crc ^= 0x04;
crc <<= 1;
crc |= 0x01;
}
else
{
crc <<= 1;
}
}
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
return crc;
}
/*******************************************************************************
* Function Name : MSD_WriteBuffer
* Description : Writes many blocks on the MSD
* Input : - pBuffer : pointer to the buffer containing the data to be
* written on the MSD.
* - WriteAddr : address to write on.
* - NumByteToWrite: number of data to write
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite)
static rt_err_t _send_cmd(
struct rt_spi_device* device,
uint8_t cmd,
uint32_t arg,
uint8_t crc,
response_type type,
uint8_t * response
)
{
u32 i = 0, NbrOfBlock = 0, Offset = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
struct rt_spi_message message;
uint8_t cmd_buffer[8];
uint8_t recv_buffer[sizeof(cmd_buffer)];
uint32_t i;
cmd_buffer[0] = DUMMY;
cmd_buffer[1] = (cmd | 0x40);
cmd_buffer[2] = (uint8_t)(arg >> 24);
cmd_buffer[3] = (uint8_t)(arg >> 16);
cmd_buffer[4] = (uint8_t)(arg >> 8);
cmd_buffer[5] = (uint8_t)(arg);
if(crc == 0x00)
{
crc = crc7(&cmd_buffer[1], 5);
crc = (crc<<1) | 0x01;
}
cmd_buffer[6] = (crc);
cmd_buffer[7] = DUMMY;
/* Calculate number of blocks to write */
NbrOfBlock = NumByteToWrite / BLOCK_SIZE;
/* MSD chip select low */
MSD_CS_LOW();
/* initial message */
message.send_buf = cmd_buffer;
message.recv_buf = recv_buffer;
message.length = sizeof(cmd_buffer);
message.cs_take = message.cs_release = 0;
/* Data transfer */
while (NbrOfBlock --)
{
/* Send CMD24 (MSD_WRITE_BLOCK) to write blocks */
MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr + Offset, 0xFF);
_wait_ready(device);
/* Check if the MSD acknowledged the write block command: R1 response (0x00: no errors) */
if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
/* transfer message */
device->bus->ops->xfer(device, &message);
for(i=CARD_NCR; i<(CARD_NCR_MAX+1); i++)
{
return MSD_RESPONSE_FAILURE;
}
/* Send dummy byte */
MSD_WriteByte(DUMMY);
/* Send the data token to signify the start of the data */
MSD_WriteByte(MSD_START_DATA_SINGLE_BLOCK_WRITE);
/* Write the block data to MSD : write count data by block */
for (i = 0; i < BLOCK_SIZE; i++)
{
/* Send the pointed byte */
MSD_WriteByte(*pBuffer);
/* Point to the next location where the byte read will be saved */
pBuffer++;
uint8_t send = DUMMY;
/* initial message */
message.send_buf = &send;
message.recv_buf = response;
message.length = 1;
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
if(0 == (response[0] & 0x80))
{
break;
}
} /* wait response */
if((CARD_NCR_MAX+1) == i)
{
return RT_ERROR;//fail
}
/* Set next write address */
Offset += 512;
/* Put CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Read data response */
if (MSD_GetDataResponse() == MSD_DATA_OK)
{
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
//recieve other byte
if(type == response_r1)
{
return RT_EOK;
}
else
else if(type == response_r1b)
{
/* Set response value to failure */
rvalue = MSD_RESPONSE_FAILURE;
rt_tick_t tick_start = rt_tick_get();
uint8_t recv;
while(1)
{
/* initial message */
message.send_buf = RT_NULL;
message.recv_buf = &recv;
message.length = 1;
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
if(recv == DUMMY)
{
return RT_EOK;
}
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(2000)))
{
return RT_ETIMEOUT;
}
}
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_ReadBuffer
* Description : Reads multiple block of data from the MSD.
* Input : - pBuffer : pointer to the buffer that receives the data read
* from the MSD.
* - ReadAddr : MSD's internal address to read from.
* - NumByteToRead : number of bytes to read from the MSD.
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead)
{
u32 i = 0, NbrOfBlock = 0, Offset = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
/* Calculate number of blocks to read */
NbrOfBlock = NumByteToRead / BLOCK_SIZE;
/* MSD chip select low */
MSD_CS_LOW();
/* Data transfer */
while (NbrOfBlock --)
{
/* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */
MSD_SendCmd (MSD_READ_SINGLE_BLOCK, ReadAddr + Offset, 0xFF);
/* Check if the MSD acknowledged the read block command: R1 response (0x00: no errors) */
if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
return MSD_RESPONSE_FAILURE;
else if(type == response_r2)
{
/* initial message */
message.send_buf = RT_NULL;
message.recv_buf = response+1;
message.length = 1;
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
}
/* Now look for the data token to signify the start of the data */
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
/* Read the MSD block data : read NumByteToRead data */
for (i = 0; i < BLOCK_SIZE; i++)
{
/* Read the pointed data */
*pBuffer = MSD_ReadByte();
/* Point to the next location where the byte read will be saved */
pBuffer++;
}
/* Set next read address*/
Offset += 512;
/* get CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte();
MSD_ReadByte();
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
else if((type == response_r3) || (type == response_r7))
{
/* initial message */
message.send_buf = RT_NULL;
message.recv_buf = response+1;
message.length = 4;
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
}
else
{
/* Set response value to failure */
rvalue = MSD_RESPONSE_FAILURE;
return RT_ERROR; // unknow type?
}
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Returns the reponse */
return rvalue;
return RT_EOK;
}
/*******************************************************************************
* Function Name : MSD_GetCSDRegister
* Description : Read the CSD card register.
* Reading the contents of the CSD register in SPI mode
* is a simple read-block transaction.
* Input : - MSD_csd: pointer on an SCD register structure
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetCSDRegister(sMSD_CSD* MSD_csd)
static rt_err_t _wait_token(struct rt_spi_device* device, uint8_t token)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
u8 CSD_Tab[16];
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD9 (CSD register) or CMD10(CSD register) */
MSD_SendCmd(MSD_SEND_CSD, 0, 0xFF);
/* Wait for response in the R1 format (0x00 is no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
for (i = 0; i < 16; i++)
{
/* Store CSD register value on CSD_Tab */
CSD_Tab[i] = MSD_ReadByte();
}
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
MSD_WriteByte(DUMMY);
MSD_WriteByte(DUMMY);
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Byte 0 */
MSD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;
MSD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;
MSD_csd->Reserved1 = CSD_Tab[0] & 0x03;
/* Byte 1 */
MSD_csd->TAAC = CSD_Tab[1] ;
/* Byte 2 */
MSD_csd->NSAC = CSD_Tab[2];
/* Byte 3 */
MSD_csd->MaxBusClkFrec = CSD_Tab[3];
/* Byte 4 */
MSD_csd->CardComdClasses = CSD_Tab[4] << 4;
/* Byte 5 */
MSD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
MSD_csd->RdBlockLen = CSD_Tab[5] & 0x0F;
/* Byte 6 */
MSD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;
MSD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;
MSD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;
MSD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4;
MSD_csd->Reserved2 = 0; /* Reserved */
MSD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10;
/* Byte 7 */
MSD_csd->DeviceSize |= (CSD_Tab[7]) << 2;
/* Byte 8 */
MSD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
MSD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;
MSD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);
/* Byte 9 */
MSD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;
MSD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;
MSD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;
/* Byte 10 */
MSD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;
MSD_csd->EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2;
MSD_csd->EraseGrMul = (CSD_Tab[10] & 0x03) << 3;
/* Byte 11 */
MSD_csd->EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5;
MSD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x1F);
/* Byte 12 */
MSD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;
MSD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;
MSD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;
MSD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;
/* Byte 13 */
MSD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6;
MSD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;
MSD_csd->Reserved3 = 0;
MSD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01);
/* Byte 14 */
MSD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;
MSD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6;
MSD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;
MSD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;
MSD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2;
MSD_csd->ECC = (CSD_Tab[14] & 0x03);
/* Byte 15 */
MSD_csd->msd_CRC = (CSD_Tab[15] & 0xFE) >> 1;
MSD_csd->Reserved4 = 1;
/* Return the reponse */
return rvalue;
struct rt_spi_message message;
rt_tick_t tick_start;
uint8_t send, recv;
tick_start = rt_tick_get();
/* wati token */
/* initial message */
send = DUMMY;
message.send_buf = &send;
message.recv_buf = &recv;
message.length = 1;
message.cs_take = message.cs_release = 0;
while(1)
{
/* transfer message */
device->bus->ops->xfer(device, &message);
if(recv == token)
{
return RT_EOK;
}
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(CARD_WAIT_TOKEN_TIMES)))
{
MSD_DEBUG("[err] wait data start token timeout!\r\n");
return RT_ETIMEOUT;
}
} /* wati token */
}
/*******************************************************************************
* Function Name : MSD_GetCIDRegister
* Description : Read the CID card register.
* Reading the contents of the CID register in SPI mode
* is a simple read-block transaction.
* Input : - MSD_cid: pointer on an CID register structure
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetCIDRegister(sMSD_CID* MSD_cid)
static rt_err_t _wait_ready(struct rt_spi_device* device)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
u8 CID_Tab[16];
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD10 (CID register) */
MSD_SendCmd(MSD_SEND_CID, 0, 0xFF);
/* Wait for response in the R1 format (0x00 is no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
/* Store CID register value on CID_Tab */
for (i = 0; i < 16; i++)
{
CID_Tab[i] = MSD_ReadByte();
}
struct rt_spi_message message;
rt_tick_t tick_start;
uint8_t send, recv;
tick_start = rt_tick_get();
send = DUMMY;
/* initial message */
message.send_buf = &send;
message.recv_buf = &recv;
message.length = 1;
message.cs_take = message.cs_release = 0;
while(1)
{
/* transfer message */
device->bus->ops->xfer(device, &message);
if(recv == DUMMY)
{
return RT_EOK;
}
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(1000)))
{
MSD_DEBUG("[err] wait ready timeout!\r\n");
return RT_ETIMEOUT;
}
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
MSD_WriteByte(DUMMY);
MSD_WriteByte(DUMMY);
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte: 8 Clock pulses of delay */
MSD_WriteByte(DUMMY);
/* Byte 0 */
MSD_cid->ManufacturerID = CID_Tab[0];
/* Byte 1 */
MSD_cid->OEM_AppliID = CID_Tab[1] << 8;
/* Byte 2 */
MSD_cid->OEM_AppliID |= CID_Tab[2];
/* Byte 3 */
MSD_cid->ProdName1 = CID_Tab[3] << 24;
/* Byte 4 */
MSD_cid->ProdName1 |= CID_Tab[4] << 16;
/* Byte 5 */
MSD_cid->ProdName1 |= CID_Tab[5] << 8;
/* Byte 6 */
MSD_cid->ProdName1 |= CID_Tab[6];
/* Byte 7 */
MSD_cid->ProdName2 = CID_Tab[7];
/* Byte 8 */
MSD_cid->ProdRev = CID_Tab[8];
/* Byte 9 */
MSD_cid->ProdSN = CID_Tab[9] << 24;
/* Byte 10 */
MSD_cid->ProdSN |= CID_Tab[10] << 16;
/* Byte 11 */
MSD_cid->ProdSN |= CID_Tab[11] << 8;
/* Byte 12 */
MSD_cid->ProdSN |= CID_Tab[12];
/* Byte 13 */
MSD_cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4;
/* Byte 14 */
MSD_cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8;
/* Byte 15 */
MSD_cid->ManufactDate |= CID_Tab[14];
/* Byte 16 */
MSD_cid->msd_CRC = (CID_Tab[15] & 0xFE) >> 1;
MSD_cid->Reserved2 = 1;
/* Return the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_SendCmd
* Description : Send 5 bytes command to the MSD card.
* Input : - Cmd: the user expected command to send to MSD card
* - Arg: the command argument
* - Crc: the CRC
* Output : None
* Return : None
*******************************************************************************/
void MSD_SendCmd(u8 Cmd, u32 Arg, u8 Crc)
static rt_err_t _read_block(struct rt_spi_device* device, void * buffer, uint32_t block_size)
{
u32 i = 0x00;
u8 Frame[6];
/* Construct byte1 */
Frame[0] = (Cmd | 0x40);
/* Construct byte2 */
Frame[1] = (u8)(Arg >> 24);
/* Construct byte3 */
Frame[2] = (u8)(Arg >> 16);
/* Construct byte4 */
Frame[3] = (u8)(Arg >> 8);
/* Construct byte5 */
Frame[4] = (u8)(Arg);
/* Construct CRC: byte6 */
Frame[5] = (Crc);
/* Send the Cmd bytes */
for (i = 0; i < 6; i++)
{
MSD_WriteByte(Frame[i]);
}
}
struct rt_spi_message message;
rt_err_t result;
/*******************************************************************************
* Function Name : MSD_GetDataResponse
* Description : Get MSD card data response.
* Input : None
* Output : None
* Return : The MSD status: Read data response xxx0<status>1
* - status 010: Data accecpted
* - status 101: Data rejected due to a crc error
* - status 110: Data rejected due to a Write error.
* - status 111: Data rejected due to other error.
*******************************************************************************/
u8 MSD_GetDataResponse(void)
{
u32 i = 0;
u8 response, rvalue;
while (i <= 64)
{
/* Read resonse */
response = MSD_ReadByte();
/* Mask unused bits */
response &= 0x1F;
switch (response)
{
case MSD_DATA_OK:
{
rvalue = MSD_DATA_OK;
break;
}
case MSD_DATA_CRC_ERROR:
return MSD_DATA_CRC_ERROR;
case MSD_DATA_WRITE_ERROR:
return MSD_DATA_WRITE_ERROR;
default:
{
rvalue = MSD_DATA_OTHER_ERROR;
break;
}
/* wati token */
result = _wait_token(device, MSD_TOKEN_READ_START);
if(result != RT_EOK)
{
return result;
}
/* Exit loop in case of data ok */
if (rvalue == MSD_DATA_OK)
break;
/* Increment loop counter */
i++;
}
/* Wait null data */
while (MSD_ReadByte() == 0);
/* Return response */
return response;
/* read data */
{
/* initial message */
message.send_buf = RT_NULL;
message.recv_buf = buffer;
message.length = block_size;
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
} /* read data */
/* get crc */
{
uint8_t recv_buffer[2];
/* initial message */
message.send_buf = RT_NULL;
message.recv_buf = recv_buffer;
message.length = 2;
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
} /* get crc */
return RT_EOK;
}
/*******************************************************************************
* Function Name : MSD_GetResponse
* Description : Returns the MSD response.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetResponse(u8 Response)
static rt_err_t _write_block(struct rt_spi_device* device, const void * buffer, uint32_t block_size, uint8_t token)
{
u32 Count = 0xFFF;
/* Check if response is got or a timeout is happen */
while ((MSD_ReadByte() != Response) && Count)
{
Count--;
}
if (Count == 0)
{
/* After time out */
return MSD_RESPONSE_FAILURE;
}
else
{
/* Right response got */
return MSD_RESPONSE_NO_ERROR;
}
struct rt_spi_message message;
uint8_t send_buffer[16];
rt_memset(send_buffer, DUMMY, sizeof(send_buffer));
send_buffer[sizeof(send_buffer) - 1] = token;
/* send start block token */
{
/* initial message */
message.send_buf = send_buffer;
message.recv_buf = RT_NULL;
message.length = sizeof(send_buffer);
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
}
/* send data */
{
/* initial message */
message.send_buf = buffer;
message.recv_buf = RT_NULL;
message.length = block_size;
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
}
/* put crc and get data response */
{
uint8_t recv_buffer[3];
uint8_t response;
/* initial message */
message.send_buf = send_buffer;
message.recv_buf = recv_buffer;
message.length = sizeof(recv_buffer);
message.cs_take = message.cs_release = 0;
/* transfer message */
device->bus->ops->xfer(device, &message);
// response = 0x0E & recv_buffer[2];
response = MSD_GET_DATA_RESPONSE(recv_buffer[2]);
if(response != MSD_DATA_OK)
{
MSD_DEBUG("[err] write block fail! data response : 0x%02X\r\n", response);
return RT_ERROR;
}
}
/* wati ready */
return _wait_ready(device);
}
/*******************************************************************************
* Function Name : MSD_GetStatus
* Description : Returns the MSD status.
* Input : None
* Output : None
* Return : The MSD status.
*******************************************************************************/
u16 MSD_GetStatus(void)
/* RT-Thread Device Driver Interface */
static rt_err_t rt_msd_init(rt_device_t dev)
{
u16 Status = 0;
struct msd_device * msd = (struct msd_device *)dev;
uint8_t response[MSD_RESPONSE_MAX_LEN];
rt_err_t result = RT_EOK;
rt_tick_t tick_start;
uint32_t OCR;
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD13 (MSD_SEND_STATUS) to get MSD status */
MSD_SendCmd(MSD_SEND_STATUS, 0, 0xFF);
if(msd->spi_device == RT_NULL)
{
MSD_DEBUG("[err] the SPI SD device has no SPI!\r\n");
return RT_EIO;
}
Status = MSD_ReadByte();
Status |= (u16)(MSD_ReadByte() << 8);
/* config spi */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 */
cfg.max_hz = 1000*400; /* 400kbit/s */
rt_spi_configure(msd->spi_device, &cfg);
} /* config spi */
/* init SD card */
{
struct rt_spi_message message;
result = MSD_take_owner(msd->spi_device);
if (result != RT_EOK)
{
goto _exit;
}
MSD_release_cs(msd->spi_device);
/* The host shall supply power to the card so that the voltage is reached to Vdd_min within 250ms and
start to supply at least 74 SD clocks to the SD card with keeping CMD line to high.
In case of SPI mode, CS shall be held to high during 74 clock cycles. */
{
uint8_t send_buffer[100]; /* 100byte > 74 clock */
/* initial message */
memset(send_buffer, DUMMY, sizeof(send_buffer));
message.send_buf = send_buffer;
message.recv_buf = RT_NULL;
message.length = sizeof(send_buffer);
message.cs_take = message.cs_release = 0;
/* transfer message */
msd->spi_device->bus->ops->xfer(msd->spi_device, &message);
} /* send 74 clock */
/* Send CMD0 (GO_IDLE_STATE) to put MSD in SPI mode */
{
tick_start = rt_tick_get();
while(1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, GO_IDLE_STATE, 0x00, 0x95, response_r1, response);
MSD_release_cs(msd->spi_device);
if((result == RT_EOK) && (response[0] == MSD_IN_IDLE_STATE))
{
break;
}
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(CARD_TRY_TIMES)))
{
MSD_DEBUG("[err] SD card goto IDLE mode timeout!\r\n");
result = RT_ETIMEOUT;
goto _exit;
}
}
MSD_DEBUG("[info] SD card goto IDLE mode OK!\r\n");
} /* Send CMD0 (GO_IDLE_STATE) to put MSD in SPI mode */
/* CMD8 */
{
tick_start = rt_tick_get();
do
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, SEND_IF_COND, 0x01AA, 0x87, response_r7, response);
MSD_release_cs(msd->spi_device);
if(result == RT_EOK)
{
MSD_DEBUG("[info] CMD8 response : 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\r\n",
response[0], response[1], response[2], response[3], response[4]);
if(response[0] & (1<<2))
{
/* illegal command, SD V1.x or MMC card */
MSD_DEBUG("[info] CMD8 is illegal command.\r\n");
MSD_DEBUG("[info] maybe Ver1.X SD Memory Card or MMC card!\r\n");
msd->card_type = MSD_CARD_TYPE_SD_V1_X;
break;
}
else
{
/* SD V2.0 or later or SDHC or SDXC memory card! */
MSD_DEBUG("[info] Ver2.00 or later or SDHC or SDXC memory card!\r\n");
msd->card_type = MSD_CARD_TYPE_SD_V2_X;
}
if((0xAA == response[4]) && (0x00 == response[3]))
{
/* SD2.0 not support current voltage */
MSD_DEBUG("[err] VCA = 0, SD2.0 not surpport current operation voltage range\r\n");
result = RT_ERROR;
goto _exit;
}
}
else
{
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(200)))
{
MSD_DEBUG("[err] CMD8 SEND_IF_COND timeout!\r\n");
result = RT_ETIMEOUT;
goto _exit;
}
}
}
while(0xAA != response[4]);
} /* CMD8 */
/* Ver1.X SD Memory Card or MMC card */
if(msd->card_type == MSD_CARD_TYPE_SD_V1_X)
{
rt_bool_t is_sd_v1_x = RT_FALSE;
rt_tick_t tick_start;
/* try SD Ver1.x */
while(1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, READ_OCR, 0x00, 0x00, response_r3, response);
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[info] It maybe SD1.x or MMC But it is Not response to CMD58!\r\n");
goto _exit;
}
if(0 != (response[0]&0xFE))
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[info] It look CMD58 as illegal command so it is not SD card!\r\n");
break;
}
MSD_release_cs(msd->spi_device);
OCR = response[1];
OCR = (OCR<<8) + response[2];
OCR = (OCR<<8) + response[3];
OCR = (OCR<<8) + response[4];
MSD_DEBUG("[info] OCR is 0x%08X\r\n", OCR);
if( 0 == (OCR & (0x1 << 15)))
{
MSD_DEBUG(("[err] SD 1.x But not surpport current voltage\r\n"));
result = RT_ERROR;
goto _exit;
}
/* --Send ACMD41 to make card ready */
tick_start = rt_tick_get();
/* try CMD55 + ACMD41 */
while(1)
{
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(CARD_TRY_TIMES_ACMD41)))
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[info] try CMD55 + ACMD41 timeout! mabey MMC card!\r\n");
break;
}
MSD_take_cs(msd->spi_device);
/* CMD55 APP_CMD */
result = _send_cmd(msd->spi_device, APP_CMD, 0x00, 0x00, response_r1, response);
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
continue;
}
if(0 != (response[0]&0xFE))
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[info] Not SD card2 , may be MMC\r\n");
break;
}
/* ACMD41 SD_SEND_OP_COND */
result = _send_cmd(msd->spi_device, SD_SEND_OP_COND, 0x00, 0x00, response_r1, response);
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
continue;
}
if(0 != (response[0]&0xFE))
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[info] Not SD card4 , may be MMC\r\n");
break;
}
if(0 == (response[0]&0xFF))
{
MSD_release_cs(msd->spi_device);
is_sd_v1_x = RT_TRUE;
MSD_DEBUG("[info] It is Ver1.X SD Memory Card!!!\r\n");
break;
}
} /* try CMD55 + ACMD41 */
break;
} /* try SD Ver1.x */
/* try MMC */
if(is_sd_v1_x != RT_TRUE)
{
uint32_t i;
MSD_DEBUG("[info] try MMC card!\r\n");
MSD_release_cs(msd->spi_device);
/* send dummy clock */
{
uint8_t send_buffer[100];
/* initial message */
memset(send_buffer, DUMMY, sizeof(send_buffer));
message.send_buf = send_buffer;
message.recv_buf = RT_NULL;
message.length = sizeof(send_buffer);
message.cs_take = message.cs_release = 0;
for(i=0; i<10; i++)
{
/* transfer message */
msd->spi_device->bus->ops->xfer(msd->spi_device, &message);
}
} /* send dummy clock */
/* send CMD0 goto IDLE state */
tick_start = rt_tick_get();
while(1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, GO_IDLE_STATE, 0x00, 0x95, response_r1, response);
MSD_release_cs(msd->spi_device);
if((result == RT_EOK) && (response[0] == MSD_IN_IDLE_STATE))
{
break;
}
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(CARD_TRY_TIMES)))
{
MSD_DEBUG("[err] SD card goto IDLE mode timeout!\r\n");
result = RT_ETIMEOUT;
goto _exit;
}
} /* send CMD0 goto IDLE stat */
/* send CMD1 */
tick_start = rt_tick_get();
while(1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, SEND_OP_COND, 0x00, 0x00, response_r1, response);
MSD_release_cs(msd->spi_device);
if((result == RT_EOK) && (response[0] == MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[info] It is MMC card!!!\r\n");
msd->card_type = MSD_CARD_TYPE_MMC;
break;
}
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(CARD_TRY_TIMES)))
{
MSD_DEBUG("[err] SD card goto IDLE mode timeout!\r\n");
result = RT_ETIMEOUT;
goto _exit;
}
} /* send CMD1 */
} /* try MMC */
}
else if(msd->card_type == MSD_CARD_TYPE_SD_V2_X)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, READ_OCR, 0x00, 0x00, response_r3, response);
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] It maybe SD2.0 But it is Not response to CMD58!\r\n");
goto _exit;
}
if((response[0] & 0xFE) != 0)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] It look CMD58 as illegal command so it is not SD card!\r\n");
result = RT_ERROR;
goto _exit;
}
MSD_release_cs(msd->spi_device);
OCR = response[1];
OCR = (OCR<<8) + response[2];
OCR = (OCR<<8) + response[3];
OCR = (OCR<<8) + response[4];
MSD_DEBUG("[info] OCR is 0x%08X\r\n", OCR);
if( 0 == (OCR & (0x1 << 15)))
{
MSD_DEBUG(("[err] SD 1.x But not surpport current voltage\r\n"));
result = RT_ERROR;
goto _exit;
}
/* --Send ACMD41 to make card ready */
tick_start = rt_tick_get();
/* try CMD55 + ACMD41 */
do
{
MSD_take_cs(msd->spi_device);
if(rt_tick_timeout(tick_start, rt_tick_from_millisecond(CARD_TRY_TIMES_ACMD41)))
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] SD Ver2.x or later try CMD55 + ACMD41 timeout!\r\n");
result = RT_ERROR;
goto _exit;
}
/* CMD55 APP_CMD */
result = _send_cmd(msd->spi_device, APP_CMD, 0x00, 0x65, response_r1, response);
// if((result != RT_EOK) || (response[0] == 0x01))
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
continue;
}
if((response[0] & 0xFE) != 0)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] Not SD ready!\r\n");
result = RT_ERROR;
goto _exit;
}
/* ACMD41 SD_SEND_OP_COND */
result = _send_cmd(msd->spi_device, SD_SEND_OP_COND, 0x40000000, 0x77, response_r1, response);
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] ACMD41 fail!\r\n");
result = RT_ERROR;
goto _exit;
}
if((response[0] & 0xFE) != 0)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[info] Not SD card4 , response : 0x%02X\r\n", response[0]);
// break;
}
}
while(response[0] != MSD_RESPONSE_NO_ERROR);
MSD_release_cs(msd->spi_device);
/* try CMD55 + ACMD41 */
/* --Read OCR again */
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, READ_OCR, 0x00, 0x00, response_r3, response);
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] It maybe SD2.0 But it is Not response to 2nd CMD58!\r\n");
goto _exit;
}
if((response[0] & 0xFE) != 0)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] It look 2nd CMD58 as illegal command so it is not SD card!\r\n");
result = RT_ERROR;
goto _exit;
}
MSD_release_cs(msd->spi_device);
OCR = response[1];
OCR = (OCR<<8) + response[2];
OCR = (OCR<<8) + response[3];
OCR = (OCR<<8) + response[4];
MSD_DEBUG("[info] OCR 2nd read is 0x%08X\r\n", OCR);
if((OCR & 0x40000000) != 0)
{
MSD_DEBUG("[info] It is SD2.0 SDHC Card!!!\r\n");
msd->card_type = MSD_CARD_TYPE_SD_SDHC;
}
else
{
MSD_DEBUG("[info] It is SD2.0 standard capacity Card!!!\r\n");
}
} /* MSD_CARD_TYPE_SD_V2_X */
else
{
MSD_DEBUG("[err] SD card type unkonw!\r\n");
result = RT_ERROR;
goto _exit;
}
} /* init SD card */
if(msd->card_type == MSD_CARD_TYPE_SD_SDHC)
{
dev->read = rt_msd_sdhc_read;
dev->write = rt_msd_sdhc_write;
}
else
{
dev->read = rt_msd_read;
dev->write = rt_msd_write;
}
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte 0xFF */
MSD_WriteByte(DUMMY);
/* set CRC */
{
MSD_release_cs(msd->spi_device);
MSD_take_cs(msd->spi_device);
#ifdef MSD_USE_CRC
result = _send_cmd(msd->spi_device, CRC_ON_OFF, 0x01, 0x83, response_r1, response);
#else
result = _send_cmd(msd->spi_device, CRC_ON_OFF, 0x00, 0x91, response_r1, response);
#endif
MSD_release_cs(msd->spi_device);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD59 CRC_ON_OFF fail! response : 0x%02X\r\n", response[0]);
result = RT_ERROR;
goto _exit;
}
} /* set CRC */
/* CMD16 SET_BLOCKLEN */
{
MSD_release_cs(msd->spi_device);
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, SET_BLOCKLEN, SECTOR_SIZE, 0x00, response_r1, response);
MSD_release_cs(msd->spi_device);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD16 SET_BLOCKLEN fail! response : 0x%02X\r\n", response[0]);
result = RT_ERROR;
goto _exit;
}
msd->geometry.block_size = SECTOR_SIZE;
msd->geometry.bytes_per_sector = SECTOR_SIZE;
}
return Status;
/* read CSD */
{
uint8_t CSD_buffer[MSD_CSD_LEN];
MSD_take_cs(msd->spi_device);
// result = _send_cmd(msd->spi_device, SEND_CSD, 0x00, 0xAF, response_r1, response);
result = _send_cmd(msd->spi_device, SEND_CSD, 0x00, 0x00, response_r1, response);
if(result != RT_EOK)
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] CMD9 SEND_CSD timeout!\r\n");
goto _exit;
}
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_release_cs(msd->spi_device);
MSD_DEBUG("[err] CMD9 SEND_CSD fail! response : 0x%02X\r\n", response[0]);
result = RT_ERROR;
goto _exit;
}
result = _read_block(msd->spi_device, CSD_buffer, MSD_CSD_LEN);
MSD_release_cs(msd->spi_device);
if(result != RT_EOK)
{
MSD_DEBUG("[err] read CSD fail!\r\n");
goto _exit;
}
/* Analyze CSD */
{
uint8_t CSD_STRUCTURE;
uint32_t C_SIZE;
uint32_t card_capacity;
uint8_t tmp8;
uint16_t tmp16;
uint32_t tmp32;
/* get CSD_STRUCTURE */
tmp8 = CSD_buffer[0] & 0xC0; /* 0b11000000 */
CSD_STRUCTURE = tmp8 >> 6;
/* MMC CSD Analyze. */
if(msd->card_type == MSD_CARD_TYPE_MMC)
{
uint8_t C_SIZE_MULT;
uint8_t READ_BL_LEN;
if(CSD_STRUCTURE > 2)
{
MSD_DEBUG("[err] bad CSD Version : %d\r\n", CSD_STRUCTURE);
result = RT_ERROR;
goto _exit;
}
if(CSD_STRUCTURE == 0)
{
MSD_DEBUG("[info] CSD version No. 1.0\r\n");
}
else if(CSD_STRUCTURE == 1)
{
MSD_DEBUG("[info] CSD version No. 1.1\r\n");
}
else if(CSD_STRUCTURE == 2)
{
MSD_DEBUG("[info] CSD version No. 1.2\r\n");
}
/* get TRAN_SPEED 8bit [103:96] */
tmp8 = CSD_buffer[3];
tmp8 &= 0x03; /* [2:0] transfer rate unit.*/
if(tmp8 == 0)
{
msd->max_clock = 100 * 1000; /* 0=100kbit/s. */
}
else if(tmp8 == 1)
{
msd->max_clock = 1 * 1000 * 1000; /* 1=1Mbit/s. */
}
else if(tmp8 == 2)
{
msd->max_clock = 10 * 1000 * 1000; /* 2=10Mbit/s. */
}
else if(tmp8 == 3)
{
msd->max_clock = 100 * 1000 * 1000; /* 3=100Mbit/s. */
}
if(tmp8 == 0)
{
MSD_DEBUG("[info] TRAN_SPEED: 0x%02X, %dkbit/s.\r\n", tmp8, msd->max_clock/1000);
}
else
{
MSD_DEBUG("[info] TRAN_SPEED: 0x%02X, %dMbit/s.\r\n", tmp8, msd->max_clock/1000/1000);
}
/* get READ_BL_LEN 4bit [83:80] */
tmp8 = CSD_buffer[5] & 0x0F; /* 0b00001111; */
READ_BL_LEN = tmp8; /* 4 bit */
MSD_DEBUG("[info] CSD : READ_BL_LEN : %d %dbyte\r\n", READ_BL_LEN, (1 << READ_BL_LEN));
/* get C_SIZE 12bit [73:62] */
tmp16 = CSD_buffer[6] & 0x03; /* get [73:72] 0b00000011 */
tmp16 = tmp16<<8;
tmp16 += CSD_buffer[7]; /* get [71:64] */
tmp16 = tmp16<<2;
tmp8 = CSD_buffer[8] & 0xC0; /* get [63:62] 0b11000000 */
tmp8 = tmp8>>6;
tmp16 = tmp16 + tmp8;
C_SIZE = tmp16; //12 bit
MSD_DEBUG("[info] CSD : C_SIZE : %d\r\n", C_SIZE);
/* get C_SIZE_MULT 3bit [49:47] */
tmp8 = CSD_buffer[9] & 0x03;//0b00000011;
tmp8 = tmp8<<1;
tmp8 = tmp8 + ((CSD_buffer[10] & 0x80/*0b10000000*/)>>7);
C_SIZE_MULT = tmp8; // 3 bit
MSD_DEBUG("[info] CSD : C_SIZE_MULT : %d\r\n", C_SIZE_MULT);
/* memory capacity = BLOCKNR * BLOCK_LEN */
/* BLOCKNR = (C_SIZE+1) * MULT */
/* MULT = 2^(C_SIZE_MULT+2) */
/* BLOCK_LEN = 2^READ_BL_LEN */
card_capacity = (1 << READ_BL_LEN) * ((C_SIZE + 1) * (1 << (C_SIZE_MULT+2)));
msd->geometry.sector_count = card_capacity / msd->geometry.bytes_per_sector;
MSD_DEBUG("[info] card capacity : %d Mbyte\r\n", card_capacity/(1024*1024));
}
else /* SD CSD Analyze. */
{
if(CSD_STRUCTURE == 0)
{
uint8_t C_SIZE_MULT;
uint8_t READ_BL_LEN;
MSD_DEBUG("[info] CSD Version 1.0\r\n");
/* get TRAN_SPEED 8bit [103:96] */
tmp8 = CSD_buffer[3];
if(tmp8 == 0x32)
{
msd->max_clock = 1000 * 1000 * 10; /* 10Mbit/s. */
}
else if(tmp8 == 0x5A)
{
msd->max_clock = 1000 * 1000 * 50; /* 50Mbit/s. */
}
else
{
msd->max_clock = 1000 * 1000 * 1; /* 1Mbit/s default. */
}
MSD_DEBUG("[info] TRAN_SPEED: 0x%02X, %dMbit/s.\r\n", tmp8, msd->max_clock/1000/1000);
/* get READ_BL_LEN 4bit [83:80] */
tmp8 = CSD_buffer[5] & 0x0F; /* 0b00001111; */
READ_BL_LEN = tmp8; /* 4 bit */
MSD_DEBUG("[info] CSD : READ_BL_LEN : %d %dbyte\r\n", READ_BL_LEN, (1 << READ_BL_LEN));
/* get C_SIZE 12bit [73:62] */
tmp16 = CSD_buffer[6] & 0x03; /* get [73:72] 0b00000011 */
tmp16 = tmp16<<8;
tmp16 += CSD_buffer[7]; /* get [71:64] */
tmp16 = tmp16<<2;
tmp8 = CSD_buffer[8] & 0xC0; /* get [63:62] 0b11000000 */
tmp8 = tmp8>>6;
tmp16 = tmp16 + tmp8;
C_SIZE = tmp16; //12 bit
MSD_DEBUG("[info] CSD : C_SIZE : %d\r\n", C_SIZE);
/* get C_SIZE_MULT 3bit [49:47] */
tmp8 = CSD_buffer[9] & 0x03;//0b00000011;
tmp8 = tmp8<<1;
tmp8 = tmp8 + ((CSD_buffer[10] & 0x80/*0b10000000*/)>>7);
C_SIZE_MULT = tmp8; // 3 bit
MSD_DEBUG("[info] CSD : C_SIZE_MULT : %d\r\n", C_SIZE_MULT);
/* memory capacity = BLOCKNR * BLOCK_LEN */
/* BLOCKNR = (C_SIZE+1) * MULT */
/* MULT = 2^(C_SIZE_MULT+2) */
/* BLOCK_LEN = 2^READ_BL_LEN */
card_capacity = (1 << READ_BL_LEN) * ((C_SIZE + 1) * (1 << (C_SIZE_MULT+2)));
msd->geometry.sector_count = card_capacity / msd->geometry.bytes_per_sector;
MSD_DEBUG("[info] card capacity : %d Mbyte\r\n", card_capacity/(1024*1024));
}
else if(CSD_STRUCTURE == 1)
{
MSD_DEBUG("[info] CSD Version 2.0\r\n");
/* get TRAN_SPEED 8bit [103:96] */
tmp8 = CSD_buffer[3];
if(tmp8 == 0x32)
{
msd->max_clock = 1000 * 1000 * 10; /* 10Mbit/s. */
}
else if(tmp8 == 0x5A)
{
msd->max_clock = 1000 * 1000 * 50; /* 50Mbit/s. */
}
else if(tmp8 == 0x0B)
{
msd->max_clock = 1000 * 1000 * 100; /* 100Mbit/s. */
/* UHS50 Card sets TRAN_SPEED to 0Bh (100Mbit/sec), */
/* for both SDR50 and DDR50 modes. */
}
else if(tmp8 == 0x2B)
{
msd->max_clock = 1000 * 1000 * 200; /* 200Mbit/s. */
/* UHS104 Card sets TRAN_SPEED to 2Bh (200Mbit/sec). */
}
else
{
msd->max_clock = 1000 * 1000 * 1; /* 1Mbit/s default. */
}
MSD_DEBUG("[info] TRAN_SPEED: 0x%02X, %dMbit/s.\r\n", tmp8, msd->max_clock/1000/1000);
/* get C_SIZE 22bit [69:48] */
tmp32 = CSD_buffer[7] & 0x3F; /* 0b00111111 */
tmp32 = tmp32<<8;
tmp32 += CSD_buffer[8];
tmp32 = tmp32<<8;
tmp32 += CSD_buffer[9];
C_SIZE = tmp32;
MSD_DEBUG("[info] CSD : C_SIZE : %d\r\n", C_SIZE);
/* memory capacity = (C_SIZE+1) * 512K byte */
card_capacity = (C_SIZE + 1) / 2; /* unit : Mbyte */
msd->geometry.sector_count = card_capacity * 1024; /* 1 Mbyte = 512 byte X 2048 */
MSD_DEBUG("[info] card capacity : %d.%d Gbyte\r\n", card_capacity/1024, (card_capacity%1024)*100/1024);
}
else
{
MSD_DEBUG("[err] bad CSD Version : %d\r\n", CSD_STRUCTURE);
result = RT_ERROR;
goto _exit;
}
} /* SD CSD Analyze. */
} /* Analyze CSD */
} /* read CSD */
/* config spi to high speed */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 */
cfg.max_hz = msd->max_clock;
rt_spi_configure(msd->spi_device, &cfg);
} /* config spi */
_exit:
MSD_release_cs(msd->spi_device);
rt_mutex_release(&(msd->spi_device->bus->lock));
return result;
}
/*******************************************************************************
* Function Name : MSD_GoIdleState
* Description : Put MSD in Idle state.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GoIdleState(void)
static rt_err_t rt_msd_open(rt_device_t dev, rt_uint16_t oflag)
{
int i;
/* MSD chip select low */
MSD_CS_LOW();
/* Send CMD0 (GO_IDLE_STATE) to put MSD in SPI mode */
MSD_SendCmd(MSD_GO_IDLE_STATE, 0, 0x95);
/* Wait for In Idle State Response (R1 Format) equal to 0x01 */
if (MSD_GetResponse(MSD_IN_IDLE_STATE))
{
/* No Idle State Response: return response failue */
return MSD_RESPONSE_FAILURE;
}
/*----------Activates the card initialization process-----------*/
do
{
/* MSD chip select high */
MSD_CS_HIGH();
/* Send Dummy byte 0xFF */
MSD_WriteByte(DUMMY);
for (i = 0; i < 0xfff; i++);
/* MSD chip select low */
MSD_CS_LOW();
for (i = 0; i < 0xfff; i++);
/* Send CMD1 (Activates the card process) until response equal to 0x0 */
MSD_SendCmd(MSD_SEND_OP_COND, 0, 0xFF);
/* Wait for no error Response (R1 Format) equal to 0x00 */
}
while (MSD_GetResponse(MSD_RESPONSE_NO_ERROR));
/* MSD chip select high */
MSD_CS_HIGH();
/* Send dummy byte 0xFF */
MSD_WriteByte(DUMMY);
return MSD_RESPONSE_NO_ERROR;
// struct msd_device * msd = (struct msd_device *)dev;
return RT_EOK;
}
/*******************************************************************************
* Function Name : MSD_WriteByte
* Description : Write a byte on the MSD.
* Input : Data: byte to send.
* Output : None
* Return : None.
*******************************************************************************/
u8 MSD_WriteByte(u8 Data)
static rt_err_t rt_msd_close(rt_device_t dev)
{
/* Wait until the transmit buffer is empty */
while (SPI_I2S_GetFlagStatus(MSD_SPI, SPI_I2S_FLAG_TXE) == RESET);
/* Send the byte */
SPI_I2S_SendData(MSD_SPI, Data);
/* Get the received data */
Data = SPI_I2S_ReceiveData(MSD_SPI);
return Data;
// struct msd_device * msd = (struct msd_device *)dev;
return RT_EOK;
}
/*******************************************************************************
* Function Name : MSD_ReadByte
* Description : Read a byte from the MSD.
* Input : None.
* Output : None
* Return : The received byte.
*******************************************************************************/
u8 MSD_ReadByte(void)
static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
u8 Data = 0;
struct msd_device * msd = (struct msd_device *)dev;
uint8_t response[MSD_RESPONSE_MAX_LEN];
rt_err_t result = RT_EOK;
result = MSD_take_owner(msd->spi_device);
if (result != RT_EOK)
{
goto _exit;
}
/* Wait until the transmit buffer is empty */
while (SPI_I2S_GetFlagStatus(MSD_SPI, SPI_I2S_FLAG_TXE) == RESET);
/* Send the byte */
SPI_I2S_SendData(MSD_SPI, DUMMY);
/* config spi to high speed */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 */
cfg.max_hz = msd->max_clock;
/* Wait until a data is received */
while (SPI_I2S_GetFlagStatus(MSD_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/* Get the received data */
Data = SPI_I2S_ReceiveData(MSD_SPI);
rt_spi_configure(msd->spi_device, &cfg);
} /* config spi */
/* Return the shifted data */
return Data;
/* SINGLE_BLOCK? */
if(size == 1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, READ_SINGLE_BLOCK, pos * msd->geometry.bytes_per_sector, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] read SINGLE_BLOCK #%d fail!\r\n", pos);
size = 0;
goto _exit;
}
result = _read_block(msd->spi_device, buffer, msd->geometry.bytes_per_sector);
if(result != RT_EOK)
{
MSD_DEBUG("[err] read SINGLE_BLOCK #%d fail!\r\n", pos);
size = 0;
}
}
else if(size > 1)
{
uint32_t i;
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, READ_MULTIPLE_BLOCK, pos * msd->geometry.bytes_per_sector, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] read READ_MULTIPLE_BLOCK #%d fail!\r\n", pos);
size = 0;
goto _exit;
}
for(i=0; i<size; i++)
{
result = _read_block(msd->spi_device,
(uint8_t *)buffer + msd->geometry.bytes_per_sector * i,
msd->geometry.bytes_per_sector);
if(result != RT_EOK)
{
MSD_DEBUG("[err] read READ_MULTIPLE_BLOCK #%d fail!\r\n", pos);
size = i;
break;
}
}
/* send CMD12 stop transfer */
result = _send_cmd(msd->spi_device, STOP_TRANSMISSION, 0x00, 0x00, response_r1b, response);
if(result != RT_EOK)
{
MSD_DEBUG("[err] read READ_MULTIPLE_BLOCK, send stop token fail!\r\n");
}
} /* READ_MULTIPLE_BLOCK */
_exit:
/* release and exit */
MSD_release_cs(msd->spi_device);
rt_mutex_release(&(msd->spi_device->bus->lock));
return size;
}
/*******************************************************************************
* Function Name : SPI_Config
* Description : Initializes the SPI and CS pins.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SPI_Config(void)
static rt_size_t rt_msd_sdhc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
uint32_t delay;
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
/* GPIOA and GPIOC Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
/* SPI Periph clock enable */
RCC_APB2PeriphClockCmd(MSD_RCC_SPI, ENABLE);
/* Configure SPI pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PA4 pin: CS pin, PC4 : SD Power */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* SPI Config */
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(MSD_SPI, &SPI_InitStructure);
/* SPI enable */
SPI_Cmd(MSD_SPI, ENABLE);
/* active SD card */
GPIO_ResetBits(GPIOC, GPIO_Pin_4);
for (delay = 0; delay < 0xfffff; delay ++);
}
struct msd_device * msd = (struct msd_device *)dev;
uint8_t response[MSD_RESPONSE_MAX_LEN];
rt_err_t result = RT_EOK;
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
result = MSD_take_owner(msd->spi_device);
/*
* RT-Thread SD Card Driver
* 2009-04-17 Bernard first version
* 2010-07-15 Modify read/write according new block driver interface
*/
#include <rtthread.h>
#include <dfs_fs.h>
static struct rt_device sdcard_device;
static struct dfs_partition part;
if (result != RT_EOK)
{
goto _exit;
}
#define SECTOR_SIZE 512
/* config spi to high speed */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 */
cfg.max_hz = msd->max_clock;
/* RT-Thread Device Driver Interface */
static rt_err_t rt_msd_init(rt_device_t dev)
{
sMSD_CSD MSD_csd;
MSD_GetCSDRegister(&MSD_csd);
rt_spi_configure(msd->spi_device, &cfg);
} /* config spi */
return RT_EOK;
/* SINGLE_BLOCK? */
if(size == 1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, READ_SINGLE_BLOCK, pos, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] read SINGLE_BLOCK #%d fail!\r\n", pos);
size = 0;
goto _exit;
}
result = _read_block(msd->spi_device, buffer, msd->geometry.bytes_per_sector);
if(result != RT_EOK)
{
MSD_DEBUG("[err] read SINGLE_BLOCK #%d fail!\r\n", pos);
size = 0;
}
}
else if(size > 1)
{
uint32_t i;
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, READ_MULTIPLE_BLOCK, pos, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] read READ_MULTIPLE_BLOCK #%d fail!\r\n", pos);
size = 0;
goto _exit;
}
for(i=0; i<size; i++)
{
result = _read_block(msd->spi_device,
(uint8_t *)buffer + msd->geometry.bytes_per_sector * i,
msd->geometry.bytes_per_sector);
if(result != RT_EOK)
{
MSD_DEBUG("[err] read READ_MULTIPLE_BLOCK #%d fail!\r\n", pos);
size = i;
break;
}
}
/* send CMD12 stop transfer */
result = _send_cmd(msd->spi_device, STOP_TRANSMISSION, 0x00, 0x00, response_r1b, response);
if(result != RT_EOK)
{
MSD_DEBUG("[err] read READ_MULTIPLE_BLOCK, send stop token fail!\r\n");
}
} /* READ_MULTIPLE_BLOCK */
_exit:
/* release and exit */
MSD_release_cs(msd->spi_device);
rt_mutex_release(&(msd->spi_device->bus->lock));
return size;
}
static rt_err_t rt_msd_open(rt_device_t dev, rt_uint16_t oflag)
static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
return RT_EOK;
}
struct msd_device * msd = (struct msd_device *)dev;
uint8_t response[MSD_RESPONSE_MAX_LEN];
rt_err_t result;
static rt_err_t rt_msd_close(rt_device_t dev)
{
return RT_EOK;
}
result = MSD_take_owner(msd->spi_device);
static rt_size_t rt_msd_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_uint8_t status;
rt_uint32_t i;
status = MSD_RESPONSE_NO_ERROR;
// rt_kprintf("read: 0x%x, size %d\n", pos, size);
/* read all sectors */
for (i = 0; i < size; i ++)
{
status = MSD_ReadBlock((rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE),
(part.offset + pos + i)* SECTOR_SIZE, SECTOR_SIZE);
if (status != MSD_RESPONSE_NO_ERROR)
{
rt_kprintf("sd card read failed\n");
return 0;
}
}
if (status == MSD_RESPONSE_NO_ERROR) return size;
rt_kprintf("read failed: %d\n", status);
return 0;
if (result != RT_EOK)
{
MSD_DEBUG("[err] get SPI owner fail!\r\n");
goto _exit;
}
/* config spi to high speed */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 */
cfg.max_hz = msd->max_clock;
rt_spi_configure(msd->spi_device, &cfg);
} /* config spi */
/* SINGLE_BLOCK? */
if(size == 1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, WRITE_BLOCK, pos * msd->geometry.bytes_per_sector, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD WRITE_BLOCK fail!\r\n");
size = 0;
goto _exit;
}
result = _write_block(msd->spi_device, buffer, msd->geometry.bytes_per_sector, MSD_TOKEN_WRITE_SINGLE_START);
if(result != RT_EOK)
{
MSD_DEBUG("[err] write SINGLE_BLOCK #%d fail!\r\n", pos);
size = 0;
}
}
else if(size > 1)
{
struct rt_spi_message message;
uint32_t i;
MSD_take_cs(msd->spi_device);
#ifdef MSD_USE_PRE_ERASED
if(msd->card_type != MSD_CARD_TYPE_MMC)
{
/* CMD55 APP_CMD */
result = _send_cmd(msd->spi_device, APP_CMD, 0x00, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD55 APP_CMD fail!\r\n");
size = 0;
goto _exit;
}
/* ACMD23 Pre-erased */
result = _send_cmd(msd->spi_device, SET_WR_BLK_ERASE_COUNT, size, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] ACMD23 SET_BLOCK_COUNT fail!\r\n");
size = 0;
goto _exit;
}
}
#endif
result = _send_cmd(msd->spi_device, WRITE_MULTIPLE_BLOCK, pos * msd->geometry.bytes_per_sector, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD WRITE_MULTIPLE_BLOCK fail!\r\n");
size = 0;
goto _exit;
}
/* write all block */
for(i=0; i<size; i++)
{
result = _write_block(msd->spi_device,
(const uint8_t *)buffer + msd->geometry.bytes_per_sector * i,
msd->geometry.bytes_per_sector,
MSD_TOKEN_WRITE_MULTIPLE_START);
if(result != RT_EOK)
{
MSD_DEBUG("[err] write SINGLE_BLOCK #%d fail!\r\n", pos);
size = i;
break;
}
} /* write all block */
/* send stop token */
{
uint8_t send_buffer[18];
rt_memset(send_buffer, DUMMY, sizeof(send_buffer));
send_buffer[sizeof(send_buffer) - 1] = MSD_TOKEN_WRITE_MULTIPLE_STOP;
/* initial message */
message.send_buf = send_buffer;
message.recv_buf = RT_NULL;
message.length = sizeof(send_buffer);
message.cs_take = message.cs_release = 0;
/* transfer message */
msd->spi_device->bus->ops->xfer(msd->spi_device, &message);
}
/* wait ready */
result = _wait_ready(msd->spi_device);
if(result != RT_EOK)
{
MSD_DEBUG("[warning] wait WRITE_MULTIPLE_BLOCK stop token ready timeout!\r\n");
}
} /* size > 1 */
_exit:
/* release and exit */
MSD_release_cs(msd->spi_device);
rt_mutex_release(&(msd->spi_device->bus->lock));
return size;
}
static rt_size_t rt_msd_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
static rt_size_t rt_msd_sdhc_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_uint8_t status;
rt_uint32_t i;
status = MSD_RESPONSE_NO_ERROR;
// rt_kprintf("write: 0x%x, size %d\n", pos, size);
/* write all sectors */
for (i = 0; i < size; i ++)
{
status = MSD_WriteBuffer((rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE),
(part.offset + pos + i)* SECTOR_SIZE, SECTOR_SIZE);
if (status != MSD_RESPONSE_NO_ERROR)
{
rt_kprintf("sd card write failed\n");
return 0;
}
}
if (status == MSD_RESPONSE_NO_ERROR) return size;
rt_kprintf("write failed: %d\n", status);
return 0;
struct msd_device * msd = (struct msd_device *)dev;
uint8_t response[MSD_RESPONSE_MAX_LEN];
rt_err_t result;
result = MSD_take_owner(msd->spi_device);
if (result != RT_EOK)
{
goto _exit;
}
/* config spi to high speed */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible Modes 0 */
cfg.max_hz = msd->max_clock;
rt_spi_configure(msd->spi_device, &cfg);
} /* config spi */
/* SINGLE_BLOCK? */
if(size == 1)
{
MSD_take_cs(msd->spi_device);
result = _send_cmd(msd->spi_device, WRITE_BLOCK, pos, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD WRITE_BLOCK fail!\r\n");
size = 0;
goto _exit;
}
result = _write_block(msd->spi_device, buffer, msd->geometry.bytes_per_sector, MSD_TOKEN_WRITE_SINGLE_START);
if(result != RT_EOK)
{
MSD_DEBUG("[err] write SINGLE_BLOCK #%d fail!\r\n", pos);
size = 0;
}
}
else if(size > 1)
{
struct rt_spi_message message;
uint32_t i;
MSD_take_cs(msd->spi_device);
#ifdef MSD_USE_PRE_ERASED
/* CMD55 APP_CMD */
result = _send_cmd(msd->spi_device, APP_CMD, 0x00, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD55 APP_CMD fail!\r\n");
size = 0;
goto _exit;
}
/* ACMD23 Pre-erased */
result = _send_cmd(msd->spi_device, SET_WR_BLK_ERASE_COUNT, size, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] ACMD23 SET_BLOCK_COUNT fail!\r\n");
size = 0;
goto _exit;
}
#endif
result = _send_cmd(msd->spi_device, WRITE_MULTIPLE_BLOCK, pos, 0x00, response_r1, response);
if((result != RT_EOK) || (response[0] != MSD_RESPONSE_NO_ERROR))
{
MSD_DEBUG("[err] CMD WRITE_MULTIPLE_BLOCK fail!\r\n");
size = 0;
goto _exit;
}
/* write all block */
for(i=0; i<size; i++)
{
result = _write_block(msd->spi_device,
(const uint8_t *)buffer + msd->geometry.bytes_per_sector * i,
msd->geometry.bytes_per_sector,
MSD_TOKEN_WRITE_MULTIPLE_START);
if(result != RT_EOK)
{
MSD_DEBUG("[err] write MULTIPLE_BLOCK #%d fail!\r\n", pos);
size = i;
break;
}
} /* write all block */
/* send stop token */
{
uint8_t send_buffer[18];
rt_memset(send_buffer, DUMMY, sizeof(send_buffer));
send_buffer[sizeof(send_buffer) - 1] = MSD_TOKEN_WRITE_MULTIPLE_STOP;
/* initial message */
message.send_buf = send_buffer;
message.recv_buf = RT_NULL;
message.length = sizeof(send_buffer);
message.cs_take = message.cs_release = 0;
/* transfer message */
msd->spi_device->bus->ops->xfer(msd->spi_device, &message);
}
result = _wait_ready(msd->spi_device);
if(result != RT_EOK)
{
MSD_DEBUG("[warning] wait WRITE_MULTIPLE_BLOCK stop token ready timeout!\r\n");
}
} /* size > 1 */
_exit:
/* release and exit */
MSD_release_cs(msd->spi_device);
rt_mutex_release(&(msd->spi_device->bus->lock));
return size;
}
static rt_err_t rt_msd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
struct msd_device * msd = (struct msd_device *)dev;
RT_ASSERT(dev != RT_NULL);
return RT_EOK;
if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
{
struct rt_device_blk_geometry *geometry;
geometry = (struct rt_device_blk_geometry *)args;
if (geometry == RT_NULL) return -RT_ERROR;
geometry->bytes_per_sector = msd->geometry.bytes_per_sector;
geometry->block_size = msd->geometry.block_size;
geometry->sector_count = msd->geometry.sector_count;
}
return RT_EOK;
}
void rt_hw_msd_init()
rt_err_t msd_init(const char * sd_device_name, const char * spi_device_name)
{
if (MSD_Init() == MSD_RESPONSE_NO_ERROR)
{
rt_uint8_t status;
rt_uint8_t *sector;
/* register sdcard device */
sdcard_device.init = rt_msd_init;
sdcard_device.open = rt_msd_open;
sdcard_device.close = rt_msd_close;
sdcard_device.read = rt_msd_read;
sdcard_device.write = rt_msd_write;
sdcard_device.control = rt_msd_control;
/* no private */
sdcard_device.user_data = RT_NULL;
/* get the first sector to read partition table */
sector = (rt_uint8_t*) rt_malloc (512);
if (sector == RT_NULL)
{
rt_kprintf("allocate partition sector buffer failed\n");
return;
}
status = MSD_ReadBlock(sector, 0, 512);
if (status == MSD_RESPONSE_NO_ERROR)
{
/* get the first partition */
status = dfs_filesystem_get_partition(&part, sector, 0);
if (status != RT_EOK)
{
/* there is no partition table */
part.offset = 0;
part.size = 0;
}
}
else
{
/* there is no partition table */
part.offset = 0;
part.size = 0;
}
/* release sector buffer */
rt_free(sector);
rt_device_register(&sdcard_device, "sd0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
}
else
{
rt_kprintf("sdcard init failed\n");
}
rt_err_t result = RT_EOK;
struct rt_spi_device * spi_device;
spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
if(spi_device == RT_NULL)
{
MSD_DEBUG("spi device %s not found!\r\n", spi_device_name);
return -RT_ENOSYS;
}
rt_memset(&_msd_device, 0, sizeof(_msd_device));
_msd_device.spi_device = spi_device;
/* register sdcard device */
_msd_device.parent.type = RT_Device_Class_Block;
_msd_device.geometry.bytes_per_sector = 0;
_msd_device.geometry.sector_count = 0;
_msd_device.geometry.block_size = 0;
_msd_device.parent.init = rt_msd_init;
_msd_device.parent.open = rt_msd_open;
_msd_device.parent.close = rt_msd_close;
_msd_device.parent.read = RT_NULL;
_msd_device.parent.write = RT_NULL;
_msd_device.parent.control = rt_msd_control;
/* no private, no callback */
_msd_device.parent.user_data = RT_NULL;
_msd_device.parent.rx_indicate = RT_NULL;
_msd_device.parent.tx_complete = RT_NULL;
result = rt_device_register(&_msd_device.parent, sd_device_name,
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
return result;
}
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : msd.h
* Author : MCD Application Team
* Version : V2.1
* Date : 05/30/2008
* Description : Header for msd.c file.
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MSD_H
#define __MSD_H
/* Includes ------------------------------------------------------------------*/
#include <stm32f10x.h>
/* Private define ------------------------------------------------------------*/
/* Block Size */
#define BLOCK_SIZE 512
/* Dummy byte */
#define DUMMY 0xFF
/*
* File : msd.h
* SPI mode SD Card Driver
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-04-17 Bernard first version.
*/
#ifndef MSD_H_INCLUDED
#define MSD_H_INCLUDED
#include <stdint.h>
#include <drivers/spi.h>
/* SD command (SPI mode) */
#define GO_IDLE_STATE 0 /* CMD0 R1 */
#define SEND_OP_COND 1 /* CMD1 R1 */
#define SWITCH_FUNC 6 /* CMD6 R1 */
#define SEND_IF_COND 8 /* CMD8 R7 */
#define SEND_CSD 9 /* CMD9 R1 */
#define SEND_CID 10 /* CMD10 R1 */
#define STOP_TRANSMISSION 12 /* CMD12 R1B */
#define SEND_STATUS 13 /* CMD13 R2 */
#define SET_BLOCKLEN 16 /* CMD16 R1 */
#define READ_SINGLE_BLOCK 17 /* CMD17 R1 */
#define READ_MULTIPLE_BLOCK 18 /* CMD18 R1 */
#define WRITE_BLOCK 24 /* CMD24 R1 */
#define WRITE_MULTIPLE_BLOCK 25 /* CMD25 R1 */
#define PROGRAM_CSD 27 /* CMD27 R1 */
#define SET_WRITE_PROT 28 /* CMD28 R1B */
#define CLR_WRITE_PROT 29 /* CMD29 R1B */
#define SEND_WRITE_PROT 30 /* CMD30 R1 */
#define ERASE_WR_BLK_START_ADDR 32 /* CMD32 R1 */
#define ERASE_WR_BLK_END_ADDR 33 /* CMD33 R1 */
#define ERASE 38 /* CMD38 R1B */
#define LOCK_UNLOCK 42 /* CMD42 R1 */
#define APP_CMD 55 /* CMD55 R1 */
#define GEN_CMD 56 /* CMD56 R1 */
#define READ_OCR 58 /* CMD58 R3 */
#define CRC_ON_OFF 59 /* CMD59 R1 */
/* Application-Specific Command */
#define SD_STATUS 13 /* ACMD13 R2 */
#define SEND_NUM_WR_BLOCKS 22 /* ACMD22 R1 */
#define SET_WR_BLK_ERASE_COUNT 23 /* ACMD23 R1 */
#define SD_SEND_OP_COND 41 /* ACMD41 R1 */
#define SET_CLR_CARD_DETECT 42 /* ACMD42 R1 */
#define SEND_SCR 51 /* ACMD51 R1 */
/* Start Data tokens */
/* Tokens (necessary because at nop/idle (and CS active) only 0xff is on the data/command line) */
#define MSD_START_DATA_SINGLE_BLOCK_READ 0xFE /* Data token start byte, Start Single Block Read */
#define MSD_START_DATA_MULTIPLE_BLOCK_READ 0xFE /* Data token start byte, Start Multiple Block Read */
#define MSD_START_DATA_SINGLE_BLOCK_WRITE 0xFE /* Data token start byte, Start Single Block Write */
#define MSD_START_DATA_MULTIPLE_BLOCK_WRITE 0xFD /* Data token start byte, Start Multiple Block Write */
#define MSD_STOP_DATA_MULTIPLE_BLOCK_WRITE 0xFD /* Data toke stop byte, Stop Multiple Block Write */
#define MSD_TOKEN_READ_START 0xFE /* Data token start byte, Start Single Block Read */
#define MSD_TOKEN_WRITE_SINGLE_START 0xFE /* Data token start byte, Start Single Block Write */
/* MSD functions return */
#define MSD_SUCCESS 0x00
#define MSD_FAIL 0xFF
#define MSD_TOKEN_WRITE_MULTIPLE_START 0xFC /* Data token start byte, Start Multiple Block Write */
#define MSD_TOKEN_WRITE_MULTIPLE_STOP 0xFD /* Data toke stop byte, Stop Multiple Block Write */
/* MSD reponses and error flags */
#define MSD_RESPONSE_NO_ERROR 0x00
#define MSD_IN_IDLE_STATE 0x01
#define MSD_ERASE_RESET 0x02
#define MSD_ILLEGAL_COMMAND 0x04
#define MSD_COM_CRC_ERROR 0x08
#define MSD_ERASE_SEQUENCE_ERROR 0x10
#define MSD_ADDRESS_ERROR 0x20
#define MSD_PARAMETER_ERROR 0x40
#define MSD_RESPONSE_FAILURE 0xFF
#define MSD_RESPONSE_NO_ERROR 0x00
#define MSD_IN_IDLE_STATE 0x01
#define MSD_ERASE_RESET 0x02
#define MSD_ILLEGAL_COMMAND 0x04
#define MSD_COM_CRC_ERROR 0x08
#define MSD_ERASE_SEQUENCE_ERROR 0x10
#define MSD_ADDRESS_ERROR 0x20
#define MSD_PARAMETER_ERROR 0x40
#define MSD_RESPONSE_FAILURE 0xFF
/* Data response error */
#define MSD_DATA_OK 0x05
#define MSD_DATA_CRC_ERROR 0x0B
#define MSD_DATA_WRITE_ERROR 0x0D
#define MSD_DATA_OTHER_ERROR 0xFF
/* Commands: CMDxx = CMD-number | 0x40 */
#define MSD_GO_IDLE_STATE 0 /* CMD0=0x40 */
#define MSD_SEND_OP_COND 1 /* CMD1=0x41 */
#define MSD_SEND_CSD 9 /* CMD9=0x49 */
#define MSD_SEND_CID 10 /* CMD10=0x4A */
#define MSD_STOP_TRANSMISSION 12 /* CMD12=0x4C */
#define MSD_SEND_STATUS 13 /* CMD13=0x4D */
#define MSD_SET_BLOCKLEN 16 /* CMD16=0x50 */
#define MSD_READ_SINGLE_BLOCK 17 /* CMD17=0x51 */
#define MSD_READ_MULTIPLE_BLOCK 18 /* CMD18=0x52 */
#define MSD_SET_BLOCK_COUNT 23 /* CMD23=0x57 */
#define MSD_WRITE_BLOCK 24 /* CMD24=0x58 */
#define MSD_WRITE_MULTIPLE_BLOCK 25 /* CMD25=0x59 */
#define MSD_PROGRAM_CSD 27 /* CMD27=0x5B */
#define MSD_SET_WRITE_PROT 28 /* CMD28=0x5C */
#define MSD_CLR_WRITE_PROT 29 /* CMD29=0x5D */
#define MSD_SEND_WRITE_PROT 30 /* CMD30=0x5E */
#define MSD_TAG_SECTOR_START 32 /* CMD32=0x60 */
#define MSD_TAG_SECTOR_END 33 /* CMD33=0x61 */
#define MSD_UNTAG_SECTOR 34 /* CMD34=0x62 */
#define MSD_TAG_ERASE_GROUP_START 35 /* CMD35=0x63 */
#define MSD_TAG_ERASE_GROUP_END 36 /* CMD36=0x64 */
#define MSD_UNTAG_ERASE_GROUP 37 /* CMD37=0x65 */
#define MSD_ERASE 38 /* CMD38=0x66 */
#define MSD_READ_OCR 39 /* CMD39=0x67 */
#define MSD_CRC_ON_OFF 40 /* CMD40=0x68 */
/* Exported types ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
typedef struct _MSD_CSD /*Card Specific Data*/
#define MSD_DATA_OK 0x05
#define MSD_DATA_CRC_ERROR 0x0B
#define MSD_DATA_WRITE_ERROR 0x0D
#define MSD_DATA_OTHER_ERROR 0xFF
#define MSD_DATA_RESPONSE_MASK 0x1F
#define MSD_GET_DATA_RESPONSE(res) (res & MSD_DATA_RESPONSE_MASK)
#define MSD_CMD_LEN 6 /**< command, arg and crc. */
#define MSD_RESPONSE_MAX_LEN 5 /**< response max len */
#define MSD_CSD_LEN 16 /**< SD crad CSD register len */
#define SECTOR_SIZE 512 /**< sector size, default 512byte */
/* card try timeout, unit: ms */
#define CARD_TRY_TIMES 3000
#define CARD_TRY_TIMES_ACMD41 800
#define CARD_WAIT_TOKEN_TIMES 800
#define MSD_USE_PRE_ERASED /**< id define MSD_USE_PRE_ERASED, before CMD25, send ACMD23 */
/**
* SD/MMC card type
*/
typedef enum
{
vu8 CSDStruct; /* CSD structure */
vu8 SysSpecVersion; /* System specification version */
vu8 Reserved1; /* Reserved */
vu8 TAAC; /* Data read access-time 1 */
vu8 NSAC; /* Data read access-time 2 in CLK cycles */
vu8 MaxBusClkFrec; /* Max. bus clock frequency */
vu16 CardComdClasses; /* Card command classes */
vu8 RdBlockLen; /* Max. read data block length */
vu8 PartBlockRead; /* Partial blocks for read allowed */
vu8 WrBlockMisalign; /* Write block misalignment */
vu8 RdBlockMisalign; /* Read block misalignment */
vu8 DSRImpl; /* DSR implemented */
vu8 Reserved2; /* Reserved */
vu16 DeviceSize; /* Device Size */
vu8 MaxRdCurrentVDDMin; /* Max. read current @ VDD min */
vu8 MaxRdCurrentVDDMax; /* Max. read current @ VDD max */
vu8 MaxWrCurrentVDDMin; /* Max. write current @ VDD min */
vu8 MaxWrCurrentVDDMax; /* Max. write current @ VDD max */
vu8 DeviceSizeMul; /* Device size multiplier */
vu8 EraseGrSize; /* Erase group size */
vu8 EraseGrMul; /* Erase group size multiplier */
vu8 WrProtectGrSize; /* Write protect group size */
vu8 WrProtectGrEnable; /* Write protect group enable */
vu8 ManDeflECC; /* Manufacturer default ECC */
vu8 WrSpeedFact; /* Write speed factor */
vu8 MaxWrBlockLen; /* Max. write data block length */
vu8 WriteBlockPaPartial; /* Partial blocks for write allowed */
vu8 Reserved3; /* Reserded */
vu8 ContentProtectAppli; /* Content protection application */
vu8 FileFormatGrouop; /* File format group */
vu8 CopyFlag; /* Copy flag (OTP) */
vu8 PermWrProtect; /* Permanent write protection */
vu8 TempWrProtect; /* Temporary write protection */
vu8 FileFormat; /* File Format */
vu8 ECC; /* ECC code */
vu8 msd_CRC; /* CRC */
vu8 Reserved4; /* always 1*/
}
sMSD_CSD;
typedef struct _MSD_CID /*Card Identification Data*/
MSD_CARD_TYPE_UNKNOWN = 0, /**< unknown */
MSD_CARD_TYPE_MMC, /**< MultiMedia Card */
MSD_CARD_TYPE_SD_V1_X, /**< Ver 1.X Standard Capacity SD Memory Card */
MSD_CARD_TYPE_SD_V2_X, /**< Ver 2.00 or later Standard Capacity SD Memory Card */
MSD_CARD_TYPE_SD_SDHC, /**< High Capacity SD Memory Card */
MSD_CARD_TYPE_SD_SDXC, /**< later Extended Capacity SD Memory Card */
}msd_card_type;
typedef enum
{
vu8 ManufacturerID; /* ManufacturerID */
vu16 OEM_AppliID; /* OEM/Application ID */
vu32 ProdName1; /* Product Name part1 */
vu8 ProdName2; /* Product Name part2*/
vu8 ProdRev; /* Product Revision */
vu32 ProdSN; /* Product Serial Number */
vu8 Reserved1; /* Reserved1 */
vu16 ManufactDate; /* Manufacturing Date */
vu8 msd_CRC; /* CRC */
vu8 Reserved2; /* always 1*/
}
sMSD_CID;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*----- High layer function -----*/
u8 MSD_Init(void);
u8 MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);
u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);
u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite);
u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead);
u8 MSD_GetCSDRegister(sMSD_CSD* MSD_csd);
u8 MSD_GetCIDRegister(sMSD_CID* MSD_cid);
/*----- Medium layer function -----*/
void MSD_SendCmd(u8 Cmd, u32 Arg, u8 Crc);
u8 MSD_GetResponse(u8 Response);
u8 MSD_GetDataResponse(void);
u8 MSD_GoIdleState(void);
u16 MSD_GetStatus(void);
/*----- Low layer function -----*/
u8 MSD_WriteByte(u8 byte);
u8 MSD_ReadByte(void);
#endif /* __MSD_H */
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
response_type_unknown = 0,
response_r1,
response_r1b,
response_r2,
response_r3,
response_r4,
response_r5,
response_r7,
}response_type;
struct msd_device
{
struct rt_device parent; /**< RT-Thread device struct */
struct rt_device_blk_geometry geometry; /**< sector size, sector count */
struct rt_spi_device * spi_device; /**< SPI interface */
msd_card_type card_type; /**< card type: MMC SD1.x SD2.0 SDHC SDXC */
uint32_t max_clock; /**< MAX SPI clock */
};
extern rt_err_t msd_init(const char * sd_device_name, const char * spi_device_name);
#endif // MSD_H_INCLUDED
......@@ -5,18 +5,98 @@
#include "stm32_eth.h"
#endif /* RT_USING_LWIP */
#ifdef RT_USING_SPI
#include "rt_stm32f10x_spi.h"
#if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT)
#include "msd.h"
#endif /* RT_USING_DFS */
/*
* SPI1_MOSI: PA7
* SPI1_MISO: PA6
* SPI1_SCK : PA5
*
* CS0: PA4 SD card.
*/
static void rt_hw_spi_init(void)
{
#ifdef RT_USING_SPI1
/* register spi bus */
{
static struct stm32_spi_bus stm32_spi;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,
ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
stm32_spi_register(SPI1, &stm32_spi, "spi1");
}
/* attach cs */
{
static struct rt_spi_device spi_device;
static struct stm32_spi_cs spi_cs;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/* spi21: PG10 */
spi_cs.GPIOx = GPIOA;
spi_cs.GPIO_Pin = GPIO_Pin_4;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = spi_cs.GPIO_Pin;
GPIO_SetBits(spi_cs.GPIOx, spi_cs.GPIO_Pin);
GPIO_Init(spi_cs.GPIOx, &GPIO_InitStructure);
rt_spi_bus_attach_device(&spi_device, "spi10", "spi1", (void*)&spi_cs);
}
#endif /* RT_USING_SPI1 */
}
#endif /* RT_USING_SPI */
void rt_platform_init(void)
{
#ifdef RT_USING_LWIP
/* initialize eth interface */
rt_hw_stm32_eth_init();
#endif /* RT_USING_LWIP */
#ifdef RT_USING_SPI
rt_hw_spi_init();
#if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT)
/* init sdcard driver */
{
extern void rt_hw_msd_init(void);
rt_hw_msd_init();
GPIO_InitTypeDef GPIO_InitStructure;
/* PC4 : SD Power */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* SD card power on. */
GPIO_ResetBits(GPIOC, GPIO_Pin_4);
rt_thread_delay(2);
msd_init("sd0", "spi10");
}
#endif /* RT_USING_DFS && RT_USING_DFS_ELMFAT */
#endif // RT_USING_SPI
#ifdef RT_USING_LWIP
/* initialize eth interface */
rt_hw_stm32_eth_init();
#endif /* RT_USING_LWIP */
}
#include "rt_stm32f10x_spi.h"
static rt_err_t configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration);
static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message);
static struct rt_spi_ops stm32_spi_ops =
{
configure,
xfer
};
#ifdef USING_SPI1
static struct stm32_spi_bus stm32_spi_bus_1;
#endif /* #ifdef USING_SPI1 */
#ifdef USING_SPI2
static struct stm32_spi_bus stm32_spi_bus_2;
#endif /* #ifdef USING_SPI2 */
#ifdef USING_SPI3
static struct stm32_spi_bus stm32_spi_bus_3;
#endif /* #ifdef USING_SPI3 */
//------------------ DMA ------------------
#ifdef SPI_USE_DMA
static uint8_t dummy = 0xFF;
#endif
#ifdef SPI_USE_DMA
static void DMA_Configuration(struct stm32_spi_bus * stm32_spi_bus, const void * send_addr, void * recv_addr, rt_size_t size)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_ClearFlag(stm32_spi_bus->DMA_Channel_RX_FLAG_TC
| stm32_spi_bus->DMA_Channel_RX_FLAG_TE
| stm32_spi_bus->DMA_Channel_TX_FLAG_TC
| stm32_spi_bus->DMA_Channel_TX_FLAG_TE);
/* RX channel configuration */
DMA_Cmd(stm32_spi_bus->DMA_Channel_RX, DISABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(stm32_spi_bus->SPI->DR));
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_BufferSize = size;
if(recv_addr != RT_NULL)
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32) recv_addr;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
}
else
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32) (&dummy);
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
}
DMA_Init(stm32_spi_bus->DMA_Channel_RX, &DMA_InitStructure);
DMA_Cmd(stm32_spi_bus->DMA_Channel_RX, ENABLE);
/* TX channel configuration */
DMA_Cmd(stm32_spi_bus->DMA_Channel_TX, DISABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(stm32_spi_bus->SPI->DR));
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_BufferSize = size;
if(send_addr != RT_NULL)
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)send_addr;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
}
else
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(&dummy);;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
}
DMA_Init(stm32_spi_bus->DMA_Channel_TX, &DMA_InitStructure);
DMA_Cmd(stm32_spi_bus->DMA_Channel_TX, ENABLE);
}
#endif
rt_inline uint16_t get_spi_BaudRatePrescaler(rt_uint32_t max_hz)
{
uint16_t SPI_BaudRatePrescaler;
/* STM32F10x SPI MAX 18Mhz */
if(max_hz >= SystemCoreClock/2 && SystemCoreClock/2 <= 18000000)
{
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
}
else if(max_hz >= SystemCoreClock/4)
{
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
}
else if(max_hz >= SystemCoreClock/8)
{
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
}
else if(max_hz >= SystemCoreClock/16)
{
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
}
else if(max_hz >= SystemCoreClock/32)
{
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
}
else if(max_hz >= SystemCoreClock/64)
{
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
}
else if(max_hz >= SystemCoreClock/128)
{
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
}
else
{
/* min prescaler 256 */
SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
}
return SPI_BaudRatePrescaler;
}
static rt_err_t configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration)
{
struct stm32_spi_bus * stm32_spi_bus = (struct stm32_spi_bus *)device->bus;
SPI_InitTypeDef SPI_InitStructure;
SPI_StructInit(&SPI_InitStructure);
/* data_width */
if(configuration->data_width <= 8)
{
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
}
else if(configuration->data_width <= 16)
{
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
}
else
{
return RT_EIO;
}
/* baudrate */
SPI_InitStructure.SPI_BaudRatePrescaler = get_spi_BaudRatePrescaler(configuration->max_hz);
/* CPOL */
if(configuration->mode & RT_SPI_CPOL)
{
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
}
else
{
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
}
/* CPHA */
if(configuration->mode & RT_SPI_CPHA)
{
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
}
else
{
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
}
/* MSB or LSB */
if(configuration->mode & RT_SPI_MSB)
{
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
}
else
{
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
}
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
/* init SPI */
SPI_I2S_DeInit(stm32_spi_bus->SPI);
SPI_Init(stm32_spi_bus->SPI, &SPI_InitStructure);
/* Enable SPI_MASTER */
SPI_Cmd(stm32_spi_bus->SPI, ENABLE);
SPI_CalculateCRC(stm32_spi_bus->SPI, DISABLE);
return RT_EOK;
};
static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message)
{
struct stm32_spi_bus * stm32_spi_bus = (struct stm32_spi_bus *)device->bus;
struct rt_spi_configuration * config = &device->config;
SPI_TypeDef * SPI = stm32_spi_bus->SPI;
struct stm32_spi_cs * stm32_spi_cs = device->parent.user_data;
rt_uint32_t size = message->length;
/* take CS */
if(message->cs_take)
{
GPIO_ResetBits(stm32_spi_cs->GPIOx, stm32_spi_cs->GPIO_Pin);
}
#ifdef SPI_USE_DMA
if(message->length > 32)
{
if(config->data_width <= 8)
{
DMA_Configuration(stm32_spi_bus, message->send_buf, message->recv_buf, message->length);
SPI_I2S_DMACmd(SPI, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
while (DMA_GetFlagStatus(stm32_spi_bus->DMA_Channel_RX_FLAG_TC) == RESET
|| DMA_GetFlagStatus(stm32_spi_bus->DMA_Channel_TX_FLAG_TC) == RESET);
SPI_I2S_DMACmd(SPI, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, DISABLE);
}
// rt_memcpy(buffer,_spi_flash_buffer,DMA_BUFFER_SIZE);
// buffer += DMA_BUFFER_SIZE;
}
else
#endif
{
if(config->data_width <= 8)
{
const rt_uint8_t * send_ptr = message->send_buf;
rt_uint8_t * recv_ptr = message->recv_buf;
while(size--)
{
rt_uint8_t data = 0xFF;
if(send_ptr != RT_NULL)
{
data = *send_ptr++;
}
//Wait until the transmit buffer is empty
while (SPI_I2S_GetFlagStatus(SPI, SPI_I2S_FLAG_TXE) == RESET);
// Send the byte
SPI_I2S_SendData(SPI, data);
//Wait until a data is received
while (SPI_I2S_GetFlagStatus(SPI, SPI_I2S_FLAG_RXNE) == RESET);
// Get the received data
data = SPI_I2S_ReceiveData(SPI);
if(recv_ptr != RT_NULL)
{
*recv_ptr++ = data;
}
}
}
else if(config->data_width <= 16)
{
const rt_uint16_t * send_ptr = message->send_buf;
rt_uint16_t * recv_ptr = message->recv_buf;
while(size--)
{
rt_uint16_t data = 0xFF;
if(send_ptr != RT_NULL)
{
data = *send_ptr++;
}
//Wait until the transmit buffer is empty
while (SPI_I2S_GetFlagStatus(SPI, SPI_I2S_FLAG_TXE) == RESET);
// Send the byte
SPI_I2S_SendData(SPI, data);
//Wait until a data is received
while (SPI_I2S_GetFlagStatus(SPI, SPI_I2S_FLAG_RXNE) == RESET);
// Get the received data
data = SPI_I2S_ReceiveData(SPI);
if(recv_ptr != RT_NULL)
{
*recv_ptr++ = data;
}
}
}
}
/* release CS */
if(message->cs_release)
{
GPIO_SetBits(stm32_spi_cs->GPIOx, stm32_spi_cs->GPIO_Pin);
}
return message->length;
};
/** \brief init and register stm32 spi bus.
*
* \param SPI: STM32 SPI, e.g: SPI1,SPI2,SPI3.
* \param stm32_spi: stm32 spi bus struct.
* \param spi_bus_name: spi bus name, e.g: "spi1"
* \return
*
*/
rt_err_t stm32_spi_register(SPI_TypeDef * SPI,
struct stm32_spi_bus * stm32_spi,
const char * spi_bus_name)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
if(SPI == SPI1)
{
stm32_spi->SPI = SPI1;
#ifdef SPI_USE_DMA
/* Enable the DMA1 Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
stm32_spi->DMA_Channel_RX = DMA1_Channel2;
stm32_spi->DMA_Channel_TX = DMA1_Channel3;
stm32_spi->DMA_Channel_RX_FLAG_TC = DMA1_FLAG_TC2;
stm32_spi->DMA_Channel_RX_FLAG_TE = DMA1_FLAG_TE2;
stm32_spi->DMA_Channel_TX_FLAG_TC = DMA1_FLAG_TC3;
stm32_spi->DMA_Channel_TX_FLAG_TE = DMA1_FLAG_TE3;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
}
else if(SPI == SPI2)
{
stm32_spi->SPI = SPI2;
#ifdef SPI_USE_DMA
/* Enable the DMA1 Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
stm32_spi->DMA_Channel_RX = DMA1_Channel4;
stm32_spi->DMA_Channel_TX = DMA1_Channel5;
stm32_spi->DMA_Channel_RX_FLAG_TC = DMA1_FLAG_TC4;
stm32_spi->DMA_Channel_RX_FLAG_TE = DMA1_FLAG_TE4;
stm32_spi->DMA_Channel_TX_FLAG_TC = DMA1_FLAG_TC5;
stm32_spi->DMA_Channel_TX_FLAG_TE = DMA1_FLAG_TE5;
#endif
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
}
else if(SPI == SPI3)
{
stm32_spi->SPI = SPI3;
#ifdef SPI_USE_DMA
/* Enable the DMA2 Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
stm32_spi->DMA_Channel_RX = DMA2_Channel1;
stm32_spi->DMA_Channel_TX = DMA2_Channel2;
stm32_spi->DMA_Channel_RX_FLAG_TC = DMA2_FLAG_TC1;
stm32_spi->DMA_Channel_RX_FLAG_TE = DMA2_FLAG_TE1;
stm32_spi->DMA_Channel_TX_FLAG_TC = DMA2_FLAG_TC2;
stm32_spi->DMA_Channel_TX_FLAG_TE = DMA2_FLAG_TE2;
#endif
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
}
else
{
return RT_ENOSYS;
}
return rt_spi_bus_register(&stm32_spi->parent, spi_bus_name, &stm32_spi_ops);
}
#ifndef STM32_SPI_H_INCLUDED
#define STM32_SPI_H_INCLUDED
#include <rtdevice.h>
#include "stm32f10x.h"
#include "stm32f10x_spi.h"
#include "board.h"
//#define SPI_USE_DMA
struct stm32_spi_bus
{
struct rt_spi_bus parent;
SPI_TypeDef * SPI;
#ifdef SPI_USE_DMA
DMA_Channel_TypeDef * DMA_Channel_TX;
DMA_Channel_TypeDef * DMA_Channel_RX;
uint32_t DMA_Channel_TX_FLAG_TC;
uint32_t DMA_Channel_TX_FLAG_TE;
uint32_t DMA_Channel_RX_FLAG_TC;
uint32_t DMA_Channel_RX_FLAG_TE;
#endif /* SPI_USE_DMA */
};
struct stm32_spi_cs
{
GPIO_TypeDef * GPIOx;
uint16_t GPIO_Pin;
};
/* public function list */
rt_err_t stm32_spi_register(SPI_TypeDef * SPI,
struct stm32_spi_bus * stm32_spi,
const char * spi_bus_name);
#endif // STM32_SPI_H_INCLUDED
......@@ -5,7 +5,7 @@
* @version V3.5.0
* @date 08-April-2011
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @attention
......@@ -19,7 +19,7 @@
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
......@@ -107,12 +107,6 @@ void DebugMon_Handler(void)
{
}
void SysTick_Handler(void)
{
extern void rt_hw_timer_handler(void);
rt_hw_timer_handler();
}
/******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
......@@ -132,7 +126,7 @@ void USART1_IRQHandler(void)
#ifdef RT_USING_UART1
extern struct rt_device uart1_device;
extern void rt_hw_serial_isr(struct rt_device *device);
/* enter interrupt */
rt_interrupt_enter();
......@@ -191,7 +185,7 @@ void USART3_IRQHandler(void)
/**
* @}
*/
*/
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
......@@ -13,6 +13,7 @@
* 2010-03-29 Bernard remove interrupt Tx and DMA Rx mode
*/
#include <board.h>
#include "usart.h"
#include <serial.h>
#include <stm32f10x_dma.h>
......
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_proj.xsd">
<SchemaVersion>1.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header>
<Targets>
<Target>
<TargetName>RT-Thread STM32</TargetName>
......@@ -12,25 +15,25 @@
<Device>STM32F107VC</Device>
<Vendor>STMicroelectronics</Vendor>
<Cpu>IRAM(0x20000000-0x2000FFFF) IROM(0x8000000-0x803FFFF) CLOCK(25000000) CPUTYPE("Cortex-M3")</Cpu>
<FlashUtilSpec />
<FlashUtilSpec></FlashUtilSpec>
<StartupFile>"STARTUP\ST\STM32F10x.s" ("STM32 Startup Code")</StartupFile>
<FlashDriverDll>UL2CM3(-O14 -S0 -C0 -N00("ARM Cortex-M3") -D00(1BA00477) -L00(4) -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F10x_CL -FS08000000 -FL040000)</FlashDriverDll>
<DeviceId>4889</DeviceId>
<RegisterFile>stm32f10x_lib.h</RegisterFile>
<MemoryEnv />
<Cmp />
<Asm />
<Linker />
<OHString />
<InfinionOptionDll />
<SLE66CMisc />
<SLE66AMisc />
<SLE66LinkerMisc />
<MemoryEnv></MemoryEnv>
<Cmp></Cmp>
<Asm></Asm>
<Linker></Linker>
<OHString></OHString>
<InfinionOptionDll></InfinionOptionDll>
<SLE66CMisc></SLE66CMisc>
<SLE66AMisc></SLE66AMisc>
<SLE66LinkerMisc></SLE66LinkerMisc>
<SFDFile>SFD\ST\STM32F107x\STM32F107.sfr</SFDFile>
<UseEnv>0</UseEnv>
<BinPath />
<IncludePath />
<LibPath />
<BinPath></BinPath>
<IncludePath></IncludePath>
<LibPath></LibPath>
<RegisterFilePath>ST\STM32F10x\</RegisterFilePath>
<DBRegisterFilePath>ST\STM32F10x\</DBRegisterFilePath>
<TargetStatus>
......@@ -54,16 +57,18 @@
<BeforeCompile>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name />
<UserProg2Name />
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X>
<nStopU2X>0</nStopU2X>
</BeforeCompile>
<BeforeMake>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name />
<UserProg2Name />
<UserProg1Name></UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
</BeforeMake>
......@@ -71,12 +76,12 @@
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>fromelf --bin !L --output rtthread.bin</UserProg1Name>
<UserProg2Name />
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
</AfterMake>
<SelectedForBatchBuild>0</SelectedForBatchBuild>
<SVCSIdString />
<SVCSIdString></SVCSIdString>
</TargetCommonOption>
<CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler>
......@@ -90,16 +95,16 @@
<AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode>
<CustomArgument />
<IncludeLibraryModules />
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
</CommonProperty>
<DllOption>
<SimDllName>SARMCM3.DLL</SimDllName>
<SimDllArguments />
<SimDllArguments></SimDllArguments>
<SimDlgDll>DARMSTM.DLL</SimDlgDll>
<SimDlgDllArguments>-pSTM32F107VC</SimDlgDllArguments>
<TargetDllName>SARMCM3.DLL</TargetDllName>
<TargetDllArguments />
<TargetDllArguments></TargetDllArguments>
<TargetDlgDll>TARMSTM.DLL</TargetDlgDll>
<TargetDlgDllArguments>-pSTM32F107VC</TargetDlgDllArguments>
</DllOption>
......@@ -131,22 +136,23 @@
<RestoreMemoryDisplay>1</RestoreMemoryDisplay>
<RestoreFunctions>0</RestoreFunctions>
<RestoreToolbox>1</RestoreToolbox>
<RestoreTracepoints>0</RestoreTracepoints>
</Target>
<RunDebugAfterBuild>0</RunDebugAfterBuild>
<TargetSelection>7</TargetSelection>
<SimDlls>
<CpuDll />
<CpuDllArguments />
<PeripheralDll />
<PeripheralDllArguments />
<InitializationFile />
<CpuDll></CpuDll>
<CpuDllArguments></CpuDllArguments>
<PeripheralDll></PeripheralDll>
<PeripheralDllArguments></PeripheralDllArguments>
<InitializationFile></InitializationFile>
</SimDlls>
<TargetDlls>
<CpuDll />
<CpuDllArguments />
<PeripheralDll />
<PeripheralDllArguments />
<InitializationFile />
<CpuDll></CpuDll>
<CpuDllArguments></CpuDllArguments>
<PeripheralDll></PeripheralDll>
<PeripheralDllArguments></PeripheralDllArguments>
<InitializationFile></InitializationFile>
<Driver>Segger\JL2CM3.dll</Driver>
</TargetDlls>
</DebugOption>
......@@ -160,8 +166,8 @@
<DriverSelection>4099</DriverSelection>
</Flash1>
<Flash2>Segger\JL2CM3.dll</Flash2>
<Flash3 />
<Flash4 />
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
</Utilities>
<TargetArmAds>
<ArmAdsMisc>
......@@ -193,7 +199,7 @@
<RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M3"</AdsCpuType>
<RvctDeviceName />
<RvctDeviceName></RvctDeviceName>
<mOS>0</mOS>
<uocRom>0</uocRom>
<uocRam>0</uocRam>
......@@ -324,7 +330,7 @@
<Size>0x0</Size>
</OCR_RVCT10>
</OnChipMemories>
<RvctStartVector />
<RvctStartVector></RvctStartVector>
</ArmAdsMisc>
<Cads>
<interw>1</interw>
......@@ -339,11 +345,12 @@
<Rwpi>0</Rwpi>
<wLevel>0</wLevel>
<uThumb>0</uThumb>
<uSurpInc>0</uSurpInc>
<VariousControls>
<MiscControls />
<MiscControls></MiscControls>
<Define>STM32F10X_CL, USE_STDPERIPH_DRIVER</Define>
<Undefine />
<IncludePath>.;..\..\components\CMSIS\Include;..\..\components\dfs;..\..\components\dfs\include;..\..\components\finsh;..\..\components\init;..\..\components\net\lwip\src;..\..\components\net\lwip\src\arch\include;..\..\components\net\lwip\src\include;..\..\components\net\lwip\src\include\ipv4;..\..\components\net\lwip\src\include\netif;..\..\include;..\..\libcpu\arm\common;..\..\libcpu\arm\cortex-m3;Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x;Libraries\STM32F10x_StdPeriph_Driver\inc;applications;drivers</IncludePath>
<Undefine></Undefine>
<IncludePath>.;..\..\components\CMSIS\Include;..\..\components\dfs;..\..\components\dfs\include;..\..\components\drivers\include;..\..\components\finsh;..\..\components\init;..\..\components\net\lwip\src;..\..\components\net\lwip\src\arch\include;..\..\components\net\lwip\src\include;..\..\components\net\lwip\src\include\ipv4;..\..\components\net\lwip\src\include\netif;..\..\include;..\..\libcpu\arm\common;..\..\libcpu\arm\cortex-m3;Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x;Libraries\STM32F10x_StdPeriph_Driver\inc;applications;drivers</IncludePath>
</VariousControls>
</Cads>
<Aads>
......@@ -354,11 +361,12 @@
<SplitLS>0</SplitLS>
<SwStkChk>0</SwStkChk>
<NoWarn>0</NoWarn>
<uSurpInc>0</uSurpInc>
<VariousControls>
<MiscControls />
<Define />
<Undefine />
<IncludePath />
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads>
<LDads>
......@@ -370,12 +378,12 @@
<useFile>0</useFile>
<TextAddressRange>0x08000000</TextAddressRange>
<DataAddressRange>0x20000000</DataAddressRange>
<ScatterFile />
<IncludeLibs />
<IncludeLibsPath />
<ScatterFile></ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc> --keep __fsym_* --keep __vsym_* </Misc>
<LinkerInputFile />
<DisabledWarnings />
<LinkerInputFile></LinkerInputFile>
<DisabledWarnings></DisabledWarnings>
</LDads>
</TargetArmAds>
</TargetOption>
......@@ -388,8 +396,6 @@
<FileType>1</FileType>
<FilePath>applications\application.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>startup.c</FileName>
<FileType>1</FileType>
......@@ -405,43 +411,36 @@
<FileType>1</FileType>
<FilePath>drivers\board.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>msd.c</FileName>
<FileType>1</FileType>
<FilePath>drivers\msd.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>platform.c</FileName>
<FileType>1</FileType>
<FilePath>drivers\platform.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>rt_stm32f10x_spi.c</FileName>
<FileType>1</FileType>
<FilePath>drivers\rt_stm32f10x_spi.c</FilePath>
</File>
<File>
<FileName>serial.c</FileName>
<FileType>1</FileType>
<FilePath>drivers\serial.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32_eth.c</FileName>
<FileType>1</FileType>
<FilePath>drivers\stm32_eth.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_it.c</FileName>
<FileType>1</FileType>
<FilePath>drivers\stm32f10x_it.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>usart.c</FileName>
<FileType>1</FileType>
......@@ -457,169 +456,121 @@
<FileType>1</FileType>
<FilePath>Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\system_stm32f10x.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_crc.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_crc.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_rcc.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_rcc.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_wwdg.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_wwdg.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_pwr.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_pwr.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_exti.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_exti.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_bkp.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_bkp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_i2c.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_i2c.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_adc.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_adc.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_dac.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_dac.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_rtc.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_rtc.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_fsmc.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_fsmc.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_tim.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_tim.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_iwdg.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_iwdg.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_spi.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_spi.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_flash.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_flash.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_sdio.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_sdio.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_gpio.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_gpio.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_usart.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_usart.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_dbgmcu.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_dbgmcu.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_dma.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_dma.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_can.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_can.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stm32f10x_cec.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_cec.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>misc.c</FileName>
<FileType>1</FileType>
<FilePath>Libraries\STM32F10x_StdPeriph_Driver\src\misc.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>startup_stm32f10x_cl.s</FileName>
<FileType>2</FileType>
......@@ -635,78 +586,56 @@
<FileType>1</FileType>
<FilePath>..\..\src\clock.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>device.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\device.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>idle.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\idle.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>ipc.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\ipc.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>irq.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\irq.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>kservice.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\kservice.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>mem.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\mem.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>mempool.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\mempool.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>object.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\object.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>scheduler.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\scheduler.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>thread.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\src\thread.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>timer.c</FileName>
<FileType>1</FileType>
......@@ -722,29 +651,21 @@
<FileType>1</FileType>
<FilePath>..\..\libcpu\arm\cortex-m3\cpuport.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>context_rvds.S</FileName>
<FileType>2</FileType>
<FilePath>..\..\libcpu\arm\cortex-m3\context_rvds.S</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>backtrace.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\libcpu\arm\common\backtrace.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>div0.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\libcpu\arm\common\div0.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>showmem.c</FileName>
<FileType>1</FileType>
......@@ -760,36 +681,26 @@
<FileType>1</FileType>
<FilePath>..\..\components\dfs\src\dfs.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>dfs_fs.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\dfs\src\dfs_fs.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>dfs_file.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\dfs\src\dfs_file.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>dfs_posix.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\dfs\src\dfs_posix.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>dfs_elm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\dfs\filesystems\elmfat\dfs_elm.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>ff.c</FileName>
<FileType>1</FileType>
......@@ -797,6 +708,21 @@
</File>
</Files>
</Group>
<Group>
<GroupName>DeviceDrivers</GroupName>
<Files>
<File>
<FileName>spi_core.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\drivers\spi\spi_core.c</FilePath>
</File>
<File>
<FileName>spi_dev.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\drivers\spi\spi_dev.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>finsh</GroupName>
<Files>
......@@ -805,85 +731,61 @@
<FileType>1</FileType>
<FilePath>..\..\components\finsh\cmd.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_compiler.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_compiler.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_error.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_error.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_heap.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_heap.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_init.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_init.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_node.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_node.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_ops.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_ops.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_parser.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_parser.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_token.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_token.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_var.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_var.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>finsh_vm.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\finsh_vm.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>shell.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\finsh\shell.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>symbol.c</FileName>
<FileType>1</FileType>
......@@ -909,239 +811,171 @@
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\api_lib.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>api_msg.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\api_msg.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>err.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\err.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>netbuf.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\netbuf.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>netdb.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\netdb.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>netifapi.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\netifapi.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>sockets.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\sockets.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>tcpip.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\api\tcpip.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>sys_arch.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\arch\sys_arch.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>def.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\def.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>dhcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\dhcp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>dns.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\dns.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>init.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\init.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>memp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\memp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>netif.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\netif.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>pbuf.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\pbuf.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>raw.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\raw.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>stats.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\stats.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>sys.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\sys.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>tcp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\tcp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>tcp_in.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\tcp_in.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>tcp_out.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\tcp_out.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>timers.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\timers.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>udp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\udp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>autoip.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\autoip.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>icmp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\icmp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>igmp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\igmp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>inet.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\inet.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>inet_chksum.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\inet_chksum.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>ip.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\ip.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>ip_addr.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\ip_addr.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>ip_frag.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\core\ipv4\ip_frag.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>etharp.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\netif\etharp.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>ethernetif.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\components\net\lwip\src\netif\ethernetif.c</FilePath>
</File>
</Files>
<Files>
<File>
<FileName>slipif.c</FileName>
<FileType>1</FileType>
......@@ -1152,4 +986,5 @@
</Groups>
</Target>
</Targets>
</Project>
......@@ -2,4 +2,4 @@
# GoldBull debug board
- 10M/100M ethernet
- SPI SD Card
- LCD
SPI: SPI1 (PA5,PA6,PA7). CS:PA4
......@@ -58,7 +58,7 @@
/* SECTION: Device System */
/* Using Device System */
#define RT_USING_DEVICE
#define RT_USING_UART1
#define RT_USING_SPI
/* SECTION: Console options */
#define RT_USING_CONSOLE
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册