对freertos的API函数进行了初步的整理,方便查阅。
/*freertos头文件*/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "timers.h"
#include "event_groups.h"
/*基础类变量*/
UBaseType_t
/*freertos config配置*/
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1 //1使能时间片调度(默认式使能的)
#define configMAX_PRIORITIES ( 5 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) )
#define configUSE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_TRACE_FACILITY 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
/*互斥量量API运用流程*/
#include "semphr.h"
SemaphoreHandle_t mutexHandle //信号量句柄初始化
mutexHandle = xSemaphoreCreateMutex();//互斥量初始化
xSemaphoreTake(mutexHandle, portMAX_DELAY); //获取互斥量
xSemaphoreGive(mutexHandle); //释放互斥量
/*task任务创建*/
xTaskCreate (vTask1, "T1", 200, NULL, 1, NULL); //线程初始化
//param 5: priority
//param 6: taskhandle
vTaskStartScheduler();//开启线程调度
void vTask1(void * pvParams); //函数入口
/*task任务传参*/
const int task_1_Param = 1;
xTaskCreate (vTask, "T1", 150, (void *)&task_1_Param, 1, NULL);
void vTask(void * pvParams)
{
const int * tparam = (const int *)pvParams;
}
/*task中调用,会主动让出cpu,让其他task获得执行权限*/
taskYIELD();
/*队列API函数(轮询状态)*/
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) //队列相关宏定义
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
u8 msgq_remain_size; //消息队列剩余大小
u8 msgq_total_size; //消息队列总大小
msgq_remain_size=uxQueueSpacesAvailable(Message_Queue);//得到队列剩余大小
msgq_total_size=uxQueueMessagesWaiting(Message_Queue)+uxQueueSpacesAvailable(Message_Queue);//得到队列总大小,总大小=使用+剩余的。
QueueHandle_t qHandle;
const char *t1_Msg = "Task-1 Message...";
qHandle = xQueueCreate(1, sizeof(char *));
txStatus = xQueueSendToBack(qHandle, &t1_Msg, 2);
xQueueReceive(qHandle, &msgPtr, 500);
/*队列API函数(中断状态)*/
void handler()
{
BaseType_t xHigherPriorityTaskWoken;
xQueueSendToBackFromISR(qHandle, &t1_Msg, &xHigherPriorityTaskWoken);
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
/*二值信号量API函数使用流程(带中断)*/
SemaphoreHandle_t smphrHandle;
smphrHandle = xSemaphoreCreateBinary();
xSemaphoreTake(smphrHandle, portMAX_DELAY);
void handler()
{
BaseType_t xHigherPriorityTaskWoken;
xSemaphoreGiveFromISR(smphrHandle, &xHigherPriorityTaskWoken);
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
/*创建计数型信号量*/
CountSemaphore=xSemaphoreCreateCounting(255,0);
xSemaphoreGive(CountSemaphore);//释放计数型信号量
u8 semavalue;
semavalue=uxSemaphoreGetCount(CountSemaphore); //获取计数型信号量值
xSemaphoreTake(CountSemaphore,portMAX_DELAY); //等待数值信号量
/*task提升或降低优先级*/
const int task_1_Param = 1;
xTaskCreate (vTask, "T1", 150, (void *)&task_1_Param, 1, &hTask1);
void vTask(void * pvParams)
{
const int * tparam = (const int *)pvParams;
for(;;)
{
if(...)
{
vTaskPrioritySet(hTask1, uxTaskPriorityGet(hTask1)+1);
}
/*delete task*/ vTaskDelete(hTask1);
}
}
/*临界区API函数*/
taskENTER_CRITICAL();
taskEXIT_CRITICAL();
taskENTER_CRITICAL_FROM_ISR();
taskEXIT_CRITICAL_FROM_ISR();
/*挂起线程*/
vTaskSuspend(hTask1);//挂起任务1
vTaskSuspendFromISR(hTask1);//挂起任务1(中断使用)
/*恢复线程*/
vTaskResume(hTask1);//恢复任务1
vTaskResumeFromISR(hTask1);//恢复任务1(中断使用)
/*打开或关闭可屏蔽的中断*/
taskDISABLE_INTERRUPTS();
taskENABLE_INTERRUPTS();
/*打开或关闭任务调度器*/
vTaskStartScheduler();
vTaskEndScheduler(); //at the time of writing only the x86 read mode port
/* 注意:系统时钟会停止运行,所有创建的任务都会自动删除掉*/
/*挂起任务调度器*/
vTaskSuspendAll();
/*恢复任务调度器*/
xTaskResumeAll();
/*注意挂起任务调度器是支持嵌套的,挂起任务调度器几次就需要恢复同样的次数*/
/*列表和列表项的定义*/
List_t TestList; //测试用列表
ListItem_t ListItem1; //测试用列表项1
ListItem_t ListItem2; //测试用列表项2
ListItem_t ListItem3; //测试用列表项3
/*列表和列表项的初始化*/
vListInitialise(&TestList);
vListInitialiseItem(&ListItem1);
vListInitialiseItem(&ListItem2);
vListInitialiseItem(&ListItem3);
//设置列表项相应的数值
ListItem1.xItemValue=40; //ListItem1列表项值为40
ListItem2.xItemValue=60; //ListItem2列表项值为60
ListItem3.xItemValue=50; //ListItem3列表项值为50
/*使用对应的插入函数或移除函数*/
vListInsert(&TestList,&ListItem1);
vListInsert(&TestList,&ListItem2);
vListInsert(&TestList,&ListItem3);
uxListRemove(&ListItem2);
vListInsertEnd(&TestList,&ListItem2);
/*注意:vListInsert函数是按升序方式插入的,而vListInsertEnd函数默认插入在列表的末尾。*/
/*tickless模式下执行空闲任务时会停止节拍中断,此函数负责补上节拍*/
#define configUSE_TICKLESS_IDLE 1
vTaskStepTick();
/*查询任务状态*/
UBaseType_t ArraySize;
ArraySize=uxTaskGetNumberOfTasks(); //获取系统任务数量
StatusArray=pvPortMalloc(ArraySize*sizeof(TaskStatus_t));//申请内存
ArraySize=uxTaskGetSystemState((TaskStatus_t* )StatusArray, //任务信息存储数组
(UBaseType_t )ArraySize, //任务信息存储数组大小
(uint32_t* )&TotalRunTime);//保存系统总的运行时间
//通过串口打印出获取到的系统任务的有关信息,比如任务名称、任务优先级和任务编号。
for(x=0;x<ArraySize;x++)
{
//通过串口打印出获取到的系统任务的有关信息,比如任务名称、
//任务优先级和任务编号。
printf("%s\t\t%d\t\t\t%d\t\t\t\r\n",
StatusArray[x].pcTaskName,
(int)StatusArray[x].uxCurrentPriority,
(int)StatusArray[x].xTaskNumber);
}
vPortFree(StatusArray); //释放内存
/*函数vTaskGetInfo()的使用*/
TaskHandle_t TaskHandle;
TaskStatus_t TaskStatus;
TaskHandle=xTaskGetHandle("led0_task"); //根据任务名获取任务句柄。
vTaskGetInfo((TaskHandle_t )TaskHandle, //任务句柄
(TaskStatus_t* )&TaskStatus, //任务信息结构体
(BaseType_t )pdTRUE, //允许统计任务堆栈历史最小剩余大小
(eTaskState )eInvalid); //函数自己获取任务运行壮态
printf("任务名: %s\r\n",TaskStatus.pcTaskName);
printf("任务编号: %d\r\n",(int)TaskStatus.xTaskNumber);
printf("任务壮态: %d\r\n",TaskStatus.eCurrentState);
printf("任务当前优先级: %d\r\n",(int)TaskStatus.uxCurrentPriority);
printf("任务基优先级: %d\r\n",(int)TaskStatus.uxBasePriority);
printf("任务堆栈基地址: %#x\r\n",(int)TaskStatus.pxStackBase);
printf("任务堆栈历史剩余最小值:%d\r\n",TaskStatus.usStackHighWaterMark);
/*函数eTaskGetState()的使用*/
eTaskState TaskState;
char TaskInfo[10];
TaskHandle=xTaskGetHandle("query_task"); //根据任务名获取任务句柄。
TaskState=eTaskGetState(TaskHandle); //获取query_task任务的任务壮态
memset(TaskInfo,0,10);
switch((int)TaskState)
{
case 0:
sprintf(TaskInfo,"Running");
break;
case 1:
sprintf(TaskInfo,"Ready");
break;
case 2:
sprintf(TaskInfo,"Suspend");
break;
case 3:
sprintf(TaskInfo,"Delete");
break;
case 4:
sprintf(TaskInfo,"Invalid");
break;
}
printf("任务壮态值:%d,对应的壮态为:%s\r\n",TaskState,TaskInfo);
/*函数vTaskList()的使用 */
vTaskList(InfoBuffer);
printf("%s\r\n",InfoBuffer); //通过串口打印所有任务的信息
xTaskGetTickCountFromISR();
/*查询任务运行时间*/
char RunTimeInfo[400]; //保存任务运行时间信息
memset(RunTimeInfo,0,400); //信息缓冲区清零
vTaskGetRunTimeStats(RunTimeInfo); //获取任务运行时间信息
printf("任务名\t\t\t运行时间\t运行所占百分比\r\n");
printf("%s\r\n",RunTimeInfo);
/*软件定时器*/
TimerHandle_t AutoReloadTimer_Handle; //周期定时器句柄
TimerHandle_t OneShotTimer_Handle; //单次定时器句柄
void AutoReloadCallback(TimerHandle_t xTimer); //周期定时器回调函数
void OneShotCallback(TimerHandle_t xTimer); //单次定时器回调函数
//创建软件周期定时器
AutoReloadTimer_Handle=xTimerCreate((const char* )"AutoReloadTimer",
(TickType_t )1000,
(UBaseType_t )pdTRUE,
(void* )1,
(TimerCallbackFunction_t)AutoReloadCallback); //周期定时器,周期1s(1000个时钟节拍),周期模式
//创建单次定时器
OneShotTimer_Handle=xTimerCreate((const char* )"OneShotTimer",
(TickType_t )2000,
(UBaseType_t )pdFALSE,
(void* )2,
(TimerCallbackFunction_t)OneShotCallback); //单次定时器,周期2s(2000个时钟节拍),单次模式
xTimerStart(AutoReloadTimer_Handle,0); //开启周期定时器
xTimerStart(OneShotTimer_Handle,0); //开启单次定时器
xTimerStop(AutoReloadTimer_Handle,0); //关闭周期定时器
xTimerStop(OneShotTimer_Handle,0); //关闭单次定时器
//周期定时器的回调函数
void AutoReloadCallback(TimerHandle_t xTimer)
{
...
}
//单次定时器的回调函数
void OneShotCallback(TimerHandle_t xTimer)
{
...
}
/*事件标志组*/
/*支持的事件数量*/
/*当configUSE_16_BIT_TICKS1 为 1 的时候事件标志组有 8 个 可 用 的 位 (bit0~bit7)*/
/*configUSE_16_BIT_TICKS 为 0 的时候事件标志组有 24 个可用的位(bit0~bit23)*/
EventGroupHandle_t EventGroupHandler; //事件标志组句柄
#define EVENTBIT_0 (1<<0) //事件位
#define EVENTBIT_1 (1<<1)
#define EVENTBIT_2 (1<<2)
EventGroupHandler=xEventGroupCreate(); //创建事件标志组
xEventGroupSetBits(EventGroupHandler,EVENTBIT_1);
xEventGroupSetBits(EventGroupHandler,EVENTBIT_2);
EventValue=xEventGroupWaitBits((EventGroupHandle_t )EventGroupHandler,
(EventBits_t )EVENTBIT_ALL,
(BaseType_t )pdTRUE,
(BaseType_t )pdTRUE,
(TickType_t )portMAX_DELAY);
EventBits_t NewValue;
NewValue=xEventGroupGetBits(EventGroupHandler); //获取事件组的
/*任务通知模拟计数信号量和二值信号量*/
extern TaskHandle_t DataProcess_Handler; //接收任务通知的任务句柄
void hander()
{
...
BaseType_t xHigherPriorityTaskWoken;
vTaskNotifyGiveFromISR(DataProcess_Handler,&xHigherPriorityTaskWoken);//发送任务通知
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换
}
u32 NotifyValue; //事件通知的数据类型是32位的和定时器的位数相同
NotifyValue=ulTaskNotifyTake(pdTRUE,portMAX_DELAY); //获取任务通知
xTaskNotifyGive(SemapTakeTask_Handler);
NotifyValue=ulTaskNotifyTake(pdFALSE,portMAX_DELAY);
/*参数为 pdFALSE 的话在退出函数 ulTaskNotifyTake()的时候任务通知值
减一,类似计数型信号量。当此参数为 pdTRUE 的话在退出函数的时候
任务任务通知值清零,类似二值信号量。*/
xTaskNotifyGive(SemapTakeTask_Handler);
/*任务通知模拟邮箱*/
err=xTaskNotify((TaskHandle_t )Keyprocess_Handler, //接收任务通知的任务句柄
(uint32_t )key, //任务通知值
(eNotifyAction )eSetValueWithOverwrite); //覆写的方式发送任务通知
err=xTaskNotifyWait((uint32_t )0x00, //进入函数的时候不清除任务bit
(uint32_t )ULONG_MAX, //退出函数的时候清除所有的bit
(uint32_t* )&NotifyValue, //保存任务通知值
(TickType_t )portMAX_DELAY); //阻塞时间
/*任务通知模拟事件组*/
xTaskNotify((TaskHandle_t )EventGroupTask_Handler,//接收任务通知的任务句柄
(uint32_t )EVENTBIT_1, //要更新的bit
(eNotifyAction )eSetBits); //更新指定的bit
xTaskNotify((TaskHandle_t )EventGroupTask_Handler,//接收任务通知的任务句柄
(uint32_t )EVENTBIT_2, //要更新的bit
(eNotifyAction )eSetBits); //更新指定的bit
uint32_t NotifyValue;
//获取任务通知值
err=xTaskNotifyWait((uint32_t )0x00, //进入函数的时候不清除任务bit
(uint32_t )ULONG_MAX, //退出函数的时候清除所有的bit
(uint32_t* )&NotifyValue, //保存任务通知值
(TickType_t )portMAX_DELAY); //阻塞时间
//如果没有使用抢占式内核的话就强制进行一次任务切换查看是否有其他
//任务有效,如果有使用抢占式内核的话就不需要这一步,因为只要有任
//何任务有效(就绪)之后都会自动的抢夺 CPU 使用权
taskYIELD();