⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu.c

📁 8051单片机的ucos移植
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************
//           uCOS-II 8051 Port
//
//           written by
//
//           Wai Chan
//           Apr. 10 2001
*********************************************************************/

#define OS_CPU_GLOBALS
#include "includes.h"


void *OSTaskStkInit(void *task, void *pdata, void *ptos, INT16U opt);
void OSStartHighRdy();
void OSCtxSw();
void OSIntCtxSw();
void OSSetTickPerSec( INT16U ticks );
void OSSetTimer();
void OSInterruptInit();

#if OS_CPU_HOOKS_EN
void OSTaskCreateHook (OS_TCB *ptcb);
void OSTaskDelHook (OS_TCB *ptcb);
void OSTaskSwHook (void);
void OSTaskStatHook (void);
void OSTimeTickHook (void);

void OSTaskCreateHook (OS_TCB *ptcb)
{
    ptcb = ptcb;
}

void OSTaskDelHook (OS_TCB *ptcb)
{
    ptcb = ptcb;
}

void OSTaskSwHook (void)
{
}

void OSTaskStatHook (void)
{
}

void OSTimeTickHook (void)
{
}
#endif


/* The max ticks per second should be TIMER_TICKS_PER_SECOND */
void OSSetTickPerSec( INT16U ticks )
{
     if ( ticks > TIMER_TICKS_PER_SECOND )
        ticks = TIMER_TICKS_PER_SECOND;

     OSTickFrequency = TIMER_TICKS_PER_SECOND / ticks;
}

void OSSetTimer()
{
    /* Use Timer 0 Mode 0 */
	TCON |= 0x10;
	TMOD |= 0x00;
    OSTickCtr = 0;
}

void OSInterruptInit()
{
    /* for using monitor program, we only enables Time 0 Interrupt */
    IE = 0x82;
}




INTERRUPT(_TF0_) _OSTickISR()
{  

   /* Check the tick frequency */
   OSTickCtr++;

   if ( OSTickCtr < OSTickFrequency )
   {     
      return;
   }

   OSTickCtr = 0;


   asm {
        /* Increment OSIntNesting */
        MOV DPTR,#OSIntNesting 
        MOVX A,[DPTR]
        INC A
        MOVX [DPTR],A
        /* Process system tick */
        LCALL OSTimeTick
        /* Exit from interrupt */
        LCALL OSIntExit
   }

} 


/*****************************************************************************
   We are saving 0x7F-?stk bytes of internal ram onto the external stack.  These bytes
   include the internal stack.  Here is what it looks like in the internal
   stack after the timer interrupt.

          +--------------------+
          |       ARG_LOW      |
          +--------------------+
          |       ARG_High     |
          +--------------------+
          | Reture Address Low |
          +--------------------+
          | Reture Address High|
          +--------------------+
          | Reture Address Low |
          +--------------------+
          | Reture Address High|
          +--------------------+
          |       PSW          |
          +--------------------+
          |       A            |
          +--------------------+
          |       B            |
          +--------------------+
          |       DPH          |
          +--------------------+
          |       DPL          |
          +--------------------+
          |       R0           |
          +--------------------+
          |       R1           |
          +--------------------+
          |       .            |
          +--------------------+
          |       .            |
          +--------------------+
          |       R7           |
          +--------------------+
          |       .            |
          +--------------------+
          |                    |

We are faking the return address bytes to be the task starting address 
*****************************************************************************/

void *OSTaskStkInit(void *task, void *pdata, void *ptos, INT16U opt)
{
    INT8U *stk, i;
    INT16U *address;
    INT8U total_bytes;

    opt = opt;

    asm {
      MOV DPL,#ISTK_START
      MOV DPH,#=ISTK_START
      MOV A,#?stk
      MOVX [DPTR],A
    }

    total_bytes = 0x7F-ISTK_START;

    stk = (INT8U*)ptos;

    /* mark all internal ram to be zero on the external stack */
    for ( i = 0; i < total_bytes; i++ )
    {
        *stk-- = 0;
    }


    /* put argument address on the external stack */
    stk = (INT8U*)ptos;                      
    address = (INT16U*)(stk-total_bytes);
    *address = (INT16U)pdata;


    /* put return address on the external stack to simulate function call
       so tasks can access the arguments on the stack */
    stk = (INT8U*)ptos;                      
    address = (INT16U*)(stk-total_bytes+2);
    *address = (INT16U)task;
         
   /* put return address on the external stack */
   stk = (INT8U*)ptos;
   address = (INT16U*)(stk-total_bytes+4);
   *address = (INT16U)task;

    /* put the internal stack pointer on the external stack */
    stk = (INT8U*)ptos;
    *stk = ISTK_START+19;    /* stack starts at ?stk-1, we've faked 14 register
                                  plus 2 bytes return address and 2 bytes argument.
                                  so totally we have 18 bytes that has been
                                  pushed on the stack */



     /* Fake the initial internal stack pointer postion.
                                   We have 12 general registers plus two bytes of 
                                   return address to be pushed on the stack.
                                   Therefore the stack pointer should be pointing
                                   to the starting position(?stk-1) plus 14 */

   /* return the current stack pointer */
   stk = (INT8U*)ptos;
   return (void*)(stk-total_bytes);
}


void OSStartHighRdy()
{
    asm {
            /* Indicate the multitasking has started */
            MOV DPTR,#OSRunning
            MOVX A,[DPTR]
            INC A
            MOVX [DPTR],A
            /* Call user function */
            LCALL OSTaskSwHook 
            /* get stack pointer */
            MOV DPL,#OSTCBHighRdy
            MOV DPH,#=OSTCBHighRdy 
            MOVX A,[DPTR]
            MOV R0,A,
            INC DPTR
            MOVX A,[DPTR]
            MOV R1,A
            MOV DPL,R0
            MOV DPH,R1
            MOVX A,[DPTR]
            MOV ?stack,A
            INC DPTR,
            MOVX A,[DPTR]
            MOV ?stack+1,A 
            /* pop all internal stack values from external stack back to internal ram */
            MOV B,#0   We have 0x7F-?stk bytes to move starting from low to high
_HCpyIRAM   MOV A,B
            ADD A,#1 
            MOV B,A
            ADD A,#?stk
            MOV R0,A
            MOV A,?stack
            MOV DPL,A
            MOV A,?stack+1
            MOV DPH,A
            MOVX A,[DPTR]
            MOV [R0],A
            MOV A,?stack
            ADD A,#1
            MOV ?stack,A
            MOV A,?stack+1
            ADDC A,#0
            MOV ?stack+1,A
            MOV A,B
            CJNE A,#$7F-?stk,_HCpyIRAM 
            AJMP _HCpyDone
_HCpyDone
            /* pop internal stack pointer */
            MOV A,?stack
            MOV DPL,A
            MOV A,?stack+1
            MOV DPH,A
            MOVX A,[DPTR]
            MOV SP,A
            MOV A,?stack
            ADD A,#1
            MOV ?stack,A
            MOV A,?stack+1
            ADDC A,#0
            MOV ?stack+1,A
            /* now pop all registers from the fake internal stack */                  
            POP 7
            POP 6
            POP 5
            POP 4
            POP 3
            POP 2
            POP 1
            POP 0
            POP DPL
            POP DPH
            POP B
            POP A
            POP PSW
    }
}


void OSCtxSw()
{
    asm {
            PUSH PSW
            PUSH A

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -