FreeRTOS基础函数汇总-入门学习总结

目录

基础任务相关函数

动态任务创建函数:

静态创建任务函数:

静态创建任务函数示例:

任务删除函数

任务挂起函数

任务恢复函数(任务中恢复)

任务恢复函数(中断中恢复)

中断开启函数

中断关闭函数

临界段代码保护函数

任务调度器的挂起和恢复

列表和列表项

API函数:

使用示例:

任务状态查询API函数介绍

获取任务优先级

设置任务优先级

获取系统中任务的数量 

获取所有任务状态信息

获取指定单个的任务信息

获取当前任务的任务句柄

根据任务名获取该任务的任务句柄

获取任务的任务栈历史剩余最小值

获取任务状态       

以“表格”形式获取所有任务的信息

获取任务的运行时间

使用示例:

队列

动态方式创建:

往队列写入消息API函数

队列写入消息

往队列写入消息函数入口参数解析:

从队列读取消息API函数:

使用示例:

二值信号量

动态创建二值信号量函数:

静态创建二值信号量函数:

释放二值信号量函数

获取二值信号量函数:

使用示例: 

计数型二值信号量

创建计数型二值信号量函数:

使用示例:

互斥信号量

创建互斥信号量函数

使用示例:

任务通知

发送通知相关API函数:

任务通知方式共有以下几种:

接收通知相关API函数:

 ·使用示例(任务通知模拟二值信号量实验):

·使用示例(任务通知模拟消息邮箱):

·使用示例(任务通知模拟事件标志组):


基础任务相关函数

动态任务创建函数:

        使用前将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为 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

)

参数:

        pxTaskCode /* 指向任务函数的指针 */

        pcName   /* 任务名字,最大长度configMAX_TASK_NAME_LEN */

        usStackDepth, /* 任务堆栈大小,注意字为单位 */

        pvParameters, /* 传递给任务函数的参数 */

        uxPriority  /*任务优先级,范围:0 ~ configMAX_PRIORITIES - 1

        pxCreatedTask /* 任务句柄,就是任务的任务控制块 */

返回值:

        成功:pdPASS

        失败:errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY

静态创建任务函数:

        使用前需将宏configSUPPORT_STATIC_ALLOCATION 配置为 1

TaskHandle_t xTaskCreateStatic(

             TaskFunction_t                         pxTaskCode,

             const char * const                     pcName,

             const uint32_t                           ulStackDepth,

             void * const                               pvParameters,

             UBaseType_t                            uxPriority,

             StackType_t * const                  puxStackBuffer,

             StaticTask_t * const                  pxTaskBuffer );

参数:

        pxTaskCode, /* 指向任务函数的指针 */

        pcName, /* 任务函数名 */

        ulStackDepth, /* 任务堆栈大小注意字为单位 */

        pvParameters, /* 传递的任务函数参数 */

        uxPriority, /* 任务优先级 */

        puxStackBuffer, /* 任务堆栈,一般为数组,由用户分配

        pxTaskBuffer /* 任务控制块指针,由用户分配 */

返回值:

        成功:任务句柄

        失败:NULL

还需实现两个接口函数:

/*空闲任务内存配置*/

StaticTask_t idle_task_tcb;

StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];

/*软件定时器内存配置*/

StaticTask_t timer_task_tcb;

StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH];

void vApplicationGetIdleTaskMemory(

StaticTask_t ** ppxIdleTaskTCBBuffer,

StackType_t ** ppxIdleTaskStackBuffer,

uint32_t * pulIdleTaskStackSize )

{

* ppxIdleTaskTCBBuffer = &idle_task_tcb;

* ppxIdleTaskStackBuffer = idle_task_stack;

* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;

}

void vApplicationGetTimerTaskMemory(

StaticTask_t ** ppxTimerTaskTCBBuffer,

StackType_t ** ppxTimerTaskStackBuffer,

uint32_t * pulTimerTaskStackSize )

{

* ppxTimerTaskTCBBuffer = &timer_task_tcb;

* ppxTimerTaskStackBuffer = timer_task_stack;

* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;

}

静态创建任务函数示例:

#define    START_TASK_PRIO    1
#define START_SIZE        128
TaskHandle_t     start_task_handle;
StackType_t        start_task_stack[START_SIZE];
StaticTask_t    start_task_tcb;

#define    TASK1_PRIO        2
#define TASK1_SIZE        50
TaskHandle_t task1_handle;
StackType_t        task1_stack[TASK1_SIZE];
StaticTask_t    task1_tcb;

#define    TASK2_PRIO        3
#define TASK2_SIZE        50
TaskHandle_t task2_handle;
StackType_t        task2_stack[TASK2_SIZE];
StaticTask_t    task2_tcb;

void freertos_dome(void);
void start_task(void *pvParameters);
void task1(void *pvParameters);
void task2(void *pvParameters);


//空闲任务内存配置
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];


//软件定时器内存配置
StaticTask_t timer_task_tcb;
StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH];

//空闲任务内存分配
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
                                   StackType_t ** ppxIdleTaskStackBuffer,
                                   uint32_t * pulIdleTaskStackSize )
{
    * ppxIdleTaskTCBBuffer = &idle_task_tcb;
    * ppxIdleTaskStackBuffer = idle_task_stack;
    * pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}


//软件定时器内存分配
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                         StackType_t ** ppxTimerTaskStackBuffer,
                                         uint32_t * pulTimerTaskStackSize )
{
    * ppxTimerTaskTCBBuffer = &timer_task_tcb;
    * ppxTimerTaskStackBuffer = timer_task_stack;
    * pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}


int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4          
    delay_init();                        //延时函数初始化      
    uart_init(115200);                    //初始化串口
    LED_Init();                              //初始化LED
    
     
    freertos_dome();
  
}

//开始任务任务函数
void freertos_dome(void)
{
    start_task_handle = xTaskCreateStatic( 
                                             (TaskFunction_t    )        start_task,
                                           (char *            )        "start_task",
                                           (uint32_t         )        START_SIZE,
                                           (void *            )        NULL,
                                           (UBaseType_t        )        START_TASK_PRIO,
                                           (StackType_t *    )        start_task_stack,
                                           (StaticTask_t *    )        &start_task_tcb 
                                        );
    
    
    vTaskStartScheduler();          //开启任务调度
}


void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    
    task1_handle = xTaskCreateStatic( (TaskFunction_t    )        task1,
                                       (char *            )        "task1",
                                       (uint32_t         )        TASK1_SIZE,
                                       (void *            )        NULL,
                                       (UBaseType_t        )        TASK1_PRIO,
                                       (StackType_t *    )        task1_stack,
                                       (StaticTask_t *    )        &task1_tcb 
                                    );
                       
    task2_handle = xTaskCreateStatic( (TaskFunction_t    )        task2,
                                       (char *            )        "task2",
                                       (uint32_t         )        TASK2_SIZE,
                                       (void *            )        NULL,
                                       (UBaseType_t        )        TASK2_PRIO,
                                       (StackType_t *    )        task2_stack,
                                       (StaticTask_t *    )        &task2_tcb 
                                     );
    
    task3_handle = xTaskCreateStatic( (TaskFunction_t    )        task3,
                                       (char *            )        "task3",
                                       (uint32_t         )        TASK3_SIZE,
                                       (void *            )        NULL,
                                       (UBaseType_t        )        TASK3_PRIO,
                                       (StackType_t *    )        task3_stack,
                                       (StaticTask_t *    )        &task3_tcb 
                                     );
    
    vTaskDelete(start_task_handle);
    taskEXIT_CRITICAL();            //退出临界区
}


//实现LED0每500ms反转一次
void task1(void *pvParameters) 
{
    while(1)
    {
        printf("-----task1正在运行-----\n");
        LED0 = 0;
        vTaskDelay(200);
        LED0 = 1;
        vTaskDelay(200);
    }
}


//实现LED1每800ms反转一次
void task2(void *pvParameters)
{
    while(1)
    {
        printf("-----task2正在运行-----\n");
        LED1 = 0;
        vTaskDelay(800);
        LED1 = 1;
        vTaskDelay(800);
    }
}

任务删除函数

        使用删除任务函数,需将宏INCLUDE_vTaskDelete 配置为 1

void vTaskDelete(TaskHandle_t xTaskToDelete);

参数:

        xTaskToDelete /*待删除任务的任务句柄*/

        传NULL表示删除当前任务

返回值:无

任务挂起函数

        此函数用于挂起任务,使用时需将宏 INCLUDE_vTaskSuspend  配置为 1。

void vTaskSuspend(TaskHandle_t xTaskToSuspend)

参数:

        xTaskToSuspend 待挂起任务的任务句柄

任务恢复函数(任务中恢复)

        使用该函数注意宏:INCLUDE_vTaskSuspend必须定义为 1

void vTaskResume(TaskHandle_t xTaskToResume)

参数:

        xTaskToResume 待恢复任务的任务句柄

描述:

        注意:任务无论被 vTaskSuspend() 挂起多少次,只需在任务中调用  vTakResume() 恢复一次,就可以继续运行。且被恢复的任务会进入就绪态!

任务恢复函数(中断中恢复)

         使用该函数注意宏:INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须定义为 1

 BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume)

参数:

        xTaskToResume 待恢复任务的任务句柄

返回值:        成功:pdTRUE

                        失败:pdFLASE

描述:      

        该函数专用于中断服务函数中,用于解挂被挂起任务

        注意:中断服务程序中要调用freeRTOS的API函数则中断优先级不能高于FreeRTOS所管理的最高优先级

中断开启函数

portENABLE_INTERRUPTS ()

参数:无

返回值:无

描述:本质是一个宏定义,具体实现通过操控BASEPRI寄存器实现

中断关闭函数

portDISABLE_INTERRUPTS()

参数:无

返回值:无

描述:本质是一个宏定义,具体实现通过操控BASEPRI寄存器实现

临界段代码保护函数

  1. taskENTER_CRITICAL()                           任务级进入临界段
  2. taskEXIT_CRITICAL()                                任务级退出临界段
  3. taskENTER_CRITICAL_FROM_ISR()       中断级进入临界段
  4. taskEXIT_CRITICAL_FROM_ISR()           中断级退出临界段

任务调度器的挂起和恢复

vTaskSuspendAll()                                              挂起任务调度器

xTaskResumeAll()                                               恢复任务调度器 

列表和列表项

API函数:

函数

描述

vListInitialise() 

初始化列表

vListInitialiseItem() 

初始化列表项

vListInsertEnd() 

列表末尾插入列表项

vListInsert() 

列表插入列表项

uxListRemove() 

列表移除列表项

使用示例:

List_t List;
ListItem_t ListItem1;
ListItem_t ListItem2;
ListItem_t ListItem3;
 

void List_Task(void *p)
{
    vListInitialise(&List);
    vListInitialiseItem(&ListItem1);
    vListInitialiseItem(&ListItem2);
    vListInitialiseItem(&ListItem3);
    
    printf("/***********列表和列表项初始化地址********\r/\n");
    printf("List                        %#x\r\n",(int)&List);
    printf("ListItem1                   %#x\r\n",(int)&ListItem1);
    printf("ListItem2                   %#x\r\n",(int)&ListItem2);
    printf("ListItem3                   %#x\r\n",(int)&ListItem3);
    printf("/******************结束**********//\r\n");
    
    vListInsert(&List,&ListItem1);
    printf("/*************添加ListItem1****************//\r\n");
    printf("/**************Next*********//\r\n");    
    printf("List->xListEnd->pxNext      %#x\r\n",(int)(List.xListEnd.pxNext));
    printf("ListItem1->pxNext                        %#x\r\n",(int)(ListItem1.pxNext));
    printf("/***************pxPrevious*********//\r\n");    
    printf("List->xListEnd->pxPrevious    %#x\r\n",(int)(List.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious                %#x\r\n",(int)(ListItem1.pxPrevious));
    
    vListInsert(&List,&ListItem2);
    printf("/************添加ListItem2************//\r\n");
    printf("/*******************Next************//\r\n");    
    printf("List->xListEnd->pxNext            %#x\r\n",(int)(List.xListEnd.pxNext));
    printf("ListItem1->pxNext                        %#x\r\n",(int)(ListItem1.pxNext));
    printf("ListItem2->pxNext                        %#x\r\n",(int)(ListItem2.pxNext));
    printf("/****************pxPrevious***********//\r\n");    
    printf("List->xListEnd->pxPrevious    %#x\r\n",(int)(List.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious                %#x\r\n",(int)(ListItem1.pxPrevious));
    printf("ListItem2->pxPrevious                %#x\r\n",(int)(ListItem2.pxPrevious));
    
    vListInsert(&List,&ListItem3);
    printf("/**************添加ListItem3**************//\r\n");
    printf("/*********************Next***************//\r\n");    
    printf("List->xListEnd->pxNext            %#x\r\n",(int)(List.xListEnd.pxNext));
    printf("ListItem1->pxNext                        %#x\r\n",(int)(ListItem1.pxNext));
    printf("ListItem2->pxNext                        %#x\r\n",(int)(ListItem2.pxNext));
    printf("ListItem3->pxNext                        %#x\r\n",(int)(ListItem3.pxNext));
    printf("/*****************pxPrevious********//\r\n");    
    printf("List->xListEnd->pxPrevious    %#x\r\n",(int)(List.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious                %#x\r\n",(int)(ListItem1.pxPrevious));
    printf("ListItem2->pxPrevious                %#x\r\n",(int)(ListItem2.pxPrevious));
    printf("ListItem3->pxPrevious                %#x\r\n",(int)(ListItem3.pxPrevious));
    
    uxListRemove(&ListItem2);
    printf("/**************删除ListItem2*******//\r\n");
    printf("/**************Next********//\r\n");    
    printf("List->xListEnd->pxNext            %#x\r\n",(int)(List.xListEnd.pxNext));
    printf("ListItem1->pxNext                        %#x\r\n",(int)(ListItem1.pxNext));
    printf("ListItem3->pxNext                        %#x\r\n",(int)(ListItem3.pxNext));
    printf("/**************pxPrevious**********//\r\n");    
    printf("List->xListEnd->pxPrevious    %#x\r\n",(int)(List.xListEnd.pxPrevious));
    printf("ListItem1->pxPrevious                %#x\r\n",(int)(ListItem1.pxPrevious));
    printf("ListItem3->pxPrevious                %#x\r\n",(int)(ListItem3.pxPrevious));
    
    vListInsertEnd(&List,&ListItem2);
    printf("/**************在末尾项添加ListItem2*************//\r\n");
    printf("/**************Next*************//\r\n");    
    printf("List->xListEnd->pxNext            %#x\r\n",(int)(List.xListEnd.pxNext));
    
    printf("ListItem1->pxNext                        %#x\r\n",(int)(ListItem1.pxNext));
    printf("ListItem3->pxNext                        %#x\r\n",(int)(ListItem3.pxNext));
    printf("ListItem2->pxNext                        %#x\r\n",(int)(ListItem2.pxNext));
    printf("/***************pxPrevious*****************//\r\n");    
    printf("List->xListEnd->pxPrevious    %#x\r\n",(int)(List.xListEnd.pxPrevious));
    
    printf("ListItem1->pxPrevious                %#x\r\n",(int)(ListItem1.pxPrevious));
    printf("ListItem3->pxPrevious                %#x\r\n",(int)(ListItem3.pxPrevious));
    printf("ListItem2->pxPrevious                %#x\r\n",(int)(ListItem2.pxPrevious));
    while(1)
    {
        
    }
}

  • 任务状态查询API函数介绍

获取任务优先级

        此函数用于获取指定任务的任务优先级,使用该函数需将宏 INCLUDE_uxTaskPriorityGet 置 1

UBaseType_t  uxTaskPriorityGet(  const TaskHandle_t xTask  )

参数:

        xTask                要查找的任务句柄,NULL代表任务自身

返回值:

        整数                  任务优先级数值   

设置任务优先级

        此函数用于改变某个任务的任务优先级,使用该函数需将宏 INCLUDE_vTaskPrioritySet  为 1

void vTaskPrioritySet( TaskHandle_t xTask , UBaseType_t uxNewPriority )

参数:        

        xTask                        任务句柄,NULL代表任务自身

        uxNewPriority           需要设置的任务优先级  

获取系统中任务的数量 

        此函数用于获取系统中任务的任务数量

UBaseType_t uxTaskGetNumberOfTasks( void )

返回值:

        整型                系统中任务的数量  

获取所有任务状态信息

        此函数用于获取系统中所有任务的任务状态信息,使用该函数需将宏 configUSE_TRACE_FACILITY 置 1

UBaseType_t  uxTaskGetSystemState(  

                        TaskStatus_t * const pxTaskStatusArray,

                        const UBaseType_t uxArraySize,

                        configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime  )

参数:

        pxTaskStatusArray                        指向TaskStatus_t 结构体数组首地址

        uxArraySize                                  接收信息的数组大小

        pulTotalRunTime                           系统总运行时间,为NULL 则省略总运行时间值

返回值:

        整型                获取信息的任务数量

获取指定单个的任务信息

        函数用于获取指定的单个任务的状态信息,使用该函数需将宏 configUSE_TRACE_FACILITY  置 1

void vTaskGetInfo( TaskHandle_t xTask,
          TaskStatus_t * pxTaskStatus,
          BaseType_t xGetFreeStackSpace,
          eTaskState eState  )

参数:

        xTask                                        指定获取信息的任务的句柄

        pxTaskStatus                                接收任务信息的变量

        xGetFreeStackSpace                        

                                                                任务栈历史剩余最小值,

                                                                当为“pdFALSE” 则跳过这个步骤,

                                                                当为“pdTRUE”则检查历史剩余最小堆栈

        eState                                          任务状态,可直接赋值,如想获取代入“eInvalid”

typedef enum

{   

        eRunning = 0, /* 运行态 */

        eReady /* 就绪态 */

        eBlocked, /* 阻塞态 */

        eSuspended, /* 挂起态 */

        eDeleted, /* 任务被删除 */

        eInvalid /* 无效 */

} eTaskState;

获取当前任务的任务句柄

        此函数用于获取当前任务的任务句柄, 使用该函数需将宏 INCLUDE_xTaskGetCurrentTaskHandle  置 1

TaskHandle_t    xTaskGetCurrentTaskHandle( void )

返回值:

        当前任务的任务句柄

根据任务名获取该任务的任务句柄

        此函数用于通过任务名获取任务句柄 , 使用该函数需将宏 INCLUDE_xTaskGetHandle 置 1

TaskHandle_t xTaskGetHandle(const char * pcNameToQuery);

参数:
        pcNameToQuery                任务名

返回值:

        任务的任务句柄

获取任务的任务栈历史剩余最小值

        此函数用于获取指定任务的任务栈历史最小剩余堆栈;使用该函数需将宏 INCLUDE_uxTaskGetStackHighWaterMark 置 1

UBaseType_t    uxTaskGetStackHighWaterMark( TaskHandle_t  xTask )

参数:

        xTask         任务句柄

返回值:

        任务栈的历史剩余最小值

获取任务状态       

         此函数用于查询某个任务的运行状态,使用此函数需将宏 INCLUDE_eTaskGetState 置1  

eTaskState    eTaskGetState(TaskHandle_t xTask)

参数:
        xTask                任务句柄

返回值:

        eTaskState          任务当前状态

typedef enum

{   

        eRunning = 0, /* 运行态 */

        eReady /* 就绪态 */

        eBlocked, /* 阻塞态 */

        eSuspended, /* 挂起态 */

        eDeleted, /* 任务被删除 */

        eInvalid /* 无效 */

} eTaskState;

以“表格”形式获取所有任务的信息

        此函数用于以“表格”的形式获取系统中任务的信息 ;使用此函数需将宏 configUSE_TRACE_FACILITY 和configUSE_STATS_FORMATTING_FUNCTIONS 置1

void   vTaskList(char * pcWriteBuffer)

参数:

        pcWriteBuffer        接收任务信息的缓存指针

获取任务的运行时间

使用示例:

char task_buff[500];

/* 任务二,实现任务状态查询API函数使用 */

void task2( void * pvParameters )

{

    UBaseType_t priority_num = 0;

    UBaseType_t task_num = 0;

    UBaseType_t task_num2 = 0;

    TaskStatus_t * status_array = 0;

    TaskStatus_t * status_array2 = 0;

    TaskHandle_t task_handle = 0;

    UBaseType_t task_stack_min = 0;

    eTaskState state = 0;

    

    uint8_t i = 0;

    

/*改变/设置任务优先级*/

vTaskPrioritySet( task2_handler,4 );

/*获取任务优先级*/

    priority_num = uxTaskPriorityGet( NULL );

    printf("task2任务优先级为%ld\r\n",priority_num);

    

/*获取系统中任务数量*/

    task_num = uxTaskGetNumberOfTasks();

    printf("任务数量:%ld\r\n",task_num);

    

/*获取所有任务状态信息*/

status_array = mymalloc(SRAMIN,(sizeof(TaskStatus_t) * task_num));

    task_num2 = uxTaskGetSystemState( status_array,task_num,NULL);

    printf("任务名\t\t任务优先级\t任务编号\r\n");

    for(i = 0; i < task_num2; i++)

    {

        printf("%s\t\t%ld\t%ld\r\n",

                status_array[i].pcTaskName,

                status_array[i].uxCurrentPriority,

                status_array[i].xTaskNumber);

}

    /*获取指定单个的任务信息*/

    status_array2 = mymalloc(SRAMIN,sizeof(TaskStatus_t));

    vTaskGetInfo( task2_handler,status_array2,pdTRUE,eInvalid);

    printf("任务名:%s\r\n",status_array2->pcTaskName);

    printf("任务优先级:%ld\r\n",status_array2->uxCurrentPriority);

    printf("任务编号:%ld\r\n",status_array2->xTaskNumber);

    printf("任务状态:%d\r\n",status_array2->eCurrentState);

    

/*根据任务名获取该任务的任务句柄*/

    task_handle = xTaskGetHandle( "task1" );

    printf("任务句柄:%#x\r\n",(int)task_handle);

    printf("task1的任务句柄:%#x\r\n",(int)task1_handler);

    

/*获取任务状态*/

    state = eTaskGetState( task2_handler );

printf("当前task2的任务状态为:%d\r\n",state);

 /*相对于“获取所有任务状态信息”这个好用*/

    /*以“表格”形式获取所有任务的信息 */

    vTaskList( task_buff );

    printf("%s\r\n",task_buff);

    while(1)

    {

   

/*获取任务的任务栈历史剩余最小值*/     //task_stack_min=uxTaskGetStackHighWaterMark( task2_handler );

//printf("task2历史剩余最小堆栈为%ld\r\n",task_stack_min);

        vTaskDelay(1000);

    }

}

队列

动态方式创建:

#define xQueueCreate (  uxQueueLength,   uxItemSize  )

   xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ),(queueQUEUE_TYPE_BASE))

参数:

        uxQueueLength                队列长度

        uxItemSize                          队列项目的大小

返回值:        

        NULL                                队列创建失败

        其他值                            队列创建成功,返回队列句柄    

#define queueSEND_TO_BACK     ( ( BaseType_t ) 0 )/* 写入队列尾部 */

#define queueSEND_TO_FRONT    ( ( BaseType_t ) 1 )/* 写入队列头部 */

#define queueOVERWRITE        ( ( BaseType_t ) 2 )/* 覆写队列*/

注意:覆写方式写入队列,只有在队列的队列长度为 1 时,才能够使用

往队列写入消息API函数

函数

描述

xQueueSend() 

往队列的尾部写入消息

xQueueSendToBack() 

同 xQueueSend()

xQueueSendToFront() 

往队列的头部写入消息

xQueueOverwrite() 

覆写队列消息(只用于队列长度为 1 的情况)

xQueueSendFromISR() 

在中断中往队列的尾部写入消息

xQueueSendToBackFromISR() 

同 xQueueSendFromISR()

xQueueSendToFrontFromISR() 

在中断中往队列的头部写入消息

xQueueOverwriteFromISR() 

在中断中覆写队列消息(只用于队列长度为 1 的情况)

队列写入消息

#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 )

#define queueSEND_TO_BACK     ( ( BaseType_t ) 0 )/* 写入队列尾部 */

#define queueSEND_TO_FRONT    ( ( BaseType_t ) 1 )/* 写入队列头部 */

#define queueOVERWRITE        ( ( BaseType_t ) 2 )/* 覆写队列*/

注意:覆写方式写入队列,只有在队列的队列长度为 1 时,才能够使用

往队列写入消息函数入口参数解析:

BaseType_t     xQueueGenericSend(  QueueHandle_t xQueue,
         const void * const pvItemToQueue,
         TickType_t xTicksToWait,
         const BaseType_t xCopyPosition )

参数:

        xQueue                                                待写入的队列

        pvItemToQueue                                   待写入消息

        xTicksToWait                                        阻塞超时时间

        xCopyPosition                                      写入的位置

返回值:

        pdTRUE                         队列写入成功

        errQUEUE_FULL           队列写入失败

从队列读取消息API函数:

函数

描述

xQueueReceive() 

从队列头部读取消息,并删除消息

xQueuePeek() 

从队列头部读取消息

xQueueReceiveFromISR() 

在中断中从队列头部读取消息,并删除消息

xQueuePeekFromISR() 

在中断中从队列头部读取消息

此函数用于在任务中,从队列中读取消息,并且消息读取成功后,会将消息从队列中移除。

BaseType_t    xQueueReceive( QueueHandle_t  xQueue,

  void *   const pvBuffer,  

TickType_t   xTicksToWait )

参数:      

        ueue                             待读取的队列

        pvBuffer                        信息读取缓冲区

        xTicksToWait                 阻塞超时时间

此函数用于在任务中,从队列中读取消息, 但与函数 xQueueReceive()不同,此函数在成功读取消息后,并不会移除已读取的消息! 

BaseType_t   xQueuePeek( QueueHandle_t   xQueue,  

    void * const   pvBuffer,   

TickType_t   xTicksToWait )

参数:       

        ueue                             待读取的队列

        pvBuffer                        信息读取缓冲区

        xTicksToWait                 阻塞超时时间

 返回值:

        pdTRUE                  读取成功

        pdFALSE                 读取失败

使用示例:

QueueHandle_t key_queue;                /*小数据句柄*/
QueueHandle_t big_data_queue;        /*大数据句柄*/


char buff[100] = {"11111111111111111111111***************************1111111111111111111111111\r\n"};


void FreeRTOS_Dome(void)
{
    key_queue = xQueueCreate( 2, sizeof(uint8_t));
    if(key_queue != NULL)
        printf("队列key_queue创建成功\r\n");
    else
        printf("队列key_queue创建失败\r\n");
    
    big_data_queue = xQueueCreate(2, sizeof(char *));
    if(big_data_queue != NULL)
        printf("队列big_data_queue创建成功\r\n");
    else
        printf("队列big_data_queue创建失败\r\n");
  xTaskCreate(Start_Task,"Start_Task",START_STK_SZIE,NULL,START_TASK_PRIO,&START_Handle_t);
    vTaskStartScheduler();

}


void Task2(void *p)
{
    BaseType_t err;
    uint8_t key_val=0;
    char *buf;
    buf = &buff[0];
    while(1)
    {
        if(KeyScanf(GPIOC,GPIO_PIN_13) == 1)
        { 
            err = xQueueSend(big_data_queue,&buf,0);
            if(err == pdTRUE)
                printf("队列big_data_queue发送成功\r\n");
            else
                printf("队列big_data_queue发送失败\r\n");
        } 
//        if(KeyScanf(GPIOA,GPIO_PIN_0) == 1)
//        { 
//            err = xQueueReceive(key_queue,&key_val,0);
//            if(err == pdTRUE)
//                printf("队列key_queue读取成功,data:%d\r\n",key_val);
//            else
//                printf("队列key_queue读取失败\r\n");
//        }
            vTaskDelay(10);
    }
}


void Task3(void *p)
{
    uint8_t key_val;
    BaseType_t err;
    char *buf;
    while(1)
    {
        key_val = 1;
        if(KeyScanf(GPIOA,GPIO_PIN_0) == 1)
        { 
//            err = xQueueSend(key_queue,&key_val,0);
//            if(err == pdTRUE)
//                printf("队列key_queue发送成功\r\n");
//            else
//                printf("队列key_queue发送失败\r\n");
//        } 
//        if(KeyScanf(GPIOC,GPIO_PIN_13) == 1)
//        { 
            err = xQueueReceive(big_data_queue,&buf,0);
            if(err == pdTRUE)
                printf("队列big_data_queue读取成功,data:%s\r\n",buf);
            else
                printf("队列big_data_queue读取失败\r\n");
        }
        vTaskDelay(10);
    }
}

二值信号量

动态创建二值信号量函数:

·SemaphoreHandle_t   xSemaphoreCreateBinary( void )

参数:

返回值:创建失败 NULL

 创建成功 二值信号量的句柄

静态创建二值信号量函数:

·xSemaphoreCreateBinaryStatic()

释放二值信号量函数

任务中:

        ·BaseType_t   xSemaphoreGive( xSemaphore )

                参数:要释放的信号量句柄

                返回值: pdPASS                         释放信号量成功

                                errQUEUE_FULL          释放信号量失败

中断中:

        ·BaseType_t   xSemaphoreGiveFromISR(

                        SemaphoreHandle_t xSemaphore,

                        BaseType_t* pxHigherPriorityTask Woken)

        参数: xSemaphore: 要释放的信号量句柄。

                pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任  务切换,这个变量的值由这三个函  数来设置的,用户不用进行设置,  用户只需要提供一个变量来保存    这个值就行了。当此值为pdTRUE  的时候在退出中断服务函数之前  一定要进行一次任务切换。

        返回值:    pdPASS                         释放信号量成功。

                        errQUEUE_FULL           释放信号量失败。

获取二值信号量函数:

任务中:

        ·BaseType_t   xSemaphoreTake( xSemaphore, xBlockTime )

                参数:     xSemaphore                 要获取的信号量句柄

                                xBlockTime                   阻塞时间

                返回值: pdTRUE                   获取信号量成功

                                pdFALSE                 超时,获取信号量失败

中断中:

        ·BaseType_t xSemaphoreTakeFromISR(

                        SemaphoreHandle_t xSemaphore,

                        BaseType_t * pxHigherPriority Task Woken)

        参数:

                xSemaphore:要获取的信号量句柄。

                pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这三个函数来设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为pdTRUE的时候在退出中断服务函数之前一定要进行一次任务切换。

        返回值:           pdPASS:                    获取信号量成功。

                                pdFALSE:                 获取信号量失败。

使用示例: 

QueueHandle_t semphorc_Handle;

semphorc_Handle = xSemaphoreCreateBinary();

if(semphorc_Handle != NULL)

printf("semphorc_Handle succeeded\r\n");

void Task1(void *p)

{

BaseType_t xReturn;

while(1)

{

if(KeyScanf(GPIOC,GPIO_PIN_13) == 1)

{

if(semphorc_Handle != NULL)

{

xReturn = xSemaphoreGive(semphorc_Handle);

if(xReturn == pdPASS)

printf("xSemaphoreGive succeeded\r\n");

else

printf("xSemaphoreGive failed\r\n");

}

}

}

}

void Task2(void *p)

{

uint8_t i=0;

BaseType_t xReturn;

while(1)

{

xReturn = xSemaphoreTake(semphorc_Handle,1000);

if(xReturn  == pdTRUE)

printf("xSemaphoreTake succeeded \r\n");

else

printf("xSemaphoreTake failed num%d\r\n",++i);

}

}

计数型二值信号量

创建计数型二值信号量函数:

动态方式:

        ·SemaphoreHandle_t xSemaphoreCreateCounting(

                        UBaseType_t uxMaxCount,

                        UBaseType_t uxInitialCount )

        参数:

                 uxMaxCount: 计数信号量最大计数值,当信号量值等于此值的 时候释放信号量就会失败。

                uxInitialCount:计数信号量初始值。

        返回值:           

                NULL:         计数型信号量创建失败。

                 其他值:         计数型信号量创建成功,返回计数型信号量句柄。

静态方式:

        ·SemaphoreHandle_t xSemaphoreCreateCountingStatic(

                        UBaseType_t uxMaxCount,

                        UBaseType_t uxInitialCount,

                        StaticSemaphore_t *pxSemaphoreBuffer )

        参数:

                uxMaxCount: 计数信号量最大计数值,当信号量值等于此 值的时候释放信号量就会失败。

                uxInitialCount: 计数信号量初始值。

                pxSemaphoreBuffer: 指向一个StaticSemaphore_t类型的变量, 用来保存信号量结构体。

返回值:

         NULL:         计数型信号量创建失败。

        其他值:         计数型号量创建成功,返回计数型信号量句柄。

uxSemaphoreGetCount()  返回信号量的计数值

计数型信号量的释放和获取与二值信号量相同 !

使用示例:

QueueHandle_t cnt_semphorc_Handle;

#define cnt_semphorc_MAX  100

#define cnt_semphorc_Init  100  /* or  0 */

cnt_semphorc_Handle = xSemaphoreCreateCounting(cnt_semphorc_MAX,cnt_semphorc_Init);

if(cnt_semphorc_Handle != NULL)

printf("计数型信号量创建成功\r\n");

void Task1(void *p)

{

BaseType_t xReturn;

while(1)

{

if(KeyScanf(GPIOC,GPIO_PIN_13) == 1)

{

if(cnt_semphorc_Handle != NULL)

xReturn = xSemaphoreGive(cnt_semphorc_Handle); /*释放信号量*/

}

vTaskDelay(10);

}

}

void Task2(void *p)

{

BaseType_t xReturn;

while(1)

{

xReturn = xSemaphoreTake(cnt_semphorc_Handle,portMAX_DELAY);

if(xReturn == pdTRUE)

printf("信号量计数值为:%d\r\n",(int)uxSemaphoreGetCount(cnt_semphorc_Handle));

vTaskDelay(1000);

}

}

互斥信号量

创建互斥信号量函数

动态创建互斥信号量函数

        ·SemaphoreHandle_t xSemaphoreCreateMutex( void )

        参数:

                无。

        返回值:

                NULL: 互斥信号量创建失败。

                其他值: 创建成功的互斥信号量的句柄。

静态创建互斥信号量函数

        ·SemaphoreHandle_t xSemaphoreCreateMutexStatic

                                        ( StaticSemaphore_t *pxMutexBuffer )

        参数:

                pxMutexBuffer: 此参数指向一个 StaticSemaphore_t类型 的变量,用来保存信号量结构体。

        返回值:

                NULL: 互斥信号量创建失败。

                其他值: 创建成功的互斥信号量的句柄。

注意:创建互斥信号量时,会主动释放一次信号量

·互斥信号量的释放和获取函数与二值信号量相同 !只不过互斥信号量不 支持中断中调用

使用示例:

QueueHandle_t mutex_semphorc_Handle;

mutex_semphorc_Handle = xSemaphoreCreateMutex(); /*创建互斥信号量,并且主动释放一次信号量*/

if(mutex_semphorc_Handle != NULL)

printf("semphorc_Handle succeeded\r\n");

void Task1(void *p)

{

while(1)

{

printf("低优先级任务获取信号量\r\n");

xSemaphoreTake(mutex_semphorc_Handle,portMAX_DELAY);

printf("低优先级任务正在运行\r\n");

delay_ms(3000);

printf("低优先级任务释放信号量\r\n");

xSemaphoreGive(mutex_semphorc_Handle);

vTaskDelay(1000);

}

}

void Task2(void *p)

{

while(1)

{

printf("中优先级任务正在运行\r\n");

vTaskDelay(1000);

}

}

void Task3(void *p)

{

while(1)

{

printf("高优先级任务获取信号量\r\n");

xSemaphoreTake(mutex_semphorc_Handle,portMAX_DELAY);

printf("高优先级任务正在运行\r\n");

delay_ms(1000);

printf("高优先级任务释放信号量\r\n");

xSemaphoreGive(mutex_semphorc_Handle);

vTaskDelay(1000);

}

}

任务通知

发送通知相关API函数:

函数

描述

xTaskNotify()

发送通知,带有通知值

xTaskNotifyAndQuery() 

发送通知,带有通知值并且保留接收任务的原通知值

xTaskNotifyGive()

发送通知,不带通知值

xTaskNotifyFromISR()

在中断中发送任务通知

xTaskNotifyAndQueryFromISR() 

vTaskNotifyGiveFromISR()

BaseType_t  xTaskGenericNotify(  TaskHandle_t xTaskToNotify,

                           UBaseType_t uxIndexToNotify,

                           uint32_t ulValue,

                           eNotifyAction eAction,

                           uint32_t * pulPreviousNotificationValue  )

形参

描述

xTaskToNotify 

接收任务通知的任务句柄

uxIndexToNotify 

任务的指定通知(任务通知相关数组成员)

ulValue 

任务通知值

eAction 

通知方式(通知值更新方式)

pulPreviousNotificationValue 

用于保存更新前的任务通知值(为NULL则不保存)

任务通知方式共有以下几种:

typedef  enum

{    

        eNoAction = 0, /* 无操作 */

        eSetBits /* 更新指定bit */

        eIncrement /* 通知值加一 */

          eSetValueWithOverwrite /* 覆写的方式更新通知值 */

        eSetValueWithoutOverwrite /* 不覆写通知值 */

} eNotifyAction;

接收通知相关API函数:

函数

描述

ulTaskNotifyTake()

获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减一。

当任务通知用作二值信号量或者计数信号量的时候,使用此函数来获取信号量。

xTaskNotifyWait()

获取任务通知,比 ulTaskNotifyTak()更为复杂,可获取通知值和清除通知值的指定位

·当任务通知用作于信号量时,使用函数获取信号量:ulTaskNotifyTake()

·当任务通知用作于事件标志组或队列时,使用此函数来获取: xTaskNotifyWait()

·#define ulTaskNotifyTake( xClearCountOnExit  ,   xTicksToWait ) \


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

此函数用于接收任务通知值,可以设置在退出此函数的时候将任务通知值清零或者减一

形参

描述

uxIndexToWaitOn 

任务的指定通知(任务通知相关数组成员)

xClearCountOnExit 

指定在成功接收通知后,将通知值清零或减 1,

pdTRUE:把通知值清零;pdFALSE:把通知值减一

xTicksToWait 

阻塞等待任务通知值的最大时

BaseType_t    xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t * pulNotificationValue,
TickType_t xTicksToWait     );

此函数用于获取通知值和清除通知值的指定位值,适用于模拟队列和事件标志组,使用该函数来获取任务通知 。

形参

描述

uxIndexToWaitOn 

任务的指定通知(任务通知相关数组成员)

ulBitesToClearOnEntry 

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

ulBitesToClearOnExit 

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

pulNotificationValue 

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

xTicksToWait 

阻塞等待任务通知值的最大时间

返回值

描述

pdTRUE 

等待任务通知成功

pdFALSE 

等待任务通知失败

 ·使用示例(任务通知模拟二值信号量实验):

/*任务一,发送任务通知值*/

void Task1(void *p)

{

uint8_t key_val = 0;

while(1)

{

key_val = KeyScanf();

if(key_val == KEY0_PRES)

{

// printf("任务通知模拟二值信号量释放\r\n");

// xTaskNotifyGive(Task2_Handle_t);

printf("任务通知模拟计数型信号量,计数值加1\r\n");

xTaskNotifyGive(Task2_Handle_t);

}

vTaskDelay(10);

}

}

/*任务二,接收任务通知值*/

void Task2(void *p)

{

uint32_t ulReturn;

while(1)

{

// ulReturn = ulTaskNotifyTake(pdTRUE,portMAX_DELAY);

// if(ulReturn == pdTRUE)

// printf("任务通知模拟二值信号量接收成功\r\n");

ulReturn = ulTaskNotifyTake(pdFALSE,portMAX_DELAY);

if(ulReturn != 0)

printf("任务通知模拟计数型号量,计数值减一 :%d\r\n",ulReturn);

vTaskDelay(1000);

}

}

·使用示例(任务通知模拟消息邮箱):

/*任务一,发送任务通知值*/

void Task1(void *p)

{

uint8_t key_val = 0;

while(1)

{

key_val = KeyScanf();

if((key_val !=0) && Task2_Handle_t != NULL)

{

printf("发送任务通知模拟消息邮箱发送,发送的键值:%d\r\n",key_val);

xTaskNotify(Task2_Handle_t,key_val,eSetValueWithoutOverwrite);

}

vTaskDelay(10);

}

}

/*任务二,接收任务通知值*/

void Task2(void *p)

{

uint32_t noyify_val = 0;

while(1)

{

xTaskNotifyWait(0,0xffffffff,&noyify_val,portMAX_DELAY);

switch(noyify_val)

{

case KEY0_PRES:

printf("KEY0按下,接收到的通知值为:%d\r\n",noyify_val);

break;

case KEY1_PRES:

printf("KEY1按下,接收到的通知值为:%d\r\n",noyify_val);

break;

default: break;

}

}

}

·使用示例(任务通知模拟事件标志组):

#define EventBIT_0   (1 << 0)

#define EventBIT_1   (1 << 1)

void Task1(void *p)

{

uint8_t key_val=0;

while(1)

{

key_val = KeyScanf();

if(key_val == KEY0_PRES)

{

printf("将bit0位置1 \r\n");

 xTaskNotify(Task2_Handle_t,EventBIT_0,eSetBits);

}

else if(key_val == KEY1_PRES)

{

printf("将bit1位置1 \r\n");

 xTaskNotify(Task2_Handle_t,EventBIT_1,eSetBits);

}

vTaskDelay(10);

}

}

void Task2(void *p)

{

uint32_t notiyf_val = 0,event_bit = 0;

while(1)

{

xTaskNotifyWait(0,0xffffffff,¬iyf_val,portMAX_DELAY);

if(notiyf_val & EventBIT_0)

{

event_bit |= EventBIT_0;

}

if(notiyf_val & EventBIT_1)

{

event_bit |= EventBIT_1;

}

if(event_bit == (EventBIT_0 | EventBIT_1))

{

event_bit = 0;

printf("任务通知模拟事件标志组接收成功\r\n");

}

vTaskDelay(10);

}

}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值