嵌入式Linux网络驱动程序开发设计
2.3.1网络设备初始化
网络设备的初始化是由net_device结构中的init函数实现的,内核加载网络驱动模块后,就会调用初始化过程。实例中初始化函数_init cs8900_probe中主要完成的工作:
a.调用内核中通用的设置以太网接口的函数ether_setup();
b.填充net_device结构体变量dev中其它大部分成员;
c.调用check_mem_region()检测I/O地址空间,然后调用request_mem_region()申请以dev->base_addr为起始地址的16个连续的 I/O地址空间;
d.通过cs8900_read()探测网卡CS8900A,读取ID信息;
e.设置CS8900A的INTRQ0作为中断信号输出引脚;
f.将MAC地址写入CS8900A的IA寄存器中;
g.通过register_netdev()将CS8900A注册到Linux全局网络设备链表中;
2.3.2打开(或关闭)网络设备
系统响应ifconfig命令时,打开(关闭)一个网络接口。ifconfig命令开始会调用ioctl(SIOCSIFADDR)来将地址赋予接口。响应SIOCSIFADDR由内核来完成,与设备无关。接着,ifconfig命令会调用ioctl(SIOCSIFFLAGS)设置dev->flag的IFF_UP位来打开设备,这个调用会使设备的open方法得到调用。(当ifconfig调用ioctl(SIOCSIFFLAGS)清除dev->flag的IFF_UP位时,设备的stop方法将被调用)
实例中利用cs8900_start()函数打开网络设备,主要完成的工作:
a.通过set_irq_type()向内核注册网络设备的中断处理程序;
b.通过cs8900_set()设置CS8900A网卡中各控制寄存器和配置寄存器;
c.通过内核中netif_start_queue()函数开启网络接口的数据传输队列;
2.3.3网络数据包的发送
数据包的发送和接收是网络驱动程序中实现的两个最重要的任务。当网络设备被激活时,net_device结构中的open方法被调用,它负责打开设备并调用net_device结构中的hard_header函数指针建立硬件帧头信息。最后通过函数dev_queue_xmit()来调用net_device结构中的hard_start_xmit方法把存放在sk_buff中的数据发送到网络物理设备。如果发送成功,则在hard_start_xmit中释放sk_buff并返回0;如果硬件设备忙暂时无法处理,则返回1。网络硬件在发送完数据包后会产生中断,把dev->tbusy置0,通知系统可以再次发送。
实例中,hard_start_xmit方法即为网络设备数据发送函数cs8900_send_start(),该函数实现把数据发送到以太网上,由网络协议接口层函数dev_queue_xmit()对其调用。
cs8900_send_start()中主要完成的工作:
a.发送数据前关闭中断,中止网络设备的数据传输队列;
b.向CS8900A寄存器TxCMD中写入传送数据命令控制字,向寄存器TxLength中写入待发送数据帧长度;
c.通过cs8900_read()反复读取CS8900A总线状态寄存器BusST信息,直到其已经准备好接收来自主机的数据;
d.调用cs8900_frame_write()将待发数据送入CS8900A的sk_buff中,硬件设备会将数据帧发送到以太网上;
e.记录数据帧的发送时刻,打开中断,释放sk_buff缓存,函数返回0;
2.3.4网络数据包的接收和中断处理
网络设备是异步地接收外来的数据包并且主动的"请求"将硬件获得的数据包压入内核。网络设备接收数据包是通过中断实现的。对于网络接口,接收到新数据包,发送完成或者报告错误信息及连接状态等都会触发中断,通常中断处理程序通过检测硬件状态寄存器判断是哪种情况。
当设备收到数据后会产生一个中断,由硬件通知驱动程序有数据包到达。在中断处理程序中驱动程序申请一块sk_buff(一般定义为skb)缓冲区,然后从硬件读出数据放到申请好的缓冲区里,接下来填充sk_buff中的部分信息:包括接收到数据的设备结构体指针填入skb->dev;收到数据帧的类型填入skb->protocol;把指针skb->mac.raw指向硬件数据并丢弃硬件针头(skb_pull);设置skb->pkt_type,标明链路层数据类型。最后调用协议接口层函数netif_rx() 把接收到的数据包传输到网络上层协议处理。这里,netif_rx()只是负责把数据放入工作队列就返回,真正的处理是在中断返回以后,这样可减少中断处理的时间。几乎每个中断处理程序的编写都要涉及底半部机制,这样可以保证中断的高效处理。
实例中数据接收函数cs8900_receive()由网络驱动的中断处理函数调用,主要完成如下工作:
a.通过从I/O口读取RxStatus和RxLength的值,确定接收数据帧的状态信息和长度;
b.判断接收数据帧的状态是否正常,若异常则记录相关错误信息,然后函数返回;
c.正常情况下,在内存中申请一块sk_buff缓存,并将数据从CS8900A的片内存储器传送到sk_buff缓存中;d.从数据帧中获取协议头并赋给skb->protocol;
e.通过调用netif_rx()函数将接收到的数据送往上层协议栈进行处理;
f.记录接收数据的时间并更新统计信息;
- SoC前段(ARM)嵌入式系统开发实作训练(上) (02-28)
- 基于嵌入式Linux的智能手机系统设计(05-10)
- 基于ARM+uCLinux的网络控制系统设计与实现(05-03)
- 基于Linux和S3C2410的嵌入式图象传输系统设计(05-24)
- 北大首倡“中国芯”出成果 未来充满变数(06-09)
- 嵌入式系统中闪存设备IO软件的设计与实现(07-08)