Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393116
  • 博文数量: 87
  • 博客积分: 1171
  • 博客等级: 少尉
  • 技术积分: 1068
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-19 14:34
文章分类

全部博文(87)

文章存档

2014年(10)

2013年(24)

2012年(53)

我的朋友

分类: 嵌入式

2012-10-13 22:16:20

    

      首先介绍下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  

 

阅读(654) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~