📄 os_cpu_c.c
字号:
// Get the stack pointer of the task to resume
$SP = (OS_REGS *)OSTCBHighRdy->OSTCBStkPtr;
OSTCBCur = OSTCBHighRdy;
OSPrioCur = OSPrioHighRdy;
// Execute return from interrupt;
RFI();
}
#if OS_CPU_HOOKS_EN
/*
*********************************************************************************************************
* TASK CREATION HOOK
*
* Description: This function is called when a task is created.
*
* Arguments : ptcb is a pointer to the task control block of the task being created.
*
* Note(s) : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
void OSTaskCreateHook (OS_TCB *ptcb)
{
ptcb = ptcb; /* Prevent compiler warning */
}
/*
*********************************************************************************************************
* TASK DELETION HOOK
*
* Description: This function is called when a task is deleted.
*
* Arguments : ptcb is a pointer to the task control block of the task being deleted.
*
* Note(s) : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
void OSTaskDelHook (OS_TCB *ptcb)
{
ptcb = ptcb; /* Prevent compiler warning */
}
/*
*********************************************************************************************************
* TASK SWITCH HOOK
*
* Description: This function is called when a task switch is performed. This allows you to perform other
* operations during a context switch.
*
* Arguments : none
*
* Note(s) : 1) Interrupts are disabled during this call.
* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
* task being switched out (i.e. the preempted task).
*********************************************************************************************************
*/
void OSTaskSwHook (void)
{
}
/*
*********************************************************************************************************
* STATISTIC TASK HOOK
*
* Description: This function is called every second by uC/OS-II's statistics task. This allows your
* application to add functionality to the statistics task.
*
* Arguments : none
*********************************************************************************************************
*/
void OSTaskStatHook (void)
{
}
/*
*********************************************************************************************************
* TICK HOOK
*
* Description: This function is called every tick.
*
* Arguments : none
*
* Note(s) : 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************
*/
void OSTimeTickHook (void)
{
}
#if OS_VERSION >= 204
void OSInitHookBegin(void)
{
}
void OSInitHookEnd(void)
{
}
void OSTCBInitHook(OS_TCB *ptcb)
{
}
#endif
#if OS_VERSION >= 251
void OSTaskIdleHook(void)
{
}
#endif
#endif
void (*OSDispatcher)(INT32U, INT32U)
__attribute__ ((section (".data"))) = IRQDispatch;
void OSInterruptHandler(void)
__attribute__ ((naked, section (".interrupt")));
void OSInterruptHandler(void)
{
register INT32U cause, sr;
// Get the address of the interrupted context
__asm__ volatile ("mfc0 $kt0,$14");
// Allocate space on the stack to save all the
// registers
$SP--;
SAVE_ALL();
// Get the cause register to figure out what type of interrupt
// we have
__asm__ volatile
(".set noreorder \n"
"mfc0 %0,$13 \n" /* Cause reg */
"mfc0 %1,$12 \n" /* Status reg */
"sw $kt0,%2($sp) \n" /* Save exception address */
".set reorder "
: "=d"(cause), "=d"(sr)
: "I"(offsetof(OS_REGS, reg_pc)));
(*OSDispatcher)(cause, sr);
}
void OSCtxSw(void) __attribute__((naked));
void OSCtxSw(void)
{
register INT32U $RA __asm__("$31");
// Allocate space on the stack to save all the
// registers
$SP--;
$SP->reg_pc = $RA;
// We only need to save the non volatile registers because
// we come here through a normal function call.
SAVE_NON_VOLATILE();
// Save the current stack pointer
OSTCBCur->OSTCBStkPtr = (OS_STK *)$SP;
// Call use definable
OSTaskSwHook();
OSTCBCur = OSTCBHighRdy;
OSPrioCur = OSPrioHighRdy;
__asm__ volatile ("mfc0 $kt0,$12");
$SP = (OS_REGS *)OSTCBHighRdy->OSTCBStkPtr;
__asm__ volatile
("ori $kt0,$kt0,4 \n"
"mtc0 $kt0,$12 ");
// Return from interrupt
RFI();
}
/*********************/
/* Interrupt support */
/*********************/
#define MAXINTERRUPTS 8
FUNC IRQVector[MAXINTERRUPTS];
static void IRQEnable(int IRQNum)
{
register INT32U tmp;
register INT32U mask;
// The IntMask field is at offset 8, but the
// first 2 bits are for the Software interrupts
mask = (1<<(8+IRQNum))+1;
__asm__ volatile
("mfc0 %0,$12 \n"
"nop \n"
"or %0,%1,%2 \n"
"mtc0 %1,$12 \n"
: "=d"(tmp)
: "d"(tmp), "d"(mask));
}
FUNC IRQInstall(int IRQNum, FUNC ISRFun)
{
FUNC OldISR;
if (IRQNum < 0 || IRQNum >= MAXINTERRUPTS)
return((FUNC)0);
/* Get old ISR function */
OldISR = IRQVector[IRQNum];
/* Replace with new ISR function */
IRQVector[IRQNum] = ISRFun;
/* Enable the interrupt */
IRQEnable(IRQNum);
return(OldISR);
}
void IRQDispatch(INT32U exc_cause, INT32U exc_sr)
{
INT32U Mask = SR_IBIT8;
INT32U Status,imask;
int IRQNum = 7;
OSIntNesting++;
if (OSIntNesting == 1)
{
OSTCBCur->OSTCBStkPtr = (OS_STK *)$SP;
}
Status = exc_cause & exc_sr & SR_IMASK;
while (IRQNum >= 0) {
if (Status & Mask) {
if (IRQVector[IRQNum])
(*(IRQVector[IRQNum]))();
else
;/* spurious interrupt */
break;
}
Mask = Mask >> 1;
IRQNum--;
}
OSIntExit();
// Return from interrupt
RFI();
}
OS_CPU_SR disable_ints()
{
register OS_CPU_SR sr, sr_off;
sr = GET_SR();
sr_off = sr & 0xfffffffe;
SET_SR(sr_off);
return (sr);
}
void enable_ints(OS_CPU_SR cpu_sr)
{
register OS_CPU_SR sr;
sr = GET_SR();
cpu_sr &= 0x00000001;
sr |= cpu_sr;
SET_SR(sr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -