常见问题
ARM嵌入式系统开发之发送过程的实现
要通过网卡发送数据时,上层协议实体调用函数hard_start_xmit(),在我们的驱动程序中这个函数被同构成DM9000_wait_to_send_packet()函数,正如它名字中wait所回应的那样,这个函数只已完成了等候发送到的工作,实际的发送到是调用DM9000_hardware_send_packet()函数已完成的,这也是前面提及的buffer分配机制的一种反映。 在明确讲解这两个函数之前,有适当非常简单说一说DM9000芯片发送数据的工作原理。
前面早已谈过,为了减少网络吞吐量DM9000芯片内部构建了8K的buffer,芯片对这些buffer使用了内存页面管理方式,每页256B,内部寄存器反对非常简单的内存分配指令。对于内核来说,发送数据只是把数据从内核送往芯片的buffer中去,实际向物理媒介上的发送到和涉及的掌控(CSMA/CD)是由芯片自律已完成的。已完成情况通过中断的方式通报内核。 在数据发送到中中用两个函数。
函数DM9000_wait_to_send_packet()一方面构建和上层协议模块,另一方面检查buffer分配否顺利,如果顺利就调用,DM9000_hardware_send_packet()将数据传输到buffer中去,如果不顺利,则关上涉及中断,在分配顺利时由中断控制程序调用DM9000_hardware_send_packet()已完成数据传输。这两个函数都中用Linux网络协议栈中很最重要的一个数据结构sk_buff,关于它在谈接管程序时再行详尽讲解。
下面融合代码片段分析这两个函数的功能构建。 staticintDM9000_wait_to_send_packet(structsk_buff*skb,structnet_device*dev) { structDM9000_local*lp=(structDM9000_local*)dev-》priv; wordlength; unsignedshortnumPages; wordtime_out; wordstatus; lp-》saved_skb=skb; length=ETH_ZLEN《skb-》len?skb-》len:ETH_ZLEN; numPages=((length0xfffe)+6); numPages》》=8; DM9000_SELECT_BANK(2); outw(MC_ALLOC|numPages,MMU_CMD_REG); } 以上代码从skb中朗读数据长度做到一些处置后,折算出所须要的页面数。
然后向芯片收到分配buffer的催促,MC_ALLOC和MMU_CMD_REG都是在头文件中定义的宏,MC_ALLOC是分配buffer空间的寄存器指令,而MMU_CMD_REG是MMU命令寄存器的地址。 time_out=MEMORY_WAIT_TIME; do{ status=inb(INT_REG); if(statusIM_ALLOC_INT){ break; } }while(--time_out); 这段代码是检查buffer分配否顺利,检查的方法很尤其。需解释一下,在系统初始化时buffer分配中断是被屏蔽的,所以即使分配顺利也会产生物理中断信号,但是中断状态寄存器依然不会有适当标志。
这段代码正是利用这个特性,在一个时间范围内检查中断状态寄存器,检查分配否顺利,这个是一种整天等候,但因为time_out设得较小所以在有些时候它比中断方式效率高。 if(!time_out){ DM9000_ENABLE_INT(IM_ALLOC_INT); return0; } 如果超时,证明buffer整天,关上buffer分配中断,待分配顺利时由中断程序已完成有关操作者。 DM9000_hardware_send_packet(dev); netif_wake_queue(dev); return0; } 如果不超时,必要调用DM9000_hardware_send_packet()已完成发送到。下面来看DM9000_hardware_send_packet()函数,它的主要功能一是把数据从sk_buff结构中传输到芯片buffer区,二是展开传输后处理。
数据传输部分牵涉到一些类似问题处置,例如按字(16b)传输时如何处置奇数字节的问题,以及结构以太网帧头结构问题等,这些问题各种网卡处理方式大致相同,比较较为烦琐,所以在代码片段中仅有不作回应。 staticvoidDM9000_hardware_send_packet(structnet_device*dev) { outsw(DATA_REG,buf,(length)》》1); /*对涉及寄存器展开操作者,将数据传输到芯片buffer*/ DM9000_ENABLE_INT((IM_TX_INT|IM_TX_EMPTY_INT)); lp-》saved_skb=NULL; dev_kfree_skb_any(skb); dev-》trans_start=jiffies; netif_wake_queue(dev); return; } 传输后处理,明确为关上传输涉及的异常情况中断,获释skb空间,设置发送到时间、苏醒网络设备等候队列。
本文关键词:米乐m6,ARM,嵌入式,系统,开,发之,发送,过程,的,实现
本文来源:米乐m6-www.sclhdkj.com