第一章 FreeRTOS 整体架构
第二章 FreeRTOS 编程规范
第三章 FreeRTOS 内存管理
第三章 FreeRTOS 内存管理
第四章 FreeRTOS 任务管理
第五章 FreeRTOS 消息队列
第六章 FreeRTOS 软件定时器
第七章 FreeRTOS 信号量
第八章 FreeRTOS 互斥量
第九章 FreeRTOS 任务通知
第十章 FreeRTOS 事件组
本章主要介绍FreeRTOS的命名、注释、数据结构等编码规范。方便后续的源码阅读。
FreeRTOS的核心代码遵从MISRA-C(汽车产业软件可靠性协会)编码标准。如果出现有不满足标准的会在代码中显示注释出来。可以在代码中全局搜索"MISRA exception"找到不满足MISRA-C标准的编码。在FreeRTOSV10.4.6中一共有27处不满足,不同类型的如下:
/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
* for the header files above, but not in this file, in order to generate the
* correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */
if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */
if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */
( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
#define configUSE_PREEMPTION 1
#define configCPU_CLOCK_HZ ( 100000000 )
#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 )
#define tskRUNNING_CHAR ( 'X' )
#define queueSEND_TO_BACK ( ( BaseType_t ) 0 )
#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 )
#define queueOVERWRITE ( ( BaseType_t ) 2 )
命名规则:位宽前缀Name1Name2…Namex
uint8_t ucQueueType;
int8_t cRxLock;
char cStatus;
FreeRTOS中没有直接用 uint16_t 和 int16_t 命名的变量
uint32_t ulStackDepth
int32_t lArrayIndex;
FreeRTOS 的自定义的数据类型如下:
/* integer data type */
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t; /* 32bit hardware*/
/* defined by freertos */
typedef struct tskTaskControlBlock * TaskHandle_t;
typedef struct QueueDefinition * QueueHandle_t;
typedef xTIMER Timer_t;
typedef struct EventGroupDef_t * EventGroupHandle_t
FreeRTOS自定义的数据类型只有两种前缀,如下:
/* integer data type */
UBaseType_t uxTimerNumber;
BaseType_t xListWasEmpty;
StackType_t xStack[ STACK_SIZE ];
TickType_t xNextExpireTime;
/* defined by freertos */
TaskHandle_t xTimerTaskHandle = NULL;
QueueHandle_t xTimerQueue = NULL;
Timer_t xNewTimer;
EventGroupHandle_t xEventGroup = NULL;
在2.2.1和2.2.2的数据类型的命名前面增加 ‘p’
uint8_t * pucStackByte;
int8_t * pcOriginalReadPosition;
uint32_t * pulNotificationValue;
StackType_t * pxTopOfStack;
BaseType_t * pxHigherPriorityTaskWoken
UBaseType_t *puxVariableToIncrement;
TickType_t * const pxTicksToWait;
TaskHandle_t *pxCreatedTask;
Queue_t * pxNewQueue ;
Timer_t * const pxTimer;
EventGroup_t * pxEventBits;
/* task.c */
static void prvDeleteTCB( TCB_t * pxTCB )
/* queue.c */
static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void * pvItemToQueue, const BaseType_t xPosition )
/* task.c */
UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
/* queue.c */
BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
/* timer.c */
void vTimerSetTimerID( TimerHandle_t xTimer, void * pvNewID )
/* porttable.h */
void * pvPortMalloc( size_t xSize )
见 2.2节,变量的命令。主要就是三种数据类型
/**************** timer.h **************/
/**
* BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
*
* Queries a timer to see if it is active or dormant.
*
* A timer will be dormant if:
* 1) It has been created but not started, or
* 2) It is an expired one-shot timer that has not been restarted.
*
* Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
* xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
* xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the
* active state.
*
* @param xTimer The timer being queried.
*
* @return pdFALSE will be returned if the timer is dormant. A value other than
* pdFALSE will be returned if the timer is active.
*
* Example usage:
* @verbatim
* // This function assumes xTimer has already been created.
* void vAFunction( TimerHandle_t xTimer )
* {
* if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
* {
* // xTimer is active, do something.
* }
* else
* {
* // xTimer is not active, do something else.
* }
* }
* @endverbatim
*/
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/**************** timer.c**************/
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
{
BaseType_t xReturn;
Timer_t * pxTimer = xTimer;
configASSERT( xTimer );
/* Is the timer in the list of active timers? */
taskENTER_CRITICAL();
{
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
}
taskEXIT_CRITICAL();
return xReturn;
} /*lint !e818 Can't be pointer to const due to the typedef. */