• 2.FreeRTOS中断优先级和任务优先级


    FreeRTOS中断优先级和任务优先级

    • 架构:Cortex-M3

    • 版本:FreeRTOS V9.0.0

    • 前言:

      最开始,我并没有搞清楚什么是中断优先级和任务优先级,但看了部分资料后发现这两个并没有半毛钱关系,于是便有了这篇笔记,本篇文章以Cortex-M3(STM32F103)为例子。

    1.Cortex-M3的中断优先级

    ​ 根据Cortex-M3权威指南,每个外部中断都有一个可编程的中断优先级寄存器。并且记住优先级越大在这个寄存器的值是越小的。在STM32F103中,该寄存器的高四位才是代表优先级值,低四位没用。

    ​ 优先级分组寄存器PRIGROUP,把优先级分为抢占优先级和子优先级,一般为了方便,我们把它设为NVIC_PriorityGroup_4,意思就是4个bit都为抢占优先级,所以一共是0~15个级别的优先级,0的最优先级大,15的最优先级小。

    1.1 PendSV和SysTick的中断优先级

    ​ 在FreeRTOS中SysTickPendSV的优先级都是最低的,具体在开启调度器函数BaseType_t xPortStartScheduler( void )里面赋值:

    	/* Make PendSV and SysTick the lowest priority interrupts. */
    	portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
    	portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
    

    portNVIC_SYSPRI2_REG实际上是0xE000_ED20-0xE000_ED23(一共四字节),22-23分别是设置PendSV和Systick优先级的寄存器。portNVIC_PENDSV_PRIportNVIC_SYSTICK_PRI**的值具体展开:

    
    1. #define __NVIC_PRIO_BITS          4 /*!< STM32 uses 4 Bits for the Priority Levels    */
    2. #define configPRIO_BITS       		__NVIC_PRIO_BITS
    
    3. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			15         //中断最低优先级
    
    4. #define configKERNEL_INTERRUPT_PRIORITY     ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
    
    5.#define portNVIC_PENDSV_PRI					( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
    6.#define portNVIC_SYSTICK_PRI				( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
        
        
    

    前面说了,STM32使用了4个bit来表示优先级,并且15是为最低优先级,很明白,把(0xFFFF0000)这个优先级放到了0xE000_ED22和0xE000_ED23中,即把Systick和PendSV的优先级设为最低。

    1.1.2 在FreeRTOS中关闭中断

    Cortex-M3中有一个寄存器BASEPRI,和配置优先级一样,当低于这个寄存器的优先级数,会被屏蔽,比如设置了优先级为5,那么优先级0~4会被关闭,FreeRTOS用函数portDISABLE_INTERRUPTS() portENABLE_INTERRUPTS() 控制中断开关,根据配置的宏configMAX_SYSCALL_INTERRUPT_PRIORITY确认屏蔽的优先级数。

    1.1.3 FreeRTOS利用关闭中断实现临界代码区的保护

    1.1.3.1普通临界区

    所谓临界区就是不希望有中断来打扰某段程序的执行,用函数taskENTER_CRITICAL()taskEXIT_CRITICAL() ,具体看如何实现:

    void vPortEnterCritical( void )
    {
    	portDISABLE_INTERRUPTS();
    	uxCriticalNesting++;
    
    	/* This is not the interrupt safe version of the enter critical function so
    	assert() if it is being called from an interrupt context.  Only API
    	functions that end in "FromISR" can be used in an interrupt.  Only assert if
    	the critical nesting count is 1 to protect against recursive calls if the
    	assert function also uses a critical section. */
    	if( uxCriticalNesting == 1 )
    	{
    		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
    	}
    }
    
    

    没错,就是利用BASEPRI寄存器来关闭中断,当进入调用这个函数时全局变量uxCriticalNesting会加1,那么我们基本可以得出,退出临界区一定是当uxCriticalNesting为1时,会打开中断,退出临界区函数如下:

    void vPortExitCritical( void )
    {
    	configASSERT( uxCriticalNesting );
    	uxCriticalNesting--;
    	if( uxCriticalNesting == 0 )
    	{
    		portENABLE_INTERRUPTS();
    	}
    }
    
    1.1.3.2中断临界区

    除此之外还有在保护中断临界区的函数,就是不希望某个中断里的代码不被另一个中断打断,用函数taskENTER_CRITICAL_FROM_ISR() taskEXIT_CRITICAL_FROM_ISR( x ),函数实现上普通临界区是一模一样的

    2. FreeRTOS 的任务优先级

    FreeRTOS的任务优先级和中断优先级最大的不同就是,任务优先级数的值越大,任务的优先级越大。

  • 相关阅读:
    Android Virtual Device(AVD)屏幕大小调整
    修改obj三维模型文件中坐标z为其相反数
    AE安装检测(C++)
    单件模式
    地形转立体实验截图
    保持几何特征的三维建筑物模型简化方法 毕业硕士论文
    判断多边形点串存放序列
    mathematica 查找 mathpass 注册文件位置
    在线调色板搜集
    图标资源搜集
  • 原文地址:https://www.cnblogs.com/r1chie/p/14128223.html
Copyright © 2020-2023  润新知