gdf78 发表于 2011-11-3 10:05:37

请教一个 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个,达到缓冲区满中断触发时就死

请过来人给指点啊 谢谢了

justidle 发表于 2011-11-3 19:17:10

首先一个问题需要确认一下,你用dbgu口,dbgu口的中断是和别人共享的。请注意这个。

gdf78 发表于 2011-11-5 09:21:06

是的,之前也担心这个问题
后来换了US0测试,还是老样子,郁闷

gdf78 发表于 2011-11-5 10:07:39

现在感觉是 OS_EXIT_CRITICAL 函数,恢复寄存器的汇编可能有问题,但这一块不行啊

gdf78 发表于 2011-11-5 12:04:24

谁有 IAR UCOSII 中断函数 相关部门的 代码贡献下给学习啊,感谢啊

ljt80158015 发表于 2011-11-5 13:16:58

回复【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;
      }
      
}

gdf78 发表于 2011-11-5 18:24:28

楼上好,我是用UCOSII的
这个系统是否能支持硬中断啊?
找了好多参考资料,最后还是死在接收缓冲中断。如没有触发中断都能正常运行,一中断进去就出不来(确定已经进入中断函数执行了)。
也仔细看了 OSIntExit() 函数,对比了其他代码,应该没问题啊

难道只能继续裸奔吗?
请高人讲下 iar ucosii (7x256)硬中断的切换啊

gdf78 发表于 2011-11-5 18:25:44

这里代码是:
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

ljt80158015 发表于 2011-11-5 19:23:30

可以的,不限os的。
代码表述的很清楚了。

gdf78 发表于 2011-11-5 20:55:34

谢谢LS答复,我菜了,还是看不懂你的代码
现在为了避免DBG系统中断共用问题,我换用US0简单点的
1、能进入串口中断,是否说明我中断函数注_册成功了?
2、里面加了 发送字符 的函数,中断函数开始处加了 OSIntEnter,确信已经执行到 中断函数最后一个 OSIntExit()了,但没返回到被中断的任务,系统死掉。
我怀疑是串口中断函数退出时状态没恢复好,或者没从中断切换到普通的任务,但不知道哪有问题?

ljt80158015 发表于 2011-11-5 21:32:08

进中断要保护现场的,有一段汇编代码。

ljt80158015 发表于 2011-11-7 11:45:31

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

gdf78 发表于 2011-11-7 16:45:46

谢谢,我用的是 UCOSII 2.7 版本的
对比了你提供的代码,在 OSCtxSw 和 OSIntCtxSw 处的代码不同

我再试试看

gdf78 发表于 2011-11-19 20:08:41

还是不行,神奇的UCOS,暂时挂着先了

ljt80158015 发表于 2011-11-26 10:12:02

不是吧!~

gdf78 发表于 2011-12-5 10:19:12

目前确定不行啊,如有运行通过的朋友,请指点啊,痛苦西

ljt80158015 发表于 2011-12-5 10:39:37

回复【15楼】gdf78
目前确定不行啊,如有运行通过的朋友,请指点啊,痛苦西
-----------------------------------------------------------------------

你cpu是运行在 ARM模式还是THUMB模式?

gdf78 发表于 2011-12-8 15:12:42

THUMB的

gdf78 发表于 2011-12-8 15:13:06

ARM模式下也试过了,都不行啊

ljt80158015 发表于 2011-12-8 17:21:37

我这段代码是ARM模式的
页: [1]
查看完整版本: 请教一个 IAR下 7x256串口中断接收问题,搞了2天,不行了