首先介绍下raw OS,这是网上大神txj写的实时内核,其介绍在 可以详细看到,个人觉得研究这个系统之后,入手linux,比先学习ucos,然后入手llinux更容易,因为里面大量借鉴了linux的思想,链表 slab 分配器。目前raw 正在升级之中,已经在VC 下,STM32下,S3C2440下,完成移植,移植简单,快速,做过ucos的朋友,不用一天的时间就能完成raw移植。下面将自己移植过程中的一些心得和经验总结下。希望对raw感兴趣的朋友有所帮助。在移植过程中txj大神给予了全程指导,在此表示非常感谢。
1,在任务调度函数中raw_sched()中,
void raw_sched ()
{
RAW_SR_ALLOC();
if (raw_int_nesting) {
return;
}
if (raw_sched_lock) {
return;
}
RAW_CRITICAL_ENTER();
get_ready_task();
if (high_ready_obj == raw_task_active) {
RAW_CRITICAL_EXIT();
return;
}
CONTEXT_SWITCH();
RAW_CRITICAL_EXIT();
}
看到,进入临界区后,进行了CONTEXT_SWITCH(); ,此时并没有开中断,即没有执行到RAW_CRITICAL_EXIT();,也就是说完成了关中断(即 RAW_CRITICAL_ENTER();)但是没有完成开中断,那说明,开中断操作是在任务切换里的,进入raw.S中,CONTEXT_SWITCH(); 可以看到。
LDMFD SP!, {R0} @POP CPSR
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
在port_task_switch()函数中,上面这些语句对CPSR进行了操作,也就是说在这里开的中断,那么一个第一次调度的函数怎么能够完成开中断呢,这要求这个任务的在初始化它自身的堆栈时,压栈的CPSR必须是开中断的,所以在port_stack_init(在prot.c) 压CPSR入栈的时候,必须使*(--stk) = (RAW_U32)0x00000013L; //CPSR 开中断。这样保证任务切换后能够响应中断,这样才能保证任务的交替执行。
2,汇编中引用C中的函数问题。
在汇编中引用C中的函数,没有使用.extern,竟然也没有在链接的时候报错,不知什么原因,但是下次的时候一定要注意了。
3.部分移植的相关代码
OS_CPU_SR_Save:
MRS R0, CPSR @ Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1, R0, #0xC0
MSR CPSR_c, R1
MRS R1, CPSR @Confirm that CPSR contains the proper interrupt disable flags
AND R1, R1, #0xC0
CMP R1, #0xC0
BNE OS_CPU_SR_Save @ Not properly disabled (try again)
MOV PC, LR @ Disabled, return the original CPSR contents in R0
OS_CPU_SR_Restore:
MSR CPSR_c, R0
MOV PC, LR
CPU_IntDis:
MRS R0,CPSR
ORR R0,R0,#0xC0
MSR CPSR_c,R0
BX LR
CPU_IntEn:
MRS R0,CPSR
AND R1,R0,#0x3F
MSR CPSR_c,R1
BX LR
raw_start_first_task:
MSR CPSR_cxsf,#SVCMODE|NOINT @Switch to SVC mode with IRQ&FIQ disable
BL task_switch_hook @Call user define Task switch hook
@----------------------------------------------------------------------------------
@ SP = raw_task_active->task_stack;
@----------------------------------------------------------------------------------
LDR R0, =raw_task_active
LDR R0, [R0]
LDR SP, [R0]
@----------------------------------------------------------------------------------
@ Prepare to return to proper mode
@----------------------------------------------------------------------------------
LDMFD SP!, {R0}
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
port_task_switch:
STMFD SP!, {LR} @PC
STMFD SP!, {R0-R12, LR} @R0-R12 LR
MRS R0, CPSR @Push CPSR
STMFD SP!, {R0}
@----------------------------------------------------------------------------------
@ raw_task_active->task_stack = SP
@----------------------------------------------------------------------------------
LDR R0, =raw_task_active
LDR R0, [R0]
STR SP, [R0]
@----------------------------------------------------------------------------------
@ task_switch_hook();
@---------------------------------------------------------------------------------
BL task_switch_hook
@----------------------------------------------------------------------------------
@ raw_task_active= high_ready_obj;
@----------------------------------------------------------------------------------
LDR R0, =high_ready_obj
LDR R1, =raw_task_active
LDR R0, [R0]
STR R0, [R1]
@----------------------------------------------------------------------------------
@ high_ready_obj->task_stack;
@----------------------------------------------------------------------------------
LDR R0, =high_ready_obj
LDR R0, [R0]
LDR SP, [R0]
@----------------------------------------------------------------------------------
@Restore New task context
@----------------------------------------------------------------------------------
LDMFD SP!, {R0} @POP CPSR
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
raw_int_switch:
@BL task_switch_hook
@----------------------------------------------------------------------------------
@ raw_task_active = high_ready_obj;
@----------------------------------------------------------------------------------
LDR R0, =high_ready_obj
LDR R1, =raw_task_active
LDR R0, [R0]
STR R0, [R1]
@----------------------------------------------------------------------------------
@ SP = high_ready_obj->task_stack;
@----------------------------------------------------------------------------------
LDR R0, =high_ready_obj
LDR R0, [R0]
LDR SP, [R0]
@----------------------------------------------------------------------------------
@ Restore New Task context
@----------------------------------------------------------------------------------
LDMFD SP!, {R0} @POP CPSR
MSR SPSR_cxsf, R0
LDMFD 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, SP
ADD SP, SP, #12 @Adjust IRQ stack pointer
SUB R2, LR, #4 @Adjust PC for return address to task
MRS R3, SPSR @ Copy SPSR (Task CPSR)
MSR CPSR_cxsf, #SVCMODE|NOINT @Change to SVC mode
@ SAVE TASK''S CONTEXT ONTO OLD TASK''S STACK
STMFD SP!, {R2} @ Push task''s PC
STMFD SP!, {R4-R12, LR} @ Push task''s LR,R12-R4
LDMFD R1!, {R4-R6} @Load Task''s R1-R3 from IRQ stack
STMFD SP!, {R4-R6} @ Push Task''s R1-R3 to SVC stack
STMFD SP!, {R0} @ Push Task''s R0 to SVC stack
STMFD SP!, {R3} @ Push task''s CPSR
LDR R0,=raw_int_nesting @raw_int_nesting++
LDRB R1,[R0]
ADD R1,R1,#1
STRB R1,[R0]
CMP R1,#1 @if(raw_int_nesting==1){
BNE 1f
LDR R4,=raw_task_active @high_ready_obj->task_stack=SP;
LDR R5,[R4]
STR SP,[R5] @}
1:
MSR CPSR_c,#IRQMODE|NOINT @Change to IRQ mode to use IRQ stack to handle interrupt
LDR R0, =INTOFFSET
LDR R0, [R0]
LDR R1, =HandleEINT0
MOV LR, PC @ Save LR befor jump to the C function we need return back
LDR PC, [R1, R0, LSL #2] @ Call OS_CPU_IRQ_ISR_handler();
MSR CPSR_c,#SVCMODE|NOINT @Change to SVC mode
BL raw_finish_int @Call raw_finish_int
LDMFD SP!,{R4} @POP the task''s CPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC}^ @POP new Task''s context
OSTickISR:
MOV R5,LR
MOV R1, #1
MOV R1, R1, LSL #10 @ Timer0 Source Pending Reg.
LDR R0, =SRCPND
LDR R2, [R0]
ORR R1, R1,R2
STR R1, [R0]
LDR R0, =INTPND
LDR R1, [R0]
STR R1, [R0]
@----------------------------------------------------------------------------------
@ OSTimeTick();
@----------------------------------------------------------------------------------
BL raw_time_tick
MOV PC, R5 @Return