当前位置: 首页 > news >正文

STM32F103移植FreeRTOS必须搞明白的系列知识---4(FreeRTOSConfig.h配置文件)

STM32F103移植FreeRTOS必须搞明白的系列知识---1(Cortex-CM3中断优先级)

STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

STM32F103移植FreeRTOS必须搞明白的系列知识---3(堆栈)

STM32F103移植FreeRTOS必须搞明白的系列知识---4(FreeRTOSConfig.h配置文件)
 

目录

一、FreeRTOSConfig.h配置文件概述

二、configCPU_CLOCK_HZ

三、configTICK_RATE_HZ

四、configMAX_PRIORITIES

五、configMINIMAL_STACK_SIZE

六、configTOTAL_HEAP_SIZE

七、configKERNEL_INTERRUPT_PRIORITY

八、configMAX_SYSCALL_INTERRUPT_PRIORITY 

九、实例

       1、配置configMAX_PRIORITIES

       2、配置configTOTAL_HEAP_SIZE

        3、配置configKERNEL_INTERRUPT_PRIORITY

        4、配置configMAX_SYSCALL_INTERRUPT_PRIORITY

        5、创建5个任务

        6、配置NVIC中断优先级组和抢占优先级和响应优先级


一、FreeRTOSConfig.h配置文件概述

        FreeRTOSConfig.h配置文件是由FreeRTOS官网提供给用户针对具体的某一款MCU并且独立于FreeRTOS内核的配置文件。

        要想实现STM32F103移植,必须熟悉FreeRTOSConfig.h配置文件中的以下几项(注:博主使用的FreeRTOS版本为FreeRTOS Kernel V10.2.1)。

         1、configCPU_CLOCK_HZ

         2、configTICK_RATE_HZ

         3、configMAX_PRIORITIES

         4、configMINIMAL_STACK_SIZE

         5、configTOTAL_HEAP_SIZE

         6、configKERNEL_INTERRUPT_PRIORITY

         7、configMAX_SYSCALL_INTERRUPT_PRIORITY 

二、configCPU_CLOCK_HZ

        写入实际的CPU内核时钟频率,也就是CPU指令执行频率。(stm32f103芯片的晶振为72MHZ。)

​        配置此值是为了正确的配置系统节拍中断周期。

        例如,在STM32F10X中,FreeRTOS Kernel V10.2.1

#define configCPU_CLOCK_HZ            ( ( unsigned long ) 72000000 )

三、configTICK_RATE_HZ

        FreeRTOS系统自己的节拍中断的频率。即一秒中断的次数,每次中断FreeRTOS都会进行任务调度。

        系统节拍中断用来测量时间,因此,越高的测量频率意味着可测到越高的分辨率时间。但是,高的系统节拍中断频率也意味着RTOS内核占用更多的CPU时间,因此会降低效率。RTOS演示例程都是使用系统节拍中断频率为1000HZ,这是为了测试RTOS内核,比实际使用的要高。(实际使用时不用这么高的系统节拍中断频率)
  多个任务可以共享一个优先级,RTOS调度器为相同优先级的任务分享CPU时间,在每一个RTOS 系统节拍中断到来时进行任务切换。高的系统节拍中断频率会降低分配给每一个任务的“时间片”持续时间。

  例如,在STM32F10X中,FreeRTOS Kernel V10.2.1

#define configTICK_RATE_HZ            ( ( TickType_t ) 1000 )

  表示滴答中断(SYSTICK)1毫秒中断1次。

  如果想让滴答中断(SYSTICK)100微秒中断1次,可以如下进行配置

#define configTICK_RATE_HZ            ( ( TickType_t ) 100 )


四、configMAX_PRIORITIES

        配置应用程序最大可用的优先级数目。

  在FreeRTOS内核中,每个有效优先级都会消耗一定量的RAM,因此这个值最好不要超过你的应用实际需要的优先级数目,FreeRTOS官网建议,宏configMAX_PRIORITIES最大数目不要超过32,那么工程项目可以使用的任务的优先级号范围为(0~31)

        每一个任务都会被分配一个优先级,任务的优先级值在0~ (configMAX_PRIORITIES - 1)之间。

        FreeRTOS任务优先级数值越,表示任务优先级越;FreeRTOS任务优先级数值越,表示任务优先级越

        空闲任务的优先级为0(tskIDLE_PRIORITY),因此它是最低优先级任务。

        例如,在STM32F103中,FreeRTOS Kernel V10.2.1

#define configMAX_PRIORITIES		( 5 )

        程序中给任务分配优先级时,可用的优先级号为:(0~configMAX_PRIORITIES-1)

        #define configMAX_PRIORITIES=5,因此工程项目中任务可用的优先级号范围为(0~4)。优先级号0被FreeRTOS内核固定分配给空闲任务;优先级号1,优先级号2,优先级号3,优先级号4都可以分配给用户任务。
        警告:优先级号5禁止分配给任务。如果优先级号5分配给任务,则会造成系统崩溃。

五、configMINIMAL_STACK_SIZE

        定义空闲任务使用的堆栈大小。

        通常此值不应小于对应处理器演示例程文件FreeRTOSConfig.h中定义的数值。

       例如,在STM32F103中,FreeRTOS Kernel V10.2.1

#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 128 )

       在STM32F103中,堆栈大小不是以字节为单位,而是以字为单位的。在32位架构下,栈大小为128表示栈内存占用128*4=512字节的空间。

六、configTOTAL_HEAP_SIZE

        配置FreeRTOS任务栈可用的RAM总量。

        工程项目分配的所有任务都在该区域申请用户栈,每个任务的形参、非静态局部变量以及函数调用信息也在该区域申请空间。也就是说,工程项目中动态创建的每一个任务,都需要从configTOTAL_HEAP_SIZE空间申请栈区(称之为任务栈)

        工程项目中动态创建的每个任务从configTOTAL_HEAP_SIZE空间申请到栈区(称之为任务栈)后,该任务的形参、非静态局部变量以及函数调用信息都会使用这个栈区(称之为任务栈)进行入栈和出栈。

        例如,在STM32F10X中,FreeRTOS Kernel V10.2.1

#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 17 * 1024 ) )

        如果实际工程项目创建的任务比较大,可以增加configTOTAL_HEAP_SIZE空间,例如:

#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 25 * 1024 ) )

七、configKERNEL_INTERRUPT_PRIORITY

        设置FreeRTOS内核的中断优先级(内核PendSV中断和SysTick中断使用的中断优先级),因为FreeRTOS内核中断(PendSV中断和SysTick中断)不允许抢占用户使用的中断(例如:用户的USART1中断,用户的SPI1中断),因此这个宏configKERNEL_INTERRUPT_PRIORITY一般定义为硬件最低优先级(例如:15)

        对于STM32F103 Cortex-M3 内核而言,硬件最低优先级为15。因此宏configKERNEL_INTERRUPT_PRIORITY=255,参见下图。

/* This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
(lowest) to 0 (1?) (highest). */
/*这是Cortex-M3 NVIC的原始值。值可以是255(最低)到0(1?)(最高)*/ 
#define configKERNEL_INTERRUPT_PRIORITY 		255

        configKERNEL_INTERRUPT_PRIORITY=255和中断优先级15有什么联系呢?

        (1)、对于STM32F103Cortex-M3内核,只使用了8位中的高四位[7:4]作为中断优先级,低四位无任何意义,一般填充1。

        (2)、configKERNEL_INTERRUPT_PRIORITY=255,而255=1111 1111B,高4位的1111B=0x0F=15。所以,255就表示FreeRTOS内核的中断优先级号=15。

提示:

        (1)、宏configKERNEL_INTERRUPT_PRIORITY用于设置FreeRTOS内核PendSV中断和SysTick(滴答定时器)中断的中断优先级。

        (2)、port.c 中有如下定义:

#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )

八、configMAX_SYSCALL_INTERRUPT_PRIORITY 

        配置可受FreeRTOS内核控制的最高中断优先级号,这个宏配置的中断优先级号范围为(1~15),禁止将configMAX_SYSCALL_INTERRUPT_PRIORITY设置为0

       警告:宏configMAX_SYSCALL_INTERRUPT_PRIORITY的设置范围为1~15,千万不能将宏configMAX_SYSCALL_INTERRUPT_PRIORITY设置为0。因为中断优先级号0是专门用于SVC中断启动任务使用的。(内核启动中断vTaskStartScheduler())

        优先级号于这个宏(configMAX_SYSCALL_INTERRUPT_PRIORITY)的硬件中断,不受FreeRTOS管控,FreeRTOS无权用taskENTER_CRITICAL()函数禁止这些硬件中断,同时也不能在这些硬件中断中调用任何FreeRTOS API函数,否则系统会有崩溃的风险。优先级号于这个宏(configMAX_SYSCALL_INTERRUPT_PRIORITY)的硬件中断,才接受FreeRTOS的管控,FreeRTOS可以用taskENTER_CRITICAL()函数禁止这些硬件中断,FreeRTOS可以在这些硬件中断中调用FreeRTOS API函数,

        在文件portmacro.h 中,将宏(configMAX_SYSCALL_INTERRUPT_PRIORITY) 写入到BASEPRI 寄存器,最终对应于taskENTER_CRITICAL()函数,参见下图。

static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
{

uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{

/* Set BASEPRI to the max syscall priority to effect a critical section. */
mrs ulReturn, basepri //先读出 BASEPRI 的值,保存在 ulReturn 中
msr basepri, ulNewBASEPRI //将 configMAX_SYSCALL_INTERRUPT_PRIORITY 写入到寄存器 BASEPRI 中。
dsb
isb
}
return ulReturn; //返回 ulReturn,退出临界区代码保护的时候要使用到此值
}

        例如,在STM32F10X中,FreeRTOS Kernel V10.2.1

/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY不能设置为零!!!! */
/*相当于0x5F或优先级5*/
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 95 /*equivalent to 0x50, or priority 5. */
 

        上面的代码中,配置configMAX_SYSCALL_INTERRUPT_PRIORITY中断优先级号为5。

        configMAX_SYSCALL_INTERRUPT_PRIORITY=95和中断优先级号5有什么联系呢?

        (1)、对于STM32F103Cortex-M3内核,只使用了8位中的高四位[7:4]作为中断优先级,低四位无任何意义,一般填充1。

        (2)、configMAX_SYSCALL_INTERRUPT_PRIORITY=95,而95=0101 1111B,高4位的0101B=0x05=5。所以,95就表示可受FreeRTOS管控的起始中断优先级号=5。

        1、如果配置configMAX_SYSCALL_INTERRUPT_PRIORITY = 95(0x5F也即中断优先级号为5),那么,中断优先级号为0~4  的中断不受FreeRTOS控制,用户不能在中断优先级号为0~4  的中断服务程序中调用以​FromISR结尾的API函数,否则会造成系统崩溃。

        2、如果配置configMAX_SYSCALL_INTERRUPT_PRIORITY = 95(0x5F也即中断优先级号为5),那么,中断优先级号为5~15  的中断可以接受FreeRTOS控制,用户可以在中断优先级号为5~15  的中断服务程序中调用以​FromISR结尾的API函数。

        3、如果用户在用户任务中调用关闭中断的API函数taskENTER_CRITICAL(); 如果中断优先级号为0~4的中断触发,那么用户关中闭断的操作不起任何作用,程序仍然会跳转到中断优先级号为0~4 的中断服务程序中执行。中断优先级号为0~4的中断称之为不受FreeRTOS控制的中断(原因:configMAX_SYSCALL_INTERRUPT_PRIORITY宏配置的优先级号为5,优先级号5及5以上的硬件中断才受FreeRTOS控制的控制;优先级号低于5以下的中断不受FreeRTOS控制的控制)。

        4、如果用户在用户任务中调用关闭中断的API函数taskENTER_CRITICAL(); 如果中断优先级号为5~15的中断触发,那么用户关闭中断的操作起作用,程序不会跳转到中断优先级号为5~15的中断服务程序中,仍然会执行用户任务中的程序,只有当用户任务中执行开中断API函数taskEXIT_CRITICAL();,系统才会去响应中断优先级号为5~15的中断,跳转到中断优先级号为5~15的中断服务程序中执行。

九、实例

       实际的工程项目需要:3个串口中断(USART1,USART2,USART3),1个定时器TIM2中断,创建5个任务,请问:该如何配置FreeRTOSConfig.h

       1、配置configMAX_PRIORITIES

             由于需要创建5个任务,因此宏configMAX_PRIORITIES=6。

#define configMAX_PRIORITIES		( 6 )

             任务优先级号1,分配给用户任务vTaskVoltage_Task(void *pvParameters)

             任务优先级号2,分配给用户任务vTaskDT_Poll_Task(void *pvParameters)

             任务优先级号3,分配给用户任务vTaskDT_Parse_Task(void *pvParameters)

             任务优先级号4,分配给用户任务vFreeModbus_Task(void *pvParameters)

             任务优先级号5,分配给用户任务vGPS_Task(void *pvParameters)

       2、配置configTOTAL_HEAP_SIZE

#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 20 * 1024 ) )

        3、配置configKERNEL_INTERRUPT_PRIORITY

        设置FreeRTOS内核的中断优先级=15。(内核PendSV中断和SysTick中断使用的中断优先级)    

/* This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 		255

        4、配置configMAX_SYSCALL_INTERRUPT_PRIORITY

        设置可受FreeRTOS内核控制的最高中断优先级号=5。

        (1)、中断优先级号为0的中断禁止用户配置。

        (2)、中断优先级号为1~4的中断不受FreeRTOS内核控制

        (3)、中断优先级号为5~15的中断受FreeRTOS内核控制

/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY不能设置为零!!!! */
/*相当于0x5F或优先级5*/
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 95 /*equivalent to 0x50, or priority 5. */
 

        5、创建5个任务

	xTaskCreate( vTaskVoltage_Task,     	// 任务函数  
                 "vTaskStart",   			// 任务名    
                 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 tskIDLE_PRIORITY + 1, 		// 任务优先级
                 &xHandleTaskVoltage);   	// 任务句柄  
	
	xTaskCreate( vTaskDT_Poll_Task,    		// 任务函数  
                 "vTaskDT_Poll",   				// 任务名    
                 //configMINIMAL_STACK_SIZE,// 任务栈大小,单位word,也就是4字节
				 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 tskIDLE_PRIORITY + 2,		// 任务优先级
                 &xHandleTaskDT);  			// 任务句柄  		

	xTaskCreate( vTaskDT_Parse_Task,    	// 任务函数  
                 "vTaskDT_Parse",   		// 任务名    
                 //configMINIMAL_STACK_SIZE,// 任务栈大小,单位word,也就是4字节
				 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 tskIDLE_PRIORITY + 3,		// 任务优先级
                 &xHandleTaskDT);  			// 任务句柄  				
			 
	xTaskCreate( vFreeModbus_Task,     		// 任务函数  
                 "vFreeModbus",   			// 任务名    
                 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 tskIDLE_PRIORITY + 4,		// 任务优先级
                 &xHandleTaskFreeModbus);  	// 任务句柄  
			 

	xTaskCreate( vGPS_Task,     			// 任务函数  
                 "vGPS",   					// 任务名    
                 512,            			// 任务栈大小,单位word,也就是4字节 
                 NULL,           			// 任务参数  
                 tskIDLE_PRIORITY + 5,		// 任务优先级
                 &xHandleTaskGps);   		// 任务句柄  

        6、配置NVIC中断优先级组和抢占优先级和响应优先级

        (1)、优先级分组设置为NVIC_PriorityGroup_4

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 

        中断优先级号为1~4的中断不受FreeRTOS内核控制,中断优先级号为5~15的中断受FreeRTOS内核控制。

        (2)、设置USART1的抢占优先级号=5

        (3)、设置USART2的抢占优先级号=6

        (4)、设置USART4的抢占优先级号=7

        (5)、设置TIM2定时中断的抢占优先级号=8

	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;	 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);	
	
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;	 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

致谢:

(20条消息) FreeRTOS内核配置说明---FreeRTOS Kernel V10.2.1_ba_wang_mao的博客-CSDN博客

相关文章:

  • wordpress 建立分类/产品推广策划方案
  • 什么网站做的好看的/竞价托管多少钱一个月
  • 兰州网站建设/佛山seo培训机构
  • 简述常用的软件开发文档/昆明seo外包
  • wordpress+培训模板/seo工作怎么样
  • 做软装什么网站可以/seo营销外包公司
  • C语言中的字符串转数字函数常见问题详解
  • 从零开始搭建仿抖音短视频APP-构建后端项目
  • 力扣 221. 最大正方形
  • 爬虫报错:twisted.web._newclient.ResponseNeverReceived
  • 前后端分离技术渲染动态页面 - 表白墙(Servlet)
  • 关于springboot多环境设设置说明
  • 一幅长文细学CSS3
  • P2-Net:用于2D像素与3D点匹配的局部特征的联合描述符和检测器(ICCV 2021)
  • 电磁兼容(EMC)基础(二)
  • 面向终客户和设备制造商的Ethernet-APL
  • React.lazy与Suspence实现延迟加载
  • React 中 memo useMemo useCallback 到底该怎么用