在easy2104中我建立两个任务,每个任务是使led不同时间间隔闪烁。并且利用EINT1作外部中断,并利用KEY1触发中断。当发生EINT1中断产生时,蜂鸣器响一段时间,中断返回。可是两个任务执行正常。一产生中断就死机,保持按下KEY1 时的状态。<br />;/****************************************Copyright (c)*************************************************<br />;**--------------文件信息-------------------------------------------------------------------------------<br />;**文 件 名: IRQ.s<br />;**最后修改日期: 2007年2月3日<br />;**描 述: 允许中断嵌套时的IRQ<br />;** 每个工程应当有独立的这个文件的拷贝,并进行相应的修改 <br />;**--------------历史版本信息---------------------------------------------------------------------------<br />;** 创建人:<br />;** 版 本:<br />;** 日 期: <br />;** 描 述: 原始版本<br />;******************************************************************************************************/<br />NoInt EQU 0x80 ; EQU必须顶格<br /><br />USR32Mode EQU 0x10<br />SVC32Mode EQU 0x13<br />SYS32Mode EQU 0x1f<br />IRQ32Mode EQU 0x12<br />FIQ32Mode EQU 0x11<br /><br /> IMPORT OSIntNesting<br /> IMPORT OSIntExit<br /> IMPORT OSTCBHighRdy<br /> IMPORT OSTCBCur<br /> IMPORT OSIntCtxSw <br /> IMPORT OsEnterSum<br /> IMPORT StackUsr <br /><br /> CODE32 <br /> AREA IRQ,CODE,READONLY<br /><br /> MACRO<br />$IRQ_Label HANDLER $IRQ_Exception <br /> EXPORT $IRQ_Label ; 输出的标号<br /> IMPORT $IRQ_Exception ; 引用的外部标号<br /><br />$IRQ_Label<br /> SUB LR, LR, #4 ; 计算返回地址<br /> STMFD SP!,{R0-R3, R12, LR} ; 保存任务环境<br /> MRS R3, SPSR ; 保存状态<br /> STMFD SP, {R3,SP,LR}^ ; 保存用户状态的SP,SPSR和LR, 注意不能回写<br /> NOP<br /> SUB SP, SP,#4*3 LDR R2, =OSIntNesting <br /> LDRB R1, [R2]<br /> ADD R1, R1, #1<br /> STRB R1, [R2]<br /><br /> MSR CPSR_c, #(NoInt | SYS32Mode) <br /> CMP R1, #1<br /> LDREQ R2, =StackUsr <br /> LDREQ SP, [R2] <br /> <br /> BL $IRQ_Exception LDR R2, =OsEnterSum <br /> MOV R1, #1<br /> STR R1, [R2]<br /><br /> BL OSIntExit <br /> LDR R2, =OsEnterSum <br /> MOV R1, #0<br /> STR R1, [R2]<br /><br /> MSR CPSR_c, #(NoInt | IRQ32Mode) ; <br /> LDMFD SP, {R3,SP,LR}^ <br /> MSR SPSR_cxsf, R3 <br /> ADD SP, SP, #4*3 LDR R0, =OSTCBHighRdy LDR R0, [R0] <br /> LDR R1, =OSTCBCur<br /> LDR R1, [R1]<br /> CMP R0, R1<br /> <br /> LDMEQFD SP!, {R0-R3, R12, PC}^ <br /> LDR PC, =OSIntCtxSw <br /> MEND<br /><br />;/* 以下添加中断句柄,用户根据实际情况改变 */<br />IRQ_Handler HANDLER IRQ_Exception<br />Timer0_Handler HANDLER Timer0_Exception<br />Eint1_Handler HANDLER Eint1_Exception<br /> END<br /><br />;/*******************************************************************************************************<br />;** End Of File<br />;********************************************************************************************************/<br />#define BEE (1 << 7) <br /> void IRQ_Exception(void)<br />{<br /> <br /> while(1); <br />}<br /><br />void Eint1_Exception(void)<br />{<br /> uint32 i;<br /><br /> OS_ENTER_CRITICAL();<br /><br /> while ((EXTINT & 0x02)!= 0)<br /> {<br /> EXTINT = 0x02;<br /> }<br /><br /> VICVectAddr = 0x00; // 通知中断控制器中断结束,该写操作将清零内部中断优先级硬件当中对应中断标志<br /><br /> OS_EXIT_CRITICAL();<br /><br /> <br /> IOCLR = BEE;<br /> i=0;<br /> while(i<200)<br /> {<br /> i++;<br /> }<br /><br /> IOSET = BEE;<br /> i=0;<br /> while(i<200)<br /> {<br /> i++;<br /> }<br /><br /> IOCLR = BEE;<br /> i=0;<br /> while(i<200)<br /> {<br /> i++;<br /> }<br /><br /> IOSET = BEE; <br /> i=0;<br /> while(i<200)<br /> {<br /> i++;<br /> }<br /> <br /> return; <br />}<br /><br />/********************************************************************************************************<br />** 函数名称: Timer0_Exception<br />** 功能描述: 定时器0中断服务程序<br />********************************************************************************************************/<br /> <br /> void Timer0_Exception(void)<br />{<br /> T0IR = 0x01; // 匹配通道0中断标志清除<br /> VICVectAddr = 0; // 通知中断控制器中断结束,该写操作将清零内部中断优先级硬件当中对应中断标志<br /> OSTimeTick();<br />}<br /><br /><br />/********************************************************************************************************<br />** 函数名称: Timer0Init<br />** 功能描述: 定时器0初始化<br />********************************************************************************************************/<br /> <br /> void Timer0Init(void)<br />{<br /> T0IR = 0xffffffff; //T0中断寄存器.有中断产生,IR对应位置位。可写IR清除中断<br /> T0TC = 0; //T0定时器计数器<br /> T0TCR = 0x01; //T0计数器使能<br /> T0MCR = 0x03; //T0匹配控制寄存器。MRO与TC值匹配时产生中断和复位TC<br /> T0MR0 = (Fpclk / OS_TICKS_PER_SEC); //T0匹配寄存器<br /> }<br /><br />/********************************************************************************************************<br />** 函数名称: VICInit<br />** 功能描述: 向量中断控制器初始化<br />********************************************************************************************************/<br /><br /> void VICInit(void)<br />{<br /> extern void IRQ_Handler(void);<br /> extern void Timer0_Handler(void);<br /><br /> VICIntEnClr = 0xffffffff; //清零中断使能寄存器中的对应位,并禁止对应的中断请求<br /> VICDefVectAddr = (uint32)IRQ_Handler; //默认非向量地址寄存器<br /><br /> VICVectAddr0 = (uint32)Timer0_Handler; //向量地址寄存器0<br /> VICVectCntl0 = (0x20 | 0x04); //向量控制寄存器0,向量IRQ使能。分配给此向量IRQ Slot的中<br /> //断请求编号。此时为4。即T0<br /> VICVectAddr1 = (uint32)Eint1_Handler;<br /> VICVectCntl1 = (0x20 | 0x0F);<br /> VICIntEnable = (1 << 4); //中断使能寄存器。此时使能T0<br /><br /> }<br /><br /><br />/********************************************************************************************************<br />** 函数名称: TargetInit<br />** 功能描述: 目标板初始化代码,在需要的地方调用,根据需要改变<br />********************************************************************************************************/<br /><br /> void TargetInit(void)<br />{<br /> OS_ENTER_CRITICAL();<br /> srand((uint32) TargetInit); //?<br /> VICInit();<br /> Timer0Init();<br /> OS_EXIT_CRITICAL();<br />}<br /><br /><br />/********************************************************************************************************<br />** 函数名称: InitialiseUART0<br />** 功能描述: 设置串口0 <br />** 输 入: bps:波特率<br />********************************************************************************************************/<br /><br /> void InitialiseUART0(uint32 bps)<br />{ <br /> uint16 Fdiv; //除数值<br /> <br /> PINSEL0 = (PINSEL0 & 0xfffffff0) | 0x05; /* 选择管脚为UART0 */<br /><br /> U0LCR = 0x80; /* 允许访问分频因子寄存器 */<br /> Fdiv = (Fpclk / 16) / bps; /* 设置波特率 */<br /> U0DLM = Fdiv / 256; <br /> U0DLL = Fdiv % 256; <br /> U0LCR = 0x03; /* 禁止访问分频因子寄存器 */<br /> /* 且设置为8,1,n */<br /> U0IER = 0x00; /* 禁止中断 */<br /> U0FCR = 0x00; /* 初始化FIFO */<br />} <br /><br />/********************************************************************************************************<br />** 函数名称: TargetResetInit<br />** 功能描述: 调用main函数前目标板初始化代码,根据需要改变,不能删除<br />********************************************************************************************************/<br /><br /> void TargetResetInit(void)<br />{<br />#ifdef __DEBUG_RAM <br /> MEMMAP = 0x2; <br />#endif<br /><br />#ifdef __DEBUG_FLASH <br /> MEMMAP = 0x1; //remap<br />#endif<br /><br />#ifdef __IN_CHIP <br /> MEMMAP = 0x1; //remap<br />#endif<br /><br />PINSEL0 = (PINSEL0 & 0xFFFF0000) | 0x05 | 0x50; // UART0 P0.0 TxD、P0.1 RxD; I2C P0.2 SCL、P0.3 SDA<br /><br /><br /> PLLCON = 1; // sun PLLE = 1,PLLC = 0启动PLL,但是不连接PLL 到系统内核<br />#if (Fpclk / (Fcclk / 4)) == 1<br /> VPBDIV = 0;<br />#endif<br />#if (Fpclk / (Fcclk / 4)) == 2<br /> VPBDIV = 2;<br />#endif<br />#if (Fpclk / (Fcclk / 4)) == 4<br /> VPBDIV = 1;<br />#endif<br /><br />#if (Fcco / Fcclk) == 2<br /> PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5);<br />#endif<br />#if (Fcco / Fcclk) == 4<br /> PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5);<br />#endif<br />#if (Fcco / Fcclk) == 8<br /> PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5);<br />#endif<br />#if (Fcco / Fcclk) == 16<br /> PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5);<br />#endif<br /> PLLFEED = 0xaa; PLLFEED = 0x55; <br /> while((PLLSTAT & (1 << 10)) == 0); <br /> PLLCON = 3; PLLFEED = 0xaa;<br /> PLLFEED = 0x55;<br /><br /> MAMCR = 0; // MAM 功能禁止<br />#if Fcclk < 20000000<br /> MAMTIM = 1; // MAM取指周期为1个处理器时钟<br />#else<br />#if Fcclk < 40000000<br /> MAMTIM = 2; // MAM取指周期为2个处理器时钟<br />#else<br /> MAMTIM = 3; // MAM取指周期为3个处理器时钟<br />#endif<br />#endif<br /> MAMCR = 2; <br /><br /> InitialiseUART0(115200); //115200为波特率<br /><br /><br /><br /> CCR = 1; // 时钟使能<br /> PREINT = Fpclk / 32768 - 1; <br /> PREFRAC = Fpclk - (Fpclk / 32768) * 32768; <br /> YEAR = 2004;<br /> MONTH = 3;<br /> DOM = 25;<br /> <br /><br /> VICIntEnClr = 0xffffffff; // 清零中断使能寄存器中的对应位,并禁止对应的中断请求<br /> VICVectAddr = 0; // 向量地址寄存器<br /> VICIntSelect = 0; // 中断选择寄存器. 1对应FIQ, 0对应IRQ<br /> T0IR = 0xffffffff; // T0中断寄存器.有中断产生,IR对应位置位。可写IR清除中断<br /> T0TCR = 0x02; // 0位使能禁止。1位复位计数器<br />}<br /><br /><br />#include "config.h"<br /><br />#define TASK_STK_SIZE 64<br />OS_STK TaskStartStk[TASK_STK_SIZE];<br />OS_STK TaskStk[TASK_STK_SIZE];<br />OS_STK Task1Stk[TASK_STK_SIZE];<br /><br />#define KEY1 (1 << 14) /* P0.14为key1 ,设为EINT1*/<br />#define BEE (1 << 7) /* P0.07为蜂鸣器 */<br />#define LEDCON1 (1 << 10) /* P0.10为LED1 */ <br />#define LEDCON2 (1 << 11) /* P0.11为LED2 */ <br /><br />void TaskStart(void *data);<br />void Task(void *data);<br />void Task1(void *data);<br />/*******************************************************************************************************<br />** 函数名称: main<br />** 功能描述: c语言的主函数,由它启动多任务环境<br />** 调用模块: OSInit,OSTaskCreate,OSStart<br />*******************************************************************************************************/<br /> int main (void)<br />{<br /> OSInit();<br /><br /> OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);<br /><br /> OSStart();<br /> return 0;<br />}<br /><br />/*******************************************************************************************************<br />** 函数名称: TaskStart<br />** 功能描述: μCOS-II的第一个任务,通常由它初始化目标板和建立其它任务<br />*******************************************************************************************************/<br /><br /> void TaskStart(void *pdata)<br />{<br /> pdata = pdata; /* 避免编译警告 */<br /><br /> TargetInit(); <br /> PINSEL0 = (PINSEL0 & 0xcf0f3fff)|0x20000000; <br /> IODIR |= BEE; /* 设置蜂鸣器为输出*/<br /> IODIR |= LEDCON1; // 设置LEDCON1为输出<br /> IODIR |= LEDCON2; // 设置LEDCON2为输出<br /> IODIR &= ~KEY1; /* 设置KEY1为输入*/<br /><br /> IOSET = BEE; // 开始蜂鸣器不响<br /><br /> EXTINT = 0x07; // 清外部中断标志<br /> VICIntSelect = 0x0; VICIntEnable |= (1 << 15); <br /><br /> OSTaskCreate(Task, (void *)0, &TaskStk[TASK_STK_SIZE - 1], 8); OSTaskCreate(Task1, (void *)0, &Task1Stk[TASK_STK_SIZE - 1], 9);<br />for(;;)<br /> {<br /> OSTimeDly(OS_TICKS_PER_SEC); /* 延时1秒 */<br /> }<br /><br /><br />}<br /><br />/*******************************************************************************************************<br />** 函数名称: Task<br />** 功能描述: μCOS-II的任务<br />********************************************************************************************************/<br /> void Task(void *pdata)<br />{<br /> pdata = pdata; <br /> for (;;)<br /> {<br /> IOCLR = LEDCON1; //亮<br /> OSTimeDly(OS_TICKS_PER_SEC / 10); IOSET = LEDCON1; //灭<br /> OSTimeDly(OS_TICKS_PER_SEC / 10); IOCLR = LEDCON1; //亮<br /> OSTimeDly(OS_TICKS_PER_SEC / 10); IOSET = LEDCON1; //灭<br /> OSTimeDly(OS_TICKS_PER_SEC / 10); }<br />}<br /><br /><br /> void Task1(void *pdata)<br />{<br /> pdata = pdata; <br />for (;;)<br /> {<br /> <br /> IOCLR = LEDCON2; //亮<br /> OSTimeDly(OS_TICKS_PER_SEC / 2); IOSET = LEDCON2; //灭<br /> OSTimeDly(OS_TICKS_PER_SEC / 2); <br /> IOCLR = LEDCON2; //亮<br /> OSTimeDly(OS_TICKS_PER_SEC / 2); <br /> IOSET = LEDCON2; //灭<br /> OSTimeDly(OS_TICKS_PER_SEC / 2); <br /> }<br /> <br />}<br />/*******************************************************************************************************<br />** End Of File<br />********************************************************************************************************/<br /><br /><br /><br /> |
|