UcOS2移植
4、基于uCOS-II操作系统的移植实验
实验目的
内核的主要结构。 2.掌握将uC/OS-II 内核移植到ARM7 处 理器上的基本方法。
1.了解uC/OS-II
实验工具
实验平台 ADS1.2 超级终端
实验原理
所谓移植,指的是一个操作系统可以在某
个微处理器或者微控制器上运行。 设计的语言 C:主要开发工具 汇编:读写处理器、寄存器时只能通过汇 编语言来实现
C语言函数
后5个函数为接口函数,可以不加代码
uC/OS-II的启动
void main (void) { OSInit(); // 初始化uC/OS-II
. 通过调用OSTaskCreate()或 OSTaskCreateExt()创建至少一个任务; . OSStart(); //开始多任务调度,永不返回
所涉及到的函数
汇编函数
OSStartHighRdy() OSCtxSw() OSIntCtxSw() OSTickISR()
void void void void void void void *OSTaskStkInit (void (*task)(void *pd),void *pdata, *ptos, INT16U opt) OSTaskCreateHook (OS_TCB *ptcb) OSTaskDelHook (OS_TCB *ptcb) OSTaskSwHook (void) OSTaskStatHook (void) OSTimeTickHook (void)
}
基于uC/OS的应用开发
void YourTask (void *pdata)
{ /* 用户代码 */
OSTaskDel(OS_PRIO_SELF); }
ucos-II在ARM7上地移植
uc/os-II在ARM7上的移植1、移植的要求要使µC/OS-Ⅱ正常运行于某处理器上,须满足以下要求:1)处理器的C编译器能产生可重入代码;2)可以在C语言代码中打开和关闭中断;3)处理器支持中断,并且能产生定时中断(通常在10至100Hz之间);4)处理器支持能够容纳一定量数据(可能是几千字节)的硬件堆栈;5)处理器有将堆栈指针和其它CPU寄存器读出和存储到堆栈或内存中的指令。
2、移植过程基于µC/OS-Ⅱ的硬/软件体系结构如下图。
教材P165 图5-8µC/OS-Ⅱ的移植集中在OS_CPU.h,OS_CPU_A.s,OS_CPU.c这三个文件上,下面分别详细介绍三个文件中的函数和需要修改或者编写的代码。
2.1 OS_CPU.h的移植该文件定义了和处理器及编译器相关的定义及一些全局函数声明。
由于ARM7 处理器字长为32位,半字长为16位,字节为8位,因此在OS_CPU.h文件修改与编译器相关的定义如下:typedef unsigned char BOOLEAN;typedef unsigned char INT8U;typedef signed char INT8S;typedef unsigned short INT16U; /*某些编译器中int是32位的,故统一用short表示*/typedef signed short INT16S;typedef unsigned long INT32U;typedef signed long INT32S;typedef float FP32;typedef double FP64;typedef unsigned long OS_STK; /*堆栈宽度为32位,即ARM7种的字对齐方式*//*下面是与处理器相关的代码*/#define OS_CRITICAL_METHOD 2 /*使用方式2保护临界代码*/#define OS_ENTER_CRITICAL() ARMDisableInt() /*临界段代码保护宏定义*/ #define OS_EXIT_CRITICAL() ARMEnableInt()#define OS_STK_GROWTH 1 /*定义堆栈生长方向为向下生长 */#define OS_TASK_SW OSCtxSw /*宏定义,用于非中断级的任务切换*//*下面开始声明全局函数声明,均是OS_CPU_A.S中需要编写的函数*/extern void OSCtxSw(void); /*声明任务级任务切换函数*/extern void OSIntCtxSw(void); /*声明中断级任务切换函数*/extern void ARMDisableInt(void); /*声明中断禁止函数*/extern void ARMEnableInt(void); /*声明中断恢复函数*/extern void OSTickISR(void); /*声明时钟中断服务函数*/2.2 OS_CPU_C.C文件移植OS_CPU_C.C文件时,需要编写的是任务堆栈初始化函数OSTaskStkInit和时钟节拍中断服务钩子函数OSTimeTickHook。
《UCOSII移植》课件
分享UCOSII移植过程中的启示和思考,如项目管理、团队协作和技术挑战。
参考资料
• UCOSII官方文档 • 相关论文和书籍 • 移植过程中遇到的问题及解决方法的记录
任务切换和调度算法
介绍如何优化UCOSII的任务切 换和调度算法,以提高系统的 响应性和资源利用率。
增加新的系统服务
讲解如何增加新的系统服务, 如文件系统、网络协议和设备 驱动等,以满足特定需求。
扩展硬件驱动支持
探讨如何扩展UCOSII的硬件驱 动支持,以兼容不同的外设和 接口。
结束语
1 移植的重要性与价值
UCOSII的源代码
讲解UCOSII的源代码结构和功能模块,为后续的移植工作提供基础。
移植前的准备
1 硬件环境
介绍适用于UCOSII移植的硬件平台要求,例如处理器架构、外设支持和存储器需求。
2 开发工具
探讨用于UCOSII移植的开发工具,如编译器、调试器和仿真器等,以及如何配置和使用 它们。
3 UCOSII源代码
移植后的测试
1
资源占用率
介绍如何测试UCOSII移植后的硬件资源占用情况,以优化内存和处理器利用。
2
任务优先级和响应时间
讨论如何测试UCOSII移植后任务的优先级和响应时间,以确保实时性和性能。
3
系统稳定性和可靠性
探究如何测试UCOSII移植后系统的稳定性和可靠性,以验证移植的有效性。
优化和改进
解释如何获取UCOSII的源代码,并对代码结构和组织进行介绍,以便于后续的移植工作。
开始移植
1
方法和步骤
详细介绍UCOSII移植的具体方法和步骤,包括环境配置、源代码修改和编译等。
ucos_II移植总结
Ucos_II移植总结:之前已经基本算是成功的移植过ucos-II(内存管理部分没有处理),但是由于可恶的硬盘故障,让我的劳动成果付诸东流。
其间的一些移植经验没有及时总结,现在想来颇有点从头再来的悲壮!鉴于之前的教训,这次,边移植边总结,以防重蹈覆辙。
还好之前的移植过程已经解决了部分棘手的难题,现在复现一下权当是复习一下arm和ucos_II了。
这次的移植还是基于SEP4020芯片,其中的一些引导代码和中断处理代码还是照搬已经写好的代码吧,现在已经没有自己动手写的激情了!下面按照自己的移植步骤一步步总结吧:第一步:创建工程,将基本的启动代码照搬过来,建立一个最小系统,能够在开发板上运行成功。
第二步:将ucos-II源代码copy过来。
第三步:对基本的语法错误进行改正。
对工程进行编译,根据提示进行基本语法的改正。
主要包括:INCLUDES.h中头文件的调用第四步:对需要自己手动编写的函数首先要清空,防止编译报错,然后一步步手动编写代码。
1、临界段代码:os_cpu.h中OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()两个宏重新定义为我们自己写的开关中断函数。
Os_cpu_a.s文件添加如下代码:AREA MCUINIT , CODE, READONLYENTRY;/* 开启IRQ中断*/;voidEnableInterrupt(void);{EXPORT EnableInterruptEnableInterruptmrs r0,CPSRbic r0, r0, #0x80 ;set bit7 to 0msr CPSR_cxsf,r0movpc,lr ;Return to caller;};/* 关闭IRQ中断*/;voidDisableInterrupt(void);{EXPORT DisableInterruptDisableInterruptmrs r0,CPSRorr r0, r0, #0x80 ;set bit7 to 1msr CPSR_cxsf,r0movpc,lr ;Return to caller;}END2、OS_CPU_A.S文件代码编写AREA MCUINIT , CODE, READONLYENTRY;/* 开启IRQ中断*/;voidEnableInterrupt(void);{EXPORT EnableInterruptEnableInterruptmrs r0,CPSRbic r0, r0, #0x80 ;set bit7 to 0msr CPSR_cxsf,r0movpc,lr ;Return to caller;};/* 关闭IRQ中断*/;voidDisableInterrupt(void);{EXPORT DisableInterruptDisableInterruptmrs r0,CPSRorr r0, r0, #0x80 ;set bit7 to 1msr CPSR_cxsf,r0movpc,lr ;Return to caller;};任务切换代码OSCTXSWEXPORT OS_TASK_SW_ARMOS_TASK_SW_ARMSTMFD sp!, {lr} ; save pcSTMFD sp!, {lr} ; save lrMRS r14, SPSRSTMFD sp!, {r14} ; save current PSRSTMFD sp!, {r0-r12} ; save register file and ret address ;; OSPrioCur = OSPrioHighRdyIMPORT OSPrioCurIMPORT OSPrioHighRdyLDR r4, =OSPrioCurLDR r5, =OSPrioHighRdyLDRB r6, [r5]STRB r6, [r4]; Get current task TCB addressIMPORT OSTCBCurLDR r4, =OSTCBCurLDR r5, [r4]STR sp, [r5] ; store sp in preempted taskss TCB; Get highest priority task TCB addressIMPORT OSTCBHighRdyLDR r6, =OSTCBHighRdyLDR r6, [r6]LDR sp, [r6] ; get new tasks stack pointer; OSTCBCur = OSTCBHighRdySTR r6, [r4] ; set new current task TCB address;LDMFD sp!, {r0-r12} ; YYY+LDMFD sp!, {r14} ; YYY+; LDR r14, =0x000000D3MSR CPSR_cxsf, r14 ; YYY+;调试时屏掉此句才会跑的通,待解决LDMFD sp!, {lr,pc} ; YYY+;OS启动时开始运行创建的最高优先级任务; void OSStartHighRdy(void); ; Start the task with the highest priority;;EXPORT OSStartHighRdyOSStartHighRdyIMPORT OSTCBCurIMPORT OSTCBHighRdyIMPORT OSRunningLDR r4, =OSTCBCur ; Get current task TCB addressLDR r5, =OSTCBHighRdy ; Get highest priority task TCB addressLDR r5, [r5] ; get stack pointerLDR sp, [r5] ; switch to the new stackSTR r5, [r4] ; set new current task TCB address;OSRunning = 1 'TURE'LDR r4, =0x01 ; Get current task TCB addressLDR r5, =OSRunning ; Get highest priority task TCB addressSTRB r4, [r5];LDMFD sp!, {r0-r12} ; start the new taskLDMFD sp!, {r14} ; get new state from top of the stackMSR CPSR_cxsf, r14 ; CPSR should be SVC32ModeLDMFD sp!, {lr,pc};中断级任务切换EXPORT OSIntCtxSwOSIntCtxSwIMPORT OSTCBCurIMPORT OSPrioCurIMPORT OSTCBHighRdyIMPORT OSPrioHighRdyIMPORT OSTaskSwHookBL OSTaskSwHook;OSTCBCur = OSTCBHighRdyLDR r4, =OSTCBCurLDR r5, =OSTCBHighRdyLDR r6, [r5]STR r6, [r4];OSPrioCur = OSPrioHighRdyLDR r4, =OSPrioCurLDR r5, =OSPrioHighRdyLDRB r6, [r5]STRB r6, [r4];sp = OSTCBHighRdy->OSTCBStkPtrLDR r6, =OSTCBHighRdyLDR r6, [r6]LDR sp, [r6] ; get new tasks stack pointerLDMFD sp!,{r0, r1};在timedly中断服务程序中,函数开始压栈两个寄存器,为保证堆栈中数据一致,需出栈对齐;resume registersLDMFD sp!, {r0-r12} ; start the new taskLDMFD sp!, {r14} ; get new state from top of the stack; LDR r14, =0x000000D3MSR CPSR_cxsf, r14 ; CPSR SVC32Mode调试时屏掉此句才会跑的通,待解决LDMFD sp!, {lr,pc}END中断服务程序代码IRQ_DOstmfd sp!, {r0,r1}ldr r0, =IRQ_R1str r1, [r0]ldmfd sp!, {r0}ldr r1, =IRQ_R0str r0, [r1] ;保存R0和R1寄存器(因为这两个寄存器再后面要用到)add r13, r13, #4 ;restore the sp_irq top to original irq topsub r14, r14, #4mov r0, r14 ;LR_irq(R14)减4并保存在R0mrs r1, spsrorr r1, r1, #0x80 ;将SPSR_irq的中断屏蔽位置‘1’(屏蔽中断),并保存再R1 中msr cpsr_cxsf, r1 ;将模式切换到中断前的模式;---------------------------------------------------------------------------------------------bic r1, r1, #0x80 ;将原先保存的SPSR_irq的R1的中断屏蔽位清零(允许中断)stmfd sp!, {r0}stmfd sp!, {r14}stmfd sp!, {r1} ;依次将R0,R14,R1的值压入中断前模式下的堆栈(当前R0,R14,R1中存放的分别是LR_irq-4,中断前模式下的LR,SPSR_irq)ldr r0, =IRQ_R1ldr r1, [r0]stmfd sp!, {r1}ldr r1, =IRQ_R0ldr r0, [r1]stmfd sp!, {r0}ldmfd sp!, {r0,r1} ;恢复原先保存的R0和R1stmfd sp!, {r0-r12} ;将r0--r12全部压入中断以前模式下的堆栈;; Get current task TCB addressIMPORT OSTCBCurLDR r4, =OSTCBCur;及时保存当前任务中断,因为可能会进行任务切换LDR r5, [r4]STR sp, [r5] ; store sp in preempted taskss TCB;-----------------------------IMPORT int_vector_handlerbl int_vector_handler ;跳转到中断源判断和中断处理程序;----------------------------- ;restore the registerldmfd sp!, {r0-r12} ;恢复原先保存的R0-R12ldmfd sp!, {r14}msr cpsr_cxsf, r14ldmfd sp!, {r14} ;将原先保存的SPSR_irq恢复到CPSR中ldmfd sp!, {pc}3、堆栈初始化函数OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) {unsignedint *stk;opt = opt; /* 'opt' is not used, prevent warning */stk = (unsigned int *)ptos; /* Load stack pointer *//* build a context for the new task */*--stk = (unsigned int) task; /* pc */*--stk = (unsigned int) task; /* lr */*--stk = (0x60000053); /* cpsr IRQ, FIQ disable*/*--stk = 0; /* r12 */*--stk = 0; /* r11 */*--stk = 0; /* r10 */*--stk = 0; /* r9 */*--stk = 0; /* r8 */*--stk = 0; /* r7 */*--stk = 0; /* r6 */*--stk = 0; /* r5 */*--stk = 0; /* r4 */*--stk = 0; /* r3 */*--stk = 0; /* r2 */*--stk = 0; /* r1 */*--stk = (unsigned int) pdata; /* r0 */// *--stk = (0x0); /* spsr IRQ, FIQ disable */return ((void *)stk);}4、timertick函数void Timer_IRQ_Service1(void){U32 dummyread;U8 y;dummyread = *(RP)TIMER_T1ISCR;/* timerflag = 1;*///OSIntNesting = OSIntNesting + 1;clear_reg( TIMER_T1CR, 0);//关闭通道1中断OSTimeTick ();set_reg( TIMER_T1CR, 0);//使能通道1中断OS_ENTER_CRITICAL();if ((OSIntNesting == 0) && (OSLockNesting == 0)) { /* Sched. only if all ISRs done & not locked */y = OSUnMapTbl[OSRdyGrp]; /* Get pointer to HPT ready to run */OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);if (OSPrioHighRdy != OSPrioCur) { /* No CtxSw if current task is highest rdy */OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];OSCtxSwCtr++; /* Increment context switch counter *///OS_TASK_SW(); /* Perform a context switch */OSIntCtxSw();}}OS_EXIT_CRITICAL();}第五步:对移植好的代码进行调试。
UCOSII移植过程及心得
UCOSII V2.86在LPC2378上的移植(编译器ADS1.2)忙了几天,终于移植成功了。
移植UCOS需要准备一些东西,首先当然是OS源代码,再就是选定编译器,需要弄清一下几点:1、UCOS需要移植的内容2、编译器的特性(在这里主要是ATPCS)3、处理器的特性(这里主要注意ARM7的模式)以下先简要说一下这几点,为后面的程序说明做准备首先说说第一点,UCOS需要移植的内容。
1、数据类型的定义,这个根据平台来处理。
具体代码如下:2、任务切换函数,就是两个任务环境之间的切换。
3、处理临界代码前要关闭中断,之后再打开,这个实现的方法与平台关系很大。
4、栈的初始化,栈中保存的是任务的运行环境,不同的处理器中的寄存器自然是不一样的。
5、还有一个和任务切换差不多的,这个函数只运行一次,就是将第一个运行的任务的运行环境复制到CPU中。
再说说编译器的特性,ATPCS规定(想要详细一些的可以看看ADS 的帮助文档):R0-R3用来传递参数,R4-R12用来处理局部变量。
这个在处理汇编和C的接口时十分重要。
最后是CPU的特性。
ARM7有7种模式,但是有些模式对于UCOS在ARM7上的运行用处不大,经过综合考虑,可以只使用四种模式:SVC:运行OS代码和用户代码SYS:用于IRQ的嵌套处理,(暂时还未实现)IRQ:处理中断,处于OS的控制范围内FIQ:独立于操作系统,处理快速中断有了上面的说明,下面可以具体讨论了,因为网页中显示代码及注释不方便,所以把它们放在了附件中。
标题中前面是内容,括号内是涉及到的需要移植的函数1、任务栈(OSTaskStkInit)任务栈相当于CPU的一个备份,可以这样认为,当运行一个任务时,将栈中的数据复制到CPU中,由于某种原因停止运行一个任务时将CPU复制到任务栈中。
ARM7的CPU需要保存的寄存器如下:PC任务断点LRR12R11R10R9R8R7R6R5R4R3R2R1R0CPSR还有一个栈指针SP,这个保存在任务控制块中。
实验一 uCOS-II的移植
实验一uC/OS-II的移植1.实验目的(1)理解uCOS-II实时内核的工作原理;(2)熟悉uCOS-II在XS128上的移植过程;(3)掌握uCOS-II移植的细节。
2.实验任务(1)观察示例程序中的代码,体会实时操作系统与前后台程序的不同之处。
(2)完成由前后台程序编程到基于实时操作系统编程的思想转变。
3.预习要求(1)参考《嵌入式实时操作系统uCOS-II》(第2版),熟悉uCOS-II各模块的基本工作原理。
(2)参考《单片机与嵌入式系统开发方法》第9章内容以及《uCOS-II移植说明文档》。
熟悉uCOS-II在XS128上的移植过程。
4.实验步骤(1)打开示例程序,观察程序结构。
(2)识别出哪些是与硬件无关的文件,哪些是移植需要修改和添加的文件。
(3)打开OS_CPU.H文件,该文件定义CPU的数据类型,定义相关的宏。
打开OS_CPU_C文件,分析文件里各个函数的作用。
这两个文件是与CPU特性有关的文件。
(4)分别打开OS_CFG.H, INCLUDES.H. OS_CFG.H这三个文件,了解这三个文件的作用。
用户根据自己的应用系统来定制合适的内核服务功能.包括两个文件:OS_CFG.H, INCLUDES.H. OS_CFG.H是来配置内核, 用户根据需要对内核进行定制, 留下需要的部分, 去掉不需要的部分, 设置系统的基本情况. 比如系统可提供的最大任务数量, 是否定制邮箱服务, 是否需要系统提供任务挂起功能, 是否提供任务优先级动态改变功能等等;头文件INCLUDES.H为整个实时系统程序所需要的文件,包括了内核和用户的头文件。
(5)修改.prm文件中的中断向量,将其中的ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFEFF;改为ROM_C000 = READ_ONLYDATA_NEAR IBCC_NEAR 0xC000 TO 0xEEFF;将结尾处原有的VECTOR 0 _Startup;改为VECTOR ADDRESS 0xEFFE _Startup;再添加上VECTOR ADDRESS 0xEFF6 OSCtxSw;VECTOR ADDRESS 0xEFF0 OSTickISR两个中断向量。
uCOS-II在51单片机上的移植
#if OS_CRITICAL_METHOD = = 3 #define OS_ENTER_CRITICAL() ?? #define OS_EXIT_CRITICAL() ?? #endif
#define OS_STK_GROWTH
1
#define OS_TASK_SW()
???
9
7.1.8 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()
功能
处理临界段方式选择 堆栈增长方向 进入临界区 退出临界区 就绪态最高优先级任务运行 任务级任务切换 中断级任务切换 时钟节拍 任务堆栈初始化
表7-1 需要修改的关键函数和宏定义
6
7.1.6 INCLUDES.H
❖ 使得项目中的每个.c文件不用分别考虑它实际上需要那些头文件。 ❖ 它会包含一些不相关的头文件 ❖ INCLUDES.H 是一个头文件,它在所有的.c文件的第一行被包含。 ❖ #include “includes.h”
/***************************************************************************
*
uC/OS-II 实时内核
*
(c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
*
版权所有
方法1:
asm(“DI”);
在OS_ENTER_CRITICAL()中调用处理器指令来禁止#中def断ine ,OS以_EX及IT在_CRITICAL() \
OS_EXIT_CRITICAL()中调用允许中断指令。
asm(“POP PSW”);
方法2:
关于UCOS-Ⅱ的移植
关于UC/OS-II的移植网上介绍的已经很多了,比较流行的几款处理器(例如ARM)在网上都可以直接下载移植好的代码。
由于最近选修了一门嵌入式系统的课,用的处理器是EPSON公司的S1C33系列,做实验的时候要进行操作系统的移植,这个周末花了一天半的时间学习了一下,因为毕业设计的时候做过ARM 上的移植,于是将两者比较了一下,给出一般的移植要点。
由于将来实验还要设计到GUI的移植以及文件系统的移植和网络协议的移植,我会将自己的学习笔记都记录下来。
大家下载到源码后,针对Intel 80x86的代码在uCOS-II\Ix86L目录下。
代码是80x86实模式,且在编译器大模式下编译的。
移植部分的代码可在下述文件中找到:OS_CPU.H, OS_CPU_C.C, 和OS_CPU_A.ASM。
大家可以参考这个例子,对它进行修改。
INCLUDES.H 是主头文件,在所有后缀名为.C的文件的开始都包含INCLUDES.H文件。
使用INCLUDES.H 的好处是所有的.C文件都只包含一个头文件,程序简洁,可读性强。
缺点是.C文件可能会包含一些它并不需要的头文件,额外的增加编译时间。
与优点相比,多一些编译时间还是可以接受的。
用户可以改写INCLUDES.H文件,增加自己的头文件,但必须加在文件末尾。
//////////////////////////////////////////////////////////一、(1)OS_CPU.H文件的移植(针对S1C33209)//////////////////////////////////////////////////////////OS_CPU.H 文件中包含与处理器相关的常量,宏和结构体的定义。
#ifdef OS_CPU_GLOBALS#define OS_CPU_EXT //全局变量#else#define OS_CPU_EXT extern#endif//////////////////////////////////////////////////////////由于不同的处理器有不同的字长,µC/OS-II的移植需要重新定义一系列的数据结构。
uCOS-II多核移植
uC/OS-II是源码开放、可固化、可移植、可裁剪、可剥夺的实时多任务OS 内核,适用于任务多、对实时性要求较高的场合。
uC/OS-II适合小型系统,具有执行效率高、占用空间小、实时性优良和可扩展性等特点,最小内核可编译至2K。
uC/OS-II内核提供任务调度与管理、时间管理、任务间同步与通信、内存管理和中断服务等功能。
所谓RTOS移植,就是使一个实时内核能在某个微处理器或微控制器上运行。
大部分的uC/OS-II代码试用C写的,但仍需要用C和ASM写一些与处理器相关的代码,这是因为uC/OS-II在读写处理器寄存器时只能通过ASM实现。
要是uC/OS-II正常运行,处理器必须满足一定的条件:处理器的C编译器能产生可重入代码;用C语言就可以打开和关闭中断;处理器支持中断,并能产生定时中断;处理器支持能够容纳一定量数据的硬件堆栈;处理器有将SP和其他CPU reg读出和存储到堆栈或内存中的指令;uC/OS-II移植工作主要包括以下三个方面的内容:(1)修改与处理器核编译器相关的代码:主要在includes.h中,修改数据类型定义说明,OS_ENTER_CRITICAL()、OS_EXIT_CRITICAL()和堆栈增长方向定义OS_STK_GROWTH。
(2)用C语言编写10个移植相关的函数:主要在OS_CPU_C.C中,包括堆栈初始化OSTaskStkInit()和各种回调函数。
(3)编写4个汇编语言函数:主要在OS_CPU_A.ASM中,包括:_OSTickISR //时钟中断处理函数_OSIntCtxSW //从ISR中调用的任务切换函数_OSCtxSW //从任务中调用的任务切换函数_OSStartHighRdy //启动最高优先级的任务uC/OS-II移植的关键问题:(1)临界区访问:uC/OS-II需要先禁止中断再访问代码临界段,并且在访问完毕后重新允许中断,这就使得uC/OS-II能够保护临界段代码免受多任务或ISR的破坏。
uCOS-II嵌入式操作系统介绍与移植
退出/进入临界区函数 ARMDisableInt/ARMEnableInt
1、直接操作CPSR的I、F位
2、 ARMDisableInt将CPSR的I、F位设置为1, 关闭所有中断
3、 ARMEnableInt将CPSR的I、F位设置为0, 打开中断
任务级上下文切换函数 OS_TASK_SW
ARM处理器相关宏定义
1、退出临界区
#defineOS_ENTER_CRITICAL() ARMDisableInt()
2、进入临界区
#defineOS_EXIT_CRITICAL() ARMEnableInt()
堆栈增长方向
1、堆栈由高地址向低地址增长,这个也 是和编译器有关的,当进行函数调用时, 入口参数和返回地址一般都会保存在当 前任务的堆栈中,编译器的编译选项和 由此生成的堆栈指令就会决定堆栈的增 长方向。 #define OS_STK_GROWTH 1
1、该函数当任务因为被阻塞而主动请求cpu 调度时被执行,由于此时的任务切换都是在 非异常模式下进行的,因此区别于中断级别 的任务切换。 2、它先将当前任务的cpu现场保存到该任务 堆栈中,然后获得最高优先级任务的堆栈指 针,从该堆栈中恢复此任务的cpu现场,使之 继续执行。这样就完成了一次任务切换。
多任务应用程序、调用函数ARMTargetInit初始化ARM处理器; 2、调用OSInit进行操作系统初始化; 3、调用OSTaskCreate函数两个任务:TaskLED 和TaskSEG; 4、调用ARMTargetStart函数启动时钟节拍中断; 5、调用OSStart启动系统任务调度。
OS_CPU_A.S的移植
uCOSII几种移植方案的分析比较
uCOSII几种移植方案的分析比较ucosII的移植主要是修改os_cpu.h、os_cpu.s、os_cpu.c三个文件。
一、头文件《os_cpu.h》头文件《os_cpu.h》中定义使用的数据类型,堆栈的增长方向以及开关中断的实现。
中断的打开与关闭,在MCU-51移植中这样实现:#define OS_ENTER_CRITICAL() EA=0 //关中断#define OS_EXIT_CRITICAL() EA=1 //开中断#define OS_STK_GROWTH 0 //堆栈向上增长通过直接调用处理器指令来关闭打开中断。
存在一定的问题是:当系统调用后返回中断有可能是打开的。
另一种实现方法是,在OS_ENTER_CRITICAL()时先将中断禁止状态保存到堆栈中,然后禁止中断;在OS_EXIT_CRITICAL()时,恢复保存的状态。
在ARM移植中可以这样实现的,通过软件中断调用一段汇编代码,软件中断时就已经将cpsr保存到spsr中,在汇编代码中关闭中断即可。
如:#define OS_ENTER_CRITICAL() OsSwiHandle1(1);宏定义,参数1的软中断ENTER_CRITICAL;汇编代码实现关中断LDR R1, =OsEnterSumLDRB R2, [R1]ADD R2, R2, #1STRB R2, [R1]MRS R0, SPSRORR R0, R0, #NoIntMSR SPSR_c, R0MOVS PC, LR宏定义OS_TASK_SW(),它是在μC/OS-Ⅱ从低优先级任务切换到最高优先级任务时被调用的。
OS_TASK_SW()总是在任务级代码中被调用的。
另一个函数OSIntExit()被用来在ISR使得更高优先级任务处于就绪状态时,执行任务切换功能。
任务切换只是简单的将处理器寄存器保存到将被挂起的任务的堆栈中,并且将更高优先级的任务从堆栈中恢复出来。
uCOS_II的移植
uCOS_II的移植一....................................................................................嵌入式实时操作系统二....................................................................................uCOS_II的简介三....................................................................................uCOS_II的任务四....................................................................................uCOS_II的中断和时钟五....................................................................................uCOS_II同步通信六....................................................................................uCOS_II信号集与内存的管理七....................................................................................Keil的使用八....................................................................................51单片机的原理图与PCB九....................................................................................STM32的原理图与PCB十....................................................................................在51单片机上移植uCOS_II十一....................................................................................在STM32上移植uCOS_II十二....................................................................................常用英语翻译十三....................................................................................uCOS_II速查手册与PC中的函数功能十四....................................................................................总结第一章操作系统:一种系统软件(即程序加说明)它在计算机硬件与应用系统之间,通过提供程序接口屏蔽了计算机硬件的一些工作细节从而使应用程序设计人员得以在一个友好的平友上进行运用程序的设计。
ucos-ii的移植例子
两个任务分别控制一个led,位于PB4和PB5. PB4上的led每秒闪一次,PB5上的led每四秒闪一次。
#include"lf2407.h"#include"ucos_ii.h"OS_STK Main_TaskStk[64];OS_STK Sub_TaskStk[64];void Main_Task(void*data);void Sub_Task(void*data);void InitCPU(void){SCSR1 = 0x00fd;SCSR2 =(SCSR2|0x000b)& 0x000f;WDCR = 0x00e8;WSGR = 0x0040;MCRA = 0x0FFF;PBDATDIR = PBDATDIR|0x0F000;T2CON = 0x0000;GPTCONA = 0x0000;T2CNT = 0x0000;T2PR = 50000;T2CON = 0xd340;IMR = 0x0000;IFR = 0x003f;IMR = 0x0004;EVAIFRA = 0xFFFF;EVAIFRB = 0xFFFF;EVAIFRC = 0xFFFF;EVAIMRA = 0x0000;EVAIMRB = 0x0000;EVAIMRC = 0x0000;EVBIFRA = 0xFFFF;EVBIFRB = 0xFFFF;EVBIFRC = 0xFFFF;EVBIMRA = 0x0000;EVBIMRB = 0x0000;EVBIMRC = 0x0000;asm(" CLRC INTM");}int main(void){InitCPU();OSInit();OSTaskCreate(Main_Task,(void*)0,&Main_TaskStk[63], 0); OSStart();return 0;}void Main_Task(void*p_arg){EnableTick();OSTaskCreate(Sub_Task,(void*)0,&Sub_TaskStk[63],10);while(1){PBDATDIR |= 0x0010;OSTimeDlyHMSM(0, 0, 0, 500);PBDATDIR &= 0x0ffef;OSTimeDlyHMSM(0, 0, 0, 500);}}void Sub_Task(void*p_arg){while(1){PBDATDIR |= 0x0020;OSTimeDlyHMSM(0, 0, 2, 0);PBDATDIR &= 0x0ffdf;OSTimeDlyHMSM(0, 0, 2, 0);}}ucos-ii的移植及rtos下的应用API FOR 44B0要保证μC/OS-Ⅱ移植到微处理器后能正确运行;处理器需具备如下特性:1)处理器的c编译器支持可重入函数可重入的代码指的是一段代码(如一个函数)可以被多个任务同时调用,而不必担心会破坏数据。
UCOS-II在51单片机上的移植
UCOS-II在51单片机上的移植做操作系统的移植首先明白什么是移植,操作系统是一种鱼硬件(处理器)相关的软件,根据某一种处理器来设计的操作系统通常不能运行在那其他处理器。
所谓的移植是指修改操作系统,然后加载到一个处理器上。
本文只讲解步骤,至于理论知识,需要大家自己学习。
步骤:1,在UCOS-II的官网上下载,操作系统。
2,在网上找到或者自己建三四个文件:OS_CPU_A.ASSMOS_CPU.HOS_CPU_C.COS_CFG.H以上文件需要修改3,移植源码的编写和修改❖OS_CPU.H1)定义与编译器有关的数据类型typedef unsigned char BOOLEAN; /* 不能使用bit定义,结构中无法使用*/typedef unsigned char INT8U; /* 无符号8位数*/typedef unsigned char INT8S; /* 有符号8位数*/typedef unsigned int INT16U; /* 无符号16位数*/typedef signed int INT16S; /* 有符号16位数*/typedef unsigned long INT32U; /* 无符号32位数*/typedef signed long INT32S; /* 有符号32位数*/typedef float FP32; /* 单精度浮点数*/typedef double FP64; /* 双精度浮点数*/typedef unsigned char OS_STK; /* 定义堆栈入口宽度为8位*/typedef unsigned char OS_CPU_SR; /* 定义CPU状态字的宽度为8位*/2)定义堆栈增长方向#define OS_STK_GROWTH 0 /* MCS-51堆栈从下往上增长,1=向下,0=向上*/3)定义任务级的任务切换宏#define OS_TASK_SW() OSCtxSw() /* 任务级的任务切换宏*/4)定义临界段宏:#define OS_ENTER_CRITICAL() EA=0#define OS_EXIT_CRITICAL() EA=1❖OS_CPU_C.C①初始化任务栈void *OSTaskStkInit(void(*task)(void *pd), void *ppdata, void *ptos, INT16U opt) REENTRANT{O S_STK *stk;p pdata=ppdata; //pata data 为52文件关键字o pt =opt; /* opt没被用到,保留此语句防止警告产生 */s tk =(OS_STK *)ptos; /* 任务堆栈最低有效地址*/*stk++=15; /* 任务堆栈长度*/ *stk++=(INT16U)task & 0xFF; /* 任务代码地址低8位*/*stk++=(INT16U)task >> 8; /* 任务代码地址高8位*//* 处理器是按特定的顺序将寄存器存入堆栈的,所以用户在将寄存器存入堆栈的时候也要依照这一顺序 */*stk++=0x00; /* PSW*/*stk++=0x0A; /* ACC*/*stk++=0x0B; /* B */ *stk++=0x00; /* DPL*/*stk++=0x00; /* DPH*/*stk++=0x00; /* R0 */ *stk++=0x01; /* R1 */ *stk++=0x02; /* R2 */ *stk++=0x03; /* R3 */ *stk++=0x04; /* R4 */ *stk++=0x05; /* R5 */ *stk++=0x06; /* R6 */ *stk++=0x07; /* R7 */ /* 不用保存SP,任务切换时根据用户堆栈长度计算得出*/*stk++=(INT16U)(ptos+MAX_STK_SIZE) >> 8; /* ?C_XBP 仿真堆栈指针高8位 */*stk++=(INT16U)(ptos+MAX_STK_SIZE) & 0xFF; /* ?C_XBP 仿真堆栈低8位*/r eturn ((void *)ptos); /* 返回最低地址,这里不用弹出栈顶指针是为了提高计算效率 */}②初始化定时器void InitTimer0(void) REENTRANT{TMOD=TMOD&0xF0; //屏蔽高四位TMOD=TMOD|0x01; /* 模式1(16位定时器),仅受TR0控制 */ TH0=TIMER_20MS_TH0;TL0=TIMER_20MS_TL0;E A=0; /* EA和ET0,51上电缺省值为0,EA将在OSStartHighRdy()中打开*/ET0=0; /* 满足在OSStart()前不产生时钟中断的要求,系统启动后第一时间开定时器T0中断 */TR0=1;}❖OS_CPU_A.ASM编写4个函数OSStartHighRdy()OSCtxSw()OSIntCtxSw()OSTickISR()❖OS_CFG.H主要为参数和使能的宏定义#define MAX_STK_SIZE 1024 /* 最大堆栈大小为1k*/#define OS_MAX_EVENTS 5 /* 应用程序中事件控制块的最大数量(必须大于零)*/#define OS_MAX_FLAGS 2 /* 应用程序中事件标志组的最大数目(必须大于零)*/#define OS_MAX_MEM_PART 5 /* 内存分区的最大数目(必须大于零)*/#define OS_MAX_QS 2 /* 应用程序中队列控制块的最大数目(必须大于零)*/#define OS_MAX_TASKS 11 /* 应用程序中任务的最大数目(必须大于2)*/#define TASK_START_PRIO 2 /* 应用程序开始优先级*/#define OS_LOWEST_PRIO 12 /* 定义可分配的最低优先级(必须大于63)*/#define TASK_STK_SIZE 512 /* 默认任务堆栈大小*/#define OS_TICKS_PER_SEC 50 /* 设置每秒节拍数*/#define TIMER_20MS_TH0 0x70 /* CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TH0=0x70 */#define TIMER_20MS_TL0 0x00 /* CPU=22.1184MHz, OS_TICKS_PER_SEC=50, TL0=0x00 */晶振频率为22.1184MHz时才有OS_TICKS_PER_SEC=50,OS_TICKS_PER_SEC=50。
uCOS-II的移植及使用
uC/OS-II 概述-性能特点
• 源代码公开 • 可移植(Portable) – 大部分代码用ANSI C写,与处理器无关,移植时不 需修改 – 少量与微处理器硬件相关的部分用C与汇编编写, 移植时需修改:
• OS_CPU.H //与硬件相关,移植时需修改 • OS_CPU_A.ASM //集中了所有与处理器相关的汇编语言 代码 • OS_CPU.C //集中了所有与处理器相关的汇编语言代码
uC/OS-II 概述--文件结构
应用软件 (用户代码) μC/OS-II (与处理器类型无关的代码) μC/OS-II配置文件 (与应用程序有关) OS_CFG.H INCLUDES.H
体系 结构
OS_CORE.C OS_FLAG.C OS_MBOX.C OS_MEM.C OS_MUTEX.C
OS_Q.C OS_SEM.C OS_TASK.C OS_TIME.C uC/OS-II.C uC/OS-II.H
任务控制块就相当于是一个任务的身份证,没 有任务控制块的任务是不能被系统承认和管理 的。
任务控制块的结构
typedef struct os_tcb { OS_STK *OSTCBStkPtr;
//指向当前任务堆栈栈顶的指针。每个任务的堆栈容量可以是任意的。
#if OS_TASK_CREATE_EXT_EN
为了有效的对中断进行控制,在任务的代码里可使用UC/OS-II定义的宏 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来控制何时响应中断, 何时屏蔽中断。在运行这两个宏之间的代码时是不会响应中断的,这种受保 护的代码段叫临界段。
2.1.2 uC/OS-II的任务—任务控制块(TCB)
uC/OS-II 概述-性能特点
uCOS移植(uCOS-II在Microblaze上的移植)
随着集成电路设计与制造技术的发展,FPGA芯片的容量越来越大、性能越来越高,用FPGA构建片上系统成为现实,基于FPGA的嵌入式系统与SOPC(System On a Programmable Chip)设计技术将逐渐成为系统设计的主流技术,正获得越来越广泛地研究。
Microblaze是Xilinx公司一款针对FPGA器件进行了优化设计的软处理器核,有不错的性能且价格低廉,且支持Xilinx全系列的FPGA器件,应该有着广阔的发展前景。
μC/OS-II 是Jean Labrosse先生于1998年推出的一个优秀的开放源码的实时操作系统,具有移植方便、执行效率高、占用空间小、实时性强和可靠性高等优点。
采用μC/OS-II+Microblaze的应用平台对中小嵌入式系统应用来说是十分适合的。
本文基于μC/OS-II在Microblaze上的移植与基于该系统的应用研究,记录移植和使用过程的心得、体会,内容可能会有些零散,希望对有类似应用的朋友有些帮助,也欢迎大家来交流与讨论。
一、主要参考资料①μC/OS-II学习主要参考邵贝贝教授译的《嵌入式实时操作系统μC/OS-II(第2版)》下面是CHINA-PUB的介绍/12618网上也有该书第一版的电子书可以找来学习。
② Micrium公司的Micrium-uCOS-II-V286.ZIP,包括代码与文档,可以从获得。
③ Micrium公司的μC/OS-II and the Xilinx MicroBlaze Processor Application Note可以从获得。
④ Xilinx公司EDK相关文档:/ise/embedded/edk_docs.htm⑤ISE、EDK软件的帮助文档,包括MicroBlaze Processor Reference Guide (mb_ref_guide.pdf)。
⑥ EDK的基本使用可以参考:Xilinx官方的6个EDK实验(中文版).pdf百度文库上有/view/e92e71d184254b35eefd3425.html二、操作系统的配置选项问题在进行Software Platform配置时,一般安装了EDK软件后,操作系统与库设置时可选择的标准选项只有两个:Standalone和Xilkernel。
ucos ii移植过程详解
uCOS-II移值过程实例讲解我将uCOS-II 移植到了EPONS 的C33209的平台上,接下来我就基于我移植好的代码讲解如何将uCOS-II从一种MCU移植到另一种MCU。
首先介绍uCOS-II的文件,如下表:ucos_ii.hos_cfg.hos_cpu.hos_core.cos_dbg_r.cos_flag.cos_mbox.cos_mem.cos_mutex.cos_q.cos_sem.cos_task.cos_time.cucos_ii.cos_cpu_c.cos_cpu_a.asm其中我们和硬件平台相关的文件的文件名被加粗了,也就是说若要将uCOS-II移植到新的平台上只要关心被以上四个文件就行了。
当然你也可以根据需要再添加你自己的和平台相关的文件,事实上我也是这么做的。
在我移植的例子中就添加了四个和平台相关的文件,文件如下表:crt0.cdrv_rtc.cvector.cext.scrt0.c是用来初始化系统的比如说MCU的一些特殊寄存器、设置外围的总线接口,等。
drv_rtc.c是用来初始化系统中的一个RTC的,这个RTC可以为内核提供必要的基于时间片调度的时基。
同时提供了对RTC开始和停止的操作函数。
在我的例子中RTC会每秒产生32次中断。
vector.c顾名思义,它是系统上电后为系统提供矢量入口表的文件,当然也包括中断向量表。
ext.s是为uc/OS-II 提供OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()函数的具体实现以及在用户程序的中断函数出入时要调用的状态保护和状态恢复函数OS_SA VEALL ()和OS_RESTOREALL ()。
前面两个函数的功能是:OS_ENTER_CRITICAL()屏蔽中断;OS_EXIT_CRITICAL()恢复原来的中断使能状态。
1. os_cpu_a.asm的说明要想顺利的移植首先要了解uCOS-II的一些基本概念。
ucos-ii在pc上的移植
ucos-ii在pc上的移植一、安装工作1.安装Borland C++。
我安装的是BC4.5。
2.安装TASM5.0汇编编译器。
(注意解压后放在哪了)3.右键单击我的电脑--->属性--->高级--->环境变量--->弹出“环境变量”对话框。
4.在“用户变量”列表中找到path,在变量值末尾添加“;C:\TASM\BIN;”二、uCOS/II 相关文件说明1.CPU移植相关程序OS_CPU_A.ASMOS_CPU_C.COS_CPU.H2.uCOS-II核心程序uCOS_II.HuCOS_II.COS_CORE.COS_TASK.COS_TIME.COS_FLAG.COS_MBOX.COS_MEM.COS_MUTEX.COS_Q.COS_SEM.C3.PC相关程序PC.CPC.H4.实验程序INCLUDES.HOS_CFG.HTEST.C5.需要编译的程序有五个,如下实验程序:TEST.CCPU程序:OS_CPU_C.C、OS_CPU_A.ASM(CPU汇编程序)uCOS_II程序:uCOS_II.CPC机程序:PC.C三、准备工作为了尽量不改动原来的文件,我只进行文件夹移动。
我把测试的工程建在F:\ucos-tst\project,ucos-tst下还有其他三个文件夹:1.F:\ucos-tst\source (放置实验程序INCLUDES.H OS_CFG.H TEST.C)2.F:\ucos-tst\obj (放置工程临时文件)3.F:\ucos-tst\final (放置可执行文件)将SOFTWARE 复制到F盘目录下SOFTWARE 提供CPU程序、uCOS-II核心程序、PC相关程序。
之所以要放在F盘下是因为includes.h 中有这么一句#include"\software\ucos-ii\ix86l\bc31\os_cpu.h",这句的意思是在当前盘符下查找文件夹software 中的内容。
实验二 uCOS-II在windows下的移植
实验二uCOS-II在windows下的移植
一:实验目的:
1.掌握uCOS-II在windows下的移植。
二:实验内容:
完成实验环境搭建,并且将uCOS-II移植到d盘下。
三:实验步骤:
1.可以将该工程所需的五个文件:OS_CPU_A.ASM,OS_CPU_C.C,PC.C,TEST.C,Ucos_II.C
放到一个独立的文件夹中,添加的时候便于添加。
2.按照实验一的步骤建立工程
添加所需要的文件:
3.若是将工程建到同software文件夹同一磁盘,但并未如之前一样放到“software\uCOS-II\EX1_x86L\BC45\source\”路径下,在编译运行时会提醒:“unable to open includes.h”和“unable to open os_cfg.h”,解决方法如下:
方法一:将#include “includes.h”改为
“#include “..\SOFTWARE\uCOS-II\EX1_x86L\BC45\SOURCE\includes.h””
将#include “os_cfg.h”改为
“#include “..\SOFTWARE\uCOS-II\EX1_x86L\BC45\SOURCE\os_cfg.h””
方法二:将“..\SOFTWARE\uCOS-II\EX1_x86L\BC45\SOURCE\”路径下的“includes.h”和“os_cfg.h”复制到工程所在的目录之下。
3.运行程序:。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
学号:
嵌入式系统及应用
实验报告
uc/os-II的移植
学生姓名
班级
成绩
计算机与信息工程学院
2013年10月14日
任务的基本管理
1、实验目的
a)理解stm32处理器的寄存器结构;
b)写好uc/os-II的接口代码;
2、实验原理及程序结构
2.1 实验设计
本实验主要实现操作和底层寄存器的数据交换和通信,从而实现操作系统的移植。
实现主要如下。
(1)实现配置文件的编写;
(2)实现寄存器和内存的管理;
2.2 源程序说明
IMPORT OSRunning ; External references
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSIntNesting
IMPORT OSIntExit
IMPORT OSTaskSwHook
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
EXPORT OS_CPU_SR_Save ; Functions declared in this file
EXPORT OS_CPU_SR_Restore
EXPORT PendSV_Handler
NVIC_INT_CTRL EQU 0xE000ED04 ; 中断控制寄存器
NVIC_SYSPRI2 EQU 0xE000ED20 ; 系统优先级寄存器(2)
NVIC_PENDSV_PRI EQU 0xFFFF0000 ; PendSV中断和系统节拍中断
; (都为最低,0xff).
NVIC_PENDSVSET EQU 0x10000000 ; 触发软件中断的值.
PRESERVE8
AREA |.text|, CODE, READONLY
THUMB
OS_CPU_SR_Save
MRS R0, PRIMASK ;读取PRIMASK到R0,R0为返回值
CPSID I ;PRIMASK=1,关中断(NMI和硬件FAULT可以响应)
BX LR ;返回
OS_CPU_SR_Restore
MSR PRIMASK, R0 ;读取R0到PRIMASK中,R0为参数
BX LR ;返回
;函数名称: OSStartHighRdy
;功能描述: 使用调度器运行第一个任务
参数: None
返回值: None
OSStartHighRdy
LDR R4, =NVIC_SYSPRI2 ; set the PendSV exception priority
LDR R5, =NVIC_PENDSV_PRI
STR R5, [R4]
MOV R4, #0 ; set the PSP to 0 for initial context switch call MSR PSP, R4
LDR R4, =OSRunning ; OSRunning = TRUE
MOV R5, #1
STRB R5, [R4];切换到最高优先级的任务
LDR R4, =NVIC_INT_CTRL ;rigger the PendSV exception (causes context switch) LDR R5, =NVIC_PENDSVSET
STR R5, [R4]
CPSIE I ;enable interrupts at processor level
OSStartHang
B OSStartHang ;should never get here
;/**************************************************************************************
;* 函数名称: OSCtxSw
;* 功能描述: 任务级上下文切换
;* 参数: None
;* 返回值: None
;*******************************************************************************
OSCtxSw
PUSH {R4, R5}
LDR R4, =NVIC_INT_CTRL ;触发PendSV异常 (causes context switch)
LDR R5, =NVIC_PENDSVSET
STR R5, [R4]
POP {R4, R5}
BX LR
;/******************************************************************************
;* 函数名称: OSIntCtxSw
;* 功能描述: 中断级任务切换
;* 参数: None
;* 返回值: None
;***************************************************************************************/ OSIntCtxSw
PUSH {R4, R5}
LDR R4, =NVIC_INT_CTRL ;触发PendSV异常 (causes context switch)
LDR R5, =NVIC_PENDSVSET
STR R5, [R4]
POP {R4, R5}
BX LR
NOP
;/**************************************************************************************
;* 函数名称: OSPendSV
;* 功能描述: OSPendSV is used to cause a context switch.
;* 参数: None
;* 返回值: None
;*******************************************************************************
PendSV_Handler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer 如果在用PSP堆栈,则可以忽略保存寄存器,参考CM3权威中的双堆栈-白菜注
CBZ R0, PendSV_Handler_Nosave ; Skip register save the first time
SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
STM R0, {R4-R11}
LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out ; At this point, entire context of process has been saved
PendSV_Handler_Nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
BLX R0
POP {R14
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0, {R4-R11} ; Restore r4-11 from new process stack
ADDS R0, R0, #0x20
MSR PSP, R0 ; Load PSP with new process SP
ORR LR, LR, #0x04 ; Ensure exception return uses process stack
CPSIE I
BX LR ; Exception return will restore remaining context
end。