在SylixOS下实现网络驱动与Linux下有诸多不同,最大的不同是Linux的网络芯片厂商都会提供,对其修改主要是PHY芯片或引脚分配的更改,而在SylixOS下,网络驱动要自己编写。从技术难度上肯定要比Linux下更换个PHY芯片大,不过作为一款嵌入式实时系统,SylixOS不需要像Linux那样考虑那么多的通用性,因此其驱动复杂程度也远远小于编写一个Linux网络驱动。
拿到的I.MX6Q开发板型号是SABRELite,编写驱动的第一步是寻找资料。找到的响应资料有:
1、imx6_platform_sdk_v1.1.0.tgz和补丁包sabre_lite.patch.tar.bz2、sabre_lite_enet.patch.tar.gz。其中补丁包是在freescale公司论坛上找的地址如下(要感谢Li Baizhang和Rafal Fabich的无私分享):https://community.freescale.com/thread/304517。
2、SABRELite开发板的uboot和Linux软件包,这个软件比较奇怪,在timesys网站上下载很多次没有成功,最后找英蓓特咨询索要的。根据手册安装编译后获取对应的源码导入Source Insight 以方便查看。
3、一套SylixOS开发环境极其已经提供的BSP包,目前有imx283和am335x。
4、I.MX6Q和IMX28的用户手册,需要下载最新版,在老版本中关于以太网控制器的说明不全面。
首先大致阅读下上述资料并确定工作思路。
1、 uboot代码和Linux代码比较庞大和复杂,因此主要参考platform_sdk软件包进行编写BSP,uboot和Linux的代码作为备份参考。在platform_sdk中\lwip\mx6文件夹下放着imx6q芯片的lwip驱动文件,显然跟踪这个文件中的内容理论上就可以完成对其以太网驱动的编写。
2、 需要选择一个BSP模板,由于imx283和imx6q均是freescale公司的处理器,其设计应该会有类似之处,通过各种用户手册也会发现其有诸多相同的地方。因此选用imx283bsp中的以太网驱动作为模板修改。
驱动好思路后我们开始实际的工作,
1、 将imx283中的netif目录下的文件拷贝到imx6q处理器bsp包下,并修改名称imx6q_netif,在makefile中加入对该文件的编译。在bspInit.c文件的函数VOID bspNetifAttch (VOID)添加对enetInit();函数的调用。
2、 对比I.MX6Q和IMX28的用户手册,查找其不同之处,仔细对比会发现imx6q处理器是在imx283上增加了功能扩展,关键的FIFO工作描述符是相同的,对比platform_sdk的代码和imx283的网络驱动会发现区别并不太大。
3、 上述得到的区别,修改imx6q中的驱动代码,主要有寄存器地址、imx6的小端模式、千兆网模式和RGMII部分,引脚分配和PHY芯片寄存器的读写。
完成上述工作后,编译运行并不成功,主要是PHY寄存器读写不正常。对比imx283和am335x的记录发现在phy芯片初始化和网络连接状态处理上差别很大,imx183使用了SylixOS提供的MII库,而am335x并没有使用。在对比二者实现后,决定也不使用SylixOS系统提供的mii库,这样调试起来也方便。对PHY芯片部分修改如下:
1、 修改BSP的地址映射,将以太网控制器的地址设置为平坦映射。
2、 参考platform_sdk的代码重新编写PHY芯片寄存器读写函数,并在ENET_DEFAULT_INTE宏定义中,将MII的中断使能位去除。查看Linux下的代码也是使用类似方法处理PHY的读写,但考虑到MII总线时钟频率较高,读写速度较快,这时使用中断效率不见得比轮询要高。
3、 参考platform_sdk编写PHY芯片初始化函数,
4、 添加中断设置,查询得到以太网的中断号是150,而SylixOS操作系统的中断默认支持128个,因此需要修改系统配置文件,为:../libsylixos/SylixOS/config/kernel/kernel_cfg.h修改宏
#define LW_CFG_MAX_INTER_SRC 256 /* 系统使用中断向量表大小,中断源数量 < 9999 */ |
在I.MX6Q的手册中,对中断的说明内容较少,仅仅是说明使用GIC中断控制器和各个外设中断编号。更多内容需要参考《GIC_architecture_spec_v1_0.pdf》。之后中断使能函数为:
{ API_InterVectorConnect(150, (PINT_SVR_ROUTINE)enetIsr, (PVOID)pnetif, "enet_isr"); API_InterVectorEnable(150); /* 调试期间没有使用标准的宏定义 */ } |
5、 修改内核后,重新编译,使用“ints”命令,就可以实现看到有以太网的线程出现。
6、 参考platform_sdk修改enetThread线程入口函数内容,如果使用mii框架,PHY状态监测需要开启两个线程,一个是enetThread一个是SylixOS系统MII框架自身的Timer启动的线程。在不使用MII框架后,相关内容都要放到enetThread内实现,在AM335x的bsp中延时200ms,考虑到网络连接状态监测频率高低影响并不会太大,因此这里延时1S中。
7、 完成上述修改后,将MII相关内容删除:
删除enetCoreOpen函数里面的
// if (penet->ENET_iMiiInit) { // API_MiiPhyMonitorStart(); // } |
删除enetCoreClose函数里面的
// if (penet->ENET_iMiiInit) { // API_MiiPhyMonitorStop(); // } |
函数enetInit里面的
// pmiidrv = miiDrvInit(); // if (!pmiidrv) { // return (PX_ERROR); // } // _G_enetInfo.ENET_miidrv = pmiidrv; // pmiidrv->MIID_enet = &_G_enetInfo; |
删除上述内容后,还可以将相关函数删除。
另外还需要删除imx283中实现数据大小端交换的函数enetSwapPkt,因为imx6中的以太网控制器自身会完成这些工作。
8、 在enetHwInit函数中修改imx6的引脚分配,并添加PHY芯片复位设置,这部分代码参考
platform_sdk进行。需要特别说明的是,在对芯片引脚分配需要完全依照打补丁包后的platform_sdk进行,否则会无法产生发送中断,完成后的enetHwInit代码如下:
/* * 对此开发板的引脚分配必须经过两次,这样才能显示PHY芯片的地址为6,否则地址显示为2 */ imx_enet_iomux(); /* PHY 芯片初始化之前需要复位,否则无法进行读写。 */ gpio_set_level(GPIO_PORT3, 23, GPIO_LOW_LEVEL); udelay(100000); gpio_set_level(GPIO_PORT3, 23, GPIO_HIGH_LEVEL); udelay(100000); /* Pins init,对ENET相关引脚进行PINMUX设置 */ enet_iomux_reconfig(); |
详细原因在https://community.freescale.com/thread/304517有说明。
9、 完成以上内容后,编译工程,修改其中的错误,下载到电路板中应该可以使用了。
注:在调试的时候因为发送中断没有产生花费很多时间,最后找到是引脚分配的内容。在调试中思路也很重要,这些需要自己实践下才有概念,本驱动调试主要使用printk进行调试。
至此以太网已经能够使用,结构调整、代码格式、网络稳定性、多核、实现ioremap等工作就可以继续了。
文章评论(0条评论)
登录后参与讨论