[学习笔记] AC78013FDLA Free RTOS的消息队列实验

[复制链接]
1586|8
 楼主| kzlzqi 发表于 2023-5-26 11:43 | 显示全部楼层 |阅读模式
消息队列:异步通信机制

1.当队列中的消息是空时,读取消息的任务将被阻塞
2.可以指定阻塞的任务时间 xTicksToWait(这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效)
3.等待期间如果队列有消息,会唤醒被阻塞的任务并处理消息
4.等待超时,即使队列没有数据也会让任务进入就绪状态


5.消息先进先出
6.允许不同长度(限定范围之内)
7.一个消息队列可以服务于一个或多个任务
6.队列使用结束后通过删除队列函数删除


消息队列基本要素
头指针 pcHead、尾指针 pcTail、消息大小 uxItemSize 以及队列长度 uxLength  
消息队列与消息空间占用一段连续内存
一经创建不可改变

发送消息(任何任务或者中断函数都可以) 队列未满或者允许覆盖入队(消息安全性如何保证?),也可以是消息阻塞状态(那么发送消息的任务进入阻塞状态?是的)如果等待超时任务会进入就绪状态并会报错(errQUEUE_FULL)
普通消息加入队尾(先进先出),紧急消息加入队头。
发送到消息队列的数据是拷贝数据,不是引用数据

如果消息的长度过长可以将消息的地址作为消息发送(要保证数据不被多次擦写)


消息读取:
某任务试图读取消息时可以指定超时时间等待消息


保护机制:


阻塞机制:

读取阻塞:
任务A对队列L进行读操作的时候如果队列中没有消息:
1.任务直接放弃读取
2.任务A等待(进入阻塞状态)等待时间由软件定义
3.任务A一直等待,A进入阻塞状态直到消息队列有数据才会恢复为就绪状态

写入阻塞
任务B被允许对队列L写入时
1.如果队列已满,任务B可以等待阻塞超时时间,指定时间内如果不能完成写入操作返回错误吗errQUEUEFULL,然后进入就绪状态
2.中断中发送队列消息不允许有阻塞机制
3.如果有多个消息阻塞在队列操作中,这些任务将按照优先级进行排序



评论

———————————————— 版权声明:本文为CSDN博主「大唐不夜城」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/DiQiZiYouDu/article/details/117224782  发表于 2023-5-26 11:44
 楼主| kzlzqi 发表于 2023-5-26 11:44 | 显示全部楼层
安全设计思想:
一个队列尽可能只对应一个任务可以写入和读取,生产者和消费者保证唯一性。
一个队列由多任务或中断写入是经常的事,但由多个任务读出倒是用的比较少。



实验:设计两个任务,一个按键检测任务Key,一个LED点亮任务Led
检测到Key(扫描方式)发送消息给到Led任务点亮Led
检测到Key(中断方式)发送消息给到Led任务点亮Led



下面贴部分代码,欢迎交流参考
  1. * AutoChips Inc. (C) 2021. All rights reserved.
  2.   *
  3.   * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  4.   * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
  5.   * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
  6.   * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
  7.   * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  8.   * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  9.   * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
  10.   * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
  11.   * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
  12.   * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
  13.   * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
  14.   * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
  15.   * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
  16.   * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  17.   * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
  18.   * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
  19.   * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
  20.   * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
  21.   * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
  22.   *
  23.   ******************************************************************************  
  24.   */

  25. /* --------------------------------- Includes -------------------------------*/
  26. #include "main.h"
  27. #include "ac780x_irq_cb.h"
  28. #include "ac780x_uart.h"
  29. #include "ac780x_uart_reg.h"
  30. #include "ac780x_gpio.h"
  31. /* USER CODE BEGIN Includes */
  32. #include  <stdarg.h>
  33. #include  <stdio.h>
  34. #include  <stdlib.h>
  35. #include  <math.h>


  36. #include "FreeRTOS.h"
  37. #include "task.h"
  38. #include "queue.h"
  39. #include "croutine.h"
  40. /* USER CODE END Includes */

  41. /* --------------------------------- Typedefs -------------------------------*/
  42. /* USER CODE BEGIN Typedefs */
  43. static TaskHandle_t xHandleTaskLed = NULL;
  44. static TaskHandle_t xTaskTaskKey = NULL;
  45. QueueHandle_t      Test_GpioQueue =NULL;  //消息队列句柄

  46. /* USER CODE END Typedefs */

  47. /* --------------------------------- Defines --------------------------------*/
  48. /* USER CODE BEGIN Defines */

  49. /* USER CODE END Defines */

  50. /* --------------------------------- Macros ---------------------------------*/
  51. /* USER CODE BEGIN Macros */

  52. /* USER CODE END Macros */

  53. /* --------------------------------- Variables ------------------------------*/

  54. /* USER CODE BEGIN Variables */

  55. /* USER CODE END Variables */

  56. /* --------------------------------- Function Prototypes --------------------*/
  57. void SystemClock_Config(void);
  58. static void ATC_GPIO_Init(void);
  59. static void ATC_UART2_Init(void);
  60. static void ATC_UART1_Init(void);
  61. void MSP_Init(void);
  62. void MSP_UART_Init(UART_Type* UARTx);

  63. /* USER CODE BEGIN Function_Prototypes */
  64. static void vTaskTaskLed(void* parameter)
  65. {

  66. BaseType_t xReturn = pdPASS;
  67. uint8_t    xRekeydata[2]={0x0};

  68. while (1)
  69. {
  70.         printf("Scan msg \r\n");
  71.       
  72.         xReturn = xQueueReceive(Test_GpioQueue, xRekeydata, 500);
  73.       
  74.         if(xReturn == errQUEUE_EMPTY)
  75.                 {
  76.                         printf("empty\r\n");
  77.                 }
  78.                
  79.         if(xReturn == pdTRUE)
  80.         {
  81.                 printf("Get  %d,%d\r\n",xRekeydata[0],xRekeydata[1]);
  82.                
  83.                 if(xRekeydata[0] == 0x01)
  84.                         GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_LOW);
  85.                 else
  86.                         GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_HIGH);
  87.         }
  88.         else
  89.         {
  90.                
  91.         }


  92.          /*
  93.         printf("Task Led 0\r\n");
  94.        GPIO_SetPinLevel(LED1_GPIO_Port,LED1_Pin,GPIO_LEVEL_LOW);
  95.                 vTaskDelay(500);
  96.         printf("Task Led 1\r\n");
  97.         GPIO_SetPinLevel(LED1_GPIO_Port,LED1_Pin,GPIO_LEVEL_HIGH);
  98.                 vTaskDelay(500);
  99.      */
  100. }
  101. }
  102. static void vTaskTaskKey(void* parameter)
  103. {

  104. BaseType_t xReturn = pdPASS;
  105. uint8_t    xkeydata[2]={0x0};
  106. while (1)  
  107. {
  108.         //L  enable
  109. /*        printf("Task Key\r\n");
  110.         if(GPIO_GetPinLevel(KEY2_GPIO_Port, KEY2_Pin) == 0)
  111.                 {
  112.         //        GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_LOW);
  113.                 xkeydata[0] = 0x00;
  114.                 xkeydata[1] = 0x00;
  115.                 xReturn =  xQueueSend( Test_GpioQueue, xkeydata,0);
  116.                 }
  117.         else
  118.                 {
  119.         //        GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_HIGH);
  120.                 xkeydata[0] = 0x01;
  121.                 xkeydata[1] = 0x01;
  122.                 xReturn =  xQueueSend( Test_GpioQueue, xkeydata,0);
  123.                 }
  124.         vTaskDelay(5000);
  125. */
  126. }
  127. }
  128. /* USER CODE END Function_Prototypes */

  129. /* USER CODE BEGIN 0 */

  130. static void AppTaskCreate (void)
  131. {

  132. Test_GpioQueue = xQueueCreate(16, 2);

  133. if(NULL != Test_GpioQueue)
  134. {
  135. printf("消息队列创建成功\r\n");
  136. }
  137. else
  138. {
  139. printf("消息队列创建失败\r\n");
  140. }




  141.     xTaskCreate( vTaskTaskLed,            
  142.                  "vTaskLed",              
  143.                  512,                        
  144.                  NULL,                       
  145.                  1,                          
  146.                  &xHandleTaskLed );   

  147.         xTaskCreate( vTaskTaskKey,            
  148.                  "vTaskUserTRE",              
  149.                  512,                        
  150.                  NULL,                       
  151.                  1,                          
  152.                  &xTaskTaskKey );   
  153.       
  154. }



  155. /*******************************************************************************
  156. * Function Name  :void ACC_IRQHandler(void *device, uint32_t wpara, uint32_t lpara)
  157. * Description    :ACC  引脚中断处理程序
  158. * Output         : None
  159. * Return         : None
  160. *******************************************************************************/
  161. void SocGpioACC_IRQHandler(void *device, uint32_t wpara, uint32_t lpara)
  162. {
  163. uint8_t    xkeydata[2]={0x0};
  164. //if(GPIO_GetPendingExtInterrupt() & KEY2_Pin)
  165. {
  166.           GPIO_ClearPendingExtInterrupt(KEY2_Pin);
  167. xkeydata[0] =GPIO_GetPinLevel(KEY2_GPIO_Port, KEY2_Pin);
  168. xQueueSend( Test_GpioQueue, xkeydata,0);


  169. }
  170. }


  171. /*******************************************************************************
  172. * Function Name  :void  SocGpioEXITAccDet(void)
  173. * Description    :使能 ACC   中断
  174. * Output         : None
  175. * Return         : None
  176. *******************************************************************************/
  177. void  SocGpioEXITKeyDet(void)
  178. {


  179.         GPIO_SetPullup(KEY2_GPIO_Port,KEY2_Pin, ENABLE);

  180.       
  181. GPIO_EnableExtInterrupt(KEY2_GPIO_Port, KEY2_Pin, EXTI_TRIGGER_RISING_FALLING);
  182.       
  183. GPIO_SetCallback(KEY2_Pin, SocGpioACC_IRQHandler);


  184. }
















  185. /* USER CODE END 0 */

  186. /**
  187.   * [url=home.php?mod=space&uid=247401]@brief[/url]  The application entry point.
  188.   *
  189.   * @retval int
  190.   */
  191. int main(void)
  192. {
  193.     /* USER CODE BEGIN 1 */

  194.     /* USER CODE END 1 */

  195.     /* MCU Configuration------------------------------------------------------*/

  196.     /* USER CODE BEGIN Init */

  197.     /* USER CODE END Init */

  198.     /* Configure the system clock */
  199.     SystemClock_Config();

  200.     /* USER CODE BEGIN SysInit */

  201.     /* USER CODE END SysInit */

  202.     /* Initialize all configured peripherals */
  203.     ATC_GPIO_Init();
  204.     ATC_UART2_Init();
  205.     ATC_UART1_Init();

  206.     /* USER CODE BEGIN 2 */

  207.         SocGpioEXITKeyDet();
  208.         InitDebug();
  209.         AppTaskCreate();
  210.         vTaskStartScheduler();
  211.       
  212.       
  213.       
  214.     /* USER CODE END 2 */

  215.     /* Infinite loop */
  216.     while(1)
  217.     {

  218.         /* USER CODE BEGIN WHILE */

  219.         /* USER CODE END WHILE */

  220.     }

  221.     /* USER CODE BEGIN 3 */

  222.     /* USER CODE END 3 */
  223. }

  224. /**
  225.     * @brief System Clock Configuration
  226.     * @retval None
  227.     */
  228. void SystemClock_Config(void)
  229. {
  230.     SPM_EnableXOSC(ENABLE);
  231.     SPM_EnablePLL(ENABLE);
  232.     CKGEN_SetPLLReference(PLL_REF_INTERAL_OSC);
  233.     CKGEN_SetPllPrevDiv(PLL_PREDIV_1);
  234.     CKGEN_SetPllFeedbackDiv(96);
  235.     CKGEN_SetPllPostDiv(PLL_POSDIV_16);
  236.     CKGEN_SetSysclkDiv(SYSCLK_DIVIDER_1);
  237.     CKGEN_SetSysclkSrc(SYSCLK_SRC_PLL_OUTPUT);
  238.     CKGEN_SetAPBClockDivider(APBCLK_DIVIDER_2);
  239. }

  240. /* UART1 init function */
  241. static void ATC_UART1_Init(void)
  242. {
  243.     /* USER CODE BEGIN UART1_Init 0 */

  244.     /* USER CODE END UART1_Init 0 */

  245.     UART_ConfigType uartConfig;
  246.     memset(&uartConfig, 0, sizeof(uartConfig));

  247.     /* USER CODE BEGIN UART1_Init 1 */

  248.     /* USER CODE END UART1_Init 1 */

  249.     MSP_UART_Init(UART1);

  250.     uartConfig.baudrate = 115200;
  251.     uartConfig.dataBits = UART_WORD_LEN_8BIT;
  252.     uartConfig.stopBits = UART_STOP_1BIT;
  253.     uartConfig.parity = UART_PARI_NO;
  254.     uartConfig.fifoByteEn = DISABLE;
  255.     uartConfig.dmaEn = UART_DMA_TXRX_NONE;
  256.     uartConfig.sampleCnt = UART_SMP_CNT0;

  257.     UART_Init(UART1, &uartConfig);

  258.     /* USER CODE BEGIN UART1_Init 2 */

  259.     /* USER CODE END UART1_Init 2 */
  260. }

  261. /* UART2 init function */
  262. static void ATC_UART2_Init(void)
  263. {
  264.     /* USER CODE BEGIN UART2_Init 0 */

  265.     /* USER CODE END UART2_Init 0 */

  266.     UART_ConfigType uartConfig;
  267.     memset(&uartConfig, 0, sizeof(uartConfig));

  268.     /* USER CODE BEGIN UART2_Init 1 */

  269.     /* USER CODE END UART2_Init 1 */

  270.     MSP_UART_Init(UART2);

  271.     uartConfig.baudrate = 115200;
  272.     uartConfig.dataBits = UART_WORD_LEN_8BIT;
  273.     uartConfig.stopBits = UART_STOP_1BIT;
  274.     uartConfig.parity = UART_PARI_NO;
  275.     uartConfig.fifoByteEn = DISABLE;
  276.     uartConfig.dmaEn = UART_DMA_TXRX_NONE;
  277.     uartConfig.sampleCnt = UART_SMP_CNT0;

  278.     UART_Init(UART2, &uartConfig);

  279.     /* USER CODE BEGIN UART2_Init 2 */

  280.     /* USER CODE END UART2_Init 2 */
  281. }

  282. /** Configure pins as
  283.               * Analog
  284.               * Input
  285.               * Output
  286.               * EVENT_OUT
  287.               * EXTI
  288. */
  289. static void ATC_GPIO_Init(void)
  290. {
  291.     GPIO_SetFunc(KEY2_GPIO_Port, KEY2_Pin, GPIO_FUN0);
  292.     GPIO_SetFunc(KEY1_GPIO_Port, KEY1_Pin, GPIO_FUN0);
  293.     GPIO_SetFunc(LED2_GPIO_Port, LED2_Pin, GPIO_FUN0);
  294.     GPIO_SetFunc(LED1_GPIO_Port, LED1_Pin, GPIO_FUN0);
  295.     GPIO_SetDir(KEY2_GPIO_Port, KEY2_Pin, GPIO_IN);
  296.     GPIO_SetDir(KEY1_GPIO_Port, KEY1_Pin, GPIO_IN);
  297.     GPIO_SetDir(LED2_GPIO_Port, LED2_Pin, GPIO_OUT);
  298.     GPIO_SetDir(LED1_GPIO_Port, LED1_Pin, GPIO_OUT);
  299.     GPIO_SetPinLevel(LED2_GPIO_Port, LED2_Pin, GPIO_LEVEL_LOW);
  300.     GPIO_SetPinLevel(LED1_GPIO_Port, LED1_Pin, GPIO_LEVEL_LOW);
  301.     GPIO_SetDrivingAbility(LED2_GPIO_Port, LED2_Pin, GPIO_DRIVING_4MA);
  302.     GPIO_SetDrivingAbility(LED1_GPIO_Port, LED1_Pin, GPIO_DRIVING_4MA);
  303. }

  304. /* USER CODE BEGIN 4 */

  305. /* USER CODE END 4 */

  306. /**
  307.   * @brief  This function is executed in case of error occurrence.
  308.   * @param  file: The file name as string.
  309.   * @param  line: The line in file as a number.
  310.   * @retval None
  311.   */
  312. void Error_Handler(char *file, int line)
  313. {
  314.     /* USER CODE BEGIN Error_Handler_Debug */
  315.     /* User can add his own implementation to handle the driver error */
  316.     while(1)
  317.     {
  318.     }
  319.     /* USER CODE END Error_Handler_Debug */
  320. }

  321. /************************ (C) COPYRIGHT AutoChips *****END OF FILE****/
tpgf 发表于 2023-6-8 17:15 | 显示全部楼层
如何学习一个 RTOS?最简单的就是在别人移植好的系统之上,看看 RTOS 里面的 API 使用说明,然后调用这些 API 实现自己想要的功能即可
木木guainv 发表于 2023-6-9 08:41 | 显示全部楼层
FreeRTOS 于 2018 年被亚马逊收购,改名为 AWS FreeRTOS,版本号升级为 V10,且 开源协议也由原来的 GPLv2+修改为 MIT,与 GPLv2+相比,MIT 更加开放,你完全可以理 解为是为所欲为的免费
磨砂 发表于 2023-6-9 09:24 | 显示全部楼层
FreeRTOS 是一款 “开源免费”的实时操作系统,遵循的是 GPLv2+的许可协议。
晓伍 发表于 2023-6-9 09:50 | 显示全部楼层
FreeRTOS 和 OpenRTOS 拥有的代码是一样的,但是可从官方获取到的服务却是不一 样的。FreeRTOS 号称免费,OpenRTOS 号称收费
八层楼 发表于 2023-6-9 10:33 | 显示全部楼层
当你的产品使用了 FreeRTOS 且没有修改 FreeRTOS 内核源码的时候,你的产品的全部代码都可以闭源,不用开源,但是当 你修改了 FreeRTOS 内核源码的时候,就必须将修改的这部分开源,反馈给社区,其它应用部 分不用开源
观海 发表于 2023-6-9 10:47 | 显示全部楼层
阅读 RTOS 的源码,深究内核和每个组件的实现方式,这个过程枯燥且痛苦
您需要登录后才可以回帖 登录 | 注册

本版积分规则

127

主题

996

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部