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

【安富莱】【RTX操作系统教程】第24章 RTX低功耗之tickles...

[复制链接]
baiyongbin2009 发布时间:2016-2-17 15:53
本帖最后由 baiyongbin2009 于 2016-2-18 15:25 编辑

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

第24章     RTX低功耗之tickless模式: 【RTX操作系统教程】第24ç«  RTX低功耗之tickless模式.pdf (776.74 KB, 下载次数: 9)
收藏 评论3 发布时间:2016-2-17 15:53

举报

3个回答
baiyongbin2009 回答时间:2016-2-17 16:29:57
24.4 实验例程说明
24.4.1 STM32F103开发板实验
配套例子:
    V4-424_RTX实验_低功耗(tickless模式)
实验目的:
    1.     学习RTX的低功耗(tickless模式)。
    2.     tickless模式低功耗的实现采用了停机模式,使用RTC的闹钟中断进行唤醒
    3.     tickless模式的实现在源文件RTX_Conf_CM.C文件中的空闲任务os_idle_demon函数里面。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro。
      任务AppTaskMsgPro接收到消息后进行消息处理。
    3.各个任务实现的功能如下:
    AppTaskUserIF任务   :按键消息处理。
    AppTaskLED任务     :LED闪烁。
    AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的信号量同步信号。
    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
设计低功耗主要从以下几个方面着手:
    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配置向导详情如下:
                              
24.2.png
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
        Number of tasks with user-provided stack
创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
    在休眠模式下,无法动态的查看任务的调试信息。下面的是单步调试时状态查看:
24.3.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类型数据运算会出问题。
系统栈大小分配:
24.4.png
外设初始化:
    注意新加的函数初始化函数DBGMCU_Config(DBGMCU_STOP, ENABLE);保证停机模式下调试器正常连接使用。
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
  5. *             全局变量。
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_Init(void)
  11. {
  12.      /* 保证停机模式下调试器继续可以连接使用 */
  13.      DBGMCU_Config(DBGMCU_STOP, ENABLE);
  14.    
  15.      /* 优先级分组设置为4, 优先配置好NVIC */
  16.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

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

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. }
复制代码

tickless模式在空闲任务实现,即配置向导文件RTX_Conf_CM.c文件中
  1. /*--------------------------- os_idle_demon ---------------------------------*/
  2. #include "stm32f10x.h"
  3. __task void os_idle_demon (void)
  4. {
  5.      EXTI_InitTypeDef  EXTI_InitStructure;
  6.      NVIC_InitTypeDef NVIC_InitStructure;
  7.      uint32_t sleep;
  8.    
  9.      /* 使能PWR和BKP时钟 */
  10.      RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  11.      /* 允许写入RTC和后备寄存器 */
  12.      PWR_BackupAccessCmd(ENABLE);

  13.      /* 复位后备寄存器 */
  14.      BKP_DeInit();

  15.      /* 使能LSI */
  16.      RCC_LSICmd(ENABLE);

  17.      /* 等待直到LSI就绪 */
  18.      while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);

  19.      /* 选择LSI作为RTC的时钟 */
  20.      RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

  21.      /* 使能RTC时钟 */
  22.      RCC_RTCCLKCmd(ENABLE);

  23.      /*
  24.         在APB1总线复位或者停止后重新开启,RTC的任何读取前得等待RTC寄存器
  25.         (RTC_CNT, RTC_ALR and RTC_PRL)跟RTC APB时钟同步。
  26.      */
  27.      RTC_WaitForSynchro();

  28.      /* 等待RTC寄存器写操作完成 */
  29.      RTC_WaitForLastTask();

  30.      /*
  31.        1. LSI的频率典型值是40KHz(30KHz到60KHz)
  32.        2. 这里按40KHz来计算
  33.           RTC 周期 = RTCCLK / RTC_PR = (40 KHz)/(19 + 1) = 2KHz
  34.      */
  35.      RTC_SetPrescaler(19);

  36.      /* 等待RTC寄存器写操作完成 */
  37.      RTC_WaitForLastTask();

  38.      /* EXTI线17连接到RTC闹钟事件,使能中断 */
  39.      EXTI_ClearITPendingBit(EXTI_Line17);
  40.      EXTI_InitStructure.EXTI_Line = EXTI_Line17;
  41.      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  42.      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  43.      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  44.      EXTI_Init(&EXTI_InitStructure);

  45.      /* 设置闹钟中断的NVIC */
  46.      NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
  47.      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
  48.      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  49.      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  50.      NVIC_Init(&NVIC_InitStructure);

  51.      for (;;)
  52.      {
  53.          /* 挂起OS, 并返回可以执行低功耗的时长 */
  54.          sleep = os_suspend ();
  55.          
  56.          if (sleep)
  57.          {
  58.               /* RTC计数设置 */
  59.               RTC_SetCounter(0);
  60.               RTC_WaitForLastTask();

  61.               /* 设置闹钟时间 */
  62.               RTC_SetAlarm(sleep*(OS_TICK/1000)*2);
  63.               RTC_WaitForLastTask();
  64.             
  65.               /* 使能闹钟中断 */
  66.               RTC_ITConfig(RTC_IT_ALR, ENABLE);
  67.               RTC_WaitForLastTask();
  68.             
  69.               /* 进入停机模式 */
  70.               PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
  71.             
  72.               /*
  73.                 1、当一个中断或唤醒事件导致退出停止模式时,HSI RC振荡器被选为系统时钟。
  74.                 2、退出低功耗的停机模式后,需要重新配置使用HSE和HSE
  75.               */
  76.               SystemInit();
  77.             
  78.               /*
  79.                  在APB1总线复位或者停止后重新开启,RTC的任何读取前得等待RTC寄存器
  80.                  (RTC_CNT, RTC_ALR and RTC_PRL)跟RTC APB时钟同步。
  81.               */
  82.               RTC_WaitForSynchro();
  83.             
  84.               /* 检查唤醒标志是否设置 */
  85.               if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
  86.               {
  87.                    /* 用户可以在这里加入相关串口打印等函数来检测是否进入停机模式 */
  88.                    //printf("lowpower\r\n");
  89.                    /* 清除唤醒标志 */
  90.                    PWR_ClearFlag(PWR_FLAG_WU);
  91.               }
  92.               else
  93.               {
  94.                    sleep = 0;
  95.               }
  96.             
  97.          }
  98.         
  99.          /* 恢复OS */
  100.          os_resume (sleep);           
  101.      }
  102. }

  103. /*--------------------------- RTC闹钟中断 ----------------------------------*/
  104. void RTCAlarm_IRQHandler(void)
  105. {
  106.      if (RTC_GetITStatus(RTC_IT_ALR) != RESET)
  107.      {
  108.          /* 禁止RTC的闹钟中断 */
  109.          RTC_ITConfig(RTC_IT_ALR, DISABLE);
  110.          RTC_WaitForLastTask();
  111.         
  112.          /* 清除中断标志 */
  113.          EXTI_ClearITPendingBit(EXTI_Line17);
  114.         
  115.          /* 清除中断标志 */
  116.          RTC_ClearITPendingBit(RTC_IT_ALR);
  117.          RTC_WaitForLastTask();
  118.      }   
  119. }
复制代码

信号量的创建:
  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-17 16:36:02
24.4.2   STM32F407开发板实验
配套例子:
    V5-424_RTX实验_低功耗(tickless模式)
实验目的:
    1.     学习RTX的低功耗(tickless模式)。
    2.     tickless模式低功耗的实现采用了停机模式,使用RTC的唤醒中断进行唤醒。这个和前面STM32F1开发板采用的闹钟中断唤醒不同。
    3.     tickless模式的实现在源文件RTX_Conf_CM.C文件中的空闲任务os_idle_demon函数里面。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro。
    任务AppTaskMsgPro接收到消息后进行消息处理。
    3.各个任务实现的功能如下:
    AppTaskUserIF任务   :按键消息处理。
    AppTaskLED任务     :LED闪烁。
    AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的信号量同步信号。
    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
设计低功耗主要从以下几个方面着手:
     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配置向导详情如下:
                              
24.5.png
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
        Number of tasks with user-provided stack
    创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
24.6.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类型数据运算会出问题。
系统栈大小分配:
24.7.png
外设初始化:
    注意新加的函数初始化函数DBGMCU_Config(DBGMCU_STOP, 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_STOP, ENABLE);
  15.    
  16.      /* 优先级分组设置为4, 优先配置好NVIC */
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  18.    
  19.      bsp_InitUart();    /* 初始化串口 */
  20.      bsp_InitKey();     /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
  21.      bsp_InitLed();     /* 初始LED指示灯端口 */
  22. }
复制代码

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. }
复制代码

tickless模式在空闲任务实现,即配置向导文件RTX_Conf_CM.c文件中
  1. /*----------------------------------------------------------------------------
  2. *      Global Functions
  3. *---------------------------------------------------------------------------*/
  4. #include "stm32f4xx.h"
  5. extern void SetSysClock(void);
  6. void RTC_WKUP_IRQHandler (void) {
  7.   EXTI->PR = (1 << 22);                 /* Clear pending EXTI interrupt      */
  8.   RTC->CR &= ~RTC_CR_WUTE;              /* Disable wakeup timer              */
  9. }

  10. /*--------------------------- os_idle_demon ---------------------------------*/

  11. __task void os_idle_demon (void) {
  12. //  /* The idle demon is a system task, running when no other task is ready */
  13. //  /* to run. The 'os_xxx' function calls are not allowed from this task.  */
  14.   uint32_t sleep;

  15.   SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;    /* Configure Cortex-M3 for deep sleep */
  16.   PWR->CR &= ~PWR_CR_PDDS;              /* Enter Stop mode when in deepsleep  */
  17.   PWR->CR  |= PWR_CR_LPDS;              /* Voltage regulator in low-power     */

  18.   /* Enable LSI clock and wait until ready */
  19.   RCC->CSR |= RCC_CSR_LSION;
  20.   while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);

  21.   /* Enable power interface clock */
  22.   RCC->APB1ENR |= RCC_APB1ENR_PWREN;

  23.   /* Disable backup domain write protection */
  24.   PWR->CR |= PWR_CR_DBP;

  25.   /* Select LSI as clock source for RTC and enable RTC */
  26.   RCC->BDCR &= ~RCC_BDCR_RTCSEL;
  27.   RCC->BDCR |=  RCC_BDCR_RTCSEL_1;
  28.   RCC->BDCR |=  RCC_BDCR_RTCEN;

  29.   /* Disable the write protection for RTC registers */
  30.   RTC->WPR   = 0xCA;
  31.   RTC->WPR   = 0x53;

  32.   /* Configure RTC auto-wakeup mode */
  33.   RTC->ISR  &= ~RTC_ISR_WUTF;           /* Clear wakeup timer flag            */
  34.   RTC->CR   &= ~RTC_CR_WUCKSEL;         /* Set RTC clock to 2kHz              */
  35.   RTC->CR   |=  RTC_CR_WUTIE;           /* Enable RTC wakeup timer interrupt  */

  36.   /* Configure EXTI line 22 for wakeup on rising edge */
  37.   EXTI->EMR  |= (1 << 22);              /* Event request is not masked        */
  38.   EXTI->RTSR |= (1 << 22);              /* Rising trigger enabled             */

  39.   NVIC_EnableIRQ (RTC_WKUP_IRQn);       /* Enable RTC WakeUp IRQ              */

  40.   for (;;) {
  41.     /* HERE: include optional user code to be executed when no task runs.     */
  42.     sleep = os_suspend ();              /* OS Suspend                         */
  43.    
  44.     if (sleep) {
  45.       RTC->ISR &= ~RTC_ISR_WUTF;        /* Clear timer wakeup flag            */
  46.       RTC->CR &= ~RTC_CR_WUTE;          /* Disable wakeup timer               */
  47.       while ((RTC->ISR & RTC_ISR_WUTWF) == 0);

  48.       /* RTC clock is @2kHz, set wakeup time for OS_TICK >= 1ms */
  49.       RTC->WUTR = (sleep * (OS_TICK / 1000) * 2);

  50.       RTC->CR |=  RTC_CR_WUTE;          /* Enable wakeup timer                */
  51.       __WFE ();                         /* Enter STOP mode                    */

  52.       /* After Wake-up */
  53.       if ((RTC->ISR & RTC_ISR_WUTF) == 0) {
  54.         sleep = 0;                      /* We didn't enter Stop mode          */
  55.       }
  56.       
  57.     }
  58.      os_resume (sleep);                  /* OS Resume                          */
  59.    
  60.      /*
  61.         下面的代码由用户添加。
  62.         1、当一个中断或唤醒事件导致退出停止模式时,HSI RC振荡器被选为系统时钟。
  63.         2、退出低功耗的停机模式后,需要重新配置使用HSE和HSE。
  64.         3、测试发现时钟配置函数SetSysClock不能放在os_suspend和os_resume,要不会有问题。
  65.      */
  66.      /* Disable IRQs */
  67.      __disable_irq();
  68.    
  69.      SetSysClock();
  70.    
  71.      /* Enable IRQs */
  72.     __enable_irq();
  73.   }
  74. }
复制代码

信号量的创建:
  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-17 16:36:58
24.5 总结
    本章节主要为大家讲解了RTX本身支持的低功耗tickless模式,对于初学者来说,刚开始学习可能不是特别理解,随着后面自己有了一定的经验后就比较容易理解了,特别是tickless的实现方法。另外tickless模式不限制用户必须采用停机模式,采用睡眠模式也是可以的,官方只是为用户提供了一种参考方法。

所属标签

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