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

STM32超低功耗平台上的RTOS培训--FreeRTOS低功耗项目简单分析

[复制链接]
Angel_YY 发布时间:2018-4-14 09:31
接上篇:STM32超低功耗平台上的RTOS应用--PDF课件




根据培训的视频讲解,继续学习FreeRTOS,编译成功后来简单分析一下工程和代码。

0001.png
这里使用的工程师STM32L4HAL库自带的例程,实现了一个简单的FreeRTOS的低功耗功能。
工程的主函数文件main.c内容如下,注释中做了简单的分析。
  1. /**
  2.   ******************************************************************************
  3.   * @file    FreeRTOS\FreeRTOS_LowPower\Src\main.c
  4.   * @author  MCD Application Team
  5.   * @brief   Main program body
  6.   ******************************************************************************
  7.   * @attention
  8.   *
  9.   * <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
  10.   * All rights reserved.</center></h2>
  11.   *
  12.   * Redistribution and use in source and binary forms, with or without
  13.   * modification, are permitted, provided that the following conditions are met:
  14.   *
  15.   * 1. Redistribution of source code must retain the above copyright notice,
  16.   *    this list of conditions and the following disclaimer.
  17.   * 2. Redistributions in binary form must reproduce the above copyright notice,
  18.   *    this list of conditions and the following disclaimer in the documentation
  19.   *    and/or other materials provided with the distribution.
  20.   * 3. Neither the name of STMicroelectronics nor the names of other
  21.   *    contributors to this software may be used to endorse or promote products
  22.   *    derived from this software without specific written permission.
  23.   * 4. This software, including modifications and/or derivative works of this
  24.   *    software, must execute solely and exclusively on microcontroller or
  25.   *    microprocessor devices manufactured by or for STMicroelectronics.
  26.   * 5. Redistribution and use of this software other than as permitted under
  27.   *    this license is void and will automatically terminate your rights under
  28.   *    this license.
  29.   *
  30.   * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
  31.   * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
  32.   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  33.   * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  34.   * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
  35.   * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  36.   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  37.   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  38.   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  39.   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  40.   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  41.   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42.   *
  43.   ******************************************************************************
  44.   */

  45. /* Includes ------------------------------------------------------------------*/
  46. #include "main.h"
  47. #include "cmsis_os.h"

  48. /* Private typedef -----------------------------------------------------------*/
  49. /* Private define ------------------------------------------------------------*/
  50. /* Private macro -------------------------------------------------------------*/
  51. #define blckqSTACK_SIZE   configMINIMAL_STACK_SIZE
  52. #define QUEUE_SIZE        (uint32_t) 1   //消息队列大小
  53. /* Private variables ---------------------------------------------------------*/
  54. osMessageQId osQueue;    //消息队列句柄

  55. /* The number of items the queue can hold.  This is 1 as the Rx task will
  56. remove items as they are added so the Tx task should always find the queue
  57. empty. */
  58. #define QUEUE_LENGTH             (1)     //消息队列的长度

  59. /* The rate at which the Tx task sends to the queue. */
  60. #define TX_DELAY                 (500)   //发送消息队列任务的延时长度

  61. /* The value that is sent from the Tx task to the Rx task on the queue. */
  62. #define QUEUED_VALUE             (100)   //发送消息队列的值

  63. /* The length of time the LED will remain on for.  It is on just long enough
  64. to be able to see with the human eye so as not to distort the power readings too
  65. much. */
  66. #define LED_TOGGLE_DELAY         (20)    //LED灯的翻转延时
  67. //私有函数声明
  68. /* Private function prototypes -----------------------------------------------*/
  69. static void QueueReceiveThread(const void *argument);  //队列接收线程
  70. static void QueueSendThread(const void *argument);     //队列发送线程
  71. static void GPIO_ConfigAN(void);                       //GPIO配置
  72. void SystemClock_Config(void);                         //系统时钟配置

  73. /* Private functions ---------------------------------------------------------*/

  74. /**
  75.   * @brief  Main program.
  76.   * @param  None
  77.   * @retval None
  78.   */
  79. int main(void)  //主函数
  80. {
  81.   /* STM32L4xx HAL library initialization:
  82.        - Configure the Flash prefetch
  83.        - Systick timer is configured by default as source of time base, but user
  84.          can eventually implement his proper time base source (a general purpose
  85.          timer for example or other time source), keeping in mind that Time base
  86.          duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
  87.          handled in milliseconds basis.
  88.        - Set NVIC Group Priority to 4
  89.        - Low Level Initialization
  90.      */
  91.   HAL_Init();  //初始化HAL库

  92.   /* Configure the System clock to 80 MHz */
  93.   SystemClock_Config();  //系统时钟配置

  94.   /* Configure GPIO's to AN to reduce power consumption */
  95.   GPIO_ConfigAN();  //配置GPIO到模拟模式以降低功耗

  96.   /* Initialize LED */
  97.   BSP_LED_Init(LED1);//初始化开发板的LED1

  98.   /* Create the queue used by the two threads */
  99.   osMessageQDef(osqueue, QUEUE_LENGTH, uint16_t);
  100.   osQueue = osMessageCreate(osMessageQ(osqueue), NULL);//创建队列

  101.   /* Note the Tx has a lower priority than the Rx when the threads are
  102.   spawned. */
  103.   osThreadDef(RxThread, QueueReceiveThread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
  104.   osThreadCreate(osThread(RxThread), NULL);  //创建接收队列线程(任务)

  105.   osThreadDef(TxThread, QueueSendThread, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE);
  106.   osThreadCreate(osThread(TxThread), NULL);  //创建发送队列线程(任务)

  107.   /* Start scheduler */
  108.   osKernelStart();    //开启任务调取器

  109.   /* We should never get here as control is now taken by the scheduler */
  110.   for (;;);

  111. }

  112. /**
  113.   * @brief  Message Queue Producer Thread.
  114.   * @param  argument: Not used
  115.   * @retval None
  116.   */
  117. static void QueueSendThread(const void *argument)  //发送消息队列线程
  118. {
  119.   for (;;)
  120.   {
  121.     /* Place this thread into the blocked state until it is time to run again.
  122.        The kernel will place the MCU into the Retention low power sleep state
  123.        when the idle thread next runs. */
  124.     osDelay(TX_DELAY);    //延时

  125.     /* Send to the queue - causing the queue receive thread to flash its LED.
  126.        It should not be necessary to block on the queue send because the Rx
  127.        thread will already have removed the last queued item. */
  128.     osMessagePut(osQueue, (uint32_t)QUEUED_VALUE, 0);  //发送消息队列
  129.   }
  130. }

  131. /**
  132.   * @brief  Message Queue Consumer Thread.
  133.   * @param  argument: Not used
  134.   * @retval None
  135.   */
  136. static void QueueReceiveThread(const void *argument)  //接收消息队列线程
  137. {
  138.   osEvent event;

  139.   for (;;)
  140.   {
  141.     /* Wait until something arrives in the queue. */
  142.     event = osMessageGet(osQueue, osWaitForever);  //获取消息队列,死等

  143.     /*  To get here something must have arrived, but is it the expected
  144.     value?  If it is, turn the LED on for a short while. */
  145.     if (event.status == osEventMessage)
  146.     {
  147.       if (event.value.v == QUEUED_VALUE)  //如果获得消息队列,并且消息值正确
  148.       {
  149.         BSP_LED_On(LED1);
  150.         osDelay(LED_TOGGLE_DELAY);  //闪烁LED1
  151.         BSP_LED_Off(LED1);
  152.       }
  153.     }
  154.   }
  155. }

  156. /**
  157.   * @brief  Pre Sleep Processing
  158.   * @param  ulExpectedIdleTime: Expected time in idle state
  159.   * @retval None
  160.   */
  161. void PreSleepProcessing(uint32_t * ulExpectedIdleTime)  //进入睡眠模式前的处理函数
  162. {
  163.   /* Called by the kernel before it places the MCU into a sleep mode because
  164.   configPRE_SLEEP_PROCESSING() is #defined to PreSleepProcessing().

  165.   NOTE:  Additional actions can be taken here to get the power consumption
  166.   even lower.  For example, peripherals can be turned off here, and then back
  167.   on again in the post sleep processing function.  For maximum power saving
  168.   ensure all unused pins are in their lowest power state. */

  169.   /*
  170.     (*ulExpectedIdleTime) is set to 0 to indicate that PreSleepProcessing contains
  171.     its own wait for interrupt or wait for event instruction and so the kernel vPortSuppressTicksAndSleep
  172.     function does not need to execute the wfi instruction  
  173.   */
  174.   *ulExpectedIdleTime = 0;
  175.   
  176.   /*Enter to sleep Mode using the HAL function HAL_PWR_EnterSLEEPMode with WFI instruction*/
  177.   HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);  //调用HAL库函数进入睡眠模式
  178. }

  179. /**
  180.   * @brief  Post Sleep Processing
  181.   * @param  ulExpectedIdleTime: Not used
  182.   * @retval None
  183.   */
  184. void PostSleepProcessing(uint32_t * ulExpectedIdleTime)//睡眠模式唤醒后处理函数
  185. {
  186.   /* Called by the kernel when the MCU exits a sleep mode because
  187.   configPOST_SLEEP_PROCESSING is #defined to PostSleepProcessing(). */

  188.   /* Avoid compiler warnings about the unused parameter. */
  189.   (void) ulExpectedIdleTime;
  190. }

  191. /**
  192.   * @brief  Configure all GPIO's to AN to reduce the power consumption
  193.   * @param  None
  194.   * @retval None
  195.   */
  196. static void GPIO_ConfigAN(void)
  197. {
  198.   GPIO_InitTypeDef GPIO_InitStruct;

  199.   /* Configure all GPIO as analog to reduce current consumption on non used IOs */
  200.   /* Enable GPIOs clock */
  201.   __HAL_RCC_GPIOA_CLK_ENABLE();
  202.   __HAL_RCC_GPIOB_CLK_ENABLE();
  203.   __HAL_RCC_GPIOC_CLK_ENABLE();
  204.   __HAL_RCC_GPIOD_CLK_ENABLE();
  205.   __HAL_RCC_GPIOE_CLK_ENABLE();
  206.   __HAL_RCC_GPIOF_CLK_ENABLE();
  207.   __HAL_RCC_GPIOG_CLK_ENABLE();
  208.   __HAL_RCC_GPIOH_CLK_ENABLE();
  209.   __HAL_RCC_GPIOI_CLK_ENABLE();

  210.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  211.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  212.   GPIO_InitStruct.Pin = GPIO_PIN_All;
  213.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  214.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  215.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  216.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  217.   HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
  218.   HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
  219.   HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
  220.   HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
  221.   HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

  222.   /* Disable GPIOs clock */
  223.   __HAL_RCC_GPIOA_CLK_DISABLE();
  224.   __HAL_RCC_GPIOC_CLK_DISABLE();
  225.   __HAL_RCC_GPIOC_CLK_DISABLE();
  226.   __HAL_RCC_GPIOD_CLK_DISABLE();
  227.   __HAL_RCC_GPIOE_CLK_DISABLE();
  228.   __HAL_RCC_GPIOF_CLK_DISABLE();
  229.   __HAL_RCC_GPIOG_CLK_DISABLE();
  230.   __HAL_RCC_GPIOH_CLK_DISABLE();
  231.   __HAL_RCC_GPIOI_CLK_DISABLE();
  232. }

  233. /**
  234.   * @brief  System Clock Configuration
  235.   *         The system Clock is configured as follows :
  236.   *            System Clock source            = PLL (MSI)
  237.   *            SYSCLK(Hz)                     = 80000000
  238.   *            HCLK(Hz)                       = 80000000
  239.   *            AHB Prescaler                  = 1
  240.   *            APB1 Prescaler                 = 1
  241.   *            APB2 Prescaler                 = 1
  242.   *            MSI Frequency(Hz)              = 4000000
  243.   *            PLL_M                          = 1
  244.   *            PLL_N                          = 40
  245.   *            PLL_R                          = 2
  246.   *            PLL_P                          = 7
  247.   *            PLL_Q                          = 4
  248.   *            Flash Latency(WS)              = 4
  249.   * @param  None
  250.   * @retval None
  251.   */
  252. void SystemClock_Config(void)
  253. {
  254.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  255.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  256.   /* MSI is enabled after System reset, activate PLL with MSI as source */
  257.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  258.   RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  259.   RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  260.   RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  261.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  262.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
  263.   RCC_OscInitStruct.PLL.PLLM = 1;
  264.   RCC_OscInitStruct.PLL.PLLN = 40;
  265.   RCC_OscInitStruct.PLL.PLLR = 2;
  266.   RCC_OscInitStruct.PLL.PLLP = 7;
  267.   RCC_OscInitStruct.PLL.PLLQ = 4;
  268.   if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  269.   {
  270.     /* Initialization Error */
  271.     while(1);
  272.   }
  273.   
  274.   /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
  275.      clocks dividers */
  276.   RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  277.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  278.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  279.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
  280.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  281.   if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  282.   {
  283.     /* Initialization Error */
  284.     while(1);
  285.   }
  286. }

  287. #ifdef  USE_FULL_ASSERT

  288. /**
  289.   * @brief  Reports the name of the source file and the source line number
  290.   *   where the assert_param error has occurred.
  291.   * @param  file: pointer to the source file name
  292.   * @param  line: assert_param error line source number
  293.   * @retval None
  294.   */
  295. void assert_failed(char *file, uint32_t line)
  296. {
  297.   /* User can add his own implementation to report the file name and line number,
  298.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  299.   /* Infinite loop */
  300.   while (1)
  301.   {}
  302. }
  303. #endif

  304. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码


VID_20180414_090729.gif
下载到STM32L469ZE Nucleo开发板后,就可以看到闪烁的LED灯了,证明FreeRTOS已经跑起来了。

收藏 2 评论2 发布时间:2018-4-14 09:31

举报

2个回答
wdliming-222461 回答时间:2020-4-13 17:34:38
taiwangpai 回答时间:2020-5-8 14:04:15
简单实用

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

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