Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
SPI
搞定了stm32f0的spi开启DMA
发布于 2020-03-02 10:06:52 浏览:3453
订阅该版
* 本帖最后由 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.5k
关于作者
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
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
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
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部