Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
SPI
搞定了stm32f0的spi开启DMA
发布于 2020-03-02 10:06:52 浏览:3564
订阅该版
* 本帖最后由 sunwan 于 2020-3-2 10:15 编辑 * stm32f030cc,rt_thread 3.1.3,W25Q80芯片,SPI不开启RX和TX的DMA时,读写正常。在ENV中开启SPI DMA,编译不通过,好多DMA相关的define没有定义,参照f1系列的spi_config.h,修改f0的,如下(大家可以根据芯片手册的DMA通道和IRQ修改成合适的): ```c #ifdef BSP_USING_SPI1 #ifndef SPI1_BUS_CONFIG #define SPI1_BUS_CONFIG \ { \ .Instance = SPI1, \ .bus_name = "spi1", \ } #endif /* SPI1_BUS_CONFIG */ #endif /* BSP_USING_SPI1 */ #if defined(BSP_SPI1_TX_USING_DMA) || defined(BSP_SPI1_RX_USING_DMA) #define SPI1_DMA_IRQHandler DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler #endif #ifdef BSP_SPI1_TX_USING_DMA #ifndef SPI1_TX_DMA_CONFIG #define SPI1_TX_DMA_CONFIG \ { \ .dma_rcc = RCC_AHBENR_DMA1EN, \ .Instance = DMA1_Channel3, \ .dma_irq = DMA1_Ch2_3_DMA2_Ch1_2_IRQn, \ } #endif /* SPI1_TX_DMA_CONFIG */ #endif /* BSP_SPI1_TX_USING_DMA */ #ifdef BSP_SPI1_RX_USING_DMA #ifndef SPI1_RX_DMA_CONFIG #define SPI1_RX_DMA_CONFIG \ { \ .dma_rcc = RCC_AHBENR_DMA1EN, \ .Instance = DMA1_Channel2, \ .dma_irq = DMA1_Ch2_3_DMA2_Ch1_2_IRQn, \ } #endif /* SPI1_RX_DMA_CONFIG */ #endif /* BSP_SPI1_RX_USING_DMA */ #ifdef BSP_USING_SPI2 #ifndef SPI2_BUS_CONFIG #define SPI2_BUS_CONFIG \ { \ .Instance = SPI2, \ .bus_name = "spi2", \ } #endif /* SPI2_BUS_CONFIG */ #endif /* BSP_USING_SPI2 */ #if defined(BSP_SPI2_TX_USING_DMA) || defined(BSP_SPI2_RX_USING_DMA) #define SPI2_DMA_IRQHandler DMA1_Ch4_7_DMA2_Ch3_5_IRQHandler #endif #ifdef BSP_SPI2_TX_USING_DMA #ifndef SPI2_TX_DMA_CONFIG #define SPI2_TX_DMA_CONFIG \ { \ .dma_rcc = RCC_AHBENR_DMA1EN, \ .Instance = DMA1_Channel5, \ .dma_irq = DMA1_Ch4_7_DMA2_Ch3_5_IRQn, \ } #endif /* SPI2_TX_DMA_CONFIG */ #endif /* BSP_SPI2_TX_USING_DMA */ #ifdef BSP_SPI2_RX_USING_DMA #ifndef SPI2_RX_DMA_CONFIG #define SPI2_RX_DMA_CONFIG \ { \ .dma_rcc = RCC_AHBENR_DMA1EN, \ .Instance = DMA1_Channel4, \ .dma_irq = DMA1_Ch4_7_DMA2_Ch3_5_IRQn, \ } #endif /* SPI2_RX_DMA_CONFIG */ #endif /* BSP_SPI2_RX_USING_DMA */ ``` 编译通过了,运行时卡住了,调试发现是卡在了驱动drv_spi.c中的spixfer函数了,停在了 while (HAL_SPI_GetState(spi_handle) != HAL_SPI_STATE_READY); 这句了。 仔细检查drv_spi.c对DMA的初始化,发现最主要的是对stm32f0系列,没有开启DMA时钟,原来RX DMA的代码(410行开始): ```c { rt_uint32_t tmpreg = 0x00U; #if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ SET_BIT(RCC->AHBENR, spi_config*.dma_rx->dma_rcc); tmpreg = READ_BIT(RCC->AHBENR, spi_config*.dma_rx->dma_rcc); #elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) SET_BIT(RCC->AHB1ENR, spi_config*.dma_rx->dma_rcc); /* Delay after an RCC peripheral clock enabling */ tmpreg = READ_BIT(RCC->AHB1ENR, spi_config*.dma_rx->dma_rcc); #endif UNUSED(tmpreg); /* To avoid compiler warnings */ } ``` 原来的TX DMA部分的代码(448行开始): ```c { rt_uint32_t tmpreg = 0x00U; #if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ SET_BIT(RCC->AHBENR, spi_config*.dma_rx->dma_rcc); tmpreg = READ_BIT(RCC->AHBENR, spi_config*.dma_rx->dma_rcc); #elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) SET_BIT(RCC->AHB1ENR, spi_config*.dma_tx->dma_rcc); /* Delay after an RCC peripheral clock enabling */ tmpreg = READ_BIT(RCC->AHB1ENR, spi_config*.dma_tx->dma_rcc); #endif UNUSED(tmpreg); /* To avoid compiler warnings */ } ``` 这两部分中缺少针对stm32f0的编译开关,还有TX中的代码应该是spi_config*.dma_tx->dma_rcc,误写成了spi_config*.dma_rx->dma_rcc,不过一般来说RX和TX的DMA都是同一个时钟,所以对f1系列没有产生错误。分别修改成如下: ```c { rt_uint32_t tmpreg = 0x00U; #if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ SET_BIT(RCC->AHBENR, spi_config*.dma_rx->dma_rcc); tmpreg = READ_BIT(RCC->AHBENR, spi_config*.dma_rx->dma_rcc); #elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) SET_BIT(RCC->AHB1ENR, spi_config*.dma_rx->dma_rcc); /* Delay after an RCC peripheral clock enabling */ tmpreg = READ_BIT(RCC->AHB1ENR, spi_config*.dma_rx->dma_rcc); #endif UNUSED(tmpreg); /* To avoid compiler warnings */ } ``` ```c { rt_uint32_t tmpreg = 0x00U; #if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ SET_BIT(RCC->AHBENR, spi_config*.dma_tx->dma_rcc); tmpreg = READ_BIT(RCC->AHBENR, spi_config*.dma_tx->dma_rcc); #elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) SET_BIT(RCC->AHB1ENR, spi_config*.dma_tx->dma_rcc); /* Delay after an RCC peripheral clock enabling */ tmpreg = READ_BIT(RCC->AHB1ENR, spi_config*.dma_tx->dma_rcc); #endif UNUSED(tmpreg); /* To avoid compiler warnings */ } ``` 同时发现drv_spi.c对stm32f0系列的SPI初始化中有个有可能产生隐患的小问题,f0系列都支持NSSP模式,原驱动对f0的NSSPMode没有赋值,原来代码: ```c #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) spi_handle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; #endif ``` 修改后: ```c #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32F0) spi_handle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; ``` #424147[关于 #ifdef #endif 不能折叠的反馈](Q) ****在drv_spi.c的void SPI1_IRQHandler(void)后面添加DMA的Handler,因为RX DMA和TX DMA的IRQ为同一个,所以要修改了如下,同样对其余的SPI DMA同样处理:** ```c #if defined(BSP_SPI1_TX_USING_DMA) || defined(BSP_SPI1_RX_USING_DMA) void SPI1_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); HAL_SPI_IRQHandler(&spi_bus_obj[SPI1_INDEX].handle); /* leave interrupt */ rt_interrupt_leave(); } #ifdef SPI1_DMA_IRQHandler /** * @brief This function handles DMA Rx or Tx interrupt request for same DMA_NVIC. * @param None * @retval None */ void SPI1_DMA_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); #if defined(BSP_USING_SPI1) && defined(BSP_SPI1_RX_USING_DMA) HAL_DMA_IRQHandler(&spi_bus_obj[SPI1_INDEX].dma.handle_rx); #endif #if defined(BSP_USING_SPI1) && defined(BSP_SPI1_TX_USING_DMA) HAL_DMA_IRQHandler(&spi_bus_obj[SPI1_INDEX].dma.handle_tx); #endif /* leave interrupt */ rt_interrupt_leave(); } #endif //SPI1_DMA_IRQHandler #endif //defined(BSP_SPI1_TX_USING_DMA) || defined(BSP_SPI1_RX_USING_DMA) ``` **经过修改编译后一次通过。**
查看更多
2
个回答
默认排序
按发布时间排序
我夏了夏天
认证专家
2020-03-02
Life isn't about finding yourself, life is about creating yourself.
楼主大赞,可以尝试给 rtt 提交一个 PR 哦 :D
我夏了夏天
认证专家
2020-03-02
Life isn't about finding yourself, life is about creating yourself.
关于这些 DMA 的配置信息,以后使用 RTT IDE 的话可以图形化配置了,这些功能在后续几个版本会逐渐加上来 :lol
撰写答案
登录
注册新账号
关注者
2
被浏览
3.6k
关于作者
sunwan
这家伙很懒,什么也没写!
提问
10
回答
91
被采纳
0
关注TA
发私信
相关问题
1
BBB的SPI驱动
2
求个SPI上挂两个或多个设备的使用例子
3
SPI设备有个bug
4
spi flash 的fatfs使用一段时间后读写文件出现故障
5
SPI驱动
6
请教rt_spi_configure函数理解
7
SPI FLASH挂载的问题
8
SPI-FLASH 文件系统 SPIFFS
9
求助一个完整的 spi flash 驱动
10
关于同时使用文件系统与SPI FLASH的问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
单片机也能聊天?RT-Thread上跑通大语言模型
2
【RT-Thread】【ci】【scons】将ci.attachconfig.yml和scons结合使用
3
Rt-thread中OTA下载后,bootloader不搬程序
4
ulog 日志 LOG_HEX 输出时间改为本地日期时间
5
在RT-Thread Studio中构建前执行python命令
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
5
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部