You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32H755ZIT6 Cortex-M4核USART+DMA接收帧错误问题排查

STM32H755ZIT6 M4核USART+RTS+DMA接收帧错误问题

核心问题

在STM32H755ZIT6的Cortex-M4核上使用USART+仅RTS+DMA(非循环模式,外设到内存,DMA1 Stream0)接收数据时出现Framing Error(帧错误),相同代码在M7核上运行正常。帧错误表示接收端未在预期时间识别到停止位。

相关代码

// u8* dma_rx_buffer_ = (u8*)((u32)0x24000000);
// u8* dma_rx_buffer_ = (u8*)((u32)0x38000000);
u8* dma_rx_buffer_ = (u8*)((u32)0x30000000);

int main(void)
{
    //SCB_InvalidateDCache_by_Addr((u32*)dma_rx_buffer_, 14);
    error = HAL_UART_Receive_DMA(&usart2_dma_, dma_rx_buffer_, 14);
}

注:M4核无法使用SCB_InvalidateDCache_by_Addr函数。

链接脚本配置

M7核Flash.ld

MEMORY {   
         RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH =  512K
         FLASH   (rx)   : ORIGIN = 0x08000000, LENGTH = 1024K
         DTCMRAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K
         RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
         RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
         ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
      }

M4核Flash.ld

MEMORY
    {
       FLASH (rx)     : ORIGIN = 0x08100000, LENGTH = 1024K
       RAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 288K
       //RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
       //RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
    }

已尝试的操作

  1. 在M4核的Flash.ld中添加RAM_D1和RAM_D2,并通过以下方式定义缓冲区:
    __attribute__ ((section(".RAM_D2"))) __attribute__ ((aligned (32))) u8* dma_rx_buffer_;
    
    无效果。
  2. 查阅DMA相关文档,未找到解决方案。
  3. 测试不同RAM地址(RAM_D1、RAM_D2、RAM_D3)作为缓冲区,得到的数据不同,但均出现帧错误。
  4. 配置MPU区域,代码如下,但使用RAM_D1、RAM_D2或RAM_D3均无效果:
    /* Disable fault exceptions */
    SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
    
    /* Disable the MPU and clear the control register*/
    MPU->CTRL = 0;
    
    MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk;
    
    SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
    
    __DSB();
    __ISB();
    
    MPU->RNR = MPU_REGION_NUMBER8;
    
    //MPU->RBAR = 0x24000000;
    //MPU->RBAR = 0x38000000;
    MPU->RBAR = 0x30000000;
    MPU->RASR = ((uint32_t)MPU_INSTRUCTION_ACCESS_ENABLE << MPU_RASR_XN_Pos)   |
                ((uint32_t)MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos)   |
                ((uint32_t)MPU_TEX_LEVEL0 << MPU_RASR_TEX_Pos)  |
                ((uint32_t)MPU_ACCESS_SHAREABLE << MPU_RASR_S_Pos)    |
                ((uint32_t)MPU_ACCESS_CACHEABLE << MPU_RASR_C_Pos)    |
                ((uint32_t)MPU_ACCESS_BUFFERABLE << MPU_RASR_B_Pos)    |
                ((uint32_t)0x00 << MPU_RASR_SRD_Pos)  |
                ((uint32_t)MPU_REGION_SIZE_32B << MPU_RASR_SIZE_Pos) |
                ((uint32_t)MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos);
    

疑问

请问我哪里操作有误?


解答

1. MPU配置错误

当前MPU配置存在两个关键问题:

  • 缓存属性不匹配:DMA直接访问的内存区域必须配置为非缓存,否则M4核的缓存会和DMA写入的数据不一致,打乱传输时序引发帧错误。你设置了MPU_ACCESS_CACHEABLE,这是错误的。
  • 区域大小不匹配:RAM_D2长度为288KB,你设置的MPU_REGION_SIZE_32B仅覆盖32字节,大部分RAM_D2地址未被MPU规则覆盖。

修改后的MPU配置代码:

/* Disable fault exceptions */
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;

/* Disable the MPU and clear the control register*/
MPU->CTRL = 0;

MPU->RNR = MPU_REGION_NUMBER8;
// 配置RAM_D2区域(0x30000000,512KB覆盖整个288KB范围)
MPU->RBAR = 0x30000000 | MPU_RBAR_VALID_Msk;
MPU->RASR = ((uint32_t)MPU_INSTRUCTION_ACCESS_ENABLE << MPU_RASR_XN_Pos)   |
            ((uint32_t)MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos)   |
            ((uint32_t)MPU_TEX_LEVEL0 << MPU_RASR_TEX_Pos)  |
            ((uint32_t)MPU_ACCESS_SHAREABLE << MPU_RASR_S_Pos)    |
            ((uint32_t)MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos)    | // 改为非缓存
            ((uint32_t)MPU_ACCESS_BUFFERABLE << MPU_RASR_B_Pos)    |
            ((uint32_t)0x00 << MPU_RASR_SRD_Pos)  |
            ((uint32_t)MPU_REGION_SIZE_512KB << MPU_RASR_SIZE_Pos) | // 匹配RAM_D2的范围
            ((uint32_t)MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos);

MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk;

SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;

__DSB();
__ISB();

2. 缓冲区定义错误

你使用u8* dma_rx_buffer_指针指向RAM_D2地址,但指针本身可能被分配到M4的私有RAM,且未在RAM_D2中实际分配缓冲区空间。正确做法是直接定义数组,并通过section属性分配到RAM_D2:

__attribute__ ((section(".RAM_D2"))) __attribute__ ((aligned (32))) u8 dma_rx_buffer_[14];

同时修改M4的Flash.ld,添加RAM_D2的section映射:

MEMORY
{
   FLASH (rx)     : ORIGIN = 0x08100000, LENGTH = 1024K
   RAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 288K
   RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
}

SECTIONS
{
  /* 保留原有SECTION配置,新增以下内容 */
  .RAM_D2 :
  {
    . = ALIGN(32);
    *(.RAM_D2)
    . = ALIGN(32);
  } > RAM_D2
}

3. 内存访问权限问题

STM32H7的M4核默认只能访问自身私有RAM(0x10000000)和部分共享外设区域,需确保:

  • M7核已配置AXI总线,允许M4核访问RAM_D2区域(通过RCC->AXI3SMENR等寄存器启用)。
  • M4核的MPU规则正确覆盖RAM_D2,且权限设置为全访问。

4. RTS流控时序问题

帧错误可能源于RTS信号时序不匹配,检查:

  • USART的RTSE位(流控使能)是否正确置位。
  • RTS引脚的复用功能和输出模式是否配置正确(复用推挽输出,根据需求配置上下拉)。
  • USART的波特率、数据位、停止位配置与发送端完全一致。

内容的提问来源于stack exchange,提问作者user3473485

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:05:04