共2条
1/1 1 跳转至页
44B0X,uc,os 请教:44B0X在跑uc/os时,硬件连续两次重新启动的问题
问
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";
}
问题描述:
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 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 | |
【分享评测,赢取加热台】使用8051单片机驱动WS2812被打赏40分 |