ARM2200 下的中断编程三 -
[导读]
一.在uc/os操作系统上设计中断函数时所要考虑的一些问题:1 .操作系统本身必须使用一个定时器中断源来作为系统节拍中断,它是操作系统工作的基础。2.只要没有关闭中断,中断服务程序就可以中断任何任务
一.在uc/os操作系统上设计中断函数时所要考虑的一些问题:
本文引用地址: http://www.21ic.com/app/mcu/201807/765794.htm
1 .操作系统本身必须使用一个定时器中断源来作为系统节拍中断,它是操作系统工作的基础。
2.只要没有关闭中断,中断服务程序就可以中断任何任务的运行,所以将中断服务程序看成比最高优先级(0)级的任务还要高的任务。
3.中断服务程序的功能应该尽量简单,只要将获取的异步事件通信给关联任务即可,后续处理由其关联任务完成。
4.实时操作系统UC/OS移植到ARM7体系的CPU上时,没有对FIQ进行处理,即FIQ是不受操作系统管理的。由于没有操作系统介入,FIQ的ISR无法与关联任务进行通信,所获取的信息不能及时得到关联任务的处理,故只能以原始形式保存在一个缓冲区内,等待以后进行离线处理。
注:由于使用FIQ方式进行采样,其ISR不受操作系统管理,所以只能用使能中断源和关闭中断源来控制FIQ中断过程。
二.在UC/OS操作系统上编写ISR
1.在UC/OS上编写ISR和在裸机上编写ISR时的区别
l进入中断:除了要保护现场外,还需要调用进入中断服务函数,用来通知实时操作系统,使UC/OS操作系统掌握当前中断的嵌套深度
l运行功能代码:除了完成ISR的实质公能的代码外,还要实现与其他任务进行通信的功能。通过这种通信功能使关联任务得到同步信号或数据,从而进入就绪状态。但是,在ISR中不允许调用延迟函数和可能被挂起的系统服务函数。
2.如何在UC/OS操作系统上编写ISR?
在UC/OS中用中断程序由以下几部分组成:
l添加中断句柄
l配置和初始化中断源
l配置向量中断控制器
l编写中断服务函数
1>.中断句柄:
在UC/OS操作系统上编写中断程序,必须在文件IRQ.S的尾部添加中断句柄:
XXX_HandlerHANDLERXXX_Exception
lXXX_Handler是ISR的起始地址,即汇编的起始地址,在初始化化向量控制器时作为中断向量地址使用。其中的XXX可根据具体的中断源名称命名
lHANDLER是句柄关键字,必须大写。
lXXX_Exception:是用C语言编写的功能函数名,该函数用汇编调用。其中的XXX可根据具体的中断源名称命名
Eg:如果要使用UART0作为一个中断源,用来接收数据,则需要在文件IRQ.S的尾部添加一个中断句柄:
Timer0_HandlerHANDLER Timer0_Exception
UART0_HandlerHANDLER UART0_Exception
RTC_HandlerHANDLERRTC_Exception
EINT3_HandlerHANDLEREINT3_Exception
2>.配置和初始化中断源
1>在一个中断源开始之前,需要配置和初始化中断源,使它按预定的方式工作。
还是以UART0为例:
/***********************************************************
*作者:tiger-john
*时间:2011年1月29日
*名称:UART0_Init
*功能:UART0初始化通讯波特率115200,8位数据位,1位停止位,无奇偶校验
*入口参数:bps串口波特率
*出口参数:无
***********************************************************/
voidUART0_Init(uint32 bps)
{
uint16Fdiv;
PINSEL0 = (PINSEL0 & ~(0xf) " 0x05) ;//设置UART0的引脚
U0LCR = 0x83;
Fdiv = (Fpclk>>4)/bps;
U0DLM = Fdiv>>8;
U0DLL = Fdiv%256;
U0LCR = 0x03;
U0FCR = 0x41;//使能FIFO,并设置触发点为4字节
U0IER = 0x01;//允许RBR中断,即接收中断
}
3>.向量中断控制器配置
为了使中断信号和对应的ISR联系起来,还必需对向量中断控制器进行配置。对于通道号为X的中断源XXXX,如果配置中断优先级为Y,则需要在target.c文件中的
VICInit ()函数中添加代码:
//声明中断源XXX的中断服务函数ISR
externvoidXXXX_Handler(void);
//将ISR入口地址填入向量寄存器Y
VICVectAddrY = (uint32)XXXX_Handler;
//向量中断方式,通道号为X
VICVectCntlY = (0x20 | X);
void VICInit(void)
{
extern void IRQ_Handler(void);
extern void Timer0_Handler(void);
extern void UART0_Handler(void);
extern void RTC_Handler(void);
extern void EINT3_Handler(void);
VICIntEnClr = 0xffffffff;
VICDefVectAddr = (uint32)IRQ_Handler;
VICVectAddr0 = (uint32)Timer0_Handler;
VICVectCntl0 = (0x20 | 0x04);
VICIntEnable = 1 << 4;
VICVectAddr1 = (uint32)UART0_Handler;
VICVectCntl1 = (0x20 | 6);
VICVectAddr2 = (uint32)RTC_Handler;
VICVectCntl2 = (0x20 | 13);
VICIntEnable = 1 << 13;
VICVectAddr3 = (uint32)EINT3_Handler;
VICVectCntl3 = (0x20 | 17);
VICIntEnable = 1 << 17;
}
4>.编写中断服务程序程序的功能函数
voidXXXX_Exception(void)
{
OS_ENTER_CRITICAL();//关中断
清除中断源;
通知中断控制器中断结束;
OS_EXIT_CRITICAL();//开中断
用户中断处理代码;
}
注:在UC/OS编写中断服务函数时,清除中断源和清除中断控制器的工作必须放在临界代码端中。即在UC/OS中编写中断服务函数时,必须要有OS_ENTER_CRITICAL();和OS_EXIT_CRITICAL()。
3.控制中断源的工作:
在程序运行过程中,可以通过使能中断源和关闭中断源来启动和关闭通道号为X的中断源。
VICIntEnable = 1 << X;//使能中断源X产生中断
VICIntEnClr = 1 << X;//禁止中断源X产生中断
三.设计ISR与关联任务之间的通信方法:
1. ISR的主要功能是响应异步事件,该异步事件将触发一系列操作。ISR设计的基本原则是:尽可能简短。
2.ISR与关联任务的通信方式有两种类型:信号型和数据型。
1>当使用信号量进行通信时,ISR只完成发送信号量的工作,表示事件已经发生,通过信号量的同步功能触发关联任务。
2>当使用数据进行通信时,ISR需要完成对异步事件的信息进行采集工作,然后使用消息邮箱(或消息队列)将数据发送给关联任务,由关联任务完成后续数据处理工作。
3>做项目时常见的三种情况:
?触发ISR的事件不包含数据:不需要对事件进行信息采集。此时,ISR使用信号量与关联任务进行通信。
?触发ISR的事件是包含数据的低频事件:将数据采集的工作放在关联任务中完成,(产生的时刻延迟与采样周期相比可以忽略不计,对采集数据的质量没有影响。此时,ISR使用信号量与关联任务进行通信,从而简化了ISR。
?触发ISR的事件是包含数据的中高频事件:数据采集的工作放在关联任务中完成时,产生的时延与采样周期相比不能忽略不计时,对采样数据的质量有影响。此时,关联任务从消息邮箱中得到消息的数据,并完成后续处理工作。
?触发ISR的事件是包含数据的非周期高频率事件:对于非周期高频事件,其最短事件间隔可能小于一个事件数据处理的耗时,如果使用消息邮箱进行通信,就可能会出现数据丢失现象。此时,数据采集的工作应该在ISR中完成,由ISR使用具有数据缓冲功能的消息队列与关联任务进行通信。关联任务从消息队列中得到消息的数据,并完成后续处理工作。
查看评论 回复