| 网站首页 | 新闻 | SOPC | FPGA | DSP | ARM | 嵌入式操作系统 | 下载 | 所有产品 | 留言 | 论坛 | 购买指南 | 网络协议 | 驱动设计 | 
您现在的位置: 21嵌入式控制研究室 >> 嵌入式操作系统 >> ucOSII >> 文章正文 用户登录 新用户注册
在S3C44B0X上移植UC/OS-II关于UC/OS-II移植到S3C44B0     ★★★★★ 【字体:
在S3C44B0X上移植UC/OS-II关于UC/OS-II移植到S3C44B0
作者:佚名    文章来源:本站原创    点击数:    更新时间:2005-11-30
移植需要改写的文件:OS_CPU.H, OS_CPU_A.S, OS_CPU_C.C

1.OS_CPU.H

定义了数据类型,与编译器相关,需要修改;

#define    SVC32MODE    0x13
移植后的OS运行在SVC模式下;

typedef unsigned int OS_STK
因为处理器现场的寄存器在任务切换时都将会保存在当前运行任务的堆栈中,所以OS_STK数据类型应该是和处理器的寄存器长度一致。
定义了堆栈的方向,在S3C44B0X定义为:#define OS_STK_GROWTH 1


OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()的实现:
我们用第二种方式:#define OS_CRITICAL_METHOD 2,使用堆栈保存状态和恢复状态;

#define    OS_ENTER_CRITICAL()    ARMDisableInt()
#define    OS_EXIT_CRITICAL()    ARMEnableInt()
在OS_CPU.A.S中实现:

        EXPORT     ARMDisableInt
ARMDisableInt
    MRS    r0, cpsr
    STMFD    sp!, {r0}              push current PSR
    ORR    r0, r0, #0xC0
    MSR    cpsr_c, r0          disable IRQ Int s
    MOV    pc, lr

        EXPORT     ARMEnableInt
ARMEnableInt
    LDMFD    sp!, {r0}                 pop current PSR
    MSR    cpsr_c, r0                restore original cpsr
    MOV    pc, lr

2. OS_CPU_C.C 
钩子函数(HOOK)由用户实现,这里只有定义即可。
主要实现OSTaskStkInit函数:OSTaskCreate和OSTaskCreateExt通过调用OSTaskStkInit来初始化任务的堆栈结构。
堆栈看起来就像中断刚发生过一样,所有寄存器都保存在堆栈里。

OS_STK * OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
    unsigned int *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 = 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 = (SVC32MODE|0x40);            /* cpsr  FIQ disable*/
    //*--stk = (SVC32MODE|0x40);    /* spsr  FIQ disable */

    return ((OS_STK *)stk);
}

定义一个全局变量:
INT32U        OSIntCtxSwFlag = 0;           /* Used to flag a context switch */
3. OS_CPU_A.S

4个简单的汇编语言函数

(1) OSStartHighRdy()
OSStart()函数调用OSStartHighRdy()来使就绪态任务中优先级最高的任务开始运行。

示意代码:
void OSStartHighRdy(void)
{
   调用用户定义的OSTaskSwHook();
   OSRunning = TRUE;
   得到将要恢复运行任务的堆栈指针:
   Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
   从新任务堆栈中恢复处理器的所有寄存器;
   执行中断返回指令;
}

汇编代码:

OSStartHighRdy

        BL     OSTaskSwHook              Call user-defined hook function

        LDR     r4,=OSRunning             Indicate that multitasking has started
        MOV     r5, #1                   
        STRB     r5, [r4]                  OSRunning = true

        LDR     r4, =OSTCBHighRdy         Get highest priority task TCB address
        LDR     r4, [r4]                  get stack pointer
        LDR     sp, [r4]                  switch to the new stack

        LDMFD     sp!, {r4}                 pop new task s psr
        MSR     cpsr_cxsf, r4
        LDMFD     sp!, {r0-r12,lr,pc}       pop new task s r0-r12,lr & pc

(2) OSCtxSw()
OSCtxSw():实现任务切换功能。

示意代码:

void OSCtxSw(void)
{
    保存处理器寄存器;
    在当前任务的任务控制块中保存当前任务的堆栈指针:
    OSTCBur->OSTCBStkPtr = Stack pointer;
    OSTaskSwHook();
    OSTCBCur = OSTCBHighRdy;
    OSPrioCur = OSPrioHighRdy;
    得到将要重新开始的任务的堆栈指针:
    Stack Pointer = OSTCBHighRdy->OSTCBStkPtr;
    从新任务的任务堆栈中恢复处理器所有寄存器的值;
    执行中断返回指令;
}

汇编代码:
OSCtxSw
        STMFD     sp!, {lr}                 push pc (lr is actually be pushed in place of PC)
        STMFD     sp!, {r0-r12,lr}          push lr & register file

        MRS     r4, cpsr
        STMFD     sp!, {r4}                 push current psr

        LDR     r4, =OSTCBCur             Get current task TCB address
        LDR    r5, [r4]
        STR     sp, [r5]                  store sp in preempted tasks s TCB
    
        IMPORT  OSTaskSwHook
OSIntCtxSw
    BL    OSTaskSwHook
        
    LDR    r4, =OSTCBHighRdy
    LDR    r4, [r4]
    LDR    r5, =OSTCBCur
    STR    r4, [r5]                  OSTCBCur = OSTCBHighRdy

    LDR    r6, =OSPrioHighRdy
    LDRB    r6, [r6]
    LDR    r5, =OSPrioCur
    STRB    r6, [r5]                  OSPrioCur = OSPrioHighRdy

    LDR    sp, [r4]
    LDMFD     sp!, {r4}                  pop new task cpsr
    MSR     cpsr_cxsf, r4
    LDMFD     sp!, {r0-r12,lr,pc}          pop new task r0-r12,lr & pc

OSIntCtxSw是OSCtxSw的一部分。

(3) OSIntCtxSw()
OSIntExit()通过调用OSintCtxSw(),在ISR中执行任务切换功能。

示意性代码:
void OSIntCtxSw(void)
{
    调用用户定义的OSTaskSwHook();
    OSTCBCur = OSTCBHIGHRdy;
    OSPrioCur = OSPrioHighRdy;
    得到将要重新执行的任务的堆栈指针:
    Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
    从新任务堆栈中恢复所有处理器寄存器;
    执行中断返回指令;
}

汇编代码:
在上面已经实现。

(4) OSTickISR()
时钟节拍中断服务例程。

示意性代码:
void OSTickISR(void)
{
    保存处理器的寄存器;
    调用OSIntEnter()或者直接给OSIntNesting加1;
    if (OSIntNesting == 1)
    {
        OSTCBCur->OSTCBStkPtr = Stack Pointer;
    }
    给产生中断的设备清中断;
    重新允许中断(可选);
    OSTimeTick();
    OSIntExit();
    恢复处理器寄存器;
    执行中断返回指令;
}

汇编代码:
    EXPORT     OSTickISR
    IMPORT    OSIntEnter
    IMPORT    OSTimeTick
    IMPORT    tick_hook    
    IMPORT    OSIntExit

LINK_SAVE    DCD        0
PSR_SAVE    DCD        0

OSTickISR
    STMFD    sp!, {r4}        这个SP是IRQ模式下的!
    
    LDR        r4, =LINK_SAVE
    STR        lr, [r4]                      LINK_SAVE = lr_irq

    MRS        lr,    spsr
    STR        lr, [r4, #4]              PSR_SAVE = spsr_irq
    
    LDMFD    sp!, {r4}                                 只好重新恢复R4
        
    ORR        lr, lr,    #0x80              Mask irq for context switching before 
    MSR        cpsr_cxsf, lr               returning back from irq mode.我们还没有
                                                          保存好现场,如果打开中断,就有可能发生新的
                                                          抢占式调度,于是这个现场就OVER了。现场保
                                                          护和现场恢复都要一气呵成。

    SUB        sp, sp, #4                  Space for PC
    STMFD    sp!, {r0-r12, lr}

    LDR        r4, =LINK_SAVE
    LDR        lr, [r4, #0]
    SUB        lr, lr, #4                  PC = LINK_SAVE - 4,
    STR        lr, [sp, #(14*4)]          SAVE PC [..]the return address for pc.

    LDR        r4, [r4, #4]              r4 = PSR_SAVE,
    STMFD    sp!, {r4}                          CPSR of the task
 
    LDR        r4, =OSTCBCur
    LDR        r4, [r4]
    STR        sp, [r4]                  OSTCBCur -> stkptr = sp  保存现场完毕

    BL    OSIntEnter
    BL     OSTimeTick
    BL    tick_hook                                 我们在Tick_hook()里清除S3C44B0x的Tick_Int_Pend位,这个
                                                          函数在main.c里,是另加的.
    BL    OSIntExit                                

    LDMFD     sp!, {r4}                                 pop current task cpsr
    MSR     cpsr_cxsf, r4
    LDMFD     sp!, {r0-r12,lr,pc}                       pop current task r0-r12,lr & pc

特别感谢:
       uCOS-II在 S3C44B0x 系统上的移置 Arming
       (实际上这个版本就是他移植好的)

参考文献:
       嵌入式实时操作系统uc/os-II    Jean J.Labrosse
文章录入:fengfeiyi    责任编辑:fengfeiyi 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
  • uC/OS-II 初级程序员指南

  • μC/OS-II的实时性能分析

  • uC/OS-II任务栈处理的一种改…

  • μC/OSII中的时钟中断技术研…

  • uC/OS-Ⅱ在C167CR单片机上的…

  • 基于uC/OS-II的变频器变结构…

  • μC/OS-II在AT89C51上的移植

  • 嵌人式实时操作系统uC/OS在…

  • uC/OS开发方法

  • uc/os 任务调度机制

  •   网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)