ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

VxWorks BSP开发实战:基于ARM9的启动流程与调试技巧

VxWorks BSP开发实战:基于ARM9的启动流程与调试技巧 简介这是一份面向嵌入式底层开发者的VxWorks基于ARM9S3C2410X的BSP资源包适用于需要完成BSP移植、驱动调试或学习板级支持包构建的工程师与学生也可作为嵌入式系统课程设计和毕业设计的参考资料。包内共37个文件主要包括C源码、H头文件、汇编启动文件、目标文件、配置文件、Makefile及README说明整体约1000KB结构上覆盖了串口、中断控制器、定时器、CS8900A网卡驱动等关键模块。已有188人学习下载说明该包在同类资源中具备一定参考价值。通过阅读源码和配置可以梳理从ROM启动、系统时钟初始化到设备驱动注册的完整流程理解S3C2410X内存布局与中断映射以及驱动编写和调试方法包内包含编译链接所需的Makefile与目标文件便于直接进行交叉编译和烧写测试为二次开发和问题排查提供可对照的实例。 干这行的都清楚VxWorks的BSPBoard Support Package板级支持包开发看着不复杂但真上手弄过基于ARM9的BSP才算把嵌入式底层这块骨头啃明白。很多刚接触VxWorks的朋友手里拿一块ARM9开发板比如经典的S3C2440装个Tornado或者Workbench第一反应是“我直接从网上找个BSP下来改改不就行了”——实际做完你就会发现BSP不只是“启动代码驱动”那么简单它决定了一个实时操作系统能不能在你的硬件平台上稳定跑起来。这篇文章我就拿ARM9平台为主线带大家把VxWorks的BSP开发完整走一遍从整体架构、启动流程、核心文件到实操中的下载调试和避坑经验一次讲透。无论你是学校课程项目要做BSP实验还是工作中接手了一块新板子需要移植VxWorks这篇内容都能给你一个可参考的完整思路。1. BSP整体设计与思路拆解1.1 BSP到底是什么为什么不能随便改改就用BSP的全称是Board Support Package它的作用是在VxWorks内核和具体硬件之间搭一座桥。说得直白点VxWorks内核并不知道你用的CPU是ARM9还是PowerPC它只管任务调度、消息队列、信号量这些东西。而BSP负责把“抽象的VxWorks”变成“你板子上能跑的VxWorks”。很多人有个误解觉得BSP就是把启动代码加驱动文件配置一下就行。但实际BSP要完成的事情很多CPU初始化关中断、设置异常向量表、内存映射MMU/TLB配置、时钟和定时器初始化、串口驱动用于调试输出、中断控制器初始化、总线设备枚举以及把VxWorks镜像从Flash加载到内存并跳转执行。任何一个环节出问题系统都起不来而且调试难度很大因为这时候还没有操作系统帮你打日志。ARM9和X86平台最大的区别在于ARM9的存储结构是统一编址的外设寄存器通过地址访问没有独立的I/O空间。所以BSP里大量工作就是对着芯片手册查寄存器地址然后正确配置它们。以S3C2440为例它内部有GPIO、UART、DMA、中断控制器、定时器等模块每个模块都有各自的基地址和寄存器偏移BSP要做的事情就是把这些寄存器配置成VxWorks期望的状态。1.2 为什么选择ARM9作为BSP开发的学习平台虽然现在Cortex-A系列处理器已经很普及但ARM9依然是学习BSP开发非常好的平台。原因有三点第一ARM9架构没有像Cortex-A那么复杂的GIC通用中断控制器中断管理相对简单适合理解中断处理的本质第二ARM9的MMU和Cache机制比Cortex-A简单配置起来容易调通第三大量的ARM9开发板如S3C2440、AT91RM9200都有公开的BSP源码和参考资料遇到问题好排查。ARM9中的典型代表S3C2440主频400MHz有独立的16KB指令Cache和16KB数据Cache支持MMU跑VxWorks完全够用。而且S3C2440的启动方式支持NOR Flash启动和NAND Flash启动两种方式这对理解BSP中镜像加载逻辑非常有帮助。2. 核心文件解析与配置要点2.1 VxWorks BSP的目录结构和关键文件拿到一个VxWorks BSP你会看到一整套文件看上去很杂但实际上可以分成几类第一类是启动代码典型文件是romInit.s和romStart.c。romInit.s是汇编写的它是CPU复位后执行的第一段代码负责最基本的初始化设置CPU模式、关闭中断、初始化堆栈指针。romStart.c是C语言入口负责把镜像从Flash拷贝到RAM并跳转到usrInit。这一段是整个BSP中最关键的部分因为它涉及代码重定位和内存初始化。第二类是系统初始化文件典型是sysLib.c、sysHwInit.c、sysHwInit2.c。sysLib.c主要是提供sysPhysMemDesc[]这样的内存映射描述表告诉VxWorks内核你的板子物理内存如何映射到虚拟地址空间。sysHwInit.c负责初始化各个硬件设备的中断、寄存器状态它是VxWorks启动早期调用的这个时候中断还是关闭的。第三类是配置文件最重要的是config.h。这个文件里有大量宏定义比如DEFAULT_BOOT_LINE默认启动参数、RAM_HIGH_ADRS和RAM_LOW_ADRS内存地址布局、INCLUDE_MMU是否使能MMU等。改BSP有七成的时间是在改这个文件。还有一类是Makefile它控制整个BSP的编译链接过程。VxWorks的Makefile继承了Wind River提供的一套规则框架一般不需要从头写但需要根据你的板子修改一些变量。2.2 config.h中那些绕不开的关键配置项config.h是整个BSP配置的核心它同时作用于bootrom和vxWorks镜像。我第一次做ARM9的BSP配置时最容易搞混的就是几个内存地址相关的宏RAM_LOW_ADRS表示VxWorks内核镜像在RAM中的加载地址RAM_HIGH_ADRS表示系统内存堆的最高地址这两个值直接决定了VxWorks能不能正确在RAM中解压缩和运行。对于S3C2440这种通常有64MB SDRAM的板子常见设置是RAM_LOW_ADRS 0x30000000 0x1000RAM_HIGH_ADRS 0x30000000 0x04000000。另外一个容易出错的地方是DEFAULT_BOOT_LINE。这一行字符串指定了启动设备、启动文件、主机IP、目标机IP等信息。比如tffs0(0,0)host:/vxWorks h192.168.1.10 e192.168.1.11 utarget pwtarget oae如果在没有网络环境的情况下调试可以用串口下载或者直接从Flash启动配置方式就完全不同。建议刚开始调试时先把启动参数配成从Flash加载避免网络问题干扰判断。2.3 中断控制器和定时器ARM9 BSP最容易翻车的地方ARM9平台的BSP中中断控制器和定时器的初始化是排查问题周期最长的部分没有之一。S3C2440的中断控制器支持60多个中断源分成了两个子中断组。BSP的sysHwInit2中你需要先关掉所有中断然后逐个注册ISR再在sysHwIntEnable中使能对应的中断源。VxWorks对中断处理的方式是所有的中断都会先进入一个统一的入口——intEnt然后由VxWorks内核分发到注册的handler。所以BSP需要提供intEnt的地址给内核这个是通过INCLUDE_INT_CONTROL和相关的宏配置的。定时器也容易踩坑。VxWorks的系统时钟system clock和辅助时钟auxiliary clock在ARM9平台通常使用不同的硬件定时器。系统时钟用的是PWM定时器0辅助时钟用的是定时器3或4。如果系统时钟没有配置好VxWorks的tick不会跳动表现出来就是taskDelay永远不返回任务调度看起来像卡死了一样。3. 实操过程从零配置ARM9的VxWorks BSP3.1 环境准备与工具链选择做VxWorks BSP开发第一个决策是选择开发环境。老牌的选择是Tornado 2.2它支持VxWorks 5.5对ARM9的支持比较成熟缺点是运行在Windows XP这种老系统上。新一代的是Workbench 3.0支持VxWorks 6.x界面更现代但配置复杂度也更高。我的经验是如果只是学习BSP原理用Tornado 2.2 VxWorks 5.5 ARM9的经典组合是最省心的因为这个组合的资料非常多踩坑之后容易搜到解决方案。工具链方面Tornado自带了ARM交叉编译器arm-elf-gcc等不需要额外安装。除此之外你还需要一个调试终端工具。串口调试用SecureCRT或者Putty都可以关键是波特率要和BSP中配置的一致S3C2440平台常见的是115200bps。3.2 建立BSP工程与编译流程在Tornado中新建BSP工程一般选择“Create a bootable VxWorks image”类型的工程然后选择从已有的BSP模板复制一份出来。如果你用的开发板没有现成的BSP就找一个最接近的模板复制然后逐步修改。我常用的方法是先把工程建好用默认配置编译一遍确保最小系统能跑起来再逐个添加组件每加一个就编译、下载、测试一次。千万别一次性把所有驱动和组件都勾选上出了问题你根本不知道是哪个环节导致的。编译之前要重点检查Makefile中的CPU类型和工具链前缀。对于ARM9CPU应该设为ARMARCH5或者ARMARCH4取决于具体内核。S3C2440是ARM920T对应ARMARCH5。如果CPU类型配错编译出来的镜像在启动早期就会崩溃而且往往没有任何输出。3.3 启动流程的逐步验证新板子BSP调试最核心的事情是验证启动流程的每一步。我习惯按照以下顺序来验证第一步验证romInit.s能跑通。下载bootrom到Flash上电后看串口有没有输出。哪怕是最简单的“Uncompressing...”也算成功一半了。如果完全没有输出先查串口寄存器配置再看时钟初始化是否正确。第二步验证romStart.c的拷镜像流程。这里往往会遇到两个问题一个是源地址和目的地址配置不对导致拷贝后程序跑飞另一个是解压缩算法不匹配导致跳转后崩溃。第三步验证usrInit和usrRoot。在VxWorks的启动流程中usrInit会调用sysHwInit来初始化硬件然后创建usrRoot根任务。这个阶段如果出现问题可以通过在usrInit中添加printf来定位到具体卡在哪个函数。虽然这种方法比较土但在系统还没有完整起来之前printf是最可靠的工具。第四步验证定时器tick是否正常。启动完成后在shell里执行“i”命令查看任务列表同时观察系统时钟是否在跳动。如果时钟不跳动重点检查定时器0的寄存器配置和中断是否已经使能。3.4 内存映射与MMU配置实战ARM9平台开启MMU之后VxWorks访问外设就需要依赖sysPhysMemDesc[]中的映射关系。S3C2440的内存布局中SDRAM位于0x30000000开始的地址区间各种外设寄存器起始地址各不相同GPIO在0x56000000UART在0x50000000中断控制器在0x4A000000。sysPhysMemDesc[]的典型写法是把整个物理地址空间映射到相同的虚拟地址空间也就是恒等映射。对于S3C2440可以这样配置PHYS_MEM_DESC sysPhysMemDesc[] { {0x00000000, 0x00000000, 0x10000000, VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE}, {0x30000000, 0x30000000, 0x04000000, VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE}, {0x48000000, 0x48000000, 0x28000000, VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE}, {0x56000000, 0x56000000, 0x01000000, VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE}, };这里面有一个很重要的细节SDRAM映射为Cacheable可以提升性能但外设寄存器所在的内存区域一定不能设置为Cacheable。如果把外设寄存器映射成Cacheable你会遇到一个很诡异的问题往串口发送寄存器写数据第一次写不出去要写第二次才能发出来。原因是第一次写入的数据停留在Cache里没有被立刻写回外设。3.5 串口驱动的实现细节串口是BSP调试的生命线几乎所有早期调试都靠串口输出。S3C2440的UART控制器有三个通道BSP中至少要实现uart16750或者类似的串口驱动接口并且要支持VxWorks标准的sysSerialTtyConnect。串口初始化需要配置波特率、数据位、停止位、校验位。S3C2440的波特率设置比较特殊它需要通过一个除法器寄存器UART_BRDIV来计算计算公式是UBRDIV (PCLK / (波特率 * 16)) - 1如果主时钟PCLK是50MHz波特率116200实际是115200笔误正确的是115200那UBRDIV大概是26。算错这个值串口会输出乱码。我之前就遇到过串口输出全是一堆“#%”这样的乱码排查半天发现是PCLK频率算错了——实际PCLK是66MHz而不是50MHz重新计算之后乱码就消失了。4. 常见问题与排查技巧实录4.1 系统启动无任何输出的排查思路这是BSP调试中最常见的问题也是让人最头疼的问题。我总结了一个排查顺序先看电源和复位用示波器量一下复位引脚有没有正常拉高再看时钟ARM9通常需要外部晶振提供时钟源检查晶振是否起振PLL锁相环配置是否正确然后看串口接线S3C2440的TXD/RXD是否交叉连接正确最后才是看代码。代码层面的排查重点是romInit.s。因为bootrom是烧在NOR Flash里面的CPU复位后从0x00000000地址取指令。你需要确认这条路径上有没有被MMU干预。虽然在romInit阶段MMU通常还没有开启但如果代码里错误地提前使能了MMU就会导致PC跑飞无任何输出。一个非常实用的技巧是在romInit.s的关键步骤之间添加板载LED的翻转代码用示波器看LED引脚的电平变化来定位卡死位置。这比猜代码快得多。4.2 vxWorks镜像加载后崩溃的定位方法有时候bootrom已经正常跑起来了引导信息也打印出来了但解压完vxWorks镜像跳转执行之后就崩溃。这种问题往往涉及内存地址的匹配问题。首先检查config.h中RAM_LOW_ADRS的配置是否和链接脚本一致。如果在Tornado的工程设置中vxWorks镜像的链接地址是0x30100000而实际镜像被加载到了0x30000000跳转之后第一条指令就会访问错误地址导致异常。其次检查镜像是否完整。可以通过对比Flash中镜像的大小和config.h中配置的RAM大小来判断如果镜像超过了实际RAM大小那么加载过程中末尾的数据会丢失运行到后期必然崩溃。还有一个容易被忽视的问题是栈溢出。VxWorks的启动阶段从romInit到usrInit使用的是临时栈栈的大小在romInit.s中定义。如果栈设置太小函数调用层级一旦加深就会溢出表现为启动到某一步突然死机。解决方法是在usrInit之前把栈加大或者先跳到一个简单的C函数中测试栈是否够用。4.3 任务创建不起来或任务调度异常的排查系统能起来但用户任务创建后就崩溃或者任务调度异常这类问题通常和定时器、中断优先级配置有关。先检查系统时钟中断号是否注册正确。S3C2440的PWM定时器0中断号是INT_TIMER0通常为10如果注册成了INT_TIMER1中断永远不会触发系统tick就不会跳动。再检查中断优先级配置。S3C2440的中断控制器支持优先级仲裁如果系统时钟中断和串口中断的优先级配置不当可能出现在高负载情况下定时器中断一直被串口中断打断造成系统时间漂移。最后检查任务栈大小。VxWorks中每个任务都有独立的栈如果自定义任务的栈设置太小任务运行到深层函数调用时会栈溢出。ARM9平台可以开启栈溢出检测功能在config.h中定义INCLUDE_STACK_CHECK这样栈溢出时会打印警告信息便于定位问题。4.4 网络不通时的配置检查清单网络是VxWorks调试中另一个高频问题来源。如果目标机连不上主机从以下三个方面排查第一确认网络接口驱动已加载。在shell中执行ifconfig命令查看网络接口是否存在。如果没有网络接口检查config.h中是否包含了INCLUDE_END以及END驱动是否正确绑定了网络控制器芯片比如DM9000或CS8900。第二确认IP地址配置正确。通过DEFAULT_BOOT_LINE或nvRam中的参数来设置目标机IP。注意目标机和主机的IP必须在同一网段而且不能有地址冲突。第三确认物理层连接正常。ARM9平台常用的网络接口芯片有些需要EEPROM来存储MAC地址如果EEPROM中的数据有问题网络接口虽然能初始化但收不到数据包。调试时可以先用tftp命令测试目标机向主机发起传输看看能否双向通信。5. 实操心得与经验总结5.1 一个完整的BSP开发流程复盘把ARM9平台的VxWorks BSP从头做一遍整个流程可以归纳为六个阶段环境准备、模板复制、最小系统调试、硬件设备驱动、网络功能验证、系统集成测试。最忌讳的就是跳步——还没验证串口输出就急着调网络出了问题永远不知道是底层问题还是上层问题。我在实际项目中通常按70%的工作量花在调试上30%花在编码上来规划。其中调试的70%里面又有超过一半的时间是在做“起点验证”——确认某个功能从最基础的寄存器配置开始就是正确的。做BSP开发学会“反向推理”很重要如果串口没输出不一定是串口驱动的问题可能是系统时钟没起来导致CPU根本没有执行到串口初始化代码如果网络不通不一定是网卡驱动的问题可能是内存映射导致DMA缓冲区地址出错。从一个现象推理到可能的多个原因再逐一验证排除这种思路是BSP调试的核心能力。5.2 常见工程管理经验版本管理要尽早做。BSP代码涉及大量配置改动一个config.h的改动可能导致行为完全变化。每完成一个阶段的调试就提交一次代码写清楚改动内容和验证结果。这样后续如果改出问题可以快速回退。对于团队协作的场景必须统一工具的版本。Tornado 2.2和Workbench生成的BSP工程结构不同交叉编译器版本也不同混用会导致代码风格和编译选项不一致。建议整个团队使用相同的开发环境包括补丁版本也要统一。日志规范要从第一天就建立起来。BSP的调试信息应该分级管理基本的启动日志、详细的初始化日志、调试用的寄存器读写日志。在sysHwInit阶段用串口直接输出在系统运行后用logMsg输出到shell。合理的日志设计能让问题排查效率提升一倍以上。5.3 最后再分享一个调BSP的实用技巧提一个很多文档不会细说的小技巧在调试ARM9的BSP时善用看门狗。S3C2440内置了看门狗定时器它不仅可以防止系统卡死还能在调试阶段作为定位工具使用。比如你怀疑某段代码执行时间过长可以在代码块前开启看门狗设置一个较短的超时时间如果这段代码卡住了看门狗就会复位系统通过复位原因寄存器来判断是不是这里导致的。这个方法尤其适合定位那种“系统跑着跑着突然重启”的隐蔽问题。当然正常发布的时候记得把看门狗关掉不然后续维护的人会以为系统不稳定实际上是你留了个定时炸弹在那里。本文还有配套的精品资源点击获取
返回列表