Browse Source

[bsp] stm32f429-apollo added spi flash driver and mount as FatFs

tanek liang 8 years ago
parent
commit
e4999e60b0

+ 9 - 2
bsp/stm32f429-apollo/applications/application.c

@@ -77,9 +77,16 @@ void rt_init_thread_entry(void* parameter)
             rt_kprintf("File System initialzation failed!\n");
             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 */
     #endif /* RT_USING_DFS_ELMFAT */
-//    module_ptr = rt_module_open("/hello.mo");
-    
         
         
 #endif /* DFS */
 #endif /* DFS */
     /* LwIP Initialization */
     /* LwIP Initialization */

+ 8 - 0
bsp/stm32f429-apollo/drivers/SConscript

@@ -24,6 +24,14 @@ if GetDepend('RT_USING_LWIP'):
 if GetDepend('RT_USING_PIN'):
 if GetDepend('RT_USING_PIN'):
     src += ['gpio.c']
     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]
 CPPPATH = [cwd]
 
 
 group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
 group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)

+ 734 - 0
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 <board.h>
+#include <finsh.h>
+
+//#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);
+}

+ 49 - 0
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 <rtthread.h>
+#include <drivers/spi.h>
+
+#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

+ 87 - 0
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 <board.h>
+#include "drv_spi.h"
+#include "spi_flash.h"
+#include "spi_flash_sfud.h"
+
+#include <rthw.h>
+#include <finsh.h>
+
+
+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)

+ 1 - 1
bsp/stm32f429-apollo/drivers/stm32f4xx_hal_conf.h

@@ -73,7 +73,7 @@
 #define HAL_RTC_MODULE_ENABLED   /* */
 #define HAL_RTC_MODULE_ENABLED   /* */
 /* #define HAL_SAI_MODULE_ENABLED   */
 /* #define HAL_SAI_MODULE_ENABLED   */
 #define HAL_SD_MODULE_ENABLED   /* */
 #define HAL_SD_MODULE_ENABLED   /* */
-/* #define HAL_SPI_MODULE_ENABLED   */
+#define HAL_SPI_MODULE_ENABLED
 /* #define HAL_TIM_MODULE_ENABLED   */
 /* #define HAL_TIM_MODULE_ENABLED   */
 #define HAL_UART_MODULE_ENABLED
 #define HAL_UART_MODULE_ENABLED
 #define HAL_USART_MODULE_ENABLED   
 #define HAL_USART_MODULE_ENABLED   

+ 12 - 1
bsp/stm32f429-apollo/rtconfig.h

@@ -135,7 +135,7 @@
 #define RT_DFS_ELM_CODE_PAGE        437
 #define RT_DFS_ELM_CODE_PAGE        437
 #define RT_DFS_ELM_MAX_LFN			255
 #define RT_DFS_ELM_MAX_LFN			255
 /* Maximum sector size to be handled. */
 /* 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 */
 /* DFS: UFFS nand file system options */
@@ -210,4 +210,15 @@
 /* RT_GDB_STUB */
 /* RT_GDB_STUB */
 //#define RT_USING_GDB
 //#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
 #endif