3599|2

24

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

OSCtxsw第二次出栈错误 [复制链接]

为了方便,我直接贴上代码:
.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任务???

最新回复

难道是传说中的代码  详情 回复 发表于 2011-12-30 11:11
点赞 关注

回复
举报

1018

帖子

0

TA的资源

纯净的硅(中级)

沙发
 
难道是传说中的代码
 
个人签名android培训
 

回复

24

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

应用程序是我自己修改过,

只创建一个任务
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表