硬汉嵌入式论坛

 找回密码
 立即注册
查看: 5423|回复: 19
收起左侧

[FreeRTOS教程] 第10章 FreeRTOS任务管理

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2016-8-18 14:16:26 | 显示全部楼层 |阅读模式
第10章      FreeRTOS任务管理


    对于初学者,特别是对于没有RTOS基础的同学来说,了解FreeRTOS的任务管理非常重要,了解任务管理的目的就是让初学者从裸机的,单任务编程过渡到带OS的,多任务编程上来。搞清楚了这一点,那么FreeRTOS学习就算入门了。

    本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407以及F429。
10.1   单任务系统
10.2   多任务系统
10.3   FreeRTOS的任务设置
10.4   FreeRTOS的系统任务栈设置
10.5   FreeRTOS的任务状态
10.6   FreeRTOS启动
10.7   FreeRTOS的任务创建
10.8   FreeRTOS的任务删除
10.9   FreeRTOS的任务挂起
10.10   FreeRTOS的任务恢复
10.11   FreeRTOS的任务恢复(中断方式)
10.12   FreeRTOS的空闲任务
10.13   实验例程说明
10.14   实验例程说明(中断方式)
10.15    总结
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:20:43 | 显示全部楼层
10.1  单任务系统
    学习多任务系统之前,我们先来回顾下单任务系统的编程框架,即裸机时的编程框架。裸机编程主要是采用超级循环(super-loops)系统,又称前后台系统。应用程序是一个无限的循环,循环中调用相应的函数完成相应的操作,这部分可以看做后台行为;中断服务程序处理异步事件,这部分可以看做是前台行为。后台也可以叫做任务级,前台也叫作中断级。
10.1.jpg

图10.1单任务系统

    对于前后台系统的编程思路主要有以下两种方式:

10.1.1 查询方式


    对于一些简单的应用,处理器可以查询数据或者消息是否就绪,就绪后进行处理,然后再等待,如此循环下去。对于简单的任务,这种方式简单易处理。但大多数情况下,需要处理多个接口数据或者消息,那就需要多次处理,如下面的流程图所示:
10.2.JPG

    用查询方式处理简单的应用,效果比较好,但是随着工程的复杂,采用查询方式实现的工程就变得很难维护,同时,由于无法定义查询任务的优先级,这种查询方式会使得重要的接口消息得不到及时响应。比如程序一直在等待一个非紧急消息就绪,如果这个消息后面还有一个紧急的消息需要处理,那么就会使得紧急消息长时间得不到执行。

10.1.2 中断方式


    对于查询方式无法有效执行紧急任务的情况,采用中断方式就有效地解决了这个问题,下面是中断方式简单的流程图:
10.3.JPG

采用中断和查询结合的方式可以解决大部分裸机应用,但随着工程的复杂,裸机方式的缺点就暴露出来了:
u  必须在中断(ISR)内处理时间关键运算:
    l  ISR 函数变得非常复杂,并且需要很长执行时间。
    l  ISR 嵌套可能产生不可预测的执行时间和堆栈需求。
u  超级循环和ISR之间的数据交换是通过全局共享变量进行的:
    l  应用程序的程序员必须确保数据一致性。
u  超级循环可以与系统计时器轻松同步,但:
    l  如果系统需要多种不同的周期时间,则会很难实现。
    l  超过超级循环周期的耗时函数需要做拆分。
    l  增加软件开销,应用程序难以理解。
u  超级循环使得应用程序变得非常复杂,因此难以扩展:
    l  一个简单的更改就可能产生不可预测的副作用,对这种副作用进行分析非常耗时。
    l  超级循环概念的这些缺点可以通过使用实时操作系统(RTOS) 来解决。


努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:25:35 | 显示全部楼层
10.2 多任务系统


    针对这些情况,使用多任务系统就可以解决这些问题了。下面是一个多任务系统的流程图:
10.4.JPG

    多任务系统或者说RTOS的实现,重点就在这个调度器上,而调度器的作用就是使用相关的调度算法来决定当前需要执行的任务。如上图所示的那样,创建了任务并完成OS初始化后,就可以通过调度器来决定任务A,任务B和任务C的运行,从而实现多任务系统。另外需要初学者注意的是,这里所说的多任务系统同一时刻只能有一个任务可以运行,只是通过调度器的决策,看起来像所有任务同时运行一样。为了更好的说明这个问题,再举一个详细的运行例子,运行条件如下:
u  使用抢占式调度器
u  1个空闲任务,优先级最低。
u  2个应用任务,一个高优先级和一个低优先级,优先级都比空闲任务优先级高。
u  中断服务程序,含USB中断,串口中断和系统滴答定时器中断
    下图10.2所示是任务的运行过程,其中横坐标是任务优先级由低到高排列,纵坐标是运行时间,时间刻度有小到大。
10.5.jpg
图10.2多任务系统运行过程

(1)   启动RTOS,首先执行高优先级任务(vTaskStartScheduler)
(2)   高优先级任务等待事件标志(xEventGroupWaitBits)被阻塞,低优先级任务得到执行。
(3)   低优先级任务执行的过程中产生USB中断,进入USB中断服务程序。
(4)   退出USB中断复位程序,回到低优先级任务继续执行。
(5)   低优先级任务执行过程中产生串口接收中断,进入串口接收中断服务程序。
(6)   退出串口接收中断复位程序,并发送事件标志设置消息(xEventGroupSetBitsFromISR),被阻塞的高优先级任务就会重新进入就绪状态,这个时候高优先级任务和低优先级任务都在就绪态,抢占式调度器就会让高优先级的任务先执行,所以此时就会进入高优先级任务。
(7)   高优先级任务由于等待事件标志(xEventGroupWaitBits)会再次被阻塞,低优先级任务开始继续执行。
(8)   低优先级任务调用函数vTaskDelay,低优先级任务被挂起,从而空闲任务得到执行。
(9)   空闲任务执行期间发生滴答定时器中断,进入滴答定时器中断服务程序。
(10)  退出滴答定时器中断,由于低优先级任务延时时间到,低优先级任务继续执行。
(11)  低优先级任务再次调用延迟函数vTaskDelay,低优先级任务被挂起,从而切换到空闲任务。空闲任务得到执行。
    通过上面实例的讲解,大家应该对多任务系统完整的运行过程有了一个全面的认识。随着教程后面对调度器,任务切换等知识点的讲解,大家会对这个运行过程有更深刻的理解。
    FreeRTOS就是一款支持多任务运行的实时操作系统,具有时间片,抢占式和合作式三种调度方法。通过FreeRTOS实时操作系统可以将程序函数分成独立的任务,并为其提供合理的调度方式。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:28:28 | 显示全部楼层
10.3 FreeRTOS的任务栈设置


    不管是裸机编程还是RTOS编程,栈的分配大小都非常重要。局部变量,函数调用时的现场保护和返回地址,函数的形参,进入中断函数前和中断嵌套等都需要栈空间,栈空间定义小了会造成系统崩溃。
    裸机的情况下,用户可以在这里配置栈大小:
u STM32F103工程中栈大小的配置文件
10.6.jpg


u STM32F407工程中栈大小的配置文件
10.7.jpg

u STM32F429工程中栈大小的配置文件
10.8.jpg

    不同于裸机编程,在RTOS下,每个任务都有自己的栈空间。对于FreeRTOS来说,任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
    具体每个任务的栈大小是在创建FreeRTOS的任务时进行设置的:
  1. static void AppTaskCreate (void)
  2. {
  3.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  4.                  "vTaskUserIF",     /* 任务名    */
  5.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  6.                  NULL,              /* 任务参数  */
  7.                  1,                 /* 任务优先级*/
  8.                  &xHandleTaskUserIF );  /* 任务句柄  */
  9.    
  10.    
  11.      xTaskCreate( vTaskLED,           /* 任务函数  */
  12.                  "vTaskLED",         /* 任务名    */
  13.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,               /* 任务参数  */
  15.                  2,                  /* 任务优先级*/
  16.                  &xHandleTaskLED ); /* 任务句柄  */
  17.    
  18.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  19.                  "vTaskMsgPro",           /* 任务名    */
  20.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  21.                  NULL,                    /* 任务参数  */
  22.                  3,                       /* 任务优先级*/
  23.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  24.    
  25.    
  26.      xTaskCreate( vTaskStart,             /* 任务函数  */
  27.                  "vTaskStart",            /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  4,                       /* 任务优先级*/
  31.                  &xHandleTaskStart );   /* 任务句柄  */
  32. }
复制代码

实际应用中给任务开辟多大的堆栈空间合适呢,在第11章详细跟大家进行讲解。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:31:54 | 显示全部楼层
10.4 FreeRTOS的系统栈设置


    上面跟大家讲解了什么是任务栈,这里的系统栈又是什么呢?裸机的情况下,凡是用到栈空间的地方都是在这里配置的栈空间:
u STM32F103工程中栈大小的配置文件
10.9.jpg


u STM32F407工程中栈大小的配置文件
10.10.jpg

u STM32F429工程中栈大小的配置文件
10.11.jpg

    在RTOS下,上面两个截图中设置的栈大小有了一个新的名字叫系统栈空间,而任务栈是不使用这里的空间的。任务栈不使用这里的栈空间,哪里使用这里的栈空间呢?答案就在中断函数和中断嵌套。
    对于这个问题,简单的描述如下,更详细的内容待我们讲解FreeRTOS任务切换和双堆栈指针时再细说(此章节在后期FreeRTOS教程升级版本时再加入)
u 由于Cortex-M3和M4内核具有双堆栈指针,MSP主堆栈指针和PSP进程堆栈指针,或者叫PSP任务堆栈指针也是可以的。在FreeRTOS操作系统中,主堆栈指针MSP是给系统栈空间使用的,进程堆栈指针PSP是给任务栈使用的。也就是说,在FreeRTOS任务中,所有栈空间的使用都是通过PSP指针进行指向的。一旦进入了中断函数以及可能发生的中断嵌套都是用的MSP指针。这个知识点要记住它,当前可以不知道这是为什么,但是一定要记住。
u 实际应用中系统栈空间分配多大,主要是看可能发生的中断嵌套层数,下面我们就按照最坏执行情况进行考虑,所有的寄存器都需要入栈,此时分为两种情况
    l 64字节
      对于Cortex-M3内核和未使用FPU(浮点运算单元)功能的Cortex-M4内核在发生中断时需要将16个通用寄存器全部入栈,每个寄存器占用4个字节,也就是16*4 = 64字节的空间。
       可能发生几次中断嵌套就是要64乘以几即可。当然,这种是最坏执行情况,也就是所有的寄存器都入栈。
      (注:任务执行的过程中发生中断的话,有8个寄存器是自动入栈的,这个栈是任务栈,进入中断以后其余寄存器入栈以及发生中断嵌套都是用的系统栈
    l 200字节
      对于具有FPU(浮点运算单元)功能的Cortex-M4内核,如果在任务中进行了浮点运算,那么在发生中断的时候除了16个通用寄存器需要入栈,还有34个浮点寄存器也是要入栈的,也就是(16+34)*4 = 200字节的空间。当然,这种是最坏执行情况,也就是所有的寄存器都入栈。
      (注:任务执行的过程中发送中断的话,有8个通用寄存器和18个浮点寄存器是自动入栈的,这个栈是任务栈,进入中断以后其余通用寄存器和浮点寄存器入栈以及发生中断嵌套都是用的系统栈
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:35:43 | 显示全部楼层
10.5 FreeRTOS的任务状态


    FreeRTOS的运行支持以下四种状态:
u  Running—运行态
    当任务处于实际运行状态被称之为运行态,即CPU的使用权被这个任务占用。
u  Ready—就绪态
    处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同优先级或更高优先级的任务正在运行。
u  Blocked—阻塞态
    由于等待信号量,消息队列,事件标志组等而处于的状态被称之为阻塞态,另外任务调用延迟函数也会处于阻塞态。
u  Suspended—挂起态
    类似阻塞态,通过调用函数vTaskSuspend()对指定任务进行挂起,挂起后这个任务将不被执行,只有调用函数xTaskResume()才可以将这个任务从挂起态恢复。
---------------------------------------------------------------------------
    下面是任务在各个状态之间切换的关系图,通过这个图,大家基本可以对任务的运行状态有了一个整体的认识。在后面章节的学习中会对各个状态有一个深入的认识。
10.12.JPG
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:39:00 | 显示全部楼层


10.6   FreeRTOS启动

    使用如下函数即可启动FreeRTOS:
u vTaskStartScheduler();
    关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:
10.13.jpg

这里也对此函数进行下介绍。
函数原型:
  1. void vTaskStartScheduler( void );
复制代码
函数描述:
函数vTaskStartScheduler用于启动FreeRTOS调度器,即启动FreeRTOS的多任务执行。
使用这个函数要注意以下几个问题:
1.     空闲任务和可选的定时器任务是在调用这个函数后自动创建的。
2.     正常情况下这个函数是不会返回的,运行到这里极有可能是用于定时器任务或者空闲任务的heap空间不足造成创建失败,此时需要加大FreeRTOSConfig.h文件中定义的heap大小:
      #defineconfigTOTAL_HEAP_SIZE             ( ( size_t ) ( 17 * 1024 ) )
使用举例:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.     /* 启动调度,开始执行任务 */
  35.     vTaskStartScheduler();
  36.      /*
  37.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  38.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  39.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  40.      */
  41.      while(1);
  42. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:41:12 | 显示全部楼层


10.7 FreeRTOS的任务创建


    使用如下函数可以实现FreeRTOS的任务创建:
u xTaskCreate()
关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:
10.14.jpg


这里也对此函数进行下介绍。
函数原型:
  1. BaseType_t xTaskCreate(
  2.                             TaskFunction_t pvTaskCode,     /* 任务函数 */
  3.                             const char * const pcName,     /* 任务名   */
  4.                             unsigned short usStackDepth,   /* 任务栈大小,单位word,也就是4字节 */
  5.                             void *pvParameters,            /* 任务参数  */
  6.                             UBaseType_t uxPriority,        /* 任务优先级  */
  7.                             TaskHandle_t *pvCreatedTask    /* 任务句柄  */
  8.                         );
复制代码
函数描述:
函数xTaskCreate用于实现FreeRTOS操作系统的任务创建,并且还可以自定义任务栈的大小。
u 第1个参数填创建任务的函数名。
u 第2个参数是任务名,这个参数主要是用于调试目的,调试的时候方便看是哪个任务。
u 第3个参数是任务栈大小,单位word,也就是4字节。
u 第4个参数是创建的任务函数的形参。
u 第5个参数是任务句柄,用于区分不同的任务。
使用举例:
  1. /* 任务句柄 */
  2. static TaskHandle_t xHandleTaskStart = NULL;
  3. /*
  4. *********************************************************************************************************
  5. *    函 数 名: vTaskStart
  6. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  7. *    形    参: pvParameters 是在创建该任务时传递的形参
  8. *    返 回 值: 无
  9. *   优 先 级: 4
  10. *********************************************************************************************************
  11. */
  12. static void vTaskStart(void *pvParameters)
  13. {
  14.     while(1)
  15.     {
  16.           /* 按键扫描 */
  17.          bsp_KeyScan();
  18.         vTaskDelay(10);
  19.     }
  20. }
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: AppTaskCreate
  24. *    功能说明: 创建应用任务
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. static void AppTaskCreate (void)
  30. {
  31.      xTaskCreate( vTaskStart,             /* 任务函数  */
  32.                  "vTaskStart",            /* 任务名    */
  33.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  34.                  NULL,                    /* 任务参数  */
  35.                  4,                       /* 任务优先级*/
  36.                  &xHandleTaskStart );     /* 任务句柄  */   
  37. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:44:49 | 显示全部楼层


10.8   FreeRTOS的任务删除
    使用如下函数可以实现FreeRTOS的任务删除:
u  vTaskDelete()
关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:
10.15.jpg

这里也对此函数进行下介绍。
函数原型:
  1. void vTaskDelete(
  2. TaskHandle_t xTask ); /* 任务句柄 */
复制代码
函数描述:
函数vTaskDelete用于实现FreeRTOS操作系统的任务删除。
u 第1个参数填要删除任务的句柄
使用这个函数要注意以下问题:
1.     使用此函数需要在FreeRTOSConfig.h配置文件中配置如下宏定义为1
    #defineINCLUDE_vTaskDelete      1
2.     如果用往此函数里面填的任务ID是NULL,即数值0的话,那么删除的就是当前正在执行的任务,此任务被删除后,FreeRTOS会切换到任务就绪列表里面下一个要执行的最高优先级任务。
3.     在FreeRTOS中,创建任务所需的内存需要在空闲任务中释放,如果用户在FreeRTOS中调用了这个函数的话,一定要让空闲任务有执行的机会,否则这块内存是无法释放的。另外,创建的这个任务在使用中申请了动态内存,这个内存不会因为此任务被删除而删除,这一点要注意,一定要在删除前将此内存释放。
使用举例:
  1. /* 任务句柄 */
  2. static TaskHandle_t xHandleTaskStart = NULL;
  3. /*
  4. *********************************************************************************************************
  5. *    函 数 名: vTaskStart
  6. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  7. *    形    参: pvParameters 是在创建该任务时传递的形参
  8. *    返 回 值: 无
  9. *   优 先 级: 4
  10. *********************************************************************************************************
  11. */
  12. static void vTaskStart(void *pvParameters)
  13. {
  14.     while(1)
  15.     {
  16.           /* 按键扫描 */
  17.          bsp_KeyScan();
  18.         vTaskDelay(10);
  19.     }
  20. }
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: AppTaskDelete
  24. *    功能说明: 任务删除
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. static void AppTaskDelete (void)
  30. {
  31.      xTaskCreate( vTaskStart,             /* 任务函数  */
  32.                  "vTaskStart",            /* 任务名    */
  33.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  34.                  NULL,                    /* 任务参数  */
  35.                  4,                       /* 任务优先级*/
  36.                  &xHandleTaskStart );     /* 任务句柄  */
  37.      /* 删除此任务 */
  38.      if(xHandleTaskStart!= NULL)
  39.      {
  40.          vTaskDelete(xHandleTaskStart);
  41.      }
  42.    
  43. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:48:17 | 显示全部楼层


10.9 FreeRTOS的任务挂起


    使用如下函数可以实现FreeRTOS的任务挂起:
u xTaskSuspend()
关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:
10.16.jpg

这里也对此函数进行下介绍。

函数原型:
  1. void vTaskSuspend(
  2. TaskHandle_t xTaskToSuspend); /* 任务句柄 */
复制代码

函数描述:
函数vTaskSuspend用于实现FreeRTOS操作系统的任务挂起。
u 第1个参数填要挂起任务的句柄
使用这个函数要注意以下问题:
1.     使用此函数需要在FreeRTOSConfig.h配置文件中配置如下宏定义为1
    #defineINCLUDE_vTaskSuspend          1
2.     如果用往此函数里面填的任务ID是NULL,即数值0的话,那么挂起的就是当前正在执行的任务,此任务被挂起后,FreeRTOS会切换到任务就绪列表里面下一个要执行的高优先级任务。
3.     多次调用此函数的话,只需调用一次vTaskResume即可将任务从挂起态恢复。
使用举例:
  1. /* 任务句柄 */
  2. static TaskHandle_t xHandleTaskStart = NULL;
  3. /*
  4. *********************************************************************************************************
  5. *    函 数 名: vTaskStart
  6. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  7. *    形    参: pvParameters 是在创建该任务时传递的形参
  8. *    返 回 值: 无
  9. *   优 先 级: 4
  10. *********************************************************************************************************
  11. */
  12. static void vTaskStart(void *pvParameters)
  13. {
  14.     while(1)
  15.     {
  16.           /* 按键扫描 */
  17.          bsp_KeyScan();
  18.         vTaskDelay(10);
  19.     }
  20. }
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: AppTaskSuspend
  24. *    功能说明: 任务挂起
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. static void AppTaskSuspend (void)
  30. {
  31.      xTaskCreate( vTaskStart,             /* 任务函数  */
  32.                  "vTaskStart",            /* 任务名    */
  33.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  34.                  NULL,                    /* 任务参数  */
  35.                  4,                       /* 任务优先级*/
  36.                  &xHandleTaskStart );     /* 任务句柄  */
  37.      /* 挂起此任务 */
  38.      if(xHandleTaskStart!= NULL)
  39.      {
  40.          vTaskSuspend(xHandleTaskStart);
  41.      }
  42.    
  43. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:50:53 | 显示全部楼层


10.10   FreeRTOS的任务恢复


    使用如下函数可以实现FreeRTOS的任务恢复:
u xTaskResume()
关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:
10.17.jpg

这里也对此函数进行下介绍。
函数原型:
  1. void vTaskResume(
  2. TaskHandle_t xTaskToResume); /* 任务句柄 */
复制代码
函数描述:
函数vTaskResume用于实现FreeRTOS操作系统的任务挂起
u 第1个参数填要恢复任务的句柄
使用这个函数要注意以下问题:
1.     使用此函数需要在FreeRTOSConfig.h配置文件中配置如下宏定义为1
    #defineINCLUDE_vTaskSuspend          1
2.     多次调用函数vTaskSuspend的话,只需调用一次vTaskResume即可将任务从挂起态恢复。
3.     此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的xTaskResumeFromISR(),以后缀FromISR结尾。
使用举例:
  1. /* 任务句柄 */
  2. static TaskHandle_t xHandleTaskStart = NULL;
  3. /*
  4. *********************************************************************************************************
  5. *    函 数 名: vTaskStart
  6. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  7. *    形    参: pvParameters 是在创建该任务时传递的形参
  8. *    返 回 值: 无
  9. *   优 先 级: 4
  10. *********************************************************************************************************
  11. */
  12. static void vTaskStart(void *pvParameters)
  13. {
  14.     while(1)
  15.     {
  16.           /* 按键扫描 */
  17.          bsp_KeyScan();
  18.         vTaskDelay(10);
  19.     }
  20. }
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: AppTaskResume
  24. *    功能说明: 任务恢复
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. static void AppTaskResume (void)
  30. {
  31.      xTaskCreate( vTaskStart,             /* 任务函数  */
  32.                  "vTaskStart",            /* 任务名    */
  33.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  34.                  NULL,                    /* 任务参数  */
  35.                  4,                       /* 任务优先级*/
  36.                  &xHandleTaskStart );     /* 任务句柄  */
  37.      /* 挂起此任务 */
  38.      if(xHandleTaskStart!= NULL)
  39.      {
  40.          vTaskSuspend(xHandleTaskStart);
  41.      }
  42.      /* 恢复此任务 */
  43.      if(xHandleTaskStart!= NULL)
  44.      {
  45.          vTaskResume(xHandleTaskStart);
  46.      }
  47. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:53:58 | 显示全部楼层
10.11 FreeRTOS的任务恢复(中断方式)


    使用如下函数可以实现FreeRTOS的任务恢复(中断方式):
u xTaskResumeFromISR()
关于这个函数的讲解及其使用方法可以看FreeRTOS在线版手册:
10.18.jpg

这里也对此函数进行下介绍。
函数原型:
  1. void vTaskResumeFromISR(
  2. TaskHandle_t xTaskToResume); /* 任务句柄 */
复制代码
函数描述:
函数vTaskResumeFromISR用于实现FreeRTOS操作系统的任务恢复。
u 第1个参数填要恢复任务的句柄
使用这个函数要注意以下问题:
1.     使用此函数需要在FreeRTOSConfig.h配置文件中配置如下宏定义为1
    #defineINCLUDE_xResumeFromISR                  1
2.     多次调用函数vTaskSuspend的话,只需调用一次vTaskResumeFromISR即可将任务从挂起态恢复。
3.     如果用户打算采用这个函数实现中断与任务的同步,要注意一种情况,如果此函数的调用优先于函数vTaskSuspend被调用,那么此次同步会丢失,这种情况下建议使用信号量来实现同步。
4.     此函数是用于中断服务程序中调用的,故不可以在任务中使用此函数,任务中使用的是vTaskResume。
使用举例:
  1. /* 任务句柄 */
  2. static TaskHandle_t xHandleTaskStart = NULL;
  3. /*
  4. *********************************************************************************************************
  5. *    函 数 名: vTaskStart
  6. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  7. *    形    参: pvParameters 是在创建该任务时传递的形参
  8. *    返 回 值: 无
  9. *   优 先 级: 4
  10. *********************************************************************************************************
  11. */
  12. static void vTaskStart(void *pvParameters)
  13. {
  14.     while(1)
  15.     {
  16.           /* 按键扫描 */
  17.          bsp_KeyScan();
  18.         vTaskDelay(10);
  19.     }
  20. }
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: AppTaskResume
  24. *    功能说明: 任务恢复
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. static void AppTaskResume (void)
  30. {
  31.      xTaskCreate( vTaskStart,             /* 任务函数  */
  32.                  "vTaskStart",            /* 任务名    */
  33.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  34.                  NULL,                    /* 任务参数  */
  35.                  4,                       /* 任务优先级*/
  36.                  &xHandleTaskStart );     /* 任务句柄  */
  37.      /* 挂起此任务 */
  38.      if(xHandleTaskStart!= NULL)
  39.      {
  40.          vTaskSuspend(xHandleTaskStart);
  41.      }
  42. }
  43. /*
  44. *********************************************************************************************************
  45. *    函 数 名: TIM2_IRQHandler
  46. *    功能说明: 定时器中断。                     
  47. *    形    参: 无
  48. *    返 回 值: 无
  49. *********************************************************************************************************
  50. */
  51. static void TIM2_IRQHandler(void)
  52. {
  53.      BaseType_t xYieldRequired;
  54.      /* 中断消息处理,此处省略 */
  55.      ……
  56.     /* 恢复挂起任务 */
  57.      xYieldRequired = xTaskResumeFromISR(xHandleTaskStart);
  58.       /* 退出中断后是否需要执行任务切换 */
  59.      if( xYieldRequired == pdTRUE )
  60.      {
  61.          portYIELD_FROM_ISR(xYieldRequired);
  62.      }
  63. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 14:56:21 | 显示全部楼层
10.12   FreeRTOS的空闲任务


   几乎所有的小型 RTOS 中都会有一个空闲任务,空闲任务属于系统任务,是必须要执行的,用户程序不能将其关闭。不光小型系统中有空闲任务,大型的系统里面也有的,比如WIN7,下面的截图就是 WIN7中的空闲进程。
10.19.jpg


空闲任务主要有以下几个作用:
u 用户不能让系统一直在执行各个应用任务,这样的话系统利用率就是 100%,系统就会一直超负荷运行,所以空闲任务很有必要。
u 为了更好的实现低功耗,空闲任务也很有必要,用户可以在空闲任务中实现睡眠,停机等低功耗措施。
在后面的章节中我们会用到空闲任务的钩子函数,再给大家进行详述。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 15:21:06 | 显示全部楼层
10.13   实验例程说明



10.13.1 STM32F103开发板实验


配套例子:
    V4-303_FreeRTOS实验_任务的创建,删除,挂起和恢复
实验目的:
    1. 学习FreeRTOS的任务创建,删除,挂起和恢复。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下,删除任务vTaskLED。
    3.     K3按键按下,重新创建任务vTaskLED。
    4.     摇杆UP按键按下,挂起任务vTaskLED。
    5.     摇杆DOWN键按下,恢复任务vTaskLED。
    6.     各个任务实现的功能如下:
                    vTaskUserIF任务   :按键消息处理。
                    vTaskLED任务     :LED闪烁。
                    vTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
                    vTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. #endif
  6. #define configUSE_PREEMPTION         1
  7. #define configUSE_IDLE_HOOK          0
  8. #define configUSE_TICK_HOOK          0
  9. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 72000000 )  
  10. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  11. #define configMAX_PRIORITIES         ( 5 )
  12. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  13. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  14. #define configMAX_TASK_NAME_LEN      ( 16 )
  15. #define configUSE_TRACE_FACILITY      1
  16. #define configUSE_16_BIT_TICKS       0
  17. #define configIDLE_SHOULD_YIELD      1
  18. /* Run time and task stats gathering related definitions. */
  19. #define configGENERATE_RUN_TIME_STATS                1
  20. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  21. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  22. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  23. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  24. /* Co-routine definitions. */
  25. #define configUSE_CO_ROUTINES            0
  26. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  27. /* Set the following definitions to 1 to include the API function, or zero
  28. to exclude the API function. */
  29. #define INCLUDE_vTaskPrioritySet          1
  30. #define INCLUDE_uxTaskPriorityGet         1
  31. #define INCLUDE_vTaskDelete               1
  32. #define INCLUDE_vTaskCleanUpResources      0
  33. #define INCLUDE_vTaskSuspend              1
  34. #define INCLUDE_vTaskDelayUntil           1
  35. #define INCLUDE_vTaskDelay                1
  36. /* Cortex-M specific definitions. */
  37. #ifdef __NVIC_PRIO_BITS
  38.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  39.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  40. #else
  41.      #define configPRIO_BITS              4        /* 15 priority levels */
  42. #endif
  43. /* The lowest interrupt priority that can be used in a call to a "set priority"
  44. function. */
  45. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  46. /* The highest interrupt priority that can be used by any interrupt service
  47. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  48. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  49. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  50. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY         0x01
复制代码

几个重要选项说明:
u #define configUSE_PREEMPTION        1
    使能抢占式调度器
u #define configCPU_CLOCK_HZ      ( ( unsigned long ) 72000000 )   
    系统主频72MHz。
u #define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
    系统时钟节拍1KHz,即1ms。
u #define configMAX_PRIORITIES          ( 5 )
    定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
u #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
    定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
u #define INCLUDE_vTaskSuspend               1
    使用FreeRTOS的任务挂起函数vTaskSuspend和任务恢复函数vTaskResume必须配置此宏定义为1。
u configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
    定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
l 使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
l 对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为0到15,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
l 这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。
更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
10.20.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
u  任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
      #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 17 * 1024 ) )
u  系统栈大小分配:
10.21.jpg

u  FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.     /* 启动调度,开始执行任务 */
  35.     vTaskStartScheduler();
  36.      /*
  37.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  38.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  39.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  40.      */
  41.      while(1);
  42. }
复制代码

u  硬件外设初始化
硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
  5. *             全局变量。
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_Init(void)
  11. {
  12.      /*
  13.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  14.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  15.          系统时钟缺省配置为72MHz,如果需要更改,可以修改 system_stm32f10x.c 文件
  16.      */
  17.    
  18.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  19.      bsp_InitUart();    /* 初始化串口 */
  20.      bsp_InitLed();     /* 初始LED指示灯端口 */
  21.      bsp_InitKey();     /* 初始化按键 */
  22. }
复制代码

u  FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.    
  34.      xTaskCreate( vTaskStart,             /* 任务函数  */
  35.                  "vTaskStart",            /* 任务名    */
  36.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  37.                  NULL,                    /* 任务参数  */
  38.                  4,                       /* 任务优先级*/
  39.                  &xHandleTaskStart );   /* 任务句柄  */
  40. }
复制代码

u  四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      uint8_t ucKeyCode;
  13.      uint8_t pcWriteBuffer[500];
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下 打印任务执行情况 */
  23.                    case KEY_DOWN_K1:         
  24.                        printf("=================================================\\r\\n");
  25.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  26.                        vTaskList((char *)&pcWriteBuffer);
  27.                        printf("%s\\r\\n", pcWriteBuffer);
  28.                   
  29.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  30.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  31.                        printf("%s\\r\\n", pcWriteBuffer);
  32.                        break;
  33.                   
  34.                    /* K2键按下 删除任务vTaskLED */
  35.                    case KEY_DOWN_K2:         
  36.                        printf("K2键按下,删除任务vTaskLED\\r\\n");
  37.                        if(xHandleTaskLED != NULL)
  38.                        {
  39.                             vTaskDelete(xHandleTaskLED);
  40.                             xHandleTaskLED = NULL;
  41.                        }
  42.                        break;
  43.                   
  44.                    /* K3键按下 重新创建任务vTaskLED */
  45.                    case KEY_DOWN_K3:
  46.                        printf("K3键按下,重新创建任务vTaskLED\\r\\n");
  47.                        if(xHandleTaskLED == NULL)
  48.                        {
  49.                             xTaskCreate(    vTaskLED,            /* 任务函数  */
  50.                                                "vTaskLED",          /* 任务名    */
  51.                                                512,                 /* stack大小,单位word,也就是4字节 */
  52.                                                NULL,                /* 任务参数  */
  53.                                                2,                   /* 任务优先级*/
  54.                                                &xHandleTaskLED );   /* 任务句柄  */
  55.                        }
  56.                        break;
  57.                      
  58.                    /* 摇杆UP键按下,挂起任务vTaskLED */
  59.                    case JOY_DOWN_U:
  60.                        printf("摇杆UP键按下,挂起任务vTaskLED\\r\\n");
  61.                        vTaskSuspend(xHandleTaskLED);
  62.                        break;
  63.                   
  64.                    /* 摇杆DOWN键按下,恢复任务vTaskLED */
  65.                    case JOY_DOWN_D:
  66.                        printf("摇杆DOWN键按下,恢复任务vTaskLED\\r\\n");
  67.                        vTaskResume(xHandleTaskLED);
  68.                        break;
  69.                   
  70.                    /* 其他的键值不处理 */
  71.                    default:                    
  72.                        break;
  73.               }
  74.          }
  75.         
  76.          vTaskDelay(20);
  77.      }
  78. }
  79. /*
  80. *********************************************************************************************************
  81. *    函 数 名: vTaskLED
  82. *    功能说明: LED闪烁
  83. *    形    参: pvParameters 是在创建该任务时传递的形参
  84. *    返 回 值: 无
  85. *   优 先 级: 2
  86. *********************************************************************************************************
  87. */
  88. static void vTaskLED(void *pvParameters)
  89. {
  90.     while(1)
  91.     {
  92.          bsp_LedToggle(2);
  93.         vTaskDelay(200);
  94.     }
  95. }
  96. /*
  97. *********************************************************************************************************
  98. *    函 数 名: vTaskMsgPro
  99. *    功能说明: 消息处理,这里是用作LED闪烁   
  100. *    形    参: pvParameters 是在创建该任务时传递的形参
  101. *    返 回 值: 无
  102. *   优 先 级: 3
  103. *********************************************************************************************************
  104. */
  105. static void vTaskMsgPro(void *pvParameters)
  106. {
  107.     while(1)
  108.     {
  109.          bsp_LedToggle(3);
  110.         vTaskDelay(300);
  111.     }
  112. }
  113. /*
  114. *********************************************************************************************************
  115. *    函 数 名: vTaskStart
  116. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  117. *    形    参: pvParameters 是在创建该任务时传递的形参
  118. *    返 回 值: 无
  119. *   优 先 级: 4
  120. *********************************************************************************************************
  121. */
  122. static void vTaskStart(void *pvParameters)
  123. {
  124.     while(1)
  125.     {
  126.          /* 按键扫描 */
  127.          bsp_KeyScan();
  128.         vTaskDelay(10);
  129.     }
  130. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 15:25:25 | 显示全部楼层
10.13.2   STM32F407开发板实验


配套例子:
     V5-303_FreeRTOS实验_任务的创建,删除,挂起和恢复
实验目的:
    1. 学习FreeRTOS的任务创建,删除,挂起和恢复。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下,删除任务vTaskLED。
    3.     K3按键按下,重新创建任务vTaskLED。
    4.     摇杆UP按键按下,挂起任务vTaskLED。
    5.     摇杆DOWN键按下,恢复任务vTaskLED。
    6.     各个任务实现的功能如下:
                    vTaskUserIF任务   :按键消息处理。
                    vTaskLED任务     :LED闪烁。
                    vTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
                    vTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. /* Ensure stdint is only used by the compiler, and not the assembler. */
  6. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  7. #include <stdint.h>
  8. extern volatile uint32_t ulHighFrequencyTimerTicks;
  9. #endif
  10. #define configUSE_PREEMPTION         1
  11. #define configUSE_IDLE_HOOK          0
  12. #define configUSE_TICK_HOOK          0
  13. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  14. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  15. #define configMAX_PRIORITIES         ( 5 )
  16. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  17. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  18. #define configMAX_TASK_NAME_LEN      ( 16 )
  19. #define configUSE_TRACE_FACILITY      1
  20. #define configUSE_16_BIT_TICKS       0
  21. #define configIDLE_SHOULD_YIELD      1
  22. /* Run time and task stats gathering related definitions. */
  23. #define configGENERATE_RUN_TIME_STATS                1
  24. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  25. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  26. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  27. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  28. /* Co-routine definitions. */
  29. #define configUSE_CO_ROUTINES             0
  30. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  31. /* Set the following definitions to 1 to include the API function, or zero
  32. to exclude the API function. */
  33. #define INCLUDE_vTaskPrioritySet     1
  34. #define INCLUDE_uxTaskPriorityGet         1
  35. #define INCLUDE_vTaskDelete               1
  36. #define INCLUDE_vTaskCleanUpResources 0
  37. #define INCLUDE_vTaskSuspend              1
  38. #define INCLUDE_vTaskDelayUntil           1
  39. #define INCLUDE_vTaskDelay                1
  40. /* Cortex-M specific definitions. */
  41. #ifdef __NVIC_PRIO_BITS
  42.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  43.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  44. #else
  45.      #define configPRIO_BITS              4        /* 15 priority levels */
  46. #endif
  47. /* The lowest interrupt priority that can be used in a call to a "set priority"
  48. function. */
  49. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  50. /* The highest interrupt priority that can be used by any interrupt service
  51. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  52. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  53. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  54. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
复制代码
几个重要选项说明:
u #define configUSE_PREEMPTION        1
    使能抢占式调度器
u #define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )  
    系统主频168MHz。
u #define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
    系统时钟节拍1KHz,即1ms。
u #define configMAX_PRIORITIES          ( 5 )
    定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
u #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
    定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
u #define INCLUDE_vTaskSuspend               1
    使用FreeRTOS的任务挂起函数vTaskSuspend和任务恢复函数vTaskResume必须配置此宏定义为1。
u configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
    定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    l 使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    l 对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为0到15,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
    l 这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。
更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
10.22.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
u  任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
      #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 30 * 1024 ) )
u  系统栈大小分配:
10.23.jpg

u  FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.     /* 启动调度,开始执行任务 */
  35.     vTaskStartScheduler();
  36.      /*
  37.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  38.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  39.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  40.      */
  41.      while(1);
  42. }
复制代码
u  硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  18.      bsp_InitUart();    /* 初始化串口 */
  19.      bsp_InitKey();     /* 初始化按键变量 */
  20.      bsp_InitLed();     /* 初始LED指示灯端口 */
  21. }
复制代码
u  FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                  /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.    
  34.      xTaskCreate( vTaskStart,             /* 任务函数  */
  35.                  "vTaskStart",            /* 任务名    */
  36.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  37.                  NULL,                    /* 任务参数  */
  38.                  4,                       /* 任务优先级*/
  39.                  &xHandleTaskStart );   /* 任务句柄  */
  40. }
复制代码
u  四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      uint8_t ucKeyCode;
  13.      uint8_t pcWriteBuffer[500];
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下 打印任务执行情况 */
  23.                    case KEY_DOWN_K1:         
  24.                        printf("=================================================\\r\\n");
  25.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  26.                        vTaskList((char *)&pcWriteBuffer);
  27.                        printf("%s\\r\\n", pcWriteBuffer);
  28.                   
  29.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  30.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  31.                        printf("%s\\r\\n", pcWriteBuffer);
  32.                        break;
  33.                   
  34.                    /* K2键按下 删除任务vTaskLED */
  35.                    case KEY_DOWN_K2:         
  36.                        printf("K2键按下,删除任务vTaskLED\\r\\n");
  37.                        if(xHandleTaskLED != NULL)
  38.                        {
  39.                             vTaskDelete(xHandleTaskLED);
  40.                             xHandleTaskLED = NULL;
  41.                        }
  42.                        break;
  43.                   
  44.                    /* K3键按下 重新创建任务vTaskLED */
  45.                    case KEY_DOWN_K3:
  46.                        printf("K3键按下,重新创建任务vTaskLED\\r\\n");
  47.                        if(xHandleTaskLED == NULL)
  48.                        {
  49.                             xTaskCreate(    vTaskLED,            /* 任务函数  */
  50.                                                "vTaskLED",          /* 任务名    */
  51.                                                512,                 /* stack大小,单位word,也就是4字节 */
  52.                                                NULL,                /* 任务参数  */
  53.                                                2,                   /* 任务优先级*/
  54.                                                &xHandleTaskLED );   /* 任务句柄  */
  55.                        }
  56.                        break;
  57.                      
  58.                    /* 摇杆UP键按下,挂起任务vTaskLED */
  59.                    case JOY_DOWN_U:
  60.                        printf("摇杆UP键按下,挂起任务vTaskLED\\r\\n");
  61.                        vTaskSuspend(xHandleTaskLED);
  62.                        break;
  63.                   
  64.                    /* 摇杆DOWN键按下,恢复任务vTaskLED */
  65.                    case JOY_DOWN_D:
  66.                        printf("摇杆DOWN键按下,恢复任务vTaskLED\\r\\n");
  67.                        vTaskResume(xHandleTaskLED);
  68.                        break;
  69.                   
  70.                    /* 其他的键值不处理 */
  71.                    default:                    
  72.                        break;
  73.               }
  74.          }
  75.         
  76.          vTaskDelay(20);
  77.      }
  78. }
  79. /*
  80. *********************************************************************************************************
  81. *    函 数 名: vTaskLED
  82. *    功能说明: LED闪烁
  83. *    形    参: pvParameters 是在创建该任务时传递的形参
  84. *    返 回 值: 无
  85. *   优 先 级: 2
  86. *********************************************************************************************************
  87. */
  88. static void vTaskLED(void *pvParameters)
  89. {
  90.     while(1)
  91.     {
  92.          bsp_LedToggle(2);
  93.         vTaskDelay(200);
  94.     }
  95. }
  96. /*
  97. *********************************************************************************************************
  98. *    函 数 名: vTaskMsgPro
  99. *    功能说明: 消息处理,这里是用作LED闪烁   
  100. *    形    参: pvParameters 是在创建该任务时传递的形参
  101. *    返 回 值: 无
  102. *   优 先 级: 3
  103. *********************************************************************************************************
  104. */
  105. static void vTaskMsgPro(void *pvParameters)
  106. {
  107.     while(1)
  108.     {
  109.          bsp_LedToggle(3);
  110.         vTaskDelay(300);
  111.     }
  112. }
  113. /*
  114. *********************************************************************************************************
  115. *    函 数 名: vTaskStart
  116. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  117. *    形    参: pvParameters 是在创建该任务时传递的形参
  118. *    返 回 值: 无
  119. *   优 先 级: 4
  120. *********************************************************************************************************
  121. */
  122. static void vTaskStart(void *pvParameters)
  123. {
  124.     while(1)
  125.     {
  126.          /* 按键扫描 */
  127.          bsp_KeyScan();
  128.         vTaskDelay(10);
  129.     }
  130. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 15:30:24 | 显示全部楼层
10.13.3 STM32F429开发板实验


配套例子:
     V6-303_FreeRTOS实验_任务的创建,删除,挂起和恢复
实验目的:
    1. 学习FreeRTOS的任务创建,删除,挂起和恢复。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下,删除任务vTaskLED。
    3.     K3按键按下,重新创建任务vTaskLED。
    4.     摇杆UP按键按下,挂起任务vTaskLED。
    5.     摇杆DOWN键按下,恢复任务vTaskLED。
    6.     各个任务实现的功能如下:
              vTaskUserIF任务   :按键消息处理。
              vTaskLED任务     :LED闪烁。
              vTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
              vTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. #endif
  6. #define configUSE_PREEMPTION         1
  7. #define configUSE_IDLE_HOOK          0
  8. #define configUSE_TICK_HOOK          0
  9. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  10. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  11. #define configMAX_PRIORITIES         ( 5 )
  12. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  13. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  14. #define configMAX_TASK_NAME_LEN      ( 16 )
  15. #define configUSE_TRACE_FACILITY      1
  16. #define configUSE_16_BIT_TICKS       0
  17. #define configIDLE_SHOULD_YIELD      1
  18. /* Run time and task stats gathering related definitions. */
  19. #define configGENERATE_RUN_TIME_STATS                1
  20. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  21. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  22. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  23. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  24. /* Co-routine definitions. */
  25. #define configUSE_CO_ROUTINES            0
  26. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  27. /* Set the following definitions to 1 to include the API function, or zero
  28. to exclude the API function. */
  29. #define INCLUDE_vTaskPrioritySet          1
  30. #define INCLUDE_uxTaskPriorityGet         1
  31. #define INCLUDE_vTaskDelete               1
  32. #define INCLUDE_vTaskCleanUpResources      0
  33. #define INCLUDE_vTaskSuspend              1
  34. #define INCLUDE_vTaskDelayUntil           1
  35. #define INCLUDE_vTaskDelay                1
  36. /* Cortex-M specific definitions. */
  37. #ifdef __NVIC_PRIO_BITS
  38.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  39.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  40. #else
  41.      #define configPRIO_BITS              4        /* 15 priority levels */
  42. #endif
  43. /* The lowest interrupt priority that can be used in a call to a "set priority"
  44. function. */
  45. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  46. /* The highest interrupt priority that can be used by any interrupt service
  47. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  48. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  49. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  50. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY         0x01
复制代码

几个重要选项说明:
u #define configUSE_PREEMPTION        1
      使能抢占式调度器
u #define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )  
      系统主频168MHz。
u #define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
      系统时钟节拍1KHz,即1ms。
u #define configMAX_PRIORITIES          ( 5 )
      定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
u #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
      定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
u #define INCLUDE_vTaskSuspend               1
      使用FreeRTOS的任务挂起函数vTaskSuspend和任务恢复函数vTaskResume必须配置此宏定义为1。
u configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
      定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    l 使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    l 对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为0到15,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
    l 这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。
    更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
10.24.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
u  任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
    #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 30 * 1024 ) )
u  系统栈大小分配:
10.25.jpg

u  FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.     /* 启动调度,开始执行任务 */
  35.     vTaskStartScheduler();
  36.      /*
  37.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  38.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  39.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  40.      */
  41.      while(1);
  42. }
复制代码

u  硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  18.    
  19.      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */
  20.      bsp_InitUart();    /* 初始化串口 */
  21.      bsp_InitKey();     /* 初始化按键变量 */
  22.      bsp_InitExtIO();   /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */
  23.      bsp_InitLed();     /* 初始LED指示灯端口 */
  24. }
复制代码

u  FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.    
  34.      xTaskCreate( vTaskStart,             /* 任务函数  */
  35.                  "vTaskStart",            /* 任务名    */
  36.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  37.                  NULL,                    /* 任务参数  */
  38.                  4,                       /* 任务优先级*/
  39.                  &xHandleTaskStart );   /* 任务句柄  */
  40. }
复制代码

u  四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      uint8_t ucKeyCode;
  13.      uint8_t pcWriteBuffer[500];
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下 打印任务执行情况 */
  23.                    case KEY_DOWN_K1:         
  24.                        printf("=================================================\\r\\n");
  25.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  26.                        vTaskList((char *)&pcWriteBuffer);
  27.                        printf("%s\\r\\n", pcWriteBuffer);
  28.                   
  29.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  30.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  31.                        printf("%s\\r\\n", pcWriteBuffer);
  32.                        break;
  33.                   
  34.                    /* K2键按下 删除任务vTaskLED */
  35.                    case KEY_DOWN_K2:         
  36.                        printf("K2键按下,删除任务vTaskLED\\r\\n");
  37.                        if(xHandleTaskLED != NULL)
  38.                        {
  39.                             vTaskDelete(xHandleTaskLED);
  40.                             xHandleTaskLED = NULL;
  41.                        }
  42.                        break;
  43.                   
  44.                    /* K3键按下 重新创建任务vTaskLED */
  45.                    case KEY_DOWN_K3:
  46.                        printf("K3键按下,重新创建任务vTaskLED\\r\\n");
  47.                        if(xHandleTaskLED == NULL)
  48.                        {
  49.                             xTaskCreate(    vTaskLED,            /* 任务函数  */
  50.                                                "vTaskLED",          /* 任务名    */
  51.                                                512,                 /* stack大小,单位word,也就是4字节 */
  52.                                                NULL,                /* 任务参数  */
  53.                                                2,                   /* 任务优先级*/
  54.                                                &xHandleTaskLED );   /* 任务句柄  */
  55.                        }
  56.                        break;
  57.                      
  58.                    /* 摇杆UP键按下,挂起任务vTaskLED */
  59.                    case JOY_DOWN_U:
  60.                        printf("摇杆UP键按下,挂起任务vTaskLED\\r\\n");
  61.                        vTaskSuspend(xHandleTaskLED);
  62.                        break;
  63.                   
  64.                    /* 摇杆DOWN键按下,恢复任务vTaskLED */
  65.                    case JOY_DOWN_D:
  66.                        printf("摇杆DOWN键按下,恢复任务vTaskLED\\r\\n");
  67.                        vTaskResume(xHandleTaskLED);
  68.                        break;
  69.                   
  70.                    /* 其他的键值不处理 */
  71.                    default:                    
  72.                        break;
  73.               }
  74.          }
  75.         
  76.          vTaskDelay(20);
  77.      }
  78. }
  79. /*
  80. *********************************************************************************************************
  81. *    函 数 名: vTaskLED
  82. *    功能说明: LED闪烁
  83. *    形    参: pvParameters 是在创建该任务时传递的形参
  84. *    返 回 值: 无
  85. *   优 先 级: 2
  86. *********************************************************************************************************
  87. */
  88. static void vTaskLED(void *pvParameters)
  89. {
  90.     while(1)
  91.     {
  92.          bsp_LedToggle(2);
  93.         vTaskDelay(200);
  94.     }
  95. }
  96. /*
  97. *********************************************************************************************************
  98. *    函 数 名: vTaskMsgPro
  99. *    功能说明: 消息处理,这里是用作LED闪烁   
  100. *    形    参: pvParameters 是在创建该任务时传递的形参
  101. *    返 回 值: 无
  102. *   优 先 级: 3
  103. *********************************************************************************************************
  104. */
  105. static void vTaskMsgPro(void *pvParameters)
  106. {
  107.     while(1)
  108.     {
  109.          bsp_LedToggle(3);
  110.         vTaskDelay(300);
  111.     }
  112. }
  113. /*
  114. *********************************************************************************************************
  115. *    函 数 名: vTaskStart
  116. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  117. *    形    参: pvParameters 是在创建该任务时传递的形参
  118. *    返 回 值: 无
  119. *   优 先 级: 4
  120. *********************************************************************************************************
  121. */
  122. static void vTaskStart(void *pvParameters)
  123. {
  124.     while(1)
  125.     {
  126.          /* 按键扫描 */
  127.          bsp_KeyScan();
  128.         vTaskDelay(10);
  129.     }
  130. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 15:39:15 | 显示全部楼层
10.14 实验例程说明(中断方式)



10.14.1 STM32F103开发板实验


配套例子:
    V4-304_FreeRTOS实验_任务恢复(中断方式)
实验目的:
    1.     学习FreeRTOS的任务恢复(中断方式)。
    2.     任务中的任务恢复函数调用的vTaskResume,而中断里面的任务恢复函数调用xTaskResumeFromISR,中断中调用的函数是以FromISR结尾的,实际应用中切不可混淆。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下,删除任务vTaskLED。
    3.     K3按键按下,重新创建任务vTaskLED。
    4.     摇杆UP按键按下,挂起任务vTaskLED。
    5.     摇杆DOWN键按下,恢复任务vTaskLED。
    6.     摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复。
    7.     各个任务实现的功能如下:
                vTaskUserIF任务   :按键消息处理。
                vTaskLED任务     :LED闪烁。
                vTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
                vTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. #endif
  6. #define configUSE_PREEMPTION         1
  7. #define configUSE_IDLE_HOOK          0
  8. #define configUSE_TICK_HOOK          0
  9. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 72000000 )  
  10. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  11. #define configMAX_PRIORITIES         ( 5 )
  12. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  13. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  14. #define configMAX_TASK_NAME_LEN      ( 16 )
  15. #define configUSE_TRACE_FACILITY      1
  16. #define configUSE_16_BIT_TICKS       0
  17. #define configIDLE_SHOULD_YIELD      1
  18. /* Run time and task stats gathering related definitions. */
  19. #define configGENERATE_RUN_TIME_STATS                1
  20. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  21. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  22. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  23. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  24. /* Co-routine definitions. */
  25. #define configUSE_CO_ROUTINES            0
  26. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  27. /* Set the following definitions to 1 to include the API function, or zero
  28. to exclude the API function. */
  29. #define INCLUDE_vTaskPrioritySet          1
  30. #define INCLUDE_uxTaskPriorityGet         1
  31. #define INCLUDE_vTaskDelete               1
  32. #define INCLUDE_vTaskCleanUpResources      0
  33. #define INCLUDE_vTaskSuspend              1
  34. #define INCLUDE_xTaskResumeFromISR        1
  35. #define INCLUDE_vTaskDelayUntil           1
  36. #define INCLUDE_vTaskDelay                1
  37. /* Cortex-M specific definitions. */
  38. #ifdef __NVIC_PRIO_BITS
  39.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  40.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  41. #else
  42.      #define configPRIO_BITS              4        /* 15 priority levels */
  43. #endif
  44. /* The lowest interrupt priority that can be used in a call to a "set priority"
  45. function. */
  46. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  47. /* The highest interrupt priority that can be used by any interrupt service
  48. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  49. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  50. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  51. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY         0x01
复制代码
几个重要选项说明:
u #define configUSE_PREEMPTION        1
      使能抢占式调度器
u #define configCPU_CLOCK_HZ      ( ( unsigned long ) 72000000 )   
      系统主频72MHz。
u #define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
      系统时钟节拍1KHz,即1ms。
u #define configMAX_PRIORITIES          ( 5 )
       定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
u #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
      定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
u #define INCLUDE_vTaskSuspend               1
      使用FreeRTOS的任务挂起函数vTaskSuspend和任务恢复函数vTaskResume必须配置此宏定义为1。
u #define INCLUDE_xTaskResumeFromISR   1
     默认情况下,用户只需配置了宏定义INCLUDE_vTaskSuspend为1就可以使用函数xTaskResumeFromISR,因为宏定义INCLUDE_xTaskResumeFromISR已经在FreeRTOS.h文件里面默认配置为1。这里我们为说明问题也将这个宏定义写出来了。
u configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
    定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    l 使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    l 对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为0到15,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
     l 这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。
更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
10.26.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
u  任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
    #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 17 * 1024 ) )
u  系统栈大小分配:
10.27.jpg

u  FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.     /* 启动调度,开始执行任务 */
  35.     vTaskStartScheduler();
  36.      /*
  37.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  38.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  39.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  40.      */
  41.      while(1);
  42. }
复制代码
u  硬件外设初始化
硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
  5. *             全局变量。
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_Init(void)
  11. {
  12.      /*
  13.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  14.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  15.          系统时钟缺省配置为72MHz,如果需要更改,可以修改 system_stm32f10x.c 文件
  16.      */
  17.    
  18.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  19.      bsp_InitUart();    /* 初始化串口 */
  20.      bsp_InitLed();     /* 初始LED指示灯端口 */
  21.      bsp_InitKey();     /* 初始化按键 */
  22.      bsp_InitHardTimer(); /* 初始化TIM2定时器 */
  23. }
复制代码
u  FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.    
  34.      xTaskCreate( vTaskStart,             /* 任务函数  */
  35.                  "vTaskStart",            /* 任务名    */
  36.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  37.                  NULL,                    /* 任务参数  */
  38.                  4,                       /* 任务优先级*/
  39.                  &xHandleTaskStart );   /* 任务句柄  */
  40. }
复制代码
u  四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      uint8_t ucKeyCode;
  13.      uint8_t pcWriteBuffer[500];
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下 打印任务执行情况 */
  23.                    case KEY_DOWN_K1:         
  24.                        printf("=================================================\\r\\n");
  25.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  26.                        vTaskList((char *)&pcWriteBuffer);
  27.                        printf("%s\\r\\n", pcWriteBuffer);
  28.                   
  29.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  30.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  31.                        printf("%s\\r\\n", pcWriteBuffer);
  32.                        break;
  33.                   
  34.                    /* K2键按下 删除任务vTaskLED */
  35.                    case KEY_DOWN_K2:         
  36.                        printf("K2键按下,删除任务vTaskLED\\r\\n");
  37.                        if(xHandleTaskLED != NULL)
  38.                        {
  39.                             vTaskDelete(xHandleTaskLED);
  40.                             xHandleTaskLED = NULL;
  41.                        }
  42.                        break;
  43.                   
  44.                    /* K3键按下 重新创建任务vTaskLED */
  45.                    case KEY_DOWN_K3:
  46.                        printf("K3键按下,重新创建任务vTaskLED\\r\\n");
  47.                        if(xHandleTaskLED == NULL)
  48.                        {
  49.                             xTaskCreate(    vTaskLED,            /* 任务函数  */
  50.                                                "vTaskLED",          /* 任务名    */
  51.                                                512,                 /* stack大小,单位word,也就是4字节 */
  52.                                                NULL,                /* 任务参数  */
  53.                                                2,                   /* 任务优先级*/
  54.                                                &xHandleTaskLED );   /* 任务句柄  */
  55.                        }
  56.                        break;
  57.                      
  58.                    /* 摇杆UP键按下,挂起任务vTaskLED */
  59.                    case JOY_DOWN_U:
  60.                        printf("摇杆UP键按下,挂起任务vTaskLED\\r\\n");
  61.                        vTaskSuspend(xHandleTaskLED);
  62.                        break;
  63.                   
  64.                    /* 摇杆DOWN键按下,恢复任务vTaskLED */
  65.                    case JOY_DOWN_D:
  66.                        printf("摇杆DOWN键按下,恢复任务vTaskLED\\r\\n");
  67.                        vTaskResume(xHandleTaskLED);
  68.                        break;
  69.                    /* 摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复 */
  70.                    case JOY_DOWN_OK:
  71.                       printf("摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复\\r\\n");
  72.                       bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack1);
  73.                       break;
  74.                   
  75.                    /* 其他的键值不处理 */
  76.                    default:                    
  77.                        break;
  78.               }
  79.          }
  80.         
  81.          vTaskDelay(20);
  82.      }
  83. }
  84. /*
  85. *********************************************************************************************************
  86. *    函 数 名: vTaskLED
  87. *    功能说明: LED闪烁
  88. *    形    参: pvParameters 是在创建该任务时传递的形参
  89. *    返 回 值: 无
  90. *   优 先 级: 2
  91. *********************************************************************************************************
  92. */
  93. static void vTaskLED(void *pvParameters)
  94. {
  95.     while(1)
  96.     {
  97.          bsp_LedToggle(2);
  98.         vTaskDelay(200);
  99.     }
  100. }
  101. /*
  102. *********************************************************************************************************
  103. *    函 数 名: vTaskMsgPro
  104. *    功能说明: 消息处理,这里是用作LED闪烁   
  105. *    形    参: pvParameters 是在创建该任务时传递的形参
  106. *    返 回 值: 无
  107. *   优 先 级: 3
  108. *********************************************************************************************************
  109. */
  110. static void vTaskMsgPro(void *pvParameters)
  111. {
  112.     while(1)
  113.     {
  114.          bsp_LedToggle(3);
  115.         vTaskDelay(300);
  116.     }
  117. }
  118. /*
  119. *********************************************************************************************************
  120. *    函 数 名: vTaskStart
  121. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  122. *    形    参: pvParameters 是在创建该任务时传递的形参
  123. *    返 回 值: 无
  124. *   优 先 级: 4
  125. *********************************************************************************************************
  126. */
  127. static void vTaskStart(void *pvParameters)
  128. {
  129.     while(1)
  130.     {
  131.          /* 按键扫描 */
  132.          bsp_KeyScan();
  133.         vTaskDelay(10);
  134.     }
  135. }
复制代码
u  定时器中断回调函数中将任务从挂起状态恢复:
    定时器中断的初始化和中断函数在bsp_timer.c 文件中实现,这个不是教程的重点,故不作介绍。 这里主要关心任务恢复函数xTaskResumeFromISR在中断服务程序中的使用方法。
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: TIM_CallBack1
  4. *    功能说明: 定时器中断的回调函数,此函数被bsp_StartHardTimer所调用。                        
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void TIM_CallBack1(void)
  10. {
  11.      BaseType_t xYieldRequired;
  12.     /* 恢复挂起任务 */
  13.      xYieldRequired = xTaskResumeFromISR(xHandleTaskLED);
  14.       /* 退出中断后是否需要执行任务切换 */
  15.      if( xYieldRequired == pdTRUE )
  16.      {
  17.          portYIELD_FROM_ISR(xYieldRequired);
  18.      }
  19. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 15:44:19 | 显示全部楼层
10.14.2   STM32F407开发板实验


配套例子:
    V5-304_FreeRTOS实验_任务恢复(中断方式)
实验目的:
    1.     学习FreeRTOS的任务恢复(中断方式)。
    2.     任务中的任务恢复函数调用的vTaskResume,而中断里面的任务恢复函数调用xTaskResumeFromISR,中断中调用的函数是以FromISR结尾的,实际应用中切不可混淆。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下,删除任务vTaskLED。
    3.     K3按键按下,重新创建任务vTaskLED。
    4.     摇杆UP按键按下,挂起任务vTaskLED。
    5.     摇杆DOWN键按下,恢复任务vTaskLED。
    6.     摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复。
    7.     各个任务实现的功能如下:
              vTaskUserIF任务   :按键消息处理。
              vTaskLED任务     :LED闪烁。
              vTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
              vTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. /* Ensure stdint is only used by the compiler, and not the assembler. */
  6. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  7. #include <stdint.h>
  8. extern volatile uint32_t ulHighFrequencyTimerTicks;
  9. #endif
  10. #define configUSE_PREEMPTION         1
  11. #define configUSE_IDLE_HOOK          0
  12. #define configUSE_TICK_HOOK          0
  13. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  14. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  15. #define configMAX_PRIORITIES         ( 5 )
  16. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  17. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  18. #define configMAX_TASK_NAME_LEN      ( 16 )
  19. #define configUSE_TRACE_FACILITY      1
  20. #define configUSE_16_BIT_TICKS       0
  21. #define configIDLE_SHOULD_YIELD      1
  22. /* Run time and task stats gathering related definitions. */
  23. #define configGENERATE_RUN_TIME_STATS                1
  24. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  25. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  26. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  27. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  28. /* Co-routine definitions. */
  29. #define configUSE_CO_ROUTINES             0
  30. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  31. /* Set the following definitions to 1 to include the API function, or zero
  32. to exclude the API function. */
  33. #define INCLUDE_vTaskPrioritySet          1
  34. #define INCLUDE_uxTaskPriorityGet         1
  35. #define INCLUDE_vTaskDelete               1
  36. #define INCLUDE_vTaskCleanUpResources      0
  37. #define INCLUDE_vTaskSuspend              1
  38. #define INCLUDE_xTaskResumeFromISR        1
  39. #define INCLUDE_vTaskDelayUntil           1
  40. #define INCLUDE_vTaskDelay                1
  41. /* Cortex-M specific definitions. */
  42. #ifdef __NVIC_PRIO_BITS
  43.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  44.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  45. #else
  46.      #define configPRIO_BITS              4        /* 15 priority levels */
  47. #endif
  48. /* The lowest interrupt priority that can be used in a call to a "set priority"
  49. function. */
  50. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  51. /* The highest interrupt priority that can be used by any interrupt service
  52. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  53. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  54. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  55. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
复制代码
几个重要选项说明:
u #define configUSE_PREEMPTION        1
        使能抢占式调度器
u #define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )  
        系统主频168MHz。
u #define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
         系统时钟节拍1KHz,即1ms。
u #define configMAX_PRIORITIES          ( 5 )
        定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
u #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
        定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
u #define INCLUDE_vTaskSuspend               1
        使用FreeRTOS的任务挂起函数vTaskSuspend和任务恢复函数vTaskResume必须配置此宏定义为1。
u #define INCLUDE_xTaskResumeFromISR   1
      默认情况下,用户只需配置了宏定义INCLUDE_vTaskSuspend为1就可以使用函数xTaskResumeFromISR,因为宏定义INCLUDE_xTaskResumeFromISR已经在FreeRTOS.h文件里面默认配置为1。这里我们为说明问题也将这个宏定义写出来了。
u configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
    定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    l 使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    l 对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为0到15,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
    l 这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。
更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
10.28.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
u  任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
      #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 30 * 1024 ) )
u  系统栈大小分配:
10.29.jpg

u  FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.     /* 启动调度,开始执行任务 */
  35.     vTaskStartScheduler();
  36.      /*
  37.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  38.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  39.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  40.      */
  41.      while(1);
  42. }
复制代码
u  硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  18.      bsp_InitUart();    /* 初始化串口 */
  19.      bsp_InitKey();     /* 初始化按键变量 */
  20.      bsp_InitLed();     /* 初始LED指示灯端口 */
  21. bsp_InitHardTimer(); /* 初始化TIM2定时器 */
  22. }
复制代码
u  FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.    
  34.      xTaskCreate( vTaskStart,             /* 任务函数  */
  35.                  "vTaskStart",            /* 任务名    */
  36.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  37.                  NULL,                    /* 任务参数  */
  38.                  4,                       /* 任务优先级*/
  39.                  &xHandleTaskStart );   /* 任务句柄  */
  40. }
复制代码
u  四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      uint8_t ucKeyCode;
  13.      uint8_t pcWriteBuffer[500];
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下 打印任务执行情况 */
  23.                    case KEY_DOWN_K1:         
  24.                        printf("=================================================\\r\\n");
  25.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  26.                        vTaskList((char *)&pcWriteBuffer);
  27.                        printf("%s\\r\\n", pcWriteBuffer);
  28.                   
  29.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  30.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  31.                        printf("%s\\r\\n", pcWriteBuffer);
  32.                        break;
  33.                   
  34.                    /* K2键按下 删除任务vTaskLED */
  35.                    case KEY_DOWN_K2:         
  36.                        printf("K2键按下,删除任务vTaskLED\\r\\n");
  37.                        if(xHandleTaskLED != NULL)
  38.                        {
  39.                             vTaskDelete(xHandleTaskLED);
  40.                             xHandleTaskLED = NULL;
  41.                        }
  42.                        break;
  43.                   
  44.                    /* K3键按下 重新创建任务vTaskLED */
  45.                    case KEY_DOWN_K3:
  46.                        printf("K3键按下,重新创建任务vTaskLED\\r\\n");
  47.                        if(xHandleTaskLED == NULL)
  48.                        {
  49.                             xTaskCreate(    vTaskLED,            /* 任务函数  */
  50.                                                "vTaskLED",          /* 任务名    */
  51.                                                512,                 /* stack大小,单位word,也就是4字节 */
  52.                                                NULL,                /* 任务参数  */
  53.                                                2,                   /* 任务优先级*/
  54.                                                &xHandleTaskLED );   /* 任务句柄  */
  55.                        }
  56.                        break;
  57.                      
  58.                    /* 摇杆UP键按下,挂起任务vTaskLED */
  59.                    case JOY_DOWN_U:
  60.                        printf("摇杆UP键按下,挂起任务vTaskLED\\r\\n");
  61.                        vTaskSuspend(xHandleTaskLED);
  62.                        break;
  63.                   
  64.                    /* 摇杆DOWN键按下,恢复任务vTaskLED */
  65.                    case JOY_DOWN_D:
  66.                        printf("摇杆DOWN键按下,恢复任务vTaskLED\\r\\n");
  67.                        vTaskResume(xHandleTaskLED);
  68.                        break;
  69.                   
  70.                    /* 摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复 */
  71.                    case JOY_DOWN_OK:
  72.                       printf("摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复\\r\\n");
  73.                       bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack1);
  74.                       break;
  75.                    /* 其他的键值不处理 */
  76.                    default:                    
  77.                        break;
  78.               }
  79.          }
  80.         
  81.          vTaskDelay(20);
  82.      }
  83. }
  84. /*
  85. *********************************************************************************************************
  86. *    函 数 名: vTaskLED
  87. *    功能说明: LED闪烁
  88. *    形    参: pvParameters 是在创建该任务时传递的形参
  89. *    返 回 值: 无
  90. *   优 先 级: 2
  91. *********************************************************************************************************
  92. */
  93. static void vTaskLED(void *pvParameters)
  94. {
  95.     while(1)
  96.     {
  97.          bsp_LedToggle(2);
  98.         vTaskDelay(200);
  99.     }
  100. }
  101. /*
  102. *********************************************************************************************************
  103. *    函 数 名: vTaskMsgPro
  104. *    功能说明: 消息处理,这里是用作LED闪烁   
  105. *    形    参: pvParameters 是在创建该任务时传递的形参
  106. *    返 回 值: 无
  107. *   优 先 级: 3
  108. *********************************************************************************************************
  109. */
  110. static void vTaskMsgPro(void *pvParameters)
  111. {
  112.     while(1)
  113.     {
  114.          bsp_LedToggle(3);
  115.         vTaskDelay(300);
  116.     }
  117. }
  118. /*
  119. *********************************************************************************************************
  120. *    函 数 名: vTaskStart
  121. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  122. *    形    参: pvParameters 是在创建该任务时传递的形参
  123. *    返 回 值: 无
  124. *   优 先 级: 4
  125. *********************************************************************************************************
  126. */
  127. static void vTaskStart(void *pvParameters)
  128. {
  129.     while(1)
  130.     {
  131.          /* 按键扫描 */
  132.          bsp_KeyScan();
  133.         vTaskDelay(10);
  134.     }
  135. }
复制代码
u  定时器中断回调函数中将任务从挂起状态恢复:
    定时器中断的初始化和中断函数在bsp_timer.c 文件中实现,这个不是教程的重点,故不作介绍。 这里主要关心任务恢复函数xTaskResumeFromISR在中断服务程序中的使用方法。
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: TIM_CallBack1
  4. *    功能说明: 定时器中断的回调函数,此函数被bsp_StartHardTimer所调用。                        
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void TIM_CallBack1(void)
  10. {
  11.      BaseType_t xYieldRequired;
  12.     /* 恢复挂起任务 */
  13.      xYieldRequired = xTaskResumeFromISR(xHandleTaskLED);
  14.       /* 退出中断后是否需要执行任务切换 */
  15.      if( xYieldRequired == pdTRUE )
  16.      {
  17.          portYIELD_FROM_ISR(xYieldRequired);
  18.      }
  19. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 15:48:47 | 显示全部楼层
10.14.3 STM32F429开发板实验


配套例子:
    V6-304_FreeRTOS实验_任务恢复(中断方式)
实验目的:
    1.     学习FreeRTOS的任务恢复(中断方式)。
    2.     任务中的任务恢复函数调用的vTaskResume,而中断里面的任务恢复函数调用xTaskResumeFromISR,中断中调用的函数是以FromISR结尾的,实际应用中切不可混淆。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下,删除任务vTaskLED。
    3.     K3按键按下,重新创建任务vTaskLED。
    4.     摇杆UP按键按下,挂起任务vTaskLED。
    5.     摇杆DOWN键按下,恢复任务vTaskLED。
    6.     摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复。
    7.     各个任务实现的功能如下:
              vTaskUserIF任务   :按键消息处理。
              vTaskLED任务     :LED闪烁。
              vTaskMsgPro任务 :消息处理,这里是用作LED闪烁。
              vTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
     FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. #endif
  6. #define configUSE_PREEMPTION         1
  7. #define configUSE_IDLE_HOOK          0
  8. #define configUSE_TICK_HOOK          0
  9. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  10. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  11. #define configMAX_PRIORITIES         ( 5 )
  12. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  13. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  14. #define configMAX_TASK_NAME_LEN      ( 16 )
  15. #define configUSE_TRACE_FACILITY      1
  16. #define configUSE_16_BIT_TICKS       0
  17. #define configIDLE_SHOULD_YIELD      1
  18. /* Run time and task stats gathering related definitions. */
  19. #define configGENERATE_RUN_TIME_STATS                1
  20. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  21. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  22. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  23. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  24. /* Co-routine definitions. */
  25. #define configUSE_CO_ROUTINES            0
  26. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  27. /* Set the following definitions to 1 to include the API function, or zero
  28. to exclude the API function. */
  29. #define INCLUDE_vTaskPrioritySet          1
  30. #define INCLUDE_uxTaskPriorityGet         1
  31. #define INCLUDE_vTaskDelete               1
  32. #define INCLUDE_vTaskCleanUpResources      0
  33. #define INCLUDE_vTaskSuspend              1
  34. #define INCLUDE_xTaskResumeFromISR        1
  35. #define INCLUDE_vTaskDelayUntil           1
  36. #define INCLUDE_vTaskDelay                1
  37. /* Cortex-M specific definitions. */
  38. #ifdef __NVIC_PRIO_BITS
  39.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  40.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  41. #else
  42.      #define configPRIO_BITS              4        /* 15 priority levels */
  43. #endif
  44. /* The lowest interrupt priority that can be used in a call to a "set priority"
  45. function. */
  46. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  47. /* The highest interrupt priority that can be used by any interrupt service
  48. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  49. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  50. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  51. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY         0x01
复制代码
几个重要选项说明:
u #define configUSE_PREEMPTION        1
        使能抢占式调度器
u #define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )  
       系统主频168MHz。
u #define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
        系统时钟节拍1KHz,即1ms。
u #define configMAX_PRIORITIES          ( 5 )
          定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
u #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
          定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
u #define INCLUDE_vTaskSuspend               1
         使用FreeRTOS的任务挂起函数vTaskSuspend和任务恢复函数vTaskResume必须配置此宏定义为1。
u #define INCLUDE_xTaskResumeFromISR   1
         默认情况下,用户只需配置了宏定义INCLUDE_vTaskSuspend为1就可以使用函数xTaskResumeFromISR,因为宏定义INCLUDE_xTaskResumeFromISR已经在FreeRTOS.h文件里面默认配置为1。这里我们为说明问题也将这个宏定义写出来了。
u configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
    定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    l 使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    l 对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为0到15,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
    l 这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY为0x01表示用户可以在抢占式优先级为1到15的中断里面调用FreeRTOS的API函数,抢占式优先级为0的中断里面是不允许调用的。
更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
10.30.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
     #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
     #definetskREADY_CHAR           ( 'R' ) 任务就绪
     #definetskDELETED_CHAR           ( 'D' )  任务删除
     #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
u  任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
      #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 30 * 1024 ) )
u  系统栈大小分配:
10.31.jpg

u  FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.     /* 启动调度,开始执行任务 */
  35.     vTaskStartScheduler();
  36.      /*
  37.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  38.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  39.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  40.      */
  41.      while(1);
  42. }
复制代码
u  硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  18.    
  19.      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */
  20.      bsp_InitUart();    /* 初始化串口 */
  21.      bsp_InitKey();     /* 初始化按键变量 */
  22.      bsp_InitExtIO();   /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */
  23.      bsp_InitLed();     /* 初始LED指示灯端口 */
  24. bsp_InitHardTimer(); /* 初始化TIM2定时器 */
  25. }
复制代码
u  FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.    
  34.      xTaskCreate( vTaskStart,             /* 任务函数  */
  35.                  "vTaskStart",            /* 任务名    */
  36.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  37.                  NULL,                    /* 任务参数  */
  38.                  4,                       /* 任务优先级*/
  39.                  &xHandleTaskStart );   /* 任务句柄  */
  40. }
复制代码
u  四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      uint8_t ucKeyCode;
  13.      uint8_t pcWriteBuffer[500];
  14.     while(1)
  15.     {
  16.          ucKeyCode = bsp_GetKey();
  17.         
  18.          if (ucKeyCode != KEY_NONE)
  19.          {
  20.               switch (ucKeyCode)
  21.               {
  22.                    /* K1键按下 打印任务执行情况 */
  23.                    case KEY_DOWN_K1:         
  24.                        printf("=================================================\\r\\n");
  25.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  26.                        vTaskList((char *)&pcWriteBuffer);
  27.                        printf("%s\\r\\n", pcWriteBuffer);
  28.                   
  29.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  30.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  31.                        printf("%s\\r\\n", pcWriteBuffer);
  32.                        break;
  33.                   
  34.                    /* K2键按下 删除任务vTaskLED */
  35.                    case KEY_DOWN_K2:         
  36.                        printf("K2键按下,删除任务vTaskLED\\r\\n");
  37.                        if(xHandleTaskLED != NULL)
  38.                        {
  39.                             vTaskDelete(xHandleTaskLED);
  40.                             xHandleTaskLED = NULL;
  41.                        }
  42.                        break;
  43.                   
  44.                    /* K3键按下 重新创建任务vTaskLED */
  45.                    case KEY_DOWN_K3:
  46.                        printf("K3键按下,重新创建任务vTaskLED\\r\\n");
  47.                        if(xHandleTaskLED == NULL)
  48.                        {
  49.                             xTaskCreate(    vTaskLED,            /* 任务函数  */
  50.                                                "vTaskLED",          /* 任务名    */
  51.                                                512,                 /* stack大小,单位word,也就是4字节 */
  52.                                                NULL,                /* 任务参数  */
  53.                                                2,                   /* 任务优先级*/
  54.                                                &xHandleTaskLED );   /* 任务句柄  */
  55.                        }
  56.                        break;
  57.                      
  58.                    /* 摇杆UP键按下,挂起任务vTaskLED */
  59.                    case JOY_DOWN_U:
  60.                        printf("摇杆UP键按下,挂起任务vTaskLED\\r\\n");
  61.                        vTaskSuspend(xHandleTaskLED);
  62.                        break;
  63.                   
  64.                    /* 摇杆DOWN键按下,恢复任务vTaskLED */
  65.                    case JOY_DOWN_D:
  66.                        printf("摇杆DOWN键按下,恢复任务vTaskLED\\r\\n");
  67.                        vTaskResume(xHandleTaskLED);
  68.                        break;
  69.                   
  70.                    /* 摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复 */
  71.                    case JOY_DOWN_OK:
  72.                       printf("摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复\\r\\n");
  73.                       bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack1);
  74.                       break;
  75.                    /* 其他的键值不处理 */
  76.                    default:                    
  77.                        break;
  78.               }
  79.          }
  80.         
  81.          vTaskDelay(20);
  82.      }
  83. }
  84. /*
  85. *********************************************************************************************************
  86. *    函 数 名: vTaskLED
  87. *    功能说明: LED闪烁
  88. *    形    参: pvParameters 是在创建该任务时传递的形参
  89. *    返 回 值: 无
  90. *   优 先 级: 2
  91. *********************************************************************************************************
  92. */
  93. static void vTaskLED(void *pvParameters)
  94. {
  95.     while(1)
  96.     {
  97.          bsp_LedToggle(2);
  98.         vTaskDelay(200);
  99.     }
  100. }
  101. /*
  102. *********************************************************************************************************
  103. *    函 数 名: vTaskMsgPro
  104. *    功能说明: 消息处理,这里是用作LED闪烁   
  105. *    形    参: pvParameters 是在创建该任务时传递的形参
  106. *    返 回 值: 无
  107. *   优 先 级: 3
  108. *********************************************************************************************************
  109. */
  110. static void vTaskMsgPro(void *pvParameters)
  111. {
  112.     while(1)
  113.     {
  114.          bsp_LedToggle(3);
  115.         vTaskDelay(300);
  116.     }
  117. }
  118. /*
  119. *********************************************************************************************************
  120. *    函 数 名: vTaskStart
  121. *    功能说明: 启动任务,也就是最高优先级任务,这里用作按键扫描。
  122. *    形    参: pvParameters 是在创建该任务时传递的形参
  123. *    返 回 值: 无
  124. *   优 先 级: 4
  125. *********************************************************************************************************
  126. */
  127. static void vTaskStart(void *pvParameters)
  128. {
  129.     while(1)
  130.     {
  131.          /* 按键扫描 */
  132.          bsp_KeyScan();
  133.         vTaskDelay(10);
  134.     }
  135. }
复制代码
u  定时器中断回调函数中将任务从挂起状态恢复:
    定时器中断的初始化和中断函数在bsp_timer.c 文件中实现,这个不是教程的重点,故不作介绍。 这里主要关心任务恢复函数xTaskResumeFromISR在中断服务程序中的使用方法。
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: TIM_CallBack1
  4. *    功能说明: 定时器中断的回调函数,此函数被bsp_StartHardTimer所调用。                        
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void TIM_CallBack1(void)
  10. {
  11.      BaseType_t xYieldRequired;
  12.     /* 恢复挂起任务 */
  13.      xYieldRequired = xTaskResumeFromISR(xHandleTaskLED);
  14.       /* 退出中断后是否需要执行任务切换 */
  15.      if( xYieldRequired == pdTRUE )
  16.      {
  17.          portYIELD_FROM_ISR(xYieldRequired);
  18.      }
  19. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-18 15:49:27 | 显示全部楼层
10.15 总结

     本章节主要为大家讲解了FreeRTOS的任务管理,此章节比较重要,望初学者用心掌握。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-14 19:52 , Processed in 0.278529 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表