本帖最后由 uu799 于 2019-5-15 18:49 编辑
最近在在H750VB移植RT-Thread最新发布的RW007 SPI WIFI,目前已经把轮训模式调通,但是由于SPI WIFI的通讯速度很高,轮训容易把CPU吃满,所以准备使用SPI DMA去处理,但是使用HAL1.4.0版本的库,使用SPI DMA的API只发送是正常的,但是一旦DMA接受就异常,SPI DMA无法再次正常通讯,相同逻辑在F4是可以正常运行。
下面是基于RTT的SPI驱动,SPI DMA区域在AXI区域不在TCM内存区域,没有开启cache。不知道有人遇到和我一样的问题吗,调试了1周无果,虚心请求解答。
- /*
- * @File: drv_sdcard.c
- * @Author: liuguang
- * @Date: 2019-02-24 23:48:19
- *
- * @LICENSE:
- * The code owner is liuguang. Other personnel may
- * not be used or modified.
- *
- * Change Logs:
- * Date Author Notes
- * 2019-02-24 liuguang The first version.
- */
-
- #include "drv_spi.h"
- #include "board.h"
- #include "rtdevice.h"
- // iperf:
- #define BSP_SPI_ENABLE_DEBUG
- //#define BSP_SPI_USING_DMA
- #define DBG_ENABLE
- #define DBG_SECTION_NAME "drv.spi"
- #if defined(BSP_SPI_ENABLE_DEBUG)
- #define DBG_LEVEL DBG_LOG
- #else
- #define DBG_LEVEL DBG_INFO
- #endif
- #define DBG_COLOR
- #include <rtdbg.h>
- struct stm32_spi
- {
- SPI_HandleTypeDef hspi;
- struct rt_spi_configuration *cfg;
- #if defined(BSP_SPI_USING_DMA)
- DMA_HandleTypeDef hdma_tx;
- DMA_HandleTypeDef hdma_rx;
- #endif
- };
- typedef struct stm32_spi* stm32_spi_t;
- struct stm32_spi_cs
- {
- rt_uint32_t pin;
- };
- typedef struct stm32_spi_cs* stm32_spi_cs_t;
- #if defined(BSP_SPI_ENABLE_PORT3)
- static __align(8) struct stm32_spi spi3 = {.hspi.Instance = SPI3};
- static __align(8) struct rt_spi_bus spi3_bus = {.parent.user_data = &spi3};
- #endif
- #if defined(BSP_SPI_ENABLE_PORT4)
- static __align(8) struct stm32_spi spi4 = {.hspi.Instance = SPI4};
- static __align(8) struct rt_spi_bus spi4_bus = {.parent.user_data = &spi4};
- #endif
- static rt_uint32_t get_spi_clk_source_freq(SPI_HandleTypeDef *hspi)
- {
- rt_uint32_t freq = 0;
- #if defined(BSP_SPI_ENABLE_PORT3)
- if(hspi->Instance == SPI3)
- {
- PLL1_ClocksTypeDef pll1 = {0};
-
- HAL_RCCEx_GetPLL1ClockFreq(&pll1);
- freq = (rt_uint32_t)pll1.PLL1_Q_Frequency;
- }
- #endif
- #if defined(BSP_SPI_ENABLE_PORT4)
- if(hspi->Instance == SPI4)
- {
- PLL2_ClocksTypeDef pll2 = {0};
-
- HAL_RCCEx_GetPLL2ClockFreq(&pll2);
- freq = (rt_uint32_t)pll2.PLL2_Q_Frequency;
- }
- #endif
- return freq;
- }
- static rt_err_t spi_init(stm32_spi_t spi, struct rt_spi_configuration *cfg)
- {
- rt_uint32_t freq = 0;
- rt_uint32_t divx = 0;
- rt_uint32_t max_hz = 0;
- SPI_HandleTypeDef *hspi = &(spi->hspi);
- RT_ASSERT(spi != RT_NULL);
- RT_ASSERT(cfg != RT_NULL);
- if((cfg->data_width >= 4) && (cfg->data_width <= 32))
- {
- LOG_D("SPI_DATASIZE_8BIT");
- hspi->Init.DataSize = SPI_DATASIZE_8BIT;
- }
- else
- {
- LOG_E("SPI data width error.");
- return (-RT_EINVAL);
- }
- /* 计算能配置的最接近(不高于)于目标时钟频率的分频数 */
- max_hz = cfg->max_hz;
- freq = get_spi_clk_source_freq(hspi);
- divx = divx;
- if(max_hz >= freq/4)
- {
- divx = 4;
- hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
- }
- else if(max_hz >= freq/8)
- {
- divx = 8;
- hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
- }
- else if(max_hz >= freq/16)
- {
- divx = 16;
- hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
- }
- else if(max_hz >= freq/32)
- {
- divx = 32;
- hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
- }
- else if(max_hz >= freq/64)
- {
- divx = 64;
- hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
- }
- else if(max_hz >= freq/128)
- {
- divx = 128;
- hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
- }
- else
- {
- divx = 256;
- hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
- }
- LOG_D("spi clk source freq is %dHz.", freq);
- LOG_D("spi clk target freq is %dHz.", cfg->max_hz);
- LOG_D("spi clk divx is %d.", divx);
- LOG_D("spi clk freq is %dHz.", freq / divx);
- /* CPOL */
- if(cfg->mode & RT_SPI_CPOL)
- {
- LOG_D("SPI_POLARITY_HIGH");
- hspi->Init.CLKPolarity = SPI_POLARITY_HIGH;
- }
- else
- {
- LOG_D("SPI_POLARITY_LOW");
- hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
- }
- /* CPHA */
- if(cfg->mode & RT_SPI_CPHA)
- {
- LOG_D("SPI_PHASE_2EDGE");
- hspi->Init.CLKPhase = SPI_PHASE_2EDGE;
- }
- else
- {
- LOG_D("SPI_PHASE_1EDGE");
- hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
- }
- /* MSB or LSB */
- if(cfg->mode & RT_SPI_MSB)
- {
- LOG_D("SPI_FIRSTBIT_MSB");
- hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
- }
- else
- {
- LOG_D("SPI_FIRSTBIT_LSB");
- hspi->Init.FirstBit = SPI_FIRSTBIT_LSB;
- }
- /* SPI3强制为3线模式3WIRE */
- if(hspi->Instance == SPI3)
- {
- LOG_D("SPI_DIRECTION_2LINES_TXONLY");
- hspi->Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
- }
- else
- {
- LOG_D("SPI_DIRECTION_2LINES");
- hspi->Init.Direction = SPI_DIRECTION_2LINES;
- }
-
- /* DMA */
- #if defined(BSP_SPI_USING_DMA)
- if(hspi->Instance == SPI4)
- {
- __HAL_RCC_DMA2_CLK_ENABLE();
-
- spi->hdma_rx.Instance = DMA2_Stream2;
- spi->hdma_rx.Init.Request = DMA_REQUEST_SPI4_RX;
- spi->hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
- spi->hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
- spi->hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
- spi->hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
- spi->hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
- spi->hdma_rx.Init.Mode = DMA_NORMAL;
- spi->hdma_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
- spi->hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
- spi->hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
- spi->hdma_rx.Init.MemBurst = DMA_MBURST_INC4;
- spi->hdma_rx.Init.PeriphBurst = DMA_PBURST_INC4;
-
- spi->hdma_tx.Instance = DMA2_Stream3;
- spi->hdma_tx.Init.Request = DMA_REQUEST_SPI4_TX;
- spi->hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
- spi->hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
- spi->hdma_tx.Init.MemInc = DMA_MINC_ENABLE;
- spi->hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
- spi->hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
- spi->hdma_tx.Init.Mode = DMA_NORMAL;
- spi->hdma_tx.Init.Priority = DMA_PRIORITY_LOW;
- spi->hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
- spi->hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
- spi->hdma_tx.Init.MemBurst = DMA_MBURST_INC4;
- spi->hdma_tx.Init.PeriphBurst = DMA_PBURST_INC4;
- HAL_DMA_Abort(&(spi4.hdma_rx));
- HAL_DMA_DeInit(&(spi->hdma_rx));
- HAL_DMA_Init(&(spi->hdma_rx));
- __HAL_LINKDMA(hspi, hdmatx, spi->hdma_rx);
-
- HAL_DMA_Abort(&(spi4.hdma_tx));
- HAL_DMA_DeInit(&(spi->hdma_tx));
- HAL_DMA_Init(&(spi->hdma_tx));
- __HAL_LINKDMA(hspi, hdmatx, spi->hdma_tx);
-
- HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 1, 0);
- HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
- HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 1, 1);
- HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
- LOG_D("spi4 dma configuration.");
- }
- #endif
-
- hspi->Init.Mode = SPI_MODE_MASTER;
- hspi->Init.NSS = SPI_NSS_SOFT;
- hspi->Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
- hspi->Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
- hspi->Init.TIMode = SPI_TIMODE_DISABLE;
- hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
- hspi->Init.CRCPolynomial = 7;
- hspi->Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
- hspi->Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
- hspi->Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
- hspi->Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
- hspi->Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
- hspi->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
- hspi->Init.IOSwap = SPI_IO_SWAP_DISABLE;
- hspi->Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
-
- HAL_SPI_Abort(hspi);
- HAL_SPI_DeInit(hspi);
- if (HAL_SPI_Init(hspi) != HAL_OK)
- {
- return (-RT_ERROR);
- }
-
- // HAL_NVIC_SetPriority(SPI4_IRQn, 1, 0);
- // HAL_NVIC_EnableIRQ(SPI4_IRQn);
- rt_thread_mdelay(100);
- LOG_D("spi configuration.");
- return RT_EOK;
- }
- static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
- {
- rt_err_t ret = RT_EOK;
- struct stm32_spi *spi = (struct stm32_spi *)device->bus->parent.user_data;
- spi->cfg = cfg;
- ret = spi_init(spi, cfg);
- return ret;
- }
- static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
- {
- HAL_StatusTypeDef ret;
- rt_uint32_t length = message->length;
-
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(device->bus != RT_NULL);
- RT_ASSERT(device->bus->parent.user_data != RT_NULL);
- struct stm32_spi *spi = (struct stm32_spi *)device->bus->parent.user_data;
- struct stm32_spi_cs *cs = device->parent.user_data;
- if (message->cs_take)
- {
- rt_pin_write(cs->pin, PIN_LOW);
- }
-
- if(message->length == 0)
- {
- length = 0;
- goto _ret;
- }
-
- if(message->send_buf == RT_NULL && message->recv_buf == RT_NULL)
- {
- LOG_E("send_buf and recv_buf is null.");
- while(1);
- }
- else if(message->send_buf != RT_NULL && message->recv_buf == RT_NULL)
- {
- #if defined(BSP_SPI_USING_DMA)
- SCB_InvalidateDCache_by_Addr((uint32_t *)message->send_buf, message->length);
- ret = HAL_SPI_Transmit_DMA(&(spi->hspi), (uint8_t *)(message->send_buf), message->length);
- #else
- ret = HAL_SPI_Transmit(&(spi->hspi), (uint8_t *)(message->send_buf), message->length, 1000);
- #endif
- if(ret != HAL_OK)
- {
- LOG_E("HAL_SPI_Transmit = failed.", ret);
- while(1);
- }
- #if defined(BSP_SPI_USING_DMA)
- else
- {
- LOG_D("HAL_SPI_Transmit = ok.");
- }
- #endif
- }
- else if(message->send_buf == RT_NULL && message->recv_buf != RT_NULL)
- {
- #if defined(BSP_SPI_USING_DMA)
- SCB_InvalidateDCache_by_Addr((uint32_t *)message->recv_buf, message->length);
- ret = HAL_SPI_Receive_DMA(&(spi->hspi), (uint8_t *)(message->recv_buf), message->length);
- #else
- ret = HAL_SPI_Receive(&(spi->hspi), (uint8_t *)(message->recv_buf), message->length, 1000);
- #endif
- if(ret != HAL_OK)
- {
- LOG_E("HAL_SPI_Receive = failed.", ret);
- while(1);
- }
- #if defined(BSP_SPI_USING_DMA)
- else
- {
- LOG_D("HAL_SPI_Receive = ok.");
- }
- #endif
- }
- else if(message->send_buf != RT_NULL && message->recv_buf != RT_NULL)
- {
- #if defined(BSP_SPI_USING_DMA)
- SCB_InvalidateDCache_by_Addr((uint32_t *)message->send_buf, message->length);
- SCB_InvalidateDCache_by_Addr((uint32_t *)message->recv_buf, message->length);
- ret = HAL_SPI_TransmitReceive_DMA(&(spi->hspi), (uint8_t *)(message->send_buf), (uint8_t *)(message->recv_buf), message->length);
- #else
- ret = HAL_SPI_TransmitReceive(&(spi->hspi), (uint8_t *)(message->send_buf), (uint8_t *)(message->recv_buf), message->length, 1000);
- #endif
- if(ret != HAL_OK)
- {
- LOG_E("HAL_SPI_TransmitReceive = failed.", ret);
- while(1);
- }
- #if defined(BSP_SPI_USING_DMA)
- else
- {
- LOG_D("HAL_SPI_TransmitReceive = ok.");
- }
- #endif
- }
- #if defined(BSP_SPI_USING_DMA)
- rt_thread_mdelay(1000);
- #else
- while (HAL_SPI_GetState(&(spi->hspi)) != HAL_SPI_STATE_READY);
- #endif
- _ret:
- if (message->cs_release)
- {
- rt_pin_write(cs->pin, PIN_HIGH);
- }
- return length;
- }
- rt_err_t stm32_spi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint32_t pin)
- {
- rt_err_t ret = RT_EOK;
-
- struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
- RT_ASSERT(spi_device != RT_NULL);
- struct stm32_spi_cs *cs_pin = (struct stm32_spi_cs *)rt_malloc(sizeof(struct stm32_spi_cs));
- RT_ASSERT(cs_pin != RT_NULL);
- cs_pin->pin = pin;
- rt_pin_mode(pin, PIN_MODE_OUTPUT);
- rt_pin_write(pin, PIN_HIGH);
-
- ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
-
- return ret;
- }
- void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- LOG_D("HAL_SPI_MspInit");
-
- #if defined(BSP_SPI_ENABLE_PORT3)
- if(hspi->Instance == SPI3)
- {
- __HAL_RCC_SPI3_CLK_ENABLE();
- __HAL_RCC_GPIOC_CLK_ENABLE();
- GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_12;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
- }
- #endif
-
- #if defined(BSP_SPI_ENABLE_PORT4)
- if(hspi->Instance == SPI4)
- {
- __HAL_RCC_SPI4_CLK_ENABLE();
- __HAL_RCC_GPIOE_CLK_ENABLE();
- GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
- HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
- }
- #endif
- }
- void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
- {
- #if defined(BSP_SPI_ENABLE_PORT3)
- if(hspi->Instance == SPI3)
- {
- __HAL_RCC_SPI3_CLK_DISABLE();
- HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10 | GPIO_PIN_12);
- }
- #endif
-
- #if defined(BSP_SPI_ENABLE_PORT4)
- if(hspi->Instance == SPI4)
- {
- __HAL_RCC_SPI4_CLK_DISABLE();
- HAL_GPIO_DeInit(GPIOE, GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);
- }
- #endif
- }
- static struct rt_spi_ops ops = {configure, spixfer};
- int rt_hw_spi_init(void)
- {
- #if defined(BSP_SPI_ENABLE_PORT3)
- rt_spi_bus_register(&spi3_bus, "spi3", &ops);
- #endif
- #if defined(BSP_SPI_ENABLE_PORT4)
- rt_spi_bus_register(&spi4_bus, "spi4", &ops);
- #endif
- return RT_EOK;
- }
- INIT_DEVICE_EXPORT(rt_hw_spi_init);
- #if defined(BSP_SPI_USING_DMA)
- void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
- {
- #if defined(BSP_SPI_ENABLE_PORT4)
- if(hspi->Instance == SPI4)
- {
- LOG_I("HAL_SPI_TxRxCpltCallbacks.");
- }
- #endif
- }
- #if defined(BSP_SPI_ENABLE_PORT4)
- void DMA2_Stream2_IRQHandler(void)
- {
- HAL_DMA_IRQHandler(&(spi4.hdma_rx));
- }
- void DMA2_Stream3_IRQHandler(void)
- {
- HAL_DMA_IRQHandler(&(spi4.hdma_tx));
- }
- void SPI4_IRQHandler(void)
- {
- HAL_SPI_IRQHandler(&(spi4.hspi));
- }
- #endif
- #endif
复制代码
|