TI Sitara AM335x系统之转载别人的关于uCosII在AM1808上的移植
[复制链接]
这篇文章转载来自德州仪器在线社区写的很好希望对大家有用
uCosII在AM1808上的移植 准备用AM1808做一个轻量级的应用,就想到了uCOS-II操作系统,之前使用过该操作系统都是利用别人移植好的工程,顶多就是做一些简单的修改,这次觉得uCOS-II自己也用过很多了,还没有移植过一回,正好趁此机会深入了解一下。网上找了一个uCOS-II在ATMEL的ARM9上移植的版本,版本号是V2.88。决定就从它开始了。后面称之为uC-SAM9263 使用的硬件开发板是国产的hawk板子,使用串口连接,用sfh_omap-l138.exe烧写程序到NAND Flash中。开发环境使用CCS5。使用StarterWare提供的bootloader程序引导系统,在bootloader中,已经配置好了系统参数,所以ucosII就不用再对系统进行初始化。 第一步:建立工程,File->New->CCS Project,输入工程名,选择器件,再选择一个空的工程。如下图所示: 完成后产生一个空的工程在工程浏览栏,如下图所示: 第二步:根据StarterWare中提供的例子,修改AM1808.cmd文件:如下所示: -stack 0x8000 /* SOFTWARE STACK SIZE */ -heap 0x4000 /* HEAP AREA SIZE */ -e Entry MEMORY { EMIFACS0: o = 0x40000000 l = 0x20000000 /* 512MB SDRAM Data (CS0)*/ EMIFACS2: o = 0x60000000 l = 0x02000000 /* 32MB Async Data (CS2) */ EMIFACS3: o = 0x62000000 l = 0x02000000 /* 32MB Async Data (CS3) */ EMIFACS4: o = 0x64000000 l = 0x02000000 /* 32MB Async Data (CS4) */ EMIFACS5: o = 0x66000000 l = 0x02000000 /* 32MB Async Data (CS5) */ SHRAM: o = 0x80000000 l = 0x00020000 /* 128kB Shared RAM */ DDR_MEM : org = 0xC1080000 len = 0x2F7FFFF /* RAM */ ARMROM: o = 0xFFFD0000 l = 0x00010000 /* 64kB ARM local ROM */ ARMRAM: o = 0xFFFF0000 l = 0x00002000 /* 8kB ARM local RAM */ } SECTIONS { .init : { system_config.lib (.text) } load > 0xC1080000 .text : load > DDR_MEM /* CODE */ .data : load > DDR_MEM .bss : load > DDR_MEM /* GLOBAL & STATIC VARS */ RUN_START(bss_start), RUN_END(bss_end) .binit > DDR_MEM .init_array > DDR_MEM .args > DDR_MEM .neardata > DDR_MEM .fardata > DDR_MEM .rodata > DDR_MEM .const : load > DDR_MEM /* SOFTWARE SYSTEM STACK */ .cinit : load > DDR_MEM /* SOFTWARE SYSTEM STACK */ .stack : load > 0xC3FF7FFC /* SOFTWARE SYSTEM STACK */ } 第三步:建立工程目录 在生产 CCS工程时,就建立了一个文件夹,uSys/Project。删除刚才建立的main.c文件。在此文件夹下建立SoftWare目录,目录下建立App,BSP,HWLib,OS,User文件夹和下级目录。如下图所示:
其中,App是应用程序目录,BSP是板级支持包,主要是配置开发板启动初始化等工作。OS里面有几个文件夹,放操作系统源文件,系统配置文件等。还有一个HWLib,这个目录放置AM1808的硬件库,这是TI提供的StarterWare软件包的一部分,包括工程中用到的启动代码,驱动代码或库文件。 User暂时没有用,准备用来放用户的应用文件。 在App目录中建立App.c;App.h文件,从uC-SAM9263拷贝其它文件到该目录。 在BSP目录中建立两个空文件如图所示。 HWLib目录: 拷贝StarterWare中的system_config.lib utils.lib两个库和drivers,platform,inlcude目录如图所示。当然,也可以不用StarterWare包中的库文件,可以直接复制其中的源文件到工程目录下面,在这上面修改即可,以保证工程的独立性并且不影响StarterWare包源代码。其中drivers目录就是复制源文件。注意,并不是所有文件都要加入工程中,可以参考相应的StarterWare工程,从中提取有用的文件加入工程。 从 uC-SAM9263工程中拷贝操作系统源代码到工作目录,结构如下所示:
第四步:建立应用程序。 在App.c中,建立main函数,并建立一个任务,也可以从其它地方复制过来。 在BSP.C中,做开发板的初始化。由于bootloader已经对硬件做好了配置,这里要做的是在OS启动前,关闭所有中断,OSStart()运行以后,在用户任务中初始化硬件,配置中断,配置一个系统tick时钟。 uCOS-II操作系统需要一个时钟作为系统tick。配置Timer2作为一个64bit的定时器,产生系统tick。注意,Timer2使用的系统时钟是在soc_AM1808.h文件中定义的。 然后配置中断,把用户中断服务程序的函数指针注册到系统的中断向量表。这里调用的函数都是在system_config.lib库中定义的。 在中断服务程序中调用OSTimeTick()函数,这是一个系统服务函数。进行系统定时操作。 第五步:系统移植。 系统移植就是要让uCOS-II操作系统运行与目标CPU上,一般只需改os_cpu.h,os_cpu_c.c,os_cpu_a.asm三个文件,这3个文件和CPU相关。在移植之前,先配置os_cfg.h文件,其实,在系统正常工作之前,可以注销所有不需要的功能,这里先注释掉#define OS_APP_HOOKS_EN 0 一个一个来,首先是OS_CPU_C.C文件,该文件主要是定义一些HOOK函数,这些函数在任务调度前或者创建前被调用,让用户有一个做点什么事的机会。这些函数都有一个宏定义开关来打开或者注销。如果有编译不通过的注销就可以了。还有一个配置任务堆栈的函数OSTaskStkInit(),该函数在任务运行前初始化堆栈,并设置系统模式,可以看到,操作系统运行于SVC模式。 修改os_cpu_a.asm文件,该文件中使用到的函数有 OS_CPU_SR OS_CPU_SR_Save(void); void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); void OSCtxSw(void); void OSIntCtxSw(void); void OSStartHighRdy(void); void OS_CPU_ARM_ExceptIrqHndlr(void); 该文件由uC-SAM9263工程复制过来,由于原先的开发环境是IAR,而现在改为CCS5, IAR使用的是符合ARM汇编标准的编译器,而CCS5使用GNU编译器,两个编译器的汇编伪代码定义不一样。首先要处理伪代码符合GNU汇编标准。这一部分参考GNU标准和系统提供的例程。 OS_CPU_SR_Save和 OS_CPU_SR_Restore函数提供系统进入临界代码的保护,当os_cpu.h文件中OS_CRITICAL_METHOD定义为3时,使用这两个文件保存CPSR寄存器到一个临时变量。 #if OS_CRITICAL_METHOD == 3 /* See OS_CPU_A.ASM */ OS_CPU_SR OS_CPU_SR_Save(void); void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); #endif 这两个文件不需要修改 OSStartHighRdy函数功能是跳转到最高优先级任务,该函数在启动时只运行一次,首先调用一个hook函数,然后修改OSRunning变量为1,标识系统进入运行状态,再切换到最高优先级任务,最高优先级任务堆栈已经在OS_CPU_C.C文件中的OSTaskStkInit()函数定义,任务堆栈指针是任务控制块OS_TCB的第一个变量:OS_STK *OSTCBStkPtr; 该堆栈组织形式如下: 高地址 PC LR R12 R11 . . R0 低地址 CPSR 首先要明白一个概念,一般的ARM编译器使用的堆栈是满递减堆栈,即堆栈的基指针在高地址,向低地址生长,栈顶指针指向最后一个压栈地址。通过STMFD和LDMFD指令压栈和出栈时,如:LDMFD SP!, {R0-R12, LR, PC}^ ,寄存器列表可包含16个可见寄存器(R0~R15)的任意集合或全部,列表中寄存器的次序是不重要的,不影响存取的次序和指令执行后寄存器中的值,有一个约定,总是把编号低的寄存器对应于存储器的低地址。也就是说,编号最低的寄存器保存到堆栈的最低地址或从最低地址取出。 在这个出栈指令中,最后的^号,表示出栈时同时要用SPSR恢复CPSR。 OSStartHighRdy跳转到用户任务,用户任务是一个死循环,永远不会再返回到这里了。这也就是当用户任务有返回时,系统会死机的原因。 OSCtxSw函数负责任务切换,首先保存当前任务堆栈,然后把任务堆栈指针赋值给任务控制块第一个变量OSTCBStkPtr。 调用一个HOOK函数,最后取出最高优先级任务控制块的第一个变量,即任务堆栈指针,把它赋值给SP,用这个SP恢复最高优先级任务。 OSIntCtxSw函数是中断中的任务切换,由OSIntExit函数调用,而_OSIntExit函数在中断退出到任务时被调用。 OSIntCtxSw函数和OSCtxSw的基本功能是相同的,都是任务切换,但是前者不保存任务堆栈,因为该堆栈在中断处理时已经被保存过了,它只需要做后面的任务切换工作即可。 OS_CPU_ARM_ExceptIrqHndlr函数处理: 该函数是系统IRQ中断的唯一入口函数,当ARM系统发生IRQ中断时,PC指针就会跳转到该函数,在这里处理中断。 我们知道,AM1808CPU处理中断是通过内存中的中断向量表进行散转的,系统直接把中断服务程序函数指针送到HIPVR2寄存器,执行效率比较高。但是操作系统的中断服务程序需要统一处理,比如任务堆栈的入栈出栈,中断嵌套,中断退出的任务切换等。所以要在system_config工程中修改ARM中断向量表,在startup.c文件中修改如下: static unsigned int const vecTbl[14]= { 0xE59FF018, 0xE59FF018, 0xE59FF018, 0xE59FF018, 0xE59FF014, 0xE24FF008, 0xE59FF010, 0xE59FF010, (unsigned int)Entry, (unsigned int)UndefInstHandler, (unsigned int)SWIHandler, (unsigned int)AbortHandler, //(unsigned int)IRQHandler, (unsigned int)OS_CPU_ARM_ExceptIrqHndlr, (unsigned int)FIQHandler }; 然后重新编译,把编译好的lib文件复制到工程中HWLib目录。 中断服务程序 OS_CPU_ARM_ExceptIrqHndlr 首先切换到SVC模式下,保存任务堆栈,然后根据OSIntNesting的值,判断是否中断嵌套,如果没有嵌套,表示该中断是打断了一个任务,就执行OS_CPU_ARM_IRQHndlr_BreakTask函数,反之执行OS_CPU_ARM_IRQHndlr_BreakIRQ函数。 OS_CPU_ARM_IRQHndlr_BreakTask函数: 首先保存当前堆栈指针到当前任务控制块的第一个变量,然后把异常堆栈指针给SP.再通过HIPVR2调用中断服务程序,返回后恢复各个模式的堆栈,调用OSIntExit函数,检查是否切换任务,退出中断。 OS_CPU_ARM_IRQHndlr_BreakIRQ函数: 处理中断嵌套情况,首先把当前SP存储到异常堆栈中,然后通过HIPVR2调用中断服务程序。返回后直接对OSIntNESTING减一,并不调用OSIntExit函数。退出中断。 IRQ中断服务程序要修改的是ARM和GNU格式的转换,在中断跳转时读取HIPVR2寄存器的值,然后据此跳转。其它地方不用修改。 第六步:编译,除错。其中的错误大多数都是找不到定义,Project->Properties中,Build->ARM Compiler->Include Options。在页面中添加include路径:"../SoftWare/HWLib/include/armv5/am1808" "../SoftWare/HWLib/include/armv5" "../SoftWare/HWLib/include" "../SoftWare/HWLib/include/hw" "../SoftWare/HWLib" "../SoftWare/OS/Ports/ARM" "../SoftWare/OS/Source" "../SoftWare/OS/uC-CPU/ARM" "../SoftWare/OS/uC-CPU" "../SoftWare/App" "../SoftWare/BSP" "../SoftWare/User" 在ARM Linker->File SearchPath页面中,在包含库文件一栏中添加库文件 "utils.lib" "system_config.lib" 在搜索路径一栏中,添加路径 "../SoftWare/OS/uC-CPU/ARM" "../SoftWare/HWLib/include" "../SoftWare/HWLib" 注意的是,Debug和Release选项都必须配置一次。 移植成功!
|