1- 编码标准
FreeRTOS源文件(对所有端口通用,但对端口层不通用)符合MISRA编码标准指南。使用pc-lint和链接lint配置文件检查遵从性。由于标准有很多页长,并且可以从MISRA处以非常低的费用购买,所以我们在这里没有复制所有的规则。
就是下面这几个文件。在文章末尾处我会粘贴处源代码。
下面列出和MISRA标准的差别:
- 两个API函数有多个出口点。由于临界效率的原因,在这两种情况下允许有偏差。
- 在创建任务时,源代码操作内存地址来定位分配给创建的任务的堆栈的起始地址和结束地址。代码必须适用于FreeRTOS移植到的所有体系结构——包括具有8、16、20、24和32位总线的体系结构。这不可避免地需要一些指针运算。当使用指针算术时,将以编程方式检查算术结果的正确性。
- 在默认情况下,跟踪宏是空的,因此它们不生成任何代码。因此,MISRA符合性检查是使用虚拟宏定义执行的。
- MISRA 规则在认为适当的情况下逐行关闭(也就是说,如果认为对深度嵌入的系统来说,遵守规则的代码比谨慎地不遵守规则创建的代码更不合适)。每次这样的事件都伴随着使用特殊的pc-lint MISRA注释标记语法的解释。
- FreeRTOS 支持多种不同的编译器构建,其中有部分编译器比其他编译器更高级。出于这个原因,FreeRTOS 不使用由 C99 标准引入 C 语言的任何功能或语法。唯一的例外是使用stdint.h头文件。FreeRTOS/Source/include目录包含一个名为 stdint.readme 的文件,可以重命名为stdint.h,以提供构建 FreeRTOS 所需的最小stdint类型定义,如果你的编译器不支持自定义,可以使用这个文件来代替。
测试
代码的测试执行和移植分别在 FreeRTOS/Source 和FreeRTOS/Source/portable这两个文件夹下。具体的可以参考1-FreeRTOS入门指南文章。
通用代码
标准演示/测试文件试图提供“分支”测试覆盖,测试确保通过每个决策的“真”和“假”路径都被执行。(在大多数情况下,这实际上实现了“条件”覆盖,因为内核的编码风格故意保持条件简单,特别为了这个目的。)如果’else’路径为空,则使用GCOV在每个’if()'条件的’else’路径中定义一个NOP(无操作)指令的mtCOVERAGE_TEST_MARKER()宏来测量’分支’覆盖率。mtCOVERAGE_TEST_MARKER()仅在度量测试时定义。
传输层
传输层代码使用“reg test”任务进行测试,对于支持中断嵌套的端口,使用“中断队列”任务进行测试。
“reg test”中创建多个(通常是两个)任务,这些任务首先用已知值填充所有CPU寄存器,然后连续检查每个寄存器是否保持其预期的已知值,因为其他测试连续执行(浸泡测试)。每个 reg 测试任务都使用唯一的值。
“中断队列”任务对嵌套至少三个深度的不同优先级的中断执行测试。宏用于在代码中的相关点插入人为的延迟,以确保实现所需的测试覆盖率。
内存安全证明
FreeRTOS Core(和FreeRTOS for AWS IoT)库包括内存安全证明。同样的证明被应用于 FreeRTOS 内核和 FreeRTOS-Plus-TCP 堆栈,但这两个较旧的库还没有完全覆盖。
命名规则
RTOS 内核和演示应用程序源代码使用以下规则定义:
变量:
-
类型为 uint32_t的变量以ul 为前缀,其中“u”表示“无符号”,“l”表示“long”。
-
类型为 uint16_t的变量以us 为前缀,其中“u”表示“无符号”,“s”表示“short”。
-
类型为 uint8_t的变量以uc 为前缀,其中“u”表示“无符号”,“c”表示“char”。
-
非标准类型的变量以x 为前缀。示例包括 BaseType_t 和
TickType_t,它们是可移植的层定义类型定义,分别用于体系结构的自然或最有效的类型,以及用于保存 RTOS 时钟周期计数的类型。 -
非标准类型的变量以x 为前缀。示例包括 BaseType_t 和
TickType_t,它们是可移植的层定义类型定义,分别用于体系结构的自然或最有效的类型,以及用于保存 RTOS 时钟周期计数的类型。 -
指针有一个附加的前缀p,例如,一个指向uint16_t的指针会有前缀pus。
-
根据 MISRA 指南,不合格的标准字符类型只允许包含 ASCII字符,并以c 为前缀。
-
根据 MISRA 指南,char * 类型的变量只允许保存指向 ASCII 字符串的指针,并且前缀为pc。
功能
- 文件范围静态(私有)函数以prv 为前缀。
- API 函数以其返回类型为前缀,按照为变量定义的约定,添加前缀v表示void。API 函数名称以定义它们的文件的名称开头。例如,vTaskDelete 在 tasks.c 中定义,并且具有 void 返回类型。
宏定义
- 宏的定义是以他们的文件为前缀,前缀小写。比如:configUSE_PREEMPTION
这个定义是在配置文件FreeRTOSConfig.h 中定义。 - 除前缀外,宏全部以大写形式书写,并使用下划线分隔。
数据类型
仅用stdint.h和RTOS自己定义的typedef,但是下列情况除外:
-
char
与MISRA指南一致,不合格的字符类型是允许的,但只有当它们用于保存ASCII字符时才允许。 -
char *
与MISRA指南一致,允许非限定字符指针,但只有当它们用于指向ASCII字符串时才允许。这消除了在使用期望使用char *形参的标准库函数时抑制良性编译器警告的需要,特别是考虑到一些编译器默认不合格的char类型是有符号的,而另一些编译器默认不合格的char类型是无符号的。
RTOS为每个端口定义了四种类型。如下:
-
TickType_t
如果configUSE_16_BIT_TICKS设置为非零 (true),则TickType_t定义为无符号 16 位类型。如果configUSE_16_BIT_TICKS设置为零 (false),则TickType_t定义为无符号 32 位类型。有关完整信息,请参阅 API 文档的自定义部分。(这点会在后面的章节进行介绍)
32位架构应该始终将configUSE_16_BIT_TICKS设置为0。 -
BaseType_t
这被定义为体系结构中最有效、最基础的类型。例如,在32位体系结构上,basettype_t将被定义为32位类型。在16位体系结构上,basettype_t将被定义为16位类型。如果basettype_t被定义为char类型,则必须特别注意确保函数返回值使用有符号字符,这些函数返回值可能为负值,表示错误。 -
UBaseType_t
这是定义一个无符号basettype_t。 -
StackType_t
定义为存储在堆栈上的项的体系结构使用的类型。通常,这将是16位体系结构上的16位类型和32位体系结构上的32位类型,尽管有一些例外。由FreeRTOS内部使用。
RTOS风格参考指南
-
缩进
四个空格字符用于缩进。 -
注释
注释不能超过80行,除非它们跟随并描述一个参数。
C++风格的双斜杠(//)是不使用的。 -
布局
FreeRTOS 源代码布局旨在尽可能易于查看和阅读,下面给出一些代码片段的文件内容格式。
/* C库头文件放在首行... */
#include <stdlib.h>
/* ...其次是RTOS头文件... */
#include "FreeRTOS.h"
/* ...再次是其他的头文件. */
#include "HardwareSpecifics.h"
/* 接下来是宏定义,最好用括号括起来 */
#define A_DEFINITION ( 1 )
/*
* 接下来是静态(文件私有)函数原型,带有注释
* 在这种样式中,每一行都以“*”开头。.
*/
static void prvAFunction( uint32_t ulParameter );
/* 文件作用域变量是函数定义之前的最后一个变量。变量的注释采用这种样式(没有每一行以一个“*”). */
static BaseType_t xMyVariable;
/*以下分隔符用于每个函数的右括号后,在开始下一个函数定义之前,在它后面有一个空行。 */
/*-----------------------------------------------------------*/
void vAFunction( void )
{
/* 函数定义在这里—注意结束符后的分隔符花括号。 */
}
/*-----------------------------------------------------------*/
static UBaseType_t prvNextFunction( void )
{
/*函数定义在这里. */
}
/*-----------------------------------------------------------*/
File Layout
/* 函数名写在一行上,包括返回值类型。左括号前没有空格。在那里是括号后的空格。结束语前有一个空格括号。
每个逗号后面都有空格。给出参数详细的描述性名称(不像这个示例!)开篇和结尾花括号出现在它们自己的行上,彼此下方排列。*/
void vAnExampleFunction( long lParameter1, unsigned short usParameter2 )
{
/* Variable declarations are not indented. */
uint8_t ucByte;
/* Code is indented. Curly brackets are always on their own lines
and lined up underneath each other. */
for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ )
{
/* Indent again. */
}
}
/* For、while、do和if结构遵循类似的模式。没有开括号前的空格。开口后有一个空间括号。右括号前有空格。有一个
每个分号后面有空格(如果有的话)。在和之前有空格在每个运算符后面。不依赖运算符优先级-圆括号总是用来明确表示优先级。,
除0之外,始终替换为常量或#defined常量。开始和结束的花括号出现在各自的行中。 */
for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ )
{
}
while( ucByte < fileBUFFER_LENGTH )
{
}
/* 对象中的每个条件都不能依赖操作符优先级多条件决策必须唯一地括起来,所有决策都必须括起来子表达式。
*/
if( ( ucByte < fileBUFFER_LENGTH ) && ( ucByte != 0U ) )
{
/*不依赖运算符优先级的示例! */
ulResult = ( ( ulValue1 + ulValue2 ) - ulValue3 ) * ulValue4;
}
/* 条件编译的布局和缩进按其他代码。*/
#if( configUSE_TRACE_FACILITY == 1 )
{
/* Add a counter into the TCB for tracing only. */
pxNewTCB->uxTCBNumber = uxTaskNumber;
}
#endif
左方括号之后,右方括号之前放置一个空格 方括号。
ucBuffer[ 0 ] = 0U;
ucBuffer[ fileBUFFER_LENGTH - 1U ] = 0U;
Formatting of C Constructs
下面给出前面提到的三个文件代码,当然你也可以去官网找到:
FreeRTOSConfig.h
/*
FreeRTOS V7.4.2 - Copyright (C) 2013 Real Time Engineers Ltd.
FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
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. See the GNU General Public License for more
details. You should have received a copy of the GNU General Public License
and the FreeRTOS license exception along with FreeRTOS; if not it can be
viewed here: http://www.freertos.org/a00114.html and also obtained by
writing to Real Time Engineers Ltd., contact details for whom are available
on the FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, and our new
fully thread aware and reentrant UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems, who sell the code with commercial support,
indemnification and middleware, under the OpenRTOS brand.
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.
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( 100000000UL )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 40960 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_QUEUE_SETS 1
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#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_xTimerPendFunctionCall 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_pcTaskGetTaskName 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xSemaphoreGetMutexHolder 1
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 6 /* 63 priority levels */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x3f
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */
portmacro.h
/* DUMMY portmacro.h file for linting without needing to lint a port layer. */
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#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 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
#endif
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
#define portYIELD()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )
/*-----------------------------------------------------------*/
#include <intrinsics.h>
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 0 ); uxReadyPriorities = ( 0 )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS()
#define portENABLE_INTERRUPTS()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ( void ) ( x )
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/
/* portNOP() is not required by this port. */
#define portNOP()
/*-----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */
stdint.h
#ifndef STDINT_INC
#define STDINT_INC
typedef unsigned long uint32_t;
typedef long int32_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef signed char int8_t;
typedef unsigned char uint8_t;
#endif