1、 嵌入式系统软件开发技术 嵌入式系统嵌入式系统docin/sundae_meng 主要内容主要内容n版级支持包 BSPn嵌入式系统初始化以及BSP的设计nLinux系统驱动程序开发n嵌入式联网docin/sundae_mengBSP的概念 nBSP全称“板级支持包”(Board Support Packages),说的简单一点,就是一段启动代码,和计算机主板的BIOS差不多,但提供的功能区别就相差很大n在Windows CE中,BSP是驱动程序、OEM适应层(OEM Adaptation Layers,OAL)、硬件抽象层(HAL)以及启动设备和使外设正常工作所需BIOS文件的集合。docin
2、/sundae_mengBSP和BIOS区别 nBIOS主要是负责在电脑开启时检测、初始化系统设备(设置栈指针,中断分配,内存初始化.)、装入操作系统并调度操作系统向硬件发出的指令。nBSP是和操作系统绑在一起运行,尽管BSP的开始部分和BIOS所做的工作类似,但是 BSP还包含和系统有关的基本驱动 nBIOS程序是用户不能更改,编译编程的,只能对参数进行修改设置,但是程序员还可以编程修改BSP,在BSP中任意添加一些和系统无关的驱动或程序,甚至可以把上层开发的统统放到BSP中 docin/sundae_meng不同系统中的BSP n一个嵌入式操作系统针对不同的CPU,会有不同的BSPn即使同
3、一种CPU,由于外设的一点差别BSP相应的部分也不一样 docin/sundae_mengBSP的特点与功能的特点与功能 n硬件相关性n因为嵌入式实时系统的硬件环境具有应用相关性,所以,作为高层软件与硬件之间的接口,BSP必须为操作系统提供操作和控制具体硬件的方法。n操作系统相关性n不同的操作系统具有各自的软件层次结构,因此,不同的操作系统具有特定的硬件接口形式docin/sundae_mengBSP的设计与实现的设计与实现 n为实现上述两部分功能,设计一个完整为实现上述两部分功能,设计一个完整的的BSPBSP需要完成两部分工作:需要完成两部分工作:n设计初始化过程,完成嵌入式系统的初始化;设
4、计初始化过程,完成嵌入式系统的初始化;n设计硬件相关的设备驱动,完成操作系统及应用设计硬件相关的设备驱动,完成操作系统及应用程序对具体硬件的操作。程序对具体硬件的操作。docin/sundae_meng嵌入式系统初始化以及BSP的功能 n嵌入式系统的初始化过程是一个同时包括硬件嵌入式系统的初始化过程是一个同时包括硬件初始化和软件初始化的过程;而操作系统启动初始化和软件初始化的过程;而操作系统启动以前的初始化操作是以前的初始化操作是BSPBSP的主要功能之一的主要功能之一 n初始化过程总可以抽象为三个主要环境,按照初始化过程总可以抽象为三个主要环境,按照自底向上、从硬件到软件的次序依次为:自底向
5、上、从硬件到软件的次序依次为:n片级初始化片级初始化n板级初始化板级初始化n系统级初始化系统级初始化docin/sundae_meng初始化过程 n片级初始化:片级初始化:n主要完成主要完成CPUCPU的初始化的初始化n设置设置CPUCPU的核心寄存器和控制寄存器的核心寄存器和控制寄存器nCPUCPU核心工作模式核心工作模式nCPUCPU的局部总线模式等的局部总线模式等n片级初始化把片级初始化把CPUCPU从上电时的缺省状态逐步设置从上电时的缺省状态逐步设置成为系统所要求的工作状态成为系统所要求的工作状态n这是一个纯硬件的初始化过程这是一个纯硬件的初始化过程docin/sundae_meng初
6、始化过程(续1)n板级初始化:n完成CPU以外的其他硬件设备的初始化n同时还要设置某些软件的数据结构和参数,为随后的系统级初始化和应用程序的运行建立硬件和软件环境n这是一个同时包含软硬件两部分在内的初始化过程docin/sundae_meng初始化过程(续2)n系统级初始化:n这是一个以软件初始化为主的过程,主要进行操作系统初始化nBSP将控制转交给操作系统,由操作系统进行余下的初始化操作:n包括加载和初始化与硬件无关的设备驱动程序n建立系统内存区n加载并初始化其他系统软件模块(如网络系统、文件系统等)n最后,操作系统创建应用程序环境并将控制转交给应用程序的入口docin/sundae_men
7、g硬件相关的设备驱动程序 nBSPBSP另一个主要功能是硬件相关的设备驱动另一个主要功能是硬件相关的设备驱动n与初始化过程相反,硬件相关的设备驱动程序的初始化和使用通常是一个从高层到底层的过程n尽管BSP中包含硬件相关的设备驱动程序,但是这些设备驱动程序通常不直接由BSP使用n而是在系统初始化过程中由BSP把它们与操作系统中通用的设备驱动程序关联起来,并在随后的应用中由通用的设备驱动程序调用,实现对硬件设备的操作。docin/sundae_mengBSP开发的前提和步骤开发的前提和步骤 n开发的前提:n熟悉硬件方面:使用CPU等n熟悉工具方面:电表,示波器,逻辑分析仪,硬件仿真器,仿真调试环境
8、等n语言方面:汇编语言,C语言nBSP开发的一般步骤如下:n硬件主板研制,测试n操作系统的选定,BSP编程n上层应用程序的开发docin/sundae_meng编写BSP函数 nBSP对板卡中每个芯片的操作都通过多个函数来完成 n如果应用程序对板卡的操作都直接通过调用BSP中的函数来完成,那将很不利于源程序的调试,并降低了程序的可移植性n把能完成某个特定功能的函数封装在一个库文件中,并放在应用程序与BSP之间 n对每个芯片来说,都应当有初始化函数和状态读取函数 docin/sundae_meng设计实现BSP的一般方法 nBSP的开发需要具备一定的硬件知识 n要求掌握操作系统所定义的BSP接口
9、n两种快捷方法 n以经典BSP为参考 n使用操作系统提供的BSP模板 n设计实现BSP两部分功能时应采用以下两种不同方法 n“自底向上”地实现BSP中的初始化操作 n“自顶向下”地设计硬件相关的驱动程序 docin/sundae_mengBSP设计方法的不足与改进 n目前BSP的设计与实现主要是针对某些特定的文件进行修改 n直接修改相关文件容易造成代码的不一致性,增加软件设计上的隐形错误,从而增加系统调试和代码维护的难度 n解决这个问题的一个可行办法是:设计实现一种具有图形界面的BSP开发设计向导,由该向导指导设计者逐步完成BSP的设计和开发,并最终由向导生成相应的BSP文件,而不再由设计人员
10、直接对源文件进行修改。docin/sundae_mengLinuxLinux设备驱动程序及开发设备驱动程序及开发docin/sundae_mengLinux设备驱动程序概述设备驱动程序概述nLinuxLinux设备驱动程序是处理或操作硬件控制器的软设备驱动程序是处理或操作硬件控制器的软件,被集成在内核中,是常驻内存的低级硬件处件,被集成在内核中,是常驻内存的低级硬件处理程序的共享库,设备驱动程序是系统对设备的理程序的共享库,设备驱动程序是系统对设备的抽象管理与控制。抽象管理与控制。nLinuxLinux允许设备驱动程序作为内核可加载模块实现,允许设备驱动程序作为内核可加载模块实现,即除了可以在
11、系统启动时进行注册外,还可以在即除了可以在系统启动时进行注册外,还可以在启动后进行加载注册。启动后进行加载注册。docin/sundae_mengLinux驱动程序开发n建立嵌入式Linux平台,移植和编写驱动程序往往是最具挑战的工作n驱动程序的开发周期一般较长,对产品的面世时间有着重要影响n驱动程序质量的好坏,直接关系到系统工作效能和稳定性,对项目的成败起着关键作用docin/sundae_meng设备驱动程序主要功能设备驱动程序主要功能n设备驱动程序主要完成如下功能:设备驱动程序主要完成如下功能:n检测设备和初始化设备检测设备和初始化设备n使设备投入运行和退出服务使设备投入运行和退出服务n
12、从设备接收数据并提交给内核从设备接收数据并提交给内核n从内核接收数据送到设备从内核接收数据送到设备n检测和处理设备错误检测和处理设备错误docin/sundae_mengLinux设备驱动程序分类 nLinuxLinux中所有设备被抽象出来,都看成文件中所有设备被抽象出来,都看成文件 n设备的读写和普通文件一样设备的读写和普通文件一样 nLinuxLinux系统的设备分为如下三类:系统的设备分为如下三类:n字符设备字符设备(char device)(char device)n块设备块设备(block device)(block device)n网络设备网络设备(network device)(
13、network device)n字符设备是指存取时没有缓存的设备字符设备是指存取时没有缓存的设备n块设备的读写都有缓存来支持,且块设备必须块设备的读写都有缓存来支持,且块设备必须能够随机存取能够随机存取(random access)n网络设备在网络设备在LinuxLinux里做专门的处理里做专门的处理 docin/sundae_mengLinux设备驱动程序分类网络设备在网络设备在LinuxLinux里做专门的处理里做专门的处理nLinuxLinux的网络系统主要是基于的网络系统主要是基于BSD unixBSD unix的的socket socket 机制。在系统和驱动程序之间定义有专门的数机
14、制。在系统和驱动程序之间定义有专门的数据结构据结构(sk_buff)(sk_buff)进行数据的传递进行数据的传递n系统里支持对发送数据和接收数据的缓存,提系统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持供流量控制机制,提供对多协议的支持 docin/sundae_mengLinux设备驱动程序分类n典型的字符设备包括鼠标,键盘,串行口等典型的字符设备包括鼠标,键盘,串行口等n块设备主要包括硬盘、软盘设备、块设备主要包括硬盘、软盘设备、CD-ROMCD-ROM等等n一个文件系统要安装进入操作系统必须在块一个文件系统要安装进入操作系统必须在块设备上设备上docin/su
15、ndae_mengLinux驱动程序介绍n嵌入式嵌入式LinuxLinux驱动已经支持的设备门类齐全,已成驱动已经支持的设备门类齐全,已成为其相对其他嵌入式操作系统的一大优势为其相对其他嵌入式操作系统的一大优势n工业控制常用的串口,并口工业控制常用的串口,并口n人机输入设备如鼠标、键盘,触摸屏人机输入设备如鼠标、键盘,触摸屏n彩色、黑白液晶显示输出彩色、黑白液晶显示输出n网络的完善支持,包括网络的完善支持,包括tcp/iptcp/ip,udpudp,firewallfirewall,WLANWLAN,ip forwardingip forwarding,ipsecipsec,vpnvpnnUs
16、bUsb的全面支持,包括的全面支持,包括usbusb硬盘、硬盘、u u盘,盘,usbusb摄像头摄像头n支持丰富的文件系统,包括支持丰富的文件系统,包括FAT32FAT32,NTFSNTFSdocin/sundae_meng嵌入式设备框图嵌入式设备框图docin/sundae_meng驱动程序的功用1 1、驱动程序直接操控硬件、驱动程序直接操控硬件n收发通讯数据n读写存储介质,比如flash或硬盘n操作输出设备和执行机构,例如打印,开关门禁等docin/sundae_meng驱动程序的功用(续)2 2、驱动程序提供软件访问硬件的机制、驱动程序提供软件访问硬件的机制n应用软件通过驱动程序安全高效
17、的访问硬件n驱动程序文件可以方便的提供访问权限控制n驱动程序作为一个隔离的中间层软件,将底 层细节隐藏起来,提高了软件的可移植性docin/sundae_meng访问Linux设备驱动的方法n设备提供dev文件系统节点和proc文 件系统节点n应用程序通过dev文件节点访问驱动 程序n应用程序通过proc文件节点可以查 询设备驱动的信息docin/sundae_meng驱动程序位置n驱动程序位于驱动程序位于driversdrivers目录下目录下n通常驱动程序占通常驱动程序占kernelkernel代码的代码的50%50%nLinuxLinux设备驱动程序在设备驱动程序在LinuxLinux的
18、内核源代码中占有很大的比例,的内核源代码中占有很大的比例,源代码的长度日益增加,主要是驱动程序的增加。源代码的长度日益增加,主要是驱动程序的增加。n在在LinuxLinux内核的不断升级过程中,驱动程序的结构还是相对内核的不断升级过程中,驱动程序的结构还是相对稳定。稳定。n在在2.0.xx2.0.xx到到2.2.xx2.2.xx的变动里,驱动程序的编写做了一些改变,的变动里,驱动程序的编写做了一些改变,但是从但是从2.0.xx2.0.xx的驱动到的驱动到2.2.xx2.2.xx的移植只需做少量的工作。的移植只需做少量的工作。docin/sundae_mengLinux驱动程序的特点n嵌入式Li
19、nux驱动程序需求多样n嵌入式设备硬件各异n嵌入式计算平台往往资源有限,比如处理速度、存储器容量、总线带宽、电池容量等n通常要求短的开发周期、压力大n开发驱动程序需要丰富的专业知识,包括 硬件和软件知识docin/sundae_meng嵌入式Linux驱动程序特点n嵌入式系统硬件更新速度加快n国际上大的嵌入式芯片提供商如Intel、Samsung、Freescale、TI、ST每年都有大量新品推出n新的芯片功能总是需要相应的驱动程序支持docin/sundae_mengLinux驱动开发流程n 熟悉设备的特性熟悉设备的特性n 确定设备驱动程序类别确定设备驱动程序类别n 编写测试用例编写测试用例
20、n 搜集可重用的代码搜集可重用的代码n 编写自己的驱动程序代码编写自己的驱动程序代码n 编码、调试、测试编码、调试、测试docin/sundae_mengLinux驱动程序的开发环境n本机编译调试n开发环境配置简单n无需网络环境n适用于配置较高的x86机器n主机+目标机n主机可以自由选择Linux或Windows+Cygwinn主机和目标机通过网络共享文件系统n内核崩溃不会影响主机docin/sundae_mengLinux驱动程序的开发环境(续)n主机+目标机环境包括n主机运行的工具链cross gcc+glibc+gdb,如果是windows主机还要有cygwin仿真环境n主机运行远程服务
21、,常用的有tftp用来传送内 核映像、initrd,NFS用来共享文件系统n目标机运行ssh或telnet等远程登陆服务,用来 调试驱动程序docin/sundae_mengLinux驱动程序的加载方式n驱动程序直接编译入内核n驱动程序在内核启动时就已经在内存中n可以保留专用存储器空间n驱动程序以模块形式存储在文件系 统里,需要时动态载入内核n驱动程序按需加载,不用时节省内存n驱动程序相对独立于内核,升级灵活docin/sundae_mengLinux驱动程序模块加载docin/sundae_mengLinux驱动程序开发的任务n规划硬件资源的使用n分离硬件相关和硬件无关的代码n划分驱动程序的
22、抽象层次n移植驱动程序到新的平台docin/sundae_mengLinux驱动程序开发的任务n规划硬件资源的使用nCPU时间片分配n中断处理n系统存储器空间映射docin/sundae_meng设备存储器的映射docin/sundae_mengLinux驱动程序开发的任务n分离硬件相关和硬件无关的代码n划分驱动程序的抽象层次docin/sundae_mengLinux驱动程序开发的任务n移植驱动程序到新的平台docin/sundae_mengGPL对驱动程序开发的影响n实现非GPL授权的方法模块形 式动态加载n驱动程序可以以私有产权形式进行 商业授权docin/sundae_meng设备驱动
23、程序的代码n驱动程序的注册与注销驱动程序的注册与注销nregister_chrdev()nregister_blkdev()n设备的打开与释放设备的打开与释放nopen()nrelease()n设备的读写操作设备的读写操作nread()nwrite()n设备的控制操作nioctl()docin/sundae_meng设备驱动的加载n使用模块的方式动态加载驱动使用模块的方式动态加载驱动nint func_init(void)func_init(void)n Makefile:Makefile:ninsmod xx.onlsmodnrmmod xx.on将驱动静态编译到内核里面将驱动静态编译到内核
24、里面n int _init func_init(void)int _init func_init(void)n Makefile:Makefile:n启动时自动加载docin/sundae_mengLinux驱动程序模块加载docin/sundae_meng编写驱动程序的一些基本概念n无论是什么操作系统的驱动程序,都有一些通用的概念n操作系统提供给驱动程序的支持也大致相同n以下简单介绍网络设备驱动程序的一些基本要求 docin/sundae_meng编写网络驱动程序发送和接收发送和接收 这是一个网络设备最基本的功能n如一块网卡所做的无非就是收发工作。所以驱动程序里要告诉系统发送函数在哪里,系统
25、在有数据要发送时就会调用发送程序。n驱动程序由于是直接操纵硬件的,所以网络硬件有数据收到,最先能得到这个数据的也就是驱动程序,它负责把这些原始数据进行必要的处理,然后送给系统。n这里,操作系统必须要提供两个机制:n找到驱动程序的发送函数n驱动程序把收到的数据送给系统 docin/sundae_meng编写驱动程序n读写读写n几乎所有设备都有输入和输出。每个驱动程几乎所有设备都有输入和输出。每个驱动程序要负责本设备的读写操作。序要负责本设备的读写操作。n操作系统不需要知道对设备的具体读写操作操作系统不需要知道对设备的具体读写操作怎样进行,这些都由驱动程序屏蔽掉了怎样进行,这些都由驱动程序屏蔽掉了
26、n操作系统定义好一些读写接口,由驱动程序操作系统定义好一些读写接口,由驱动程序完成具体的功能完成具体的功能n在驱动程序初始化时,需要把具有这种接口在驱动程序初始化时,需要把具有这种接口的读写函数注册进操作系统的读写函数注册进操作系统docin/sundae_meng编写驱动程序n中断中断n中断在现代计算机结构中有重要的地位中断在现代计算机结构中有重要的地位n操作系统必须提供驱动程序响应中断的能力操作系统必须提供驱动程序响应中断的能力n一般是把一个中断处理程序注册到系统中去一般是把一个中断处理程序注册到系统中去n操作系统在硬件中断发生后调用驱动程序的处理程序操作系统在硬件中断发生后调用驱动程序的
27、处理程序nLinuxLinux支持中断的共享,即多个设备共享一个中断支持中断的共享,即多个设备共享一个中断docin/sundae_meng编写驱动程序n时钟时钟n在实现驱动程序时,很多地方会用到时钟。如某些在实现驱动程序时,很多地方会用到时钟。如某些协议里的超时处理,没有中断机制的硬件的轮询等。协议里的超时处理,没有中断机制的硬件的轮询等。n操作系统应为驱动程序提供定时机制操作系统应为驱动程序提供定时机制n一般是在预定的时间过了以后回调注册的时钟函数一般是在预定的时间过了以后回调注册的时钟函数docin/sundae_meng内核模块 n模块是内核的一部分,但是并没有被编译到内核里去。它们被
28、分别编译和连接成目标文件。n用命令insmod插入一个模块到内核中,用命令rmmod卸载一个模块 n在Linux内核中,以下内容一般编译成模块:n大多数的驱动程序大多数的驱动程序。包括SCSI设备,CD-ROM,网络设备,不常用的字符设备,如打印机,watchdog等。n大多数文件系统,理论上除了根文件系统不能是模块,其他文件系统都可以是模块。n一些内核支持的不常用的可执行文件格式,如binfmt_misc。docin/sundae_meng kmod 和高级模块化 nLinux 提供了对模块自动加载和卸载的支持 n要利用这一特性,在编译内核前进行的配置中,必须打开对 kmod 的支持选项。n
29、一旦内核试图访问某种资源并发现该资源不可用时,它会对 kmod 子系统进行一次特殊的调用而不仅仅是返回一个错误 n按需加载的例子:ALSA(Advanced Linux Sound Architecture)声卡驱动程序组的实现 docin/sundae_meng常用的系统支持常用的系统支持 n内存申请和释放 n中断n时钟 nI/O n中断打开关闭 n输出信息n注册驱动程序 docin/sundae_meng内存申请和释放 ninclude/linux/kernel.h里声明了kmalloc()和kfree()。用于在内核模式下申请和释放内存。n与用户模式下的malloc()不同,kmallo
30、c()申请空间有大小限制。长度是2的整次方。可以申请的最大长度也有限制。另外kmalloc()有priority参数 nKfree()释放的内存必须是kmalloc()申请的 docin/sundae_meng申请中断和释放中断 nrequest_irq()、free_irq()是驱动程序申请中断和释放中断的调用。n在include/linux/sched.h里声明 docin/sundae_meng时钟 n时钟的处理类似中断,也是登记一个时间处理函数,在预定的时间过后,系统会调用这个函数。n在include/linux/timer.h里声明n使用时钟,先声明一个timer_list结构,调用
31、init_timer对它进行初始化。Time_list结构里expires是标明这个时钟的周期,单位采用jiffies的单位。docin/sundae_mengI/O nI/O端口的存取使用:ninline unsigned int inb(unsigned short port);ninline unsigned int inb_p(unsigned short port);ninline void outb(char value,unsigned short port);ninline void outb_p(char value,unsigned short port);n在includ
32、e/adm/io.h里定义 docin/sundae_meng中断打开关闭 n系统提供给驱动程序开放和关闭响应中断的能力 n是在include/asm/system.h n#define cli()_asm_ _volatile_(cli:)n#define sti()_asm_ _volatile_(sti:)docin/sundae_meng输出信息 n驱动程序要输出信息使用printk()ninclude/linux/kernel.h里声明 docin/sundae_meng注册驱动程序 n如果使用模块(module)方式加载驱动程序,需要在模块初始化时把设备注册到系统设备表里去n不再使
33、用时,把设备从系统中卸除 n定义在drivers/net/net_init.h里的两个函数完成这个工作nInt register_netdev(struct device*dev);nvoid unregister_netdev(struct device*dev);docin/sundae_meng网络驱动程序的结构 n所有的Linux网络驱动程序遵循通用的接口 n设计时采用的是面向对象的方法 n一个设备就是一个对象(device 结构),它内部有自己的数据和方法 n每一个设备的方法被调用时的第一个参数都是这个设备对象本身。这样这个方法就可以存取自身的数据(类似面向对象程序设计时的this引
34、用)n一个网络设备最基本的方法有初始化、发送和接收 docin/sundae_meng网络驱动程序的结构(续)n初始化程序完成硬件的初始化、device中变量的初始化和系统资源的申请n发送程序是在驱动程序的上层协议层有数据要发送时自动调用的。一般驱动程序中不对发送数据进行缓存,而是直接使用硬件的发送功能把数据发送出去n接收数据一般是通过硬件中断来通知的。在中断处理程序里,把硬件帧信息填入一个skbuff结构中,然后调用netif_rx()传递给上层处理 docin/sundae_meng网络驱动程序的基本方法 n初始化(initialize)n打开(open)n关闭(stop)n发送(hard
35、_start_xmit)n接收(reception)n硬件帧头(hard_header)n地址解析(xarp)n参数设置和统计数据docin/sundae_meng 网络驱动程序的基本方法网络驱动程序的基本方法-初始化初始化n驱动程序必须有一个初始化方法n在把驱动程序载入系统的时候会调用这个初始化程序。它做以下几方面的工作:n检测设备检测设备:在初始化程序里你可以根据硬件的特征检查硬件是否存在,然后决定是否启动这个驱动程序。n配置和初始化硬件配置和初始化硬件:在初始化程序里可以完成对硬件资源的配置,比如即插即用的硬件就可以在这个时候进行配置(Linux内核对PnP功能没有很好的支持,可以在驱动
36、程序里完成这个功能)。n配置或协商好硬件占用的资源以后,就可以向系统申请这些资源。有些资源是可以和别的设备共享的,如中断。有些是不能共享的,如IO、DMA。n初始化初始化devicedevice结构中的变量结构中的变量n让硬件正式开始工作让硬件正式开始工作 docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法打开打开打开打开(open)(open)open这个方法在网络设备驱动程序里是在网络设备被激活的时候被调用(即设备状态由down-up)n实际上很多在initialize中的工作可以放到这里来做。比如资源的申请、硬件的激活。n如果dev-open返回非0(erro
37、r),则硬件的状态还是down nopen方法另一个作用是如果驱动程序做为一个模块被装入,则要防止模块卸载时设备处于打开状态。n在open方法里要调用MOD_INC_USE_COUNT宏 docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法关闭关闭关闭关闭(stop)(stop)close方法做和open相反的工作。可以释放某些资源以减少系统负担。nclose是在设备状态由up转为down时被调用的n如果是做为模块装入的驱动程序,close里 应该调用MOD_DEC_USE_COUNT,减少设备被引用的次数,以使驱动程序可以被卸载。nclose方法必须返回成功(0=s
38、uccess)docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法发送发送发送发送(hard_start_xmit)(hard_start_xmit)所有的网络设备驱动程序都必须有这个发送方法。n在系统调用驱动程序的xmit时,发送的数据放在一个sk_buff结构中。n一般的驱动程序把数据传给硬件发出去。也有一些特殊的设备比如loopback把数据组成一个接收数据再回送给系统,或者 dummy设备直接丢弃数据。n如果发送成功,hard_start_xmit方法里释放sk_buff,返回0(发送成功)n如果设备暂时无法处理,比如硬件忙,则返回1。这时如果dev-tbus
39、y置为非0,则系统认为硬件忙,要等到dev-tbusy置0以后才会再次发送。tbusy的置0任务一般由中断完成。docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法发送(续)发送(续)n硬件在发送结束后产生中断,这时可以把tbusy置0,然后用mark_bh()调用通知系统可以再次发送。n在发送不成功的情况下,也可以不置dev-tbusy为非0,这样系统会不断尝试重发。n如果hard_start_xmit发送不成功,则不要释放sk_buff。n传送下来的sk_buff中的数据已经包含硬件需要的帧头。所以在发送方法里不需要再填充硬件帧头,数据可以直接提交给硬件发送。sk
40、_buff是被锁住的(locked),确保其他程序不会存取它。docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法接收接收接收接收(reception)(reception)驱动程序并不存在一个接收方法。有数据收到应该是驱动程序来通知系统的。n一般设备收到数据后都会产生一个中断,在中断处理程序中驱动程序申请一块sk_buff(skb),从硬件读出数据放置到申请好的缓冲区里。接下来填充sk_buff中的一些信息。skb-dev=dev,判断收到帧的协议类型,填入skb-protocol(多协 议的支持)。n把指针skb-mac.raw指向硬件数据然后丢弃硬件帧头(skb
41、_pull)。docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法接收(续)接收(续)n还要 设置skb-pkt_type,标明第二层(链路层)数据类型。可以是以下类型:PACKET_BROADCAST:链路层广播 PACKET_MULTICAST:链路层组播 PACKET_SELF:发给自己的帧 PACKET_OTHERHOST:发给别人的帧(监听模式时会有这种帧)n最后调用netif_rx()把数据传送给协议层。netif_rx()里数据放入处理队列然后返回,真正的处理是在中断返回以后,这样可以减少中断时间。n调用netif_rx()以后,驱动程序就不能再存取数据
42、缓冲区skb。docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法硬件帧头硬件帧头n硬件一般都会在上层数据发送之前加上自己的硬件帧头,比如以太网(Ethernet)就有14字节的帧头。这个帧头是加在上层ip、ipx等数据包的前面的。n驱动程序提供一个hard_header方法,协议层(ip、ipx、arp等)在发送数据之前会调用这段程序。n硬件帧头的长度必须填在dev-hard_header_len,这样协议层回在数据之前保留好硬件帧头的空间。这样hard_header程序只要调用skb_push然后正确填入硬件帧头就可以了。docin/sundae_meng网络驱动
43、程序的基本方法网络驱动程序的基本方法硬件帧头(续硬件帧头(续1 1)n在协议层调用hard_header时,传送的参数包括(2.0.xx):n数据的sk_buff ndevice指针nProtocoln目的地址(daddr)n源地址(saddr)n数据长度(len)n数据长度不要使用sk_buff中的参数,因为调用hard_header时数据可能还没完全组织好 nsaddr是NULL的话是使用缺省地址(default)ndaddr是NULL表明协议层不知道硬件目的地址n如果hard_header完全填好了硬件帧头,则返回添加的字节数。docin/sundae_meng网络驱动程序的基本方法网络
44、驱动程序的基本方法硬件帧头(续硬件帧头(续2 2)n如果硬件帧头中的信息还不完全(比如daddr为NULL,但是帧头中需要目的硬件地址。典型的情况是以太网需要地址解析(arp),则返回负字节数。hard_header返回负数的情况下,协议层会做进一步的build header的工作。n目前Linux系统里就是做arp(如果hard_header返回正,dev-arp=1,表明不需要做arp,返回负,dev-arp=0,做arp)。对hard_header的调用在每个协议层的处理程序里。如ip_output。docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法地址解析地
45、址解析地址解析地址解析(xarp)(xarp)有些网络有硬件地址(比如Ethernet),并且在发送硬件帧时需要知道目的硬件地址。这样就需要上层协议地址(ip、ipx)和硬件地址的对应。这个对应是通过地址 解析完成的。n需要做arp的的设备在发送之前会调用驱动程序的rebuild_header方法。调用的主要参数包括:n指向硬件帧头的指针n协议层地址n如果驱动程序能够解析硬件地址,就返回1,如果不能,返回0。n对rebuild_header的调用在net/core/dev.c的do_dev_queue_xmit()里。docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方
46、法参数设置和统计数据参数设置和统计数据 参数设置和统计数据参数设置和统计数据 在驱动程序里还提供一些方法供系统对设备的参数进行设置和读取信息。n一般只有超级用户(root)权限才能对设备参数进行设置。n设置方法有:ndev-set_mac_address()当用户调用ioctl类型为SIOCSIFHWADDR时是要设置这个设备的mac地址。一般对mac地址的设置没有太大意义的。docin/sundae_meng网络驱动程序的基本方法网络驱动程序的基本方法参数设置和统计数据(续)参数设置和统计数据(续)ndev-set_config()当用户调用ioctl时类型为SIOCSIFMAP时,系统会调
47、用驱动程序的set_config方法。用户会传递一个ifmap结构包含需要的I/O、中断等参数。ndev-do_ioctl()如果用户调用ioctl时类型在SIOCDEVPRIVATE和SIOCDEVPRIVATE+15之间,系统会调用驱动程序的这个方法。一般是设置设备的专用数据。读取信息也是通过ioctl调用进行。n除次之外驱动程序还可以提供一个dev-get_stats方法,返回一个enet_statistics结构,包含发送接收的统计信息。nioctl的处理在net/core/dev.c的dev_ioctl()和dev_ifsioc()里 docin/sundae_meng网络驱动程序中
48、用到的数据结构 n最重要的是网络设备的数据结构。它定义在include/linux/netdevice.h nsk_buff nLinux网络各层之间的数据传送都是通过sk_buff docin/sundae_meng编写编写LinuxLinux网络驱动程序中需要注意的问题网络驱动程序中需要注意的问题 n中断共享 n硬件发送忙时的处理 n流量控制(flow control)n调试 docin/sundae_meng中断共享 nLinux系统运行几个设备共享同一个中断。需要共享的话,在申请的时候指明共享方式。n系统提供的request_irq()调用的定义:int request_irq(uns
49、igned int irq,void(*handler)(int irq,void*dev_id,struct pt_regs*regs),unsigned long irqflags,const char*devname,void*dev_id);n如果共享中断,irqflags设置SA_SHIRQ属性,这样就允许别的设备申请同一个中断。需要注意所有用到这个中断的设备在调用request_irq()都必须设置这个属性。系统在回调每个中断处理程序时,可以用dev_id这个参数找到相应的设备。一 般dev_id就设为device结构本身。系统处理共享中断是用各自的dev_id参数依次调用每一个中
50、断处理程序。docin/sundae_meng硬件发送忙时的处理n主CPU的处理能力一般比网络发送要快,所以经常会遇到系统有数据要发,但上一包数据网络设备还没发送完。因为在Linux里网络设备驱动程序一般不做数据缓存,不能发送的数据都是通知系统发送不成功,所以必须要有一个机制在硬件不忙时及时通知系统接着发送下面的数据。n一般对发送忙的处理在前面设备的发送方法(hard_start_xmit)里已经描述过,即如果发送忙,置tbusy为1。处理完发送数据后,在发送结束中断里清tbusy,同时用mark_bh()调用通知系统继续发送。但在具体实现驱动程序时发现,这样的处理系统好象并不能及时地知道硬件
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。