DMA中断寄存器及错误详解
目录
DMA中断概述
直接内存访问(DMA)控制器通过中断机制向处理器报告传输状态和错误情况。合理配置中断寄存器对于实现高效的DMA数据传输至关重要。
主要中断寄存器
1. 全局中断状态寄存器 (GISR/DMA_ISR)
| 位域 | 名称 | 描述 | 访问类型 |
|---|---|---|---|
| 31:16 | Reserved | 保留位 | 只读 |
| 15:0 | TCIFx | 通道x传输完成标志 (x=0…15) | 只读 |
| 15:0 | HTIFx | 通道x半传输完成标志 (x=0…15) | 只读 |
| 15:0 | TEIFx | 通道x传输错误标志 (x=0…15) | 只读 |
| 15:0 | GIFx | 通道x全局中断标志 (x=0…15) | 只读 |
功能说明:
- 用于查询所有通道的中断状态
- 每个通道占用4个位:TCIF, HTIF, TEIF, GIF
- 读取后需要清除相应标志位
2. 全局中断清除寄存器 (GIFCR/DMA_IFCR)
| 位域 | 名称 | 描述 | 访问类型 |
|---|---|---|---|
| 31:16 | Reserved | 保留位 | 只写 |
| 15:0 | CTCIFx | 清除通道x传输完成标志 (x=0…15) | 只写 |
| 15:0 | CHTIFx | 清除通道x半传输完成标志 (x=0…15) | 只写 |
| 15:0 | CTEIFx | 清除通道x传输错误标志 (x=0…15) | 只写 |
| 15:0 | CGIFx | 清除通道x全局中断标志 (x=0…15) | 只写 |
功能说明:
- 用于清除中断标志位
- 向相应位写入1可清除标志
- 写入0不影响标志状态
3. 通道中断使能寄存器 (CCR/DMA_CCRx)
| 位域 | 名称 | 描述 | 访问类型 |
|---|---|---|---|
| 7 | MEM2MEM | 存储器到存储器模式 | 读写 |
| 6 | PL[1:0] | 通道优先级 | 读写 |
| 5 | MSIZE[1:0] | 存储器数据大小 | 读写 |
| 4 | PSIZE[1:0] | 外设数据大小 | 读写 |
| 3 | MINC | 存储器地址增量模式 | 读写 |
| 2 | PINC | 外设地址增量模式 | 读写 |
| 1 | CIRC | 循环模式 | 读写 |
| 0 | EN | 通道使能 | 读写 |
| 4 | TCIE | 传输完成中断使能 | 读写 |
| 3 | HTIE | 半传输中断使能 | 读写 |
| 2 | TEIE | 传输错误中断使能 | 读写 |
功能说明:
- 控制单个通道的中断使能
- 可以独立配置三种中断类型
- 必须在通道使能前配置
DMA错误类型
1. 传输错误 (Transfer Error)
产生原因:
- 访问未对齐的内存地址
- 访问受保护的内存区域
- 总线访问超时
- 外设FIFO溢出/下溢
特征:
- 触发TEIF标志置位
- 如果TEIE使能,会产生中断
- 传输自动停止
2. FIFO错误
产生原因:
- FIFO阈值设置不当
- 数据传输速率不匹配
- 外设响应超时
检测方法:
- 检查DMA_FCR寄存器状态位
- 监控FIFO状态标志
3. 配置错误
常见配置错误:
- 源地址和目标地址重叠
- 数据大小不匹配
- 缓冲区大小不足
- 优先级配置冲突
4. 总线错误
产生原因:
- AHB总线访问冲突
- 内存控制器错误
- DMA仲裁失败
中断处理流程
中断服务程序模板
void DMA1_Channel1_IRQHandler(void)
{
/* 检查传输完成中断 */
if (DMA1->ISR & DMA_ISR_TCIF1) {
/* 清除传输完成标志 */
DMA1->IFCR |= DMA_IFCR_CTCIF1;
/* 处理传输完成 */
DMA_TransferComplete_Callback();
}
/* 检查半传输中断 */
if (DMA1->ISR & DMA_ISR_HTIF1) {
/* 清除半传输标志 */
DMA1->IFCR |= DMA_IFCR_CHTIF1;
/* 处理半传输完成 */
DMA_HalfTransfer_Callback();
}
/* 检查传输错误中断 */
if (DMA1->ISR & DMA_ISR_TEIF1) {
/* 清除传输错误标志 */
DMA1->IFCR |= DMA_IFCR_CTEIF1;
/* 处理传输错误 */
DMA_TransferError_Callback();
}
}
编程示例
DMA初始化配置
void DMA_Init(void)
{
/* 启用DMA时钟 */
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
/* 配置DMA通道 */
DMA1_Channel1->CCR &= ~DMA_CCR_EN; // 确保DMA禁用
/* 设置传输参数 */
DMA1_Channel1->CCR =
DMA_CCR_MEM2MEM | // 存储器到存储器模式
(0x01 << 12) | // 通道优先级:高
DMA_CCR_MSIZE_0 | // 存储器数据大小:16位
DMA_CCR_PSIZE_0 | // 外设数据大小:16位
DMA_CCR_MINC | // 存储器地址递增
DMA_CCR_PINC | // 外设地址递增
DMA_CCR_TCIE | // 传输完成中断使能
DMA_CCR_TEIE; // 传输错误中断使能
/* 设置数据传输数量 */
DMA1_Channel1->CNDTR = BUFFER_SIZE;
/* 设置外设地址 */
DMA1_Channel1->CPAR = (uint32_t)&(PERIPH->DR);
/* 设置存储器地址 */
DMA1_Channel1->CMAR = (uint32_t)buffer;
/* 启用中断 */
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
/* 启用DMA通道 */
DMA1_Channel1->CCR |= DMA_CCR_EN;
}
错误处理函数
void DMA_ErrorHandler(uint32_t error_flags)
{
if (error_flags & DMA_ISR_TEIF1) {
printf("DMA传输错误发生\n");
// 重新初始化DMA或采取恢复措施
DMA_Recovery();
}
if (error_flags & DMA_FCR_FEIF1) {
printf("DMA FIFO错误发生\n");
// 调整FIFO阈值或检查数据传输时序
DMA_AdjustFIFO();
}
}
最佳实践建议
-
中断配置
- 根据实际需求选择启用中断类型
- 避免不必要的频繁中断
- 合理设置中断优先级
-
错误处理
- 始终启用传输错误中断
- 实现完善的错误恢复机制
- 记录错误日志用于调试
-
性能优化
- 使用双缓冲技术减少中断频率
- 合理配置FIFO阈值
- 优化数据传输对齐
-
调试技巧
- 使用DMA状态寄存器监控传输状态
- 实现断点调试支持
- 添加传输进度监控
注意:具体寄存器名称和位域定义可能因不同的微控制器系列而有所差异,请参考具体芯片的数据手册和参考手册。
3449

被折叠的 条评论
为什么被折叠?



