diff --git a/bsp/stm32f10x-HAL/Kconfig b/bsp/stm32f10x-HAL/Kconfig index 28a348c4040d1a232f61cca0922db4b7222833a7..534e930ba815f5b001cbe8d57a759162f335432c 100644 --- a/bsp/stm32f10x-HAL/Kconfig +++ b/bsp/stm32f10x-HAL/Kconfig @@ -182,3 +182,16 @@ if RT_USING_SPI default n endif +if RT_USING_DEVICE_IPC && (STM32F103RC || STM32F103RD || STM32F103RE || STM32F103RF || STM32F103RG ||STM32F103VC || STM32F103VD || STM32F103VE || STM32F103VF || STM32F103VG ||STM32F103ZC || STM32F103ZD || STM32F103ZE || STM32F103ZF || STM32F103ZG) + config RT_USING_SDCARD + bool "Using sdcard with sdio" + default n + config USING_SD_RX_DMA + bool "SDCARD Rx Using Dma Mode" + default y + depends on RT_USING_SDCARD + config USING_SD_TX_DMA + bool "SDCARD Tx Using Dma Mode" + default n + depends on RT_USING_SDCARD +endif diff --git a/bsp/stm32f10x-HAL/drivers/SConscript b/bsp/stm32f10x-HAL/drivers/SConscript index 190f7710e71c049ec35a3dc88f8fd5e111bde750..586b566952bb149b4c1cdef3fc76bd0c4c7e9bed 100644 --- a/bsp/stm32f10x-HAL/drivers/SConscript +++ b/bsp/stm32f10x-HAL/drivers/SConscript @@ -18,8 +18,8 @@ if GetDepend(['RT_USING_SPI']): src += ['drv_spi.c'] if GetDepend(['RT_USING_USB_DEVICE']): src += ['drv_usb.c'] - - +if GetDepend(['RT_USING_SDCARD']): + src += ['drv_sdcard.c'] CPPPATH = [cwd] diff --git a/bsp/stm32f10x-HAL/drivers/drv_sdcard.c b/bsp/stm32f10x-HAL/drivers/drv_sdcard.c new file mode 100644 index 0000000000000000000000000000000000000000..df833b10687a951a14eb96367349fc094e787808 --- /dev/null +++ b/bsp/stm32f10x-HAL/drivers/drv_sdcard.c @@ -0,0 +1,324 @@ +/* + * File : drv_sdcard.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-01-13 Liu2guang the first version. + */ +#include +#include +#include "board.h" +#include "drv_sdcard.h" + +#ifndef SDIO_CLK_DIV +#define SDIO_CLK_DIV 2 +#endif + +#define SDIO_TIMEOUT ((uint32_t)0x100000) + +static SD_HandleTypeDef hsdcard; +static DMA_HandleTypeDef hdma; +static struct rt_semaphore sd_lock; + +void SDIO_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_SD_IRQHandler(&hsdcard); + rt_interrupt_leave(); +} + +#if defined(USING_SD_RX_DMA) || defined(USING_SD_TX_DMA) +void DMA2_Channel4_5_IRQHandler(void) +{ + rt_interrupt_enter(); + HAL_DMA_IRQHandler(&hdma); + rt_interrupt_leave(); +} +#endif + +rt_err_t stm32_read_blocks(uint32_t *data, uint32_t addr, uint32_t num) +{ + uint32_t timeout = 0; + HAL_SD_StateTypeDef state_return; + HAL_SD_CardStateTypeDef sd_card_state_return; + +#if defined(USING_SD_RX_DMA) && defined(USING_SD_TX_DMA) + hdma.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma.Init.PeriphInc = DMA_PINC_DISABLE; + hdma.Init.MemInc = DMA_MINC_ENABLE; + HAL_DMA_DeInit(&hdma); + HAL_DMA_Init(&hdma); +#endif + +#if defined(USING_SD_RX_DMA) + if(HAL_SD_ReadBlocks_DMA(&hsdcard, (uint8_t *)data, addr, num) != HAL_OK) +#else + if(HAL_SD_ReadBlocks(&hsdcard, (uint8_t *)data, addr, num, SDIO_TIMEOUT) != HAL_OK) +#endif + { + return RT_EIO; + } + + do + { + state_return = HAL_SD_GetState(&hsdcard); + timeout++; + }while((HAL_SD_STATE_BUSY == state_return) && (SDIO_TIMEOUT > timeout)); + + if(HAL_SD_STATE_READY != state_return) + { + return RT_ERROR; + } + + do + { + sd_card_state_return = HAL_SD_GetCardState(&hsdcard); + timeout++; + }while((HAL_SD_CARD_TRANSFER != sd_card_state_return) && (SDIO_TIMEOUT > timeout)); + + if(SDIO_TIMEOUT <= timeout) + { + return RT_ETIMEOUT; + } + + return RT_EOK; +} + +rt_err_t stm32_write_blocks(uint32_t *data, uint32_t addr, uint32_t num) +{ + uint32_t timeout = 0; + HAL_SD_StateTypeDef state_return; + HAL_SD_CardStateTypeDef sd_card_state_return; + +#if defined(USING_SD_RX_DMA) && defined(USING_SD_TX_DMA) + hdma.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma.Init.PeriphInc = DMA_MINC_ENABLE; + hdma.Init.MemInc = DMA_PINC_DISABLE; + HAL_DMA_DeInit(&hdma); + HAL_DMA_Init(&hdma); +#endif + +#if defined(USING_SD_TX_DMA) + if(HAL_SD_WriteBlocks_DMA(&hsdcard, (uint8_t *)data, addr, num) != HAL_OK) +#else + if(HAL_SD_WriteBlocks(&hsdcard, (uint8_t *)data, addr, num, SDIO_TIMEOUT) != HAL_OK) +#endif + { + return RT_ERROR; + } + + do + { + state_return = HAL_SD_GetState(&hsdcard); + timeout++; + }while((HAL_SD_STATE_BUSY == state_return) && (SDIO_TIMEOUT > timeout)); + + if(HAL_SD_STATE_READY != state_return) + { + return RT_ERROR; + } + + do + { + sd_card_state_return = HAL_SD_GetCardState(&hsdcard); + timeout++; + }while((HAL_SD_CARD_TRANSFER != sd_card_state_return) && (SDIO_TIMEOUT > timeout)); + + if(SDIO_TIMEOUT <= timeout) + { + return RT_ETIMEOUT; + } + + return RT_EOK; +} + +static rt_err_t stm32_sdcard_init(rt_device_t dev) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + if(rt_sem_init(&sd_lock, "sdlock", 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + return RT_ERROR; + } + + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | + GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_2; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + +#if defined(USING_SD_RX_DMA) || defined(USING_SD_TX_DMA) + __HAL_RCC_DMA2_CLK_ENABLE(); + + hdma.Instance = DMA2_Channel4; + hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma.Init.Mode = DMA_NORMAL; + hdma.Init.Priority = DMA_PRIORITY_HIGH; + +#if defined(USING_SD_RX_DMA) + hdma.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma.Init.PeriphInc = DMA_PINC_DISABLE; + hdma.Init.MemInc = DMA_MINC_ENABLE; + __HAL_LINKDMA(&hsdcard, hdmarx, hdma); +#endif + +#if defined(USING_SD_TX_DMA) + hdma.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma.Init.PeriphInc = DMA_MINC_ENABLE; + hdma.Init.MemInc = DMA_PINC_DISABLE; + __HAL_LINKDMA(&hsdcard, hdmatx, hdma); +#endif + + HAL_DMA_DeInit(&hdma); + if(HAL_DMA_Init(&hdma) != HAL_OK) + { + rt_kprintf("HAL_DMA_Init error\n"); + return RT_EIO; + } +#endif + + HAL_NVIC_SetPriority(DMA2_Channel4_5_IRQn, 3, 0); + HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); + + __HAL_RCC_SDIO_CLK_ENABLE(); + + hsdcard.Instance = SDIO; + hsdcard.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + hsdcard.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + hsdcard.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; + hsdcard.Init.BusWide = SDIO_BUS_WIDE_1B; + hsdcard.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; + hsdcard.Init.ClockDiv = SDIO_CLK_DIV; + + HAL_SD_DeInit(&hsdcard); + if(HAL_SD_Init(&hsdcard) != HAL_OK) + { + rt_kprintf("HAL_SD_Init error\n"); + return RT_EIO; + } + + HAL_NVIC_SetPriority(SDIO_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(SDIO_IRQn); + + if(HAL_SD_ConfigWideBusOperation(&hsdcard, SDIO_BUS_WIDE_4B) != HAL_OK) + { + rt_kprintf("HAL_SD_ConfigWideBusOperation error\n"); + return RT_EIO; + } + + return RT_EOK; +} + +static rt_err_t stm32_sdcard_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t stm32_sdcard_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t stm32_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + int ret = RT_EOK; + + rt_sem_take(&sd_lock, RT_WAITING_FOREVER); + ret = stm32_read_blocks((uint32_t *)buffer, pos, size); + rt_sem_release(&sd_lock); + + if(ret != RT_EOK) + { + return 0; + } + + return size; +} + +static rt_size_t stm32_sdcard_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + int ret = RT_EOK; + + rt_sem_take(&sd_lock, RT_WAITING_FOREVER); + ret = stm32_write_blocks((uint32_t *)buffer, pos, size); + rt_sem_release(&sd_lock); + + if(ret != RT_EOK) + { + return 0; + } + + return size; +} + +static rt_err_t stm32_sdcard_control(rt_device_t dev, int cmd, void *args) +{ + RT_ASSERT(dev != RT_NULL); + + // RT_DEVICE_CTRL_BLK_GETGEOME + if(cmd == RT_DEVICE_CTRL_BLK_GETGEOME) + { + HAL_SD_CardInfoTypeDef sdcard_info; + struct rt_device_blk_geometry *geometry; + + HAL_SD_GetCardInfo(&hsdcard, &sdcard_info); + + geometry = (struct rt_device_blk_geometry *)args; + + geometry->bytes_per_sector = sdcard_info.BlockSize; + geometry->block_size = sdcard_info.BlockSize; + geometry->sector_count = sdcard_info.BlockNbr; + } + + return RT_EOK; +} + +static struct rt_device device; + +int rt_hw_sdcard_init(void) +{ + rt_err_t ret = RT_EOK; + + device.type = RT_Device_Class_Block; + device.init = stm32_sdcard_init; + device.open = stm32_sdcard_open; + device.read = stm32_sdcard_read; + device.write = stm32_sdcard_write; + device.control = stm32_sdcard_control; + device.close = stm32_sdcard_close; + + ret = rt_device_register(&device, "sd0", + RT_DEVICE_FLAG_REMOVABLE | + RT_DEVICE_FLAG_RDWR | + RT_DEVICE_FLAG_STANDALONE); + if(ret != RT_EOK) + { + return ret; + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_sdcard_init); diff --git a/bsp/stm32f10x-HAL/drivers/drv_sdcard.h b/bsp/stm32f10x-HAL/drivers/drv_sdcard.h new file mode 100644 index 0000000000000000000000000000000000000000..d483020b60a890bd73a39de5c227baf5910313c0 --- /dev/null +++ b/bsp/stm32f10x-HAL/drivers/drv_sdcard.h @@ -0,0 +1,30 @@ +/* + * File : drv_sdcard.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-01-13 Liu2guang the first version. + */ + +#ifndef __DRV_SDCARD_H_ +#define __DRV_SDCARD_H_ + +int rt_hw_sdcard_init(void); + +#endif diff --git a/bsp/stm32f10x-HAL/drivers/stm32f1xx_hal_conf.h b/bsp/stm32f10x-HAL/drivers/stm32f1xx_hal_conf.h index 72b69a2e4b276e331d5d3f25ccaeeb6a3782ed09..4475e09040ce8548aecc03d1a7c9947d5b4cb4d3 100644 --- a/bsp/stm32f10x-HAL/drivers/stm32f1xx_hal_conf.h +++ b/bsp/stm32f10x-HAL/drivers/stm32f1xx_hal_conf.h @@ -80,7 +80,9 @@ #define HAL_PWR_MODULE_ENABLED #define HAL_RCC_MODULE_ENABLED // #define HAL_RTC_MODULE_ENABLED -// #define HAL_SD_MODULE_ENABLED +#ifdef RT_USING_SDCARD + #define HAL_SD_MODULE_ENABLED +#endif // #define HAL_SMARTCARD_MODULE_ENABLED #ifdef RT_USING_SPI #define HAL_SPI_MODULE_ENABLED