为了方便,我直接贴上代码: .S如下 ;******************************************************************************************************** ; uC/OS-II ; The Real-Time Kernel ; ; (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL ; All Rights Reserved ; ; ARM7 LPC21XX Specific code ; ARM mode ; ; keil4 for arm 4.14 ; ; File : OS_CPU_A.S ; By : CH314156 (QQ:358687720) ;********************************************************************************************************
Mode_USR EQU 0x10 Mode_FIQ EQU 0x11 Mode_IRQ EQU 0x12 Mode_SVC EQU 0x13 Mode_ABT EQU 0x17 Mode_UND EQU 0x1B Mode_SYS EQU 0x1F I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled T0IR EQU 0xE0004000 VICVectAddr EQU 0xFFFFF030
EXPORT SaveCpsr EXPORT RestoreCpsr EXPORT OSTickISR EXPORT OSCtxSw EXPORT OSIntCtxSw EXPORT OSStartHighRdy IMPORT OSIntEnter IMPORT OSIntExit IMPORT OSTimeTick IMPORT OSTaskSwHook IMPORT OSPrioHighRdy IMPORT OSPrioCur IMPORT OSRunning IMPORT OSTCBCur IMPORT OSTCBHighRdy IMPORT OSIntNesting PRESERVE8 AREA ABC,CODE,READONLY
SaveCpsr MRS R0,CPSR ORR R1,R0,#I_Bit :OR: F_Bit MSR CPSR_c,R1 BX LR
RestoreCpsr MSR CPSR_c,R0 BX LR
OSStartHighRdy BL OSTaskSwHook ;OSTaskSwHook() LDR R0,=OSRunning ;OSRunning = 1; MOV R1,#1 STRB R1,[R0] LDR R0,=OSTCBHighRdy ;SP = OSTCBHighRdy -> ptask LDR R0,[R0] LDR SP,[R0] LDMFD SP!,{R0} ;恢复任务 BIC R0,#I_Bit:OR:F_Bit MSR SPSR_c,R0 LDMFD SP!,{R0-R12,LR,PC}^ OSCtxSw STMFD SP!,{LR} ;保存任务(上一任务的PC) 有问题:第一次进入时R0为1第二次为3 SUB SP,#4 STMFD SP!,{R0-R12,LR} ;{R0-R12} 2011-12-27 按照压栈顺序,这样出栈{R0-R12}有问题 MRS R0,CPSR ;保存CPSR STMFD SP!,{R0} MRS R0,SPSR ;保存SPSR STMFD SP!,{R0} LDR R0,=OSTCBCur ;OSTCBCur -> ptask = SP LDR R0,[R0] STR SP,[R0] OSIntCtxSw BL OSTaskSwHook LDR R0,=OSTCBCur ;OSTCBCur = OSTCBHighRdy LDR R1,=OSTCBHighRdy LDR R1,[R1] STR R1,[R0] LDR R0,=OSPrioCur ;OSPrioCur = OSPrioHighRdy LDR R1,=OSPrioHighRdy LDRB R1,[R1] STRB R1,[R0] LDR R0,=OSTCBHighRdy ;SP = OSTCBHighRdy -> ptask 指向最高级优先级就绪任务控制块的指针 LDR R0,[R0] LDR SP,[R0] LDMFD SP!,{R0} ;恢复任务 有问题:第一次调用时R0为00000013第二次为4000002C BIC R0,#I_Bit:OR:F_Bit MSR SPSR_fc,R0 LDMFD SP!,{R0-R12,LR,PC}^
OSTickISR STMFD SP!,{R0-R2} ;保存任务 MRS R0,SPSR ;R0 R1 R2 先保存在IRQ模式的堆栈里 SUB R1,LR,#4 ;然后R0 R1 R2 分别传递 CPSR LR_irq SP_irq MOV R2,SP ADD SP,#3*4 ;还原SP_irq MSR CPSR_c,#Mode_SVC:OR:I_Bit:OR:F_Bit ;切到管理模式 STMFD SP!,{R1} ;陆续保存所有寄存器 STMFD SP!,{LR} STMFD SP!,{R3-R12} LDMFD R2!,{R3-R5} STMFD SP!,{R3-R5} STMFD SP!,{R0} BL OSIntEnter LDR R0,=OSIntNesting LDR R1,[R0] CMP R1,#1 BNE OSTickISR_1 LDR R0,=OSTCBCur ;OSTCBCur -> ptask = SP LDR R0,[R0] STR SP,[R0] OSTickISR_1 LDR R0,=T0IR ;T0IR |= 1 清中断标志 LDRB R0,[R0] ORR R0,#1 LDR R1,=T0IR STRB R0,[R1] MOV R0,#0 ;VICVectAddr = 0 通知VIC 中断已结束 LDR R1,=VICVectAddr STR R0,[R1] BL OSTimeTick BL OSIntExit LDMFD SP!,{R0} ;恢复任务 BIC R0,#I_Bit:OR:F_Bit MSR SPSR_fc,R0 LDMFD SP!,{R0-R12,LR,PC}^
END ============================= .C如下 /* ********************************************************************************************************* * 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(). * (see uCOS_II.H for OS_TASK_OPT_???). * * 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. * * Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the * PSW to 0x0002 instead. In this case, interrupts would be disabled upon task startup. The * application code would be responsible for enabling interrupts at the beginning of the task * code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable * interrupts. Failure to do this will make your system crash! ********************************************************************************************************* */ #define OS_CPU_GLOBALS #define Mode_SVC 0x13 #include "ucos_ii.h" OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) { OS_STK *stk = ptos; //软件指针 opt = opt; *--stk = (INT32U)task; //PC *--stk = 0x00000014; //LR *--stk = 0x00000012; //R12 *--stk = 0x00000011; //R11 *--stk = 0x00000010; //R10 *--stk = 0x00000009; //R9 *--stk = 0x00000008; //R8 *--stk = 0x00000007; //R7 *--stk = 0x00000006; //R6 *--stk = 0x00000005; //R5 *--stk = 0x00000004; //R4 *--stk = 0x00000003; //R3 *--stk = 0x00000002; //R2 *--stk = 0x00000001; //R1 *--stk = (INT32U)pdata; //R0 *--stk = Mode_SVC; //CPSR return ((OS_STK *)stk); }
#if OS_CPU_HOOKS_EN //使能钩子功能
void OSTaskCreateHook (OS_TCB *ptcb) { ptcb = ptcb; /* Prevent compiler warning */ }
void OSTaskDelHook (OS_TCB *ptcb) { ptcb = ptcb; /* Prevent compiler warning */ }
#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) void OSTaskSwHook (void) { #if OS_VIEW_MODULE > 0 OSView_TaskSwHook(); #endif } #endif
void OSTaskIdleHook(void) { ///* printf("This is Idletask.\n"); //printf("OSIdleCtr is %ld\n",OSIdleCtr); */ } void OSTaskStatHook (void) {
}
void OSTimeTickHook (void) {
}
void OSInitHookBegin(void) {
} void OSInitHookEnd(void) {
}
void OSTCBInitHook(OS_TCB *ptcb) { ptcb=ptcb; }
#endif ============================ 应用程序如下 #define STACK_SIZE 128 OS_STK TaskStartStk[STACK_SIZE]; //定义起始任务堆栈 int main( void ) { AppInit(); //应用程序初始化 OSInit(); //OS初始化 OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[STACK_SIZE - 1], 2); //创建起始任务 OSStart(); //OS开始运行 } void AppInit(void) { PINSEL0=0; IO0DIR=1; }
void TaskStart(void *p_arg) { p_arg=p_arg; Timer0Init(1000); //时钟节拍 while(1) { IO0CLR=1; OSTimeDly(3); IO0SET=1; OSTimeDly(3); } } ====================================== MDK编译、警告为0。问题为:运行到第二个OSTimeDly(3);时正常调用 OSCtxsw,OSCtxsw执行出栈指令后跳到了IRQ中断处,怎么也进入不了IDLE任务???
|