NXP

Freescale i.MX6 Linux Ethernet Driver驱动源码分析(1)

2019-07-12 13:12发布

最近需要在Freescale i.MX6上移植Ethernet AVB的内核patch,Ethernet AVB的Wiki:http://en.wikipedia.org/wiki/Audio_Video_Bridging,而Freescale原来已经在kernel 3.0.35 LTIB 4.0.0的基础上提供了patch:https://community.freescale.com/docs/DOC-95578,现在需要做的是把kernel 3.0.35上的patch移植到yocto kernel-3.10.17_ga上,第一次听上去就感觉像是代码的复制粘贴,不过首要的问题是Ethernet Driver都没有看过,还谈何移植,所以索性把Ethernet Driver也学习一遍,Google了一段时间,找到了几份不错的学习资料,特此共享之: http://free-electrons.com/doc/network-drivers-lab.pdf  《Linux network driver development Training lab book》个人认为最经典的学习资料,从无到有地讲述了网卡驱动的编写过程,基于Atmel的MPU的Ethernet Controller。 http://lwn.net/images/pdf/LDD3/ch17.pdf 《LDD3》的第17章节专门讲述了network driver,不过这里面着重介绍了一些技术细节,适合当工具书来看。 http://free-electrons.com/training/kernel/  这个页面是偶然找到的,不过对free-electrons印象一直不错,所以强烈推荐,这是专门讲内核与驱动开发的材料。 那几天我硬着头皮把《Linux network driver development Training lab book》看完了,后来又看了两遍,对Linux Ethernet Driver有了比较整体的认识,接下来的工作就是理解i.MX6 3.0.35内核的驱动源码。 这里不得不称赞的是,Freescale的驱动有相应的《i.MX 6Dual/6Quad Linux Reference
Manual》文档可以从官网上下到,它会给你一些简要的介绍。这对于很多初学者来说还是非常友好的。首先找到源码的位置:drviers/net/fec.c对应还有一个fec.h作头文件,同时现在大多数的MPU还集成了支持FEC1588的硬件控制器,从硬件上支持一些对时间有要求的应用,比如Ethernet AVB等等。这里以3.0.35内核目前最新release的LTIB 4.1.0环境的内核为参考。         首先是驱动程序入口: static int __initfec_enet_module_init(void){ printk(KERN_INFO "FEC Ethernet Driver "); return platform_driver_register(&fec_driver);} static void __exitfec_enet_cleanup(void){ platform_driver_unregister(&fec_driver);} module_exit(fec_enet_cleanup);module_init(fec_enet_module_init); MODULE_LICENSE("GPL"); 现在看到printk后面那个KERN_INFO一点都不觉得别扭,当初还被坑了。 printk有8个loglevel,定义在中,其中数值范围从0到7,数值越小,优先级越高。 #define    KERN_EMERG      "<0>"       #define    KERN_ALERT       "<1>" #define    KERN_CRIT "<2>"       #define    KERN_ERR    "<3>"       #define    KERN_WARNING "<4>"       #define    KERN_NOTICE     "<5>"       #define    KERN_INFO "<6>"       #define    KERN_DEBUG      "<7>"       默认在Ubuntu rootfs下,优先级大于4才会显示出来,没有指定日志级别的printk语句默认采用的级别是 DEFAULT_ MESSAGE_LOGLEVEL(这个默认情况下是4,具体的解释见http://blog.sina.com.cn/s/blog_636a55070101i6sr.html)所以如果不设置优先级的情况下,在中断上是看不到printk打印的语句的,不过在dmesg中可以看到,当然也可以echo 8 > /proc/sys/kernel/printk来修改默认输出的最低优先级。
static int fec_mac_addr_setup(char *mac_addr){ char *ptr, *p = mac_addr; unsigned long tmp; int i = 0, ret = 0; while (p && (*p) && i < 6) { ptr = strchr(p, ':'); if (ptr) *ptr++ = '