在RT-Thread中为STM32H563添加以太网(ETH)驱动支持需要根据H5系列的硬件特性进行针对性修改。以下是完整的解决方案:
1. 关键问题分析
STM32H563的ETH外设与F4/F7/H7系列存在差异,主要体现在:
- 外设寄存器地址偏移量不同
- 时钟配置逻辑更新
- PHY接口管理差异(尤其是LAN8742/LAN8720的复位和初始化)
- 中断处理和DMA描述符配置
2. 驱动修改步骤
(1) 寄存器访问宏修正
修改drv_eth.h中寄存器定义:
// 检查并调整寄存器偏移量(示例参考H563参考手册)
#define ETH_DMABMR (ETH_BASE + 0x0100)
#define ETH_DMACR (ETH_BASE + 0x0104)
// 添加H5特有寄存器
#define ETH_DMAHWTPR (ETH_BASE + 0x018C)
(2) 时钟配置
在drv_eth.c的初始化函数中添加:
// 使能ETH时钟
__HAL_RCC_ETH1MAC_CLK_ENABLE();
__HAL_RCC_ETH1TX_CLK_ENABLE();
__HAL_RCC_ETH1RX_CLK_ENABLE();
// 配置时钟源(根据CubeMX生成的代码确认)
RCC_PeriphCLKInitTypeDef clk = {0};
clk.PeriphClockSelection = RCC_PERIPHCLK_ETH;
clk.EthClockSelection = RCC_ETHCLKSOURCE_PLL3; // 具体时钟源需查手册
HAL_RCCEx_PeriphCLKConfig(&clk);
(3) PHY芯片复位逻辑
修改PHY初始化部分:
// 增加PHY硬件复位引脚控制
rt_pin_mode(PIN_PHY_RESET, PIN_MODE_OUTPUT);
rt_pin_write(PIN_PHY_RESET, PIN_LOW);
rt_thread_mdelay(50);
rt_pin_write(PIN_PHY_RESET, PIN_HIGH);
rt_thread_mdelay(200); // 需满足PHY芯片复位时间要求
(4) DMA描述符配置
更新描述符结构对齐和配置:
__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __ALIGN_END;
__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __ALIGN_END;
// 配置描述符时使用HAL_ETH_DMATxDescListInit
HAL_ETH_Init(&EthHandle);
HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, Tx_Buff, ETH_TX_DESC_CNT);
HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, Rx_Buff, ETH_RX_DESC_CNT);
(5) 中断处理
在board.c中绑定中断向量:
void ETH_IRQHandler(void)
{
rt_hw_eth_isr(&stm32_eth_device);
}
(6) MAC地址配置
在drv_eth.c中实现MAC地址获取:
void get_mac_addr(uint8_t *mac)
{
uint8_t chip_mac[6];
// 从芯片唯一ID生成MAC地址
HAL_GetUID((uint8_t*)chip_mac);
mac[0] = 0x00;
mac[1] = 0x80;
mac[2] = 0xE1;
mac[3] = chip_mac[1];
mac[4] = chip_mac[2];
mac[5] = chip_mac[3];
}
3. 关键配置参数
在board.h中添加:
/* ETH Configuration */
#define BSP_USING_ETH
#define ETH_RX_BUFFER_CNT 4
#define ETH_TX_BUFFER_CNT 4
#define ETH_RX_BUFFER_SIZE 1536
#define PHY_ADDRESS 0x01 // 根据硬件调整
#define PHY_LAN8742A // 或PHY_LAN8720
4. 调试建议
- 使用逻辑分析仪检查RMII接口信号
- 添加调试输出:
rt_kprintf("ETH Reg BMR: 0x%08xn", ETH->DMABMR);
- 测试PHY通信:
uint16_t phy_value = 0;
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDRESS, PHY_IDR1, &phy_value);
rt_kprintf("PHY ID1: 0x%04xn", phy_value);
5. 完整驱动适配
建议从官方STM32H5 Cube库中提取ETH初始化代码:
- 在CubeMX中生成ETH初始化代码
- 将以下函数移植到RT-Thread驱动:
HAL_ETH_MspInit()
HAL_ETH_RxCpltCallback()
HAL_ETH_TxCpltCallback()
6. PHY状态监测
添加链路状态检测线程:
static void phy_monitor_thread(void *param)
{
while(1) {
uint32_t status = 0;
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDRESS, PHY_BSR, &status);
if(status & PHY_LINKED_STATUS) {
eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
} else {
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
}
rt_thread_mdelay(500);
}
}
7. 其他注意事项
- MPU配置:确保ETH使用的内存区域配置为Cacheable
MPU_Region_InitTypeDef mpu = {0};
mpu.Enable = MPU_REGION_ENABLE;
mpu.BaseAddress = 0x30000000; // ETH描述符地址
mpu.Size = MPU_REGION_SIZE_64KB;
mpu.AccessPermission = MPU_REGION_FULL_ACCESS;
mpu.IsCacheable = MPU_ACCESS_CACHEABLE;
HAL_MPU_ConfigRegion(&mpu);
- DMA对齐:描述符地址需32字节对齐
- PHY地址:通过硬件原理图确认PHY地址(0/1)
完成以上修改后,使用ifconfig命令查看网络接口状态,进行ping测试。如果仍有问题,建议在RT-Thread论坛提交问题详情(包含寄存器dump和调试输出)。