UCOSII系统移植详解
一,移植UCOSII操作系统的CPU前提条件
1,处理器的C编译器能产生可重入型的代码,如果不行的话,那么就不能在任务之间随意的切换,因为当你切换到别的任务的时候,该任务在这个函数的数据就会被破坏。
2,处理器CPU支持中断,并能产生定时中断
3,用C语言就可以开关中断,进行任务切换
4,处理器CPU能够支持一定数量的数据存储硬件堆栈,也就是栈
5,处理器有将堆栈指针以及其他的CPU的寄存器的内容读出,并存储到堆栈或者内存中去的指令。任务切换的时候,需要将当前的CPU指针保存到刚刚执行的任务当中。然后切换到优先级更高的任务当中。
二,UCOSII实际移植的文件:
UCOSII的移植实例就是要求用户编写4个简单的汇编语言函数,如果编译器支持插入行汇编代码就可以将所有的与处理器相关的代码放置到OS_CPU_C.c里面种,就不需要适用汇编文件。
(1)OSStartHighRdy(); //使得最高优先级的任务运行的函数
OSStart()函数调用OSStartHighRdy()来使得就绪太任务中最高优先级的任务开始运行
void OSStartHighRdy()
{调用用户定义的OSTaskSwHook();OSRunning = TRUE;//得到将要恢复运行的任务的堆栈指针。stack pointer = OSTcbHighRdy->OSTCBStkPtr;//从新的堆栈中恢复处理器的所有的寄存器,就是把刚刚切换的堆栈保存到别的地方当中//执行中断返回,然后跳转PC指针到别的地方中去。
}
(2)OSCtxSw(); 任务级的切换是通过执行软中断指令,或者依据处理器的不同,执行TPAP陷阱指令执行的。中断服务子程序,陷阱或者异常处理的向量的地址必须指向OSCtxSw();
//任务的切换的函数:
void OSCtxSw()
{保存处理器寄存器;在当前的任务的任务控制块中保存当前任务的堆栈指针;OSTCBCur->OSTCBStkPtr = stack pointer;OSTaskSwHook();OSTCBCur = OSTCBHighRdy;OSPrioCur = OSPrioHighRdy;//得到将要重新开始运行的任务的堆栈指针:stack pointer = OSTCBHighRdy->OSTCBstkPtr;//从新的任务堆栈中恢复所有的寄存器的值;//执行中断返回的指令。
}
(3)OSIntCtxSw();
void OSTickISR(void)
{//保存处理器的寄存器//调用OSIntEnter或者直接给OSIntNesting加1if(OSIntNesting ==1){OSTCBCur->OSTCBStkPtr = Stack Pointer;}//给产生中断的设备清中断//重新允许中断OSTimeTick(); //硬件的产生中断的原理OSIntExit(); //中断退出//恢复处理器寄存器//执行中断返回指令
}
(4)OSTickISR();
void OSintCtxSw(void)
{//调整堆栈指针OSintExit();OSINTCtxSw();
}
移植UCOSII,大部分的代码是基于底层进行编写的,不需要进行移植。移植UCOSII操作系统的时候需要移植的几个文件:INCLUDES.h是一个主头文件,出现在每个.c 文件的第一行。下面讲移植UCOSII操作系统的时候需要实际移植的三个关键文件:
1,OS_CPU.h
/* 数据类型 */
typedef unsigned char BOOLEAN;
typedef unsigned int OS_STK; //堆栈入口的宽度为16位
typedef unsigned short OS_CPU_SR; //定义CPU状态寄存器的宽度为16位
/* 与处理器有关的代码 */
#define OS_ENTER_CRITICAL() //进入临界区的代码
#define OS_EXIT_CRITICAL() //跳出临界区的代码#define OS_STK_GHOWTH 1 定义堆栈的方向:1=向下递减,0=向上递增
#define OS_TASK_SW() //定义软件任务切换的函数。
2,OS_CPU_C.c (最关键的移植文件):要求用户编写10个简单的C函数:
OSTaskStkInit();OSTaskCreateHook();OSTaskDelHook();OSTaskSwHook();OSTaskIdleHook();
OSTaskStatHook();OSTimeTickHook();OSInitHookBegin();OSInitHookend();OSTCBInitHook();
(1)OSTaskStkInit()的示例代码
OS_STK * OSTaskStkInit(void (*task)(void * pd),void * pada,OS_STK *ptos,INT16U opt);
{pada = pada;模拟ISR向量;//按照预先设计的寄存器值初始化堆栈结构;//不断的在堆栈中相应的位置填入你要传递的参数//返回栈顶指针给调用该函数的函数//在这里假定堆栈是从上往下递减的,下面讨论同样适用于以相反方向从下到上递增的堆栈结构。
}
(2)OSTaskCreateHook():
添加任务的时候OS_TCBInit()函数都会调用OSTaskCreateHook()函数,该函数允许扩展UCOSII的功能,当UCOSII设置完任务控制块OS_TCB初始化的绝大部分的工作后,但是在任务控制块被链接到相应的任务链中之前,以及在该任务就绪运行之前,UCOSII会调用OSTaskCreateHook(),该函数被调用的时候中断是打开的。
(3)OSTaskIdleHook()
很多微处理器都允许执行相应的指令,将CPU置于低功耗模式。而当接收到中断信号的时候,CPU就会退出低功耗模式,OSTaskIdle()函数可调用OSTaskIdleHook()函数,实现CPU的这种低功耗的模式:
void OS_TaskIdle(void *pdata)
{pdata = pdata;for(;;){OS_ENTER_CRITICAL();OSIdleCtr++;OS_EXIT_CRITICAL();OSTaskIdleHook();}
}
void OSTaskIdleHook(void)
{asm("STOP");//收到中断并完成中断服务。
}
三,UCOSII三个关键文件:
1,OS_CPU.h
typedef unsigned char BOOLEAN; //声明一个布尔变量
typedef unsigned char INT8U; //无符号的8位整型变量
typedef signed char INT8S; //有符号的8位整型变量//关键移植部分:
typedef INT32U OS_STK; //堆栈是32位宽度typedef INT32U OS_CPU_SR; //定义SR的寄存器为32位//进入临界区函数,此处是通过汇编实现的
#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR())
#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr))#define OS_STK_GROWTH 1 //堆栈的生长的方向是从高地址到低地址//关键的任务切换的函数
#define OS_TASK_SW() OSCtxSw()
2,OS_CPU_C.C
#include "ucos_ii.h"OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
{OS_STK *stk;opt = opt;stk = ptos; //定义一个局部变量*(stk) = (OS_STK)task; //Entry Point*(--stk) = (INT32U)0; //LR*(--stk) = (INT32U)0; //R12*(--stk) = (INT32U)0; //R11*(--stk) = (INT32U)0; //R10*(--stk) = (INT32U)0; //R9*(--stk) = (INT32U)0; //R8*(--stk) = (INT32U)0; //R7*(--stk) = (INT32U)0; //R6*(--stk) = (INT32U)0; //R5*(--stk) = (INT32U)0; //R4*(--stk) = (INT32U)0; //R3*(--stk) = (INT32U)0; //R2*(--stk) = (INT32U)0; //R1*(--stk) = (INT32U)p_arg; //R0*(--stk) = (INT32U)0x000000131L; //CPSR/* 这个就是配置CPU的堆栈的寄存器,SVC的用户模式,同时的打开普通中断和快速中断*/return (stk);
}因为其他的函数不是必须要移植的,所以这里就不进行移植了。
此段代码的意义是初始化堆栈,堆栈是用OS_STK定义的数组。
进行堆栈操作时注意S3C2440是满减栈,此代码后面会有所讲解。
3,OS_CPU_A.s:实现核心的任务切换需要的基本的函数
SRCPND EQU 0x4a000000 ; 源中断的寄存器
INTPND EQU 0x4a000010 ; 中断挂起寄存器:IRQ可以读取此寄存器决定服务32个中断源的哪个源rEINTPEND EQU 0x560000a8
INTOFFSET EQU 0x4a000014USERMODE EQU 0x10 //用户模式
FIQMODE EQU 0x11 //快速中断模式
IRQMODE EQU 0x12 //中断模式
SVCMODE EQU 0x13 //普通模式
ABORTMODE EQU 0x17 //异常模式
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0;*********************************************************************************************************
; EXPORT and EXTERNAL REFERENCES
;*********************************************************************************************************/IMPORT OSRunningIMPORT OSTCBCurIMPORT OSTCBHighRdyIMPORT OSPrioCurIMPORT OSPrioHighRdyIMPORT OSIntNestingIMPORT OSIntEnterIMPORT OSIntExitIMPORT OSTaskSwHookIMPORT OSTimeTickIMPORT EINT0_HandleEXPORT OSStartHighRdyEXPORT OSCtxSwEXPORT OSTickISR EXPORT OSIntCtxSwEXPORT OSCPUSaveSREXPORT OSCPURestoreSREXPORT OS_CPU_IRQ_ISRPRESERVE8AREA UCOS_ARM, CODE, READONLY;*********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;
; The stack frame is assumed to look as follows:
;
; Entry Point(Task Name) (High memory)
; LR(R14)
; R12
; R11
; R10
; R9
; R8
; R7
; R6
; R5
; R4
; R3
; R2
; R1
; R0 : argument
; OSTCBHighRdy->OSTCBStkPtr --> CPSR (Low memory)
;
; Note : OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;********************************************************************************************************** */
OSStartHighRdy ;---------------------------------------------------------------------------------- ; OSRunning = TRUE;;---------------------------------------------------------------------------------- MSR CPSR_cxsf,#(SVCMODE :OR: NOINT) ;Switch to SVC mode with IRQ&FIQ disableBL OSTaskSwHook ;Call user define Task switch hookLDR R0, =OSRunning ; OSRunning =TRUEMOV R1, #1STRB R1, [R0];---------------------------------------------------------------------------------- ; SP = OSTCBHighRdy->OSTCBStkPtr;;---------------------------------------------------------------------------------- LDR R0, =OSTCBHighRdyLDR R0, [R0] LDR SP, [R0] ;---------------------------------------------------------------------------------- ; Prepare to return to proper mode;---------------------------------------------------------------------------------- LDMFD SP!, {R0} MSR SPSR_cxsf, R0LDMFD SP!, {R0-R12, LR, PC}^;**********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level)
; void OSCtxSw(void)
;
; Note(s): 1) Upon entry:
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 2) The stack frame of the task to suspend looks as follows:
;
; PC (High memory)
; LR(R14)
; R12
; R11
; R10
; R9
; R8
; R7
; R6
; R5
; R4
; R3
; R2
; R1
; R0
; OSTCBCur->OSTCBStkPtr ----> CPSR (Low memory)
;
;
; 3) The stack frame of the task to resume looks as follows:
;
; PC (High memory)
; LR(R14)
; R12
; R11
; R10
; R9
; R8
; R7
; R6
; R5
; R4
; R3
; R2
; R1
; R0
; OSTCBHighRdy->OSTCBStkPtr ----> CPSR (Low memory)
;*********************************************************************************************************/
OSCtxSwSTMFD SP!, {LR} ;PCSTMFD SP!, {R0-R12, LR} ;R0-R12 LRMRS R0, CPSR ;Push CPSRSTMFD SP!, {R0} ;----------------------------------------------------------------------------------; OSTCBCur->OSTCBStkPtr = SP;---------------------------------------------------------------------------------- LDR R0, =OSTCBCurLDR R0, [R0]STR SP, [R0];---------------------------------------------------------------------------------- ; OSTaskSwHook();;--------------------------------------------------------------------------------- BL OSTaskSwHook;---------------------------------------------------------------------------------- ; OSTCBCur = OSTCBHighRdy;;---------------------------------------------------------------------------------- LDR R0, =OSTCBHighRdyLDR R1, =OSTCBCurLDR R0, [R0]STR R0, [R1];---------------------------------------------------------------------------------- ; OSPrioCur = OSPrioHighRdy;;---------------------------------------------------------------------------------- LDR R0, =OSPrioHighRdyLDR R1, =OSPrioCurLDRB R0, [R0]STRB R0, [R1];---------------------------------------------------------------------------------- ; SP = OSTCBHighRdy->OSTCBStkPtr;;---------------------------------------------------------------------------------- LDR R0, =OSTCBHighRdyLDR R0, [R0]LDR SP, [R0];---------------------------------------------------------------------------------- ;Restore New task context;---------------------------------------------------------------------------------- LDMFD SP!, {R0} ;POP CPSRMSR SPSR_cxsf, R0LDMFD SP!, {R0-R12, LR, PC}^ ;*********************************************************************************************************
; TICK HANDLER
;
; Description:
; This handles all the Timer0(INT_TIMER0) interrupt which is used to generate the uC/OS-II tick.
;*********************************************************************************************************/OSTickISRMOV R5,LR MOV R1, #1MOV R1, R1, LSL #10 ; Timer0 Source Pending Reg.LDR R0, =SRCPNDLDR R2, [R0]ORR R1, R1,R2STR R1, [R0]LDR R0, =INTPNDLDR R1, [R0]STR R1, [R0] ;---------------------------------------------------------------------------------- ; OSTimeTick();;---------------------------------------------------------------------------------- BL OSTimeTickMOV PC, R5 ; Return ;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From an ISR)
; void OSIntCtxSw(void)
;
; Description: 1) This code performs a context switch if a higher priority task has been made ready-to-run
; during an ISR.
;
; 2) The stack frame of the task to suspend looks as follows:
;
; PC (High memory)
; LR(R14)
; R12
; R11
; R10
; R9
; R8
; R7
; R6
; R5
; R4
; R3
; R2
; R1
; R0
;
; OSTCBCur->OSTCBStkPtr ----> CPSR (Low memory)
;
;
; 3) The stack frame of the task to resume looks as follows:
;
; PC (High memory)
; LR(R14)
; R12
; R11
; R10
; R9
; R8
; R7
; R6
; R5
; R4
; R3
; R2
; R1
; R0
; OSTCBHighRdy->OSTCBStkPtr ----> CPSR (Low memory)
;*********************************************************************************************************/
OSIntCtxSw;---------------------------------------------------------------------------------- ; Call OSTaskSwHook();;---------------------------------------------------------------------------------- BL OSTaskSwHook;---------------------------------------------------------------------------------- ; OSTCBCur = OSTCBHighRdy;;---------------------------------------------------------------------------------- LDR R0, =OSTCBHighRdyLDR R1, =OSTCBCurLDR R0, [R0]STR R0, [R1];---------------------------------------------------------------------------------- ; OSPrioCur = OSPrioHighRdy;;---------------------------------------------------------------------------------- LDR R0, =OSPrioHighRdyLDR R1, =OSPrioCurLDRB R0, [R0]STRB R0, [R1];---------------------------------------------------------------------------------- ; SP = OSTCBHighRdy->OSTCBStkPtr;;---------------------------------------------------------------------------------- LDR R0, =OSTCBHighRdyLDR R0, [R0]LDR SP, [R0];---------------------------------------------------------------------------------- ; Restore New Task context;---------------------------------------------------------------------------------- LDMFD SP!, {R0} ;POP CPSRMSR SPSR_cxsf, R0LDMFD SP!, {R0-R12, LR, PC}^ OS_CPU_IRQ_ISR STMFD SP!, {R1-R3} ; We will use R1-R3 as temporary registers
;----------------------------------------------------------------------------
; R1--SP
; R2--PC
; R3--SPSR
;------------------------------------------------------------------------MOV R1, SPADD SP, SP, #12 ;Adjust IRQ stack pointerSUB R2, LR, #4 ;Adjust PC for return address to taskMRS R3, SPSR ; Copy SPSR (Task CPSR)MSR CPSR_cxsf, #SVCMODE:OR:NOINT ;Change to SVC mode; SAVE TASK''S CONTEXT ONTO OLD TASK''S STACKSTMFD SP!, {R2} ; Push task''s PC STMFD SP!, {R4-R12, LR} ; Push task''s LR,R12-R4LDMFD R1!, {R4-R6} ; Load Task''s R1-R3 from IRQ stack STMFD SP!, {R4-R6} ; Push Task''s R1-R3 to SVC stackSTMFD SP!, {R0} ; Push Task''s R0 to SVC stackSTMFD SP!, {R3} ; Push task''s CPSRLDR R0,=OSIntNesting ;OSIntNesting++LDRB R1,[R0]ADD R1,R1,#1STRB R1,[R0] CMP R1,#1 ;if(OSIntNesting==1){BNE %F1LDR R4,=OSTCBCur ;OSTCBHighRdy->OSTCBStkPtr=SP;LDR R5,[R4]STR SP,[R5] ;}1MSR CPSR_c,#IRQMODE:OR:NOINT ;Change to IRQ mode to use IRQ stack to handle interruptLDR R0, =INTOFFSETLDR R0, [R0]LDR R1, IRQIsrVectMOV LR, PC ; Save LR befor jump to the C function we need return backLDR PC, [R1, R0, LSL #2] ; Call OS_CPU_IRQ_ISR_handler(); MSR CPSR_c,#SVCMODE:OR:NOINT ;Change to SVC modeBL OSIntExit ;Call OSIntExitLDMFD SP!,{R4} ;POP the task''s CPSR MSR SPSR_cxsf,R4LDMFD SP!,{R0-R12,LR,PC}^ ;POP new Task''s contextIRQIsrVect DCD EINT0_Handle ;*********************************************************************************************************
; CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II''s functions that need to
; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr'
; into the CPU''s status register.
;
; Prototypes : OS_CPU_SR OSCPUSaveSR(void);
; void OSCPURestoreSR(OS_CPU_SR cpu_sr);
;
;
; Note(s) : 1) These functions are used in general like this:
;
; void Task (void *p_arg)
; {
; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; OS_CPU_SR cpu_sr;
; #endif
;
; :
; :
; OS_ENTER_CRITICAL(); /* cpu_sr = OSCPUSaveSR(); */
; :
; :
; OS_EXIT_CRITICAL(); /* OSCPURestoreSR(cpu_sr); */
; :
; :
; }
;
; 2) OSCPUSaveSR() is implemented as recommended by Atmel''s application note:
;
; "Disabling Interrupts at Processor Level"
;*********************************************************************************************************
OSCPUSaveSRMRS R0, CPSR ; Set IRQ and FIQ bits in CPSR to disable all interruptsORR R1, R0, #0xC0MSR CPSR_c, R1MRS R1, CPSR ; Confirm that CPSR contains the proper interrupt disable flagsAND R1, R1, #0xC0CMP R1, #0xC0BNE OSCPUSaveSR ; Not properly disabled (try again)MOV PC, LR ; Disabled, return the original CPSR contents in R0OSCPURestoreSRMSR CPSR_c, R0MOV PC, LREND
UCOSII系统移植详解相关推荐
- MiniGui移植详解1【转】
MiniGUI 1.3.3 移植详解 作者:大漠孤狼 E-Mail:yuqiang0107@126.com 最近移植了 MiniGUI 1.3.3 到一个开发板上,中间遇到许多问题,在论坛上发问题,结 ...
- EasyPR中文开源车牌识别系统 开发详解
在上篇文档中作者已经简单的介绍了EasyPR,现在在本文档中详细的介绍EasyPR的开发过程. 正如淘宝诞生于一个购买来的LAMP系统,EasyPR也有它诞生的原型,起源于CSDN的taotao ...
- 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 ...
- Centos新建系统用户详解
2019独角兽企业重金招聘Python工程师标准>>> Centos新建系统用户详解 听语音 | 浏览:7501 | 更新:2015-02-02 18:56 | 标签:操作系统 1 ...
- linux系统安全详解
linux系统安全详解 http://www.2cto.com/Article/201207/142181.html一,BIOS安全(硬件上的安全) 1,最基本最简单的安全配置,保障计算机硬件配置等不 ...
- python try catch打印到日志_django 捕获异常和日志系统过程详解
这一块的内容很少, 异常使用try except即可, 日志只需要几行配置. 使用装饰器捕获方法内的所有异常 我使用装饰器来整个包裹一个方法, 捕获方法中的所有异常信息.并将其转为json返回客户端. ...
- 荒野行动系统推荐观战榜_荒野行动如何进行观战 荒野行动观战系统使用详解...
在荒野行动游戏中,一般玩家组队死亡之后就会退出游戏进行下一把,不过今日荒野行动全新上线了观战系统,让每一位玩家都能够在被淘汰之后,还能与队友进行互动沟通,下面就让小编为大家来介绍一下这个全新的游戏系统 ...
- FreeRTOS之源码 及 移植详解
源:FreeRTOS之源码 及 移植详解 转载于:https://www.cnblogs.com/LittleTiger/p/9117856.html
- Linux系统 logrotate 详解
对于 Linux 系统安全来说,日志文件是极其重要的工具.不知为何,我发现很多运维同学的服务器上都运行着一些诸如每天切分 Nginx日志之类的 CRON 脚本,大家似乎遗忘了 Logrotate,争相 ...
- 戴尔台式计算机怎么安装的,戴尔Dell电脑U盘安装台式机win10系统教程详解
最近有位戴尔Dell电脑用户,在使用电脑的时候,因为操作失误导致Windows文件出现问题,需要重装系统才可以解决.因此,大白菜整理了一些u盘重装系统的资料,下面就来看看戴尔Dell电脑U盘安装台式机 ...
最新文章
- runtime自动归档/解档
- 学习junit和hamcrest的使用
- tensorflow实现图像的翻转
- nohup 输出日志到文件_超详细的EFK安装部署教程--filebeat日志数据采集
- c++求平均值_云顶之弈S4:六射手娱乐吃鸡!人均刮痧王,每个人都是主C
- webdriver鼠标上下滑动
- Hbase Solr 二级索引 同步int数据报错com.ngdata.hbaseindexer.parse.ByteArrayValueMappers: Error mapping byte
- 将服务器get到的响应打印,得到HttpResponse的响应主体
- IT创业公司如何选型,以避免未来出现的版权之争?
- c++自由读写配置ifstream(一)
- linux top功能,[每日一题]说说Linux top命令的功能和用法
- Javascript返回顶部和砸金蛋,跑马灯等游戏代码实现
- 【三边定位】 演示程序V0.1
- 如何优雅的对列表接口进行分页?
- BZOJ3956: Count
- 丹尼尔·惠灵顿(Daniel Wellington)选择一洽的理由
- ucfirst.php
- 周星驰vs韩寒vs宁浩…Python告诉你春节该看哪部电影
- SHAPE 文件格式详解
- 基于安卓Android的移动医疗终端管理系统
热门文章
- 高薪设计师必修课 AE移动UI动效设计从入门到实战
- QT QDir(获取当前路径下的所有文件)
- 【语义分割—SegNet】SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation
- 针式打印机无电脑测试软件,针式打印机断针测试软件合集
- es6阮一峰-import、export学习
- 把PDF/AZW/EPUB转成图片
- smile——Java机器学习引擎
- 基于FPGA的电子计算器设计(中)
- 嵌入式Linux开发的编程语言选择
- python爬取酷狗音乐top500_爬取酷狗音乐Top500