在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 ********************************************************************************************************/
|
|