你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【安富莱】【RTX操作系统教程】第21章 RTX低功耗之睡眠...

[复制链接]
baiyongbin2009 发布时间:2016-2-4 16:45
本帖最后由 baiyongbin2009 于 2016-2-18 15:27 编辑

完整PDF教程和例子下载:https://pan.baidu.com/s/1c0V2Why


【安富莱】【RTX操作系统教程】 【RTX操作系统教程】第21ç«  RTX低功耗之睡眠模式.pdf (677.63 KB, 下载次数: 14)

收藏 评论9 发布时间:2016-2-4 16:45

举报

9个回答
baiyongbin2009 回答时间:2016-2-4 16:50:02
21.2 STM32F407睡眠模式介绍
    说明:在RTX系统上面实现睡眠方式仅需了解这里讲解的知识基本就够用了,更多睡眠方式的知识请看STM32F407参考手册和Cortex-M4权威指南。
    默认情况下,系统复位或上电复位后,微控制器进入运行模式。在运行模式下,CPU通过HCLK 提供时钟,并执行程序代码。系统提供了多个低功耗模式,可在CPU不需要运行时(例如等待外部事件时)节省功耗。由用户根据应用选择具体的低功耗模式,以在低功耗、短启动时间和可用唤醒源之间寻求最佳平衡。STM32F407有三个低功耗模式:
(1)睡眠模式(Cortex™-M4F 内核停止,外设保持运行)
(2)停止模式(所有时钟都停止)
(3)待机模式(1.2 V 域断电)
    本章节我们主要讲解睡眠模式,而在实际的休眠模式编程时我需要清楚那些问题呢?请继续往下看。

21.2.1 如何进入睡眠模式
    执行 WFI(等待中断)或WFE(等待事件)指令即可进入睡眠模式。根据 Cortex™-M4F 系统控制寄存器中SLEEPONEXIT 位的设置,可以通过两种方案选择睡眠模式进入机制:
(1)立即休眠:如果SLEEPONEXIT 位清零, MCU将在执行WFI或WFE指令时立即进入睡眠模式。
(2)退出时休眠:如果SLEEPONEXIT位置1,MCU将在退出优先级最低的ISR时立即进入睡眠模式。
    小结:本章节配套的休眠例子我们采用WFI指令进入睡眠模式,睡眠模式的进入机制是采用的立即休眠。因为系统复位上电后SLEEPONEXIT位是被清除的,所有这个位也不需要专门的去设置。另外在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。
    在RTX系统上,我们可以将WFI指令放到空闲任务里面实现。

21.2.2 如何退出睡眠模式
    由于我们是采用指令WFI进入睡眠模式,那么任意一个被嵌套向量中断控制器NVIC响应的外设中断都能将系统从睡眠模式唤醒。并且该模式唤醒所需的时间最短,因为没有时间损失在中断的进入或退出上。
    在RTX系统上,主要是周期性执行的系统滴答定时器中断会将系统从睡眠态唤醒,当然,其它的任意中断也可以将其从休眠态唤醒。

baiyongbin2009 回答时间:2016-2-4 16:53:10
21.3 低功耗模式的调试支持
    使用WFI和WFE可以进入低功耗模式。
    MCU支持多种低功耗模式,分别可以关闭CPU时钟,或降低CPU的能耗。内核不允许在调试期间关闭FCLK或HCLK。这些时钟对于调试操作是必要的,因此在调试期间,它们必须工作。MCU使用一种特殊的方式,允许用户在低功耗模式下调试代码。为实现这一功能,调试器必须先设置一些配置寄存器来改变低功耗模式的特性。
(1)在睡眠模式下,调试器必须先置位DBGMCU_CR寄存器的DBG_SLEEP位。这将为HCLK提供与FCLK(由代码配置的系统时钟)相同的时钟。
      调用库函数:DBGMCU_Config(DBGMCU_SLEEP, ENABLE);即可
(2)停止模式下,调试器必须先置位DBG_STOP位。这将激活内部RC振荡器,在停止模式下为FCLK和HCLK。
      调用库函数:DBGMCU_Config(DBGMCU_STOP, ENABLE);即可

baiyongbin2009 回答时间:2016-2-4 16:55:25
21.4 如何有效降低休眠模式下的功耗
设计低功耗主要从以下几方面着手:
    1.  关闭可以关闭的外设时钟。
    2.  降低系统主频。
    3.  注意I/O的状态,因为休眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。
       (1)如果此I/O口带上拉,请设置为高电平输出或者高阻态输入。
       (2)如果此I/O口带下拉,请设置为低电平输出或者高阻态输入。
    4.  注意I/O和外设IC的连接。
    5.  测试低功耗的时候,一定不要连接调试器,更不能边调试边测电流。

baiyongbin2009 回答时间:2016-2-4 17:16:52
21.5 实验例程说明
21.5.1 STM32F103开发板实验
配套例子:
    V4-421_RTX实验_低功耗(睡眠模式)
实验目的:
    1.     学习RTX实验低功耗(睡眠模式)。
    2.     通过函数DBGMCU_Config(DBGMCU_SLEEP,ENABLE);保证睡眠模式下调试器正常连接使用。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro。
      任务AppTaskMsgPro接收到消息后进行消息处理。
    3.各个任务实现的功能如下:
    AppTaskUserIF任务   :按键消息处理。  
    AppTaskLED任务     :LED闪烁。
    AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的信号量同步信号。
    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    4.关于低功耗的说明:
      (1) STM32F10x有三种低功耗模式:
      a.睡眠模式(Cortex-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行)
      b.停止模式(所有的时钟都已停止)
      c.待机模式(1.8V电源关闭)
      (2) 通过指令__WFI进入休眠模式,可以通过任意中断唤醒。
      (3) 降低系统主频或者关闭外设时钟也可有效降低系统功耗。
      (4) 进入低功耗状态前,设置使用的I/O引脚不产生拉电流和灌电流也可有效降低功耗。
    5. 本例程的低功耗实现方法是在空闲任务中调用__WFI指令来进入低功耗模式。未做关闭外设时钟和设置I/O引脚处理。在文件RTX_Conf_CM.C文件中的函数os_idle_demon里面调用函数__WFI。
    6.实际项目中推荐采用官方的tickless模式。
设计低功耗主要从以下几个方面着手:
    1.     用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式可以使用的低功耗方式有休眠模式,待机模式,停机模式。
    2.     选择了低功耗方式后就是关闭可以关闭的外设时钟。
    3.     降低系统主频。
    4.     注意I/O的状态。
     如果此I/O口带上拉,请设置为高电平输出或者高阻态输入;
     如果此I/O口带下拉,请设置为低电平输出或者高阻态输入;  
     a.在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。
     b.在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。
     c.在待机模式下,所有的I/O引脚处于高阻态,除了以下的引脚:
      ● 复位引脚(始终有效)
      ● 当被设置为防侵入或校准输出时的TAMPER引脚
      ● 被使能的唤醒引脚
    5.注意I/O和外设IC的连接。
    6.测低功耗的时候,一定不要连接调试器,更不能边调试边测电流。
RTX配置:
    RTX配置向导详情如下:
                              
21.1.png
Task Configuration
    Number of concurrent running tasks
      允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。

RTX任务调试信息:
    在休眠模式下,无法动态的查看任务的调试信息。下面的是单步调试时状态查看:
21.2.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈*/
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
    任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
21.3.png
外设初始化:
    注意新加的函数初始化函数DBGMCU_Config(DBGMCU_SLEEP, ENABLE);保证睡眠模式下调试器正常连接使用。
  1. /*
  2. /*
  3. *********************************************************************************************************
  4. *        函 数 名: bsp_Init
  5. *        功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
  6. *                         全局变量。
  7. *        形    参: 无
  8. *        返 回 值: 无
  9. *********************************************************************************************************
  10. */
  11. void bsp_Init(void)
  12. {
  13.         /* 保证睡眠模式下调试器继续可以连接使用 */
  14.         DBGMCU_Config(DBGMCU_SLEEP, ENABLE);
  15.        
  16.         /* 优先级分组设置为4, 优先配置好NVIC */
  17.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

  18.         bsp_InitUart();         /* 初始化串口 */
  19.         bsp_InitLed();                 /* 初始LED指示灯端口 */
  20.         bsp_InitKey();                /* 初始化按键 */
  21. }
复制代码

RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码

RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码

睡眠模式在空闲任务实现,即配置向导文件RTX_Conf_CM.c文件中
  1. /*--------------------------- os_idle_demon ---------------------------------*/
  2. #include "stm32f10x.h"
  3. __task void os_idle_demon (void) {
  4.   /* The idle demon is a system task, running when no other task is ready */
  5.   /* to run. The 'os_xxx' function calls are not allowed from this task.  */

  6.   for (;;) {
  7.   /* HERE: include optional user code to be executed when no task runs.*/
  8.        __WFI();
  9.   }
  10. }
复制代码

信号量的创建:
  1. static OS_SEM semaphore;

  2. /*
  3. *********************************************************************************************************
  4. *    函 数 名: AppObjCreate
  5. *    功能说明: 创建任务通信机制
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. static void AppObjCreate (void)
  11. {
  12.      /* 创建信号量计数值是0, 用于任务同步 */
  13.      os_sem_init (&semaphore, 0);
  14. }
复制代码

四个RTX任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskUserIF
  4. *    功能说明: 按键消息处理     
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. __task void AppTaskUserIF(void)
  11. {
  12.      uint8_t ucKeyCode;

  13.     while(1)
  14.     {
  15.          ucKeyCode = bsp_GetKey();
  16.         
  17.          if (ucKeyCode != KEY_NONE)
  18.          {
  19.               switch (ucKeyCode)
  20.               {
  21.                    /* K1键按下,打印调试说明 */
  22.                    case KEY_DOWN_K1:
  23.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");
  24.                        break;  

  25.                    /* K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro */
  26.                    case KEY_DOWN_K2:
  27.                        printf("K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro\r\n");
  28.                        os_sem_send (&semaphore);
  29.                        break;

  30.                    /* 其他的键值不处理 */
  31.                    default:                    
  32.                        break;
  33.               }
  34.          }
  35.         
  36.          os_dly_wait(20);
  37.      }
  38. }

  39. /*
  40. *********************************************************************************************************
  41. *    函 数 名: AppTaskLED
  42. *    功能说明: LED闪烁。
  43. *    形    参: 无
  44. *    返 回 值: 无
  45. *   优 先 级: 2
  46. *********************************************************************************************************
  47. */
  48. __task void AppTaskLED(void)
  49. {
  50.      const uint16_t usFrequency = 200; /* 延迟周期 */
  51.    
  52.      /* 设置延迟周期 */
  53.      os_itv_set(usFrequency);
  54.    
  55.     while(1)
  56.     {
  57.          bsp_LedToggle(2);
  58.          bsp_LedToggle(3);

  59.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  60.           os_itv_wait();
  61.     }
  62. }

  63. /*
  64. *********************************************************************************************************
  65. *    函 数 名: AppTaskMsgPro
  66. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的信号量同步信号
  67. *    形    参: 无
  68. *    返 回 值: 无
  69. *   优 先 级: 3
  70. *********************************************************************************************************
  71. */
  72. __task void AppTaskMsgPro(void)
  73. {
  74.      OS_RESULT xResult;
  75.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
  76.    
  77.     while(1)
  78.     {
  79.          xResult = os_sem_wait (&semaphore, usMaxBlockTime);
  80.         
  81.          switch (xResult)
  82.          {
  83.               /* 无需等待接受到信号量同步信号 */
  84.               case OS_R_OK:
  85.                    printf("无需等待接受到信号量同步信号\r\n");
  86.                    break;  

  87.               /* 信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号 */
  88.               case OS_R_SEM:
  89.                    printf("信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号\r\n");
  90.                    break;

  91.               /* 超时 */
  92.               case OS_R_TMO:
  93.                    bsp_LedToggle(1);
  94.                    bsp_LedToggle(4);
  95.                    break;
  96.             
  97.               /* 其他值不处理 */
  98.               default:                    
  99.                    break;
  100.          }   
  101.     }
  102. }

  103. /*
  104. *********************************************************************************************************
  105. *    函 数 名: AppTaskStart
  106. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
  107. *    形    参: 无
  108. *    返 回 值: 无
  109. *   优 先 级: 4
  110. *********************************************************************************************************
  111. */
  112. __task void AppTaskStart(void)
  113. {
  114.      /* 创建任务 */
  115.      AppTaskCreate();
  116.    
  117.      /* 创建任务通信机制 */
  118.      AppObjCreate();
  119.    
  120.     while(1)
  121.     {
  122.          /* 按键扫描 */
  123.          bsp_KeyScan();
  124.         os_dly_wait(10);
  125.     }
  126. }
复制代码


baiyongbin2009 回答时间:2016-2-4 17:23:24
21.5.2   STM32F407开发板实验
配套例子:
    V5-421_RTX实验_低功耗(睡眠模式)
实验目的:
    1.     学习RTX实验低功耗(睡眠模式)。
    2.     通过函数DBGMCU_Config(DBGMCU_SLEEP,ENABLE);保证睡眠模式下调试器正常连接使用。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro。
     任务AppTaskMsgPro接收到消息后进行消息处理。
    3.各个任务实现的功能如下:
    AppTaskUserIF任务   :按键消息处理。
    AppTaskLED任务     :LED闪烁。
    AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的信号量同步信号。
    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    4.关于低功耗的说明:
       (1) STM32F407有三种低功耗模式:
     a.睡眠模式(Cortex-M4F内核停止,所有外设包括Cortex-M4F核心的外设,如NVIC、系统时钟(SysTick)等仍在运行)。
     b.停止模式(所有的时钟都已停止)。
     c.待机模式(1.2V电源关闭)。
       (2) 通过指令__WFI进入休眠模式,可以通过任意中断唤醒。
       (3) 降低系统主频或者关闭外设时钟也可有效降低系统功耗。
       (4) 进入低功耗状态前,设置使用的I/O引脚不产生拉电流和灌电流也可有效降低功耗。
    5.本例程的低功耗实现方法是在空闲任务中调用__WFI指令来进入低功耗模式。未做关闭外设时钟和设置I/O引脚处理。在文件RTX_Conf_CM.C文件中的函数os_idle_demon里面调用函数__WFI。
    6.实际项目中推荐采用官方的tickless模式。
设计低功耗主要从以下几个方面着手:
    1.     用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式可以使用的低功耗方式有休眠模式,待机模式,停机模式。
    2.     选择了低功耗方式后就是关闭可以关闭的外设时钟。
    3.     降低系统主频。
    4.     注意I/O的状态。
    如果此I/O口带上拉,请设置为高电平输出或者高阻态输入;
    如果此I/O口带下拉,请设置为低电平输出或者高阻态输入;
       a.在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。
       b.在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。
       c.在待机模式下,所有的I/O引脚处于高阻态,除了以下的引脚:
            ● 复位引脚(仍可用)。
            ● RTC_AF1引脚 (PC13)(如果针对入侵、时间戳、RTC闹钟输出或RTC时钟校准输出进行了配置)。
            ● WKUP引脚 (PA0)(如果使能)。
    5.注意I/O和外设IC的连接。
    6.测低功耗的时候,一定不要连接调试器,更不能边调试边测电流。
RTX配置:
    RTX配置向导详情如下:
21.4.png
                              
Task Configuration
    Number of concurrent running tasks
        允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
    Run in privileged mode
  设置任务运行在非特权级模式

RTX任务调试信息:
21.5.png
程序设计:
任务栈大小分配:
staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈*/
staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
21.6.png
外设初始化:
    注意新加的函数初始化函数DBGMCU_Config(DBGMCU_SLEEP, ENABLE);保证睡眠模式下调试器正常连接使用。
  1. /*
  2. /*
  3. *********************************************************************************************************
  4. *    函 数 名: bsp_Init
  5. *    功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
  6. *             全局变量。
  7. *    形    参: 无
  8. *    返 回 值: 无
  9. *********************************************************************************************************
  10. */
  11. void bsp_Init(void)
  12. {
  13.      /* 保证睡眠模式下调试器继续可以连接使用 */
  14.      DBGMCU_Config(DBGMCU_SLEEP, ENABLE);
  15.    
  16.      /* 优先级分组设置为4, 优先配置好NVIC */
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

  18.      bsp_InitUart();    /* 初始化串口 */
  19.      bsp_InitLed();         /* 初始LED指示灯端口 */
  20.      bsp_InitKey();         /* 初始化按键 */
  21. }
复制代码

RTX初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.    
  14.      /* 创建启动任务 */
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
  16.                        4,                        /* 任务优先级 */
  17.                        &AppTaskStartStk,         /* 任务栈 */
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
  19.      while(1);
  20. }
复制代码

RTX任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
  12.                                            1,                         /* 任务优先级 */
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
  15.    
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
  17.                                         2,                       /* 任务优先级 */
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
  20.    
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
  22.                                            3,                         /* 任务优先级 */
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
  25. }
复制代码

睡眠模式在空闲任务实现,即配置向导文件RTX_Conf_CM.c文件中
  1. /*--------------------------- os_idle_demon ---------------------------------*/
  2. #include "stm32f10x.h"
  3. __task void os_idle_demon (void) {
  4.   /* The idle demon is a system task, running when no other task is ready */
  5.   /* to run. The 'os_xxx' function calls are not allowed from this task.  */

  6.   for (;;) {
  7.   /* HERE: include optional user code to be executed when no task runs.*/
  8.        __WFI();
  9.   }
  10. }
复制代码

信号量的创建:
  1. static OS_SEM semaphore;

  2. /*
  3. *********************************************************************************************************
  4. *    函 数 名: AppObjCreate
  5. *    功能说明: 创建任务通信机制
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. static void AppObjCreate (void)
  11. {
  12.      /* 创建信号量计数值是0, 用于任务同步 */
  13.      os_sem_init (&semaphore, 0);
  14. }
复制代码

四个RTX任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskUserIF
  4. *    功能说明: 按键消息处理     
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. __task void AppTaskUserIF(void)
  11. {
  12.      uint8_t ucKeyCode;

  13.     while(1)
  14.     {
  15.          ucKeyCode = bsp_GetKey();
  16.         
  17.          if (ucKeyCode != KEY_NONE)
  18.          {
  19.               switch (ucKeyCode)
  20.               {
  21.                    /* K1键按下,打印调试说明 */
  22.                    case KEY_DOWN_K1:
  23.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");
  24.                        break;  

  25.                    /* K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro */
  26.                    case KEY_DOWN_K2:
  27.                        printf("K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro\r\n");
  28.                        os_sem_send (&semaphore);
  29.                        break;

  30.                    /* 其他的键值不处理 */
  31.                    default:                    
  32.                        break;
  33.               }
  34.          }
  35.         
  36.          os_dly_wait(20);
  37.      }
  38. }

  39. /*
  40. *********************************************************************************************************
  41. *    函 数 名: AppTaskLED
  42. *    功能说明: LED闪烁。
  43. *    形    参: 无
  44. *    返 回 值: 无
  45. *   优 先 级: 2
  46. *********************************************************************************************************
  47. */
  48. __task void AppTaskLED(void)
  49. {
  50.      const uint16_t usFrequency = 200; /* 延迟周期 */
  51.    
  52.      /* 设置延迟周期 */
  53.      os_itv_set(usFrequency);
  54.    
  55.     while(1)
  56.     {
  57.          bsp_LedToggle(2);
  58.          bsp_LedToggle(3);

  59.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
  60.          os_itv_wait();
  61.     }
  62. }

  63. /*
  64. *********************************************************************************************************
  65. *    函 数 名: AppTaskMsgPro
  66. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的信号量同步信号
  67. *    形    参: 无
  68. *    返 回 值: 无
  69. *   优 先 级: 3
  70. *********************************************************************************************************
  71. */
  72. __task void AppTaskMsgPro(void)
  73. {
  74.      OS_RESULT xResult;
  75.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
  76.    
  77.     while(1)
  78.     {
  79.          xResult = os_sem_wait (&semaphore, usMaxBlockTime);
  80.         
  81.          switch (xResult)
  82.          {
  83.               /* 无需等待接受到信号量同步信号 */
  84.               case OS_R_OK:
  85.                    printf("无需等待接受到信号量同步信号\r\n");
  86.                    break;  

  87.               /* 信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号 */
  88.               case OS_R_SEM:
  89.                    printf("信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号\r\n");
  90.                    break;

  91.               /* 超时 */
  92.               case OS_R_TMO:
  93.                    bsp_LedToggle(1);
  94.                    bsp_LedToggle(4);
  95.                    break;
  96.             
  97.               /* 其他值不处理 */
  98.               default:                    
  99.                    break;
  100.          }   
  101.     }
  102. }

  103. /*
  104. *********************************************************************************************************
  105. *    函 数 名: AppTaskStart
  106. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
  107. *    形    参: 无
  108. *    返 回 值: 无
  109. *   优 先 级: 4
  110. *********************************************************************************************************
  111. */
  112. __task void AppTaskStart(void)
  113. {
  114.      /* 创建任务 */
  115.      AppTaskCreate();
  116.    
  117.      /* 创建任务通信机制 */
  118.      AppObjCreate();
  119.    
  120.     while(1)
  121.     {
  122.          /* 按键扫描 */
  123.          bsp_KeyScan();
  124.         os_dly_wait(10);
  125.     }
  126. }
复制代码


baiyongbin2009 回答时间:2016-2-4 17:24:21
21.6 总结
    本章节主要为大家讲解了RTX低功耗之睡眠模式,这里仅是提供了一种睡眠模式在RTX上的实现思路,有兴趣的同学也可以想一些其它的实现思路。

肽宰1 回答时间:2016-2-8 20:42:26
新年快乐,恭喜发财
feixiang20 回答时间:2018-1-15 20:54:45
可真有耐心,谢谢了
liangxin-129065 回答时间:2018-2-6 15:22:09
谢谢分享

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版