在 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.c、drv_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. 测试与调试
- 编译下载后,先单独测试 SPI DMA 和 I2C DMA 功能。
- 同时启用两个外设,使用逻辑分析仪或示波器检查信号:
- 如果仍报错,检查
dma_config 结构体中的 .priority 字段,避免通道优先级冲突。
- 在
drv_dma.c 中添加调试日志,确认通道分配是否正确。
补充说明
- 关键文件:
- DMA 配置:
libraries/drivers/drv_dma.c
- SPI/I2C 驱动:
libraries/drivers/spi/drv_spi.c、libraries/drivers/i2c/drv_i2c.c
- 板级支持:
board/board.c
- 参考示例:
查阅 AT32 官方库的 SPI_DMA 和 I2C_DMA 例程,对比通道配置。
通过以上步骤,SPI DMA 与 I2C DMA 的冲突问题应能得到解决。核心思路是确保硬件通道无冲突并解除软件层的条件宏限制。
在 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.c、drv_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. 测试与调试
- 编译下载后,先单独测试 SPI DMA 和 I2C DMA 功能。
- 同时启用两个外设,使用逻辑分析仪或示波器检查信号:
- 如果仍报错,检查
dma_config 结构体中的 .priority 字段,避免通道优先级冲突。
- 在
drv_dma.c 中添加调试日志,确认通道分配是否正确。
补充说明
- 关键文件:
- DMA 配置:
libraries/drivers/drv_dma.c
- SPI/I2C 驱动:
libraries/drivers/spi/drv_spi.c、libraries/drivers/i2c/drv_i2c.c
- 板级支持:
board/board.c
- 参考示例:
查阅 AT32 官方库的 SPI_DMA 和 I2C_DMA 例程,对比通道配置。
通过以上步骤,SPI DMA 与 I2C DMA 的冲突问题应能得到解决。核心思路是确保硬件通道无冲突并解除软件层的条件宏限制。
举报