STM32H750VB SPI DMA 接受异常,怀疑硬件或者HAL库的问题
本帖最后由 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
打破零回复。 兄弟,你这个问题解决了吗?我现在也是,使用SPI FLASH,轮询模式没有问题,但是DMA模式接收的数据全是0.不清楚这个是为啥
页:
[1]