📄 os_cpu_c.c
字号:
/*
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 + -