标签归档:移植

UCOS-II OS_CPU_IRQ_ISR函数移植

在有中断发生时,程序跳到OS_CPU_IRQ_ISR处执行。OS_CPU_IRQ_ISR函数在OS_CPU_A.S中。

clip_image002

在分析这个移植代码前,先了解下发生IRQ中断时,ARM的处理流程:

1、 会把当前的CPSR的值拷贝到SPSR_irq

2、 把PC的值拷贝到LR_irq

3、 强制进入IRQ异常模式

4、 强制进入ARM状态

5、 禁止IRQ中断

6、 PC=0X18,跳转到OS_CPU_IRQ_ISR

上面这些都是硬件自动完成的。

继续阅读

UCOS-II OSIntCtxSw函数移植

clip_image002

OSIntCtxSw()的代码的OSCtxSw()下半部分的代码基本上一样。因为OSIntCtxSw()是在OSINTEXIT()中调用的。也就是在中断服务程序中调用的。在进入中断服务时,寄存器值已经被保存到了被中断任务的堆栈里。所以OSIntCtxSw()里不需要再保存。

OSIntCtxSw()得到待运行任务的任务控制块地址,根据控制块地址得到待运行任务的堆栈指针。然后把待运行任务的堆栈内容放到寄存器中,实现任务切换功能。

UCOS-II的OSCtxSw函数移植

OSCtxSw()函数把被中止任务的断点指针和CPU的寄存器值保存到该任务的堆栈中,并从待运行任务的堆栈中得到其堆栈指针,把待运行任务堆栈中的存储的CPU通用寄存器的内容恢复到CPU的通用寄存器中,最后使CPU获得待运行任务的断点指针。

任务切换函数OSCtxSw()一般有2种方法实现。一种是软中断,周立功的LPC资料上都是这么用的。一种是用子程序调用,我现在做的这个项目就是这么实现的。

在OS_CPU.H中定义

#define OS_TASK_SW() OSCtxSw()

OSCtxSw()函数在OS_CPU_A.S中:

OSCtxSw

STMFD SP!, {LR} ;PC (1)

STMFD SP!, {R0-R12, LR} ;R0-R12 LR (2)

MRS R4, CPSR ;Push CPSR (3)

STMFD SP!, {R4}

LDR R4, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; (4)

LDR R5, [R4] ;(5)

STR SP, [R5] ;(6)

;BL OSTaskSwHook ; OSTaskSwHook(); (7)

LDR R4, =OSPrioCur ; OSPrioCur = OSPrioHighRdy (8)

LDR R5, =OSPrioHighRdy ;(9)

LDRB R6, [R5] ;(10)

STRB R6, [R4] ;(11)

LDR R4, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; ;(12)

LDR R6, =OSTCBHighRdy ;(13)

LDR R6, [R6] ;(14)

STR R6, [R4] ;(15)

LDR SP, [R6] ; SP = OSTCBHighRdy->OSTCBStkPtr; ;(16)

LDMFD SP!, {R4} ;POP CPSR ;(17)

MSR CPSR_cxsf, R4 ;(18)

LDMFD SP!, {R0-R12, LR, PC} ;(19)

OS_Sched (void)函数在OS_CORE.C中:

void OS_Sched (void)

{

#if OS_CRITICAL_METHOD == 3

OS_CPU_SR cpu_sr = 0;

#endif

OS_ENTER_CRITICAL();

if (OSIntNesting == 0) {

if (OSLockNesting == 0) {

OS_SchedNew();

if(OSPrioHighRdy!=OSPrioCur) {

OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];

#if OS_TASK_PROFILE_EN > 0

OSTCBHighRdy->OSTCBCtxSwCtr++;

#endif

OSCtxSwCtr++; OS_TASK_SW();

}

}

}

OS_EXIT_CRITICAL();

}

在ADS中通过汇编语言可以看到,OS_TASK_SW();语句对应的汇编语句是 BL OSCtxSW

继续阅读