参加Python培训班幼师短期就业培训班怎么样?

您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
嵌入式系统VxWorks下网络管理的研究与实现.pdf75页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
文档加载中...广告还剩秒
需要金币:200 &&
你可能关注的文档:
··········
··········
西安电子科技大学 硕士学位论文
嵌入式系统VxWorks下网络管理的研究与实现 姓名:邵势雄 申请学位级别:硕士 专业:信号与信息处理 指导教师:李鹏 座机电话号码 摘要 随着军工、信息家电中嵌入式技术的广泛应用,如何基于一个嵌入式实时系统
设计并实现网络管理系统,成为一项重要技术。本文论述了如何在嵌入式实时操
作系统VxWorks下实现网络管理系统,重点可以分为二部分: 第一,简单网络管理协议 SNMP 的实现。一方面,SNMP报文中的每个字
段都使用了可变长度的编码值 包括长度字段也是如此 ,因此对于管理信息的通
信,程序实现了SNMP报文的编码或解码、报文的分析、MIB变量的提取、生成
请求或应答报文等功能。另一方面,对于正在被管理设备的信息,则根据需要定
义被管理设备的管理信息库 MIB 。 第二,基于GUI的网管系统的实现。程序实现了M1B浏览器、配置管理、故
障管理和性能管理四个功能模块。为方便用户的使用,结合UGI和ZINC,在
VxWorks下实现了具有图形用户界面 GUI 的上述网管系统。 测试和实验结果表明。此设计思想简单、高效,能够满足对整个系统中的设
备进行管理的需要。同时本项目开发的代理和管理程序也与其它基于SNMP协议
的网管程序兼容。 SNMP 【关键词】嵌入式实时操作系统 网络管理
VxWorks ABSTRACT most in AsEmbeddedarethe War systems populartechnologyapplied industry,
information to and Network design appliances,how implementation Management all become
underanembedded focusonthe important paper system technology.This
researchand ofnetwork underVxWorks implementationmanagement
system. at The canbediscussedtwo of emphases aspects,theimplementation simple the
network network basedon management management protocol SNM
正在加载中,请稍后...当前位置: >>
小硕vxworks网络驱动开发笔记
目录第 1 章 操作系统基本概念 ......................................................................................... 4 1.1 实时操作系统和分时操作系统的区别 .......................................................
.. 4 1.2 嵌入式操作系统 VxWorks 简介 ..................................................................... 4 1.3 VxWorks 的特点 ........................................................................................... 5 1.3.1 可靠性 .................................................................................................. 5 1.3.2 实时性 .................................................................................................. 5 1.3.3 可裁减性 ............................................................................................. 6 1.3.4 对一个实时内核的要求 ...................................................................... 6 1.4 VxWorks 的整体构架 ................................................................................... 7第 2 章 vxWorks 驱动开发预备................................................................................... 7 2.1 VxWorks 映像 .................................................................................................. 8 2.2 BSP 主要文件目录的组成及作用: .............................................................. 11 2.3 系统启动顺序 ............................................................................................... 14 2.4 Vxworks 驱动概要 ......................................................................................... 17 第3章 vxWorks 网络驱动开发.............................................................................. 213.1 驱动类别 ....................................................................................................... 22 3.2 Vxworks 下网络驱动开发 ............................................................................ 24 3.3 VxWorks 网络驱动配置及分析 .................................................................... 60 第 4 章 VxWorks 系统中常见问题 ............................................................................ 651 / 69 前言在通信, 电子领域, 目前主流的嵌入式操作系统为 linux 和 vxworks。 Linux 多用于消费电子产品,像大家熟悉的 andriod,原始系统就是 linux,也就是说 andriod 也是一种 linux 系统。还有大家熟悉的 MP3,也是使用 linux 操作系统 的。Linux 因为价格便宜(开源的,不需要付 licence),稳定性好占据了一定 的市场份额。 Vxworks 是风河系统 1983 开发的一款嵌入式实时操作系统,多 用于通信,导航,航天等领域。因为这些领域对实时性要求非常高,比如现在 LTE 系统就是使用 vxworks 系统,因为是采用 TDD 模式,而这种模式,显然 对实时性要求非常高。也就注定了 vxwroks 在这些领域的特有优势。 选择 linux 还是 vxworks 看自己的专业方向,还有自己的兴趣所有。每个 领域只要研究透彻,都是很有前途的。 既然两者都是主流的嵌入式操作系统,其还是有很多相似性。小编也初步接 触过 linux,发现具备一定的 linux 基础对日后深入学习 vxworks 很有好处,很 多思想都是相似的。 另外,本人系小硕,目前的研究领域是 vxworks 驱动开发,主攻网络驱动 开发。 在平常的日常学习中, 结合各位网友提供的资料 (自己在百度上收集的) , 还有 workbench 提供的 document(自己翻译,特别是针对网络驱动部分), 希望对广大嵌入式驱动开发者有所帮助。声明: 声明:此文档并不适合于 vxworks 初学者, 因为这里, 小编省去了很多 vxworks 下的基本知识,包括内核中常用的进程,信号量等等支持。也没有提及集成开发 环境 tornado/vworkbench. 这里的探索重点是 vxwroks 底层的东西,包括启 动过程,BSP 开发等。 附录: Vxworks 的应用领域 嵌入式 Vxworks 系统的主要应用领域主要有以下几方面: 如:以太网交换机、路由器、远程接入服务器等2 / 691.数据网络:2.远程通讯:如:电信用的 专用分组交换机和自动呼叫分配器,蜂窝电话系统等 理疗设备 4.消费电子:如:个人数字助理等 6.工业:如:机器人3.医疗设备:如:放射5.交通运输:如:导航系统、 7.航空航天:如:卫星跟踪系统 总高速火车控制系统等8.多媒体: 电视会议设备 如:9.计算机外围设备: X 终端、 如: I/O 系统等之,VxWorks 的系统结构是一个相当小的微内核的层次结构。内核仅提供多任 务环境、进程间通信和同步功能。这些功能模块足够支持 VxWorks 在较高层次 所提供的丰富的性能的要求。3 / 69 第 1 章 操作系统基本概念1.1 实时操作系统和分时操作系统的区别从操作系统能否满足实时性要求来区分, 可把操作系统分成分时操作系统和 实时操作系统。 分时操作系统按照相等的时间片调度进程轮流运行, 分时操作系统由调度程 序自动计算进程的优先级,而不是由用户控制进程的优先级。这样的系统无法实 时响应外部异步事件。 实时操作系统能够在限定的时间内执行完所规定的功能, 并能在限定的时间内对 外部的异步事件作出响应。 分时系统主要应用于科学计算和一般实时性要求不 高的场合。实时性系统主要应用于过程控制、数据采集、通信、多媒体信息处理 等对时间敏感的场合。1.2 嵌入式操作系统 VxWorks 简介VxWorks 操作系统是美国 WindRiver 公司于 1983 年设计开发的一种嵌入式 实时操作系统(RTOS),是嵌入式开发环境的关键组成部分。良好的持续发展能 力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一 席之地。 它以其良好的可靠性和卓越的实时性被广泛地应用在通信、 军事、 航空、 航天等高精尖技术及实时性要求极高的领域中,如卫星通讯、军事演习、弹道制 导、飞机导航等。在美国的 F-16、FA-18 战斗机、B-2 隐形轰炸机和爱国者导 弹上,甚至连 1997 年 4 月在火星表面登陆的火星探测器上也使用到了 VxWorks。 VxWorks 操作系统是一个嵌入式实时操作系统(RTOS)。 VxWorks 与其它实时 OS 一样,基于以下两个重要机制: 多任务环境及任务间通信。4 / 69 硬件中断处理。 VxWorks 多任务内核完成的功能是:实时调度,任务间通信及互斥。 其它功能则作为系统库围绕在内核周围,它们可根据需要进行剪裁。 VxWorks 与非实时系统的不同之处在于: VxWorks 的优先抢占机制基于调度, VxWorks 对外部事件的反应和处理快, VxWorks 容量小并且可配置(微内核结构)1.3VxWorks 的特点1.3.1 可靠性操作系统的用户希望在一个工作稳定,可以信赖的环境中工作,所以操作系 统的可靠性是用户首先要考虑的问题。而稳定、可靠一直是 VxWorks 的一个突 出优点。自从对中国的销售解禁以来,VxWorks 以其良好的可靠性在中国赢得了 越来越多的用户。1.3.2 实时性实时性是指能够在限定时间内执行完规定的功能并对外部的异步事件作出 响应的能力。实时性的强弱是以完成规定功能和作出响应时间的长短来衡量的。 VxWorks 的实时性做得非常好,其系统本身的开销很小,进程调度、进程 间通信、中断处理等系统公用程序精练而有效,它们造成的延迟很短。VxWorks 提 供 的 多 任 务 机 制 中 对 任 务 的 控 制 采 用 了 优 先 级 抢 占 ( Preemptive Priority Scheduling)和轮转调度(Round-Robin Scheduling)机制,也充分保证了可靠的 实时性,使同样的硬件配置能满足更强的实时性要求,为应用的开发留下更大的 余地。5 / 69 1.3.3 可裁减性用户在使用操作系统时,并不是操作系统中的每一个部件都要用到。例如图 形显示、 文件系统以及一些设备驱动在某些嵌入系统中往往并不使用。 VxWorks 由一个体积很小的内核及一些可以根据需要进行定制的系统模块组成。VxWorks 内核最小为 8kB, 即便加上其它必要模块, 所占用的空间也很小, 且不失其实时、 多任务的系统特征。由于它的高度灵活性,用户可以很容易地对这一操作系统进 行定制或作适当开发,来满足自己的实际应用需要。1.3.4 对一个实时内核的要求一个实时操作系统内核需满足许多特定的实时环境所提出的基本要求, 这些 包括: 多任务: 多任务:由于真实世界的事件的异步性,能够运行许多并发进程或任务是很重要 的。多任务提供了一个较好的对真实世界的匹配,因为它允许对应于许多外部事 件的多线程执行。系统内核分配 CPU 给这些任务来获得并发性。 抢占调度:真实世界的事件具有继承的优先级,在分配 CPU 的时候要注意到这 抢占调度 些优先级。基于优先级的抢占调度,任务都被指定了优先级,在能够执行的任务 (没有被挂起或正在等待资源)中,优先级最高的任务被分配 CPU 资源。换句 话说,当一个高优先级的任务变为可执行态,它会立即抢占当前正在运行的较低 优先级的任务。 任务间的通讯与同步: 可能有许多任务作为一个应用的一部 任务间的通讯与同步 在一个实时系统中, 分执行。系统必须提供这些任务间的快速且功能强大的通信机制。内核也要提供 为了有效地共享不可抢占的资源或临界区所需的同步机制。 任务与中断之间的通信: 但为了提 任务与中断之间的通信 尽管真实世界的事件通常作为中断方式到来, 供有效的排队、 优先化和减少中断延时, 我们通常希望在任务级处理相应的工作。 所以需要杂任务级和中断级之间存在通信。6 / 69 1.4VxWorks 的整体构架VxWorks 支持多种处理器,对硬件不做假设,可支持 ARM.PPC,MPIS 架构处理 支持多种处理器,对硬件不做假设, 器。驱动开发预备 第 2 章 vxWorks 驱动开发预备BSP 定义 定义: Board support packet ,为各种目标板的硬件功能提供了统一的软件接口它们包括: 硬件初始化 中断处理和产生 硬件时钟和定时器管理 内存映射和分配7 / 69 BSP 还包括 boot Rom 和其它启动机制,sysLib 和 sysALib 库是 VxWorks 可移 植的核心,BSP 库是硬件与软件的接口,处理硬件的初始化、中断处理与产生、硬 件时钟与定时管理、局部和总线内存空间的映射、内存大小定义,等等2.1 VxWorks 映像用户通过定制 VxWorks 组件和进行应用程序开发所生成 映像 包括 wind 多任务微内核,也包括 BSP 的引导代码 ? Vxworks 映像的三部分组成 BSS 段(Block Started by Symbol,未手动初始化的数据) 代码段 数据段 ?两大类 BootRom 类型映像 VxWorks 类型BootRom 类型映像 最小化、专用的 VxWorks 引导映像,实现最少的系统 初始化用于启动装 载 VxWorks 映像,功能类似于 PC 机的 BIOS。BootRom 运行时建立起多任 务环境 usrRoot 任务、网络任务(tNettask)、TFFS 任务和 FTP 任务等。运 行地点可能在 ROM/Flash 中执行(例如 ROM 驻留型引导映像),也可能在 RAM 中执行。 在系统中其对应的编译规则文件是 rules.bsp BootRom 类型分为三种 BootRom_res 一直运行在 rom 中的映象, 只把 data 段拷贝到 ram 里 面。 BootRom_uncmp 非压缩方式的映象,data 段和 text 段都要拷贝到ram 里 面,并在 ram 里面运行。8 / 69 BootRom压缩方式的映象,生成的时候编译器会把除掉 romlnit.s 和 bootInit.c 之外的目标文件压缩并“汇编”成一个 bootrom.Z.s,最后和 romInit.o, bootInit.o, version.o 进行链接,生成 bootrom 映像。要全部拷贝到 ram 中,并必须要进行解压缩的工作。而这 些工作基本上都是在 bootInit.c 中进行 的。VxWorks 类型映像系统的主映像, 是系统最终要运行的映像该映像在运行时至少有一部分(如: 数据段和 BSS 段)需要在 RAM 中运行。在系统中其对应的编译规则文件是 rules.vxWorks Vxworks 类型映像运行环境 RAM 运行的 ROM 运行的 VxWorks 类型四种映像 VxWorks: RAM 运行的 VxWorks 映像不包含引导程序, 需要 独立的引导程序从本地存储器或者经 由网络获取该映像,然后 将其下载到 RAM 中的 RAM_LOW_LADRS 处运行 压缩的 非压缩的VxWorks_romROM 自动 RAM 运行的 VxWorks 映像,不需要 BootRom 辅 助VxWorks_romResidentROM 启动 ROM 运行的 VxWorks 映像, 不需要 BootRom 辅助。包含引导代码,在重启时清空 RAM,引导 代码只将 data 段拷 贝到 RAM 中的 RAM_LOW_ADRS 处, 系统 的运行是在 ROM 中进行的,启动速度快,需要的 RAM 空间少, 但是运行速度慢 。 VxWorks_romCompressVxWorks_rom 的压缩形式9 / 69 VxWorks 型 vs BootROM 型映像对于没有自启动功能的 VxWorks 类型映像(如 VxWorks 型),映像运行 前 需 一 段 程 序 将 该 映 像 拷 贝 到 RAM 中 运 行 , BootRom 类 型 映 像 完 成 VxWorks 系统下载, 完毕后 BootRom 的任务就结束了 二者在系统初始化的时候,所做的功能基本相 同,BootRom 类型映像调 用 bootConfig.c,而 VxWorks 类型映像调用 usrConfig.c映像链接方式可被静态或动态链接 VxWorks 在开发阶段可动态地下载目标文件, 并与 操作系统及其它目标文 件动态链接。链接以后是浮动的,只在装载时才与绝对物理地址 相对应。静态 VxWorks 成品阶段是采用静态链接的。10 / 69 要对系统底层驱动清楚,也就是对 CPU 及相关的硬件有所了解.主要是 32 微 处理器(上电启动过程, download image 的方式方法,读写 ROM,地址空间分 配,MMU,寄存器,中断定义,..).参照硬件资料,多读一些源码会有所帮助. Tornado 2 开发调试环境协议框图 主机开发(Host Development System) 目标机(Target System)Tornado 工具Application Shell Editor Debugger 信 &==========& Target WTX 协 议 通 Server | Target Agent VxWorks Target Simulator 两个主要两个协议 WTX 协议(Wind River Tool eXchange): 用于开发机内部 Tornado 工具与 Target Server 之间通信. WDB 协议(Wind DeBug): 用于主机 Target Server 与目标机之间的通信. Project Browser Windview WDB 协议通信 &==========& VxWorks OS VxWorks Target (WDB)Agent2.2 BSP 主要文件目录的组成及作用 主要文件目录的组成及作用 作用: Install_direction/target/config/All:这个目录下的文件是所有 BSP 文件共享的 不是特别需要不要更改里面的任 共享的,不是特别需要不要更改里面的任 共享的11 / 69 何文件. 何文件 configAll.h: 缺省定义了所有 VxWorks 的设置.如果不用缺省的设置,可在 BSP 目录下 的 config.h 文件中用#define 或#undef 方式来更改设置. bootInit.c: 在 romInit.s 后,完成 Boot ROM 的第二步初始化.程序从 romInit.s 中的 romInit()跳到这个文件中的 romStart().来执行必要的解压和 ROM image 的 放置. bootConfig.c: 完成 Boot ROM image 的初始化和控制. usrConfig.c: VxWorks image 的初始化代码.Install/target/config/comps/src:涉及系统核心的 components,主要由 target/config/All 中 usrConfig.c 中 函数调用. intasll/target/config/bspname: 包含系统或硬件相关的 BSP 文件. Makefile 一些命令行控制 images 的生成,参见 BSP 设置部分及生成下载 README BSP 发布纪录,版本,总的文档 config.h 包括所有涉及 CPU 主板的设置及定义(includes,definations),参见 BSP 设 置文件及生成下载configNet.h网络驱动的主要设置文件,主要对 END 驱动设置. romInit.s 汇编语言文件,是 VxWorks Boot ROM 和 ROM based image 的入口,参 见 系统启动部分 sysALib.s 汇编语言文件,程序员可以把自己的汇编函数放在这个文件里,在上层调 用.VxWorks image 的入口点_sysInit 在这个文件里,是在 RAM 中执行的12 / 69 第一个函数。 sysLib.c 包含一些系统相关的函数例程,提供了一个 board-level 的接口,VxWorks 和应用程序可以以 system-indepent 的方式生成.这个文件还能包含目录 target/config/comps/src 的驱动. sysScsi.c 可选文件用于 Scsi 设备设置和初始化. 可选文件 sysSerial.c 可选文件用于所有的串口设置和初始化. 可选文件 bootrom.hex ASIC 文件包含 VxWorks Boot ROM 代码VxWorks运行在目标机上,完整的,连结后的 VxWorks 二进制文件. VxWorks.sym 完全的,连结后带有符号表的 VxWorks 二进制文件 VxWorks.st 完全的,连结后,standalone,带有符号表的 VxWorks 二进制文件 BSP 用&make&来编译连接生成(Created),而不是用 Tornado 的工具. BSP 和应用程序都可以在&make&或&tornade&上开发(developed) 。BSP 被设置包括以下驱动 被设置包括以下驱动: 中断控制 interrupt controller 计时器 timer(sys/aux) 串口 UART(serial) 显示屏 LCD 键盘 Keyboard(opt) 触摸屏 touch-screen(opt).13 / 69 2.3 系统启动顺序VxWorks image分为在 ROM 中运行和在 RAM 中运行两种.两者启动顺序的区别在于sysInit()函数的调用.该函数在 RAM 运行的 VxWorks 中初始化 RAM. 函数的调用ROM 中运行的 VxWorks VxWorks 在 ROM 中运行,即写入 ROM 中的 VxWorks 是非压缩的,不需要解压, 系统直接跳到 ROM 的首地址,运行 VxWorks.注意:ROM 运行的 VxWorks 并不 支持所有的主扳,应以主扳手册为准. 文件 romInit.s 中的 romInit()----&文件 bootInit.c 中的 romStart()--&文 usrConfig usrInit()----&sysHwInit()---&usrKernelInit()---&KernelInit(usrRoot,...)。Vxwroks 在 ROM 中运行的优势 VxWorks 在 ROM 中运行主要是为了节省 RAM 空间,以便应用程序有更大的空 间运行.只把 VxWorks image 的 data 段复制到 RAM 的 LOCAL_LOW_ADRS, text 部 分留在 ROM 并在 ROM 中执行.。ROM 中运行的 VxWorks 缺点是运行速度慢.RAM 中运行的 VxWorksVxWorks 在 RAM 中运行,即写入 ROM 中的 Boot 或 VxWorks Image 是压 缩的,需要先解压 copy 所有的 text 和 data 到 RAM 的 LOCAL_LOW_ADRS 中, 下面 sysInit()主要是初始化 RAM 用的,系统直接跳到 RAM 的首地址,运行 VxWorks usrInit()前面不压缩,即 romInit(),romStart()不能压缩. 启动过程 文 件 romInit.s 中 的 中 的 romInit()----& 文 件 sysInit()----& 文 件 bootInit.c usrConfig.c 中 的 中 的romStart()----&sysaLib.susrInit()-----&sysHwInit()-----&usrKernelInit()-----&KernelInit(usrRoot,...) 。 RAM 运行的 Boot 或 VxWorks image 的 text 段或 data 段会从 ROM 复制到 RAM,14 / 69 在 RAM 中运行。其中 usrRoot()是 VxWorks 启动的第一个任务 第一个任务,由它来初始化 第一个任务 driver,network 等。BootROM image 的启动过程最少的系统初始化,主要用于启动装载 VxWorks image.一般有压缩和不 压缩两种形式,如 bootrom 和 boot_uncmp.与 VxWorks image 的区别在于一个 Bootrom 调用 bootConfig.c,而 VxWorks 调用 usrConfig.c. 启动顺序 文件 romInit.s 中的 romInit()----&文件 bootInit.c 中的 romStart()----&文 件 bootConfig 中 的usrInit()-----&sysHwInit()-----&usrKernelInit()-----&KernelInit(usrRoot,...) 其中 /target/config/all/bootConfig.c 是 Boot ROM 设置模块.用于通过网络 加载 VxWorks image. usrRoot()----&bootCmdLoop(void) autobooting-----&bootLoad(pLine, 命 令 行 选 择 , 或&entry) 载 模 块 到 内 存 ( 网络,TFFS,TSFS...)-----&netifAttach()----&go(entry)-----&(entry)()从入口开始执 行,不返回.系统启动中几个很重要的函数及其作用 romInit()-----power up,disable interrupt,put boot type on the stack,clears caches. romStart()-----load Image Segments into RAM. usrInit()----- Interrupt lock out,save imformation about boot type,handle all the Initialization before the kernel is actually started,then starts the kernel execution to create an initial task usrRoot().This task completes the start up. sysHwInit()-----Interrup locked,Initializes hardware,registers,activationkernel.KernelInit(usrRoot,...)----- Initializes and starts the kernel. Defines system memory partition. Activates a task15 / 69 tUsrRoot to complete initalization. Unlocks inierrupts. Uses usrInit() initate stack. usrRoot() 初始化内存分区表(memory partition library) ,初始化系统系统 时钟(system clock) 。初始化输入输出系统(I/O system)----可选 Create devices----可选 设置网络(Configure network)--------可选 激活 WDB 目标通信(Activate WDB agent)---------可选 调用程序(Activate application)VxWorks Image 在 RAM 中解压的位置RAM Low Address VxWorks 运行的位置Boot image 由 ROM 解压 RAM High Address 后 Copy 的 位 置 , 即 bootRom 区RAM Low Address,RAM High Address 和有关定义在 BSP,config.h,makefile 文件中定 义.可参见 BSP 配置文件及生成下载VxWorks 在 ROM 中的情况16 / 69 ROM 低高地 址位 压缩的 VxWorks Imgage没有压缩的 romInit.s 和 romStart()在 ROM 的起始 位置,系统 power up 后,从 ROM 低地址 位 这个起始位开始执行,即 执 行 romInit(), 起 始 位置 由硬件定义,一般为 0x 注:浅蓝色为整个 VxWorks Image. 其中 RAM_LOW_ADRS, RAM_HIGH_ADRS 等一些地址在 makefile 和 BSP config.h 中定义.可参见 BSP 配置文件及生成下载2.4 Vxworks 驱动概要总线类型PLB(processor local bus),VME,PCI,PCI-Express,RapidIO,Mii,Virtual, MF(multi function device bus),USB,IIC,SPI.驱动可以提供的服务配置 配置资源例如 ns83902VxbEnd.c 设备驱动中有这么一段 devResourceGet (pHcf, &regWidth&, HCF_RES_INT, (void *)17 / 69 &registerW 这里的registerwidth 就是资源 配置参数 vxbInstParamByNameGet (pInst, &jumboEnable&, VXB_PARAM_INT32, &val); 这句话的意思是支持大包处理,jumboenable.这个就是参数配置 这个就是参数配置 又如rtl8169VxbEnd.c:中有这么一段 LOCAL VXB_PARAMETERS rtgParamDefaults[] = { {&rxQueue00&, VXB_PARAM_POINTER, {(void *)&rtgRxQueueDefault}}, {&txQueue00&, VXB_PARAM_POINTER, {(void *)&rtgTxQueueDefault}}, {&jumboEnable&, VXB_PARAM_INT32, {(void *)0}}, {NULL, VXB_PARAM_END_OF_LIST, {NULL}} };内存管理系统启动过程中分配内存。 当系统早期启动的过程中,那些最初被初始化的设备驱动是不能使用 malloc,calloc.memPartAlloc() 等函数分配内存的,因为这些方法要使用信号量等 操作。这时,只能使用如下函数分配内存 hwMemAlloc( ) 个字节,并清零。 从一个静态池中分配 N 个字节,并清零。 hwMemFree( ) 将内存分配给静态池。 将内存分配给静态池。 注意 hwMemAlloc( ) 和 hmMemFree()是在系统启动初期分配和释放内存,一旦系统 完成初始化,就可以使用标准的内存分配哈数进行分配。 malloc( ), calloc( ), memPartAlloc( ),这里怎么没有 memalign()18 / 69 硬件访问读写硬件寄存器vxbRead8( )??vxbRead16( )??vxbRead32( )???vxbRead64( ) ??vxbWrite8( ) vxbWrite16( ) vxbWrite32( ) vxbWrite64( ) 使用 vxbus 访问寄存器 访问寄存器的宏定义在下面的路径 installDir/vxWorks-6.x/target/src/hwif/h/vxbus/vxbAccess.h19 / 69 采用 vxbRegMap( ).进行映射/* find the memory mapped window for the device registers */ for (i = 0; i & VXB_MAXBARS; i++) { if (pInst-&regBaseFlags[i] == VXB_REG_MEM) } pDrvCtrl-&feiBar = pInst-&pRegBase[i]; /* store the base address */ vxbRegMap (pInst, i, &pDrvCtrl-&feiHandle); /* map the window */这段程序完成的功能是 首先查找空间,找到 VXB_REG_MEM 时,跳出,将地址 存储到【pDrvCtrl 】中,同时调用函数完成映射,返回句 柄,供继续读写用。中断处理vxbIntConnect( ) vxbIntDisable( ) 同步 任务水平的同步采用信号量(这里说 mux),spinlock,中断锁。中断水 平的同步采用信号量 (mux) 添加 item 到消息队列。 , 当使用后者时, ISR 中 在 使用 msgsend 时,timeout 应该为 zero。 中断水平的同步采用中断锁 intCpulock ,unCpuLock key = intCpuLock (); /* access shared data structures. */ intCpuUnlock (key); 注意 虽然中断锁很简单,很有效,但是现在不怎么使用中断锁了,因为以下20 / 69vxbIntDisconnect( )vxbIntEnable( ) 两个原因 1. 增加了系统开销。 2. 在多个 CPU 或 vxwroks SMP 模式下中断锁不起作用。第3章vxWorks 网络驱动开发 网络驱动开发驱动说明风河早期的驱动采用 legacy driver ,在早期的版即 vxWorks5.x 中使用, 在新的版本中已经不再提供 legacy driver 了,特别是使用 SMP 的用户,风河 强烈建议采用 vxbus 模型的驱动。驱动开发可利用到的资源 驱动开发可利用到的资源 包含网络驱动,总线控制,定时器驱动,串行设备驱动。 installDir/vxWorks-6.x/target/src/hwif/end/templateVxbEnd.c installDir/vxWorks-6.x/target/src/hwif/busCtlr/vxbTemplatePci.c installDir/vxWorks-6.x/target/src/hwif/timer/vxbTemplateTimer.c installDir/vxWorks-6.x/target/src/hwif/sio/vxbTemplateSio.c关于定时器驱动 installDir/vxWorks-6.x/target/src/hwif/sio/vxbTemplateSio.c 这里的驱动采用 vxbus 模型开发,是从 legacy driver 迁移到 vxbus 的。 installDir/vxWorks-6.x/target/src/drv/timer/m8260Timer.c 提供了 PPC8260 的定时器驱动,采用 legacydriver 开发。21 / 69 3.1 驱动类别注意开发驱动对 vxWorks 的 I/O 系统也要有所了解。 通用类别: 通用类别 串行设备。软件提供 open(),write(),ioctl() 调用。串行设备驱动例程存放路径installDir/vxWorks-6.x/target/src/hwif/sio存储设备 管理 ram,tape ram,及其板上的 flash 设备,ATA 盘,串行 ata 盘,scsi 盘,usb flash 盘等。路径:installDir/vxWorks-6.x/target/src/hwif/storage网络接口驱动 MAC 层驱动 installDir/vxWorks-6.x/target/src/hwif/end MAC 驱动与 MUX 相连。 相连。 物理层驱动 installDir/vxWorks-6.x/target/src/hwif/mii PHY 与 MAC 之间由 MII 相连。NVRAM(非易失性 RAM )驱动 installDir/vxWorks-6.x/target/src/hwif/nvram定时器驱动 installDir/vxWorks-6.x/target/src/hwif/timer 定时器驱动的作用 定时器驱动的作用: 1. 告诉 CPU 某事件已经消耗了指定时间 2. 提供加减计数22 / 69 DMA 驱动 installDir/vxWorks-6.x/target/src/hwif/dmaBus Controller Drivers(总线控制器驱动) 为不同的总线之间提供接口 每一个 CPU 在设计的时候都提供了一个与外界相连的接口,称为总线接 口。 一般情况下, 不考虑 CPU 类型, 直接与总线相连, 称为 PLB processor ( localbus)。在某些情况下,需要将不同的总线之间进行桥接,用到 PCE 或 VME. installDir/vxWorks-6.x/target/src/hwif/busCtlr 作用: 总线控制器确定系统当前是那种总线在工作。2.总线控制器负责配 置下行设备,使之能够工作。3.总线控制器负责管理地址映射。USB 驱动 USB 主机设配驱动 installDir/vxWorks-6.x/target/src/hwif/busCtlr/usb/hcd USB 类驱动 installDir/vxWorks-6.x/target/src/drv/usbInterrupt Controller Drivers(中断控制器驱动) (中断控制器驱动) 作用:当设备产生中断时,中断控制器负责将中断传递个处理器,并且保证 其他中断源不再送往 CPU 当其正在处理当前中断时。 installDir/vxWorks-6.x/target/src/hwif/intCtlr Multifunction Drivers Remote Processing Element Drivers installDir/vxWorks-6.x/target/src/hwif/cpu console 驱动 installDir/vxWorks-6.x/target/src/hwif/console Resource Drivers installDir/vxWorks-6.x/target/src/hwif/resource 资源驱动的功能是为外围设备及其配置资源23 / 69 其他类 A/D D/A 要写驱动,首先要知道驱动文件所在位置, 要写驱动,首先要知道驱动文件所在位置,这里有三个路径存放与驱动有关 的文件 installDir/vxWorks-6.x/target/3rdparty VxBus model device drivers written by third party developers that are installed as add-ons to an existing VxWorks installation. installDir/vxWorks-6.x/target/src/hwif Drivers written in compliance with the VxBus device model, distributed and supported by Wind River, and provided as part of a standard product,installation or patch. , installDir/vxWorks-6.x/target/src/drv Wind River legacy drivers (not in VxBus compliance). 这里的驱动是采用 legacy,模型(区别于 vxbus 模型),Legacy 模型用 于驱动开发是应用在 vxworks 早期版本中。驱动源文件 提供某些实体的逻辑实现 Driver source file installDir/vxWorks-6.x/target/src/hwif Third-party drivers are found under: installDir/vxWorks-6.x/target/3rdparty The example in this section discusses the file locations3.2 Vxworks 下网络驱动开发说明:vxworks 下网络驱动开发,是本文档要讲述的重点。 在本章节中,将重点介绍 vxworks 下驱动开发要完成的工作,熟悉驱动开发有 关的源文件及其头文件,根据具体情况进行修改和配置。理解使用 vxbus 开发 模型进行驱动开发的一般流程。 知道在系统初始化过程系统是如何对网络驱动进24 / 69 行初始化的,包括网络驱动的声明,注册等。在本章节中,读者要重点关注与网 络驱动有关的头文件, 源文件 (对于命名中有 end 这样字眼的程序要多加留意) , 可以仔细研读,发现其中的一般性。最后结合风河代码,给出一款网卡驱动的开 最后结合风河代码, 最后结合风河代码 发方法。 发方法vxWorks 网络协议栈与 windows 下 TCP/IP 协议栈相比,vxWorks 增加了 MUX 层。VxWorks 下网络驱动的开发要掌握的基本概念25 / 69 1. 网络驱动包括 MAC 层驱动和 PHY 驱动。 MAC 层和 PHY 层通过 MII 连接。 MII 是 meidia independent interface 的缩写,是一种连接机制。其他媒介 还有 SGMII,GMII ,PLB 等等。可以通过配置 MAC 相关的寄存器实现。 2. Vworks 下网络驱动分为 END 模型驱动和 BSD 模型驱动。 现在比较流行的 还是 END 模型驱动。 3. 写 vxWorks 下 的 驱 动 只 要 实 现 模 板 函 数 完 成 的 功 能 即 可 , 如 endload(),endunload(),endpollsend(),endpollreceive()等。 具体函数看数 据结构 netfun,有需要实现的函数接口。这些接口在系统初始化硬件的过程 中有 mux 层调用实现。驱动开发者只需关心底层的这几个函数实现,无须关 心 mux 层的实现方法。 4. Socket 与 vxWorks 网络驱动的关系 Socket 是在应用层调用。起始在 vxworks 下表现为一种文件。通过 socket 在不同进程之间传递信息。 Socket 的发送接收功能, 说到底最后还是调用底 层的驱动 send,receive 实现。对 vxwroks 网络驱动有一点了解之后,我们来重点学习 END 驱动了解什么是 MUX26 / 69 这个图表明 MUX 在协议栈中的位置,与传统 TCP/IP 协议栈相比,增加了 一层 MUX,是数据链路层与 IP 层之间的接口。 这里的协议层是与传输层及其往上应用层的接口。 与其他TCP/IP 协议相比VxWorks网络协议栈增加一层MUX层。MUX层是 VxWorks为方便在网络接口硬件上实现多种协议而增加的一层 。它主要用于管 理底层的多种硬件的设备驱动,向上层不同协议提供统一的接口,降低了上层协 议与底层物理硬件的藕合,使得网络驱动和上层协议彼此保持独立,既方便在现 有硬件基础上实现新的上层协议,也利于用新的硬件支持原有的上层协议。 MUX与END的交互是通过提供一套可供底层调用接口服务来实现的,实现END 驱动必须遵循这套接口关系。如图所示。MUX 与END 的接口关系27 / 69 图3中右边框中列出的函数是驱动需要实现的函数,供MUX 层调用在必要的时 间调用,如当上层使用该网卡发送数据时,MUX 会调用该网卡END 驱动提供 的Send函数,将数据提交给网卡芯片硬件。缓冲池数据结构网络设备驱动与上层协议进行数据交换需要相应的内存缓冲,并且管理这 些缓冲也需要相应的函数。 VxWorks提供了netBufLib函数库用于创建和管理网络 设备用到的内存缓冲池, 网络设备驱动可以直接使用也可以在此基础上设计自己 特定的内存缓冲池。数据以簇的形式保存,数据结构mBlks(内存块)和clBlks 簇 (簇块)形成的数据链结构则用于指定各个簇。 在clBlk之上是mBlk结构。该结构存储一个到clBlk的连接,也可以存储一个到另 一个mBlk的连接。通过mBlk的连接,可以引用任意数量的数据,如图4所示。 图4 mBlks 和clBlks 的数据结构装载及启动END 设备的系统函数主要用到以下几个: 设备的系统函数主要用到以下几个: 装载及启动 (1).muxDevLoad() 该函数装载指定设备的驱动程序装载函数。如果要装载END 设备,系统必须调 用muxDevLoad()函数。 (2).muxDevStart()启动设备函数 (3).muxBind() muxBind()可以将协议绑定到指定的END 设备上。其调用过程是系统调用 ipAttach()函数, 而该函数调用muxBind()函数, 绑定协议堆栈到MUX 上的一个 指定的网络接口。当一个网络接口被关闭时,ipAttach()函数将释放网络接口所 关联的TCP/IP 堆栈模块。 装载及启动END 设备驱动程序的流程如下: 使用指定的END 设备驱动程序的BSP 引导VxWorks 系统时,在引导过程中, 系统将执行任务tUsrRoot 来完成如下各项:28 / 69 (1)初始化网络任务的工作队列 初始化网络任务的工作队列; 初始化网络任务的工作队列 (2)创建tNetTask 任务来处理网络任务工作队列的条目; (3)调用muxDevLoad()装载指定的网络驱动程序; (4)调用muxDevStart()启动指定的网络驱动程序。 tUsrRoot 任务调用 任务调用MUX 设备装载函数 设备装载函数muxDevLoad()和设备启动函数 和设备启动函数muxDevStart(), , 通过这两个函数来装载和启动设备驱动程序。 muxDevLoad()函数会根据网络设备表endDevTbl[]中的定义逐一调用各网络 设备的装载函数,其中这个函数是muxDevLoad()的一个输入参数。 muxDevStart()函数也会根据endDevTbl[]逐一调用网络设备所定义的设备开始 函数。至此MUX 的初始化以及END 驱动程序的初始化工作已经完成。但是网 络设备还是不可以使用,因为还需要将协议绑定到指定的END 指定的设备上, 这一步需要用muxBind()函数实现。 在VxWorks 中,系统通过usrRoot()函数调用usrNetInit()函数完成MUX 的初始化、装载网络设备表endDevTbl[]中描述的所有设备并将IP 协议绑定到 网络引导设备上等工作。 网络设备驱动程序的安装过程即图5 所示的网络初始化顺序。 图5 网络初始化顺序发送数据在VxWorks 网络系统中,发送数据的流程如图6。 图6 数据发送29 / 69 通过对图6 分析,主要包含以下几个处理。 (1) 用户调用write()函数,通过套接字访问网络。 (2) 网络协议拷贝需要发送的数据到网络缓冲区中,并调用协议驱动程序的发送 程序。 (3) 协议驱动程序调用muxSend()启动发送循环。 (4) muxSend()通过调用send()回调函数,把缓冲区传递给END。 (5) 数据发送程序 把数据拷贝到设备缓冲区中,并把它放置到设备的发送队列 中。 (6) 当产生发送中断时,驱动程序的中断服务程序调度程序丢弃已发送的数据 当产生发送中断时, 包,彻底清理发送队列。 彻底清理发送队列接收数据在VxWorks 网络系统中,接收数据的流程如图7。30 / 69 通过对图7 进行分析,它主要包含以下几个处理。 (1)设备接收到数据包后直接把数据存放到预先分配的簇中。 (2)当接收到中断 接收到中断时,驱动程序的中断服务程序调度任务级接收程序进行如下操 接收到中断 作。 连接;mBlk 和clBlk 连接;最后构成缓冲区。 ①clBlk 结构和簇连接 连接 ②通过调用receiveRtn()函数,把缓冲区传递给更高级别的协议。 (3)muxReceive()调用协议的stackRcvRtn()函数,把成列的缓冲区传递给应用。 用户使用 read()函数,通过套接字访问网络中的成列缓冲区驱动程序的中断处理 中断处理函数fei82557INT()处理设备中断。根据中断状态调用相应的中断 处理程序,如接收终端程序、发送中断程序等。当网络接口产生中断时,系统调 用中断服务程序。为了将中断阻塞减到最小,中断驱动程序只处理那些需要最小 时间的工作, 把其他耗时的任务排列到网络任务的工作队列中。为了排列任务级 为了排列任务级 的包接收处理工作,网络驱动程序中断服务程序必须调用 函数。在 的包接收处理工作,网络驱动程序中断服务程序必须调用netJobAdd()函数 函数 调用netJobAdd()函数时,应当指定任务级处理数据包的驱动程序入口。然后由 netJobAdd()把函数指派到网络系统任务――tNetTask 的工作队列中。 VxWorks 通过tNetTask 处理任务级的网络处理。31 / 69 tNetTask 调用队列中处理程序如下: (1)包接收程序:把接收到的数据包上传到网络缓冲区的堆栈中,通过一个调 用上传给MUX。 (2)释放所有发送帧程序:程序调用netClFree()函数释放发送缓冲区中所有已 经发送的数据帧。协议层执行下列入口点stackShutdownRtn( ) stackError( ) stackRcvRtn( ) stackTxRestartRtn( )Mux 与网络驱动之间的接口 这部分学习可以参考风河代码 MuxLibmux 执行的函数有 muxbind(),muxDevload()等。Mux 相关 API 详解muxDevLoad( ) muxDevStart( ) muxBind( ) muxSend( ) 将设备装载到 MUX 从 MUX 启动设备 绑定协议层到 MUX(hook) 从协议层接收数据包,然后发往设备 获取一个只包含包数据的 mblk, 不包含链路层次的头 部信息(omitted.) muxAddressForm( ) muxIoctl( ) 将包地址放入指定的 buffer. 访问控制函数32 / 69muxDataPacketGet( ) muxMCastAddrAdd( ) muxMCastAddrDel( ) muxMCastAddrGet( ) muxUnbind( ) muxDevStop( )为设备中的表添加一个多播地址 删除一个多播表 获取设备中的多播地址表 断开协议层与 MUX 层的链接 停止设备muxDevUnload( ) muxPacketDataGet( )卸载设备 提起一个 submitted mblk 中的包数据,并将它写入 一个新的 mblkmuxPacketAddrGet( )从一个 submitted mblk 中提取 数据包中的源地址 和目的地址,并将每个地址写入它们自己的 mblk。如 果本地源/目的地址与 END 源/目的地址不同,函数将 吸入足够多的 mblk。If the localsource/destination addresses differ from the end source/destination addresses, this routine writes to as many as four mBlks. 由 stackTxRestartRtn( ) 调用,往底层发送数据包。 接收来自设备的包发往 MUX 关闭与设备有关的所有协议。 添加一个地址解决函数 从列表中获取一个特别的地址解决函数 从列表中删除一个特别的地址解决函数muxTxRestart( ) muxReceive( ) muxShutdown( ) muxAddrResFuncAdd( ) muxAddrResFuncGet( ) muxAddrResFuncDel( )这个图说明了三个层次之间的关系, 对于驱动开发者来说, 只需关心实现 END 的 对于驱动开发者来说, 相关接口即可。 相关接口即可。 注意这里有一个问题, 我们发现在 protocol 层上并没有调用 muxsend 的 注意这里有一个问题, 接口。不是没有, 之外(风河文档说明) 接口。不是没有,而是在标准的 API 之外(风河文档说明)33 / 69 协议层(protocol)的数据结构 end.h 协议层 的数据结构Mux 使用该数据结构存储于协议有关的信息 typedef struct net_protocol { NODE /* How we stay in a list. */ char name[32]; /* String name for this protocol. */ /* Protocol type from RFC 1700 */ /* Is protocol in a promiscuous mode? */ BOOL (*stackRcvRtn) (void *, long, M_BLK_ID, M_BLK_ID, void*); / * The routine to call when we get */ /* a packet. */ STATUS (*stackShutdownRtn) (void*, void*); /* The routine to call to shutdown */ /* the protocol stack. */ STATUS (*stackTxRestartRtn) (void*, void*); /* Callback for restarting on blocked tx. */ void (*stackErrorRtn) (END_OBJ*, END_ERR*, void*); /* Callback for device errors. */ void* pS /* Spare pointer that can be passed to */ /* the protocol. */ } NET_PROTOCOL;接收数据包发往 接收数据包发往协议层 stackRcvRtn( ) 包发void stackRcvRtn ( void* pCookie, long type, M_BLK_ID pNetBuff, LL_HDR_INFO* pLinkHdr, void* pSpare muxBind().*/ ) 返回错误信息 void stackError (34 / 69/* returned by muxBind() call */ /* protocol type from RFC 1700 */ /* packet with link level info */ /* link-level header info structure */ /* a void* the protocol can use to get info */ /* on receive. This was passed to END_OBJ* pEnd, END_ERR* pError, void* pSpare muxBind */ )/* pointer to END_OBJ */ /* pointer to END_ERR */ /* pointer to protocol private data passed intypedef struct end_err { INT32 errC /* error code, see above */ char* pM /* NULL-terminated error message, can be NULL */ void* pS /* pointer to user defined data, can be NULL */ } END_ERR;关闭协议层void stackShutdownRtn ( void* pCookie /* Returned by muxBind() call. */ void* pSpare /* a void* that can be used by the protocol to get */ /* info on receive. This was passed to muxBind().*/ )重新发送void muxTxRestart ( void* pCookie )/* Returned by muxBind() call. */网络层往链路层地址解决STATUS muxAddrResFuncAdd ( long ifType, /* Media interface type from m2Lib.h */ long protocol, /* Protocol type from RFC 1700 */ FUNCPTR addrResFunc /* Function to call. */ ) STATUS muxAddrResFuncDel35 / 69 ( long ifType, long protocol )/* Media interface type from m2Lib.h */ /* Protocol type from RFC 1700 */FUNCPTR muxAddrResFuncGet ( long ifType, long protocol )/* ifType from m2Lib.h */ /* protocol from RFC 1700 */Vxbus 驱动初始化过程 驱动初始化顺序驱动实例理解 1.驱动在 vxwroks 中注册,使用如下数据结构。 驱动在 中注册,使用如下数据结构。 LOCAL struct drvBusFuncs cn3xxxTimerDrvFuncs = { cn3xxxTimerInstInit, cn3xxxTimerInstInit2, cn3xxxTimerInstConnect }; 2.描述驱动支持的方法。 描述驱动支持的方法。 描述驱动支持的方法 /* devInstanceInit */ /* devInstanceInit2 */ /* devConnect */36 / 69 LOCAL struct vxbDeviceMethod cn3xxxTimerDrv_methods[] = { DEVMETHOD(vxbTimerFuncGet, cn3xxxTimerFuncGet), {0,NULL} }; 3.提供驱动注册信息 提供驱动注册信息 LOCAL struct vxbDevRegInfo cn3xxxTimerDrvRegistration = { NULL, /* reserved for VxBus use */ VXB_DEVID_DEVICE, /* devID */ VXB_BUSID_PLB, /* busID = PLB */ VXB_VER_4_0_0, /* vxbVersion */ &cn3xxxTimerDev&, /* drvName */ &cn3xxxTimerDrvFuncs, /* pDrvBusFuncs */ NULL /* pMethods */ NULL /* devProbe */ }; 。Vxwroks 在启动过程中,将驱动与特定的硬件相连。 4.提供驱动在 vxbus 中的注册函数 提供驱动在 void vxbCn3xxxTimerDrvRegister (void) { vxbDevRegister (&cn3xxxTimerDrvRegistration); } 驱动在vxbus注册后,vxwroks使用 驱动配置文件中的相关文件找到vxbus中注册 的驱动函数的入口。特别说明VXBUS 的驱动初始化过程在每一个驱动程序的最前面都可以看到,读者可以 打开 intalldirection\target\src\hwif\ 不管是网络驱动还是其他的串口驱动,都可以首先看到驱动初始化相关的这四个函数。以下是风河文档的截屏37 / 69 38 / 69 这里有一些限制 系统启动时i InstInit( ) 由 sysHwInit( )调用。因为这个时候系统刚刚启动,堆 堆 的初始化还没完成。所以这里不能分配内存等。所以这里只是初步初始化,只能 的初始化还没完成 访问硬件寄存器。 在InstInit2( ) 过程中,系统基本初始化完成,可以调用系统内核中的内核如信 过程中,系统基本初始化完成, 号量,可以使用 在堆中分配内存。 号量,可以使用malloc和free 在堆中分配内存。 和添加vxbus驱动方法 驱动方法 添加 例程39 / 69 初始化的第三个步骤,直到这里才可以连接中 这个 nicinstconnect 是 vxbus 初始化的第三个步骤,直到这里才可以连接中 断。40 / 69 添加 vxbus 驱动之后,要做的就是更新源文件中的名称(name);In general, you can change all other routines toLOCAL.VxWorks 操作系统接口介绍驱动如何是与操作系统接口的,即操作系统如何lauch 驱动,如何把驱 动添加到操作系统中的,如何管理分配内存资源的。41 / 69 通过操作系统中tNetTask任务完成的,6.8开始由tNet0.取代。VxWorks如何 如何lauch 驱动 如何 系统启动后,系统执行任务tUsrRoot,处理以下事情 , 初始化网络工作任务队列。 执行tNetTask,处理网络工作队列上的条目(item)。 调用muxDevLoad() 加载网络驱动,把驱动装载到MUX 层。(之 后有muxload 调用endload) 调用muxDevStart( )启动网络驱动。 注册中断处理程序 在endstart()中调用sysIntConnect( ).。当muxload 驱动时,它 调用muxDevstart(),然后调用endstart()驱动入口点。使用tNetTask 使用驱动操作系统直接使用网络驱动处理进来的包, 驱动操作系统直接使用网络驱动处理进来的包,直接将包分发处理交给应 用网络驱动处理进来的包 用程序, 用程序,This operation is done in the lower half of the OS, from within interrupt context.Therefore, much of the network stack is executed from within interrupt serviceroutines (ISRs). 这个操作经常在低效率的操作系统中 完成,由中断服务函数完成。 但是vxWorks是实时操作系统,ISR 必须短,所以 是实时操作系统, 须短,所以vxWorks没有使用长的 但是 是实时操作系统 没有使用长的 ISR 来处理包。因为这个原因,所有关于协议栈的包的处理,vxWroks都交给 来处理包。因为这个原因,所有关于协议栈的包的处理, 都交给 来处理from with a ISR。 了tNettask来处理 。 中断处理 一旦接受到设备发送过来的中断, vxWorks立即唤醒之前注册的中断服务函 数执行,而且要尽快处理完成。所以这里中断服务函数完成了最基本的事情:错 误/状态改变。 为了给包拒绝任务排队,ISR 必须使用netjobAdd函数。 为了给包拒绝任务排队, 必须使用 函数。 函数42 / 69 使用tNetTask 处理任务层次的网络处理。 STATUS netJobAdd ( FUNCPTR routine, /* routine to add to netTask work queue */ int param1, /* first arg to added routine */ int param2, /* second arg to added routine */ int param3, /* third arg to added routine */ int param4, /* fourth arg to added routine */ int param5 /* fifth arg to added routine */ ) 中断处理往往提供三种功能,写驱动时必须注意 中断处理 1. 处理接收中断。 2. 包发送出去后,将资源还给缓冲池。 3. 处理错误事件。如何添加网络接口驱动到 如何添加网络接口驱动到vxWorks 添加网络接口驱动到 1. 编译并include 代码到vxWorks image (参考workbech 使用方法或者 内核编程)。 2. 创建END 驱动的配置表(endDevTbl[ ]).信息,让MUX 识别END 驱 动, 往表里面添加具体的驱动信息, 配置 configNet.h, 要使用define 包 含某些信息。 3. 系统初始化过程中由usrNetInit( )完成网络设备的初始化,默认情况下 市自动调用的,所以 宏定义中一般包含INCLUDE_NETWORK和 INCLUDE_NET_INIT 4. sysDev.c, 这个函数也要注意, 包含驱动访问寄存器相关定义及其代码。 例如如果创建两种网络设备,一种支持buffer loaning,一种不支持。那 么首先就必须修改configNet.h中相关宏定义/* Parameters for loading the driver supporting buffer loaning. */#define LOAD_FUNC_0 ln7990EndLoad #define LOAD_STRING_0 &0xfffffe0:0xffffffe2:0:1:1& #define BSP_0 NULL /* Parameters for loading the driver NOT43 / 69 supporting buffer loaning. */ #define LOAD_FUNC_1 LOAD_FUNC_0 #define LOAD_STRING_1 &0xffffee0:0xfffffee2:4:1:1& #define BSP_1 NULLEND_LOAD_FUNC 确定驱动的入口点,例如如果你的驱动 ()入口点是 确定驱动的入口点,例如如果你的驱动endLoad()入口点是 驱动的入口点 () fei82557EndLoad( ),,那么在config.h必须做如下配置 必须做如下配置 #define END_LOAD_FUNC END_LOAD_STRING 传递给muxDevLoad 的 初始串参数。注意每一个END 驱动的参数都 不同,在写驱动的时候要仔细检查。 编辑 endTbl表中的信息,确保END 驱动包含到镜像中。表在 表中的信息,确保 驱动包含到镜像中。 表中的信息 configNet.h中。 中 END_TBL_ENTRY { { 0, LOAD_FUNC_0, LOAD_STRING_0, BSP_0, FALSE}, { 1, LOAD_FUNC_1, LOAD_STRING_1, BSP_1, FALSE}, { 0, END_TBL_END, 0, NULL}, }; 注意这里的FALSE 表示入口没有被处理。当系统成功加载了驱动,这里的 FALSE 将被改为TRUE。 最后修改BSP config.h file to define INCLUDE_END. 这将告诉进程包含END 驱动。当新的映像重新启动时,系统调用 MuxDevLoad,完成相关设备的初始化。 endTbl fei82557EndLoad驱动有关的5中结构需要分配内存 与END 驱动有关的 中结构需要分配内存1. 驱动控制结构 END_Driver 2. 接收和发送描述符(与DMA 的操作有关,见文档)44 / 69 3. 相关列表 4. Mblk,clblk 5. Cluster buffers建立使用缓存来处理数据包 mBlks, clBlks, and Cluster Buffers vxWorks 协议栈提供netBufLib,来管理内存,其使用的基本元素是mblk, clblk。Clusters包含mblk和clblk。我们称由mblk和clblk以某种方式相连的结 构称为cluster。netBufLib提供了两个重要函数 提供了两个重要函数 netPoolCreate( ) 创建一个网络池45 / 69 netPoolInit( ). 风河强烈推荐开发者使用前者而非后者。通常的cluster 大小是 大小是64, 128, 256, 512, 。 通常的 。网络的最大传输单元(MTU)是1500字节。如何建立网络驱动池1. Allocate memory for a network buffer configuration structure and add enough space to also hold 8 additional bytes for the pDrvCtrl-&pNetBufCfg-&pName field. if (pDrvCtrl-&pNetBufCfg = (NETBUF_CFG *) memalign (sizeof(long),(sizeof(NETBUF_CFG) +END_NAME_MAX)) == NULL) return (ERROR);46 / 69 bzero(pDrvCtrl-&pNetBufCfg,sizeof(NETBUF_CFG));2. Initialize the pName field.pDrvCtrl-&pNetBufCfg-&pName = (char *)((int)pDrvCtrl-&pNetBufCfg + sizeof(NETBUF_CFG)); sprintf(pDrvCtrl-&pNetBufCfg-&pName,&%s%d&,&fei&, pDrvCtrl-&unit); 3. Set the attributes to be cached, cache-aligned, sharable, and ISR safe. pDrvCtrl-&pNetBufCfg-&attributes = ATTR_AC_SH_ISR; 4. Use a NULL value to set pDomain to kernel. This instructs netPoolCreate( ) to allocate memory accessible in the kernel domain. pDrvCtrl-&pNetBufCfg-&pDomain = NULL; 5. Set the ratio of mBlks to clusters. pDrvCtrl-&pNetBufCfg-&ctrlNumber = pDrvCtrl-&nClusters * 10; 6. Use a NULL value to set the memory partition of mBlks to kernel. pDrvCtrl-&pNetBufCfg-&ctrlPartId = NULL; 7. For now, set extra memory size to zero. pDrvCtrl-&pNetBufCfg-&bMemExtraSize = 0; 8. Set the cluster memory partition to kernel, use NULL. pDrvCtrl-&pNetBufCfg-&bMemPartId = NULL; 9. Allocate memory for the network cluster descriptor. pDrvCtrl-&pNetBufCfg-&pClDescTbl =(NETBUF_CL_DESC *)memalign (sizeof(long), sizeof(NETBUF_CL_DESC)); 10. Initialize the cluster descriptor. pDrvCtrl-&pNetBufCfg-&pClDescTbl-&clSize = CLUSTER_SIZE; pDrvCtrl-&pNetBufCfg-&pClDescTbl-&clNum = pDrvCtrl-&nClusters * 10; pDrvCtrl-&pNetBufCfg-&clDescTblNumEnt = 1;47 / 69 11. Call netPoolCreate( ) with the link pool function table. if ((pDrvCtrl-&endObj.pNetPool = netPoolCreate ((NETBUF_CFG *)pDrvCtrl-&pNetBufCfg, _pLinkPoolFuncTbl)) == NULL) return (ERROR); 12. Free the pDrvCtrl-&pNetBufCfg and pDrvCtrl-&pNetBufCfg-&pCIDescTbl. free (pDrvCtrl-&pNetBufCfg-&pClDescTbl); free (pDrvCtrl-&pNetBufCfg);网络驱动中一种很重要的数据结构END_OBJ typedef struct end_object { NODE DEV_OBJ devO FUNCPTR receiveR BOOL SEM_ID txS struct net_funcs *pFuncT M2_INTERFACETBL mib2T struct ETHER_MULTI *pAddrL int nM LIST BOOL snarfP void* pMemP M2_ID* pMib2T /* root of the device hierarchy */ /* accesses your device’s ctrl struct */ /* routine to call on reception */ /* indicates unit is attached */ /* transmitter semaphore */ /* various flags */ /* function table */ /* MIBII counters */ /* head of the multicast address list */ /* number of elements in the list */ /* protocol node list */ /* is someone snarfing us? */ /* memory cookie used by MUX bufr mgr. */ /* RFC 2233 MIB objects */48 / 69 } END_OBJ;这里这里的flag 很有含义,说明网络的各种参数 很有含义, 这里这里的 IFF_UP IFF_BROADCAST IFF_DEBUG IFF_LOOPBACK IFF_POINTOPOINT IFF_NOTRAILERS IFF_RUNNING IFF_NOARP IFF_PROMISC IFF_ALLMULTI IFF_OACTIVE IFF_SIMPLEX 接口是开启 的 广播地址有效 正在调试 loopback 网络(什么是loopback网络) 接口是点对点网络 该设备避免使用trailers 该设备成功被分配资源 没有地址处理协议 接收所有的数据包 接收所有的广播包 发送过程 该设备不能听到自己的发送 每一层自定义bitIFF_LINK0, IFF_LINK1, IFF_LINK2 IFF_MULTICAST IFF_LOAN IFF_SCAT 支持多播支持缓存loaning 支持scatter-gather设备结构体typedef struct dev_obj { char name[END_NAME_MAX]; char description[END_DESC_MAX]; void* pD } DEV_OBJ49 / 69device name */ /* to support multiple units */ /* text description */ /* pointer back to the device data. */ 该结构告诉MUX 驱动的名字,而且将MUX 指针指向设备控制结构。 pDevice指向驱动内部控制结构。MUX 使用 使用net――funcs 管理驱动入口点typedef struct net_funcs { STATUS (*start) (void*); /* driver’s start func */ STATUS (*stop) (void*); /* driver’s stop func */ STATUS (*unload) (void*); /* driver’s unload func */ int (*ioctl) (void*, int, caddr_t); /* driver’s ioctl func */ STATUS (*send) (void* , M_BLK_ID); /* driver’s send func */ STATUS (*mCastAddrAdd) (void*, char*); /* driver’s mcast add func */ STATUS (*mCastAddrDel) (void*, char*); /* driver’s mcast delete func */ STATUS (*mCastAddrGet) (void*, MULTI_TABLE*); /* driver’s mcast get func */ STATUS (*pollSend) (void*, M_BLK_ID); /* driver’s poll send func */ STATUS (*pollRcv) (void*, M_BLK_ID); /* driver’s poll receive func */ STATUS (*addressForm) (M_BLK_ID, M_BLK_ID, M_BLK_ID); /* driver’s addr formation func */ STATUS (*packetDataGet) (M_BLK_ID, M_BLK_ID); /* driver’s pkt data get func */ STATUS (*addrGet) (M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID); /* driver’s pkt addr get func */ } NET_FUNCS;50 / 69 MUX 使用 以下数据结构跟踪链路层次的头部信息typedef struct llHdrInfo { int destAddrO int destS int srcAddrO int srcS int ctrlAddrO int ctrlS int pktT int dataO } LL_HDR_INFO; /* destination addr offset in mBlk */ /* destination address size */ /* source address offset in mBlk */ /* source address size */ /* control info offset in mBlk */ /* control info size */ /* type of the packet */ /* data offset in the mBlk */Mblk使用mblk在驱动和协议层之间传送数据,在netBufLib.h中定义 中定义 typedef struct mBlk { M_BLK_HDR mBlkH M_PKT_HDR mBlkPktH CL_BLK * pClB } M_BLK; 注意这个结构体中内嵌两个重要的结构体, 详细了解看文档。 如果要将mblk连接成串, 就要给mBlk.mHdr.mNext ormBlk.mBlkHdr.mNextPkt 赋值。 赋值。mBlk.mHdr.mNextPkt t指向 a一个包含包头部的mBlk。 。 mBlkPktHdr这个可以不用管它。 如果不使用netBufLib进行内存管理,这里就需要对Pclblk进行初始化, arg1.arg2…..,(见文档 见文档) 见文档 如果使用nebuflib进行内存管理,无须多管。/* header */ /* pkthdr */ /* pointer to cluster blk */51 / 69 驱动入口点这里是驱动开发者需要重点关注,而且要在驱动程序中实现的部分 而且要在驱动程序中实现的部分。 而且要在驱动程序中实现的部分endLoad( ) 初始化驱动,将驱动装载到MUX 中 初始化驱动,将驱动装载到 endUnload( ) 释放驱动资源 endStart( ) 启动驱动 endStop( ) 停止驱动endSend( ) 发送包给硬件 endIoctl( ) 访问驱动控制函数 往多播地址表中添加一个多播地址 从多播地址表中删除一个多播地址 获取多播地址表 轮询发送 轮询接收 中添加确切的链路级别信息, 往mblk 中添加确切的链路级别信息, 由协议 栈完成,不是驱动开发者的任务。 栈完成,不是驱动开发者的任务。 endPacketDataGet( ) 提取 提取mblk 中的包数据,由协议栈完成。 中的包数据,由协议栈完成。 endPacketAddrGet( ) 提取包地址信息,由协议栈完成。 提取包地址信息,由协议栈完成。endMCastAddrAdd( ) endMCastAddrDel( ) endMCastAddrGet( ) endPollSend( ) endPollReceive( ) endAddressForm( )具体接口实现 具体接口实现 1.驱动加载到 驱动加载到MUX 层 驱动加载到END_OBJ* endLoad (52 / 69 char* initString )/* a string encoded for the device to use for its /* initialization arguments. */系统启动期间,操作系统将调用该函数两次。第一次操作系统将一个指向空串的 指针传递给驱动 驱动负责将设备名称传递给字符串。 针传递给驱动。 第二次调用完成设备和驱 针传递给驱动 动的初始化过程。实现过程与下述函数类似 例程 END_OBJ * templateEndLoad ( char *initString /* parameter string */ ) { DRV_CTRL * pDrvC /* pointer to DRV_CTRL structure */ ... if (initString == NULL) return (NULL); if (initString[0] == 0) 【 这里我多次指针与数组的转化】。 { bcopy ((char *)DEV_NAME, (void *)initString, DEV_NAME_LEN); return (0); } }2.驱动从 驱动从MUX 层卸载 驱动从void endUnload ( void* pCookie /* pointer to device-identifying END_OBJ */ )Endunload 要完成的事件有 1. 确保设备不再产生中断,停止所有的DMA 引擎,关闭中断。 2. 如果驱动使用了看门狗机制,那么删除看门狗 3. 确保所有的描述符已经删除,并且释放了所有的tuples。 4. 释放放松信号量 5. 确保释放了所有的mblk,clblk。53 / 69 6. 释放发送和接收描述符(descriptor)。 7. 调用netPoolRelease( ),确保netbuflib 申请的mblk,clblk全部释放到 netpool. 8. 释放驱动控制数据结构。 释放驱动控制数据结构。 9. 退出卸载函数。3.endIoctl( )STATUS endIoctl ( void* pCookie, int cmd, caddr_t data )驱动控制函数注意提供的接口形式只能是如下面的形式/* pointer to device-identifying END_OBJ */ /* value identifying command */ /* data needed to complete command */如果调用该函数,没有错误,则返回OK,如果有错误,有以下错误 EINVAL 命令不支持或者参数无效ENOTSUP 设备不支持或者已经配置了需要的请求。当媒介表 EIOCGMEDIALIST是空的时候可能发生这种情况。 ENOSPC 缺少可用的buffer,无法执行cmd。Ioctl 命令及其数据类型 命令及其数据类型Cmd EIOCSFLAGS EIOCGFLAGS EIOCSADDR EIOCGADDR EIOCMULTIADD EIOCMULTIDEL EIOCMULTIGET 描述 设置设备标记 获取设备标记 设置设备地址 获取设备地址 添加多播地址 删除多播地址 获取多播地址表54 / 69数据类型 int char* char* char* char* MULTI_TABLE* EIOCPOLLSTART EIOCPOLLSTOP EIOCGPOLLCONF设置设备为轮询模式 设置设备为中断模式 从协议栈配置数据locationNULL NULL END_IFDRVCONFEIOCGPOLLSTATS EIOCGFBUF EIOCGMIB2Return network statistics to the Caller END_IFCOUNTERS* Get minimum first buffer forchaining. int Get the MIB-II counters from thedriver. M2_INTERFACETBL4.endSend( )将数据发送给设备STATUS endSend ( void* pCookie, /* device structure */ M_BLK_ID pMblk, /* data to send */ )5. endStart 启动一个设备 Status endStart( void* pCookie /* pointer to device-identifying END_OBJ structure */ )这个函数中需要有一个指针指向sysIntConnect() 用于注册ISR.6.endStop( ) 停止设备注意这里stop()完成的只是停止该设备,并不是将该设备从MUX 层卸载。 ()完成的只是停止该设备,并不是将该设备从 层卸载。 注意这里 ()完成的只是停止该设备 假设设备已经通过endload()完成到MUX 层的装载。 ()完成到 层的装载。 假设设备已经通过 ()完成到 STATUS endStop (55 / 69 void* pCookie )/* pointer to a device-identifying END_OBJ structure */7.endPollSend( )STATUS endPollSend ( void* pCookie, M_BLK_ID pMblk, )轮询发送/* pointer to device-identifying END_OBJ structure */ /* data to send */使用轮询发送函数,,首先检查设备是否处于轮询模式(由ioctl函数实现 由 函数实现) 函数实现 风河强烈建议 使用轮询发送时 保持一个传送数组 保持一个传送数组(transmit tuple),从驱动池 分配,并且永远可用。 if ((pDrvCtrl-&pTxPollMblk = netTupleGet (pDrvCtrl-&endObj.pNetPool, ETHERMTU + 16 + 4, /* max data portion */ /* size of enet header */ /* FCS */M_DONTWAIT, MT_DATA, FALSE)) == NULL) { pDrvCtrl-&lastError.errCode = END_ERR_NO_BUF; muxError(&pDrvCtrl-&endObj, &pDrvCtrl-&lastError); return ERROR; } 将指针指向tuple’s cluster buffer 将指针指向 pDrvCtrl-&pTxPollBuf = (UCHAR *)pDrvCtrl-&pTxPollMblk-&mBlkHdr.mD使用netMblkToBufCopy()完成数据的拷贝56 / 69 len = netMblkToBufCopy (pMblk, (char *) pDrvCtrl-&pTxPollBuf, NULL7.endPollReceive 轮询接收int endPollReceive ( void* pCookie, M_BLK_ID pMblk )/* device structure */ /* place to return the data */正确返回OK 错误返回EGAIN (如果mblk没有足够大的空间存放接收包, 或者没有空间可用) 。8.endMCastAddAddr 添加多播地址STATUS endMCastAddAddr ( void* pCookie, /* pointer to a device-identifying END_OBJ structure */ char* pAddress /* pointer to address to add */ ) 返回值 OK 或者ERROR ,如果是ERROR ,需要设置errno9.endMCastAddrDel 删除多播地址STATUS endMCastAddrDel ( void* pCookie, char* pAddress ) 为了管理多播地址,vxWorks提供了etherMultiLib /* pointer to a device-identifying END_OBJ structure */ /* pointer to address to delete */10.endMCastAddrGet 获取多播地址STATUS endMCastAddrGet ( void* pCookie,57 / 69 MULTI_TABLE* pMultiTable ) 调用etherMultiLib中的函数获取多播地址表 中的函数获取多播地址表 多播地址表的定义在end.h 多播地址表的定义在 typedef struct { char *pT } MULTI_TABLE; /* length of table in bytes */ /* pointer to entries */ len 指示地址的个数Forming an Address for Packet Transmission: 11.endAddressForm( )M_BLK_ID endAddressForm ( M_BLK_ID pMblk, M_BLK_ID pSrcAddress, M_BLK_ID pDstAddress )/* packet data */ /* source address */ /* destination address */该函数获取目的地址和源地址,然后将信息赋值到Mblk,这个由驱动开发者完 这个由驱动开发者完 库提供的函数完成。 成。然后该功能一个简单的实现由endlib 库提供的函数完成。当将地址添加到 然后该功能一个简单的实现由 mblk中,endAddressForm()能够相应的适配 中 能够相应的适配mBlk.mBlkHdr.mLen , 能够相应的适配 mBlk.mBlkHdr.mData12.endPacketDataGet( ) 获取一个只有数据的 获取一个只有数据的MBLKSTATUS endPacketDataGet ( M_BLK_ID pBuff, LL_HDR_INFO* pLinkHdrInfo )58 / 69/ * packet data and address information */ /* structure to hold link-level info. */ 注意pbuff指向的结构体中同时包含有数据和头部信息 LL_DHR_INFO 是返回的结构体指针。13.endEtherPacketAddrGet( ) 返回包地址信息STATUS endEtherPacketAddrGet ( M_BLK_ID pMblk, M_BLK_ID pSrc, M_BLK_ID pDst, M_BLK_ID pESrc, M_BLK_ID pEDst ) /* pointer to packet */ /* pointer to source address */ /* pointer to destination address */ /* pointer to source address (if any) */ /* pointer to destination address (if any) */网络驱动发送和接收数据概要今天网络接口驱动流行的模型是 DMA 引擎。DMA 只是其中模型的一种, 你也可以使用可编程的 I/O 或其他存储共享技术。 有关 DMA 引擎在 END 驱动中的使用,这里不再赘述,可参考风河文档。发送数据的过程: 发送数据的过程: 协议层调用 muxAddressForm( ).,将合适的头部放入缓存中。然后发送数据 包,协议层调用 muxSend(),该函数中有 muxBind()返回的 cookie 参数及 其 mblk 中的包数据。MUX 将包发送给驱动处理。接收数据的过程: 接收数据的过程: 响应来自网络设备的中断 函数,将包发送 MUX 层。 然后驱动调用muxReceive(),该函数确定包的协议类型((0x800 for IP,59 / 69,vxWorks 执行之前网络驱动注册的中断服务 0x806 for ARP, and so on),然后查找协议表,查找是否有设备注册使用该 协议类型。如果 protocl(我翻译为协议层)处理这个包,那么 mux 将包发往 stackRcvRtn( ),由它进行处理。 ,由它进行处理。 ()与 看下 muxBind()与 stackrcvrtn() 的关系,谁调用谁。 () () 的关系,谁调用谁。 在包被送往一个确定的协议之前, 在包被送往一个确定的协议之前,muxReceive( ) 调用muxPacketDataGet( ) 函 数,将两个mBlks发往协议层。第一个mblk包含链路(link-level)层次头部的信 息,第二个mblk 包含紧跟头部的其他所有信息。 协议层传输重新开始 muxTkSend( )可能返回错误 END_ERR_BLOCK,意识是目前没有足够的资源传 输数据,那么就要重传,同时 mux 调用协议栈函数 RestartRtn( )重传。Protocol Shutdown(协议停止) (协议停止) 当协议使用完接口后调用 muxUnbind( ), 这个函数高速 MUX 层为协议层重新 分配其他内存和 NET_PROTOCOL3.3 VxWorks 网络驱动配置及分析VxWorks 支持两种形式的网络驱动,一种是 BSD 驱动支持通用的 BSD4.4 网 络,API,结构等和大多数 BSD 网络的驱动类似.另一种是 END 网络驱动,是 VxWorks 独有的,根据 VxWorks MUX 接口编程,不过 END 驱动在底层也要转换成 BSD 的形 式.BSD4.4 网络驱动设置. 网络驱动设置网络设备驱动的调用主要在/target/src/config/usrNetwork.c 文件中,下面说明 BSD4.4 驱动在 VxWorks 系统调用. 主要调用过程如下: VxWorks 系 统 执 行 的 第 一 个 任 务 target\config\all\usrConfig.c 文 件 中60 / 69 usrRoot()=======&&target\src\config\usrNetwork.c 文件中的 usrNetInit ( )通过数组表 netIf[]初始化相应的 BSD 网卡驱动. 在 usrNetwork.c 中的调用过程如下: usrNetInit()函数中调用 usrNetIfAttach(): #ifdef INCLUDE_BSD if (!attached) { if ( (usrNetIfAttach (pNetDev, params.unitNum, pBootString) !=OK)) return (ERROR); attached = TRUE; } #endif /*INCLUDE_BSD*/ usrNetIfAttach ()函数中调用数组表 usrNetIfTbl for (pNif = usrNetIfT pNif-&ifName != 0; pNif++) { if (strcmp (buf, pNif-&ifName) == 0) }网络 BSD 驱动数组表 usrNetIfTbl 在文件/target/src/config/usrNetwork.c 中的定义 初始化: ... LOCAL NETIF netIf [] = { /* 下面是定义包含的各种网络驱动 */ #ifdef INCLUDE_DC /* 从 DEC 芯片启动,即系统有 NVRAM 存在,现在已过时*/ /* 网络接口 定义网卡驱动 */ 网络接口,定义网卡驱动{ &dc&, dcattach, (char*)IO_ADRS_DC, INT_VEC_DC, INT_LVL_DC, DC_POOL_ADRS, DC_POOL_SIZE, DC_DATA_WIDTH, DC_RAM_PCI_ADRS, DC_MODE },61 / 69 #endif /* INCLUDE_DC */ #ifdef INCLUDE_FEI /* 如果定义了 INCLUDE_FEI,初始化 Intel 网卡 */ 初始化{ &fei&, feiattach, (char*)FEI_POOL_ADRS, 0, 0, 0, 0}, #endif #ifdef /* INCLUDE_FEI */ INCLUDE_EX /* Excelan 网卡 */{ &ex&, exattach, (char*)IO_ADRS_EX, INT_VEC_EX, INT_LVL_EX, IO_AM_EX_MASTER, IO_AM_EX }, #endif #ifdef /* INCLUDE_EX */ INCLUDE_ENP /* CMC 网卡 */{ &enp&, enpattach, (char*)IO_ADRS_ENP, INT_VEC_ENP, INT_LVL_ENP, IO_AM_ENP }, #endif ... } 设置方法: 从以上可以看出 BSD 网络驱动只需在 BSP 配置文件 config.h 中将网络(#define INCLUDE_NETWORK)BSD 网卡宏定义(#define INCLUDE_xxx)和一些 I/O 参数(一般 不需要)加入,则在文件 usrNetwork.c 中进行相应的初始化. 如 : 在 VxWorks 加 入 支 持 intel 的 网 卡 驱 动 . 在 config.h 中 加 入 &#define INCLUDE_FEI&. /* INCLUDE_ENP */主要网卡定义如下: #define #define #define #define #define #define #define INCLUDE_ENE INCLUDE_ELT INCLUDE_ESMC INCLUDE_FEI INCLUDE_ELC INCLUDE_EEX INCLUDE_EEX32 /* include Eagle/Novell NE2000 interface */ /* include 3COM EtherLink III interface */ /* include SMC 91c9x Ethernet interface */ /* include Intel Ether Express PRO100B PCI */ /* include SMC Elite16 interface */ /* include INTEL EtherExpress interface */ /* include INTEL EtherExpress flash 32 */62 / 69 #define #define #define #define */ #defineINCLUDE_EX INCLUDE_ENP/* include Excelan Ethernet interface */ /* include CMC Ethernet interface*/ /* include backplane net interface */INCLUDE_SM_NETINCLUDE_SM_SEQ_ADDR /* shared memory network auto address setupINCLUDE_EL_3C90X_END /* 3com fast etherLink XL PCI */#define INCLUDE_LN_97X_END /* AMD 79C972 END DRIVER */ ....END 网络驱动设置(这是我们要关注的部分) 网络驱动设置(这是我们要关注的部分)END 网络设备的初始化主要通过定义在文件 configNet.h 中的一个数组表实现. 初始化网络时 muxDevLoad()会按这个表的定义把 end 初始化安装到 VxWorks 系 统. 主要调用过程: VxWorks 系 统 执 行 的 第 一 个 任 务 target\config\all\usrConfig.c 文 件 中 usrRoot()=======&&target\src\config\usrNetwork.c 文件(该文件初始化 TCP/IP)中 usrNetInit(BOOT_LINE_ADRS)(该函数作用是添加 MUX END)========&&pcooki = pCookie = muxDevLoad(pDevTbl-&unit,.....)其中 pDevTbl 在 BSP 网络配置文件 configNet.h 中定义.END_TBL_ENTRY endDevTbl[]={...},该表定义了网络设备的具体 参数. configNet.h 部分定义如下所示 部分定义如下所示: #define DEC_LOAD_FUNC dec21x40EndLoad /* 定义加载网络设备的入口程序 */ #define DEC_BUFF_LOAN 1 /* 网络设备硬件的物理定义数据串,一般 BSP 已经定义,不到必要时,无需更改 */ /* * &devAdrs&:&PCIadrs&:&ivec&:&ilevel&:&numRds&:&numTds&:&memBase&: \ * &memSize&:&userFlags& */# define DEC_LOAD_STRING63 / 69 &0xxx12:0x12:-1:-1:-1:0:0x& IMPORT END_OBJ* DEC_LOAD_FUNC (char*, void*);/* 网络 END 设备表 */END_TBL_ENTRY endDevTbl [] = { 0, DEC_LOAD_FUNC, DEC_LOAD_STRING, DEC_BUFF_LOAN, NULL, FALSE}, { 0, END_TBL_END, NULL, 0, NULL, FALSE}, };设置方法: 设置方法由以上可看出在 VxWorks 添加 END 网络驱动 在 文 件config.h 中 添 加 &#define INCLUDE_NETWORK& 和 &#define中 加 入 驱 动 的 入 口 函 数 &#defineINCLUDE_END&. 在configNet.hENDxxx_LOAD_FUNC xxxxxEndLoad&和一些相关的初始化字符串. 这样就会在生成 BSP 包含 END/MUX,系统网络初始化调用函数 muxDevLoad() 会更据这个表初始化 END 网络.文件 configNet.c 关于 END 驱动初始化的主要内容: #ifdef INCLUDE_END IMPORT int ipAttach (); /* 定义这个表 */IMPORT END_TBL_ENTRY endDevTbl[]; #endif /* INCLUDE_END */ .......... #ifdef INCLUDE_END END_TBL_ENTRY* pDevT END_OBJ* pCookie = NULL; END_OBJ* pE/* END 设备列表 */64 / 69 #endif /* INCLUDE_END */ #if defined(INCLUDE_END) muxMaxBinds = MUX_MAX_BINDS; if (muxLibInit() == ERROR) /* 初始化 MUX 接口 */系统中常见问题 第 4 章 VxWorks 系统中常见问题Bootrom 和 Boot image 的区别bootrom 是指 on-chip bootrom,在 CPU 芯片内部,内嵌有小的 boot 程序 (bootloader),类似于 PC 机主板上的 BIOS 的存储区域。 boot image 不是一回事。 和 VxWorks 文档中的 bootrom 区是指 boot image 存放的位置。 boot image 的作用 是把 VxWorks image 加载到主板。boot image 只初始化很少的硬件系统如串口, 网口等。 为加载 VxWorks image 做准备, VxWorks 系统下载完毕后, 当 boot image 的作用也就完成了。 VxWorks image 含有完整的 VxWorks OS。是真正运行于目 标板上的操作系统。应用程序运行于 VxWorks 系统之上。 boot image 和 VxWorks image 生成在使用 BSP 文件上的区别 区别在于: 在启动顺序中 区别 Bootrom 调用 bootConfig.c,而 VxWorks 调用 usrConfig.c.在 ROM 中 vxWorks 运行的方式65 / 69 (和 bootrom 编译到一起还是单独固化到 ROM 中),在 ROM 中的内存分配? VxWorks 加载到主板运行,分不同的情况: 如果 VxWorks 是压缩的,加载时解压到 RAM 的 RAM_HIGH_ADRS. 如果是 ROM based VxWorks,VxWorks image 的 data 段复制到 RAM 的 LOCAL_LOW_ADRS, text 部分留在 ROM 并在 ROM 中执行。 既不压缩又不 ROM based 的 VxWorks 直接 copy 到 RAM_LOW_ADRS 运行。 中修改系统设置,如增加网卡等, bootrom? 若在 config.h 中修改系统设置,如增加网卡等,是否需要重新烧 bootrom?如 产品呢? 果增加其他 oem 产品呢? 如果主板中有 Boot image 存在则不需要重新烧, FTP 等 download 加载 VxWorks 用 即可。 系统编程中任务级与中断级的通讯如何实现? VxWorks 系统编程中任务级与中断级的通讯如何实现? 中断是由硬件触发,软件的作用只是将中断服务例程(ISP)与中断事件连接起来. 1.使能中断,函数 intEnable(). 2.用 intConnect()登记中断号,和相应的中断例程 ISR. 这样一旦有中断发生,系统自动跳转到相应位置执行 ISR. 怎么得到,如果对开发板有些改动, Bootloader 怎么得到,如果对开发板有些改动,还能使用开发板的 bootloader 起到什么作用? 吗?bootloader 起到什么作用? Bootloader 相当于 PC 机主板上的 BIOS,是最底层的引导软件,初始化主板的基本 设置,为接收外部程序做硬件上的准备.有些 bootloader 已经嵌在 CPU 内了 有些 内了,没 有 bootloader 的 CPU 可 以 在 片 外 的 eeprom 内 做 bootloader, 也 可 以 不 要 bootloader, 直接通过 JTAG 口灌入程序, 开发板改动基本上不会影响 bootloader.VxWorks 应用程序编译下载时常见问题及原因分析66 / 69 环境下编译产生的错误: Tornado 环境下编译产生的错误:标准 C 函数或自己的函数,变量不认识 (undefined symbol),编译失败。 Tornado 支持 c 和 c++ ,文件后缀为.cpp 时编译器会认为是 c++文件,这样有些 定义类型为 C 的函数在编译或下载时不被认可。 解决方法是 1.把如果在 c++文件(.cpp)中调用 c 函数, 应该把这些不被认可的 c 类型函数用语句 extern &C&说明一下为 c 函数。 另外,如果将 c 文件的后缀小写的.c 误写为大写的.C,也会出同样的错误,编 译时不会编译这个文件。环境应用程序下载产生的错误: Tornado 环境应用程序下载产生的错误:函数不认识(undefined symbol),下 载失败。 虽然编译通过,可是下载时依然会有这样的问题,仍然是函数或变量没有定义。 系统不认识,这是出错的原因基本上时没有定义的错误。查找包含函数或变量的 头文件是否加了进去。如果实在找不到定义的话,简单的办法是先把这他们去掉 (当然是没有其他地方用到的情况下)试一试,先 down 下去,能运行后,然后 添加,再继续查找。image,直接烧入 在 ARM 下不用 Boot image,直接烧入 VxWorks image 的过程 有些 ARM CPU 一般分两种运行方式, 一种是 Boot 方式, 一种是 normal 方式。 在 Boot 方式下直接烧写 VxWorks image 到 Flash 这种 VxWorks image 包含有 boot Flash, 的功能(类似 VxWorks.rom 形式),中间那段烧写到 flash 的程序是必须的,第一 次通过串口下载 VxWorks image 到 Dram 是一个简单的过渡, bootloader 控制。 由67 / 69 当烧写完成后,切换 CPU 到 normal 模式,系统启动,开始逐行读 Flash 中的指 令,是由 VxWorks BSP 控制,根据不同的 VxWorks image 定义,执行不同的操作, 例如若 VxWorks 是压缩的,则解压复制到 DRAM 的高位地址,...。 image VxWorks image 和 Boot image 中的两次硬件初始化之间的区别 Boot image 和 VxWorks image 都对硬件进行了初始化。两次硬件初始化的 是不同的。 BootRom 映像主要作用是通过网口或串口下载 VxWorks 系统,所以它只是初 始化很少的硬件系统如串口,网口等来满足下载 VxWorks 的需要,一旦 VxWorks 下载完毕。这些初始化过的硬件的作用也就完成了。 VxWorks 启动后会从新对 几乎所有的硬件设备进行完全的初始化来满足 VxWorks 操作系统运行的需要。系统编程的使用: 汇编语言在 VxWorks 系统编程的使用:汇编语言主要出现在 BSP 文件 romInit.s,sysAlib.s 等, 这些汇编指令是系统初 始化硬件用的,硬件系统 Power up 时硬件特别是内存没有初始化,C 函数库没有 硬件系统 时硬件特别是内存没有初始化,C 装入内存, 语言程序, 位汇编指令,所以只 装入内存,系统此时不支持 C 语言程序,只支持它自己的 32 位汇编指令 能用汇编指令来初始化硬件,为后续的操作系统包括 C 语言支持做准备.在 OS 正 常运行后,就可以用 C 了. Tornado 不支持汇编指令, 汇编在编译连接 BSP,生成 bootrom 或 VxWorks 映像,才被编译.有两种方法: 1.现在可以在 Tornado 环境下生成 bootrom 或建 Bootable 的 project 生成 VxWorks 2.传统的方法,在命令行方式,用 make 编译生成.68 / 69 在 Tornado 下的 downloadable 的 project,application 中不能用汇编. 不过一般汇编很少用. 可以与其他 bsp 文件在 tornado 下作成 bsp 或用命令行 make.VxWorks 下写驱动需注意的问题 1。MMU 对该硬件的地址映射正确 (改 BSP )。 2。 中断向量表该中断的定义位置, 知道相应中断的中断标志位等信息 (改 BSP ) 3。查出中断号及中断级别,硬件中断登记 (INTCONNECT ),及 ISR 4。系统任务协调,保证在该程序执行时,没有其它任务占用 CPU69 / 69
All rights reserved Powered by
copyright &copyright 。文档资料库内容来自网络,如有侵犯请联系客服。}

我要回帖

更多关于 net就业培训班 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信