[FreeRTOS学习] 任务控制

创建任务

  1. 任务函数
void ATaskFunction( void *pvParameters );

FreeRTOS 任务不允许以任何方式从实现函数中返回——它们绝不能有一条”return”语句,也不能执行到函数末尾。如果一个任务不再需要,可以显式地将其删除

void ATaskFunction( void *pvParameters )
{
/* 可以像普通函数一样定义变量。用这个函数创建的每个任务实例都有一个属于自己的iVarialbleExample变
量。但如果iVariableExample被定义为static,这一点则不成立 – 这种情况下只存在一个变量,所有的任务实
例将会共享这个变量。 */
int iVariableExample = 0;
/* 任务通常实现在一个死循环中。 */
for( ;; )
{
/* 完成任务功能的代码将放在这里。 */
}
/* 如果任务的具体实现会跳出上面的死循环,则此任务必须在函数运行完之前删除。传入NULL参数表示删除
的是当前任务 */
vTaskDelete( NULL );
}

一个任务函数可以创建若干个函数,每一个函数独立运行,拥有属于自己的堆栈空间。

  1. 创建任务函数,删除任务函数
voidvTaskDelete( TaskHandle_t xTask );
 xTaskCreate();
portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,
                              const signed portCHAR * const pcName,
                              unsigned portSHORT usStackDepth,
                              void *pvParameters,
                              unsigned portBASE_TYPE uxPriority,
                              xTaskHandle *pxCreatedTask 
                             );

具体参数含义 见API文档
Demo

void vTask1( void *pvParameters )
{
      const char *pcTaskName = "Task 1 is running\r\n";
      volatile unsigned long ul;
      /* 和大多数任务一样,该任务处于一个死循环中。 */
      for( ;; )
      {
            /* Print out the name of this task. */
            vPrintString( pcTaskName );
            /* 延迟,以产生一个周期 */
            for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
            {
                  /* 这个空循环是最原始的延迟实现方式。在循环中不做任何事情。后面的示例程序将采用
                delay/sleep函数代替这个原始空循环。 */
            }
      }
  }
程序清单4 例1中的第一个任务实现代码
void vTask2( void *pvParameters )
{
      const char *pcTaskName = "Task 2 is running\r\n";
      volatile unsigned long ul;
      /* 和大多数任务一样,该任务处于一个死循环中。 */
      for( ;; )
      {
            /* Print out the name of this task. */
            vPrintString( pcTaskName );
            /* 延迟,以产生一个周期 */
            for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
            {
                  /* 这个空循环是最原始的延迟实现方式。在循环中不做任何事情。后面的示例程序将采用
                  delay/sleep函数代替这个原始空循环。 */
            }
      }
}
int main( void )
{
      /* 创建第一个任务。 需要说明的是一个实用的应用程序中应当检测函      数xTaskCreate()的返回值,以确保任务创建成功。 */
      xTaskCreate( vTask1, /* 指向任务函数的指针 */
                    "Task 1", /* 任务的文本名字,只会在调试中用到 */
                    1000, /* 栈深度 – 大多数小型微控制器会使用的值会比此值小得多 */
                    NULL, /* 没有任务参数 */
                    1, /* 此任务运行在优先级1上. */
                    NULL ); /* 不会用到任务句柄 */
      /* Create the other task in exactly the same way and at the same priority. */
      xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
      /* 启动调度器,任务开始执行 */
      vTaskStartScheduler();
      /* 如果一切正常, main()函数不应该会执行到这里。但如果执行到这里,很可能是内存堆空间不足导致空闲
任务无法创建。第五章有讲述更多关于内存管理方面的信息 */
      for( ;; );
}
  1. 优先级
  • vTaskPrioritySet() 修改优先级
  • 任意数量的任务可以共享同一个优先级——以保证最大设计弹性
  • 有效的优先级号范围从 0 到(configMAX_PRIORITES – 1)
  • 被选中的优先级上具有不止一个任务,调度器会让这些任务轮流执行,每个任务都执行一个”时间片”
  • 时间片的长度通过心跳中断的频率进行设定,configTICK_RATE_HZ 进行配置(如,设为100(HZ),则时间片长度为 10ms)
  • 常量 portTICK_RATE_MS 用于将以心跳为单位的时间值转化
    为以毫秒为单位的时间值
  • 相关API
    • 相对延时
   void vTaskDelay( portTickTypexTicksToDelay )
常量portTICK_RATE_MS 用来辅助计算真实时间,此值是系统节拍时钟中断的周期,单位是毫秒。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelay 必须设置成1,此函数才能有效。

比如vTaskDelay(100),那么从调用vTaskDelay()后,任务进入阻塞状态,经过100个系统时钟节拍周期,任务解除阻塞

调用vTaskDelay()到任务解除阻塞的时间不总是固定的并且该任务下一次调用vTaskDelay()函数的时间也不总是固定的(两次执行同一任务的时间间隔本身就不固定,中断或高优先级任务抢占也可能会改变每一次执行时间)。

  • 绝对延时

void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,
const TickType_txTimeIncrement );

    * INCLUDE_vTaskDelayUntil 必须设置成1,此函数才有效
    * 这个函数不同于vTaskDelay()函数的一个重要之处在于:vTaskDelay()指定的延时时间是从调用vTaskDelay()之后(执行完该函数)开始算起的,但是vTaskDelayUntil()指定的延时时间是一个绝对时间。

  + 获取任务优先级
       ```
      UBaseType_t uxTaskPriorityGet(TaskHandle_t xTask );
      ```
      * INCLUDE_vTaskPriorityGet必须设置成1
      * xTask:任务句柄。NULL表示获取当前任务的优先级

  + 设置任务优先级
      ```
 void vTaskPrioritySet( TaskHandle_txTask,
                           UBaseType_tuxNewPriority );
* INCLUDE_vTaskPrioritySet 必须设置成1
  • 任务挂起

void vTaskSuspend( TaskHandle_txTaskToSuspend );

    * 被挂起的任务绝不会得到处理器时间
    * INCLUDE_vTaskSuspend必须设置成1
  + 恢复挂起任务
    ```
 void vTaskResume( TaskHandle_txTaskToResume );
* INCLUDE_vTaskSuspend必须置1
* 通过调用一次或多次vTaskSuspend()挂起的任务,可以调用一次vTaskResume ()函数来再次恢复运行
  • 恢复挂起的任务(在中断服务函数中使用)

BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume );

    * 用于恢复一个挂起的任务,用在ISR中
    *  INCLUDE_xTaskResumeFromISR 必须设置成1
    * xTaskResumeFromISR()不可用于任务和中断间的同步,如果中断恰巧在任务被挂起之前到达,这就会导致一次中断丢失(任务还没有挂起,调用xTaskResumeFromISR()函数是没有意义的,只能等下一次中断)。这种情况下,可以使用信号量作为同步机制。
    ```
xTaskHandlexHandle;               //注意这是一个全局变量  
 void vAFunction( void )  
 {  
     // 创建任务并保存任务句柄  
     xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );  
   
     // ... 剩余代码.  
 }  
 void vTaskCode( void *pvParameters )  
 {  
     for( ;; )  
     {  
         // ... 在这里执行一些其它功能  
         // 挂起自己  
         vTaskSuspend( NULL );  
         //直到ISR恢复它之前,任务会一直挂起  
     }  
 }  
 void vAnExampleISR( void )  
 {  
     portBASE_TYPExYieldRequired;  
     // 恢复被挂起的任务  
     xYieldRequired = xTaskResumeFromISR(xHandle );  
     if( xYieldRequired == pdTRUE )  
     {  
         // 我们应该进行一次上下文切换  
         // 注:  如何做取决于你具体使用,可查看说明文档和例程  
         portYIELD_FROM_ISR();  
     }  
 }  
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容