背景
有一块吃灰7年的神州IV号开发板,主控芯片STM32F107VCT6,PHY芯片DM9161A,配套的资料都是当年ST的标准库。这个开发板应该是因为当年上市太匆忙,资料和代码的细节部分做的不太好。
最近想玩玩MQTT,想用这个开发板的网口,顺便通过此过程熟悉下STM32 ETH的用法。配置其实网上教程很多,看着也不难,结果试下来老是ping不通,一开始感觉无从下手。后来追代码,看手册,检查原理图等等,耗费大半周业余时间终于在清明假期的第二天上午ping通了,终于感到点安慰。记录下过程就要出去晒晒太阳了。
欢迎备注原作者转发
1.根据原理图在STM32CubeMx中做配置
我的开发板是用的RMII通讯方式
自动协商开启(协商全双工半双工,10M还是100M),因为没有使用系统,用裸机跑lwip, 所以模式选择polling
Phy地址应该是由硬件引脚决定的,我的是0.
因为配置里没有DM9161A,所以随便选了个LAN8742.其实只用基本功能,这些PHY的基本寄控制和状态存器都是有标准规定死的,都一样。不一样的是后面的一些厂家指定的寄存器,我开始没ping通就是因为这个厂家指定的寄存器。
STM32F107的MCO给RMII模式的PHY提供50MHZ的时钟,记得配好。并且MCO引脚要记得设置为高频输出,默认为low。
LWIP配置我用的固定IP,没用OS,其他默认。
2. 生成代码并编译
我用的MDK,所以选择MDK版本。
在因为选的是polling模式,Main函数循环中添加MX_LWIP_Process()函数,在此处处理收发包
编译完成下载,网口绿灯亮,黄灯伴随ping闪烁,但是不通,无法访问主机。
3.调试
使用debug调试代码+wareshark发现开发板收到了电脑发的ping命令,并且内容正确,也做了回复,但电脑侧还是无法访问主机。既然灯亮并且能收到ping包且做了回复,说明起码PHY运行起来了,但是可能配置有问题。
于是看了DM9161A的芯片手册,F107的ETH相关的手册(太多了,头都大了),囫囵吞枣,有了个大概印象。然后开始一步一步的追ETH的初始化代码。开发板自带了ETH的驱动程序,不过是7年前的标准库,而且代码写的也很随意,但起码板子是能跑的,于是我就对照该代码看CUBE生成的代码。
终于。。。我发现了问题
初始化过程中先设置PHY为自动协商模式,确定该模式已经生效后会读取PHY的状态寄存器,根据协商结果去初始化MAC的参数。而这个寄存器因为一开始我不知道其意义,是配错了的。
一开始因为Cube里那个PHY speed duplex mask的名字困扰了我,我也不知道这个寄存器有啥用,就在DM9161A的芯片手册里搜了这个名字,得到如下图结果,然后就把这个寄存器的偏移21还有对应位给填到cube配置参数中了。结果当然是有问题的。因为初始化代码要读取PHY的协商结果来设置MAC,而这个寄存器配错了,读取的结果肯定也不对,导致MAC配置的全双工半双工以及10M和100M就错了,那当然不能正常通信了。
在明白了驱动代码的含义后,再次翻看DM9161A的数据手册,终于找到了正确的寄存器。下图是改对后的
这里其实有个问题,cube默认双工半双工用1bit表示,10M100M用另一bit表示,总共两位。生成的代码里也是按照判断这两位来初始化。而DM9161A实际上用了4个bit
这就导致了cube生成的代码这个地方的判断是不能继续使用的,需要修改。此处的修改是和你选择如何判断模式有关的,不是唯一的,我的修改如下,
修改前
修改后
4.测试结果
修改了以上部分后,重新编译下载程序,再次ping,终于通了,激动啊!!!!
同时也庆幸,万一问题不在这,我还得继续研究MAC其他参数关于DMA的那部分的驱动代码,而那部分太复杂了,都不知道能不能坚持下去。
5. 写在最后
一开始用的是最新的STM32CubeIDE(基于cubeMXV5.5),集成了eclipse环境,可视化很好,追踪代码也很方便,然而调试很困难,老有问题断开。而且在我配置了固定IP后生成的代码中是没有IP的,此处估计是bug.
然后退回了很久前使用过的一个老版本cubeMx5.01+MDK,终于成功了。