这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 44B0X,uc,os 请教:44B0X在跑uc/os时,硬件连续两次重新启动的

共2条 1/1 1 跳转至

44B0X,uc,os 请教:44B0X在跑uc/os时,硬件连续两次重新启动的问题

院士
2006-09-17 18:14:16     打赏
44B0X,uc,os 请教:44B0X在跑uc/os时,硬件连续两次重新启动的问题



关键词: 44B0X     请教     在跑     硬件     连续     两次     重新         

院士
2006-12-22 22:43:00     打赏
2楼
44B0X在跑uc/os时,硬件连续两次重新启动的疑惑

问题描述:

44B0X开发板在移植好uc/os-ii之后,我创建了两个任务task1和task2,优先级分别为0和1。

其中,main函数从串口输出字符串“uc/os is running”

task1从串口输出字符串“task1”之后,被挂起1个时钟节拍,task2从串口输出字符串“task2”后,被挂起1个时钟节拍。

空闲任务idletask中,我在其hook函数中添加了从串口输出字符串“idletask”的代码。

系统以RTC的中断为系统的时钟节拍中断,禁用FIQ,使用IRQ,非矢量中断模式,时钟节拍数为每秒1个。


运行时,从串口检测到输入信息如下:

uc/os is running
task1                     //首先运行task1,该输出正常
task2                     //task1被挂起后,task2工作,该输出正常
idletask                  //task1和task2均被挂起,于是os运行空闲任务,该输出正常
idletask
idletask
task1                     //第一个时钟中断来临,OS进行一次任务调度,于是运行task1,输出字符串后task1被挂起
task2                    

uc/os is running         //系统重新启动,我在44binit.s中的reset入口地址开始处加了蜂鸣器开启的指令,能证明PC重新从0X0启动
task1
task2
idletask
idletask
idletask
task1                    //和第一次运行一样
task2

uc/os is running         //系统重新启动,我在44binit.s中的reset入口地址开始处加了蜂鸣器开启的指令,能证明PC重新从0X0启动
task1
task2
idletask        //之后一直运行空闲任务,task1、task2都不再被调度了....
idletask
idletask
idletask
idletask
idletask
idletask
idletask
idletask
idletask
idletask
idletask
...

这个问题困扰我好几天了,请教高人,指点一下在下,谢谢。 1: 唉,高手好象都很忙自己顶一下,希望有高手点拨一下,这个问题困扰我一个星期多了,

在第2个时钟节拍中断到来之前,我关掉全局中断,但执行到了task2中的OSTimeDly(1)语句后板子又重新启动....

2: 上代码,请高手看看,尤其是中断安装代码,谢谢//1 main.c代码


#include "..\inc\option.h"
#include "..\inc\def.h"
#include "..\inc\44b.h"
#include "..\inc\44blib.h"

#include "..\mylcd\lcd320.h"
#include "..\myip\hardware.h"

#include "..\ucos\includes.h"


#define IRQ_VECTOR_OFFSET    (0x18)

#define  RTC_OR_TIME0 0

volatile static int isrCount = 0;        // tick counter


//中断向量的安装
unsigned int ISR_Install(unsigned int offset, void *pf_ISR)
{
    unsigned int pOldEntry;

    // _ISR_STARTADDRESS :0x7ffff00
    offset += _ISR_STARTADDRESS;   //offset = HandleIRQ(0x7ffff18)

    // 旧的中断服务的入口地址
    pOldEntry = *((unsigned int *)offset); //
    
    //将OSTICKISR的入口地址赋给offset所指向的内容
    *((unsigned int *)offset) = (unsigned int)pf_ISR;  
    
    return pOldEntry;
}

#if  RTC_OR_TIME0  //tick中断切换,为1则选择RTC中断,为0则选择timer0中断
//tick初始化,设置tick中断,使能tick中断服务
void tick_init(unsigned char div)
{
    rRTCCON = (unsigned char)1; //RTC读写使能,1/32768,不复位

    rTICNT = (unsigned char)(div | 0x80); //tick = 0x80/div

    rRTCCON = (unsigned char)0;  //禁止读写RTC

    rI_ISPC = (unsigned int)(0x01 << 20);  //清除TICNT的pending
    
    rINTMSK &= (unsigned int)(~(0x01 << 20));  //允许TICNT的中断服务
}


void tick_hook(void)   //清除中断请求标志,OSTickISR调用                      
{
    rI_ISPC =((unsigned int)1) << 20;    
    isrCount++;        
}

#else

//保证div
void tick_init(unsigned char div)
{
    
    rTCFG0=0x00f;            //Timer0,死区时间长度为0,预分频值为0x0f
    rTCFG1=0x04;            //中断模式,mux=1/32
    rTCNTB0=(U16) 250 * div;//tick_cyc = div * (250*1/(60 000/15/32)) = 2 * div ms
    rTCON=0x02;                //手动更新Timer0的设置
    rTCON=0x09;                //自动重载,启动定时器
    
    rI_ISPC = (unsigned int)(0x01 << 13);  //清除TICNT的pending
    
    rINTMSK &= (unsigned int)(~(0x01 << 13));  //允许TICNT的中断服务
}

void tick_hook(void)   //清除中断请求标志,OSTickISR调用                      
{
    rI_ISPC =((unsigned int)1) << 13;    
    isrCount++;        
}

#endif


//中断控制初始化
void intcon_init(void)
{
    rINTMOD = 0;            // 所有中断均为IRQ方式
    rI_ISPC = 0x7ffffff;    // 清除所有中断请求
    rINTCON = 0x05;            // //非矢量中断,IRQ使能,FIQ禁用
}

//全局中断开关控制
void globle_int_enable(unsigned char bEnabled)
{
    if(bEnabled)
        rINTMSK &= ~(((unsigned int)0x01) << 26);
    else
        rINTMSK |= ((unsigned int)0x01) << 26;
}


void sys_init(void)
{
    PortInit();//设置端口功能,LCD
    globle_int_enable(0);  //关全局中断
    intcon_init();  //中断初始化
            
    //Uart_Select(0);
    //Uart_Init(0, 57600); //串口选择和初始化
            
    //InitNic(0); //0号网卡初始化
    
    //LCD_Init();    //LCD显示初始化
    //LCD_ChangeMode(DSPTxtMode); //显示模式为文本模式
    
    ISR_Install(IRQ_VECTOR_OFFSET, (void *)OSTickISR); //安装tick中断服务程序
}


//-----------------主函数开始------------------

#define    N_TASKS            5                // 任务数
#define    TASK_STK_SIZE    512                // 任务栈空间大小

OS_STK    TaskStk[N_TASKS][TASK_STK_SIZE];// 开辟任务栈,5*512*32/8 bytes

void Task1(void *);
void Task2(void *);

extern int Image$$RO$$Limit;
extern int Image$$RW$$Base;

int Main(int argc, char **argv)
{
    int    task_1 = 0, task_2 = 0;

    sys_init();    //系统初始化,含端口,中断,串口,网卡,LCD控制
    
    //Uart_Printf("\n***************uc/os v2.51*************************");
    //Uart_Printf("\n*************** for 44b0x  ************************");
    Uart_Printf("\nuc/os is running");
    OSInit();
    OSTaskCreate(Task1, &task_1, &TaskStk[0][TASK_STK_SIZE-1], 1);
    OSTaskCreate(Task2, &task_2, &TaskStk[1][TASK_STK_SIZE-1], 2);
    OSStart();

    return 0;
}


void Task1(void * pParam)
{    

#if RTC_OR_TIME0
    tick_init(63);    //tick节拍初始化,2 ticks /s
#else
     tick_init(250);        //tick节拍初始化,2 ticks /s
#endif

     globle_int_enable(1);    //全局中断开
     
     while(1)    
     {        
        OSSchedLock();             
        Uart_Printf( "\ntask1" );                
        OSSchedUnlock();    
        OSTimeDly(1);                
    }
}


void Task2(void * pParam)
{
    while(1)    
    {
        OSSchedLock();        
        Uart_Printf( "\ntask2" );    
        OSSchedUnlock();        
        OSTimeDly(1);
    }
}
     3: re:把编译器的优化选项关掉。

接管 Undefined,PrefetchAbort, DataAbort
看看哪一个有中断,分析寄存器的值,可以缩小查找范围

把其中的一个任务先去掉

祝你好运



4: 谢谢楼上的兄弟的指点,我再上OS_CPU_A.S文件,也许关键代码有错
该代码原自网友YJ的移植,我研读了好几遍并部分做了注释,尤其在OSIntCtxSW部分,未发现问题,也许我忽略了某些地方,请高手指点,万分感谢!


      AREA    |subr|, CODE, READONLY

;/***********************************************************************
; 函数: OSStartHighRdy
; 作用:在OS开始时调用优先级最高的就绪任务
; 参数: void
; 数出:  None
; 返回:  void
; 注意:  在OSStart()中调用
;*********************************************************************/
    EXPORT     OSStartHighRdy  ;声明此函数被其他文件使用
    IMPORT    OSTaskSwHook    ;声明此函数/参量在其他文件中定义
    IMPORT  OSTCBHighRdy    
    IMPORT  OSRunning  
OSStartHighRdy  ;使就绪表中任务最高的优先级的任务开始运行
;********************************************************
;调用用户定义的OSTaskSwHook()函数
;OSRunning = Ture
;得到将要运行的这个最高优先级任务的堆栈指针
;从该任务(上一行提到的任务)堆栈中恢复所有CPU寄存器
;执行中断返回指令
;***********************************************************
        BL     OSTaskSwHook             ; 调用用户的Hook函数,空函数

        LDR     r4,=OSRunning            ; 声明多任务OS开始运行
        MOV     r5, #1                   
        STRB     r5, [r4]                 ; OSRunning = true(0000 0001b)
                                         ;get the highrdy's TCB pointer
        LDR     r4, =OSTCBHighRdy        ; 得到最高优先级任务的任务块地址
        LDR     r4, [r4]                 ; 任务块中的第一个参数即任务的堆栈
        LDR     sp, [r4]                 ; 切换到新任务的堆栈
                                               
        LDMFD     sp!, {r4}                ;从新任务堆栈中读取第一个参数(CPSR)到(r4)        
        MSR     cpsr_cxsf, r4            ;再传给cpsr,相当于从任务堆栈恢复CPSR,CPU切换到该任务所在的模式        
        LDMFD     sp!, {r0-r12,lr,pc}      ;依次恢复该任务r0~r12,lr,pc燃拇嫫鳎琍C切换到该任务

     
;/***********************************************************************
; Function: OS_TASK_SW
; Purpose: 任务级切换
; Parameters: void
; Outputs:  None
; Returns:  void
; Notes:
;    The whole function is executed in CRITICAL state. See OSSched().
;   On entry, OSTCBCur and OSPrioCur hold the current TCB and priority
;   and OSTCBHighRdy and OSPrioHighRdy contain the same for the task
;   to be switched to.
;   在进入时,
;   The following code assumes that the virtual memory is directly
;   mapped into  physical memory. If this is not true, the cache must
;   be flushed at context switch to avoid address aliasing.
;
;*********************************************************************/
        EXPORT     OSCtxSw
        IMPORT    OSPrioCur
        IMPORT    OSPrioHighRdy
        IMPORT    OSTCBCur
        IMPORT    OSTaskSwHook
        IMPORT    OSTCBHighRdy
        
OSCtxSw
;******************************************
;保存CPU寄存器
;在当前任务控制块中保存当前任务的堆栈指针
;调用OSTaskSwHook()
;OSTCBCur = OSTCBHighRdy
;OSPrioCur = OSPriHighRdy
;得到将要开始运行的任务的堆栈指针
;从新任务的任务堆栈中恢复处理器所有寄存器的值
;执行中断返回指令
;******************************************保存CPU寄存器
        STMFD     sp!, {lr}                ; push pc (lr is actually be pushed in place of PC)
                                          ;OS_Sched()调用OSCtxSw到这里之后,lr的值就是pc的值,
                                          ;因为是任务级调用而非异常
        STMFD     sp!, {r0-r12,lr}         ; push lr & register file

        MRS     r4, cpsr                 ;通过MRS指令将cpsr入栈
        STMFD     sp!, {r4}                ; push current psr
                                         ; 被挂起的当前任务的寄存器保存完毕,下面接着保存该任务的堆栈指针
                                         ;以便下次恢复时,现找到其堆栈指针,便可恢复其寄存器
;***************在当前任务的任务控制块中保存当前任务的堆栈指针,OSTCBCur此时对应的是当前任务的TCB
        LDR     r4, =OSTCBCur            ; 得到当前TCB的地址,传给r4
        LDR        r5, [r4]                 ; 将该地址对应的值传给r5
        STR     sp, [r5]                 ; store sp in preempted tasks s TCB
                                         ; 将sp的内容传给以r5中内容为地址的空间
;OSCtxSw要恢复优先级更高的就绪任务,和OSIntCtxSw代码可共用
;***********************************************************************
; Function: OSIntCtxSw,其上下文的保护在OSTickISR中进行,不能使用上面的代码
; Purpose:
;     To perform a context switch from the interrupt level.
; Processing:
;    See uC/OS-II Interrupt Level Context Switch flow chart
; Parameters: void
; Outputs:  None
; Returns:  void
; Notes:
;   Sets up the stacks and registers to call the task level
;   context switch
;*********************************************************************/
        EXPORT     OSIntCtxSw
        IMPORT OSTaskSwHook
OSIntCtxSw                       ;准备任务切换
         ;然后在当前任务的任务控制块中保存当前任务的堆栈指针
        LDR        r4, =OSTCBCur            
        LDR        r4, [r4]
        STR        sp, [r4]    ;added by liyu
        
        BL        OSTaskSwHook    ;调用Hook函数,此为空函数
        
        LDR        r4, =OSTCBHighRdy ;将高优先级的任务控制块取出  
        LDR        r4, [r4]
        LDR        r5, =OSTCBCur
        STR        r4, [r5]         ; OSTCBCur = OSTCBHighRdy

        LDR        r6, =OSPrioHighRdy      ;取出高优先级
        LDRB         r6, [r6]           ;优先级,字节传送
        LDR        r5, =OSPrioCur
        STRB        r6, [r5]        ; OSPrioCur = OSPrioHighRdy
                                     ;此时,r4所指向的当前任务控制块中存的是高优先级任务控制块的内容                
        LDR        sp, [r4]             ;其第一个内容就是该任务的sp,所以&ostcbhighrdy->SP,得到新任务的堆栈指针
        
                                     ;开始恢复CPU寄存器
        LDMFD         sp!, {r4}        ;此时sp已经是高优先级任务栈中的sp了,于是取第一个参数,即该任务的CPSR
        MSR         cpsr_cxsf, r4    ;首先开始cpsr恢复    
        LDMFD     sp!, {r0-r12,lr,pc}        ; pop new task r0-r12,lr & pc,若在时钟节拍中断处理中调度时发现有高优先级
                                        ;任务就绪,就从这里直接返回跳转到新任务,而不返回到时钟节拍中断处理中去了
                                        
;/***********************************************************************
;
;yangye 2003-2-14
;changed this function name from OSTickISR to OSISR(it is not a TICK isr)
; Function: OSISR
;
; Purpose:
;        The IRQ interrupt handler
;
; Processing:
;    Saves context
;    Calls the IRQ dispatcher
;    Checks if context switch necessary
;    If not, restores context and returns from interrupt
;    If switch required, branches without link to IRQContextSwap
;       which performs context switch if interrupts not nested
;       and returns from interrupt to new context
;
; Parameters: void
;
; Outputs:  None
;
; Returns:  void
;
; Notes:
;   (1) here we use OSIntCtxSwFlag to indicate a request for int-level
;       context switch
;   (2) _IntCtxSw is used to perform a real switch operation
;
;*********************************************************************/    
    EXPORT     OSTickISR
    IMPORT    OSIntEnter
    IMPORT    OSTimeTick
    IMPORT    tick_hook    
    
    IMPORT    OSIntExit

LINK_SAVE    DCD        0 ;保存lr的空间
PSR_SAVE    DCD        0 ;保存spsr的空间

OSTickISR      ;主函数完成tick中断服务的安装,在tick中断产生后,非矢量中断,PC跳到此函数
    STMFD    sp!, {r4}                 ;准备保存LR,SPSR(因为异常跳转,PC和CPSR已经被改变了)
    
    LDR        r4, =LINK_SAVE
    STR        lr, [r4]                 ; LINK_SAVE = lr_irq,此时lr为异常前pc+4的值

    MRS        lr,    spsr
    STR        lr, [r4, #4]             ; PSR_SAVE = spsr_irq,此时lr存的是异常发生前的cpsr
    
    LDMFD    sp!, {r4}                
        
    ORR        lr, lr,    #0x80             ; 在上下文切换前,屏蔽中断,注意此时lr为异常前的cpsr
    MSR        cpsr_cxsf, lr              ; 完成异常前的cpsr恢复并屏蔽中断,
                                     
                                     ;下面开始保存异常前的上下文
    SUB        sp, sp, #4                 ;按任务栈结构,空一个空间预留给PC    
    STMFD    sp!, {r0-r12,lr}        ; 依次保存lr、r12-r0

    LDR        r4, =LINK_SAVE           ;准备保存pc
    LDR        lr, [r4, #0]
    SUB        lr, lr, #4                 ; 异常前的pc = LINK_SAVE - 4,此前lr为异常前pc+4的值
    STR        lr, [sp, #(14*4)]         ; 保存pc

    LDR        r4, [r4, #4]             ; r4 = PSR_SAVE,
    STMFD    sp!, {r4}                 ; 保存任务的cpsr,寄存器保护完毕
    
     ;然后在当前任务的任务控制块中保存当前任务的堆栈指针
    LDR        r4, =OSTCBCur            
    LDR        r4, [r4]
    STR        sp, [r4]                 ; OSTCBCur -> stkptr = sp
                                    
    
    BL    OSIntEnter   ;异常前的上下文保存好之后,开始准备中断服务,将OSIntNesting++
    BL     OSTimeTick   ;中断服务中,将所有延时节拍不为1的任务的节拍数都减1
    BL    tick_hook                       ;条用hook函数,清除tick中断请求标志
    
    BL    OSIntExit   ;将OSIntNesting--,并判断是否有高优先级任务就绪,若有,则调用OSIntCtxSw()调度该任务;
                     ;若没有则返回到这里,然后恢复异常前的任务
    
    LDMFD     sp!, {r4}    ;运行到这里时的sp仍然为异常发生前的sp,借助它来恢复异常前的现场
                         ;开始恢复cpsr            
    MSR     cpsr_cxsf, r4 ;切换,从irq模式切换到svc模式了
    LDMFD     sp!, {r0-r12,lr,pc}      ;恢复异常前的任务的 r0-r12,lr & pc,完毕
        
    
;/***********************************************************************
; Functions: ARMDisableInt,     ARMEnableInt
; Purpose:  Disable and enable IRQ and FIQ preserving current CPU mode.
; Processing:
;    Push the cpsr onto the stack
;    Disable IRQ and FIQ interrupts
;    Return
; Parameters: void
; Outputs:  None
; Returns:  void
; Notes:
;   (1) CAN be called from SVC mode to protect Critical Sections.
;   (2) Do not use these calls at interrupt level,中断级的屏蔽由两条指令完成.
;   (3) Used in pairs within the same function level;
;   (4) Will restore interrupt state when called; i.e., if interrupts
;       are disabled when DisableInt is called, interrupts will still
;       still be disabled when the matching EnableInt is called.
;   (5) Uses the method described by Labrosse as "Method 2".
;   (6) 注意,编译优化时应选择milimum,否则该函数可能出错
;*********************************************************************/
        EXPORT     ARMDisableInt
ARMDisableInt
    MRS    r0, cpsr
    STMFD    sp!, {r0}             ; push current PSR
    ORR    r0, r0, #0xc0
    MSR    cpsr_c, r0         ; disable IRQ Int s

    MOV    pc, lr   ;return

        EXPORT     ARMEnableInt
ARMEnableInt
    LDMFD    sp!, {r0}                ; pop current PSR
    MSR    cpsr_c, r0               ; restore original cpsr
    
    MOV    pc, lr ;return
5: 优化策略如下:Optimization Level: Minimum
Optimization Criterion: for time (for space也选过,情况依旧)

也写了abort异常的处理,但是板子并没有运行到abort的ISR,而是在OS中直接重新启动,即从0X0开始运行。

另外还有一个问题,在axd中的调试中,在44binit.s的堆栈初始化子程序中(即 执行bl        InitStacks然后进入InitStacks代码),有时连续运行会出错,单步运行则从来不会出错。

也让我有时很迷惑。 6: 可能与硬件有关把系统时钟频率调低一点。

改一下代码段的起始地址,看看现象有没有不同?

最好测一下RAM。
7: 谢谢PandaFeng站友的提示今天我按UC/OS的教材的测试步骤重新测试了一些OS,建立一个测试任务TestTask,在不挂接节拍中断时,当TestTask任务调用OSTimeDly()函数挂起自身时,OS能调度而进入空闲任务,这就说明OSCtxSW()函数正常,而OSIntCtxSW()函数属于前者的一部分,因此也应该正常。

当按上面的代码初始化中断和安装好中断之后,程序能进入OSTickISR,我在OSTickISR用点亮LED和B . 指令观察,发现系统在两种情况下崩溃(表现现象为程序重ROM的0X0启动):

1.在运行OSIntCtxSW的恢复任务的PC指针时;

2.当不执行OSIntCtxSW,即在BL    OSIntExit返回后,在OSTickISR的最后一条指令恢复PC指针时;

初步认为是OSTickISR可能有问题。但是一条一条研读,未发现问题。


在这里,我注意到一个异常,请大虾指点。

1.44BINIT.S中初始化各模式的堆栈之后,在执行MOV PC,LR之前,我在AXD。(连上44B0X开发板后使用AXD调试)中观察当前模式下的CPSR和SPSR,发现CPSR突然被改成IRQ模式!而SPSR仍然是SVC模式意味着进入MAIN后,CPSR却仍然是IRQ模式,那么,在任务级别的切换OSCtxSW,可能不会发生问题,若进入了OSTickISR,那么就可能发生问题了,过程描述请见下面初始化代码,尤其是最后面两条汇编指令。

;****************************************************
;*    The function for initializing stack                *
;****************************************************
InitStacks
    ;Don't use DRAM,such as stmfd,ldmfd......
    ;SVCstack is initialized before
    ;Under toolkit ver 2.50, 'msr cpsr,r1' CAN be used instead of 'msr cpsr_cxsf,r1'

    mrs        r0,cpsr
    bic        r0,r0,#MODEMASK
    orr        r1,r0,#UNDEFMODE|NOINT
    msr        cpsr_cxsf,r1        ;UndefMode
    ldr        sp,=UndefStack
    
    orr        r1,r0,#ABORTMODE|NOINT
    msr        cpsr_cxsf,r1             ;AbortMode
    ldr        sp,=AbortStack

    orr        r1,r0,#IRQMODE|NOINT
    msr        cpsr_cxsf,r1             ;IRQMode
    ldr        sp,=IRQStack
    
    orr        r1,r0,#FIQMODE|NOINT
    msr        cpsr_cxsf,r1             ;FIQMode
    ldr        sp,=FIQStack

    bic        r0,r0,#MODEMASK|NOINT
    orr        r1,r0,#SVCMODE
    msr        cpsr_cxsf,r1             ;执行完此语句后,CPSR和SPSR都是SVC模式

    ldr        sp,=SVCStack          ;  而执行完此语句后,CPSR突然变成了IRQ模式!!
    
(有时执行到main却发现CPSR和SPSR都是SVC模式)。

    ;USER mode is not initialized.
    ;当
    mov        pc,lr ;The LR register may be not valid for the mode changes.



这样,执行到MAIN后,CPSR仍然是IRQ模式!!
如果进入OSTickISR,那么将可能导致问题,不知道我分析得对否?

我下次将用SWI指令调用任务切换函数,将进入main后的模式定为user模式。
不知道这样是否可以。

唉,这个问题,困扰我好久了,uc/os没搞定,很多乐趣无法享受得到。我还想玩uc/linux呢。

盼望有高人能点醒我这个ARM小菜鸟。

也谢谢所有关注过这个问题的站友!
8: 是否打开了某个中断,而有没有设向量。是否打开了某个中断源,而又没有设向量。
当发生中断时,向量地址又为0,所以产生了"Reset"。
从没有产生Abort中断,可以推想。

watchdog 的可能性较大。 9: 谢谢PandaFeng和斑竹及其他关注的站友,今天有新的进展PandaFeng您好,谢谢您的指点。
在44BINIT.s中,WDT在第2条指令就开始了禁止的操作,各中断也禁止了,只有task1中初始化时钟节拍中断之后才开全局中断。

如下:
;****************************************************
;*    START                                            *
;****************************************************
ResetHandler
    ldr        r0,=WTCON        ;watch dog disable
    ldr        r1,=0x0         
    str        r1,[r0]

    ldr        r0,=INTMSK
    ldr        r1,=0x07ffffff  ;all interrupt disable
    str        r1,[r0]

...

  另外,请您分析一下这个现象:

   今天下午在一次AXD调试中,我发现44BINIT.s在初始化堆栈(BL InitStacks)之后,CPSR保持为SVC模式不变,于是一路全速执行,发现测试任务和系统的空闲任务能正常切换(看LED输出结果),和前面一个帖子预期的一样。这就意味着,OS能正常使用了。这就证明我的软件部分是正确的。

   于是烧录到flash里去,却崩溃了,情况和先前描述的一样。

   再进入axd环境,单步观察44BINIT.s中的InitStacks的代码,发现在最后初始化SVC堆栈完成之后,CPSR仍然莫名其妙改变成了IRQ模式,这样,一直执行到MAIN,仍然是IRQ模式,当发生真正的时钟中断时,系统就崩溃了。

   为什么44Binit.s初始化堆栈会出现CPSR异常改变的现象呢?????

  请看下图:注意椭圆框起来的内容
http://file.21ic.com.cn/upload/img/200511/200512217231635492.jpg





10: 不太清楚或许是被flash的启动代码影响了。

我一直用IAR 的IDE,ADS 才用过两三个星期,而且是一年前的事了。
对它并不熟悉。

烧录到flash里后崩溃了,是否指BOOT代码都不能通过吗?

单纯的点灯程序写到flash里,正常吗?

其实,我是假定ucos是正常的,因为没有产生abort。
在我的调试中,数据稍有异常,abort 中断是很容易产生的。

下面是IAR DEBUG前对44B寄存器写的值,可以参考一下。
AXD也有相关的设置,只是命令名不同。
例如:
__writeMemory32(0x11110112, 0x01c80000, "Memory");
相当于rBWSCON = 0x11110112;

顺便说一下,IAR Embedded Workbench IDE 很好用。

{
    __message "Init memery\n";
    
    __writeMemory32(0x00000001, 0x1C00000, "Memory");
    __writeMemory32(0x07FFFFFF, 0x1E0000C, "Memory");
    __writeMemory32(0x00000000, 0x1D30000, "Memory");
    __writeMemory32(0x80001B1B, 0x1C40000, "Memory");
    __writeMemory32(0x11110112, 0x01c80000, "Memory");
    __writeMemory32(0x00000600, 0x01c80004, "Memory");
    __writeMemory32(0x00007ffc, 0x01c80008, "Memory");
    __writeMemory32(0x00007ffc, 0x01c8000c, "Memory");
    __writeMemory32(0x00007ffc, 0x01c80010, "Memory");
    __writeMemory32(0x00007ffc, 0x01c80014, "Memory");
    __writeMemory32(0x00007ffc, 0x01c80018, "Memory");
    __writeMemory32(0x00018000, 0x01c8001c, "Memory");
    __writeMemory32(0x00018000, 0x01c80020, "Memory");
    __writeMemory32(0x0086041a, 0x01c80024, "Memory");
    __writeMemory32(0x00000010, 0x01C80028, "Memory");
    __writeMemory32(0x00000020, 0x01C8002C, "Memory");
    __writeMemory32(0x00000020, 0x01C80030, "Memory");
    __writeMemory32(0x00018021, 0x01D80000, "Memory");
    __message "Init Completed\n";
}

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]