uboot中的tftp和dhcp的实现都是通过调用cmd_net.c中的netboot_commom()函数。该函数的主要部分是net/net.c中到函数NetLoop(),对于tftp/dhcp,NetLoop分别调用TftpStart()/DhcpRequest()之后进入等待循环。而函数TftpStart()/DhcpRequest()则通过调用NetSetHandler()设置packetHandler函数指针分别指向TftpHandler()/DhcpHandler().另外TftpStart()/DhcpRequest()分别通过调用NetSetHandler()设置timeHandler为TftpTimeout()/BootpTimeout(), 在设置好函数指针并为一些全局状态变量赋值之后,NetLoop()进入等待循环。在循环体中,
NetLoop()但就tftp/dhcp而言只做三件事:
第一,查询用户是否按下串口到ctrl+c,若是则命令tftp/dhcp结束;
第二,查询是否超时,若超时则调用函数指针timeHandler指向的函数(也就是TftpTimeout()/BootpTimeout());
第三,查询全局变量NetState的状态,若出错或成功,命令结束。
可以看到,由于uboot是单任务环境(严格的讲还不能称作OS),所以只能查询。也就是代码的流程很固定(就像刚刚开始学c语言的学生写的代码),唯一的例外(异步动作)就是interruption.在以上的描述中显然,interruption包括网卡芯片的interruption.也就是,NetLoop()函数在执行循环到时候很可能被打断(如果网卡芯片正常工作的话,NetLoop()被打断的情况是很频繁的,因为以太网是广播性质的),而致使网卡的interrupt service route(ISR)被调用(这样就非常容易的实现局域网监听了)。
另外还有注意的地方有两点。第一,NetLoop()调用timeHandler的次数。其实这里的代码类似于linux下alarm()/alarm signal handler的机制。只有在timeHandler执行的函数中重新给timeHandler()赋值,则在下一次超时时timeHandler指向的函数才会被调用。因为其调用的方式为:
if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
thand_f *x;
x = timeHandler;
timeHandler = (thand_f *)0;/*在这里将函数指针置空*/
(*x)();
}
还有一个地方需要注意的是全局变量NetState的值。以上已经说过,uboot为单任务环境,该环境下唯一的异步动作就是interruption,那么在NetLoop()执行循环体的时候谁会对该全局变量赋值?显然是interruption service route (也就是packetHandler指向到函数,对于tftp/dhcp而言也就是TftpHandler()/DhcpHandler()了)。
在TftpHandler()/DhcpHandler()中除了对全局变量NetState进行设置外,这两个函数还分别对tftp/dhcp私有到变量进行了设置,比如用于表示tftp下载文件大小的变量NetBootFileXferSize以及用于表示dhcp成功/失败的dhcp_state.
===============================================================================
uboot中的启动参数
init指定的是內核啟起來後,進入系統中運行的第一個腳本
loadaddrDefault load address for commands like tftp or loads
阅读(6228) | 评论(0) | 转发(0) |