当定义CONFIG_CMD_NET和CONFIG_CMD_PING,编译之后执行ping命令,告警没有找到以太网。
因此,需要打开U-boot的网络功能, u-boot-sunxi-sunxi中没有找到明显的网络驱动代码,或许有通用的驱动,但可以获得资料的途径有限,再说我是个初学者,平时工作属于自动控制类,网络方面很菜,因此想通过修改一个网络驱动,进行一次初步学习,想到就开工...
边做边写,恐怕会比较乱。
开发环境: 1、笔记本RHEL5,安装编译器arm-none-eabi-版本4.7.2; 编辑器Vim;minicom2.1
2、台式机XPsp3,安装SourceInsight3.5
基本思路: 1、找到u-boot内网络代码运行的轨迹,初始化、数据交换的驱动接口等等
2、实现一个驱动,加入到这个运行轨迹中,设备初始化,数据读写等等
准备工作: 1、找到芯片资料,这个比较坑,只能找到RTL8021CP的PDF,至于CPU芯片资料,
×,那简直不能称为资料,看看三星处理器资料,为啥别人能做大,不是没有原因的。
2、Cubieboard原理图一份,这个好弄,人手一份呀
3、网线准备了两根,一个常用上网的,一根交叉线。路由器一只。
在没有研究清楚硬件连接之前,这样准备应该比较充足了。
4、下个新版本编译器,找了一个arm-none-eabi-的编译器,版本4.7.2,估计是目前最高版本。
下载:http://www.codesourcery.com/sgpp/lite/arm
选择arm处理器,linux版本,点进去之后需要用邮箱注册,下载地址会发到邮箱。
5、因为没有CPU资料,需要寻找一个A10的网络驱动代码,在支持Cubieboard的内核中找到了。
下载:http://linux-sunxi.org/Cubieboard/Cubieboard_Linux-3.9
这个驱动是linux下的,需要修改一下或参考其操作硬件的过程,以便在u-boot内运行。
一、环境建立,初步编译
考虑到这次需要参考其他开发板或CPU的网络驱动,因此用SourceInsight3.5建立一个u-boot-sunxi-sunxi的工程,建立关联关系,方便代码查阅。建立方法很简单,不懂的可以网上搜索一下。建立工程时不要删除其他代码,全部使用。
linux下编译环境设置,将下载的编译器解压到 /usr/local/arm/目录,解压之后目录是arm-2012.09
设置环境变量,在RHEL5系统内,在/ect/profile的末尾加上一句:
export PATH=$PATH:/usr/local/arm/arm-2012.09/bin
保存之后,执行:source /ect/profile 或者logout,或者重启机器。
回到bash,输入arm再按Tab键,可以看到编译工具链列出来了,执行
arm-none-eabi-gcc -v,可以看到版本是4.7.2
其他系统编译器安装设置可以在网上搜索,有很多文章会提到。
进入u-boot-sunxi-sunxi目录,修改Makefile内容,找到 CROSS_COMPILE ?= 这一行
改为:CROSS_COMPILE ?= arm-none-eabi-
进入 u-boot-sunxi-sunxi/arch/arm,修改config.mk内容,也是这一句 CROSS_COMPILE ?=
改为:CROSS_COMPILE ?= arm-none-eabi-
回到u-boot-sunxi-sunxi目录,执行:
make distclean //清除之前编译的内容
make cubieboard_config //设置板子
make -j4 //编译,-j4表示多线程编译,可以使用-j2,如果是虚拟机可以不用这个参数,
//如果电脑配置比较好,可以使用 -j8
等待一会,不出意外,编译完成,写入SD卡,到板子上运行,可以看到串口输出信息。
二、U-boot网络模块分析
1、网络初始化
之前曾经分析过主循环,在主循环main_loop()调用之前就是初始化。
在文件u-boot-sunxi-sunxiarcharmlibboard.c, 函数board_init_r()内:
...........
#if defined(CONFIG_CMD_NET)
puts("Net: ");
eth_initialize(gd->bd);
#if defined(CONFIG_RESET_PHY_R)
debug("Reset Ethernet PHYn");
reset_phy();
#endif
#endif
...........
这一段代码可以看出,要执行网络初始化,需要定义CONFIG_CMD_NET。
因此在u-boot-sunxi-sunxiincludeconfigssunxi-common.h 末尾加一句:
#define CONFIG_CMD_NET
再来看看函数eth_initialize() 的内容,在文件 u-boot-sunxi-sunxineteth.c内:
.................
if (board_eth_init != __def_eth_init) {
if (board_eth_init(bis) < 0)
printf("Board Net Initialization Failedn");
} else if (cpu_eth_init != __def_eth_init) {
if (cpu_eth_init(bis) < 0)
printf("CPU Net Initialization Failedn");
} else
printf("Net Initialization Skippedn");
.................
如果只定义CONFIG_CMD_NET,在上电时就会打印 Net Initialization Skipped,执行了最后一个else的内容,因此,需要完成网络初始化,需要实现函数board_eth_init()或者cpu_eth_init()
看代码,这两个函数谁等于__def_eth_init就执行谁,在看看__def_eth_init是啥,也在eth.c这个文件内
static int __def_eth_init(bd_t *bis)
{
return -1;
}
int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
可见,实现__def_eth_init的“alias ”,bash命令里面有个alias,如果你用过就明白这是什么意思了,实现它,就可以进行初始化啦。
想知道weak, alias是什么意思,请围观这位大侠的博客 http://blog.chinaunix.net/uid-20272712-id-1969771.html
以太网模块在A10内,A10的手册称之为WEMAC模块,因此,我们需要实现cpu_eth_init函数,表明eathnet模块在CPU内部。
在文件u-boot-sunxi-sunxiarcharmcpuarmv7sunxiboard.c内增加函数cpu_eth_init,内容如下:
#ifdef CONFIG_SUN4I_WEMAC
int cpu_eth_init(bd_t *bis)
{
return sun4i_wemac_initialize(bis);
}
#endif
2、如何实现网络模块
网络模块已经成熟了,我们并不需要增加很多代码,只需要实现对硬件的操作就可以了。
基本的操作大约就几个:初始化、打开、关闭、接收、发送、挂起
分析u-boot-sunxi-sunxinet目录内的代码,发现网络的数据结构定义在u-boot-sunxi-sunxiincludenet.h内
struct eth_device {
char name[16]; //网络名
unsigned char enetaddr[6]; //以太网地址
int iobase; //io基址?
int state; //设备状态