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

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函数,否则系统会有崩溃的风险。

        在文件portmacro.h 中,将宏(configMAX_SYSCALL_INTERRUPT_PRIORITY) 写入到BASEPRI 寄存器,最终对应于taskENTER_CRITICAL(),目的就是可以通过FreeRTOS的API屏蔽优先级号高于这个宏(configMAX_SYSCALL_INTERRUPT_PRIORITY)的硬件中断。

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博客

相关文章:

  • Java基础2(二维数组、数组的赋值判定)
  • Redis 强化之一
  • 打印设备电磁泄露信息提取和还原技术的matlab仿真实现
  • 【C++】类和对象(中)—— 日期类的实现 | const成员函数
  • 树莓派视频监控项目总结
  • datax与多种数据库间数据类型映射
  • Redis哨兵模式与Redis缓存穿透、击穿和雪崩
  • Ubuntu Budgie 22.04 设置中文语言并安装拼音输入法
  • 4K Star , Github上照片转漫画最强项目
  • Matlab 创建YOLO v2目标检测网络(仅仅是网络)
  • Java集合04:Collection子接口二:Set接口
  • 查看CPU核数、内存使用情况【一文读懂】
  • 【 java 多线程】死锁的问题
  • 全网都在说一个错误的结论
  • 免杀实战之面向PHP的WebShell免杀
  • gitlab-ci配置详解(一)
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • Java的Interrupt与线程中断
  • Java知识点总结(JavaIO-打印流)
  • js继承的实现方法
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Quartz初级教程
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • windows下mongoDB的环境配置
  • 安装python包到指定虚拟环境
  • 产品三维模型在线预览
  • 多线程 start 和 run 方法到底有什么区别?
  • 欢迎参加第二届中国游戏开发者大会
  • 通过几道题目学习二叉搜索树
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 原生Ajax
  • 进程与线程(三)——进程/线程间通信
  • ​决定德拉瓦州地区版图的关键历史事件
  • #考研#计算机文化知识1(局域网及网络互联)
  • $.ajax()方法详解
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (独孤九剑)--文件系统
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (南京观海微电子)——I3C协议介绍
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (全注解开发)学习Spring-MVC的第三天
  • (一一四)第九章编程练习
  • (转)我也是一只IT小小鸟
  • .net CHARTING图表控件下载地址
  • .NET 命令行参数包含应用程序路径吗?
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET文档生成工具ADB使用图文教程
  • [2019.3.5]BZOJ1934 [Shoi2007]Vote 善意的投票
  • [ACM] hdu 1201 18岁生日
  • [AIGC] Redis基础命令集详细介绍
  • [C/C++随笔] char与unsigned char区别
  • [cb]UIGrid+UIStretch的自适应
  • [ffmpeg] 定制滤波器