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

📄 os_cpu_c.c

📁 mips下的ucos
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
   Copyright (C) 2001, Lexra, Inc.
   Contributed by Pascal Cleve (pascal@lexra.com).

   This code 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.
*/

#define  OS_CPU_GLOBALS
#include "includes.h"
#include <stdlib.h>

/*
*********************************************************************************************************
*                                        INITIALIZE A TASK'S STACK
*
* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
*              stack frame of the task being created.  This function is highly processor specific.
*
* Arguments  : task          is a pointer to the task code
*
*              pdata         is a pointer to a user supplied data area that will be passed to the task
*                            when the task first executes.
*
*              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
*                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then
*                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
*                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
*                            of the stack.
*
*              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
*
*
* Returns    : Always returns the location of the new top-of-stack' once the processor registers have
*              been placed on the stack in the proper order.
*
*********************************************************************************************************
*/

// Keep pair of register for easy save /restore on machines with 
// load/store twin.  Also make sure the stack always stays 8-byte
// aligned.

typedef struct {
  volatile INT32U reg_2;	volatile INT32U reg_3;
  volatile INT32U reg_4;	volatile INT32U reg_5;
  volatile INT32U reg_6;	volatile INT32U reg_7;
  volatile INT32U reg_8;	volatile INT32U reg_9;
  volatile INT32U reg_10;	volatile INT32U reg_11;
  volatile INT32U reg_12;	volatile INT32U reg_13;
  volatile INT32U reg_14;	volatile INT32U reg_15;
  volatile INT32U reg_16;	volatile INT32U reg_17;
  volatile INT32U reg_18;	volatile INT32U reg_19;
  volatile INT32U reg_20;	volatile INT32U reg_21;
  volatile INT32U reg_22;	volatile INT32U reg_23;
  volatile INT32U reg_24;	volatile INT32U reg_25;
  volatile INT32U reg_30;	volatile INT32U reg_31;

  volatile INT32U reg_at;	volatile INT32U reg_pc;
  volatile INT32U reg_hi;       volatile INT32U reg_lo;
  
#if defined(PROCESSOR_lx5180) || defined(PROCESSOR_lx5280)
  // Radiax registers
  // to be provided later
#endif
} OS_REGS;


// Map the $sp register to a register variable.  $SP is 
// used to point to the top of stack where all the 
// registers are saved.

register OS_REGS *$SP __asm__("$sp");

#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
#define SAVE(reg)                                       \
  __asm__ volatile (".set 	noat		\n"	\
                    "sw		$"#reg",%0($sp)	\n"     \
                    ".set 	at"                     \
                    :                                   \
                    : "I"(offsetof(OS_REGS, reg_ ## reg)))

#define RESTORE(reg) 					\
  __asm__ volatile (".set 	noat		\n"     \
                    "lw		$"#reg",%0($sp)	\n"  	\
                    ".set 	at"                   	\
                    :                         		\
                    : "I"(offsetof(OS_REGS, reg_ ## reg)))


#if defined(PROCESSOR_lx5180) || defined(PROCESSOR_lx5280)
#define SAVE_TWIN(reg)                                  \
  __asm__ volatile (".set 	noat		\n"	\
                    "st		$"#reg",%0($sp)	\n"     \
                    ".set 	at"                     \
                    :                                   \
                    : "I"(offsetof(OS_REGS, reg_ ## reg)))

#define RESTORE_TWIN(reg) 				\
  __asm__ volatile (".set 	noat		\n"     \
                    "lt		$"#reg",%0($sp)	\n"  	\
                    ".set 	at"                   	\
                    :                         		\
                    : "I"(offsetof(OS_REGS, reg_ ## reg)))
#endif


#define SAVE_hilo()					\
  __asm__ volatile ("mfhi	$2		\n"	\
		    "mflo	$3		\n"	\
		    "sw		$2,%0($sp)	\n"	\
		    "sw		$3,%1($sp)	\n"	\
		    : : "I"(offsetof(OS_REGS, reg_hi)), \
		        "I"(offsetof(OS_REGS, reg_lo)))

#define RESTORE_hilo()					\
  __asm__ volatile ("lw		$2,%0($sp)	\n"	\
		    "lw		$3,%1($sp)	\n"	\
                    "mthi	$2		\n"	\
		    "mtlo	$3		\n"	\
		    : : "I"(offsetof(OS_REGS, reg_hi)),	\
		        "I"(offsetof(OS_REGS, reg_lo)))

#if defined(SAVE_TWIN)
#define SAVE_NON_VOLATILE() \
  SAVE_TWIN(30);\
  SAVE_TWIN(22);\
  SAVE_TWIN(20);\
  SAVE_TWIN(18);\
  SAVE_TWIN(16);

#define SAVE_ALL() \
  SAVE_NON_VOLATILE();	 \
  SAVE_TWIN(24);\
  SAVE_TWIN(14);\
  SAVE_TWIN(12);\
  SAVE_TWIN(10);\
  SAVE_TWIN(8);\
  SAVE_TWIN(6);\
  SAVE_TWIN(4);\
  SAVE_TWIN(2);\
  SAVE(at);\
  SAVE_hilo();

#else
#define SAVE_NON_VOLATILE() \
  SAVE(31);	SAVE(30);\
  SAVE(23);	SAVE(22);\
  SAVE(21);	SAVE(20);\
  SAVE(19);	SAVE(18);\
  SAVE(17);	SAVE(16);

#define SAVE_ALL() \
  SAVE_NON_VOLATILE();	 \
  SAVE(25);	SAVE(24);\
  SAVE(15);	SAVE(14);\
  SAVE(13);	SAVE(12);\
  SAVE(11);	SAVE(10);\
  SAVE(9);	SAVE(8);\
  SAVE(7);	SAVE(6);\
  SAVE(5);	SAVE(4);\
  SAVE(3);	SAVE(2);\
  SAVE(at);\
  SAVE_hilo();
#endif /* defined(SAVE_TWIN)	*/

#if defined(RESTORE_TWIN)
#define RESTORE_ALL()\
  RESTORE_hilo();\
  RESTORE_TWIN(30);\
  RESTORE_TWIN(24);\
  RESTORE_TWIN(22);\
  RESTORE_TWIN(20);\
  RESTORE_TWIN(18);\
  RESTORE_TWIN(16);\
  RESTORE_TWIN(14);\
  RESTORE_TWIN(12);\
  RESTORE_TWIN(10);\
  RESTORE_TWIN(8);\
  RESTORE_TWIN(6);\
  RESTORE_TWIN(4);\
  RESTORE_TWIN(2);\
  RESTORE(at);
#else
#define RESTORE_ALL()\
  RESTORE_hilo();\
  RESTORE(31);	RESTORE(30);\
  RESTORE(25);  RESTORE(24);\
  RESTORE(23);  RESTORE(22);\
  RESTORE(21);  RESTORE(20);\
  RESTORE(19);  RESTORE(18);\
  RESTORE(17);  RESTORE(16);\
  RESTORE(15);  RESTORE(14);\
  RESTORE(13);  RESTORE(12);\
  RESTORE(11);  RESTORE(10);\
  RESTORE(9);   RESTORE(8);\
  RESTORE(7);   RESTORE(6);\
  RESTORE(5);   RESTORE(4);\
  RESTORE(3);   RESTORE(2);\
  RESTORE(at);
#endif /* defined(RESTORE_TWIN)	*/

#define GET_SR()   ({INT32U sr;  __asm__ volatile ("mfc0 %0,$12\nnop" : "=d"(sr)); (sr);})
#define SET_SR(sr) ({__asm__ volatile ("mtc0 %0,$12\nnop" : : "d"(sr));})
 
#define RFI()                                   \
  RESTORE_ALL();	       			\
  {						\
    register INT32U $KT0 __asm__ ("$26");	\
    $KT0 = $SP->reg_pc;				\
    $SP++;				        \
    __asm__ volatile 				\
      (".set       noreorder			\n"\
       "jr         $kt0			        \n"\
       " rfe   		 			\n"\
       ".set       reorder			"\
       : : "d"($SP), "d"($KT0));		\
  }


OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
    OS_REGS *stk;

    stk = (OS_REGS *)ptos;
    stk--; // Allocate space

    stk->reg_pc = (INT32U)task;
    
    stk->reg_at = 0xdeadbeef;
    stk->reg_2 = 0xdeadbeef;
    stk->reg_3 = 0xdeadbeef;
    stk->reg_4 = (INT32U)pdata;
    stk->reg_5 = 0xdeadbeef;
    stk->reg_6 = 0xdeadbeef;
    stk->reg_7 = 0xdeadbeef;
    stk->reg_8 = 0xdeadbeef;
    stk->reg_9 = 0xdeadbeef;
    stk->reg_10 = 0xdeadbeef;
    stk->reg_11 = 0xdeadbeef;
    stk->reg_12 = 0xdeadbeef;
    stk->reg_13 = 0xdeadbeef;
    stk->reg_14 = 0xdeadbeef;
    stk->reg_15 = 0xdeadbeef;
    stk->reg_16 = 0xdeadbeef;
    stk->reg_17 = 0xdeadbeef;
    stk->reg_18 = 0xdeadbeef;
    stk->reg_19 = 0xdeadbeef;
    stk->reg_20 = 0xdeadbeef;
    stk->reg_21 = 0xdeadbeef;
    stk->reg_22 = 0xdeadbeef;
    stk->reg_23 = 0xdeadbeef;
    stk->reg_24 = 0xdeadbeef;
    stk->reg_25 = 0xdeadbeef;
    stk->reg_30 = 0xdeadbeef;
    stk->reg_31 = (INT32U)task;;

    return ((OS_STK *)stk);
}

// Forward declaration
static void IRQDispatch(INT32U exc_cause, INT32U exc_sr) __attribute__((naked));

void OSStartHighRdy(void) __attribute__((naked));
void OSStartHighRdy(void)
{
  // Call user definable
  OSTaskSwHook();

  // Get the stack pointer of the task to resume
  $SP = (OS_REGS *)OSTCBHighRdy->OSTCBStkPtr;

  OSRunning = TRUE;

  // Return from interrupt
  RFI();
}


void OSIntCtxSw(void) __attribute__((naked));
void OSIntCtxSw(void)
{
  // Call user-definable
  OSTaskSwHook();

⌨️ 快捷键说明

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