DMA中断寄存器及错误详解

「C++ 40 周年」主题征文大赛(有机会与C++之父现场交流!) 10w+人浏览 457人参与

DMA中断寄存器及错误详解

目录

DMA中断概述

直接内存访问(DMA)控制器通过中断机制向处理器报告传输状态和错误情况。合理配置中断寄存器对于实现高效的DMA数据传输至关重要。

主要中断寄存器

1. 全局中断状态寄存器 (GISR/DMA_ISR)

位域名称描述访问类型
31:16Reserved保留位只读
15:0TCIFx通道x传输完成标志 (x=0…15)只读
15:0HTIFx通道x半传输完成标志 (x=0…15)只读
15:0TEIFx通道x传输错误标志 (x=0…15)只读
15:0GIFx通道x全局中断标志 (x=0…15)只读

功能说明:

  • 用于查询所有通道的中断状态
  • 每个通道占用4个位:TCIF, HTIF, TEIF, GIF
  • 读取后需要清除相应标志位

2. 全局中断清除寄存器 (GIFCR/DMA_IFCR)

位域名称描述访问类型
31:16Reserved保留位只写
15:0CTCIFx清除通道x传输完成标志 (x=0…15)只写
15:0CHTIFx清除通道x半传输完成标志 (x=0…15)只写
15:0CTEIFx清除通道x传输错误标志 (x=0…15)只写
15:0CGIFx清除通道x全局中断标志 (x=0…15)只写

功能说明:

  • 用于清除中断标志位
  • 向相应位写入1可清除标志
  • 写入0不影响标志状态

3. 通道中断使能寄存器 (CCR/DMA_CCRx)

位域名称描述访问类型
7MEM2MEM存储器到存储器模式读写
6PL[1:0]通道优先级读写
5MSIZE[1:0]存储器数据大小读写
4PSIZE[1:0]外设数据大小读写
3MINC存储器地址增量模式读写
2PINC外设地址增量模式读写
1CIRC循环模式读写
0EN通道使能读写
4TCIE传输完成中断使能读写
3HTIE半传输中断使能读写
2TEIE传输错误中断使能读写

功能说明:

  • 控制单个通道的中断使能
  • 可以独立配置三种中断类型
  • 必须在通道使能前配置

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();
    }
}

最佳实践建议

  1. 中断配置

    • 根据实际需求选择启用中断类型
    • 避免不必要的频繁中断
    • 合理设置中断优先级
  2. 错误处理

    • 始终启用传输错误中断
    • 实现完善的错误恢复机制
    • 记录错误日志用于调试
  3. 性能优化

    • 使用双缓冲技术减少中断频率
    • 合理配置FIFO阈值
    • 优化数据传输对齐
  4. 调试技巧

    • 使用DMA状态寄存器监控传输状态
    • 实现断点调试支持
    • 添加传输进度监控

注意:具体寄存器名称和位域定义可能因不同的微控制器系列而有所差异,请参考具体芯片的数据手册和参考手册。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s0907136

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值