请教一个 IAR下 7x256串口中断接收问题,搞了2天,不行了
//* 功能:初始化DBUG口,即可作为DBGU功能,又可作为普通USART口功能//*----------------------------------------------------------------------------
void AT91F_DBGU_Init(void)
{
//* 配置I/O
AT91F_DBGU_CfgPIO(); //调用库函数
//* 复位发送功能,允许发送
AT91F_US_ResetTx ((AT91PS_USART)AT91C_BASE_DBGU);//调用库函数
//* 复位接收功能,允许接受
AT91F_US_ResetRx ((AT91PS_USART)AT91C_BASE_DBGU);//调用库函数
//* 配置 DBGU
AT91F_US_Configure ( // 调用库函数
(AT91PS_USART) AT91C_BASE_DBGU, // DBGU 基地址
AT91B_MCK,
AT91C_US_ASYNC_MODE , // 模式积存器
AT91C_DBGU_BAUD , // 波特率
0); // 触发时间
//* 允许串口发送
AT91F_US_EnableTx ((AT91PS_USART)AT91C_BASE_DBGU);
//* 允许串口接受
AT91F_US_EnableRx ((AT91PS_USART)AT91C_BASE_DBGU);
//* 允许接受缓冲区满中断
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,
AT91C_ID_SYS,
DBGU_SYS_LEVEL,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
DBGU_irq_handler);
//打开PDC_DBGU
AT91F_PDC_Open(AT91C_BASE_PDC_DBGU);
//* 启动PDC_DBGU接受
AT91F_USRT_FrameReceive((AT91PS_USART)AT91C_BASE_DBGU,ReceiveBuffer,BufferLength);
//允许PDC_DBGU发送
AT91F_PDC_EnableTx(AT91C_BASE_PDC_DBGU);
//允许PDC_DBGU接收
AT91F_PDC_EnableRx(AT91C_BASE_PDC_DBGU);
//* 允许接受缓冲区满中断
AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU,AT91C_US_RXBUFF);
//* 允许DBGU系统中断
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
}
//* 功能:DBUG中断执行,当PDC中接受缓冲区满则执行本函数。
//*----------------------------------------------------------------------------
void DBGU_irq_handler(void)
{
unsigned int i, status; //变量定义
//OS_ENTER_CRITICAL();
OSIntEnter();
//OS_EXIT_CRITICAL();
//if (OSRunning == TRUE) OSIntNesting++;
//禁止系统中断(DBGU属于系统中断)
AT91F_AIC_DisableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
//查看是那类中断,读取状态积存器/中断屏蔽积存器,以清除中断标志,
status=(AT91F_USART_GetStatus_zzf((AT91PS_USART)AT91C_BASE_DBGU)&AT91F_USRT_GetInterruptMaskStatus_zzf((AT91PS_USART)AT91C_BASE_DBGU));
if (( status &AT91C_US_RXBUFF))//如果是缓冲区满中断
{
//接受一个包
AT91F_USRT_FrameReceive((AT91PS_USART)AT91C_BASE_DBGU,ReceiveBuffer,BufferLength);
////////////////////////////////////////////////////////
//用户自己添加//此处简单的将接受到的数据发送回去
for(i=0;i<BufferLength;i++)
{
SentBufferData=ReceiveBuffer;
}
while (!AT91F_USRT_FrameSendData((AT91PS_USART)AT91C_BASE_DBGU,SentBufferData,BufferLength));
}
/////////////////////////////////////////////////////////////
else
// 如果是非PDC缓冲区满中断,则表明出错,为纠正错误,屏蔽产生此中断的位
{
AT91F_US_DisableIt ((AT91PS_USART)AT91C_BASE_DBGU,status );
}
// 重先开中断
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
OSIntExit();
}
以上,BufferLength=5
问题:
当PC发送的个数<5个,程序的LED灯正常在闪,一旦=5个,马上死机
原来在裸奔下,中断函数中的 OSIntEnter OSIntExit 两个函数是没有的,程序能正常接收运行.
我把拷贝到UCOSII中后,中断函数中加了这2个,达到缓冲区满中断触发时就死
请过来人给指点啊 谢谢了 首先一个问题需要确认一下,你用dbgu口,dbgu口的中断是和别人共享的。请注意这个。 是的,之前也担心这个问题
后来换了US0测试,还是老样子,郁闷 现在感觉是 OS_EXIT_CRITICAL 函数,恢复寄存器的汇编可能有问题,但这一块不行啊 谁有 IAR UCOSII 中断函数 相关部门的 代码贡献下给学习啊,感谢啊 回复【1楼】justidle
首先一个问题需要确认一下,你用dbgu口,dbgu口的中断是和别人共享的。请注意这个。
-----------------------------------------------------------------------
FreeRTOS for 256中共享系统中断
ATMEL的AT91SAM7256的系统控制器包括DBGU/RTT/PIT/PIOA/PIOB等数个microcontrollor,它们的特点是共享AT91C_ID_SYS一个中断。
在移植好的系统中FreeRTOS将系统中断只供PIT使用,用以产生系统调度时钟中断。而在许多系统中必须使用到DBUG串口、PIO口,如果在系统中借助查询的方式使用串口,必然会消耗很大资源。所以共享系统中断是使用FreeRTOS的一项基本任务。
笔者花了半天时间已经将基本工作完成,并且能够成功运行,下面是我的移植过程和移植的关键代码。
portasm的代码:
RSEG ICODE:CODE
CODE32
EXTERN vTaskSwitchContext
EXTERN vTaskIncrementTick
EXTERN vRTT_C_ISR
EXTERN vDBGU_C_ISR
PUBLIC vPortYieldProcessor
PUBLIC vPortPreemptiveTick
PUBLIC vPortStartFirstTask
PUBLIC vSys_IRQ_ISR
#i nclude "AT91SAM7S64_inc.h"
#i nclude "ISR_Support.h"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Starting the first task is just a matter of restoring the context that
; was created by pxPortInitialiseStack().
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vPortStartFirstTask:
portRESTORE_CONTEXT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Manual context switch function.This is the SWI hander.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vPortYieldProcessor:
ADDLR, LR, #4 ; Add 4 to the LR to make the LR appear exactly
; as if the context was saved during and IRQ
; handler.
portSAVE_CONTEXT ; Save the context of the current task...
LDR R0, =vTaskSwitchContext ; before selecting the next task to execute.
mov lr, pc
BX R0
portRESTORE_CONTEXT ; Restore the context of the selected task.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Preemptive context switch function.This will only ever get installed if
; portUSE_PREEMPTION is set to 1 in portmacro.h.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vPortPreemptiveTick:
// portSAVE_CONTEXT ; Save the context of the current task.
//在SysIRQ的中断入口完成portSAVE_CONTEXT, 所以我把此处的portSAVE_CONTEXT 注释掉
LDR R0, =vTaskIncrementTick ; Increment the tick count - this may wake a task.
mov lr, pc
BX R0
LDR R0, =vTaskSwitchContext ; Select the next task to execute.
mov lr, pc
BX R0
LDR R14, =AT91C_BASE_PITC ; Clear the PIT interrupt
LDR R0,
LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
STR R14,
portRESTORE_CONTEXT ; Restore the context of the selected task.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; VRTTISR
; 这个是RTT的中断程序的入口,由SysIRQ调用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vRTTCISR:
LDR R0, = vRTT_C_ISR
mov lr,pc
BX R0
LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
STR R14,
portRESTORE_CONTEXT ; Restore the context of the selected task.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; vDBGUISR
; DBGUR的中断入口,由SysIRQ调用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vDBGUISR:
LDR R0, = vDBGU_C_ISR
//vDBGU_C_ISR是C程序入口
mov lr,pc
BX R0
LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
STR R14,
portRESTORE_CONTEXT ; Restore the context of the selected task.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 系统中断管理函数
; 系统中断由多个中断组成
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vSys_IRQ_ISR:
portSAVE_CONTEXT ; Save the context of the current task.
//check if the interrupt is generate by PIS
LDR R0, =AT91C_PITC_PISR
LDR R1, [ R0 ]
TST R1, #0x01
BNE vPortPreemptiveTick
//check if the interrupt is generate by dbgu unit
LDR R1, =AT91C_DBGU_IMR;
LDR R1, [ R1 ]
LDR R2, =AT91C_DBGU_CSR;
LDR R2, [ R2 ]
AND R3,R1,R2
CMP R3,#0
BNE vDBGUISR
//check if the interrupt is generate by RTT
LDR R1,=AT91C_RTTC_RTMR;
LDR R1,[ R1 ]
MOV R1,R1,LSR #16
LDR R2,=AT91C_RTTC_RTSR
LDR R2,[ R2 ]
AND R3,R1,R2
CMP R3,#0
BNE vRTTCISR
vSys_IRQ_END:
//如果没有检测到中断,就是进行正确的中断返回
LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
STR R14,
portRESTORE_CONTEXT ; Restore the context of the selected task.
END
DBGU中断C程序:
void Init_DBGU()
{
AT91F_DBGU_CfgPIO();
DBGU_RX_TX_RST_DIS();
Init_DBGU_BGR(26);//26 <=> 115kBd
DBGU_Parity_Cfg(4);
DBGU_TX_Enable();
DBGU_RX_Enable();
DBGU_IRQ_Enable();
}
/*-----------------------------------------------------------*/
unsigned int dbgu_status;
unsigned int dbgu_rx_data;
inline void vDBGU_C_ISR( )
{
dbgu_status = AT91C_BASE_DBGU->DBGU_CSR;
if( dbgu_status & AT91C_US_RXRDY )
{
dbgu_rx_data = AT91C_BASE_DBGU->DBGU_RHR;
AT91C_BASE_DBGU->DBGU_THR = dbgu_rx_data;
}
}
AIC登记:
extern void ( vSys_IRQ_ISR )( void );
AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vSys_IRQ_ISR );
AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_SYS );
-----------------------------------------------------------------------------------------------------------------------
回复:FreeRTOS for 256中共享系统中断
peater发表评论于2006-7-5 14:37:00
peater
将程序烧入芯片之后,串口中断可以使用,但是PIT中断失效了,怀疑是串口中断对PIT中断产生了影响。将DBGU口的发送中断使能关闭之后,PIT中断恢复运行。
将中断C程序做了如下修改:
inline void vDBGU_C_ISR( )
{
dbgu_status = AT91C_BASE_DBGU->DBGU_CSR;
if( dbgu_status & AT91C_US_RXRDY )
{
dbgu_rx_data = AT91C_BASE_DBGU->DBGU_RHR;
AT91C_BASE_DBGU->DBGU_THR = dbgu_rx_data;
AT91C_BASE_DBGU->DBGU_IER |=AT91C_US_TXRDY;
}
else if( dbgu_status & AT91C_US_TXRDY )
{
AT91C_BASE_DBGU->DBGU_IDR |=AT91C_US_TXRDY;
}
} 楼上好,我是用UCOSII的
这个系统是否能支持硬中断啊?
找了好多参考资料,最后还是死在接收缓冲中断。如没有触发中断都能正常运行,一中断进去就出不来(确定已经进入中断函数执行了)。
也仔细看了 OSIntExit() 函数,对比了其他代码,应该没问题啊
难道只能继续裸奔吗?
请高人讲下 iar ucosii (7x256)硬中断的切换啊 这里代码是:
voidOSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SRcpu_sr = 0;
#endif
if (OSRunning == TRUE) {
OS_ENTER_CRITICAL();
if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */
OSIntNesting--;
}
if (OSIntNesting == 0) { /* Reschedule only if all ISRs complete ... */
if (OSLockNesting == 0) { /* ... and not locked. */
INT8U y;
y = OSUnMapTbl;
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl]);
if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */
OSTCBHighRdy= OSTCBPrioTbl;
#if OS_TASK_PROFILE_EN > 0
OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task*/
#endif
OSCtxSwCtr++; /* Keep track of the number of ctx switches */
OSIntCtxSw(); /* Perform interrupt level ctx switch */
}
}
}
OS_EXIT_CRITICAL();
}
}
//OSIntCtxSw()函数,汇编的
OSIntCtxSw
LDR R0, ??OS_TaskSwHook ; OSTaskSwHook();
MOV LR, PC
BX R0
LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5,??OS_PrioHighRdy
LDRB R6,
STRB R6,
LDR R4,??OS_TCBCur ; OSTCBCur= OSTCBHighRdy;
LDR R6,??OS_TCBHighRdy
LDR R6,
STR R6,
LDR SP, ; SP = OSTCBHighRdy->OSTCBStkPtr;
; RESTORE NEW TASK'S CONTEXT
LDMFD SP!, {R4} ; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; Pop new task's context 可以的,不限os的。
代码表述的很清楚了。 谢谢LS答复,我菜了,还是看不懂你的代码
现在为了避免DBG系统中断共用问题,我换用US0简单点的
1、能进入串口中断,是否说明我中断函数注_册成功了?
2、里面加了 发送字符 的函数,中断函数开始处加了 OSIntEnter,确信已经执行到 中断函数最后一个 OSIntExit()了,但没返回到被中断的任务,系统死掉。
我怀疑是串口中断函数退出时状态没恢复好,或者没从中断切换到普通的任务,但不知道哪有问题? 进中断要保护现场的,有一段汇编代码。 ucosOs_cpu_a.s
;********************************************************************************************************
; uC/OS-II
; The Real-Time Kernel
;
; (c) Copyright 1992-2004, Micrium, Weston, FL
; All Rights Reserved
;
; ARM7 Port
; IAR C Compiler
;
; File : OS_CPU_A.ASM
; By : Jean J. Labrosse
;********************************************************************************************************
AREA|subr|, CODE, READONLY
INCLUDE arm.inc
INCLUDE AT91SAM7X256.inc
IMPORTOSRunning ; External references
IMPORTOSTCBCur
IMPORTOSTCBHighRdy
IMPORTOSPrioCur
IMPORTOSPrioHighRdy
IMPORTOSIntCtxSwFlag
IMPORTOSIntEnter
IMPORTOSIntExit
IMPORTOSTaskSwHook
IMPORT OSTimeTick
IMPORT rtt_c_irq_handler
IMPORT dbgu_c_irq_handler
EXPORTOSStartHighRdy ; Functions declared in this file
EXPORT ARMDisableInt
EXPORT ARMEnableInt
EXPORTOSCtxSw
EXPORTTC_OS_IntCtxSw
EXPORTOS_CPU_SR_Save
EXPORTOS_CPU_SR_Restore
EXPORT TC_OSTickISR
EXPORT PIT_OS_IntCtxSw
EXPORT sys_irq_handler
EXPORT PIT_OS_TICK
EXPORT RTTCISR
EXPORT DBGUISR
NO_INTEQU 0xC0 ; Mask used to disable interrupts (Both FIR and IRQ)
;*********************************************************************************************************
;RTT中断处理
;*********************************************************************************************************
RTTCISR
LDR R0, =rtt_c_irq_handler
mov lr,pc
BX R0
LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
STR R14,
LDMFD SP!, {R0-R3, R12, LR}
SUBS PC, LR, #4
;*********************************************************************************************************
;debug串口中断处理
;*********************************************************************************************************
DBGUISR
LDR R0, = dbgu_c_irq_handler
mov lr,pc
BX R0
LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
STR R14,
LDMFD SP!, {R0-R3, R12, LR}
SUBS PC, LR, #4
;*********************************************************************************************************
; CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts.Generally speaking you
; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
; disable interrupts.'cpu_sr' is allocated in all of uC/OS-II's functions that need to
; disable interrupts.You would restore the interrupt disable state by copying back 'cpu_sr'
; into the CPU's status register.
;
; Prototypes : OS_CPU_SROS_CPU_SR_Save(void);
; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
;
; Note(s) : 1) These functions are used in general like this:
;
; void Task (void *p_arg)
; {
; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; OS_CPU_SRcpu_sr;
; #endif
;
; :
; :
; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */
; :
; :
; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */
; :
; :
; }
;
; 2) OS_CPU_SaveSR() is implemented as recommended by Atmels application note:
;
; "Disabling Interrupts at Processor Level"
;*********************************************************************************************************
OS_CPU_SR_Save
MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1,R0,#NO_INT
MSR CPSR_c,R1
MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags
AND R1,R1,#NO_INT
CMP R1,#NO_INT
BNE OS_CPU_SR_Save ; Not properly disabled (try again)
MOV PC,LR ; Disabled, return the original CPSR contents in R0
OS_CPU_SR_Restore
MSR CPSR_c,R0
MOV PC,LR
ARMDisableInt
MRS R12, CPSR ; get current CPU mode
ORR R12, R12, #I_BIT ; set the interrupt disable mode bit
MSR CPSR_c, R12
BX LR
ARMEnableInt
MRS R12, CPSR ; move current processor status into reg 12
BIC R12, R12, #I_BIT ; clear the interrupt disable bit
MSR CPSR_c, R12
BX LR
;*********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;
; Note : OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;*********************************************************************************************************
OSStartHighRdy
MSR CPSR_cxsf,#0xD3 ; Switch to SVC mode with IRQ and FIQ disabled
BL OSTaskSwHook ; OSTaskSwHook();
LDR R4,=OSRunning ; OSRunning = TRUE
MOV R5,#1
STRB R5,
LDR R4,=OSTCBHighRdy ; Get highest priority task TCB address
LDR R4, ; get stack pointer
LDR SP, ; switch to the new stack
LDMFD SP!,{R4} ; pop new tasks SPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R4} ; pop new tasks CPSR
MSR CPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC} ; pop new tasks R0-R12,LR & PC
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level)
;
; Note(s): Upon entry:
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdypoints to the OS_TCB of the task to resume
;*********************************************************************************************************
OSCtxSw
STMFD SP!,{LR} ; push PC (lr should be pushed in place of PC)
STMFD SP!,{R0-R12,LR} ; push LR & register file
MRS R4,CPSR
STMFD SP!,{R4} ; push current PSR
MRS R4,SPSR
STMFD SP!,{R4} ; push current SPSR
LDR R4,=OSTCBCur ; Get current task's OS_TCB address
LDR R5,
STR SP, ; store sp in preempted tasks's TCB
BL OSTaskSwHook ; OSTaskSwHook();
LDR R4,=OSPrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5,=OSPrioHighRdy
LDRB R6,
STRB R6,
LDR R4,=OSTCBCur ; Get the current tasks OS_TCB address
LDR R6,=OSTCBHighRdy ; Get highest priority tasks OS_TCB address
LDR R6,
LDR SP, ; get new tasks stack pointer
STR R6, ; OSTCBCur = OSTCBHighRdy
LDMFD SP!,{R4} ; pop new tasks SPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R4} ; pop new tasks PSR
MSR CPSR_cxsf,r4
LDMFD SP!,{R0-R12,LR,PC} ; pop new tasks R0-R12,LR & PC
;*********************************************************************************************************
; INTERRUPT LEVEL CONTEXT SWITCH
;
; Description:This code performs a context switch if a higher priority task has been made ready-to-run
; during an ISR.
;*********************************************************************************************************
TC_OS_IntCtxSw
LDR R0,=OSIntCtxSwFlag ; OSIntCtxSwFlag = FALSE
MOV R1,#0
STR R1,
LDMFD SP!,{R0-R3,R12,LR} ; Clean up IRQ stack
STMFD SP!,{R0-R3} ; We will use R0-R3 as temporary registers
MOV R1,SP
ADD SP,SP,#16
SUB R2,LR,#4
MRS R3,SPSR ; Disable interrupts for when we go back to SVC mode
ORR R0,R3,#NO_INT
BIC R0,R0,#0x00000020 ; 这一句很关键,是整个系统稳定运行的重要因素
MSR SPSR_c,R0
LDR R0,=.+8 ; Switch back to SVC mode (Code below, current location + 2 instructions)
MOVS PC,R0 ; Restore PC and CPSR
; SAVE OLD TASKS CONTEXT ONTO OLD TASKS STACK
STMFD SP!,{R2} ; Push tasks PC
STMFD SP!,{R4-R12,LR} ; Push tasks LR,R12-R4
MOV R4,R1 ; Move R0-R3 from IRQ stack to SVC stack
MOV R5,R3
LDMFD R4!,{R0-R3} ; Load R0-R3 from IRQ stack
STMFD SP!,{R0-R3} ; Push R0-R3
STMFD SP!,{R5} ; Push tasks CPSR
MRS R4,SPSR
STMFD SP!,{R4} ; Push tasks SPSR
LDR R4,=OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP
LDR R5,
STR SP,
BL OSTaskSwHook ; call Task Switch Hook
LDR R4,=OSPrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5,=OSPrioHighRdy
LDRB R6,
STRB R6,
LDR R4,=OSTCBCur ; OSTCBCur = OSTCBHighRdy
LDR R6,=OSTCBHighRdy
LDR R6,
LDR SP,
STR R6,
LDMFD SP!,{R4} ; pop new task's SPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R4} ; pop new task's PSR
MSR CPSR_cxsf,R4
;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
LDR r14, =AT91C_BASE_AIC
STR r14,
;- 读取定时器状态寄存器
LDR r12,=AT91C_BASE_TC0
LDR r12,
;- Mark the End of Interrupt on the AIC
LDR r12, =AT91C_BASE_AIC
STR r12,
LDMFD SP!,{R0-R12,LR,PC} ; pop new tasks R0-R12,LR & PC
TC_OSTickISR
STMFD SP!,{R0-R3,R12,LR}
BL OSIntEnter
BL OSTimeTick
BL OSIntExit
LDR R0, =OSIntCtxSwFlag
LDR R1,
CMP R1, #1
BEQ TC_OS_IntCtxSw
;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
LDR r14, =AT91C_BASE_AIC
STR r14,
;- 读取定时器状态寄存器
LDR r12,=AT91C_BASE_TC0
LDR r12,
;- Mark the End of Interrupt on the AIC
LDR r12, =AT91C_BASE_AIC
STR r12,
LDMFD SP!, {R0-R3, R12, LR}
SUBS PC, LR, #4 ;return
PIT_OS_IntCtxSw
LDR R0,=OSIntCtxSwFlag ; OSIntCtxSwFlag = FALSE
MOV R1,#0
STR R1,
LDMFD SP!,{R0-R3,R12,LR} ; Clean up IRQ stack
STMFD SP!,{R0-R3} ; We will use R0-R3 as temporary registers
MOV R1,SP
ADD SP,SP,#16
SUB R2,LR,#4
MRS R3,SPSR ; Disable interrupts for when we go back to SVC mode
ORR R0,R3,#NO_INT
BIC R0,R0,#0x00000020 ;- 这一句很关键,是整个系统稳定运行的重要因素
MSR SPSR_c,R0 ;- c 控制域屏蔽字节(PSR)
;- x 扩展域屏蔽字节(PSR)
;- s 状态域屏蔽字节(PSR)
;- f 标志域屏蔽字节(PSR)
LDR R0,=.+8 ; Switch back to SVC mode (Code below, current location + 2 instructions)
MOVS PC,R0 ; Restore PC and CPSR
; SAVE OLD TASKS CONTEXT ONTO OLD TASKS STACK
STMFD SP!,{R2} ; Push tasks PC
STMFD SP!,{R4-R12,LR} ; Push tasks LR,R12-R4
MOV R4,R1 ; Move R0-R3 from IRQ stack to SVC stack
MOV R5,R3
LDMFD R4!,{R0-R3} ; Load R0-R3 from IRQ stack
STMFD SP!,{R0-R3} ; Push R0-R3
STMFD SP!,{R5} ; Push tasks CPSR
MRS R4,SPSR
STMFD SP!,{R4} ; Push tasks SPSR
LDR R4,=OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP
LDR R5,
STR SP,
BL OSTaskSwHook ; call Task Switch Hook
LDR R4,=OSPrioCur ; OSPrioCur = OSPrioHighRdy
LDR R5,=OSPrioHighRdy
LDRB R6,
STRB R6,
LDR R4,=OSTCBCur ; OSTCBCur = OSTCBHighRdy
LDR R6,=OSTCBHighRdy
LDR R6,
LDR SP,
STR R6,
LDMFD SP!,{R4} ; pop new task's SPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R4} ; pop new task's PSR
MSR CPSR_cxsf,R4
;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
LDR r14, =AT91C_BASE_AIC
STR r14,
;- 读取PIT寄存器PIVR以确认中断
LDR r12,=AT91C_BASE_PITC
LDR r12,
;- Mark the End of Interrupt on the AIC
LDR r12, =AT91C_BASE_AIC
STR r12,
LDMFD SP!,{R0-R12,LR,PC} ; pop new tasks R0-R12,LR & PC
PIT_OS_TICK
BL OSIntEnter
BL OSTimeTick
BL OSIntExit
LDR R0, =OSIntCtxSwFlag
LDR R1,
CMP R1, #1
BEQ PIT_OS_IntCtxSw
;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
LDR r14, =AT91C_BASE_AIC
STR r14,
;- 读取PIT寄存器PIVR以确认中断
LDR r12,=AT91C_BASE_PITC
LDR r12,
;- Mark the End of Interrupt on the AIC
LDR r12, =AT91C_BASE_AIC
STR r12,
LDMFD SP!, {R0-R3, R12, LR}
SUBS PC, LR, #4
sys_irq_handler
STMFD SP!,{R0-R3,R12,LR}
;check if the interrupt is generate by dbgu unit
LDR R1, =AT91C_DBGU_IMR;
LDR R1,
LDR R2, =AT91C_DBGU_CSR;
LDR R2,
AND R3,R1,R2
CMP R3,#0
BNE DBGUISR
;check if the interrupt is generate by RTT
LDR R1,=AT91C_RTTC_RTMR;
LDR R1,
MOV R1,R1,LSR #16
LDR R2,=AT91C_RTTC_RTSR
LDR R2,
AND R3,R1,R2
CMP R3,#0
BNE RTTCISR
;check if the interrupt is generate by PIS
LDR R0, =AT91C_PITC_PISR
LDR R1,
TST R1, #0x01
BNE PIT_OS_TICK
;- Mark the End of Interrupt on the AIC
LDR r12, =AT91C_BASE_AIC
STR r12,
LDMFD SP!, {R0-R3, R12, LR}
SUBS PC, LR, #4
END 谢谢,我用的是 UCOSII 2.7 版本的
对比了你提供的代码,在 OSCtxSw 和 OSIntCtxSw 处的代码不同
我再试试看 还是不行,神奇的UCOS,暂时挂着先了 不是吧!~ 目前确定不行啊,如有运行通过的朋友,请指点啊,痛苦西 回复【15楼】gdf78
目前确定不行啊,如有运行通过的朋友,请指点啊,痛苦西
-----------------------------------------------------------------------
你cpu是运行在 ARM模式还是THUMB模式? THUMB的 ARM模式下也试过了,都不行啊 我这段代码是ARM模式的
页:
[1]