FreeRTOS基础知识

  • FreeRTOS文件结构
  • FreeRTOS编码标准和风格
  • FreeRTOS系统配置

1、FreeRTOS文件结构

从FreeRTOS官网下载“FreeRTOSv9.0.0.exe”,双击此文件。选择FreeRTOS源码生成的路径,就会自动生成FreeRTOS源码。生成源码之后,我们进入“D:\FreeRTOS源码\FreeRTOSv9.0.0\FreeRTOS”文件夹(这里我将文件“FreeRTOSv9.0.0.exe”放在D盘的FreeRTOS源码文件下,并且生成的源码选择在此目录下)。进入“D:\FreeRTOS源码\FreeRTOSv9.0.0\FreeRTOS”后得到下图源码文件:
在这里插入图片描述

  • Demo文件夹
    这里“Demo”表示的是与具体平台相关的例程,移植的时候可以参考相关的例程。

  • License
    文件夹“License”是FreeRTOS相关的许可信息,对于要做FreeRTOS相关产品要仔细研究。

  • Source文件夹
    进入文件夹如下图所示:
    Source文件夹

    include 文件夹该文件包含一些头文件。下面的.c文件是FreeRTOS的源码文件。其中FreeRTOS实时操作系统的主要文件是task.c,queue.c,list.c。task.c是与任务相关的代码,queue.c用于管理任务之间进行通信的队列、信号量的代码,list.c是一个双向链表。portable文件夹保存的是FreeRTOS与具体硬件之间连接的桥梁,进入该文件,如下图所示:
    portable文件夹
    其中MemMang文件夹存放的是FreeRTOS中与内存管理相关的代码,这是移植的时候必须要添加到工程中去的。观察里面文件夹存放的文件,大都包含port.c和portmacro.h,这两个文件存放的一些硬件平台的寄存器地址以及中断处理函数。通过目录可以就看出,FreeRTOS开发人员根据具体的编译环境建立一个文件夹。在这里,我用的是Keil MDK集成开发环境,点开Keil文件夹,里面提示参考RVDS文件,这样就可以进入RVDS文件夹,如下图所示:
    RVDS文件夹
    这里就可以根据具体的MCU硬件型号进行选择,例如:如果你使用的是STM32F1系列,就选择ARM_CM3文件夹里面的port.c和portable.c;如果使用STM32F0,就选择ARM_CM0文件夹里面的port.c和portable.c。下图是ARM_CM3文件夹内容:
    ARM_CM3文件夹

2、FreeRTOS编码标准和编码风格

a、变量命名规则

uint32_t 类型变量的前缀使用ul,其中u表示unsigned、l表示long;
uint16_t 类型变量的前缀使用us,其中s表示short;
uint8_t 类型变量的前缀使用uc,其中c表示char;
非stdint.h的有符号变量前面加前缀x,无符号变量前面加前缀ux,例如:BaseType_t、UBaseType_t和size_t;
枚举类型的变量的前缀使用e;
对于指针类型的变量,是在指向变量类型的前面加一个字母p,例如pus;

b、函数命名规则

prv表示static修饰的函数;
v表示函数无返回值;
Task表示函数所在的文件夹;

c、宏命名规则

宏定义前面部分表示所在文件名,用小写字母表示。后面部分用大写字母表示,其中单词之间用下划线分割。

d、数据类型

  • 还有4个移植层的变量类型,对于不同架构的MCU定义不同:
    <1>TickType_t : 当configUSE_16_BIT_TICKS为0是表示无符号16位数据;反之,表示32位无符号32位数据。代码如下:
#if( configUSE_16_BIT_TICKS == 1 )
	typedef uint16_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffff
#else
	typedef uint32_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL

	/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do not need to be guarded with a critical section. */
	#define portTICK_TYPE_IS_ATOMIC 1

<2>BaseType_t: 是MCU架构决定。当32位架构,该变量就表示32位的数据类型;当16位架构,该变量就表示16位的数据类型。在这里,我们可以从portmacro.h中找到, 代码片如下:

typedef long BaseType_t;

<3>UBaseType_t: 是一个无符号BaseType_t。在这里,我们可以从portmacro.h中找到, 代码片如下:

typedef unsigned long UBaseType_t;

<4>StackType_t 堆栈使用数据类型。当32位架构,该变量就表示32位的数据类型;当16位架构,该变量就表示16位的数据类型。在这里,我们可以从portmacro.h中找到, 代码片如下:

#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long

typedef portSTACK_TYPE StackType_t;

3、FreeRTOS系统配置

FreeRTOS提供给用户FreeRTOSConfig.h配置文件,用户可以根据MCU架构和具体应用对FreeRTOS进行裁剪和配置。 代码片如下:

/* FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. This file is part of the FreeRTOS distribution. FreeRTOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. *************************************************************************** >>! NOTE: The modification to the GPL is included to allow you to !<< >>! distribute a combined work that includes FreeRTOS without being !<< >>! obliged to provide the source code for proprietary components !<< >>! outside of the FreeRTOS kernel. !<< *************************************************************************** FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full license text is available on the following link: http://www.freertos.org/a00114.html *************************************************************************** * * * FreeRTOS provides completely free yet professionally developed, * * robust, strictly quality controlled, supported, and cross * * platform software that is more than just the market leader, it * * is the industry's de facto standard. * * * * Help yourself get started quickly while simultaneously helping * * to support the FreeRTOS project by purchasing a FreeRTOS * * tutorial book, reference manual, or both: * * http://www.FreeRTOS.org/Documentation * * * *************************************************************************** http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading the FAQ page "My application does not run, what could be wrong?". Have you defined configASSERT()? http://www.FreeRTOS.org/support - In return for receiving this top quality embedded software for free we request you assist our global community by participating in the support forum. http://www.FreeRTOS.org/training - Investing in training allows your team to be as productive as possible as early as possible. Now you can receive FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers Ltd, and the world's leading authority on the world's leading RTOS. http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool, a DOS compatible FAT file system, and our tiny thread aware UDP/IP stack. http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS licenses offer ticketed support, indemnification and commercial middleware. http://www.SafeRTOS.com - High Integrity Systems also provide a safety engineered and independently SIL3 certified version for use in safety and mission critical applications that require provable dependability. 1 tab == 4 spaces! */


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

#include "sys.h"
#include "usart.h"
#include "timer.h"
//针对不同的编译器调用不同的stdint.h文件
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif

//断言
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)

/***************************************************************************************************************/
/* FreeRTOS基础配置配置选项 */
/***************************************************************************************************************/
#define configUSE_PREEMPTION 1 //1使用抢占式内核,0使用协程
#define configUSE_TIME_SLICING 1 //1使能时间片调度(默认式使能的)
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 //1启用特殊方法来选择下一个要运行的任务
                                                                        //一般是硬件计算前导零指令,如果所使用的
                                                                        //MCU没有这些硬件指令的话此宏应该设置为0!
#define configUSE_TICKLESS_IDLE 0 //1启用低功耗tickless模式
#define configUSE_QUEUE_SETS 1 //为1时启用队列
#define configCPU_CLOCK_HZ (SystemCoreClock) //CPU频率
#define configTICK_RATE_HZ (1000) //时钟节拍频率,这里设置为1000,周期就是1ms
#define configMAX_PRIORITIES (32) //可使用的最大优先级
#define configMINIMAL_STACK_SIZE ((unsigned short)130) //空闲任务使用的堆栈大小
#define configMAX_TASK_NAME_LEN (20) //任务名字字符串长度

#define configUSE_16_BIT_TICKS 0 //系统节拍计数器变量数据类型,
                                                                        //1表示为16位无符号整形,0表示为32位无符号整形
#define configIDLE_SHOULD_YIELD 1 //为1时空闲任务放弃CPU使用权给其他同优先级的用户任务
#define configUSE_TASK_NOTIFICATIONS 1 //为1时开启任务通知功能,默认开启
#define configUSE_MUTEXES 1 //为1时使用互斥信号量
#define configQUEUE_REGISTRY_SIZE 8 //不为0时表示启用队列记录,具体的值是可以
                                                                        //记录的队列和信号量最大数目。
#define configCHECK_FOR_STACK_OVERFLOW 0 //大于0时启用堆栈溢出检测功能,如果使用此功能
                                                                        //用户必须提供一个栈溢出钩子函数,如果使用的话
                                                                        //此值可以为1或者2,因为有两种栈溢出检测方法。
#define configUSE_RECURSIVE_MUTEXES 1 //为1时使用递归互斥信号量
#define configUSE_MALLOC_FAILED_HOOK 0 //1使用内存申请失败钩子函数
#define configUSE_APPLICATION_TASK_TAG 0 
#define configUSE_COUNTING_SEMAPHORES 1 //为1时使用计数信号量

/***************************************************************************************************************/
/* FreeRTOS与内存申请有关配置选项 */
/***************************************************************************************************************/
#define configSUPPORT_DYNAMIC_ALLOCATION 1 //支持动态内存申请
#define configTOTAL_HEAP_SIZE ((size_t)(20*1024)) //系统所有总的堆大小

/***************************************************************************************************************/
/* FreeRTOS与钩子函数有关的配置选项 */
/***************************************************************************************************************/
#define configUSE_IDLE_HOOK 0 //1,使用空闲钩子;0,不使用
#define configUSE_TICK_HOOK 0 //1,使用时间片钩子;0,不使用

/***************************************************************************************************************/
/* FreeRTOS与运行时间和任务状态收集有关的配置选项 */
/***************************************************************************************************************/
#define configGENERATE_RUN_TIME_STATS 1 //为1时启用运行时间统计功能
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ConfigureTimeForRunTimeStats()//定时器3提供时间统计的时基,频率为10K,即周期为100us
#define portGET_RUN_TIME_COUNTER_VALUE() FreeRTOSRunTimeTicks //获取时间统计时间值

#define configUSE_TRACE_FACILITY 1 //为1启用可视化跟踪调试
#define configUSE_STATS_FORMATTING_FUNCTIONS 1 //与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数
                                                                        //prvWriteNameToBuffer(),vTaskList(),
                                                                        //vTaskGetRunTimeStats()
                                                                        
/***************************************************************************************************************/
/* FreeRTOS与协程有关的配置选项 */
/***************************************************************************************************************/
#define configUSE_CO_ROUTINES 0 //为1时启用协程,启用协程以后必须添加文件croutine.c
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) //协程的有效优先级数目

/***************************************************************************************************************/
/* FreeRTOS与软件定时器有关的配置选项 */
/***************************************************************************************************************/
#define configUSE_TIMERS 1 //为1时启用软件定时器
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //软件定时器优先级
#define configTIMER_QUEUE_LENGTH 5 //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) //软件定时器任务堆栈大小

/***************************************************************************************************************/
/* FreeRTOS可选函数配置选项 */
/***************************************************************************************************************/
#define INCLUDE_xTaskGetSchedulerState 1 
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1

/***************************************************************************************************************/
/* FreeRTOS与中断有关的配置选项 */
/***************************************************************************************************************/
#ifdef __NVIC_PRIO_BITS
	#define configPRIO_BITS __NVIC_PRIO_BITS
#else
	#define configPRIO_BITS 4 
#endif

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/***************************************************************************************************************/
/* FreeRTOS与中断服务函数有关的配置选项 */
/***************************************************************************************************************/
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler

#endif /* FREERTOS_CONFIG_H */

使用“INCLUDE_”开头的宏是使能或者失能相关的API函数,管理相关的函数是否被编译进内核。“config”开始的宏是管理相关的功能模块是否开启。