rt-thread/bsp/stm32f429-apollo/drivers/drv_sdio_sd.c

367 lines
11 KiB
C
Raw Normal View History

#include "drv_sdio_sd.h"
#include "string.h"
#include <rtthread.h>
#include <dfs_fs.h>
SD_HandleTypeDef SDCARD_Handler;
HAL_SD_CardInfoTypedef SDCardInfo; //SD<53><44><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><E1B9B9>
DMA_HandleTypeDef SDTxDMAHandler,SDRxDMAHandler; //SD<53><44>DMA<4D><41><EFBFBD>ͺͽ<CDBA><CDBD>վ<EFBFBD><D5BE><EFBFBD>
//SD<53><44><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
//<2F><><EFBFBD><EFBFBD>ֵ:0 <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
rt_uint8_t SD_Init(void)
{
rt_uint8_t SD_Error;
//<2F><>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1>ʱ<EFBFBD>Ӳ<EFBFBD><D3B2>ܴ<EFBFBD><DCB4><EFBFBD>400KHZ
SDCARD_Handler.Instance=SDIO;
SDCARD_Handler.Init.ClockEdge=SDIO_CLOCK_EDGE_RISING; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SDCARD_Handler.Init.ClockBypass=SDIO_CLOCK_BYPASS_DISABLE; //<2F><>ʹ<EFBFBD><CAB9>bypassģʽ<C4A3><CABD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>HCLK<4C><4B><EFBFBD>з<EFBFBD>Ƶ<EFBFBD>õ<EFBFBD>SDIO_CK
SDCARD_Handler.Init.ClockPowerSave=SDIO_CLOCK_POWER_SAVE_DISABLE; //<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ر<EFBFBD>ʱ<EFBFBD>ӵ<EFBFBD>Դ
SDCARD_Handler.Init.BusWide=SDIO_BUS_WIDE_1B; //1λ<31><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SDCARD_Handler.Init.HardwareFlowControl=SDIO_HARDWARE_FLOW_CONTROL_DISABLE;//<2F>ر<EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SDCARD_Handler.Init.ClockDiv=SDIO_INIT_CLK_DIV; //<2F><>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1>Ϊ400KHZ
SD_Error=HAL_SD_Init(&SDCARD_Handler,&SDCardInfo);
if(SD_Error!=SD_OK) return 1;
SD_Error=HAL_SD_WideBusOperation_Config(&SDCARD_Handler,SDIO_BUS_WIDE_4B);//ʹ<>ܿ<EFBFBD><DCBF><EFBFBD><EFBFBD><EFBFBD>ģʽ
if(SD_Error!=SD_OK) return 2;
return 0;
}
//SDMMC<4D>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ʹ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>DMA<4D><41><EFBFBD><EFBFBD>
//<2F>˺<EFBFBD><CBBA><EFBFBD><EFBFBD>ᱻHAL_SD_Init()<29><><EFBFBD><EFBFBD>
//hsd:SD<53><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
{
DMA_HandleTypeDef TxDMAHandler,RxDMAHandler;
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_SDIO_CLK_ENABLE(); //ʹ<><CAB9>SDIOʱ<4F><CAB1>
__HAL_RCC_DMA2_CLK_ENABLE(); //ʹ<><CAB9>DMA2ʱ<32><CAB1>
__HAL_RCC_GPIOC_CLK_ENABLE(); //ʹ<><CAB9>GPIOCʱ<43><CAB1>
__HAL_RCC_GPIOD_CLK_ENABLE(); //ʹ<><CAB9>GPIODʱ<44><CAB1>
//PC8,9,10,11,12
GPIO_Initure.Pin=GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //<2F><><EFBFBD><EFBFBD><ECB8B4>
GPIO_Initure.Pull=GPIO_PULLUP; //<2F><><EFBFBD><EFBFBD>
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //<2F><><EFBFBD><EFBFBD>
GPIO_Initure.Alternate=GPIO_AF12_SDIO; //<2F><><EFBFBD><EFBFBD>ΪSDIO
HAL_GPIO_Init(GPIOC,&GPIO_Initure); //<2F><>ʼ<EFBFBD><CABC>
//PD2
GPIO_Initure.Pin=GPIO_PIN_2;
HAL_GPIO_Init(GPIOD,&GPIO_Initure); //<2F><>ʼ<EFBFBD><CABC>
#if (SD_DMA_MODE==1) //ʹ<><CAB9>DMAģʽ
HAL_NVIC_SetPriority(SDMMC1_IRQn,2,0); //<2F><><EFBFBD><EFBFBD>SDMMC1<43>жϣ<D0B6><CFA3><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>ȼ<EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>0
HAL_NVIC_EnableIRQ(SDMMC1_IRQn); //ʹ<><CAB9>SDMMC1<43>ж<EFBFBD>
//<2F><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD>DMA
SDRxDMAHandler.Instance=DMA2_Stream3;
SDRxDMAHandler.Init.Channel=DMA_CHANNEL_4;
SDRxDMAHandler.Init.Direction=DMA_PERIPH_TO_MEMORY;
SDRxDMAHandler.Init.PeriphInc=DMA_PINC_DISABLE;
SDRxDMAHandler.Init.MemInc=DMA_MINC_ENABLE;
SDRxDMAHandler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD;
SDRxDMAHandler.Init.MemDataAlignment=DMA_MDATAALIGN_WORD;
SDRxDMAHandler.Init.Mode=DMA_PFCTRL;
SDRxDMAHandler.Init.Priority=DMA_PRIORITY_VERY_HIGH;
SDRxDMAHandler.Init.FIFOMode=DMA_FIFOMODE_ENABLE;
SDRxDMAHandler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
SDRxDMAHandler.Init.MemBurst=DMA_MBURST_INC4;
SDRxDMAHandler.Init.PeriphBurst=DMA_PBURST_INC4;
__HAL_LINKDMA(hsd, hdmarx, SDRxDMAHandler); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DMA<4D><41>SD<53><44><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HAL_DMA_DeInit(&SDRxDMAHandler);
HAL_DMA_Init(&SDRxDMAHandler); //<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DMA
//<2F><><EFBFBD>ý<EFBFBD><C3BD><EFBFBD>DMA
SDTxDMAHandler.Instance=DMA2_Stream6;
SDTxDMAHandler.Init.Channel=DMA_CHANNEL_4;
SDTxDMAHandler.Init.Direction=DMA_MEMORY_TO_PERIPH;
SDTxDMAHandler.Init.PeriphInc=DMA_PINC_DISABLE;
SDTxDMAHandler.Init.MemInc=DMA_MINC_ENABLE;
SDTxDMAHandler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD;
SDTxDMAHandler.Init.MemDataAlignment=DMA_MDATAALIGN_WORD;
SDTxDMAHandler.Init.Mode=DMA_PFCTRL;
SDTxDMAHandler.Init.Priority=DMA_PRIORITY_VERY_HIGH;
SDTxDMAHandler.Init.FIFOMode=DMA_FIFOMODE_ENABLE;
SDTxDMAHandler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
SDTxDMAHandler.Init.MemBurst=DMA_MBURST_INC4;
SDTxDMAHandler.Init.PeriphBurst=DMA_PBURST_INC4;
__HAL_LINKDMA(hsd, hdmatx, SDTxDMAHandler);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DMA<4D><41>SD<53><44><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HAL_DMA_DeInit(&SDTxDMAHandler);
HAL_DMA_Init(&SDTxDMAHandler); //<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DMA
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 3, 0); //<2F><><EFBFBD><EFBFBD>DMA<4D>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>ȼ<EFBFBD>
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 3, 0); //<2F><><EFBFBD><EFBFBD>DMA<4D>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>ȼ<EFBFBD>
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
#endif
}
//<2F>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>Ϣ
//cardinfo:<3A><><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><E6B4A2>
//<2F><><EFBFBD><EFBFBD>ֵ:<3A><><EFBFBD><EFBFBD>״̬
rt_uint8_t SD_GetCardInfo(HAL_SD_CardInfoTypedef *cardinfo)
{
rt_uint8_t sta;
sta=HAL_SD_Get_CardInfo(&SDCARD_Handler,cardinfo);
return sta;
}
#if (SD_DMA_MODE==1) //DMAģʽ
//ͨ<><CDA8>DMA<4D><41>ȡSD<53><44>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//buf:<3A><><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
//sector:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
//blocksize:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С(һ<><EFBFBD><E3B6BC>512<31>ֽ<EFBFBD>)
//cnt:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>ֵ:<3A><><EFBFBD><EFBFBD>״̬;0,<2C><><EFBFBD><EFBFBD>;<3B><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
rt_uint8_t SD_ReadBlocks_DMA(uint32_t *buf,uint64_t sector ,uint32_t cnt)
{
rt_uint8_t err=SD_OK;
err=HAL_SD_ReadBlocks_DMA(&SDCARD_Handler,buf,sector,SECTOR_SIZE,cnt);//ͨ<><CDA8>DMA<4D><41>ȡSD<53><44>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(err==SD_OK)//<2F><>ȡ<EFBFBD>ɹ<EFBFBD>
{
//<2F>ȴ<EFBFBD><C8B4><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
err=HAL_SD_CheckReadOperation(&SDCARD_Handler,(uint32_t)SD_TIMEOUT);
}
return err;
}
//дSD<53><44>
//buf:д<><D0B4><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
//sector:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
//blocksize:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С(һ<><EFBFBD><E3B6BC>512<31>ֽ<EFBFBD>)
//cnt:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>ֵ:<3A><><EFBFBD><EFBFBD>״̬;0,<2C><><EFBFBD><EFBFBD>;<3B><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
rt_uint8_t SD_WriteBlocks_DMA(uint32_t *buf,uint64_t sector,uint32_t cnt)
{
rt_uint8_t err=SD_OK;
err=HAL_SD_WriteBlocks_DMA(&SDCARD_Handler,buf,sector,SECTOR_SIZE,cnt);//ͨ<><CDA8>DMAдSD<53><44>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(err==SD_OK)//д<>ɹ<EFBFBD>
{
err=HAL_SD_CheckWriteOperation(&SDCARD_Handler,(uint32_t)SD_TIMEOUT);//<2F>ȴ<EFBFBD><C8B4><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>/
}
return err;
}
//SDMMC1<43>жϷ<D0B6><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void SDMMC1_IRQHandler(void)
{
HAL_SD_IRQHandler(&SDCARD_Handler);
}
//DMA2<41><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD>6<EFBFBD>жϷ<D0B6><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void DMA2_Stream6_IRQHandler(void)
{
HAL_DMA_IRQHandler(SDCARD_Handler.hdmatx);
}
//DMA2<41><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD>жϷ<D0B6><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void DMA2_Stream3_IRQHandler(void)
{
HAL_DMA_IRQHandler(SDCARD_Handler.hdmarx);
}
#else //<2F><>ѵģʽ
//<2F><>ȡSD<53><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//buf:<3A><><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
//sector:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
//cnt:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>ֵ:<3A><><EFBFBD><EFBFBD>״̬;0,<2C><><EFBFBD><EFBFBD>;<3B><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
rt_uint8_t SD_ReadBlocks(uint32_t *buf,uint64_t sector ,uint32_t cnt)
{
rt_uint8_t err=SD_OK;
err=HAL_SD_ReadBlocks(&SDCARD_Handler,buf,sector,SECTOR_SIZE,cnt);//ͨ<><CDA8>DMA<4D><41>ȡSD<53><44>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return err;
}
//дSD<53><44><EFBFBD><EFBFBD>
//buf:д<><D0B4><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
//sector:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
//cnt:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>ֵ:<3A><><EFBFBD><EFBFBD>״̬;0,<2C><><EFBFBD><EFBFBD>;<3B><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
rt_uint8_t SD_WriteBlocks(uint32_t *buf,uint64_t sector,uint32_t cnt)
{
return HAL_SD_WriteBlocks(&SDCARD_Handler,buf,sector,SECTOR_SIZE,cnt);
}
#endif
/*
* RT-Thread SD Card Driver
* 20100715 Bernard support SDHC card great than 4G.
* 20110905 JoyChen support to STM32F2xx
*/
static struct rt_device sdcard_device;
static struct rt_semaphore sd_lock;
/* RT-Thread Device Driver Interface */
static rt_err_t rt_sdcard_init(rt_device_t dev)
{
if (rt_sem_init(&sd_lock, "sdlock", 1, RT_IPC_FLAG_FIFO) != RT_EOK)
{
rt_kprintf("init sd lock semaphore failed\n");
}
else
rt_kprintf("SD Card init OK\n");
return RT_EOK;
}
static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t rt_sdcard_close(rt_device_t dev)
{
return RT_EOK;
}
static uint32_t sdio_buffer[512/sizeof(uint32_t)];
static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
rt_uint8_t status = SD_OK;
rt_sem_take(&sd_lock, RT_WAITING_FOREVER);
if(((uint32_t)buffer & 0x03) != 0)
{
/* non-aligned. */
uint32_t i;
uint64_t sector_adr;
uint8_t* copy_buffer;
sector_adr = (uint64_t)pos*SECTOR_SIZE;
copy_buffer = (uint8_t*)buffer;
for(i=0; i<size; i++)
{
#if (SD_DMA_MODE==1)
status=SD_ReadBlocks_DMA(sdio_buffer,sector_adr,1);//ͨ<><CDA8>DMAдSD<53><44>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#else
status=SD_ReadBlocks(sdio_buffer,sector_adr,1);
#endif
memcpy(copy_buffer, sdio_buffer, SECTOR_SIZE);
sector_adr += SECTOR_SIZE;
copy_buffer += SECTOR_SIZE;
}
}
else
{
#if (SD_DMA_MODE==1)
status=SD_ReadBlocks_DMA(buffer,(uint64_t)pos*SECTOR_SIZE,size);//ͨ<><CDA8>DMAдSD<53><44>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#else
SD_ReadBlocks(buffer,(uint64_t)pos*SECTOR_SIZE,size);
#endif
}
rt_sem_release(&sd_lock);
if (status == SD_OK) return size;
rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
return 0;
}
static rt_size_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
rt_uint8_t status = SD_OK;
rt_sem_take(&sd_lock, RT_WAITING_FOREVER);
if(((uint32_t)buffer & 0x03) != 0)
{
/* non-aligned. */
uint32_t i;
uint64_t sector_adr;
uint8_t* copy_buffer;
sector_adr = (uint64_t)pos*SECTOR_SIZE;
copy_buffer = (uint8_t*)buffer;
for(i=0; i<size; i++)
{
memcpy(sdio_buffer, copy_buffer, SECTOR_SIZE);
#if (SD_DMA_MODE==1)
status=SD_WriteBlocks_DMA((uint32_t*)sdio_buffer,sector_adr,1);
#else
status=SD_WriteBlocks((uint32_t*)sdio_buffer,sector_adr,1);
#endif
sector_adr += SECTOR_SIZE;
copy_buffer += SECTOR_SIZE;
}
}
else
{
#if (SD_DMA_MODE==1)
status=SD_WriteBlocks_DMA((uint32_t*)buffer,(uint64_t)pos*SECTOR_SIZE,size);
#else
status=SD_WriteBlocks((uint32_t*)buffer,(uint64_t)pos*SECTOR_SIZE,size);
#endif
}
// }
rt_sem_release(&sd_lock);
if (status == SD_OK) return size;
rt_kprintf("write failed: %d, buffer 0x%08x\n", status, buffer);
return 0;
}
static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
{
RT_ASSERT(dev != RT_NULL);
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 = 512;
geometry->block_size = SDCardInfo.CardBlockSize;
geometry->sector_count = SDCardInfo.CardCapacity/SDCardInfo.CardBlockSize;
}
return RT_EOK;
}
static int rt_hw_sdcard_init(void)
{
if (SD_Init() == SD_OK)
{
/* register sdcard device */
sdcard_device.type = RT_Device_Class_Block;
sdcard_device.init = rt_sdcard_init;
sdcard_device.open = rt_sdcard_open;
sdcard_device.close = rt_sdcard_close;
sdcard_device.read = rt_sdcard_read;
sdcard_device.write = rt_sdcard_write;
sdcard_device.control = rt_sdcard_control;
/* no private */
sdcard_device.user_data = &SDCardInfo;
rt_device_register(&sdcard_device, "sd0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
return RT_EOK;
}
rt_kprintf("sdcard init failed\n");
return RT_ERROR;
}
INIT_BOARD_EXPORT(rt_hw_sdcard_init);