FreeRTOS中开关中断的宏定义(往BASEPRI寄存器中写入值):
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portENTER_CRITICAL() PortEnterCritical()
// portENABLE_INTERRUPTS() 使能中断,往BASEPRI寄存器中写入0
static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI)
{
__asm
{
/* Barrier instructions are not used as this function is only used to
lower the BASEPRI value. */
msr basepri, ulBASEPRI
}
}
// portENTER_CRITICAL() 关闭中断,往BASEPRI寄存器中写入屏蔽阈值
static portFORCE_INLINE void vPortRaiseBASEPRI(void)
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
/* Set BASEPRI to the max syscall priority to effect a critical
section. */
msr basepri, ulNewBASEPRI
dsb
isb
}
}
测试实验:使用两个定时器,中断优先级分别为 4(不会被BASEPRI屏蔽) 和 5(可以被BASEPRI屏蔽),两个定时器中断服务函数,每隔 1s 打印测试语句,然后再任务中关闭一段时间,查看定时器输出。
stm32cubemx配置如下:
程序如下所示:
HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_Base_Start_IT(&htim4);
// 创建开始任务
xTaskCreate((TaskFunction_t ) start_task,
(char * ) "start_task",
(uint16_t ) START_TASK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t * ) &Start_Task_Handle);
void start_task(void *pvParameters)
{
// 创建中断任务
xTaskCreate((TaskFunction_t ) interrupt_task,
(char * ) "interrupt_task",
(uint16_t ) INTERRUPT_TASK_SIZE,
(void * ) NULL,
(UBaseType_t ) INTERRUPT_TASK_PRIO,
(TaskHandle_t * ) &Interrupt_Task_Handle);
// 删除开始任务
vTaskDelete(Start_Task_Handle);
}
// 中断测试任务
void interrupt_task(void *pvParameters)
{
uint16_t cnt = 0;
for (; ;)
{
// 运行2次后进入中断测试
if (++cnt == 2)
{
printf("\n关闭中断...");
portDISABLE_INTERRUPTS();
// 堵塞延时3s,不会进入任务调度,但可以执行中断服务
HAL_Delay(3000);
printf("\n打开中断...");
portENABLE_INTERRUPTS();
}
LED_R_TOGGLE;
vTaskDelay(1000);
}
}
void TIM3_IRQHandler(void)
{
printf("\nTIM3 Interrupt");
}
void TIM4_IRQHandler(void)
{
printf("\nTIM4 Interrupt");
}
实验现象如下所示: