zoukankan      html  css  js  c++  java
  • 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的任务优先级和中断优先级最大的不同就是,任务优先级数的值越大,任务的优先级越大。

  • 相关阅读:
    使用sql语句查询表结构
    plsql出现录相机后卡屏解决方法
    oracle的“ORA-01480:STR绑定值的结尾Null字符缺失”错误
    oracle创建表空间并对用户赋权
    Scrapy安装错误(error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools)
    震惊你不知道的python
    django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'
    python3 ImportError: No module named 'ConfigParser'
    python import报错
    No migrations to apply(django不能创建数据库中的表的问题)
  • 原文地址:https://www.cnblogs.com/r1chie/p/14128223.html
Copyright © 2011-2022 走看看