目录
说明:
一、中断基础
1.1、中断理解
1.2、中断执行步骤
1.3、中断寄存器选择位
1.4、中断优先级分类
二、中断优先级分组设置
2.1、分类
2.2、特点
三、中断有关寄存器
3.1、SHPR1寄存器
3.2、SHPR2寄存器
3.3、SHPR3寄存器
3.4、FreeRTOS中配置PendSV、Systick中断优先级步骤
四、FreeRTOS中断管理
4.1、中断有关函数
4.2、中断示例
说明:
1)以下内容多为概念了解与步骤分析
2)暂无个人示例代码,使用的是FreeRTOS的示例代码
3)若想移植代码测试的,请移步其它地方寻找,下文内容暂无个人示例代码供测试
关于其它:
1)操作系统:win 10
2)平台:keil 5 mdk
3)语言:c语言
4)板子:STM32系列移植FreeRTOS
一、中断基础
1.1、中断理解
让CPU打断正常运行的程序,转而去处理的事件(程序),称为中断。
1.2、中断执行步骤
1)中断请求,外设产生中断请求(GPIO外部中断、定时器中断);
2)响应中断,CPU停止执行当前程序,转而去处理中断程序(ISR);
3)退出中断,返回被中断打断的程序位置,继续执行程序。
1.3、中断寄存器选择位
1)ARM Cortex-M使用了8位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器;
2)但STM32,只用了中断优先级配置寄存器的高4位[7 : 4](如下图1),所以STM32提供了最大16级的中断优先等级,用于表达优先级没有实现,读回零;
图1
1.4、中断优先级分类
1)STM32的中断优先级可以分为抢占优先级和子优先级
2)抢占优先级:抢占优先级高的中断可以打断正在执行但抢占优先级低的中断
3)子优先级:当同时发生具有相同抢占优先级的两个中断时,子优先级数值小的优先执行
二、中断优先级分组设置
2.1、分类
可以分为5种,如下图2:
图2
2.2、特点
1)低于宏定义configMAX_ SYSCALL INTERRUPT_ PRIORITY优先级的中断里才允许调用FreeRTOS的API函数;
2)建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理
(调用函数HAL_ NVIC_ SetPriorityGrouping(NVIC PRIORITYGROUP_4)这是HAL库,标准库应该是:NVIC_ SetPriorityGrouping(NVIC PRIORITYGROUP_4)
3)中断优先级数值越小越优先,任务优先级数值越大越优先
三、中断有关寄存器
3.1、SHPR1寄存器
寄存器地址:0xE000ED18
3.2、SHPR2寄存器
寄存器地址:0xE000ED1C
3.3、SHPR3寄存器
寄存器地址:0xE000ED20
具体如下图3(来自Cortex M3权威指南(中文)第286页中):
图3
3.4、FreeRTOS中配置PendSV、Systick中断优先级步骤
1)SHPR3寄存器地址获取,左移16位得到设置PendSV的寄存器地址
2)SHPR3寄存器地址获取,左移24位得到设置Systick的寄存器地址
3)通过一系列赋值,最后一步是进行汇编操作直接赋值给寄存器,进行配置,最后设置出PendSV与Systick的优先级为15,最低优先级
四、FreeRTOS中断管理
4.1、中断有关函数
关中断函数原型:portDISABLE_INTERRUPTS()
如果使用的移植支持 configMAX_SYSCALL_INTERRUPT_PRIORITY( 或 configMAX_API_CALL_INTERRUPT_PRIORITY)常量,那么 taskDISABLE_interrupts 将 禁用所有中断,或在 configMAX_SYSCALL_INTRUPT_PROJECT 设置之前屏蔽(禁用)中断。 检查 taskDISABLE_INTERRUPTS 在使用的移植中的实现。
如果使用的移植不支持 configMAX_SYSCALL_INTERRUPT_PRIORITY 常量, 那么 taskDISABLE_INTERRUPTS() 将对所有可屏蔽的中断进行全局禁用。
通常情况下不会直接调用该宏,而是使用 taskENTER_CRITICAL() 和 taskEXIT_CRITICAL() 来替代。
开中断函数原型:portENABLE_INTERRUPTS()
启用微控制器中断的宏。
通常情况下不会直接调用该宏,而是使用 taskENTER_CRITICAL() 和 taskEXIT_CRITICAL() 来替代。
4.2、中断示例
板子不在身边,无法测试,之后补上。以下是FreeRTOS官方示例:
/* A function that makes use of a critical section. */ void vDemoFunction( void ) { /* Enter the critical section. In this example, this function is itself called from within a critical section, so entering this critical section will result in a nesting depth of 2. */ taskENTER_CRITICAL(); /* Perform the action that is being protected by the critical section here. */ /* Exit the critical section. In this example, this function is itself called from a critical section, so this call to taskEXIT_CRITICAL() will decrement the nesting count by one, but not result in interrupts becoming enabled. */ taskEXIT_CRITICAL(); } /* A task that calls vDemoFunction() from within a critical section. */ void vTask1( void * pvParameters ) { for( ;; ) { /* Perform some functionality here. */ /* Call taskENTER_CRITICAL() to create a critical section. */ taskENTER_CRITICAL(); /* Execute the code that requires the critical section here. */ /* Calls to taskENTER_CRITICAL() can be nested so it is safe to call a function that includes its own calls to taskENTER_CRITICAL() and taskEXIT_CRITICAL(). */ vDemoFunction(); /* The operation that required the critical section is complete so exit the critical section. After this call to taskEXIT_CRITICAL(), the nesting depth will be zero, so interrupts will have been re-enabled. */ taskEXIT_CRITICAL(); } }