发信人: gdtyy (gdtyy), 信区: Embedded
标  题: VxWorks在EasyARM2200和SmartARM2200上的移植
发信站: 水木社区 (Mon Jun 25 23:24:21 2007), 站内

**********************************************
* VxWorks在EasyARM2200和SmartARM2200上的移植 *
**********************************************
                          ------ 浅谈《ecos增值包》辅助开发VxWorks BSP
    2007/04/07  asdjf@163.com  www.armecos.com

随着《ecos增值包》用户群的增大,我们决定进一步增加对《ecos增值包》使用者的支
持力度,如果能自行解决版权问题,那么希望下面的文章能对用户您开发VxWorks BSP有帮
助。

目前,EasyARM2200和SmartARM2200开发板已经(增值)支持uCos、uCLinux、ecos、
uITRON(ecos兼容层)、VxWorks等操作系统(Linux和WinCE需要带MMU的芯片);三款TCP/IP完
整协议栈(openBSD、FreeBSD、lwip)、若干BootLoader(redboot、u-boot、bootrom、vivi
、blob等)。有些用户用它快速开发交互式web server,有些用来作为辅助开发工具、有些
用做快速原型验证......其实,《ecos增值包》是一个开发平台,它不仅限于ARM7,也适用
于ARM15、ARM16等未来芯片,因为ecos支持对PowerPC、MIPS、X86、SH等不同体系架构的抽
象,所以,您针对ecos平台开发的软件将很少/不用改动就可以平滑移植到新的体系架构上
,保护您的投资利益。ecos平台的抽象机制(HAL层、设备文件、C++等)确保您将注意力集中
在事物的核心本质上,而不必被细节干扰。例如:您可以针对ecos抽象出的万能中断模型编
程,而不必关心具体CPU的中断体系;只对串口设备文件操作而不管UART寄存器的细节等。
即使您没有很丰富的经验,也能轻松做项目,因为ecos平台将辅助您解决稳定性、效率、功
耗、成本等棘手问题。ecos提供了FS、GUI、TCP/IP等全套功能部件,完全满足您对数据存
储、显示、网络互联、控制等方面的需求,是完整的一揽子解决方案。

从ecos的观点看VxWorks BSP的开发,主要是平台和变种抽象层的移植,即我们要针对
ARM7变种LPC2210和其承载平台EasyARM2200、SmartARM2200进行移植。ecos和VxWorks简直
太象了(仅函数名不同):都使用组件概念(不知是谁抄谁的),都用GNU编译器编译(或diab)
,都实现差不多的功能。这为使用《ecos增值包》开发VxWorks BSP提供了便利。

-----------------------
    | VxWorks BSP移植规划 |
    -----------------------
    1、实现硬件初始化
    2、实现LPC2210中断体系到VxWorks中断体系的映射
    3、实现心跳时钟、辅助时钟、时标
    4、实现基于查询/中断的串口驱动
    ------------------------------------------------MileStone
    5、实现NOR/NAND Flash驱动
    6、实现多种字符设备、块设备、MUX网络设备驱动程序
    7、实现TSFS/dosFS/TrueFFS文件系统、MiniGUI等
    ......

------------
    | 移植难点 |
    ------------
    1、工具使用:Makefile编写、反汇编、调试器使用、Tornado使用等
    2、对LPC2210工作原理、硬件体系的理解
    3、对BSP目录结构、工作流程、内存分布、ROM映像类型的理解等
    4、正确的调试分析方法、完备的调试环境、有效的技术支持

---------------------------------------
    | 《ecos增值包》针对BSP开发的解决方案 |
    ---------------------------------------
    《ecos增值包》本身就提供GNU开发环境,提供step by step的指导,省去了自己搭建
环境的苦恼,可以快速上手。文档中有专门章节讲解Makefile使用,中断体系、串口原理等
等,这对于攻克难点有莫大的帮助。进行嵌入式开发不能光看书,任何书本都不能面面俱到
,而且写出的书,信息量至少损失20%,理解起来又会损失20%,真正做还要再损失至少20%
,所以,比较好的方法是靠“熏”。不断在一个已经搭建好的稳定平台上反复做实验,举一
反三,天长日久,就会不知不觉熏陶出来。很多用户不懂得调试,遇到问题就问别人,其实
首先应该问计算机,掌握调试方法就相当于掌握了打渔的方法,学会了点金术,发现问题,
debug it,trace it,解决问题,It's hacker's solution。

-----------------------
    | VxWorks BSP目录结构 |
    -----------------------
    BSP(板级支持包)就是指VxWorks的驱动程序。当然,其他一些操作系统也有自己的BSP
驱动,还有些系统的驱动程序不叫BSP,总之,这里的BSP就是指驱动程序啦。
    安装VxWorks和其BSP开发环境后,会出现c:/Tornado2.2目录,在target子目录下的内
容就是BSP的相关内容。

------config     BSP配置文件
                      |        |
                      |        |-----all     通用配置文件
                      |        |_____BspName 板级支持包
                      |
              target  |---H         头文件
                      |---Lib       库文件
                      |---Man       说明文件
                      |---Src       VxWorks特殊的源代码
                      |___Unsupport 工具及驱动

我们实际关心的只有target/config/all和target/config/BspName两个目录。
target/config/BspName里面是我们要移植的真正的BSP程序。

-------------------
    | VxWorks工作流程 |
    -------------------
    VxWorks分为bootrom和内核映像两部分,分别由不同文件完成功能。

-------------------------------------------
    bootrom执行流程:
    -------------------------------------------

romInit
    (target/config/zlgarm/romInit.s)
                 |
              romStart
     (target/config/all/bootInit.c)
                 |
              usrInit
    (target/config/all/bootConfig.c)
                 |
            bootCmdLoop
                 |
         -----------------
         |               |
     autoBoot            |_bootLoad
         |_bootLoad      |_go
         |_go

-------------------------------------------
    VxWorks内核映像启动流程图:
    -------------------------------------------
              sysInit
    (target/config/zlgarm/sysALib.s)      硬件相关
                 |                   ----------------
              usrInit                     通用启动过程
    (target/config/zlgarm/sysALib.s)
                 |
         -----------------
         |       |       |
  usrKernelInit  |      sysHwInit
                 |      (target/config/zlgarm/sysLib.c)
             kernelInit
                 |
      Hooks-->usrRoot
                 |
                 |--------
                         |
                    sysClkConnect
                         |
                         |---------
                                  |
                              sysHwInit2

bootrom首先执行硬件初始化romInit,它是用汇编写的,主要考虑到有些操作不能用C
语言完成,例如开关中断,特权堆栈初始化等。然后使用C语言写的程序romStart拷贝搬移
ROM映像,清RAM,解压代码(如果需要的话),这部分用C的好处是编程方便。usrInit是用来
执行最小内核初始化的,然后进入命令循环,分两种情况,如果7秒钟(可设置)内无按键就
自动执行预先烧好的程序,如果没有找到程序,就不断重复7秒等待过程。如果有按键按下
,就进入命令行界面接收用户命令。

VxWorks内核被加载后首先执行硬件相关初始化,这部分初始化工作与bootrom中的相同
。为什么要重复执行相同的硬件初始化呢?主要是考虑到VxWorks可能被其他bootloader加
载,为了保证工作环境一致,所以这里再次重复相同的硬件初始化过程。接下来配置内核数
据、初始化内核、启动usrRoot任务、连接启动时钟心跳,OK,现在系统就活了。虽然
VxWorks一般不开源,但提供很多钩子(Hooks)函数,可以选择适当位置插入用户代码,完成
特殊需求。

-------------------
    | VxWorks内存布局 |
    -------------------
    内存布局是VxWorks移植中需要非常准确理解的内容,它关系到config.h的配置和
Makefile的编写,如果处理不好或者概念搞错了,那就全乱了。

--------------  0x00100000 = LOCAL_MEM_SIZE = sysMemTop()
    |            |
    |    RAM     |
    |  0 filled  |
    |            |
    |------------| = (romInit+ROM_COPY_SIZE) or binArrayStart
    | ROM image  |
    |----------- |  0x00090000  = RAM_HIGH_ADRS
    | STACK_SAVE |
    |------------|
    |            |  0x00080000  = 0.5 Megabytes
    |            |
    |            |
    | 0 filled   |
    |            |
    |            |  0x00001000  = RAM_ADRS & RAM_LOW_ADRS
    |            |
    |            |  exc vectors, bp anchor, exc msg, bootline
    |            |
    |            |
    --------------  0x00000000  = LOCAL_MEM_LOCAL_ADRS

--------------
    |    ROM     |
    |            |  0xff8xxxxx  = binArrayStart
    |            |
    |            |  0xff800008  = ROM_TEXT_ADRS
    --------------  0xff800000  = ROM_BASE_ADRS

上图是一个内存布局实例(1M字节RAM空间),地址值是自己编的,主要看宏定义。
    ROM_BASE_ADRS是指ROM的起始地址,例如:0x80000000。
    ROM_TEXT_ADRS是代码段的起始地址,有些CPU不能从0开始执行,所以需要一个偏移量
,不同CPU的要求不同,一般和ROM_BASE_ADRS值相同。

LOCAL_MEM_LOCAL_ADRS是指可用RAM的起址,如:0x81000000。
    RAM_LOW_ADRS是内核在内存中的加载位置。
    RAM_HIGH_ADRS是需要拷贝到内存的ROM映像和堆栈的分界线,向下是堆栈,向上是ROM
映像的起址。
    未用的部分可以选择清零(用“0”填充)。
    大体上就是这么一个分布,但是限于篇幅,还有很多细节没有谈到。比如:堆栈保护、
解压缩代码空间、不同ROM映像类型的内存分布差异等。这些看代码可以详细了解,还是那
句话,亲自调试就能了解全部细节,写出来的内容总会有信息量的损失,从调试中你能得到
最准确全面的信息。

------------------------
    | VxWorks的ROM映像类型 |
    ------------------------
    VxWorks有三种ROM映像类型:
    1、ROM_RESIDENT-----驻留ROM型。在ROM中运行,只有数据段放在RAM里。
    2、ROM_COPY---------复制ROM型。把主要映像从ROM中拷贝到RAM里并跳到其RAM入口点
执行。
    3、ROM_COMPRESS-----解压ROM型。把主要映像从ROM中解压到RAM里并跳到其RAM入口点
执行。
    各种ROM映像类型的内存布局图如下:

ROM
    --------------
    |            |
    |------------|
    |    data    |
    |------------|  0xff8xxxxx  = ROM_DATA_ADRS
    |    text    |
    |            |  0xff800008  = ROM_TEXT_ADRS
    --------------  0xff800000  = ROM_BASE_ADRS

RAM
    --------------  0x00100000 = LOCAL_MEM_LOCAL_ADRS + LOCAL_MEM_SIZE
    |            |
    |            |
    |------------|        = RAM_DATA_ADRS + data segment size
    |            |
    |data segment|
    |            |
    |------------|  0x00001000  = RAM_DATA_ADRS
    | initial sp |
    |------------|        = RAM_DATA_ADRS - STACK_SAVE
    |            |
    |            |
    --------------  0x00000000  = LOCAL_MEM_LOCAL_ADRS

上图是驻留ROM型映像的内存分布,可见,只有数据段拷贝到了RAM内存里,当然堆栈也
在RAM内存中。

ROM
    --------------
    |            |
    |------------|  0xff8xxxxx    = binArrayEnd
    |  subImage  |
    |------------|  0xff8xxxxx    = binArrayStart
    |    data    |
    |------------|  0xff8xxxxx  = ROM_DATA_ADRS
    |    text    |
    |            |  0xff800008  = ROM_TEXT_ADRS
    --------------  0xff800000  = ROM_BASE_ADRS

RAM
    --------------  0x00100000 = LOCAL_MEM_LOCAL_ADRS + LOCAL_MEM_SIZE
    |            |
    |            |
    |------------|
    | temp data  |
    |------------|  0x00090000  = RAM_DATA_ADRS
    | initial sp |
    |------------|              = RAM_DATA_ADRS - STACK_SAVE
    |            |
    |            |
    |------------|
    |            |
    |  subimage  |
    |            |
    |------------|  0x00001000  = RAM_DST_ADRS (for non-resident images)
    |            |
    |            |
    --------------  0x00000000  = LOCAL_MEM_LOCAL_ADRS

上图是复制ROM型和解压ROM型映像的内存分布,他们比驻留ROM型稍微有点复杂。复制
ROM型和解压ROM型映像的主要差别的是subimage是否压缩,一般压缩率能超过55%,允许在
ROM中烧写更大的系统,唯一的代价是增加了几秒钟的启动延迟,而复制ROM型映像没有解压
过程,所以启动速度更快。subimage是由make产生的中间映像,并被make插在ROM映像文件
中。代码段、初始化数据段、subimage在ROM中的排列顺序就如上图所示。

复制ROM型映像直接把binArrayStart处的subimage拷贝到RAM_DST_ADRS,没有上面的
temp data部分。

对于解压ROM型映像,首先拷贝压缩的代码数据段到RAM_DATA_ADRS位置(即temp data部
分),然后运行解压缩例程把解压后的subimage放置在RAM_DST_ADRS。

RAM_DST_ADRS和RAM_DATA_ADRS宏均来自定义于make的链接地址,缺省值分别为
Makefile文件中的RAM_LOW_ADRS和RAM_HIGH_ADRS。关于如何改变链接地址的信息,参见“
target/h/make/rules.bsp”文件。

---------------
    | BSP移植详述 |
    ---------------
    罗嗦了那么多,终于开始正式移植了。还是前面那句话,写出来的东西总是挂一漏万,
无论我怎么组织语言,总有说不完的话,数不清的注意事项,虽然心里很明白,但如果每一
点都指出来,那会让读者更晕,云里雾里的,没有实际做过,很难理解我说的细节,有些妙
处真的是只可意会不可言传,我也不知道怎么表达出来,并非留一手。我希望帮你“熏”一
下,能帮多少算多少,最重要的是你要亲自实践,光看游泳书是学不会游泳的。

==========
    硬件初始化
    ==========
    硬件初始化直接抄板子自带的汇编初始化源码,改进一下执行效率即可。

======
     中断
    ======
    中断需要提供:初始化、返回向量号、中断使能、中断禁止函数。
    中断初始化真是妙不可言,因为LPC2210提供VIC映射,所以一步就可以得到向量号,不
必查询,所以初始化做得好,中断响应效率可以很高。中断使能只要对
LPC2XXX_VIC_INT_ENABLE寄存器对应位置1即可;中断禁止时对
LPC2XXX_VIC_INT_ENABLE_CLR寄存器对应位置1。

在调试BSP时,运行后总是没有动静,通过内存打印技术,发现程序死在了
excVecInit()函数处。见名知意,这个函数肯定和中断向量初始化有关,但它到底是如何工
作的呢?虽然有源码,但那个是for X86的,对于ARM体系相关的函数部分没有指导意义啊,
怎么办呢?此时,需要祭出战无不胜,攻无不克,见神杀神,见鬼杀鬼的利器---反汇编调
试。

《ecos增值包》提供了GNU开发环境,使用“arm-elf-objdump -d
vxWorks_romResident > 1.txt”就可以得到VxWorks的汇编列表文件1.txt,里面有地址和
汇编信息,可用于和AXD汇编对照调试。

8101a644 <excVecInit>:
8101a644:    e92d4800     stmdb    sp!, {fp, lr}
8101a648:    e24dd008     sub    sp, sp, #8    ; 0x8
8101a64c:    eb002d4e     bl    81025b8c <armInitExceptionModes>
8101a650:    e59fb4d4     ldr    fp, [pc, #1236]    ; 8101ab2c <$d> fp=81301524
 excEnterTbl
8101a654:    e3a01005     mov    r1, #5    ; 0x5
8101a658:    e59f04d0     ldr    r0, [pc, #1232]    ; 8101ab30 <$d+0x4>  r0 =
e59ff0f4
8101a65c:    e24bb008     sub    fp, fp, #8    ; 0x8

8101a660:    e59b3008     ldr    r3, [fp, #8]
8101a664:    e2511001     subs    r1, r1, #1    ; 0x1
8101a668:    e5830000     str    r0, [r3]
8101a66c:    e59bc008     ldr    ip, [fp, #8]
8101a670:    e59b300c     ldr    r3, [fp, #12]
8101a674:    e28bb008     add    fp, fp, #8    ; 0x8
8101a678:    e58c30fc     str    r3, [ip, #252]
8101a67c:    1afffff7     bne    8101a660 <excVecInit+0x1c> 8101a660
8101a680:    e3a0c000     mov    ip, #0    ; 0x0
8101a684:    e59f34a8     ldr    r3, [pc, #1192]    ; 8101ab34 <$d+0x8> r3 =
e7fddefe
8101a688:    e58c3000     str    r3, [ip]
8101a68c:    e59fc4a4     ldr    ip, [pc, #1188]    ; 8101ab38 <$d+0xc> ip =
813087C8
8101a690:    e59cb01c     ldr    fp, [ip, #28]     fp = [813087E4]
8101a694:    e35b0000     cmp    fp, #0    ; 0x0
8101a698:    0a000003     beq    8101a6ac <excVecInit+0x68>  8101a6ac
8101a69c:    e3a00000     mov    r0, #0    ; 0x0
8101a6a0:    e3a0101c     mov    r1, #28    ; 0x1c
8101a6a4:    e1a0e00f     mov    lr, pc
8101a6a8:    e1a0f00b     mov    pc, fp

8101a6ac:    e59f3488     ldr    r3, [pc, #1160]    ; 8101ab3c <$d+0x10>  r3 =
8101a6dc
8101a6b0:    e59fc488     ldr    ip, [pc, #1160]    ; 8101ab40 <$d+0x14>  ip =
813102a4  _func_armIrqHandler
8101a6b4:    e58c3000     str    r3, [ip]
_func_armIrqHandler = 8101a6dc excIntHandle
8101a6b8:    e3a00000     mov    r0, #0    ; 0x0
8101a6bc:    e28dd008     add    sp, sp, #8    ; 0x8
8101a6c0:    e8bd8800     ldmia    sp!, {fp, pc}

8101b494 <intVecBaseSet>:
8101b494:    e1a0f00e     mov    pc, lr

通过反复分析,intVecBaseSet在ARM体系上屁用也没有,是空的,根本不能指望通过它
改变中断向量基址VEC_BASE_ADRS。这段汇编的大概意思是:在0地址开始处填写中断向量表
跳转语句,在100H处写跳转地址,没有中断服务子程序的入口填写0xE59FF9F4(未定义指令
,用于引发异常)。怪不得死机,LPC2210重映射到0地址的RAM空间只有64字节,向100H只读
地址写数据会引发异常(44B0向ROM里写数据不会引发异常,顶多写不进去就是了,看来
LPC2210在地址空间防护上做了一些工作,能识别出向只读空间里写数据的错误。虽然是好
事,但给我们移植BSP带来了困难,怎么办呢?)。VxWorks考虑得真是周到,这部分是用源
码提供的,那就咔嚓了excVecInit(),换成自己的myExcVecInit(),齐活。

VxWorks提供的中断处理函数不能动,因为要使用VxWorks的中断体系,由它来调用我们
提供的处理函数,这样,就把LPC2210的中断体系映射到了VxWorks上。

既然可以替换成自己的代码,那就不用仿照VxWorks向量表原来的构造了,把它推翻,
换个和LPC2210匹配更好的结构。我用LPC2210内部IRAM保存向量表和ISR服务程序入口地址
,因为内部IRAM快,还可节省一些外部XRAM空间,然后把它映射到0地址即可(真是绝配啊!
)。汇编源程序如下:(target/config/zlgarm/sysALib.s)

.globl     FUNC(myExcVecInit)    /* own code for armInitExceptionModes()
---zk */

.extern    FUNC(excEnterUndef)
    .extern    FUNC(excEnterSwi)
    .extern    FUNC(excEnterPrefetchAbort)
    .extern    FUNC(excEnterDataAbort)
    .extern    FUNC(intEnt)

.extern    FUNC(armInitExceptionModes)

.extern    FUNC(_func_armIrqHandler)
    .extern    FUNC(excIntHandle)

_ARM_FUNCTION(myExcVecInit)

stmfd   sp!, {r0-r10,lr}
    bl   FUNC(armInitExceptionModes)

copy_vector:
    adr     r0, real_vectors
    add     r2, r0, #64
    ldr     r1, =0x40000000       /*前面的初始化程序已经把此RAM的前64字节重映射
到了0地址*/
/*add    r1, r1, #0x08*/
vector_copy_loop:
    ldmia   r0!, {r3-r10}
    stmia   r1!, {r3-r10}
    cmp     r0, r2
    ble     vector_copy_loop

/*反汇编的程序在此处判断了一个内存中的变量,但我没找到该变量名,没判断变量是
否为0就直接赋值了。*/
    /*看效果没有任何不良影响。*/
    ldr     r0, L$__func_armIrqHandler
    ldr     r1, L$_excIntHandle
    str     r1, [r0]

nop
    ldmfd   sp!, {r0-r10,pc}

/*************************************************/
/*    interrupt vectors                     */
/*************************************************/
real_vectors:
        ldr     pc,.reset                  //0x00
    ldr     pc,.undefined_instruction  //0x04
    ldr     pc,.software_interrupt     //0x08
    ldr     pc,.prefetch_abort         //0x0C
    ldr     pc,.data_abort             //0x10
    ldr     pc,.not_used               //0x14
    ldr     pc,.irq                    //0x18
    ldr     pc,.fiq                    //0x1C

/*************************************************/

.reset:                 .word     0xE59FF9F4
.undefined_instruction: .word     FUNC(excEnterUndef)
.software_interrupt:    .word     FUNC(excEnterSwi)
.prefetch_abort:        .word     FUNC(excEnterPrefetchAbort)
.data_abort:            .word     FUNC(excEnterDataAbort)
.not_used:              .word     0xE59FF9F4  /* not use */
.irq:                   .word     FUNC(intEnt)
.fiq:                   .word     0xE59FF9F4 /* fiq */

注意噢:子程序要压栈保存所有改变的寄存器(除非明确需要改变,如传参数值,才不
需要保存恢复),不然不要怪我没有提醒你ARM编译器会优化程序,使用寄存器传值,如果你
的子程序内部改变了寄存器值又没有恢复原先的值,那么插入你自编的函数,会发生很多奇
妙的事哦!
    stmfd   sp!, {r0-r10,lr}
    ldmfd   sp!, {r0-r10,pc}

============================
    调试器、内存打印、点灯的异同
    ============================
    这三者都是很好的调试方法,尤其在调试BSP类程序时很有用,此时,串口还没有工作
,但又想看到信息以便进行分析,怎么办?凉拌。
    点灯比较简单,看看灯的亮灭和组合就知道程序现在跑到哪了,适合问题定位。
    内存打印可以表达更多信息,但需要bootloader支持,通过命令行查看内存。
    调试器功能最强,有些支持源码调试,相当方便。打印语句调试是让被调程序牵着鼻子
走,调试器是牵着被调程序鼻子走(可以任意修改走向),想牵谁的鼻子自己决定。
    《ecos增值包》提供的调试环境适合粗调,尽管需要被被调程序牵着鼻子走,配合AXD
调试(不适合粗调,容易陷在细节中,最好先粗调定位问题,再对问题点用调试器细调),还
是很快的。

========
    时钟驱动
    ========
    时钟驱动需要实现:系统时钟和辅助时钟中断、连接、禁止、使能、读、写,时标中断
、连接、禁止、使能、读周期、读频率、读tick值、锁中断读tick值。
    需要注意的是,每次时钟中断ISR处理时都别忘了清时钟中断,不然,CPU一直陷入中断
,就不能做别的事情了。具体代码可以参照其他BSP模板(在target/config/目录下就是各种
ARM板子的BSP移植源码)并结合LPC2210开发板的时钟驱动范例自行写出。

========
    串口驱动
    ========
    VxWorks的串口驱动比较特别,与其他驱动不同。
    VxWorks串口驱动同时支持基于查询和中断的驱动,可以在运行时通过IOCTL配置运行模
式和属性。
    查询方式很简单,这里主要说下基于中断的驱动。

LPC2210的UART收发中断共用同一个中断号,我们在中断服务程序里先收后发,通过状
态寄存器判断是收中断还是发中断亦或是超时、错误中断。

(void) intConnect(INUM_TO_IVEC(devParas[i].vector), zlgarmInt, (int)
&zlgarmChan[i] );
    intEnable(INUM_TO_IVEC(devParas[i].vector));
    把串口中断ISR服务程序挂在相应中断号devParas[i].vector上并使能中断。这样每次
UART中断都会调用zlgarmInt函数。

void zlgarmInt(ZLGARM_CHAN *pChan)
{
    zlgarmIntRcv(pChan);
    zlgarmIntTx(pChan);
}
    在zlgarmInt里先调用收函数,再调用发函数,实现收发操作共用同一个中断号的目的

LOCAL int zlgarmTxStartup
    (
    SIO_CHAN * pSioChan                 /* channel to start */
    )
    {
    ZLGARM_CHAN * pChan = (ZLGARM_CHAN *)pSioChan;
    unsigned int stat;

unsigned char * base = (unsigned char *)pChan->regs;

zlgarmIntTx(pChan);

HAL_READ_UINT8(base+LPC2XXX_UART_IER, stat);
    stat = stat | LPC2XXX_UART_IER_TXE;
    HAL_WRITE_UINT8(base+LPC2XXX_UART_IER, stat);

return (OK);
    }
    每次发送前,VxWorks先调用zlgarmTxStartup激活中断,使后续发送自动化。

void zlgarmIntTx
    (
    ZLGARM_CHAN *    pChan        /* channel generating the interrupt */
    )
    {
    unsigned int stat;
    char     outChar;
    unsigned char * base = (unsigned char *)pChan->regs;

HAL_READ_UINT8(base + LPC2XXX_UART_LSR, stat);
    if((stat & LPC2XXX_UART_STAT_TXE) == 0)
        return;
    if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
        HAL_WRITE_UINT8(base + LPC2XXX_UART_THR, outChar);
    else
        {
        HAL_READ_UINT8(base+LPC2XXX_UART_IER, stat);
        stat = stat & (~LPC2XXX_UART_IER_TXE);
        HAL_WRITE_UINT8(base+LPC2XXX_UART_IER, stat);
        }
    }
    在发送时先判断是否正在发送,如果发送FIFO不为空,那么,肯定正在发送数据,程序
退出,等到发送结束,发送中断会自动调用这个程序再次发送的。如果发送FIFO为空,说明
已发送完毕,此时上层回调函数getTxChar从VxWorks管理的循环队列中取出一个字节数据继
续发送,只要字符在发送状态,发送中断就会消失,一旦发送完毕会再次触发。如果循环队
列中已无字符,一定要记住关闭发送中断使能,不然,由于发送FIFO为空,发送中断总是有
效,CPU会反复陷入发送中断。

void zlgarmIntRcv
    (
    ZLGARM_CHAN *    pChan        /* channel generating the interrupt */
    )
    {
    unsigned int stat;
    unsigned int c;
    unsigned char * base = (unsigned char *)pChan->regs;

HAL_READ_UINT8(base + LPC2XXX_UART_LSR, stat);
    if ((stat & LPC2XXX_UART_STAT_RDR) != 0)
        {
        HAL_READ_UINT8(base+LPC2XXX_UART_RBR, c);
        (*pChan->putRcvChar) (pChan->putRcvArg, c);
        }
    }
    接收中断比较简单,只要判断接收状态即可,调用上层回调函数putRcvChar把收到的字
符存入VxWorks管理的循环队列。

总体感觉VxWorks串口架构设计得非常合理和灵活,获益良多!妙不可言!

=========
    flash驱动
    =========
    略

===========
    MUX网络驱动
    ===========
    略

=====================
    Makefile和onfig.h配置
    =====================
    见《VxWorks内存布局》节

========
    编译方法
    ========
    ---------------
    bootrom编译方法
    ---------------
    拷贝c:/Tornado2.2/host/x86-win32/bin/torVars.bat到
c:/Tornado2.2/target/config/zlgarm目录并改名为zlgarmmake.bat。增加语句,最终内容
如下:

rem Command line build environments
set WIND_HOST_TYPE=x86-win32
set WIND_BASE=C:/Tornado2.2
set PATH=%WIND_BASE%/host/%WIND_HOST_TYPE%/bin;%PATH%

rem Diab Toolchain additions
set DIABLIB=%WIND_BASE%/host/diab
set PATH=%DIABLIB%/WIN32/bin;%PATH%

make clean
make bootrom_res.bin

以后只要双击该文件就可以编译驻留ROM型bootrom映像。

---------------
    vxworks编译方法
    打开Tornado编译器,选择build标签,右键设定default_romResident为激活编译类型
。以后只要点击编译图标即可。
    注意:
        每次修改Makefile和config.h后都要重新生成项目,因为Tornado使用的是上一次
配置的项目,本次修改配置无效。
        注释使用“/* */”,不要使用“//”。

========
    使用方法
    ========
    把bootrom或vxworks程序烧写到flash里,启动后就可以看到logo启动界面。enjoy
it!     ^_^
    有了BSP,就可以专心开发VxWorks应用程序了,只要在生成项目时指定BSP即可。

《ecos增值包》用户(需提供识别码)对VxWorks BSP在EasyARM2200和SmartARM2200上移
植有任何疑问均可来信询问(asdjf@163.com),不提供源码,提供文档支持。
--

※ 来源:·水木社区 http://newsmth.net·[FROM: 61.149.56.*]

VxWorks在EasyARM2200和SmartARM2200上的移植zz相关推荐

  1. RTOS 在 stm32f407 探索者上的移植(一)

    RTOS是什么 先看他们的定义.非实时操作系统指 操作系统无法保证 最高优先级任务开始执行 的最后时限. 软实时操作系统指 操作系统只能保证在xx时间内开始执行最高优先级的用户代码,但无法保证用户软件 ...

  2. 在arm linux mini2440上移植ntp服务,RTEMS 4.9.5 在 QEMU MINI2440 上的移植发布啦……

    (本文原创,转载请注明出处,谢谢) 这两天抽了个空,在rickleaf移植的 qemu mini2440 的rtems 4.9.5 bsp 上做了一些修改: 1.原来mini2440的 bsp是基于 ...

  3. OpenCV在ARM上的移植

    OpenCV在ARM上的移植 与X86 Linux类似,请参考: Linux 下编译安装OpenCV 本文在此基础上进行进一步操作. 网络上很多移植编译的方法比较老,多数针对OpenCV 1.0,而且 ...

  4. u-boot-2009.08在2440上的移植详解(三)

    一.移植环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-b ...

  5. 文件系统应用笔记之一:FatFS在STM32F4上的移植

      在实现如U盘文件读写,SD卡的文件读写等工作时,我们往往需要一个文件系统来支持我们的工作.特别在一些MCU应用中,文件系统的加入能明显改善系统交互的友好性.在这一篇中,我们就来讨论FatFS文件系 ...

  6. uCOS-II在51单片机上的移植

    uCOS-II在51单片机上的移植 约定:文中所写的硬件堆栈或系统堆栈是指51单片机SP指针所指向的堆栈空间,而用户堆栈或任务堆栈是指用来保存任务状态为每个任务分配的堆栈空间. 前一段时间一直在学习U ...

  7. QT4.7.3在dm6446平台上的移植[转]--make[1]: *** [assistant_cs.qm] Error 2

    师兄让我作达芬奇系统下的一个界面程序,听说QT不错,所以几天前就试着把QT移植到dm6446上来.去TI的论坛看了一个在omap3上的移植教程,看起来也不难,于是开始了我的移植过程. 1 首先去htt ...

  8. opus在arm的嵌入式平台上的移植和开发

    最近产品中要用到opus,圣上一声令下,把opus移植到我们平台上,什么?opus?opus是什么?在一脸 茫然中,我这特种兵码农就赤手空拳上战场了. 废话少说,赶紧在网站:https://opus- ...

  9. 基于Domoticz智能家居系统(十三)Domoticz-3.8153在Tiny6410开发板上的移植

    Domoticz-3.8153在Tiny6410开发板上的移植 本文将在友善之臂Tiny6410开发板上移植Domoticz-3.8153,起因是去年在mini2440上移植的3.5877版本编译出来 ...

最新文章

  1. 为什么LeNet5网络倒数第二个全连接层维度为84?
  2. SQL Server 2012 安装杂谈
  3. Android开发工具GenyMotion安装和使用方法
  4. win32格式化错误消息
  5. ccf画图java详细解析_ccfjava答案
  6. python 二维数组 长度_Python创建二维数组的正确姿势
  7. LOAD DATA INFILE句法
  8. Planes, Trains, but not Automobiles-求最小路径覆盖的起点终点
  9. MyEclipse打开闪退
  10. lbp特征提取算法 知乎_图像-LBP特征描述算子-人脸检测
  11. C++入门复习指南,C++Primer读书笔记
  12. APICS与AX的Master Planning(一)--Phantom bill of Material 虚项
  13. MATLAB求二阶隐函数导数,matlab隐函数求导
  14. ios搜索(可实现模糊搜索 支持拼音检索 首字母等)
  15. 云计算给IT产业结构带来的影响 .
  16. Baklib知识库-企业知识库管理平台
  17. uploadify控件 上传图片到百度云存储
  18. 安全合规/法案--31--《数据安全法》原文及解读
  19. 2022年7月22日,记录我的第一篇博客
  20. 用Python ttkbootstrap 带你制作账户注册信息界面

热门文章

  1. martin fowler_注意:Martin Fowler的微服务
  2. 原色更纯彩色更真 创维AIR Q7电视评测
  3. FME在宗地图形拓扑中的应用
  4. 手把手教你GitBook使用
  5. Talent Show 分数规划加背包dp(还不太懂)
  6. Philosophy of life: Love and Time
  7. 错排公式 ——递推与通项公式
  8. 前端HTML涉及概念
  9. ubantu16.04下配置使用DeepDive
  10. 金融风控 特征构造(有点多!!!)