这里写目录标题
- 一、什么是中断?(了解)
- 二、中断优先级分组设置(熟悉)
- 三、中断相关寄存器(熟悉)
- 四、FreeRTOS中断管理实验(掌握)
一、什么是中断?(了解)
简介:让CPU打断正常运行的程序,转而去处理紧急的事件(程序),就叫中断
中断执行机制,可简单概括为三步:
1,中断请求:外设产生中断请求(GPIO外部中断、定时器中断等)
2,响应中断:CPU停止执行当前程序,转而去执行中断处理程序(ISR)
3,退出中断:执行完毕,返回被打断的程序处,继续往下执行
二、中断优先级分组设置(熟悉)
ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器 ,但STM32,只用了中断优先级配置寄存器的高4位 [7 : 4],所以STM32提供了最大16级的中断优先等级
STM32 的中断优先级可以分为抢占优先级和子优先级
抢占优先级: 抢占优先级高的中断可以打断正在执行但抢占优先级低的中断
子优先级:当同时发生具有相同抢占优先级的两个中断时,子优先级数值小的优先执行
注意:中断优先级数值越小越优先
一共有 5 种分配方式,对应着中断优先级分组的 5 个组
通过调用函数HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)即可完成设置(在HAL_Init中设置)
特点:
1、低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS 的API函数
2、建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理
3、中断优先级数值越小越优先,任务优先级数值越大越优先
三、中断相关寄存器(熟悉)
三个系统中断优先级配置寄存器,分别为 SHPR1、 SHPR2、 SHPR3
SHPR1寄存器地址:0xE000ED18
SHPR2寄存器地址:0xE000ED1C
SHPR3寄存器地址:0xE000ED20
FreeRTOS如何配置PendSV和Systick中断优先级?
所以:PendSV和SysTick设置最低优先级
设置最低:保证系统任务切换不会阻塞系统其他中断的响应
三个中断屏蔽寄存器,分别为 PRIMASK、 FAULTMASK 和BASEPRI
FreeRTOS所使用的中断管理就是利用的BASEPRI这个寄存器
BASEPRI:屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断
比如: BASEPRI设置为0x50,代表中断优先级在5 ~15内的均被屏蔽,0 ~4的中断优先级正常执行
关中断程序示例:
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
msr basepri, ulNewBASEPRI
dsb
isb
}
}
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 /* FreeRTOS可管理的最高中断优先级 */
中断优先级在5 ~ 15的全部被关闭
当BASEPRI设置为0x50时:
在中断服务函数中调度FreeRTOS的API函数需注意:
1、中断服务函数的优先级需在FreeRTOS所管理的范围内
2、在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数
开中断程序示例:
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
__asm
{
msr basepri, ulBASEPRI
}
}
FreeRTOS中断管理就是利用BASEPRI寄存器实现的
四、FreeRTOS中断管理实验(掌握)
1、实验目的:学会使用FreeRTOS的中断管理!
本实验会使用两个定时器,一个优先级为4,一个优先级为6,注意:系统所管理的优先级范围:5~15,
现象:两个定时器每1s,打印一段字符串,当关中断时,停止打印,开中断时持续打印。
2、实验设计:将设计2个任务:start_task、task1
2个任务的功能如下
在freertos_demo.c里,设置任务1
/**
* @brief start_task
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 初始化TIM3、TIM5 */
btim_tim3_int_init(10000-1, 7200-1); //1s计时
btim_tim5_int_init(10000-1, 7200-1);
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
uint32_t task1_num = 0;
while (1)
{
if (++task1_num == 5)
{
printf("FreeRTOS关闭中断\r\n");
portDISABLE_INTERRUPTS(); /* FreeRTOS关闭中断 */
delay_ms(5000);
printf("FreeRTOS打开中断\r\n");
portENABLE_INTERRUPTS(); /* FreeRTOS打开中断 */
}
vTaskDelay(1000);
}
}
在bim.c里配置定时器后,在中断服务函数里设置
/**
* @brief 定时器更新中断回调函数
* @param htim:定时器句柄指针
* @retval 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim == (&g_tim3_handle))
{
printf("TIM3输出\r\n");
}
else if (htim == (&g_tim5_handle))
{
printf("TIM5输出\r\n");
}
}
实验结果:
TIM3的优先级是4,TIM5的优先级是6,首先打印"TIM3输出"和“TIM5”五次,然后执行FreeRTOS关闭中断,中断优先级高于5的TIM3中断继续执行,中断优先级低于5的TIM5中断停止运行,5s后FreeRTOS打开中断,TIM5中断可以执行