ST意法半导体
直播中

刘满贵

8年用户 1565经验值
私信 关注
[问答]

使用stm32F407连接PHY芯片进行以太网通讯,一插网线就会进入错误中断怎么解决?

使用STM32F407连接PHY芯片进行以太网通讯,一插网线就会进入错误中断。
/**  * @brief  Ethernet DMA transfer error callback  * @param  handlerEth: ETH handler  * @retval None  */void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *handlerEth){  net_test[2]++;  if((HAL_ETH_GetDMAError(handlerEth) & ETH_DMASR_RBUS) == ETH_DMASR_RBUS)  {设备上电插入网线,这个错误中断进入好几十次上百次,然后就网络工作正常,然后再拔掉网线,再插上,又进入这个中断,有时产生这个错误后,以太网就会彻底没法接收数据,接收中断回调都不进入了,发送正常的。我抓包发现一查网线,电脑又很多数据包会发给单片机,等一会就不发了,不知道是不是这个原因。想请教一下,这个错误回调怎么处理才能避免这个情况。

回帖(2)

李昕萌

2025-6-11 15:50:05
使用stm32F407连接PHY芯片进行以太网通讯,一插网线就会进入错误中断。
/**  * @brief  Ethernet DMA transfer error callback  * @param  handlerEth: ETH handler  * @retval None  */void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *handlerEth){  net_test[2]++;  if((HAL_ETH_GetDMAError(handlerEth) & ETH_DMASR_RBUS) == ETH_DMASR_RBUS)  {设备上电插入网线,这个错误中断进入好几十次上百次,然后就网络工作正常,然后再拔掉网线,再插上,又进入这个中断,有时产生这个错误后,以太网就会彻底没法接收数据,接收中断回调都不进入了,发送正常的。我抓包发现一查网线,电脑又很多数据包会发给单片机,等一会就不发了,不知道是不是这个原因。想请教一下,这个错误回调怎么处理才能避免这个情况。
举报

笑过就走

2025-6-18 17:49:52

要解决STM32F407连接PHY芯片时插入网线频繁触发ETH_DMASR_RBUS错误中断的问题,需要从以太网DMA描述符配置、中断处理流程和物理层状态同步等方面进行系统优化。以下是完整的解决方案:


核心问题分析




  1. ETH_DMASR_RBUS错误:表示接收描述符不可用(Receive Buffer Unavailable),通常发生在:



    • DMA接收描述符环形队列未正确初始化

    • 接收描述符处理不及时导致队列耗尽

    • PHY刚连接时链路震荡频繁触发数据接收




  2. 初始阶段频繁触发:物理层自协商期间会短暂多次激活链路,导致DMA在未完成初始化时被频繁触发。






解决方案


1. 优化接收描述符初始化


#define ETH_RXBUFNB 8 // 至少8个缓冲区

void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
    // ...其他初始化

    /* 接收描述符内存对齐至关重要 */
    heth->RxDesc = (ETH_DMADescTypeDef*)SRAM1_ALIGNED_ADDR;
}

2. 增强DMA接收缓冲管理


// 增加初始化时的缓冲池深度
static uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __attribute__((aligned(32)));

void ETH_RxDescList_Init(ETH_HandleTypeDef *heth)
{
  for(int i=0; i     heth->RxDesc[i].Buffer1Addr = (uint32_t)&Rx_Buff[i];
    heth->RxDesc[i].Status = ETH_DMARXDESC_OWN;
    // 配置环形链表
    heth->RxDesc[i].Buffer2NextDescAddr = (i == ETH_RXBUFNB-1) ?
        (uint32_t)&heth->RxDesc[0] :
        (uint32_t)&heth->RxDesc[i+1];
  }
}

3. 中断处理流程优化


// 在ETH全局中断处理函数中
void ETH_IRQHandler(void)
{
  HAL_ETH_IRQHandler(&heth);

  // 主动清除所有中断标志
  ETH->DMASR = ETH_DMASR_NIS | ETH_DMASR_RS | ETH_DMASR_RBUS;
}

4. 错误回调中恢复DMA接收


void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
{
  uint32_t dmaError = HAL_ETH_GetDMAError(heth);

  if(dmaError & ETH_DMASR_RBUS) {
    // 关键恢复操作
    __HAL_ETH_DMA_DISABLE(heth);
    ETH->DMASR |= ETH_DMASR_RBUS; // 清除标志
    ETH->DMARPDR = 0; // 重启DMA接收
    __HAL_ETH_DMA_ENABLE(heth);
  }
}

5. 防止PHY状态震荡影响


在链路状态变化中断中增加防抖处理:


void EXTIx_IRQHandler(void) // PHY状态中断
{
  static uint32_t lastTime = 0;

  if(HAL_GetTick() - lastTime > 100) // 100ms防抖
  {
    if(PHY_GetLinkState() == PHY_LINK_UP) {
      // 重新初始化DMA接收侧
      __HAL_ETH_DMA_DISABLE(&heth);
      ETH_RxDescList_Init(&heth);
      ETH->DMACR |= ETH_DMACR_RPBL_1Beat;
      __HAL_ETH_DMA_ENABLE(&heth);
    }
    lastTime = HAL_GetTick();
  }
  HAL_GPIO_EXTI_IRQHandler(LINK_GPIO_PIN);
}

6. 确保PHY硬件复位时序


上电时执行硬件复位序列:


void PHY_Reset(void)
{
  HAL_GPIO_WritePin(PHY_RST_GPIO_PORT, PHY_RST_PIN, GPIO_PIN_RESET);
  HAL_Delay(50);
  HAL_GPIO_WritePin(PHY_RST_GPIO_PORT, PHY_RST_PIN, GPIO_PIN_SET);
  HAL_Delay(100); // 等待PHY稳定
}

7. 配置MAC过滤器(关键)


在初始化时添加以下配置,过滤无效帧:


ETH_MACFilterConfigTypeDef filterCfg = {
  .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE,
  .ReceiveAllMode = ETH_RECEIVE_ALL_DISABLE,
  .HashUnicast = ETH_HASH_UNICAST_ENABLE,
  .HashMulticast = ETH_HASH_MULTICAST_ENABLE,
  .DestinationAddrFilter = ETH_DST_ADDR_NORMAL
};
HAL_ETH_ConfigMACFilter(&heth, &filterCfg);



验证步骤




  1. 示波器检查



    • 测量REF_CLK时钟质量(应50%占空比±100ppm)

    • 检查RMII_TXD0/TXD1信号无过冲




  2. 寄存器检查


    // 初始化后打印关键寄存器
    printf("MACCR: 0x%08Xn", ETH->MACCR);
    printf("DMASR: 0x%08Xn", ETH->DMASR);
    printf("MACMIIAR: 0x%08Xn", ETH->MACMIIAR);



  3. 压力测试


    # 使用Python进行插拔测试
    import serial
    ser = serial.Serial('COMx', 115200)

    for i in range(100):
       ser.write(b'ETH_RESETn') # 触发板载重置
       time.sleep(0.5)
       print(f"Test {i} status: {ser.readline().decode()}")





注意事项




  1. PCB设计检查点



    • RMII接口走线≤50mm且等长

    • REF_CLK时钟走线远离高频信号

    • PHY芯片电源去耦电容(100nF+10μF)




  2. 特殊PHY配置


    // 部分PHY需配置特殊寄存器
    PHY_WriteReg(0x1F, 0x0001); // 进入配置页
    PHY_WriteReg(0x0C, 0x3FFF); // 禁用能量检测
    PHY_WriteReg(0x1F, 0x0000); // 返回标准页



以上方案通过增强接收缓冲容错能力、优化中断处理流程、增加物理层状态同步机制,能有效解决频繁触发RBUS错误的问题。实施后插拔网线时应实现稳定连接,错误中断触发次数降至每次插拔1-2次正常范围。

举报

更多回帖

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