收藏官网首页
查看: 13126|回复: 0

【一起来玩RTOS系列】之RT-Thread 通过yield切换线程

321

主题

1054

帖子

4502

积分

论坛元老

Rank: 8Rank: 8

积分
4502
QQ
跳转到指定楼层
楼主
发表于 2017-11-25 14:06:53 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
汉枫LPB120模块

线程让出处理器

当前线程的时间片用完或者该线程自动要求让出处理器资源时,它不再占有处理器,调度器会选择相同优先级的下一个线程执行。线程调用这个接口后,这个线程仍然在就绪队列中。线程让出处理器使用下面的函数接口:

  1. rt_err_t rt_thread_yield(void)
复制代码

调用该函数后,当前线程首先把自己从它所在的就绪优先级线程队列中删除,然后把自己挂到这个优先级队列链表的尾部,然后激活调度器进行线程上下文切换(如果当前优先级只有这一个线程,则这个线程继续执行,不进行上下文切换动作)。

线程安全:安全

中断例程:可调用

下面在机智云gokit开发板上验证如何通过yield函数手动切换线程,程序中创建2个相同优先级的线程,彼此调用yield切换线程,以期2个线程轮流执行;

  1. /**
  2.   ****************************************************
  3.   * File Name          : main.c
  4.   * Description        : Main program body
  5.   ****************************************************
  6.   ** This notice applies to any and all portions of this file
  7.   * that are not between comment pairs USER CODE BEGIN and
  8.   * USER CODE END. Other portions of this file, whether
  9.   * inserted by the user or by software development tools
  10.   * are owned by their respective copyright owners.
  11.   *
  12.   * COPYRIGHT(c) 2017 STMicroelectronics
  13.   *
  14.   * Redistribution and use in source and binary forms, with or without modification,
  15.   * are permitted provided that the following conditions are met:
  16.   *   1. Redistributions of source code must retain the above copyright notice,
  17.   *      this list of conditions and the following disclaimer.
  18.   *   2. Redistributions in binary form must reproduce the above copyright notice,
  19.   *      this list of conditions and the following disclaimer in the documentation
  20.   *      and/or other materials provided with the distribution.
  21.   *   3. Neither the name of STMicroelectronics nor the names of its contributors
  22.   *      may be used to endorse or promote products derived from this software
  23.   *      without specific prior written permission.
  24.   *
  25.   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26.   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28.   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  29.   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31.   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32.   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  33.   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  34.   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35.   *
  36.   ****************************************************
  37.   */
  38. /* Includes ------------------------------------------------------------------*/
  39. #include "main.h"
  40. #include "STM32f1xx_hal.h"
  41. #include "usart.h"
  42. #include "gpio.h"

  43. /* USER CODE BEGIN Includes */
  44. #include "rtthread.h"
  45. #include "string.h"
  46. /* USER CODE END Includes */

  47. /* Private variables ---------------------------------------------------------*/

  48. /* USER CODE BEGIN PV */
  49. /* Private variables ---------------------------------------------------------*/

  50. /* USER CODE END PV */

  51. /* Private function prototypes -----------------------------------------------*/
  52. void SystemClock_Config(void);

  53. /* USER CODE BEGIN PFP */
  54. /* Private function prototypes -----------------------------------------------*/

  55. /* USER CODE END PFP */

  56. /* USER CODE BEGIN 0 */
  57. //重映射串口1到rt_kprintf
  58. void rt_hw_console_output(const char *str)
  59. {
  60.     /* empty console output */
  61.         char aa='\r';
  62.           rt_enter_critical();

  63.                 while(*str!='\0')
  64.                 {
  65.                         if(*str=='\n')
  66.                         {
  67.                                 HAL_UART_Transmit(&huart1, (uint8_t *)&aa, 1, 10);
  68.                         }
  69.                                 HAL_UART_Transmit(&huart1, (uint8_t *)(str++), 1, 10);
  70.                 }
  71.                
  72.                 rt_exit_critical();
  73. }

  74. void rt_hw_us_delay(int us)
  75. {
  76.     rt_uint32_t delta;

  77.     /* 获得延时经过的tick数 */
  78.     us = us * (SysTick->LOAD/(1000000/RT_TICK_PER_SECOND));

  79.     /* 获得当前时间 */
  80.     delta = SysTick->VAL;

  81.     /* 循环获得当前时间,直到达到指定的时间后退出循环 */
  82.     while (delta - SysTick->VAL< us);
  83. }

  84. void rt_hw_ms_delay(int ms)
  85. {
  86.         int i=0,j=0;
  87. for(j=0;j<ms;j++)
  88.         {
  89.         for (i=0;i<2;i++)
  90.         rt_hw_us_delay(500);
  91.         }
  92. }

  93. /*
  94. * 程序清单:通过rt_thread_yield函数线程让出处理器
  95. * 创建两个相同优先级的线程, 它们会通过rt_thread_yield
  96. * 接口把处理器相互让给对方进行执行。
  97. */
  98. /* 指向线程控制块的指针 */
  99. static rt_thread_t tid1 = RT_NULL;
  100. static rt_thread_t tid2 = RT_NULL;

  101. /* 线程1入口 */
  102. static void thread1_entry(void* parameter)
  103. {   
  104.     rt_uint32_t i = 0;

  105.     while (1)
  106.     {
  107.                 /* 线程1的输出 */
  108.                 rt_kprintf("thread1: i = %d\n", i ++);

  109.                 /* 执行yield后应该切换到thread2执行 */
  110.                 rt_thread_yield();
  111.     }
  112. }

  113. /* 线程2入口 */
  114. static void thread2_entry(void* parameter)
  115. {
  116.     rt_uint32_t i = 0;

  117.     while (1)
  118.     {
  119.         /* 线程2的输出 */
  120.         rt_kprintf("thread2: i = %d\n", i ++);

  121.         /* 执行yield后应该切换到thread1执行 */
  122.         rt_thread_yield();
  123.     }
  124. }

  125. /* USER CODE END 0 */

  126. int main(void)
  127. {

  128.   /* USER CODE BEGIN 1 */

  129.   /* USER CODE END 1 */

  130.   /* MCU Configuration----------------------------------------------------------*/

  131. //  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  132. //  HAL_Init();

  133. //  /* USER CODE BEGIN Init */

  134. //  /* USER CODE END Init */

  135. //  /* Configure the system clock */
  136. //  SystemClock_Config();

  137. //  /* USER CODE BEGIN SysInit */

  138. //  /* USER CODE END SysInit */

  139. //  /* Initialize all configured peripherals */
  140. //  MX_GPIO_Init();
  141. //  MX_USART1_UART_Init();

  142.   /* USER CODE BEGIN 2 */
  143.        
  144.    /* 创建线程1 */
  145.     tid1 = rt_thread_create("t1",
  146.                                                         thread1_entry,
  147.                                                         RT_NULL,
  148.                                                         512,
  149.                                                         3,
  150.                                                         20);
  151.         if (tid1 != RT_NULL)
  152.                 rt_thread_startup(tid1);
  153.        
  154.         /* 创建线程2 */
  155.         tid2 = rt_thread_create("t2",
  156.                                                         thread2_entry,
  157.                                                         RT_NULL,
  158.                                                         512,
  159.                                                         3,
  160.                                                         20);

  161.         if (tid2 != RT_NULL)
  162.                 rt_thread_startup(tid2);
  163.        
  164.         printf("\r\n机智云  只为智能硬件而生\r\n");
  165.         printf("Gizwits Smart Cloud for Smart Products\r\n");
  166.         printf("链接|增值|开放|中立|安全|自有|自由|生态\r\n");
  167.         printf("www.gizwits.com\r\n");
  168.         printf("\r\nGokit RT-Thread Demo\r\n\r\n");
  169.        
  170.         return 0;
  171.        
  172.        


  173.   /* USER CODE END 2 */

  174.   /* Infinite loop */
  175.   /* USER CODE BEGIN WHILE */
  176. //  while (1)
  177. //  {
  178.   /* USER CODE END WHILE */

  179.   /* USER CODE BEGIN 3 */
  180. //               
  181. //  }
  182.   /* USER CODE END 3 */

  183. }

  184. /** System Clock Configuration
  185. */
  186. void SystemClock_Config(void)
  187. {

  188.   RCC_OscInitTypeDef RCC_OscInitStruct;
  189.   RCC_ClkInitTypeDef RCC_ClkInitStruct;

  190.     /**Initializes the CPU, AHB and APB busses clocks
  191.     */
  192.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  193.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  194.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  195.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  196.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  197.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  198.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  199.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  200.   {
  201.     _Error_Handler(__FILE__, __LINE__);
  202.   }

  203.     /**Initializes the CPU, AHB and APB busses clocks
  204.     */
  205.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  206.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  207.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  208.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  209.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  210.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  211.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  212.   {
  213.     _Error_Handler(__FILE__, __LINE__);
  214.   }

  215.     /**Configure the Systick interrupt time
  216.     */
  217.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  218.     /**Configure the Systick
  219.     */
  220.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  221.   /* SysTick_IRQn interrupt configuration */
  222.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  223. }

  224. /* USER CODE BEGIN 4 */

  225. /* USER CODE END 4 */

  226. /**
  227.   * @brief  This function is executed in case of error occurrence.
  228.   * @param  None
  229.   * @retval None
  230.   */
  231. void _Error_Handler(char * file, int line)
  232. {
  233.   /* USER CODE BEGIN Error_Handler_Debug */
  234.   /* User can add his own implementation to report the HAL error return state */
  235.   while(1)
  236.   {
  237.   }
  238.   /* USER CODE END Error_Handler_Debug */
  239. }

  240. #ifdef USE_FULL_ASSERT

  241. /**
  242.    * @brief Reports the name of the source file and the source line number
  243.    * where the assert_param error has occurred.
  244.    * @param file: pointer to the source file name
  245.    * @param line: assert_param error line source number
  246.    * @retval None
  247.    */
  248. void assert_failed(uint8_t* file, uint32_t line)
  249. {
  250.   /* USER CODE BEGIN 6 */
  251.   /* User can add his own implementation to report the file name and line number,
  252.     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  253.   /* USER CODE END 6 */

  254. }

  255. #endif

  256. /**
  257.   * @}
  258.   */

  259. /**
  260.   * @}
  261. */

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

通过串口信息可以看到实验结果与预期一致:



源码下载:


Gokit_RT-Thread.zip (8.7 MB, 下载次数: 1, 售价: 1 金钱)




1、机智云QQ群:G1群:104975951 G2群:491509598 G3群:287087942
机智云爱好者-APP开发群: 599735135
QQ群目前非常活跃,欢迎大家参与进来,交流,讨论,答疑,解惑~~
2、机智云微信公众号: 机智云 gizwits、 机智云智能宠物屋go-iot
关注机智云Gizwits官方公众号随时掌握最新资讯和活动信息
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2024 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

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