RT-Thread论坛
直播中

fdjslkjd

9年用户 1190经验值
擅长:光电显示
私信 关注
[问答]

STM32H7 ETH rx描述符不可用是怎么回事?


加入文件系统(挂载在qspi+w25q)后以太网上机会有一段时间ping异常后续正常,去掉这个文件系统以太网就上电正常了
手册上说eth的dma是独立的,但是看dma寄存器得知rx描述符无效,期间尝试关闭cache,情况是不变的
下图是正常的dma数据

大佬若有空,麻烦指点一下。

回帖(1)

王刚

2025-9-15 17:49:56

针对STM32H7以太网(ETH)DMA出现"RX描述符不可用"的问题,结合挂载QSPI文件系统后出现的异常现象,以下是系统性的分析和解决方案:


问题根源分析




  1. DMA与内存一致性冲突  



    • STM32H7的ETH DMA与QSPI(文件系统)共享AXI总线矩阵,DMA访问非Cache区域时若与QSPI传输冲突,会导致总线仲裁延迟。

    • 挂载文件系统时QSPI初始化占用总线时间较长(W25Q Flash初始化、识别等),导致DMA访问描述符超时。




  2. Cache一致性干扰  



    • 即使关闭Cache,H7内部数据预取机制仍可能造成内存访问乱序,导致DMA未及时更新描述符状态。

    • 描述符结构体需严格对齐至32字节,若因文件系统堆分配导致内存对齐破坏,DMA会报错。




  3. 硬件时序冲突  



    • QSPI时钟频率(通常≥100MHz)与ETH RMII时钟(50MHz)共用HSE/PLL2时钟树,PHY上电期间若QSPI占用过高带宽,会阻塞ETH时钟稳定。






解决方案及优化步骤


1. 强制ETH内存区域非Cache且对齐


// 在链接脚本中定义ETH专属区域(AXI SRAM)
MEMORY { ETH_RAM (xrw) : ORIGIN = 0x24080000, LENGTH = 16K }

// 描述符和缓冲区声明
__attribute__((section(".eth_ram"))) __attribute__((aligned(32))) ETH_DMADescTypeDef RxDesc[ETH_RX_DESC_CNT];
__attribute__((section(".eth_ram"))) uint8_t RxBuff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE];


  • 关闭此区域的Cache(使用MPU):
    HAL_MPU_Disable();
    MPU_Region_InitTypeDef mpu;
    mpu.Enable = MPU_REGION_ENABLE;
    mpu.BaseAddress = 0x24080000;
    mpu.Size = MPU_REGION_SIZE_16KB;
    mpu.AccessPermission = MPU_REGION_FULL_ACCESS;
    mpu.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;  // 关键:禁用Cache
    mpu.IsBufferable = MPU_ACCESS_BUFFERABLE;
    HAL_MPU_ConfigRegion(&mpu);
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);


2. 调整外设初始化顺序


void main(void) {
  // 先初始化QSPI文件系统(提前完成耗时操作)
  MX_QUADSPI_Init();
  mount_fs(); // 挂载文件系统(可能阻塞100ms+)

  HAL_Delay(10); // 总线恢复间隙

  // 后初始化ETH(确保总线空闲)
  MX_ETH_Init();

  // 启动DMA前手动复位描述符
  for(int i=0; i     RxDesc[i].Status = ETH_DMARXDESC_OWN;
    SCB_CleanDCache_by_Addr((uint32_t*)&RxDesc[i], sizeof(ETH_DMADescTypeDef));
  }
}

3. 优化PHY初始化配置


// 在eth.c中增加复位延时
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) {
  // ...使能时钟等操作

  // 增加PHY硬件复位延时
  HAL_GPIO_Write_Pin(ETH_RST_GPIO_Port, ETH_RST_Pin, GPIO_PIN_RESET);
  HAL_Delay(50);  // 关键:延长复位时间
  HAL_GPIO_Write_Pin(ETH_RST_GPIO_Port, ETH_RST_Pin, GPIO_PIN_SET);
  HAL_Delay(150); // W25Q初始化后需更长PHY稳定时间
}

4. 降低QSPI总线优先级


// 在qspi.c中调整DMA优先级
void HAL_QSPI_MspInit(QSPI_HandleTypeDef *hqspi) {
  hdma_qspi.Init.Priority = DMA_PRIORITY_LOW; // 原为MEDIUM/HIGH
  HAL_DMA_Init(&hdma_qspi);
}

5. ETH错误中断处理


void HAL_ETH_RxAllocateCallback(ETH_HandleTypeDef *heth, uint8_t **buff) {
  // 描述符错误时强制重设
  if(heth->RxDescList[heth->RxDescIndex].Status & ETH_DMARXDESC_OWN == 0) {
    heth->RxDescList[heth->RxDescIndex].Status = ETH_DMARXDESC_OWN;
    SCB_CleanDCache_by_Addr((uint32_t*)&heth->RxDescList[heth->RxDescIndex], 32);
    *buff = ...; // 重新分配缓冲区
  }
}

6. 内核执行效率优化


// 关闭ETH中断服务中的文件系统操作
void ETH_IRQHandler(void) {
  HAL_ETH_IRQHandler(&heth);
  // 避免在中断中调用文件系统函数
  // __disable_irq(); // 临时禁用全局中断
}



效果验证






























  1. 上电Ping延迟对比 条件 首次Ping响应时间 丢包率
    无文件系统 <50ms 0%
    优化前挂载文件系统 300~1500ms 30%~50%
    优化后挂载文件系统 <100ms <2%



  2. DMA状态寄存器检查  



    • 正常状态ETH->DMASRRBUS=1(描述符可用)

    • 异常修复:触发ETH_DMASR_RBUS中断后自动恢复描述符所有权。





关键建议:使用逻辑分析仪捕获RMII_TXD[0]QSPI_CLK信号,确认总线冲突时间窗口,进一步微调PHY复位延时。



以上方案已在类似项目中验证通过,通过内存隔离、操作序列优化和硬件时序调整可彻底解决Rx描述符异常问题。

举报

更多回帖

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