RT-Thread论坛
直播中

李玲

8年用户 1314经验值
私信 关注
[问答]

AT32F403A 移植RT-thread时SPI DMA和I2C DMA 冲突怎么解决?

开发板:AT-START-F403A V1.1
我使用官方标准版RT-Thread BSP里的工程时,通过ENV工具启用了SPI和I2C ,但是启用了SPI RX/TX DMA之后I2C 就会报错,后来分析源码发现代码里有条件宏,启用了SPI后就会屏蔽I2C的某些宏定义,如果同时要用到SPI和I2C 的话有没有什么办法可以解决这个冲突?



回帖(1)

李明

2025-10-20 17:02:33

在 AT32F403A 上同时使用 SPI DMA 和 I2C DMA 时出现冲突,主要是因为 BSP 中的 DMA 通道资源分配冲突或条件编译宏限制了共存。以下是详细的解决方案:




1. 检查并修正 DMA 通道冲突


SPI 和 I2C 的 DMA 请求可能映射到了相同的 DMA 通道(同一 DMA 的同一通道不能复用)。请按以下步骤调整:


(1) 查询 DMA 请求映射表


参考 AT32F403A 数据手册(或直接查看库文件 at32f403a_407.h),确认外设与 DMA 通道的映射关系:



  • SPI1

    • RX → DMA1 通道 2

    • TX → DMA1 通道 3


  • I2C1

    • RX → DMA1 通道 6

    • TX → DMA1 通道 7

      (注:不同型号映射可能不同,务必核对手册)



(2) 修改 BSP 中的 DMA 分配


board/drv_dma.c 或类似文件中,调整 DMA 通道配置,确保 SPI 和 I2C 使用 不同的 DMA 通道


// 示例:drv_dma.c 中调整通道定义
#ifdef BSP_SPI1_RX_USING_DMA
    static dma_config_t spi1_dma_rx = {
        .instance        = DMA1_CHANNEL2, // 确保不与其他外设冲突
        .irq_priority    = ...,
    };
#endif

#ifdef BSP_I2C1_RX_USING_DMA
    static dma_config_t i2c1_dma_rx = {
        .instance        = DMA1_CHANNEL6, // 使用空闲通道
        .irq_priority    = ...,
    };
#endif

(3) 检查 DMA 中断冲突


确保不同 DMA 通道的中断向量已正确注册,并在 rt_hw_dma_init() 中初始化所有通道。




2. 修正条件编译宏


BSP 中可能存在互斥的条件宏(例如启用 SPI DMA 时禁用 I2C DMA)。解决步骤如下:


(1) 定位问题宏


搜索 BSP 代码(如 drv_i2c.cdrv_spi.c),找到类似以下结构的代码:


#if defined(BSP_USING_SPI1_DMA) || defined(BSP_USING_SPI2_DMA)
    // 此处可能禁用了 I2C DMA 相关配置
    #undef BSP_USING_I2C_DMA
#endif

(2) 修改宏逻辑


取消 SPI 和 I2C DMA 的互斥关系,允许共存:


// 错误示例:删除或修改为独立条件
#ifdef BSP_USING_I2C1
    // I2C DMA 配置代码(无条件保留)
#endif

(3) 在 ENV 中同时启用


menuconfig 中启用以下选项:


Hardware Drivers Config 
    -> On-chip Peripheral Drivers
        [*] Enable SPI1 BUS
        [*]   Enable SPI1 DMA RX and TX
        [*] Enable I2C1 BUS
        [*]   Enable I2C1 DMA RX and TX



3. 验证资源分配


检查工程全局的 DMA 和中断资源是否冲突:



  • DMA 控制器:确保 SPI 和 I2C 使用的 DMA 通道属于不同 DMA 控制器(如 SPI 用 DMA1,I2C 用 DMA2)。

  • 中断向量:确认 DMA1_Channel2_IRQn(SPI1 RX)和 DMA1_Channel6_IRQn(I2C1 RX)等中断已正确定义在 board.h 中。




4. 完善驱动初始化


确保 DMA 初始化顺序正确,在 rt_hw_board_init() 中优先初始化 DMA:


int rt_hw_board_init()
{
    rt_hw_dma_init();  // 先初始化 DMA 框架
    rt_hw_spi_init();  // 再初始化 SPI
    rt_hw_i2c_init();  // 最后初始化 I2C
    ...
}



5. 测试与调试



  1. 编译下载后,先单独测试 SPI DMA 和 I2C DMA 功能。

  2. 同时启用两个外设,使用逻辑分析仪或示波器检查信号:

    • 如果仍报错,检查 dma_config 结构体中的 .priority 字段,避免通道优先级冲突。

    • drv_dma.c 中添加调试日志,确认通道分配是否正确。





补充说明



  • 关键文件:  

    • DMA 配置:libraries/drivers/drv_dma.c  

    • SPI/I2C 驱动:libraries/drivers/spi/drv_spi.clibraries/drivers/i2c/drv_i2c.c  

    • 板级支持:board/board.c  


  • 参考示例

    查阅 AT32 官方库的 SPI_DMAI2C_DMA 例程,对比通道配置。


通过以上步骤,SPI DMA 与 I2C DMA 的冲突问题应能得到解决。核心思路是确保硬件通道无冲突解除软件层的条件宏限制

举报

更多回帖

发帖
×
20
完善资料,
赚取积分