打印
[ZLG-ARM]

ucos下的中断问题

[复制链接]
3042|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sunwensky|  楼主 | 2007-2-8 23:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ucos, TI, ST, se, ic
在easy2104中我建立两个任务,每个任务是使led不同时间间隔闪烁。并且利用EINT1作外部中断,并利用KEY1触发中断。当发生EINT1中断产生时,蜂鸣器响一段时间,中断返回。可是两个任务执行正常。一产生中断就死机,保持按下KEY1 时的状态。
;/****************************************Copyright (c)*************************************************
;**--------------文件信息-------------------------------------------------------------------------------
;**文   件   名: IRQ.s
;**最后修改日期: 2007年2月3日
;**描        述: 允许中断嵌套时的IRQ
;**              每个工程应当有独立的这个文件的拷贝,并进行相应的修改   
;**--------------历史版本信息---------------------------------------------------------------------------
;** 创建人:
;** 版  本:
;** 日 期: 
;** 描 述: 原始版本
;******************************************************************************************************/
NoInt       EQU 0x80                            ; EQU必须顶格

USR32Mode   EQU 0x10
SVC32Mode   EQU 0x13
SYS32Mode   EQU 0x1f
IRQ32Mode   EQU 0x12
FIQ32Mode   EQU 0x11

        IMPORT    OSIntNesting
        IMPORT    OSIntExit
        IMPORT    OSTCBHighRdy
        IMPORT    OSTCBCur
        IMPORT    OSIntCtxSw     
        IMPORT  OsEnterSum
        IMPORT  StackUsr 

    CODE32    
        AREA    IRQ,CODE,READONLY

    MACRO
$IRQ_Label HANDLER $IRQ_Exception                
        EXPORT  $IRQ_Label                      ; 输出的标号
        IMPORT  $IRQ_Exception                  ; 引用的外部标号

$IRQ_Label
        SUB     LR, LR, #4                      ; 计算返回地址
        STMFD   SP!,{R0-R3, R12, LR}            ; 保存任务环境
        MRS     R3, SPSR                        ; 保存状态
        STMFD   SP, {R3,SP,LR}^                    ; 保存用户状态的SP,SPSR和LR, 注意不能回写
    NOP
    SUB        SP, SP,#4*3                        LDR     R2,  =OSIntNesting             
        LDRB    R1, [R2]
        ADD     R1, R1, #1
        STRB    R1, [R2]

    MSR    CPSR_c,    #(NoInt | SYS32Mode)           
        CMP     R1, #1
        LDREQ   R2, =StackUsr        
        LDREQ   SP, [R2]        
        
    BL      $IRQ_Exception                         LDR     R2, =OsEnterSum                 
        MOV     R1, #1
        STR     R1, [R2]

        BL      OSIntExit                                                                        
        LDR     R2, =OsEnterSum                
        MOV     R1, #0
        STR     R1, [R2]

        MSR     CPSR_c, #(NoInt | IRQ32Mode)    ; 
        LDMFD   SP, {R3,SP,LR}^            
        MSR     SPSR_cxsf, R3            
       ADD     SP, SP, #4*3                        LDR     R0, =OSTCBHighRdy                        LDR     R0, [R0]            
        LDR     R1, =OSTCBCur
        LDR     R1, [R1]
        CMP     R0, R1
        
        LDMEQFD SP!, {R0-R3, R12, PC}^          
        LDR     PC, =OSIntCtxSw                
    MEND

;/* 以下添加中断句柄,用户根据实际情况改变 */
IRQ_Handler            HANDLER   IRQ_Exception
Timer0_Handler      HANDLER   Timer0_Exception
Eint1_Handler       HANDLER   Eint1_Exception
    END

;/*******************************************************************************************************
;**                            End Of File
;********************************************************************************************************/
#define      BEE    (1 << 7) 
    void IRQ_Exception(void)
{
    
   while(1);          
}

void  Eint1_Exception(void)
{
    uint32 i;

    OS_ENTER_CRITICAL();

    while ((EXTINT & 0x02)!= 0)
    {
         EXTINT = 0x02;
    }

    VICVectAddr = 0x00;  // 通知中断控制器中断结束,该写操作将清零内部中断优先级硬件当中对应中断标志

    OS_EXIT_CRITICAL();

                
    IOCLR = BEE;
     i=0;
    while(i<200)
  {
     i++;
   }

    IOSET = BEE;
     i=0;
    while(i<200)
  {
     i++;
   }

    IOCLR = BEE;
     i=0;
    while(i<200)
  {
     i++;
   }

    IOSET = BEE;     
     i=0;
    while(i<200)
  {
     i++;
   }
 
   return; 
}

/********************************************************************************************************
** 函数名称: Timer0_Exception
** 功能描述: 定时器0中断服务程序
********************************************************************************************************/
       
     void Timer0_Exception(void)
{
    T0IR = 0x01;                // 匹配通道0中断标志清除
    VICVectAddr = 0;            // 通知中断控制器中断结束,该写操作将清零内部中断优先级硬件当中对应中断标志
    OSTimeTick();
}


/********************************************************************************************************
** 函数名称: Timer0Init
** 功能描述: 定时器0初始化
********************************************************************************************************/
        
    void Timer0Init(void)
{
    T0IR = 0xffffffff;                        //T0中断寄存器.有中断产生,IR对应位置位。可写IR清除中断
    T0TC = 0;                                   //T0定时器计数器
    T0TCR = 0x01;                            //T0计数器使能
    T0MCR = 0x03;                            //T0匹配控制寄存器。MRO与TC值匹配时产生中断和复位TC
    T0MR0 = (Fpclk / OS_TICKS_PER_SEC);        //T0匹配寄存器
 }

/********************************************************************************************************
** 函数名称: VICInit
** 功能描述: 向量中断控制器初始化
********************************************************************************************************/

        void VICInit(void)
{
    extern void IRQ_Handler(void);
    extern void Timer0_Handler(void);

    VICIntEnClr = 0xffffffff;                //清零中断使能寄存器中的对应位,并禁止对应的中断请求
    VICDefVectAddr = (uint32)IRQ_Handler;    //默认非向量地址寄存器

    VICVectAddr0 = (uint32)Timer0_Handler;    //向量地址寄存器0
    VICVectCntl0 = (0x20 | 0x04);            //向量控制寄存器0,向量IRQ使能。分配给此向量IRQ Slot的中
                                            //断请求编号。此时为4。即T0
    VICVectAddr1 = (uint32)Eint1_Handler;
    VICVectCntl1 = (0x20 | 0x0F);
    VICIntEnable = (1 << 4);                //中断使能寄存器。此时使能T0

 }


/********************************************************************************************************
** 函数名称: TargetInit
** 功能描述: 目标板初始化代码,在需要的地方调用,根据需要改变
********************************************************************************************************/

        void TargetInit(void)
{
    OS_ENTER_CRITICAL();
    srand((uint32) TargetInit);            //?
    VICInit();
    Timer0Init();
    OS_EXIT_CRITICAL();
}


/********************************************************************************************************
** 函数名称: InitialiseUART0
** 功能描述: 设置串口0 
** 输 入: bps:波特率
********************************************************************************************************/

        void InitialiseUART0(uint32 bps)
{      
    uint16 Fdiv;                                //除数值
    
    PINSEL0 = (PINSEL0 & 0xfffffff0) | 0x05;    /* 选择管脚为UART0        */

    U0LCR = 0x80;                               /* 允许访问分频因子寄存器 */
    Fdiv = (Fpclk / 16) / bps;                  /* 设置波特率             */
    U0DLM = Fdiv / 256;                            
    U0DLL = Fdiv % 256;                        
    U0LCR = 0x03;                               /* 禁止访问分频因子寄存器 */
                                                /* 且设置为8,1,n          */
    U0IER = 0x00;                               /* 禁止中断               */
    U0FCR = 0x00;                               /* 初始化FIFO             */


/********************************************************************************************************
** 函数名称: TargetResetInit
** 功能描述: 调用main函数前目标板初始化代码,根据需要改变,不能删除
********************************************************************************************************/

        void TargetResetInit(void)
{
#ifdef __DEBUG_RAM    
    MEMMAP = 0x2;                 
#endif

#ifdef __DEBUG_FLASH    
    MEMMAP = 0x1;                   //remap
#endif

#ifdef __IN_CHIP    
    MEMMAP = 0x1;                   //remap
#endif

PINSEL0 = (PINSEL0 & 0xFFFF0000) | 0x05 | 0x50;       // UART0 P0.0 TxD、P0.1 RxD; I2C P0.2 SCL、P0.3 SDA


    PLLCON = 1;                                          // sun  PLLE = 1,PLLC = 0启动PLL,但是不连接PLL 到系统内核
#if (Fpclk / (Fcclk / 4)) == 1
    VPBDIV = 0;
#endif
#if (Fpclk / (Fcclk / 4)) == 2
    VPBDIV = 2;
#endif
#if (Fpclk / (Fcclk / 4)) == 4
    VPBDIV = 1;
#endif

#if (Fcco / Fcclk) == 2
    PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5);
#endif
#if (Fcco / Fcclk) == 4
    PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5);
#endif
#if (Fcco / Fcclk) == 8
    PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5);
#endif
#if (Fcco / Fcclk) == 16
    PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5);
#endif
    PLLFEED = 0xaa;                                      PLLFEED = 0x55;                                  
    while((PLLSTAT & (1 << 10)) == 0);              
 PLLCON = 3;                                         PLLFEED = 0xaa;
    PLLFEED = 0x55;

    MAMCR = 0;                                     // MAM 功能禁止
#if Fcclk < 20000000
    MAMTIM = 1;                                     // MAM取指周期为1个处理器时钟
#else
#if Fcclk < 40000000
    MAMTIM = 2;                                   // MAM取指周期为2个处理器时钟
#else
    MAMTIM = 3;                                      // MAM取指周期为3个处理器时钟
#endif
#endif
    MAMCR = 2;                                   

    InitialiseUART0(115200);                     //115200为波特率



    CCR = 1;                                     // 时钟使能
    PREINT = Fpclk / 32768 - 1;            
   PREFRAC = Fpclk - (Fpclk / 32768) * 32768;   
    YEAR = 2004;
    MONTH = 3;
    DOM = 25;
    

    VICIntEnClr = 0xffffffff;                     // 清零中断使能寄存器中的对应位,并禁止对应的中断请求
    VICVectAddr = 0;                             // 向量地址寄存器
    VICIntSelect = 0;                             // 中断选择寄存器. 1对应FIQ, 0对应IRQ
    T0IR = 0xffffffff;                             // T0中断寄存器.有中断产生,IR对应位置位。可写IR清除中断
    T0TCR = 0x02;                                 // 0位使能禁止。1位复位计数器
}


#include "config.h"

#define       TASK_STK_SIZE     64
OS_STK        TaskStartStk[TASK_STK_SIZE];
OS_STK        TaskStk[TASK_STK_SIZE];
OS_STK        Task1Stk[TASK_STK_SIZE];

#define      KEY1        (1 << 14)             /* P0.14为key1 ,设为EINT1*/
#define      BEE        (1 << 7)              /* P0.07为蜂鸣器 */
#define      LEDCON1    (1 << 10)             /* P0.10为LED1 */ 
#define      LEDCON2    (1 << 11)             /* P0.11为LED2 */ 

void  TaskStart(void *data);
void  Task(void *data);
void  Task1(void *data);
/*******************************************************************************************************
** 函数名称: main
** 功能描述: c语言的主函数,由它启动多任务环境
** 调用模块: OSInit,OSTaskCreate,OSStart
*******************************************************************************************************/
        int main (void)
{
    OSInit();

    OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);

    OSStart();
    return 0;
}

/*******************************************************************************************************
** 函数名称: TaskStart
** 功能描述: μCOS-II的第一个任务,通常由它初始化目标板和建立其它任务
*******************************************************************************************************/

        void  TaskStart(void *pdata)
{
    pdata = pdata;                                                  /* 避免编译警告 */

    TargetInit();                                                  
    PINSEL0 = (PINSEL0 & 0xcf0f3fff)|0x20000000;                   
    IODIR |= BEE;     /* 设置蜂鸣器为输出*/
    IODIR |= LEDCON1;                                                // 设置LEDCON1为输出
    IODIR |= LEDCON2;                                                // 设置LEDCON2为输出
    IODIR &= ~KEY1;                                        /* 设置KEY1为输入*/

    IOSET = BEE;                                                    // 开始蜂鸣器不响

    EXTINT = 0x07;                                             // 清外部中断标志
    VICIntSelect = 0x0;                             VICIntEnable |= (1 << 15);                                        

 OSTaskCreate(Task, (void *)0, &TaskStk[TASK_STK_SIZE - 1], 8);      OSTaskCreate(Task1, (void *)0, &Task1Stk[TASK_STK_SIZE - 1], 9);
for(;;)
    {
    OSTimeDly(OS_TICKS_PER_SEC);                                    /* 延时1秒 */
    }


}

/*******************************************************************************************************
** 函数名称: Task
** 功能描述: μCOS-II的任务
********************************************************************************************************/
        void  Task(void *pdata)
{
    pdata = pdata;                                                  
    for (;;)
    {
    IOCLR = LEDCON1;        //亮
    OSTimeDly(OS_TICKS_PER_SEC / 10);                                   IOSET = LEDCON1;        //灭
    OSTimeDly(OS_TICKS_PER_SEC / 10);                                  IOCLR = LEDCON1;        //亮
    OSTimeDly(OS_TICKS_PER_SEC / 10);                                  IOSET = LEDCON1;        //灭
    OSTimeDly(OS_TICKS_PER_SEC / 10);                                   }
}


        void  Task1(void *pdata)
{
     pdata = pdata;                                                         
for (;;)
    {
     
    IOCLR = LEDCON2;        //亮
    OSTimeDly(OS_TICKS_PER_SEC / 2);                                   IOSET = LEDCON2;        //灭
    OSTimeDly(OS_TICKS_PER_SEC / 2);                               
    IOCLR = LEDCON2;        //亮
    OSTimeDly(OS_TICKS_PER_SEC / 2);                              
    IOSET = LEDCON2;        //灭
    OSTimeDly(OS_TICKS_PER_SEC / 2);                               
    }
    
}
/*******************************************************************************************************
**                            End Of File
********************************************************************************************************/



相关帖子

沙发
zlgARM| | 2007-2-9 08:29 | 只看该作者

RE

您观察一下是否能进入中断和正确返回。
在EINT1的中断里设置一个断点,然后您触发一下试试。

使用特权

评论回复
板凳
sunwensky|  楼主 | 2007-2-9 18:56 | 只看该作者

我设过了,不能进入

我在EINT1中断地方设置一个断点,可是不能进入


使用特权

评论回复
地板
sunwensky|  楼主 | 2007-2-9 19:15 | 只看该作者

我在EINT1设过了断点,不能进入

可奇怪的是,一按key1想进入EINT1,就会停机

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

11

帖子

0

粉丝