DSPIC30F6014A移植UCOS中的os_cpu_a.s的理解

来源:互联网 发布:矛盾论读后感知乎 编辑:程序博客网 时间:2024/05/16 10:13

; This file is part of "uC/OS-II port to dsPIC30 microcontroller"

; Copyright (C) 2004 Zoran Bosnjak <zoran.bosnjak at trio-b.si>

; This program is free software; you can redistribute it and/or

; modify it under the terms of the GNU General Public License

; as published by the Free Software Foundation; either version 2

; of the License, or (at your option) any later version.

; This program is distributed in the hope that it will be useful,

; but WITHOUT ANY WARRANTY; without even the implied warranty of

; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

; GNU General Public License for more details.

;

; You should have received a copy of the GNU General Public License

; along with this program; if not, write to the Free Software

; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 

; assembler part of dsPIC30 port

 

    .equ __30F6014, 1

    .include "p30f6014a.inc"

 

         .text

        

; save registers to curent stack (MACRO)

.macro save_regs

         push.d w0   ; w0 + w1   

       push.d w2

         push.d w4

         push.d w6

         push.d w8

         push.d w10

         push.d w12

         push w14    ; don't push w15 (this is actual stack pointer)!!

 

         push ACCAL

         push ACCAH

         push ACCAU

         push ACCBL

         push ACCBH

         push ACCBU

         push TBLPAG

         push PSVPAG

         push RCOUNT

         push DCOUNT

         push DOSTARTL

         push DOSTARTH

         push DOENDL

         push DOENDH

        

         push SR

         push CORCON

        

.endm

 

; restore registers from the stack (MACRO)

.macro restore_regs

 

    pop CORCON

    pop SR

 

    pop DOENDH

    pop DOENDL

    pop DOSTARTH

    pop DOSTARTL

    pop DCOUNT

    pop RCOUNT

    pop PSVPAG

    pop TBLPAG

    pop ACCBU

    pop ACCBH

    pop ACCBL

    pop ACCAU

    pop ACCAH

    pop ACCAL

 

    pop w14     ; don't pop w15!!

    pop.d w12

    pop.d w10

    pop.d w8

    pop.d w6

    pop.d w4

    pop.d w2

    pop.d w0

.endm

 

; -------------------------------------------

         .global _OSStartHighRdy

_OSStartHighRdy://此函数就是恢复OSTCBHighRdy的任务的现场

         call _OSTaskSwHook                ; call user definable hook

 

         ; set OSRunning to TRUE

         mov #0x0001, w0

         mov.b wreg, _OSRunning

         ; get stack pointer of the task to resume//OSTCBHighRdy指向的是优先级最高的任务的任务控制块

         mov _OSTCBHighRdy, w0                  //要想恢复的任务堆栈指针总是储存在OS_TCB的0偏址内存单元中

         mov [w0], w15       //堆栈指针指向将要运行的任务堆栈地址

         restore_regs            //将所有处理器寄存器从新任务的堆栈中恢复出来;

         retfie //由于是模拟的中断,必须使用中断返回指令,才能PC,SRL(处理器状态寄存器的低字节),IPL3(CORCON<3>)

//W15所指向的地址顺序是_OSCtxSw:中相反的顺序,先restore_regs,retfie

; -------------------------------------------

; context switch and interrupt context switch

; share some code (last part of the function is the same)

         .global _OSCtxSw

    .global _OSIntCtxSw

_OSCtxSw:

    ; TRAP (interrupt) should bring us here, not 'call'.

; Since dsPIC has no TRAP, correct stack to simulate interrupt.

//这句话的意思是:由于dsPIC没有陷阱(dspic30f有陷阱,没有自定义的软件陷阱),正确的操作堆栈的方法是模拟中断。

//为什么要模拟中断呢?

//因为在UCOSII中,任务级的切换问题是通过发软中断命令或依靠处理器执行陷阱指令来完成的。中断服务例程,陷阱或

//异常处理例程的向量地址必须指向OSCtxSw()。

; That means to save also SR and IPL3 to the stack, not just PC.

//中断处理时,保存:PC,SRL(处理器状态寄存器的低字节),IPL3(CORCON<3>)

    mov.b SRL, wreg     ; load SRL

    sl w0, #8, w0       ; shift left by 8

    btsc CORCON, #IPL3  ; test IPL3 bit, skip if clear

    bset w0, #7;        ; ... (copy IPL3 to bit7 of w0)

   

    ior w0, [--w15], w0    ; merge bits

mov w0, [w15++]     ; write back

//以上部分是模拟的中断入栈的部分,为使用retfie(中断返回指令)做准备

//以下是保存CPU的相关寄存器的内容

         save_regs                        ; save processor registers

         ; save current task's stack pointer  into the current task's OS_TCB

         mov _OSTCBCur, w0      ; get index

         mov w15, [w0]                 //将W15的内容传送到_OSTCBCur,保存当前任务的堆栈指针到当前任务的控制块OS_TCB中。

         ; go on with OSIntCtxSw

 

_OSIntCtxSw:

         call _OSTaskSwHook       ; call hook,调用钩子函数

 

    ; set high prio. task to current

    mov _OSTCBHighRdy, w1

    mov w1, _OSTCBCur                  //设置高优先级的任务为当前任务

    mov.b _OSPrioHighRdy, wreg       

    mov.b wreg, _OSPrioCur      //设置高优先级的任务的优先级为当前的优先级

   

    ; get new stack pointer

    mov [w1], w15   ; stack pointer from OSTCBHighRdy

    restore_regs     ; restore registers    

         retfie                     ; return from interrupt

//由于是模拟的中断,必须使用中断返回指令,才能PC,SRL(处理器状态寄存器的低字节),IPL3(CORCON<3>)

//W15所指向的地址,顺序是_OSCtxSw:中相反的顺序,先restore_regs,retfie

; -------------------------------------------

; tick interrupt handler

    .global __T1Interrupt

__T1Interrupt:

         save_regs                                 ; save processor registers

        

         inc.b _OSIntNesting                   ; Call OSIntEnter() or increment OSIntNesting

        

         ; if OSIntNesting==1, save stack pointer

    dec.b _OSIntNesting, wreg

    bra nz, 1f

    mov _OSTCBCur, w0

    mov w15, [w0]   

1:

   

    BCLR.b IFS0, #T1IF                   ; clear int. device

 

    ; re-enable interrupts

    ; this should be on by default ??

   

    call _OSTimeTick               //调用OSTimeTick();

    call _OSIntExit

   

    restore_regs                        ; restore registers

 

         retfie                              ; return from interrupt

 


原创粉丝点击