一张纸了解freertos的使用(3)

任务通知

话不多说,直接上代码

任务通知的函数接口

发送通知

在 任务中发送任务通知的函数均是调用 xTaskGenericNotify()函数进行发送通知,xTaskGenericNotify()函数是一个通用的任务通知发送函数,在任务中发送通知的 API 函 数 , 如 xTaskNotifyGive() 、 xTaskNotify() ,xTaskNotifyAndQuery() , 都 是 以 xTaskGenericNotify()为原型的,只不过指定的发送方式不同而已。

#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL )
#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) )
#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL )

 所以,我们其实只需要搞懂

BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
只需要搞懂 xTaskGenericNotify 

 

 其中,重要的是通知方式

2.接受通知

BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )

ulTaskNotifyTake  

返回值为0,表示接受失败。 

 返回值不为0,表示接受成功。

xTaskNotifyWait 

 返回值为pdTRUE,表示等待任务通知成功

 返回值为pdFALSE,表示等待任务通知失败

 示例:

模拟二值信号

void task1(void * pvParameters)
{
/*
中间省略
*/
    while(1)
{
    key=key_scan(0);
    if(key == KEY0_PRES)
    {
        printf("任务通知模拟二值信号释放!\r\n");
        xTaskNotifyGive(task2_hangler);
    }
     vTaskDelay(10);
 }

}



void task2(void * pvParameters)
{
    uint32_t rev=0;
 while(1)
 {
    rev=ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
    if(rev != 0)
    {
        printf("接受任务通知成功,模拟获取二值型号量!\r\n");
    }

 }

}

 模拟计数型信号

void task1(void * pvParameters)
{
/*
中间省略
*/
    while(1)
{
    key=key_scan(0);
    if(key == KEY0_PRES)
    {
        printf("任务通知模拟计数型信号释放!\r\n");
        xTaskNotifyGive(task2_hangler);
    }
     vTaskDelay(10);
 }

}



void task2(void * pvParameters)
{
    uint32_t rev=0;
 while(1)
 {
    rev=ulTaskNotifyTake(pdFALSE,portMAX_DELAY);
    if(rev != 0)
    {
        printf("rev:%d\r\n",rev);
        printf("接受任务通知成功,模拟获取计数型信号量!\r\n");
    }

 }

}

 模拟消息邮箱信号


void task1(void * pvParameters)
{
/*
中间省略
*/
    while(1)
{
    key=key_scan(0);
    if((key !=0)&&(task2_handler != NULL))
    {
        printf("任务通知模拟信息邮箱发送,发送的键值为:%d\r\n");
        xTaskNotify(task2_hangler,key,eSetValueWithOverwrite);
    }

     vTaskDelay(10);
 }

}



void task2(void * pvParameters)
{
   uint32_t noyify_val=0;
 while(1)
 {
    xTaskNotifyWait(0,0xFFFFFFFF,&noyify_val,portMAX_DELAY);
   switch(noyify_val)
    {
        case xx:
                {
                    //省略
                    break;
                }
         case xx:
                {
                    //省略
                    break;
                }


    }  
 }

}

 模拟事件组

#define EVENTBIT_0 (1<<0)
#define EVENTBIT_1 (1<<1)
void task1(void * pvParameters)
{
/*
中间省略
*/
    while(1)
{
    key=key_scan(0);
    if(key == xx )
    {
        printf("将bit 0位置1\r\n");
        xTaskNotify(task2_hangler,EVENTBIT_0,eSetBits);
    }
    esle if(key == xx )
    {
        printf("将bit 1位置1\r\n");
        xTaskNotify(task2_hangler,EVENTBIT_1,eSetBits);
    }
     vTaskDelay(10);
 }

}


//当biy0,和bit 1,都被置1才触发
//接受函数,退出后一定要清零。
void task2(void * pvParameters)
{
   uint32_t noyify_val=0,event_bit = 0;
 while(1)
 {
    xTaskNotifyWait(0,0xFFFFFFFF,&noyify_val,portMAX_DELAY);
    if(noyify_val & EVENTBIT_0)
    {
        event_bit |=EVENTBIT_0;
    }
    if(noyify_val & EVENTBIT_1)
    {
        event_bit |=EVENTBIT_1;
    }
    if(event_bit  == (EVENTBIT_0 | EVENTBIT_1))
    {
        printf("任务通知模拟事件组接受成功!!\r\n");
        event_bit=0;
    }

  
 }

}

 软定时

创建

动态分配内存

/* 使用动态分配内存的方法创建定时器 
* pcTimerName:定时器名字, 用处不大, 尽在调试时用到 
* xTimerPeriodInTicks: 周期, 以 Tick 为单位 
* uxAutoReload: 类型, pdTRUE 表示自动加载, pdFALSE表示一次性 
* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器 
 * pxCallbackFunction: 回调函数 
 * 返回值: 成功则返回TimerHandle_t, 否则返回NULL 
 */ 
TimerHandle_t xTimerCreate( const char * const pcTimerName,  
       const TickType_t xTimerPeriodInTicks, 
       const UBaseType_t uxAutoReload, 
       void * const pvTimerID, 
       TimerCallbackFunction_t pxCallbackFunction ); 

静态分配内存

/* 使用静态分配内存的方法创建定时器 
 * pcTimerName:定时器名字, 用处不大, 尽在调试时用到 
 * xTimerPeriodInTicks: 周期, 以Tick为单位 
 * uxAutoReload: 类型, pdTRUE表示自动加载, pdFALSE表示一次性 
 * pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器 
 * pxCallbackFunction: 回调函数 
 * pxTimerBuffer: 传入一个StaticTimer_t结构体, 将在上面构造定时器 
 * 返回值: 成功则返回TimerHandle_t, 否则返回NULL 
 */ 
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName, 
                                 TickType_t xTimerPeriodInTicks, 
                                 UBaseType_t uxAutoReload, 
                                 void * pvTimerID, 
                                 TimerCallbackFunction_t pxCallbackFunction, 
                                 StaticTimer_t *pxTimerBuffer ); 

回调函数

回调函数的类型是:

void ATimerCallback( TimerHandle_t xTimer ); 
 
typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer );

删除

/* 删除定时器 
 * xTimer: 要删除哪个定时器 
 * xTicksToWait: 超时时间 
 * 返回值: pdFAIL表示"删除命令"在xTicksToWait个Tick内无法写入队列 
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );

启动

/* 启动定时器 
 * xTimer: 哪个定时器 
 * xTicksToWait: 超时时间 
 * 返回值: pdFAIL表示"启动命令"在xTicksToWait个Tick内无法写入队列
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); 
 
/* 启动定时器(ISR版本) 
 * xTimer: 哪个定时器 
 * pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒, 
 *                            如果守护任务的优先级比当前任务的高, 
 *                            则"*pxHigherPriorityTaskWoken = pdTRUE", 
 *                            表示需要进行任务调度 
 * 返回值: pdFAIL表示"启动命令"无法写入队列 
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerStartFromISR(   TimerHandle_t xTimer, 
                                 BaseType_t *pxHigherPriorityTaskWoken ); 

停止 

/* 停止定时器 
 * xTimer: 哪个定时器 
 * xTicksToWait: 超时时间 
 * 返回值: pdFAIL表示"停止命令"在xTicksToWait个Tick内无法写入队列 
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); 
 
/* 停止定时器(ISR版本) 
 * xTimer: 哪个定时器
 * pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒, 
 *                            如果守护任务的优先级比当前任务的高, 
 *                            则"*pxHigherPriorityTaskWoken = pdTRUE", 
 *                            表示需要进行任务调度 
 * 返回值: pdFAIL表示"停止命令"无法写入队列 
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerStopFromISR(    TimerHandle_t xTimer, 
                                 BaseType_t *pxHigherPriorityTaskWoken ); 

注意,这些函数的xTicksToWait表示的是,把命令写入命令队列的超时时间。命令队 列可能已经满了,无法马上把命令写入队列里,可以等待一会。

xTicksToWait不是定时器本身的超时时间,不是定时器本身的"周期"。

创建定时器时,设置了它的周期(period)。xTimerStart()函数是用来启动定时器。

假设 调用xTimerStart()的时刻是tX,定时器的周期是n,那么在tX+n时刻定时器的回调函数被 调用。

如果定时器已经被启动,但是它的函数尚未被执行,再次执行xTimerStart()函数相当于 执行xTimerReset(),重新设定它的启动时间。

/* 修改定时器的周期 
 * xTimer: 哪个定时器 
 * xNewPeriod: 新周期 
 * xTicksToWait: 超时时间, 命令写入队列的超时时间  
 * 返回值: pdFAIL表示"修改周期命令"在xTicksToWait个Tick内无法写入队列 
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerChangePeriod(   TimerHandle_t xTimer, 
                                 TickType_t xNewPeriod, 
                                 TickType_t xTicksToWait ); 
 
/* 修改定时器的周期 
 * xTimer: 哪个定时器 
 * xNewPeriod: 新周期 
 * pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒, 
 *                            如果守护任务的优先级比当前任务的高, 
 *                            则"*pxHigherPriorityTaskWoken = pdTRUE", 
 *                            表示需要进行任务调度 
 * 返回值: pdFAIL表示"修改周期命令"在xTicksToWait个Tick内无法写入队列 
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, 
                                      TickType_t xNewPeriod, 
                                      BaseType_t *pxHigherPriorityTaskWoken );

修改周期

/* 复位定时器 
 * xTimer: 哪个定时器 
 * xTicksToWait: 超时时间 
 * 返回值: pdFAIL表示"复位命令"在xTicksToWait个Tick内无法写入队列
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); 
 
/* 复位定时器(ISR版本) 
 * xTimer: 哪个定时器 
 * pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒, 
 *                            如果守护任务的优先级比当前任务的高, 
 *                            则"*pxHigherPriorityTaskWoken = pdTRUE", 
 *                            表示需要进行任务调度 
 * 返回值: pdFAIL表示"停止命令"无法写入队列 
 *        pdPASS表示成功 
 */ 
BaseType_t xTimerResetFromISR(   TimerHandle_t xTimer, 
                                 BaseType_t *pxHigherPriorityTaskWoken ); 

 配置文件FreeRTOSConfig.h中

##define configUSE_TIMERS    1   /* 使能定时器 */ 
##define configTIMER_TASK_PRIORITY    31  /* 守护任务的优先级, 尽可能高一些 */ 
##define configTIMER_QUEUE_LENGTH     5   /* 命令队列长度 */ 
##define configTIMER_TASK_STACK_DEPTH 32  /* 守护任务的栈大小 */

内存管理

申请内存

void *pvPortMalloc( size_t xWantedSize )

释放内存

void vPortFree( void *pv )

获得当前空闲内存的大小

size_t xPortGetFreeHeapSize( void )

临界段代码保护

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值