diff --git a/bsp/stm32f429-apollo/applications/application.c b/bsp/stm32f429-apollo/applications/application.c index 4760de9d4186fac73ca0c6fa5acad7b0bed98cda..556c81e9132cd6473df6705bc82be183e0d335bc 100644 --- a/bsp/stm32f429-apollo/applications/application.c +++ b/bsp/stm32f429-apollo/applications/application.c @@ -77,9 +77,16 @@ void rt_init_thread_entry(void* parameter) rt_kprintf("File System initialzation failed!\n"); } + /* mount sd card fat partition 0 as root directory */ + if (dfs_mount("W25Q256", "/spi", "elm", 0, 0) == 0) + { + rt_kprintf("spi flash mount to /spi !\n"); + } + else + { + rt_kprintf("spi flash mount to /spi failed!\n"); + } #endif /* RT_USING_DFS_ELMFAT */ -// module_ptr = rt_module_open("/hello.mo"); - #endif /* DFS */ /* LwIP Initialization */ diff --git a/bsp/stm32f429-apollo/drivers/SConscript b/bsp/stm32f429-apollo/drivers/SConscript index b7213b6b80ede96529c709e18dc69e6055c7dc0d..26677c31bdf7db76f62d81910227d25eb043c59b 100644 --- a/bsp/stm32f429-apollo/drivers/SConscript +++ b/bsp/stm32f429-apollo/drivers/SConscript @@ -24,6 +24,14 @@ if GetDepend('RT_USING_LWIP'): if GetDepend('RT_USING_PIN'): src += ['gpio.c'] +# add spi drivers. +if GetDepend('RT_USING_SPI'): + src += ['drv_spi.c'] + +# add spi flash drivers. +if GetDepend('RT_USING_SFUD'): + src += ['drv_spi_flash.c'] + CPPPATH = [cwd] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/stm32f429-apollo/drivers/drv_spi.c b/bsp/stm32f429-apollo/drivers/drv_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..c249a0c82f9b9d919eaade794859e2a71fe088f0 --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_spi.c @@ -0,0 +1,734 @@ +/* + * File : drv_spi.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017 RT-Thread Develop 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 + * 2017-06-05 tanek first implementation. + */ + +#include "drv_spi.h" + +#include +#include + +//#define DEBUG + +#ifdef DEBUG +#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +/* private rt-thread spi ops function */ +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 SPI_USE_DMA +static uint8_t dummy = 0xFF; +static void DMA_RxConfiguration(struct rt_spi_bus * spi_bus, + struct rt_spi_message* message) +{ + struct stm32f4_spi *f4_spi = (struct stm32f4_spi *)spi_bus->parent.user_data; + + DMA_HandleTypeDef * hdma_tx = &f4_spi->hdma_tx; + DMA_HandleTypeDef * hdma_rx = &f4_spi->hdma_rx; + + HAL_DMA_DeInit(hdma_tx); + HAL_DMA_DeInit(hdma_rx); + + /* Check if the DMA Stream is disabled before enabling it. + Note that this step is useful when the same Stream is used multiple times: + enabled, then disabled then re-enabled... In this case, the DMA Stream disable + will be effective only at the end of the ongoing data transfer and it will + not be possible to re-configure it before making sure that the Enable bit + has been cleared by hardware. If the Stream is used only once, this step might + be bypassed. */ + while (hdma_tx->Instance->CR & DMA_SxCR_EN); + while (hdma_rx->Instance->CR & DMA_SxCR_EN); + + if(message->recv_buf != RT_NULL) + { + hdma_rx->Init.MemInc = DMA_MINC_ENABLE; + } + else + { + message->recv_buf = &dummy; + hdma_rx->Init.MemInc = DMA_MINC_DISABLE; + } + HAL_DMA_Init(hdma_rx); + + __HAL_LINKDMA(&f4_spi->spi_handle, hdmarx, f4_spi->hdma_rx); + + if(message->send_buf != RT_NULL) + { + hdma_tx->Init.MemInc = DMA_MINC_ENABLE; + } + else + { + dummy = 0xFF; + message->send_buf = &dummy; + hdma_tx->Init.MemInc = DMA_MINC_DISABLE; + } + HAL_DMA_Init(hdma_tx); + + __HAL_LINKDMA(&f4_spi->spi_handle, hdmatx, f4_spi->hdma_tx); + + /* NVIC configuration for DMA transfer complete interrupt*/ + HAL_NVIC_SetPriority(f4_spi->hdma_tx_irq, 0, 1); + HAL_NVIC_EnableIRQ(f4_spi->hdma_tx_irq); + + /* NVIC configuration for DMA transfer complete interrupt*/ + HAL_NVIC_SetPriority(f4_spi->hdma_rx_irq, 0, 0); + HAL_NVIC_EnableIRQ(f4_spi->hdma_rx_irq); + +} +#endif + +static rt_err_t configure(struct rt_spi_device* device, + struct rt_spi_configuration* configuration) +{ + struct rt_spi_bus * spi_bus = (struct rt_spi_bus *)device->bus; + struct stm32f4_spi *f4_spi = (struct stm32f4_spi *)spi_bus->parent.user_data; + SPI_HandleTypeDef * SpiHandle = &f4_spi->spi_handle; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + /* data_width */ + if(configuration->data_width <= 8) + { + SpiHandle->Init.DataSize = SPI_DATASIZE_8BIT; + } + else if(configuration->data_width <= 16) + { + SpiHandle->Init.DataSize = SPI_DATASIZE_16BIT; + } + else + { + return RT_EIO; + } + + /* baudrate */ + { + uint32_t SPI_APB_CLOCK; + uint32_t max_hz; + + max_hz = configuration->max_hz; + + DEBUG_PRINTF("sys freq: %d\n", HAL_RCC_GetSysClockFreq()); + DEBUG_PRINTF("pclk2 freq: %d\n", HAL_RCC_GetPCLK2Freq()); + + SPI_APB_CLOCK = HAL_RCC_GetPCLK2Freq(); + + if(max_hz >= SPI_APB_CLOCK/2) + { + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + } + else if(max_hz >= SPI_APB_CLOCK/4) + { + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; + } + else if(max_hz >= SPI_APB_CLOCK/8) + { + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + } + else if(max_hz >= SPI_APB_CLOCK/16) + { + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; + } + else if(max_hz >= SPI_APB_CLOCK/32) + { + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; + } + else if(max_hz >= SPI_APB_CLOCK/64) + { + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; + } + else if(max_hz >= SPI_APB_CLOCK/128) + { + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; + } + else + { + /* min prescaler 256 */ + SpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; + } + } /* baudrate */ + + /* CPOL */ + if(configuration->mode & RT_SPI_CPOL) + { + SpiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH; + } + else + { + SpiHandle->Init.CLKPolarity = SPI_POLARITY_LOW; + } + /* CPHA */ + if(configuration->mode & RT_SPI_CPHA) + { + SpiHandle->Init.CLKPhase = SPI_PHASE_2EDGE; + } + else + { + SpiHandle->Init.CLKPhase = SPI_PHASE_1EDGE; + } + /* MSB or LSB */ + if(configuration->mode & RT_SPI_MSB) + { + SpiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB; + } + else + { + SpiHandle->Init.FirstBit = SPI_FIRSTBIT_LSB; + } + SpiHandle->Init.Direction = SPI_DIRECTION_2LINES; + SpiHandle->Init.Mode = SPI_MODE_MASTER; + SpiHandle->Init.NSS = SPI_NSS_SOFT; + SpiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + SpiHandle->Init.TIMode = SPI_TIMODE_DISABLE; + + /* init SPI */ + if (HAL_SPI_Init(SpiHandle) != HAL_OK) + { + return RT_ERROR; + } + /* Enable SPI_MASTER */ + __HAL_SPI_ENABLE(SpiHandle); + + DEBUG_PRINTF("spi configuration\n"); + + return RT_EOK; +}; + +static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message) +{ + struct rt_spi_bus * stm32_spi_bus = (struct rt_spi_bus *)device->bus; + struct stm32f4_spi *f4_spi = (struct stm32f4_spi *)stm32_spi_bus->parent.user_data; + struct rt_spi_configuration * config = &device->config; + SPI_TypeDef * SPI = f4_spi->spi_handle.Instance; + struct stm32_spi_cs * stm32_spi_cs = device->parent.user_data; + rt_uint32_t size = message->length; + + RT_ASSERT(device != NULL); + RT_ASSERT(message != NULL); + + /* take CS */ + if(message->cs_take) + { + HAL_GPIO_WritePin(stm32_spi_cs->GPIOx, stm32_spi_cs->GPIO_Pin, GPIO_PIN_RESET); + } + +#ifdef SPI_USE_DMA + if(message->length > 32) + { + if(config->data_width <= 8) + { + HAL_StatusTypeDef state; + DEBUG_PRINTF("spi dma transfer start\n"); + DMA_RxConfiguration(stm32_spi_bus, message); + DEBUG_PRINTF("dma configuration finish , send buf %X, rec buf %X, length: %d\n", + (uint32_t)message->send_buf, (uint32_t)message->recv_buf, message->length); + + state = HAL_SPI_TransmitReceive_DMA(&f4_spi->spi_handle, + (uint8_t*)message->send_buf, + (uint8_t*)message->recv_buf, + message->length); + if (state != HAL_OK) + { + DEBUG_PRINTF("spi flash configuration error : %d\n", state); + message->length = 0; + //while(1); + } + else + { + DEBUG_PRINTF("spi dma transfer finish\n"); + } + + while (HAL_SPI_GetState(&f4_spi->spi_handle) != HAL_SPI_STATE_READY); + DEBUG_PRINTF("spi get state finish\n"); + } + else + { + // Todo + } + } + 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++; + } + + // Todo: replace register read/write by stm32f4 lib + //Wait until the transmit buffer is empty + while ((SPI->SR & SPI_FLAG_TXE) == RESET); + // Send the byte + SPI->DR = data; + + //Wait until a data is received + while ((SPI->SR & SPI_FLAG_RXNE) == RESET); + // Get the received data + data = SPI->DR; + + 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->SR & SPI_FLAG_TXE) == RESET); + // Send the byte + SPI->DR = data; + + //Wait until a data is received + while ((SPI->SR & SPI_FLAG_RXNE) == RESET); + // Get the received data + data = SPI->DR; + + 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); + HAL_GPIO_WritePin(stm32_spi_cs->GPIOx, stm32_spi_cs->GPIO_Pin, GPIO_PIN_SET); + } + + return message->length; +}; + + + + + +#ifdef RT_USING_SPI1 + +static struct stm32f4_spi stm32f4_spi1 = +{ + /* .spi_handle = */{ + /* .Instance = */ SPI1, + }, + /* .hdma_rx = */ { + DMA2_Stream2, + DMA_CHANNEL_3, + }, + /* .hdma_rx_irq = */ DMA2_Stream2_IRQn, + + /* .hdma_tx = */{ + DMA2_Stream3, + DMA_CHANNEL_3, + }, + /* .hdma_tx_irq = */ DMA2_Stream3_IRQn, +}; + +static struct rt_spi_bus spi1_bus; + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream2_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi1.spi_handle.hdmarx); +} +/** + * @brief This function handles DMA Tx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream3_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi1.spi_handle.hdmatx); +} + +#endif + +#ifdef RT_USING_SPI2 + +struct stm32f4_spi stm32f4_spi2 = +{ + /* .spi_handle = */{ + /* .Instance = */ SPI2, + }, + /* .hdma_rx = */ { + DMA1_Stream3, + DMA_CHANNEL_0, + }, + /* .hdma_rx_irq = */ DMA1_Stream3_IRQn, + + /* .hdma_tx = */{ + DMA1_Stream4, + DMA_CHANNEL_0, + }, + /* .hdma_tx_irq = */ DMA1_Stream4_IRQn, +}; + +static struct rt_spi_bus spi2_bus; + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void DMA1_Stream3_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi2.spi_handle.hdmarx); +} +/** + * @brief This function handles DMA Tx interrupt request. + * @param None + * @retval None + */ +void DMA1_Stream4_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi2.spi_handle.hdmatx); +} + +#endif + +#ifdef RT_USING_SPI3 + +struct stm32f4_spi stm32f4_spi3 = +{ + /* .spi_handle = */{ + /* .Instance = */ SPI3, + }, + /* .hdma_rx = */ { + DMA1_Stream0, + DMA_CHANNEL_0, + }, + /* .hdma_rx_irq = */ DMA1_Stream0_IRQn, + + /* .hdma_tx = */{ + DMA1_Stream2, + DMA_CHANNEL_0, + }, + /* .hdma_tx_irq = */ DMA1_Stream2_IRQn, +}; + +static struct rt_spi_bus spi3_bus; + + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void DMA1_Stream0_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi3.spi_handle.hdmarx); +} +/** + * @brief This function handles DMA Tx interrupt request. + * @param None + * @retval None + */ +void DMA1_Stream2_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi3.spi_handle.hdmatx); +} + +#endif + +#ifdef RT_USING_SPI4 + +struct stm32f4_spi stm32f4_spi4 = +{ + /* .spi_handle = */{ + /* .Instance = */ SPI5, + }, + /* .hdma_rx = */ { + DMA2_Stream0, + DMA_CHANNEL_4, + }, + /* .hdma_rx_irq = */ DMA2_Stream0_IRQn, + + /* .hdma_tx = */{ + DMA2_Stream1, + DMA_CHANNEL_4, + }, + /* .hdma_tx_irq = */ DMA2_Stream1_IRQn, +}; + +static struct rt_spi_bus spi4_bus; + + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream0_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi4.spi_handle.hdmarx); +} +/** + * @brief This function handles DMA Tx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream1_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi4.spi_handle.hdmatx); +} + +#endif + +#ifdef RT_USING_SPI5 + +struct stm32f4_spi stm32f4_spi5 = +{ + /* .spi_handle = */{ + /* .Instance = */ SPI5, + }, + /* .hdma_rx = */ { + DMA2_Stream3, + DMA_CHANNEL_2, + }, + /* .hdma_rx_irq = */ DMA2_Stream3_IRQn, + + /* .hdma_tx = */{ + DMA2_Stream4, + DMA_CHANNEL_2, + }, + /* .hdma_tx_irq = */ DMA2_Stream4_IRQn, +}; + +static struct rt_spi_bus spi5_bus; + + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream3_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi5.spi_handle.hdmarx); +} +/** + * @brief This function handles DMA Tx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream4_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi5.spi_handle.hdmatx); +} + +#endif + +#ifdef RT_USING_SPI6 + +struct stm32f4_spi stm32f4_spi6 = +{ + /* .spi_handle = */{ + /* .Instance = */ SPI5, + }, + /* .hdma_rx = */ { + DMA2_Stream6, + DMA_CHANNEL_2, + }, + /* .hdma_rx_irq = */ DMA2_Stream6_IRQn, + + /* .hdma_tx = */{ + DMA2_Stream5, + DMA_CHANNEL_2, + }, + /* .hdma_tx_irq = */ DMA2_Stream5_IRQn, +}; + +static struct rt_spi_bus spi6_bus; + + +/** + * @brief This function handles DMA Rx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream6_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi6.spi_handle.hdmarx); +} +/** + * @brief This function handles DMA Tx interrupt request. + * @param None + * @retval None + */ +void DMA2_Stream5_IRQHandler(void) +{ + HAL_DMA_IRQHandler(stm32f4_spi6.spi_handle.hdmatx); +} + +#endif + +/** \brief init and register stm32 spi bus. + * + * \param SPI: STM32 SPI, e.g: SPI1,SPI2,SPI3. + * \param spi_bus_name: spi bus name, e.g: "spi1" + * \return + * + */ +rt_err_t stm32_spi_bus_register(SPI_TypeDef * SPI, + //struct stm32_spi_bus * stm32_spi, + const char * spi_bus_name) +{ + struct stm32f4_spi * p_spi_bus; + struct rt_spi_bus * spi_bus; + + RT_ASSERT(SPI != RT_NULL); + //RT_ASSERT(stm32_spi != RT_NULL); + RT_ASSERT(spi_bus_name != RT_NULL); + +#ifdef RT_USING_SPI1 + if(SPI == SPI1) + { + #ifdef SPI_USE_DMA + __HAL_RCC_DMA2_CLK_ENABLE(); + p_spi_bus = &stm32f4_spi1; + #endif + __HAL_RCC_SPI1_CLK_ENABLE(); + spi_bus = &spi1_bus; + } +#endif + +#ifdef RT_USING_SPI2 + if(SPI == SPI2) + { + #ifdef SPI_USE_DMA + __HAL_RCC_DMA1_CLK_ENABLE(); + p_spi_bus = &stm32f4_spi2; + #endif + __HAL_RCC_SPI2_CLK_ENABLE(); + spi_bus = &spi2_bus; + } +#endif + +#ifdef RT_USING_SPI3 + if(SPI == SPI3) + { + //stm32_spi->spi_handle.Instance = SPI3; + #ifdef SPI_USE_DMA + __HAL_RCC_DMA1_CLK_ENABLE(); + p_spi_bus = &stm32f4_spi3; + #endif + __HAL_RCC_SPI3_CLK_ENABLE(); + spi_bus = &spi3_bus; + } +#endif + +#ifdef RT_USING_SPI4 + if(SPI == SPI4) + { +#ifdef SPI_USE_DMA + __HAL_RCC_DMA2_CLK_ENABLE(); +#endif + __HAL_RCC_SPI4_CLK_ENABLE(); + spi_bus = &spi4_bus; + } +#endif + +#ifdef RT_USING_SPI5 + if(SPI == SPI5) + { + #ifdef SPI_USE_DMA + __HAL_RCC_DMA2_CLK_ENABLE(); + p_spi_bus = &stm32f4_spi5; + #endif + __HAL_RCC_SPI5_CLK_ENABLE(); + spi_bus = &spi5_bus; + } +#endif + +#ifdef RT_USING_SPI6 + if(SPI == SPI6) + { + #ifdef SPI_USE_DMA + __HAL_RCC_DMA2_CLK_ENABLE(); + p_spi_bus = &stm32f4_spi5; + #endif + __HAL_RCC_SPI6_CLK_ENABLE(); + spi_bus = &spi6_bus; + } +#endif + + if ( (SPI != SPI1) && (SPI != SPI2) && (SPI != SPI3) + && (SPI != SPI4) && (SPI != SPI5) && (SPI != SPI6)) + { + return RT_ENOSYS; + } + + /* Configure the DMA handler for Transmission process */ + p_spi_bus->hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + p_spi_bus->hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; + //p_spi_bus->hdma_tx.Init.MemInc = DMA_MINC_ENABLE; + p_spi_bus->hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + p_spi_bus->hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + p_spi_bus->hdma_tx.Init.Mode = DMA_NORMAL; + p_spi_bus->hdma_tx.Init.Priority = DMA_PRIORITY_LOW; + p_spi_bus->hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + p_spi_bus->hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + p_spi_bus->hdma_tx.Init.MemBurst = DMA_MBURST_INC4; + p_spi_bus->hdma_tx.Init.PeriphBurst = DMA_PBURST_INC4; + + p_spi_bus->hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + p_spi_bus->hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE; + //p_spi_bus->hdma_rx.Init.MemInc = DMA_MINC_ENABLE; + p_spi_bus->hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + p_spi_bus->hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + p_spi_bus->hdma_rx.Init.Mode = DMA_NORMAL; + p_spi_bus->hdma_rx.Init.Priority = DMA_PRIORITY_HIGH; + p_spi_bus->hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + p_spi_bus->hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + p_spi_bus->hdma_rx.Init.MemBurst = DMA_MBURST_INC4; + p_spi_bus->hdma_rx.Init.PeriphBurst = DMA_PBURST_INC4; + + spi_bus->parent.user_data = &stm32f4_spi5; + + return rt_spi_bus_register(spi_bus, spi_bus_name, &stm32_spi_ops); +} diff --git a/bsp/stm32f429-apollo/drivers/drv_spi.h b/bsp/stm32f429-apollo/drivers/drv_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..8967b4b98192c4df96d991943b33e90f12c5001b --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_spi.h @@ -0,0 +1,49 @@ +/* + * File : stm32f20x_40x_spi.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2009 RT-Thread Develop 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 + * 20012-01-01 aozima first implementation. + */ + +#ifndef STM32F20X_40X_SPI_H_INCLUDED +#define STM32F20X_40X_SPI_H_INCLUDED + +#include +#include + +#include "stm32f4xx_hal.h" + +#define SPI_USE_DMA + +struct stm32f4_spi +{ + SPI_HandleTypeDef spi_handle; +#ifdef SPI_USE_DMA + DMA_HandleTypeDef hdma_rx; + IRQn_Type hdma_rx_irq; + + DMA_HandleTypeDef hdma_tx; + IRQn_Type hdma_tx_irq; +#endif /* #ifdef SPI_USE_DMA */ +}; + + +struct stm32_spi_cs +{ + GPIO_TypeDef * GPIOx; + uint16_t GPIO_Pin; +}; + +/* public function */ +rt_err_t stm32_spi_bus_register(SPI_TypeDef * SPI, + //struct stm32_spi_bus * stm32_spi, + const char * spi_bus_name); + +#endif // STM32F20X_40X_SPI_H_INCLUDED diff --git a/bsp/stm32f429-apollo/drivers/drv_spi_flash.c b/bsp/stm32f429-apollo/drivers/drv_spi_flash.c new file mode 100644 index 0000000000000000000000000000000000000000..d570e7d6020d2bd39120f0834b07723d0c1fc32b --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_spi_flash.c @@ -0,0 +1,87 @@ +/* + * File : stm32f20x_40x_spi.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2009 RT-Thread Develop 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 + * 2012-01-01 aozima first implementation. + * 2012-07-27 aozima fixed variable uninitialized. + */ +#include +#include "drv_spi.h" +#include "spi_flash.h" +#include "spi_flash_sfud.h" + +#include +#include + + +static int rt_hw_spi5_init(void) +{ + /* register spi bus */ + { + GPIO_InitTypeDef GPIO_InitStructure; + rt_err_t result; + + __HAL_RCC_GPIOF_CLK_ENABLE(); + + GPIO_InitStructure.Alternate = GPIO_AF5_SPI5; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FAST; + GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9; + HAL_GPIO_Init(GPIOF, &GPIO_InitStructure); + + result = stm32_spi_bus_register(SPI5, "spi5"); + if (result != RT_EOK) + { + return result; + } + } + + /* attach cs */ + { + static struct rt_spi_device spi_device; + static struct stm32_spi_cs spi_cs; + rt_err_t result; + + GPIO_InitTypeDef GPIO_InitStructure; + + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FAST; + + spi_cs.GPIOx = GPIOF; + spi_cs.GPIO_Pin = GPIO_PIN_6; + //__HAL_RCC_GPIOF_CLK_ENABLE(); + + GPIO_InitStructure.Pin = spi_cs.GPIO_Pin; + HAL_GPIO_WritePin(spi_cs.GPIOx, spi_cs.GPIO_Pin, GPIO_PIN_SET); + HAL_GPIO_Init(spi_cs.GPIOx, &GPIO_InitStructure); + + result = rt_spi_bus_attach_device(&spi_device, "spi50", "spi5", (void*)&spi_cs); + if (result != RT_EOK) + { + return result; + } + } + + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_spi5_init); + +static int rt_hw_spi_flash_with_sfud_init(void) +{ + if (RT_NULL == rt_sfud_flash_probe("W25Q256", "spi50")) + { + return RT_ERROR; + }; + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init) diff --git a/bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h b/bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h index c2b889a958d91a0f1484e95052c7d79eb482eb6d..db56b148e470f288a4bc58eb261c00bab6fda221 100644 --- a/bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h +++ b/bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h @@ -73,7 +73,7 @@ #define HAL_RTC_MODULE_ENABLED /* */ /* #define HAL_SAI_MODULE_ENABLED */ #define HAL_SD_MODULE_ENABLED /* */ -/* #define HAL_SPI_MODULE_ENABLED */ +#define HAL_SPI_MODULE_ENABLED /* #define HAL_TIM_MODULE_ENABLED */ #define HAL_UART_MODULE_ENABLED #define HAL_USART_MODULE_ENABLED diff --git a/bsp/stm32f429-apollo/rtconfig.h b/bsp/stm32f429-apollo/rtconfig.h index 9cae871999a0cc31178bf973c4abf21ddaaa738b..2e33285e105fb6e2744bb297bd10f3d07f4d75c5 100644 --- a/bsp/stm32f429-apollo/rtconfig.h +++ b/bsp/stm32f429-apollo/rtconfig.h @@ -135,7 +135,7 @@ #define RT_DFS_ELM_CODE_PAGE 437 #define RT_DFS_ELM_MAX_LFN 255 /* Maximum sector size to be handled. */ -#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 /* DFS: UFFS nand file system options */ @@ -210,4 +210,15 @@ /* RT_GDB_STUB */ //#define RT_USING_GDB +/* spi driver */ +#define RT_USING_SPI +#define RT_USING_SPI5 + +/* Serial Flash Universal Driver */ +#define RT_USING_SFUD +/* Enable SFUD debug output */ +//#define RT_DEBUG_SFUD 1 +/* serial flash discoverable parameters by JEDEC standard */ +#define RT_SFUD_USING_SFDP + #endif