FreeRTOS应用开发常用函数汇总

FreeRTOS学习笔记:

1.任务创建函数(动态):

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName, //任务名字
                            const configSTACK_DEPTH_TYPE usStackDepth,//为该任务分配的栈大小
                            void * const pvParameters,//任务函数的参数
                            UBaseType_t uxPriority,//任务优先级
                            TaskHandle_t * const pxCreatedTask )//任务句柄

2.开启任务调度器函数:

void vTaskStartScheduler( void );

3.相对延时函数:

void vTaskDelay( const TickType_t xTicksToDelay );//单位:系统时钟节拍周期

调用之后,任务会在调用处进入阻塞状态,经过指定系统时钟节拍之后,解除阻塞


4.绝对延时函数:

#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement )

5.创建任务(静态):

TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,//任务函数
                                    const char * const pcName, //任务名字
                                    const uint32_t ulStackDepth,//任务栈大小(对于stm32为32位)
                                    void * const pvParameters,//任务函数参数
                                    UBaseType_t uxPriority,//任务优先级
                                    StackType_t * const puxStackBuffer,//为该任务静态分配的内存指针(大小要和参数三匹配)
                                    StaticTask_t * const pxTaskBuffer )//任务句柄

此函数使能需要两个条件

  • 开启configSUPPORT_STATIC_ALLOCATION宏
  • 实现vApplicationGetIdleTaskMemory函数,实现如下:
#if configSUPPORT_STATIC_ALLOCATION==1
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
  
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
#endif

6.挂起任务:

void vTaskSuspend( TaskHandle_t xTaskToSuspend )

7.恢复任务:

void vTaskResume( TaskHandle_t xTaskToResume )

8.在中断函数中恢复任务:

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )

返回值:
pdTRUE:恢复后,需要进行任务切换(手动切换!)
pdFALSE:恢复后,不需要进行任务切换

当恢复后,正在执行的任务优先级小于被恢复的任务,被恢复的任务抢占正在执行的任务,发生任务切换

freertos规定:

如果要在中断服务函数里面调用freertos的API函数,必须保证中断优先级低于freertos所管理的最高优先级


9.关闭中断与打开中断:

portDISABLE_INTERRUPTS();//关闭中断
portENABLE_INTERRUPTS();//打开中断

注意:

这两个函数只能用于控制freertos控制范围之内的中断,即优先级在宏configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY与configLIBRARY_LOWEST_INTERRUPT_PRIORITY之间的中断


10.任务调度器的挂起与恢复:

注意:

挂起任务调度器不会关闭中断,只是禁止任务切换而已,而进入临界区会禁止中断和任务切换

函数原型:

void vTaskSuspendAll( void );//挂起任务调度器
BaseType_t xTaskResumeAll( void );//恢复任务调度器

使用示例:

vTaskSuspendAll();//挂起任务调度器
{
	......//内容
}
xAlreadyYielded = xTaskResumeAll();//恢复任务调度器

挂起任务调度器之后,执行内容部分,不会切换任务,但是会被中断打断
注意与临界区区分,临界区的代码既不会切换任务,也不会被中断打断


11.临界区:

(1)任务级临界区代码保护

taskENTER_CRITICAL();
{
	....../*临界区*/
}
taskEXIT_CRITICAL();

(2)中断级临界区代码保护

uint32_t  save_status;
save_status  = taskENTER_CRITICAL_FROM_ISR();//将中断状态保存在save_status变量中
{
	....../*临界区*/
}
taskEXIT_CRITICAL_FROM_ISR(save_status );//恢复save_status标记的中断状态

进入临界段之前会关闭所有中断(freertos管理的所有中断),而任务调度是靠pendsv中断实现的,它也在freertos管理范围内,所以任务调度也会被关掉,因此在临界区中,中断被禁止,任务切换也被禁止


12.列表:

void vListInitialise( List_t * const pxList );//初始化列表
void vListInitialiseItem( ListItem_t * const pxItem );//初始化列表项
void vListInsertEnd( List_t * const pxList,
                     ListItem_t * const pxNewListItem );//列表末尾插入列表项
void vListInsert( List_t * const pxList,
                  ListItem_t * const pxNewListItem );//插入列表项
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove );//删除列表项

freertos中列表的本质是双向循环链表,列表的概念非常重要,因为freertos源码的很多基本数据结构都是通过列表实现的。


13.任务状态查询:

  • (1)获取任务优先级
UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )//获取任务优先级

参数一表示任务句柄,如果为NULL,则获取调用任务的优先级


  • (2)改变任务优先级:
void vTaskPrioritySet( TaskHandle_t xTask , UBaseType_t uxNewPriority )

参数一:任务句柄,NULL代表任务自身
参数二:新设置的优先级


  • (3)获取系统任务数量
UBaseType_t uxTaskGetNumberOfTasks( void )

  • (4)获取所有任务的状态信息
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
                                      const UBaseType_t uxArraySize,
                                      configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )

参数一:接收的任务状态信息的数组首地址
参数二:参数一的元素总个数
参数三:接收的系统运行总时间变量地址,为NULL表示不获取系统运行总时间

TaskStatus_t 类型变量是一个结构体变量

typedef struct xTASK_STATUS
{
    TaskHandle_t xHandle;                         /* 任务句柄 */
    const char * pcTaskName;                      /*任务名 */
    UBaseType_t xTaskNumber;                      /* 任务编号 */
    eTaskState eCurrentState;                     /* 任务状态 */
    UBaseType_t uxCurrentPriority;                /* 任务当前优先级 */
    UBaseType_t uxBasePriority;                   /* 任务原始优先级 */
    configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /* 任务运行时间 */
    StackType_t * pxStackBase;                    /* 任务栈基地址 */
    configSTACK_DEPTH_TYPE usStackHighWaterMark;  /* 任务栈历史剩余最小值 */
} TaskStatus_t;

  • (5)获取单个任务信息
void vTaskGetInfo( TaskHandle_t xTask,
                   TaskStatus_t * pxTaskStatus,
                   BaseType_t xGetFreeStackSpace,
                   eTaskState eState )

参数一:任务句柄
参数二:接收任务信息的变量
参数三:是否统计任务栈历史剩余最小值(pdFALSE表示不统计,pdTRUE表示统计)
参数四:是否统计任务状态(eInvalid表示统计其他表示不统计)

typedef enum
{
    eRunning = 0, /* 运行 */
    eReady,       /* 就绪 */
    eBlocked,     /* 阻塞 */
    eSuspended,   /*挂起 */
    eDeleted,     /* 删除 */
    eInvalid      /* 无效 */
} eTaskState;

  • (6)获取当前任务的任务句柄
TaskHandle_t xTaskGetCurrentTaskHandle( void )

  • (7)获取指定任务名字的任务句柄
TaskHandle_t xTaskGetHandle( const char * pcNameToQuery )

参数一:指定的任务名字
返回值:返回任务句柄,如果不存在,则返沪NULL


  • (8)获取指定任务的任务栈历史最小堆栈
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t  xTask )

  • (9)获取指定任务的任务状态
eTaskState eTaskGetState(TaskHandle_t xTask)

参数一:任务句柄
返回值:eTaskState 类型结构体,上文已提及


  • (10)获取系统的所有任务信息,以表格形式呈现
void vTaskList(char * pcWriteBuffer)

参数一:表格信息缓存指针


  • (11)任务时间统计:
void vTaskGetRunTimeStats( char * pcWriteBuffer ) 

参数一:表格信息缓存指针


表格有三列:
Task:表示任务名字
Abs time:任务的绝对运行时间(时基定时器的中断次数)
Time:任务时间相对于CPU总时间的占比


14.队列:

(1)动态方式创建队列:

#define xQueueCreate (  uxQueueLength,   uxItemSize  )   						 \					
	   xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), (queueQUEUE_TYPE_BASE )) 

参数一:队列长度(队列项个数)
参数二:队列项大小(字节)
返回值:NULL,创建失败;非空,返回队列句柄


(2)向队列写入消息:

向队列尾部写入消息,提供了两个API,它们的功能是相同的

#define  xQueueSend(  xQueue,   pvItemToQueue,   xTicksToWait  )	 					\    
	    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define  xQueueSendToBack(  xQueue,   pvItemToQueue,   xTicksToWait  )					 \    
	    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )

参数一:队列句柄
参数二:要写入的队列项
参数三:阻塞超时时间


向队列头部写入信息

#define  xQueueSendToFront(  xQueue,   pvItemToQueue,   xTicksToWait  ) 					\   
	    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )

  • 覆盖写队列信息(只能用于只有一个队列项的队列),因为是覆盖写,所以不需要指定阻塞时间
#define  xQueueOverwrite(  xQueue,   pvItemToQueue  ) 								\    
	    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )

(3)向队列读取消息:

  • 从队列中读取消息,并且消息读取成功后,会将消息从队列中移除。
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer,  TickType_t xTicksToWait )

参数一:队列句柄
参数二:读取数据缓存指针
参数三:指定等待阻塞时间
返回值:pdTRUE,读取成功;pdFALSE,读取失败


  • 从队列中读取消息,消息读取成功后,不会会将消息从队列中移除。
BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const   pvBuffer,   TickType_t   xTicksToWait )

15.信号量:


计数型信号量,二值信号量和互斥信号量的获取和释放都是使用同一组函数的,它们的创建函数不同。二值信号量有一个致命的缺点—可能导致优先级反转,这对于实时操作系统尤为致命,因此引入互斥信号量来解决它的这一缺点


(1)二值信号量与计数型信号量



  • 创建二值信号量:
#define   xSemaphoreCreateBinary( )   						\
 xQueueGenericCreate( 1 ,   semSEMAPHORE_QUEUE_ITEM_LENGTH  ,   queueQUEUE_TYPE_BINARY_SEMAPHORE )

返回值:NULL,创建失败;其他值,返回二值信号量句柄,它是一个SemaphoreHandle_t类型的变量


  • 释放信号量:
BaseType_t xSemaphoreGive( xSemaphore ) //这是宏定义转化之后的函数原型

参数一:信号量句柄
返回值:pdPASS,释放信号量成功;errQUEUE_FULL释放信号量失败,说明信号量此时已满


  • 获取信号量:
BaseType_t   xSemaphoreTake( xSemaphore, xBlockTime ) //这是宏定义转换之后的函数原型

参数一:信号量句柄
参数二:指定阻塞时间
返回值:pdTRUE,获取信号量成功;pdFALSE,超时,获取信号量失败


  • 创建计数型信号量:
#define 	xSemaphoreCreateCounting(  uxMaxCount  ,  uxInitialCount  )   		\
		xQueueCreateCountingSemaphore( (  uxMaxCount  ) , (  uxInitialCount  ) ) 

参数一:指定最大计数
参数二:指定初始计数值
返回值:NULL,创建失败;其他,返回信号量句柄,它是一个SemaphoreHandle_t类型的变量


-获取计数型信号量的当前计数值:

#define 	uxSemaphoreGetCount( xSemaphore ) 						\
		uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )

参数一:信号量句柄
返回值:整数,返回当前信号量的计数值


(2)互斥信号量

互斥信号量通过优先级继承尽可能的降低由优先级反转造成的危害(但是还是会存在优先级反转),互斥信号量不能用于中断服务函数。

  • 创建互斥信号量
#define   xSemaphoreCreateMutex()      xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )

返回值:返回信号量句柄,它是一个SemaphoreHandle_t类型的变量


16.队列集:


如果一个任务想要同时接收一个队列和获取一个信号量,但是这个队列和这个信号量目前都会使任务阻塞(队列为空,信号量未满),那么它应该阻塞等待。但是呢,这个任务如果单独的只等待队列,或者只等待信号量,都不太合理。比如阻塞等待队列期间,如果信号量置满了,那么任务应该去执行信号量的操作,可是此时任务正在阻塞等待队列,所以没法处理这个到来的信号量。如果能同时等待队列和信号量就可以解决这个问题了,怎么实现呢?队列集就是为这个使用场景而生的!


队列集可以同时等待多个信号,在代码上大概体现问如下形式:

接收任务()
{
	等待队列集中的消息
	if(队列还是信号量)
	{
		/*相关处理。。。*/
	}
}

(1)创建队列集

QueueSetHandle_t     xQueueCreateSet( const  UBaseType_t   uxEventQueueLength ); 

参数一:可容纳的队列数量
返回值:NULL调用失败;其他,QueueSetHandle_t类型的队列集句柄


(2)向队列集中添加队列:

BaseType_t xQueueAddToSet( QueueSetMemberHandle_t   	xQueueOrSemaphore ,
					      QueueSetHandle_t   		xQueueSet  	); 

参数一:要添加的队列句柄
参数二:队列集句柄
返回值:pdPASS添加成功;pdFAIL添加失败


(3)从队列集中移除队列:

BaseType_t   xQueueRemoveFromSet( QueueSetMemberHandle_t  	xQueueOrSemaphore ,
						          QueueSetHandle_t   		xQueueSet ); 

参数一:要移除的队列句柄
参数二:队列集句柄
返回值:pdPASS移除成功;pdFAIL移除失败


(4)获取队列集中有有效消息的队列句柄:

QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,                                               					      
TickType_t const xTicksToWait )

参数一:队列集
参数二:指定阻塞时间
返回值:成功返回有有效消息队列句柄;超时失败返回NULL


17.事件标志组


事件标志组包含多个事件标志位,每一个事件标志位可以表示一个事件是否发生。事件标志位可以被任何中断或者任务读写。事件标志组可以等待每一位成立,也可以等待某几位都成立,如果不成立,则阻塞调用的任务或者中断


(1)队列,信号量,事件标志组的区别与联系

队列,信号量的事件发生的时候,只会唤醒一个任务;事件信号量发生的的时候,可以唤醒所有符合条件的任务,类似”广播“的作用;

队列信号量是消耗型的资源,队列的数据被读走就没了;信号量被获取后就减少了
而被事件标志组唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件


(2)创建事件标志组

EventGroupHandle_t    xEventGroupCreate ( void ) ; 

返回值:返回事件标志组句柄


(3)清除事件标志位

EventBits_t  xEventGroupClearBits( EventGroupHandle_t 	xEventGroup,
					      const EventBits_t 	uxBitsToClear ) 

参数一:事件标志组句柄
参数二:要请除的位数
返回值:清零事件标志位之前事件组中事件标志位的值


(4)设置事件标志位

EventBits_t   xEventGroupSetBits(  EventGroupHandle_t 	xEventGroup,
						  const EventBits_t 		uxBitsToSet    ) 

参数一:事件标志组句柄
参数二:要设置的位数
返回值:函数返回时,事件组中的事件标志位值


(5)等待事件标志位

EventBits_t   xEventGroupWaitBits(        EventGroupHandle_t 	xEventGroup,
                                 			       const EventBits_t 	uxBitsToWaitFor,
                                 			       const BaseType_t 	xClearOnExit,
                                 			       const BaseType_t 	xWaitForAllBits,
                                 			       TickType_t 		xTicksToWait         )

参数一:事件标志组句柄

参数二:等待的事件标志位,可以用逻辑或等待多个事件标志位,然后通过参数四来决定是逻辑与等待这些位还是逻辑或等待这些位

参数三:成功等待到事件标志位后,选择是否清除
pdTRUE :清除参数二指定位;
pdFALSE:不清除

参数四:等待 uxBitsToWaitFor 中的所有事件标志位
pdTRUE:等待的位,全部为1
pdFALSE:等待的位,某个为1

参数五:指定阻塞时间

返回值:成功返回等待到的事件标志位,失败返回事件组中的事件标志位


(6)同步函数

同步函数会阻塞等待某个标志位置位之后(达到同步点),置位参数二指定某位(表示此刻同步事件发生)

EventBits_t    xEventGroupSync(   EventGroupHandle_t 	xEventGroup,
						const EventBits_t 	uxBitsToSet,
						const EventBits_t 	uxBitsToWaitFor,
						TickType_t 		xTicksToWait) 

参数一:事件标志组句柄
参数二:达到同步点后,要设置的事件标志
参数三:等待的事件标志
参数四:设置阻塞时间


18.任务通知:


队列,信号量等通知方式需要相关的结构体中间变量作为通讯对象,实现任务之间的间接通讯,而任务通知的通讯对象直接包含在任务控制块pcb中,不需要额外定义相关的结构体,因此任务通知更节省内存,效率更高

只要合理灵活的运用任务通知,就可以在一些场合使用任务通知模拟队列,信号量,事件标志组!


(1)发送通知:


  • 通用发送函数
BaseType_t	 xTaskGenericNotify(  TaskHandle_t 	xTaskToNotify,
                                   			    UBaseType_t 	uxIndexToNotify,
                                   			    uint32_t 		ulValue,
                                   			    eNotifyAction 	eAction,
                                  			    uint32_t * 		pulPreviousNotificationValue  )

参数一:接收任务通知的任务句柄(指定接收方)
参数二:任务的指定通知(任务通知相关数组成员索引,一般为0,及选择第一个成员作为任务通知变量)
参数三:任务通知值
参数四:通知更新方式,下文介绍
参数五:用于保存更新前的任务通知值(为NULL则不保存)

参数四eNotifyAction是枚举类型:

typedef  enum
{    
	eNoAction = 0, 			/* 无操作 */
	eSetBits				/* 更新指定bit */
	eIncrement				/* 通知值加一 */
 	eSetValueWithOverwrite		/* 覆写的方式更新通知值 */
	eSetValueWithoutOverwrite	/* 不覆写通知值 */
} eNotifyAction;


以通用发送函数为基础,通过宏定义定义如下几个函数:

  • 发送通知,带有通知值并且保留接收任务的原通知值
#define   	xTaskNotifyAndQuery( xTaskToNotify ,  ulValue ,  eAction ,  pulPreviousNotifyValue  )	 \   

		xTaskGenericNotify( ( xTaskToNotify ), 
					  ( tskDEFAULT_INDEX_TO_NOTIFY ), 
					  ( ulValue ), 
					  ( eAction ),
					  ( pulPreviousNotifyValue ) )

  • 发送通知,带有通知值
#define	xTaskNotify  (  xTaskToNotify ,  ulValue ,  eAction  ) 							\   
 		xTaskGenericNotify(  ( xTaskToNotify ) ,  ( tskDEFAULT_INDEX_TO_NOTIFY ) ,  ( ulValue ) ,  ( eAction ) ,  NULL  )

  • 发送通知,使通知值+1,不带通知值,常用于信号量
#define 	xTaskNotifyGive(  xTaskToNotify  )									 \   
		xTaskGenericNotify(  ( xTaskToNotify ) ,  ( tskDEFAULT_INDEX_TO_NOTIFY ) ,  ( 0 ) ,   eIncrement ,  NULL )

(2)接收通知:

  • 接收任务通知值,可以设置在退出此函数的时候将任务通知值清零或者减一
    常用于模拟接收二值信号量或者计数型信号量的获取
#define ulTaskNotifyTake( xClearCountOnExit  ,   xTicksToWait ) 			\

ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ),			\
				( xClearCountOnExit ), 					\
				( xTicksToWait ) ) 

参数一:指定在成功接收通知后,将通知值清零或减 1,
pdTRUE:把通知值清零;pdFALSE:把通知值减一

参数二:指定接收阻塞时间

返回值:0,接受失败;非0,接收成功,返回任务通知值


  • 此函数用于获取通知值和清除通知值的指定位值
    适用于模拟队列和事件标志组,使用该函数来获取任务通知 。
#define xTaskNotifyWait(	ulBitsToClearOnEntry, 			\
							ulBitsToClearOnExit, 			\
							pulNotificationValue, 			\
							xTicksToWait) 					\

xTaskGenericNotifyWait( 	tskDEFAULT_INDEX_TO_NOTIFY, 	\
							( ulBitsToClearOnEntry ), 		\
							( ulBitsToClearOnExit ), 		\
							( pulNotificationValue ), 		\
							( xTicksToWait )               ) 

参数一:等待前清零指定任务通知值的比特位(旧值对应bit清0)

参数二:成功等待后清零指定的任务通知值比特位(新值对应bit清0)

参数三:用来取出通知值(如果不需要取出,可设为NULL)

参数四:设置阻塞时间

返回值:pdTRUE等待任务通知成功;pdFALSE等待任务通知失败


19.软件定时器

使用软件定时器相关功能,需要把宏configUSE_TIMERS 置1 ,软件定时器的优先级configTIMER_TASK_PRIORITY = 31;配置为最高,保证第一时间调用软件定时器的超时函数(回调函数),以保证软件定时器的实时性

所有的软件定时器由同一个软件定时器任务维护,这个任务和Linux中的守护进程很相似,在开启任务调度器的那一刻,它就会一直工作

由于软件的超时回调函数使由软件定时器守护任务调用的,而守护任务会一直存在,维护所有的软件定时器,因此,回调函数中一定要快速执行,尽量避免阻塞,延时等慢操作!


(1)软件定时器结构体

typedef    struct
    {
        const char * 				pcTimerName,		/* 软件定时器名字 */
        ListItem_t 					xTimerListItem,		/* 软件定时器列表项 */
        TickType_t 					xTimerPeriodInTicks;/* 软件定时器的周期 */     
        void * 						pvTimerID,			/* 软件定时器的ID */
        TimerCallbackFunction_t	 	pxCallbackFunction,/* 软件定时器的回调函数 */
        #if ( configUSE_TRACE_FACILITY == 1 )
         UBaseType_t 				uxTimerNumber,		/*  软件定时器的编号,调试用  */
        #endif
        uint8_t 					ucStatus,            /*  软件定时器的状态  */
    } xTIMER;


(2)创建软件定时器:

TimerHandle_t   xTimerCreate(    const char * const 		    pcTimerName,
					const TickType_t 		    xTimerPeriodInTicks,
					const UBaseType_t 	    uxAutoReload,
					void * const 			    pvTimerID,
					TimerCallbackFunction_t     pxCallbackFunction  ); 

参数一:软件定时器名字

参数二:定时器超时时间,单位:系统时钟节拍(1ms)

参数三:定时器模式, pdTRUE:周期定时器, pdFALSE:单次定时器

参数四:软件定时器 ID,用于多个软件定时器公用一个超时回调函数

参数五:软件定时器超时回调函数

返回值:NULL,创建失败;其他,创建成功,返回软件定时器 句柄


(3)开启软件定时器:

BaseType_t   xTimerStart( 	TimerHandle_t 	xTimer,
				const TickType_t 	xTicksToWait  ); 

参数一:软件定时器句柄
参数二:发送启动命令到软件定时器命令队列的最大等待时间
返回值:pdPASS,发送启动命令成功;pdFAIL,发送启动命令失败

注意:单次软件定时器


(4)停止软件定时器:

BaseType_t   xTimerStop(  TimerHandle_t 	xTimer,
				const TickType_t 	xTicksToWait); 

参数一:软件定时器句柄
参数二:发送停止命令到软件定时器命令队列的最大等待时间
返回值:pdPASS,发送停止命令成功;pdFAIL,发送停止命令失败


(5)软件定时器复位(重新开始计时)

BaseType_t  xTimerReset( TimerHandle_t 	xTimer,
				const TickType_t 	xTicksToWait); 

参数一:软件定时器句柄
参数二:发送复位命令到软件定时器命令队列的最大等待时间
返回值:pdPASS,发送复位命令成功;pdFAIL,发送复位命令失败


(6)更改软件定时器超时时间

BaseType_t  xTimerChangePeriod( TimerHandle_t 		xTimer,
					     const TickType_t 	xNewPeriod,
                                                         	     const TickType_t 	xTicksToWait); 

参数一:软件定时器句柄
参数二:新的定时超时时间,单位:系统时钟节拍
参数三:发送更改超时时间命令到软件定时器命令队列的最大等待时间
返回值:pdPASS,发送更改超时时间命令成功;pdFAIL,发送更改超时时间命令失败


(7)获取软件定时器ID

如果要多个软件定时器公用一个超时回调函数,应该先调用此函数传入回调函数的参数(软件定时器句柄)获取触发本次回调函数的软件定时器的ID,然后根据这个ID来确定是哪个定时器触发本次超时函数

void * pvTimerGetTimerID( const TimerHandle_t xTimer );

注意事项:由于事先无法确定ID的类型,所有函数返回值为泛型指针类型,具体应用的时候注意强转为创建定时器的时候的ID类型

单次软件定时器状态机:
FreeRTOS应用开发常用函数汇总_第1张图片
周期软件定时器状态机:
FreeRTOS应用开发常用函数汇总_第2张图片
软件定时器在运行态只能调用停止,调用其他的会被忽略


20.低功耗模式(Tickless)

freertos低功耗模式的设计理念是,在本该空闲任务执行的期间,让MCU 进入相应的低功耗模式;当其他任务准备运行的时候,唤醒MCU退出低功耗模式

下面介绍一些低功耗宏定义配置项:


(1)使能低功耗

configUSE_TICKLESS_IDLE

(2)定义系统进入低功耗模式的最短时长
至少大于2,单位:系统时钟节拍

configEXPECTED_IDLE_TIME_BEFORE_SLEEP 

(3)定义进入低功耗模式之前要做的事情

configPRE_SLEEP_PROCESSING(x) 

(4)定义退出低功耗模式之后要做的事情

configPOSR_SLEEP_PROCESSING(x) 

21.内存管理

以freertos的heap_4为例


(1)分配内存

void * pvPortMalloc( size_t  xWantedSize );

(2)释放内存

void  vPortFree( void * pv );

(3)获取当前剩余内存大小

size_t  xPortGetFreeHeapSize( void );

你可能感兴趣的:(STM32,C语言,学习)