FreeRTOS中断
中断的寄存器:
NVIC(Cortex-M内核的MCU)和SCB中
特殊寄存器:(在FreeRTOSConfig.h)
1.PRIMASK
PRIMASK:当需要暂时屏蔽所有中断执行一些对时序要求严格的任务,这个时候就可以使用PRIMASK寄存器
//使用CPS
CPSIE I;//使能PRIMASK中断
CPSID I;//禁止PRIMASK中断
//通过MRS和MSR指令访问
MOVS R0, #1
MSR PRIMASK, R0;//将1写入PRIMASK禁止所有中断,写0使能中断
2.FAULTMASK
简单来说,就是升级版的PRIMASK,可以将HardFault一起屏蔽掉
//使用CPS
CPSIE F;//使能中断
CPSID F;//禁止中断
//通过MRS和MSR指令访问
MOVS R0, #1
MSR PRIMASK, R0;//将1写入禁止所有中断,写0使能中断
3.还有一种是BASEPRI寄存器,可以通过汇编编程具体设置需要屏蔽的中断(关闭低于0X50的中断)
//通过MRS和MSR指令访问,使能中断
MOVS R0, #0X50
MSR BASEPRI, R0;
//通过MRS和MSR指令访问,取消中断
MOVS R0, #0
MSR BASEPRI, R0;
FreeRTOS的中断配置宏
-
1.configPRIO__BITS :配置用几位优先级(具体查各mcu)
-
2.configLIBRARY__LOWEST__INTERRUPT__PRIORITY:用来设置最低优先级(具体查各mcu)
-
3.configKERNEL_INTERRUPT_PRIORITY:设置内核优先级:
-
4.configLIBRARY__MAX__SYSCALL__INTERRUPT__PRIORITY:管理freertos系统的最大优先级(数值比它小的不管理!)
-
5.configMAX__SYSCALL__INTERRUPT__PRIORITY:低于优先级的中断可以使用API函数,高于此优先级无法中断FreeRTOS,中断同样也无法调用。
FreeRTOS开关中断
-
1.vPortRaiseBASEPRI()//关闭中断
-
2.vPortSetBASEPRI(0)//使能中断
示例程序(定时器的配置基本没有大的变化)(若要管理精确,则需要在定义宏的地方确定管理范围)
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 256
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define INTERRUPT_TASK_PRIO 2
//任务堆栈大小
#define INTERRUPT_STK_SIZE 256
//任务句柄
TaskHandle_t INTERRUPTTask_Handler;
//任务函数
void interrupt_task(void *p_arg);
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
delay_init(); //延时函数初始化
uart_init(115200); //初始化串口
LED_Init(); //初始化LED
TIM3_Int_Init(10000-1,7200-1); //初始化定时器3,定时器周期1S
TIM5_Int_Init(10000-1,7200-1); //初始化定时器5,定时器周期1S
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建中断测试任务
xTaskCreate((TaskFunction_t )interrupt_task, //任务函数
(const char* )"interrupt_task", //任务名称
(uint16_t )INTERRUPT_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )INTERRUPT_TASK_PRIO, //任务优先级
(TaskHandle_t* )&INTERRUPTTask_Handler); //任务句柄
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//中断测试任务函数
void interrupt_task(void *pvParameters)
{
static u32 total_num=0;
while(1)
{
total_num+=1;
if(total_num==5)
{
printf("关闭中断.............\r\n");
portDISABLE_INTERRUPTS(); //关闭中断
delay_xms(5000); //延时5s
printf("打开中断.............\r\n"); //打开中断
portENABLE_INTERRUPTS();
}
LED0=~LED0;
vTaskDelay(1000);
}
}