uCOSii系统的中断管理
1、在使用uCOSii系统时,中断服务程序需要调用两个函数OSIntEnter()和OSIntExit()。
OSIntEnter() 进入中断时,用OSIntNesting来统计中断嵌套次数,告知uCOSii系统,当前中断服务程序正在执行;
OSIntExit()退出中断时,用OSIntNesting来统计中断嵌套次数,告知uCOSii系统,当前的中断已经处理完成;
注意:切记上述两个函数必须成对出现中断服务程序中,这种用法和FreeRTOS不同。
2、OSIntEnter()函数
函数功能:在进入中断服务函数时,需要用OSIntNesting来统计中断嵌套次数
void OSIntEnter (void)
{
if (OSRunning == OS_TRUE)
{
if (OSIntNesting < 255u)
{
OSIntNesting++;/*中断嵌套次数加1*/
}
}
}
3、OSIntExit()函数
函数功能:在退出中断服务函数时,需要用OSIntNesting来统计中断嵌套次数
void OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR cpu_sr = 0u;
#endif
if (OSRunning == OS_TRUE)
{
OS_ENTER_CRITICAL();//进入临界区(无法被中断打断),需要定义cpu_sr变量
if (OSIntNesting > 0u)
{/*防止OSIntNesting在做减法时由0x00变为0xFF*/
OSIntNesting--;/*中断嵌套次数减1*/
}
if (OSIntNesting == 0u)
{/*中断嵌套次数OSIntNesting =0*/
if (OSLockNesting == 0u)
{/*多任务上锁嵌套OSLockNesting=0表示没有上锁 */
OS_SchedNew();
//从”准备好的任务”中,找出”优先级最高的任务”的优先级,赋值给OSPrioHighRdy
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
//根据OSPrioHighRdy,读取”最高优先级任务控制块的指针” ,保存到OSTCBHighRdy
if (OSPrioHighRdy != OSPrioCur)
{
//OSPrioHighRdy为最高优先级任务的优先级
//OSPrioCur为当前任务的优先级
//如果”当前任务的优先级”和”最高优先级任务的优先级”不等,则切换任务
//在中断服务程序中,若出现更高优先级任务处于准备状态时,则执行任务切换功能
#if OS_TASK_PROFILE_EN > 0u
OSTCBHighRdy->OSTCBCtxSwCtr++;//切换任务次数计数器加1
#endif
OSCtxSwCtr++;//上下文切换次数计数器加1
OSIntCtxSw();
/*OSIntCtxSw()表示在中断服务程序中执行任务切换,退出中断便执行新任务*/
}
}
}
OS_EXIT_CRITICAL();//退出临界区(可以被中断打断)
}
}
4、uCOSii中断引用举例
#include "Timer2_Task.h"
#include "includes.h"
#include "LED.h"
u16 MilliSecond;//毫秒计数器
void TIM2_Interrupt_Initializtion(u16 arr,u16 psc);
//通用定时器2中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器2!
//TIM2_Interrupt_Initializtion(1000,36);
//当arr=1000,psc=36时,则为0.5ms,误差为0.5us;
//TIM2_Interrupt_Initializtion(2000,36);
//当arr=2000,psc=36时,则为1ms,误差为0.5us;
//TIM2_Interrupt_Initializtion(4000,36);
//当arr=4000,psc=36时,则为2ms,误差为0.5us;
void TIM2_Interrupt_Initializtion(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//使能定时器TIM2的APB1外设时钟
//定时器TIM2初始化
TIM_TimeBaseStructure.TIM_Period = arr-1;
//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc-1;
//设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//设置时钟分割:TDTS = Tck_tim
//计算公式:arr*psc/72000000/1,当arr=1000,psc=72时,则为1ms,误差为1us;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
//根据指定的参数初始化TIMx的时间基数单位
TIM_SetCounter(TIM2,0); //设置TIM2的计数器值为0;
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除TIM2溢出的待处理标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); //清除TIM2中断的待处理位
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //允许TIM2溢出产生中断
//中断优先级NVIC设置
//NVIC_PriorityGroup_4设置NVIC中断分组4:表示抢占优先级为4位,取值为0~15,没有响应优先级,取值为0
//NVIC_PriorityGroup_3设置NVIC中断分组3:表示抢占优先级为3位,取值为0~7,响应优先级只有1位,取值为0~1
//NVIC_PriorityGroup_2设置NVIC中断分组3:表示抢占优先级为2位,取值为0~3,响应优先级只有2位,取值为0~3
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 11;
//设置抢占优先级为11
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置响应优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);
//根据NVIC_InitStruct中指定的参数初始化NVIC嵌套向量中断控制寄存器
TIM_Cmd(TIM2, ENABLE);//使能TIM2外设
MilliSecond=0;//毫秒计数器
}
//函数功能:TIM2每1ms中断一次
void TIM2_IRQHandler()
{
OSIntEnter();//在进入中断服务函数时,需要用OSIntNesting来统计中断嵌套次数
if (TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET) //TIM2计数器溢出产生中断
{
MilliSecond++;//毫秒计数器加1
if(MilliSecond>=1000)//TIM2每1ms中断一次,1000表示1秒
{
MilliSecond=0;
LED0=!LED0;
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
//清除TIM2计数器的溢出中断标志;
}
OSIntExit();//在退出中断服务函数时,需要用OSIntNesting来统计中断嵌套次数
}
5、uCOSii系统不是免费的
uCOSii是开源的,但不是免费的。如果你真想要用免费的系统,还是选择FreeRTOS吧。从技术角度或者从商业角度,同FreeRTOS相比,uCOSii没有任何优势。FreeRTOS是真正免费的系统。