跳至主要内容

【转】VxWorks入门

1.VxWorks开发方式:交叉开发,即将开发分为主机(host)和目标机(target)两部分。
类似于dos下C语言程序的开发。
合并开发的优点:简单
缺点:资源消耗量大,CPU支持,非标准体系的支持
host (Tornado) target(vxWork) 小程序模块
vxWorks实际采用开发模式
Tornado提供:编辑,编译,调试,性能分析工具,是vxWorks的开发工具
vxWorks:面向对象可以剪裁的实际运行操作系统
2.vxWorks启动方式
<1>Rom方式 (vxWork_rom)
vxWorks直接烧入rom
<2>Rom引导方式(bootrom+vxWorks)
其中bootrom烧入rom,vxWorks可以通过从串口,网口,硬盘,flash等下载!这里的bootrom不是开发环境中的bootable,在开发环境里bootable指的是vxWorks,downloadable指application
3.调试
<1>attachs/20060907_164540_564.rar
用来在多任务调试时将调试对象绑定到某个任务
<2>任务级调试(attachs/20060907_164540_564.rar taskName)
单个任务的调试不会影响到其他任务的运行,主要用来调用户的应用程序。
全局断点:在调另一任务或本任务时,系统运行本任务断点,则停下。各任务要配合使用。
任务断点:调本任务时,系统运行到本任务断点,则停下。如果没有attachs/20060907_164540_564.rar到本任务,不起作用。
一次性断点:跑到一次之后自动删除。
<3>系统级调试(attachs/20060907_164540_564.rar system)
把所有task和系统core、中断看成一个整体,可用于调试系统和中断。对中断调试,如果不是系统级调试,无论是那种断点都不起作用
!wdbAgent不在调试范围内,当任务级调试时工作在中断方式,系统级调试工作在轮询方式。
!可是使用命令行方式的调试,参看crossWind教程。
4.调度
优先级调度(无条件)
时间片:同优先级,如果时间片没有打开,任务采取先到先运行,运行完毕在交出cpu,如果打开,则轮流使用cpu。
!死循环使比它优先级低的任务都不能运行。
5.任务间通讯
信号量,全局变量,管道,signal,message queue,socket
信号量:分互斥、同步(二进制)、计数三种。其中互斥用于资源管理,禁止多任务同时共享内存。它的优势是:速度快;同一任务如果已经take到,再次take还会成功。
!全局变量一定要有信号量保护。
Message queue:封装了全局变量和信号量,优势是:快;有很多操作项(send多recv少:消息可以排队,用priority_urgent选项加到队列头。send少recv多:取的时候支持fifo和优先级,即有消息到达时给高优先级任务还是先被recv阻塞的任务)
signal:紧急通信机制,仅次于中断,依赖于系统调度,不依赖时间片(中断依赖于硬件时间),因此signal又称为软中断。
!exeption:内部中断,属于硬中断(例如除法出错)。它与signal的关系如下图:
taskA taskB 软中断处理 signal taskC taskB User's tasks exception signal 软中断处理 Exception中断处理历程1. 查TCB(task control block),得到正在执行的任务信息 2. 如果注册了这个signal,则挂起任务 3. 打印exception号,pc指针,reg值 4.如果注册了这个signal,给任务发signal
6.内存分配
在config.h中由宏定义指定。
user_reserved mem (保存热启动时 的一些参数) System Memory pool Wdb poll vxWorks Memory的最终布局 LOCAL_MEM_LOCAL_ADRSRAM_LOW_ADRS FREE_RAM_ADRS WDB_POOL_SIZE sysMemTop() sysPhyMemTop() Bootrom {romInit() romStart()}Bootrom {usrInit() usrRoot()} VxWorks ROM RAM ROM_SIZEROM_BASE_SIZEROM_TEXT_ADRSRAM_HIGH_ADRSRAM_LOW_ADRS启动时的ROM和RAM布局
!bootrom中的内存驱动在config/scr/drv/mem下,直接include *.c就可以使用其中的函数。对于flash必须在config.h中加上类型的定义,换flash芯片在flash***.h中修改控制字等宏定义。
7.中断
中断分三层含义:
中断引脚号(或从中断控制器得到)(interrupt level) ***_LEVEL
中断号(interrupt number) INT_VEC_GET(***_LEVEL)
中断向量(对x86是中断号*4)(interrupt vector) INUM_TO_IVEC(INT_VEC_GET(***_LEVEL)
!中断处理程序和中断向量必须connect再enable后才能被激活,对x86使用sysIntEnablePIC(),对MIPS,ARM,PPC等使用intEnable()。
!中断中不能含有会使中断阻塞的函数接口。(例如printf就不行,使用logMsg)
8.Timer
vxWorks使用3个timer,分别用于系统时钟,辅助时钟和时标。
Timer0:用于系统时钟(system clock),可用sysClkRateSet()改变速率,默认值时60次/秒。
!vxWorks下的watchdog基于timer0,因为是在interrupt尺度,使用必须谨慎,否则会降低系统效率。
Timer1:用于辅助时钟(auxiliary clock),在bsp.h中定义了最大速率,最小速率和实际速率初始值。可用sysAuxClkRateSet()改变速度。用sysAuxClkConnect()定义辅助时钟的定时任务。
Timer2:用于时标(timestamp)。从系统开始运行时就一直递增,可以用来获得系统运行时间,在windview工具中被使用。用户程序也可以通过sysTimestamp()得到运行时间。
9.*.o,*.out,vxWorks
一个板子跑起来之后可以有多个*.o和*.out(类似于window下的应用程序)和有且仅有一个的vxWorks(类似于window操作系统),但这些*.o和*.out的编译必须和vxWorks基于同一种cpu。
!bootrom在启动时被部分复制到ram里在运行,这一部分将下载vxWorks到ram,然

后跳转到vxWorks入口处运行,然后vxWorks将这一部分的bootrom重新划分到系统池。
10.符号表(symbol table)
符号表就是一个数组,定义了函数和全局变量跟他们的地址的对应关系,默认情况下符号表放在主机上,如果定义了standalone symbol table,则目标机上也有一份符号表,一般与target shell绑定使用。
11.一些配置
pci的配置默认使用自动配置,如果要手工配置,必须定义pci configuration
键盘和显示器的驱动归入串口部分,默认输入输出是显示器和键盘,可以重定向到串口。
12.使用watchdog产生周期性调用例程
主程序:watchdog(func,param,tick)
被watchdog调用的程序:func(param)
{
watchdog(func,param,tick);
……
}
13.任务切换速度:us量级,Cache关闭时上升到10us量级。
例如对于x86,233Mhz,cache打开,中断响应典型值3.5us。其中c function挂接0.7us,中断推出+task重调度2.5us
14.tornado文件结构
用户主要需要目录:
tornado/host:tcl控制语句、主机上运行的exe
tornado/docs:帮助文件,其中的books.html提供总览
tornado/target:头文件,库文件,bsp
修改bsp主要修改target目录下的文件,bsp的修改影响到bootrom和vxworks两部分,下面介绍的是使用工程方法建立的bootrom和vxWorks.
15.bootrom的启动顺序和源码位置
函数: romInit romStart usrRoot CMDLoop
文件:
其中bootInit.c和bootConfig.c会用到sysLib.c中的一些函数,这些函数使一些通用接口,它们调用scr/config(简称S/C)下的usr***.c和scr/drv/(简称DD)下的一些程序。
DD下面的就是device driver,它们的链接方式有两种:
<1>被bootConfig.c和sysLib.c等直接#include
<2>目录下自带makefile,用cmd命令在目录下键入make,函数进入系统库
usr***.c:配合宏使用的链结方式,直接#include
!如果修改含有makefile文件的目录下的*.c文件,必须重新make,否则系统库没有更新。
!特殊修改推荐将文件拷到bsp目录下,加入工程或者#include
!如果设备供应商只提供*a或*.o而不提供源码,那么在makefile中加入LIB_EXTRA=**.a

或MACH_EXTRA=**.o。*.o是无条件链接,而*.a库是有条件链接,只有在用到了库中的函数接口时,才会被链接。
16.vxWorks启动顺序和源码位置
函数: sysInit usrInit usrRoot usrAppInit
文件:
prjConfig.c引用usr***.c,目录是target/config/comps/src(简称C/S,!不是bootrom调用的同名函数)
图形界面下的初始配置来自bsp的config.h和makefile,在工程建立的时候系统会自动完成此工作,编译使系统会根据图形界面下的配置自动生成prjparam.h和prjComps.h来保存选中的组件和配置参数。此后配置的改动将通过prjConfig.c和这两个.h文件反映,再修改config.h不会对vxWorks的生成起作用。对上面三个文件的手工修改也会被系统自动覆盖。系统同时还在usrProj下自动生成makefile,同样不能通过对文件的直接修改达到更新目的。
17.vxWorks的数据分类
Text 常数
Data 函数体外部被初始化了的变量(包括只能在本文件内使用的LOCAL型变量)
Bss 函数体外部没有被初始化的变量,拷贝vxWorks使不需要被拷贝,系统划出一定空间后统一置为零。
Stack 函数体内变量,包括root_stack(启动时需要的堆栈)、isr_stack(中断堆栈)和任务堆栈,前面两个可以在工程下定义,后面一个在发起任务时由程序指定,来源于系统池。
Pool 系统池,由malloc取用
TCB Task Control Block,任务参量
18.编译
Tornado采用gnu make作为编译工具,编译时必须注意以下三个地方保持一致:cpu起始地址,源码编译时的起始地址,相关搬运算法使用的地址。也就是说要注意makefile和config.h中下面宏定义的一致性:RAM_HIGH_ADRS,RAM_LOW_ADRS,ROM_TEXT_ADRS,ROM_SIZE
19.编译技巧
z 在build property�/c++ complier中加上-S,就可以生成.s而不是.o文件,在.s文件中可以清楚地看到data段,text段等。
z 加上-Dmacro=XXX,编译系统就会定义这个宏。
z 使用ar �crusv 可以将.o加入.a,例如:arppc �crusv lib文件位置 *.o
z 使用ar �t [>text.txt] 可以列出库文件里面包含的.o模块,并重定义输出到text.txt
z nm用来生成符号表,例如:nmppc -�numeric�sort vxWorks用来按地址排列vxWorks的符号表
21.修改MMU
如果使用MMU,必须修改sysLib.c中的全局MMU映射表:PHYS_MEM_DESC sysPhysMemDesc,内容为: {{地址1,地址2(= = 地址1),长度,屏蔽,读写权限及cache允许或禁止}, ……}
!当RAM同时被两段或两段以上的总线操作(例如有cpu2,dsp,pci设备等),则不能设为cacheAble,否则会因为cache使ram不能及时更新而出错。否则,在cpu发数据到pci设备时,先写再flush;pci设备发数据到cpu时,先invalidateCache()的相应部分,然后再写。
!pci设备必须加入MMU映射表。
22.从串口下载vxWorks需要的修改
在config.h中加入:
#undef INCLUDE_TSFS_BOOT /*tsfs启动*/
#define INCLUDE_TSFS_BOOT
#undef TTY_CONSOLE
#define TTY_CONSLE 0 /*重定向输入输出到串口0*/
#undef WDB_TTY_CHANNEL
#define WDB_TTY_CHANNEL 1 /*调试串口为串口1*/
#undef WDB_TTY_RATE
#define WDB_TTY_RATE 57600 /*串口波特率*/
bootline设置为:
"tsfs (0,0)chengjy:/tgtsvr/vxWorks h=202.38.78.76 e=202.38.78.189 u=test189 pw=test"
23.PCI网卡的初始化
<1>sysHwInit中对PCI初始化,sysHwInit2中打开中断
<2>confignet.h中的endDevTbl的初始化,定义***_LOAD_FUNC
<3>提供源码或.o方式的驱动
24.定时轮询的实现方法
<1> for(;;){do…;taskDelay(10)};
<2>watchdog
<3>auxClock
25.驱动的三层模式
以串口为例:底层是与硬件直接相关的驱动(ppc860sio.h),中间层提供从硬件相关到硬件无关的函数封装(sysSerial.c),最后在sysLib.c中提供上层要调用的初始化函数(就是在sysHwInit()中调用sysSerial.c中封装好的sysSerialHwInit())。
在实际的启动流程中通过ttyDevCreate()打开文件"/tyCo",之后就可以通过文件系统的open,read,write来对串口操作了。
26.tornado的使用
参见《tornado2_0的安装使用流程.doc》及《windview使用》

评论

此博客中的热门博文

【转】cs8900网卡的移植至基于linux2.6内核的s3c2410平台

cs8900网卡的移植至基于linux2.6内核的s3c2410平台(转) 2008-03-11 20:58 硬件环境:SBC-2410X开发板(CPU:S3C2410X) 内核版本:2.6.11.1 运行环境:Debian2.6.8 交叉编译环境:gcc-3.3.4-glibc-2.3.3 第一部分 网卡CS8900A驱动程序的移植 一、从网上将Linux内核源代码下载到本机上,并将其解压: #tar jxf linux-2.6.11.1.tar.bz2 二、打开内核顶层目录中的Makefile文件,这个文件中需要修改的内容包括以下两个方面。 (1)指定目标平台。 移植前:         ARCH?= $(SUBARCH) 移植后: ARCH            :=arm (2)指定交叉编译器。 移植前: CROSS_COMPILE ?= 移植后: CROSS_COMPILE   :=/opt/crosstool/arm-s3c2410-linux-gnu/gcc-3.3.4-glibc-2.3.3/bin/arm-s3c2410-linux-gnu- 注:这里假设编译器就放在本机的那个目录下。 三、添加驱动程序源代码,这涉及到以下几个方面。(1)、从网上下载了cs8900.c和cs8900.h两个针对2.6.7的内核的驱动程序源代码,将其放在drivers/net/arm/目录下面。 #cp cs8900.c ./drivers/net/arm/ #cp cs8900.h ./drivers/net/arm/ 并在cs8900_probe()函数中,memset (&priv,0,sizeof (cs8900_t));函数之后添加如下两条语句: __raw_writel(0x2211d110,S3C2410_BWSCON); __raw_writel(0x1f7c,S3C2410_BANKCON3); 注:其原因在"第二部分"解释。 (2)、修改drivers/net/arm/目录下的Kconfig文件,在最后添加如...

【转】嵌入式开发中使用DDD进行调试

 在嵌入式程序开发过程中,程序员要进行大量的调试,以此验证程序的正确性,修改潜在的错误。调试器对于程序员来说是不可或缺的必备工具。在Linux环境中,有很多调试工具和调试辅助工具,例如GDB、XXGDB、RHIDE、XWPE、GVD和DDD等。其中,DDD是命令行调试器的图形前端,除了一般的程序调试功能以外,还具有交互式图形数据显示的功能。它在嵌入式应用开发中也十分出色。本文主要讲述DDD(Data Display Debugger)的使用方法。      1.认识DDD     GNU DDD是命令行调试程序,如GDB、DBX、WDB、Ladebug、JDB、XDB、Perl Debugger或Python Debugger的可视化图形前端。它特有的图形数据显示功能(Graphical Data Display)可以把数据结构按照图形的方式显示出来。DDD最初源于1990年Andreas Zeller编写的VSL结构化语言,后来经过一些程序员的努力,演化成今天的模样。DDD的功能非常强大,可以调试用C\C++、Ada、 Fortran、Pascal、Modula-2和Modula-3编写的程序;可以超文本方式浏览源代码;能够进行断点设置、回溯调试和历史纪录编辑;具有程序在终端运行的仿真窗口,并在远程主机上进行调试的能力;图形数据显示功能(Graphical Data Display)是创建该调试器的初衷之一,能够显示各种数据结构之间的关系,并将数据结构以图形化形式显示;具有GDB/DBX/XDB的命令行界面,包括完全的文本编辑、历史纪录、搜寻引擎。     DDD是开源软件,用户可以去 http://www.cs.tubs.de/softech/ddd/ 下载.rpm格式的DDD源码文件。      图1显示的是DDD的主窗口。它主要由选单栏、工具条、数据窗口、源文件窗口、机器码窗口、控制台和命令工具窗口等几部分组成。其中,数据窗口用于观察复杂的数据结构,在删除数据之后,显示仍然有效;源文件窗口显示源代码、断点和当前执行到达的位置,选择该窗口中的"Display"项,可以显示任意表达式的值;机...

【转】函数指针和指针函数

【函数指针】        在程序运行中,函数代码是程序的算法指令部分,它们和数组一样也占用存储空间,都有相应的地址。可以使用指针变量指向数组的首地址,也可以使用指针变量指向函数代码的首地址,指向函数代码首地址的指针变量称为函数指针。 1.函数指针定义 函数类型 (*指针变量名)(形参列表); "函数类型"说明函数的返回类型,由于"()"的优先级高于"*",所以指针变量名外的括号必不可少,后面的"形参列表"表示指针变量指向的函数所带的参数列表。 例如: int (*f)(int x); double (*ptr)(double x); 在定义函数指针时请注意:     函数指针和它指向的函数的参数个数和类型都应该是―致的; 函数指针的类型和函数的返回值类型也必须是一致的。 2.函数指针的赋值 函数名和数组名一样代表了函数代码的首地址,因此在赋值时,直接将函数指针指向函数名就行了。 例如, int func(int x);   /* 声明一个函数 */ int (*f) (int x);    /* 声明一个函数指针 */ f=func;            /* 将func函数的首地址赋给指针f */ 赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。 3.通过函数指针调用函数 函数指针是通过函数名及有关参数进行调用的。 与其他指针变量相类似,如果指针变量pi是指向某整型变量i的指针,则*p等于它所指的变量i;如果pf是指向某浮点型变量f的指针,则*pf就等价于它所指的变量f。同样地,*f是指向函数func(x)的指针,则*f就代表它所指向的函数func。所以在执行了f=func;之后,(*f)和func代表同一函数。 由于函数指针指向存储区中的某个函数,因此可以通过函数指针调用相应的函数。现在我们就讨论如何用函数指针调用函数,它应执行下面三步: 首先,要说明函数指针变量。 例如:int (*f)...