打印
[学习笔记]

AC78013FDLA Free RTOS的消息队列实验

[复制链接]
745|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.如果有多个消息阻塞在队列操作中,这些任务将按照优先级进行排序



使用特权

评论回复
评论
kzlzqi 2023-5-26 11:44 回复TA
———————————————— 版权声明:本文为CSDN博主「大唐不夜城」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/DiQiZiYouDu/article/details/117224782 

相关帖子

沙发
kzlzqi|  楼主 | 2023-5-26 11:44 | 只看该作者
安全设计思想:
一个队列尽可能只对应一个任务可以写入和读取,生产者和消费者保证唯一性。
一个队列由多任务或中断写入是经常的事,但由多个任务读出倒是用的比较少。



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



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

/* --------------------------------- Includes -------------------------------*/
#include "main.h"
#include "ac780x_irq_cb.h"
#include "ac780x_uart.h"
#include "ac780x_uart_reg.h"
#include "ac780x_gpio.h"
/* USER CODE BEGIN Includes */
#include  <stdarg.h>
#include  <stdio.h>
#include  <stdlib.h>
#include  <math.h>


#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "croutine.h"
/* USER CODE END Includes */

/* --------------------------------- Typedefs -------------------------------*/
/* USER CODE BEGIN Typedefs */
static TaskHandle_t xHandleTaskLed = NULL;
static TaskHandle_t xTaskTaskKey = NULL;
QueueHandle_t      Test_GpioQueue =NULL;  //消息队列句柄

/* USER CODE END Typedefs */

/* --------------------------------- Defines --------------------------------*/
/* USER CODE BEGIN Defines */

/* USER CODE END Defines */

/* --------------------------------- Macros ---------------------------------*/
/* USER CODE BEGIN Macros */

/* USER CODE END Macros */

/* --------------------------------- Variables ------------------------------*/

/* USER CODE BEGIN Variables */

/* USER CODE END Variables */

/* --------------------------------- Function Prototypes --------------------*/
void SystemClock_Config(void);
static void ATC_GPIO_Init(void);
static void ATC_UART2_Init(void);
static void ATC_UART1_Init(void);
void MSP_Init(void);
void MSP_UART_Init(UART_Type* UARTx);

/* USER CODE BEGIN Function_Prototypes */
static void vTaskTaskLed(void* parameter)
{

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

while (1)
{
        printf("Scan msg \r\n");
      
        xReturn = xQueueReceive(Test_GpioQueue, xRekeydata, 500);
      
        if(xReturn == errQUEUE_EMPTY)
                {
                        printf("empty\r\n");
                }
               
        if(xReturn == pdTRUE)
        {
                printf("Get  %d,%d\r\n",xRekeydata[0],xRekeydata[1]);
               
                if(xRekeydata[0] == 0x01)
                        GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_LOW);
                else
                        GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_HIGH);
        }
        else
        {
               
        }


         /*
        printf("Task Led 0\r\n");
       GPIO_SetPinLevel(LED1_GPIO_Port,LED1_Pin,GPIO_LEVEL_LOW);
                vTaskDelay(500);
        printf("Task Led 1\r\n");
        GPIO_SetPinLevel(LED1_GPIO_Port,LED1_Pin,GPIO_LEVEL_HIGH);
                vTaskDelay(500);
     */
}
}
static void vTaskTaskKey(void* parameter)
{

BaseType_t xReturn = pdPASS;
uint8_t    xkeydata[2]={0x0};
while (1)  
{
        //L  enable
/*        printf("Task Key\r\n");
        if(GPIO_GetPinLevel(KEY2_GPIO_Port, KEY2_Pin) == 0)
                {
        //        GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_LOW);
                xkeydata[0] = 0x00;
                xkeydata[1] = 0x00;
                xReturn =  xQueueSend( Test_GpioQueue, xkeydata,0);
                }
        else
                {
        //        GPIO_SetPinLevel(LED2_GPIO_Port,LED2_Pin,GPIO_LEVEL_HIGH);
                xkeydata[0] = 0x01;
                xkeydata[1] = 0x01;
                xReturn =  xQueueSend( Test_GpioQueue, xkeydata,0);
                }
        vTaskDelay(5000);
*/
}
}
/* USER CODE END Function_Prototypes */

/* USER CODE BEGIN 0 */

static void AppTaskCreate (void)
{

Test_GpioQueue = xQueueCreate(16, 2);

if(NULL != Test_GpioQueue)
{
printf("消息队列创建成功\r\n");
}
else
{
printf("消息队列创建失败\r\n");
}




    xTaskCreate( vTaskTaskLed,            
                 "vTaskLed",              
                 512,                        
                 NULL,                       
                 1,                          
                 &xHandleTaskLed );   

        xTaskCreate( vTaskTaskKey,            
                 "vTaskUserTRE",              
                 512,                        
                 NULL,                       
                 1,                          
                 &xTaskTaskKey );   
      
}



/*******************************************************************************
* Function Name  :void ACC_IRQHandler(void *device, uint32_t wpara, uint32_t lpara)
* Description    :ACC  引脚中断处理程序
* Output         : None
* Return         : None
*******************************************************************************/
void SocGpioACC_IRQHandler(void *device, uint32_t wpara, uint32_t lpara)
{
uint8_t    xkeydata[2]={0x0};
//if(GPIO_GetPendingExtInterrupt() & KEY2_Pin)
{
          GPIO_ClearPendingExtInterrupt(KEY2_Pin);
xkeydata[0] =GPIO_GetPinLevel(KEY2_GPIO_Port, KEY2_Pin);
xQueueSend( Test_GpioQueue, xkeydata,0);


}
}


/*******************************************************************************
* Function Name  :void  SocGpioEXITAccDet(void)
* Description    :使能 ACC   中断
* Output         : None
* Return         : None
*******************************************************************************/
void  SocGpioEXITKeyDet(void)
{


        GPIO_SetPullup(KEY2_GPIO_Port,KEY2_Pin, ENABLE);

      
GPIO_EnableExtInterrupt(KEY2_GPIO_Port, KEY2_Pin, EXTI_TRIGGER_RISING_FALLING);
      
GPIO_SetCallback(KEY2_Pin, SocGpioACC_IRQHandler);


}
















/* USER CODE END 0 */

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

    /* USER CODE END 1 */

    /* MCU Configuration------------------------------------------------------*/

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    ATC_GPIO_Init();
    ATC_UART2_Init();
    ATC_UART1_Init();

    /* USER CODE BEGIN 2 */

        SocGpioEXITKeyDet();
        InitDebug();
        AppTaskCreate();
        vTaskStartScheduler();
      
      
      
    /* USER CODE END 2 */

    /* Infinite loop */
    while(1)
    {

        /* USER CODE BEGIN WHILE */

        /* USER CODE END WHILE */

    }

    /* USER CODE BEGIN 3 */

    /* USER CODE END 3 */
}

/**
    * @brief System Clock Configuration
    * @retval None
    */
void SystemClock_Config(void)
{
    SPM_EnableXOSC(ENABLE);
    SPM_EnablePLL(ENABLE);
    CKGEN_SetPLLReference(PLL_REF_INTERAL_OSC);
    CKGEN_SetPllPrevDiv(PLL_PREDIV_1);
    CKGEN_SetPllFeedbackDiv(96);
    CKGEN_SetPllPostDiv(PLL_POSDIV_16);
    CKGEN_SetSysclkDiv(SYSCLK_DIVIDER_1);
    CKGEN_SetSysclkSrc(SYSCLK_SRC_PLL_OUTPUT);
    CKGEN_SetAPBClockDivider(APBCLK_DIVIDER_2);
}

/* UART1 init function */
static void ATC_UART1_Init(void)
{
    /* USER CODE BEGIN UART1_Init 0 */

    /* USER CODE END UART1_Init 0 */

    UART_ConfigType uartConfig;
    memset(&uartConfig, 0, sizeof(uartConfig));

    /* USER CODE BEGIN UART1_Init 1 */

    /* USER CODE END UART1_Init 1 */

    MSP_UART_Init(UART1);

    uartConfig.baudrate = 115200;
    uartConfig.dataBits = UART_WORD_LEN_8BIT;
    uartConfig.stopBits = UART_STOP_1BIT;
    uartConfig.parity = UART_PARI_NO;
    uartConfig.fifoByteEn = DISABLE;
    uartConfig.dmaEn = UART_DMA_TXRX_NONE;
    uartConfig.sampleCnt = UART_SMP_CNT0;

    UART_Init(UART1, &uartConfig);

    /* USER CODE BEGIN UART1_Init 2 */

    /* USER CODE END UART1_Init 2 */
}

/* UART2 init function */
static void ATC_UART2_Init(void)
{
    /* USER CODE BEGIN UART2_Init 0 */

    /* USER CODE END UART2_Init 0 */

    UART_ConfigType uartConfig;
    memset(&uartConfig, 0, sizeof(uartConfig));

    /* USER CODE BEGIN UART2_Init 1 */

    /* USER CODE END UART2_Init 1 */

    MSP_UART_Init(UART2);

    uartConfig.baudrate = 115200;
    uartConfig.dataBits = UART_WORD_LEN_8BIT;
    uartConfig.stopBits = UART_STOP_1BIT;
    uartConfig.parity = UART_PARI_NO;
    uartConfig.fifoByteEn = DISABLE;
    uartConfig.dmaEn = UART_DMA_TXRX_NONE;
    uartConfig.sampleCnt = UART_SMP_CNT0;

    UART_Init(UART2, &uartConfig);

    /* USER CODE BEGIN UART2_Init 2 */

    /* USER CODE END UART2_Init 2 */
}

/** Configure pins as
              * Analog
              * Input
              * Output
              * EVENT_OUT
              * EXTI
*/
static void ATC_GPIO_Init(void)
{
    GPIO_SetFunc(KEY2_GPIO_Port, KEY2_Pin, GPIO_FUN0);
    GPIO_SetFunc(KEY1_GPIO_Port, KEY1_Pin, GPIO_FUN0);
    GPIO_SetFunc(LED2_GPIO_Port, LED2_Pin, GPIO_FUN0);
    GPIO_SetFunc(LED1_GPIO_Port, LED1_Pin, GPIO_FUN0);
    GPIO_SetDir(KEY2_GPIO_Port, KEY2_Pin, GPIO_IN);
    GPIO_SetDir(KEY1_GPIO_Port, KEY1_Pin, GPIO_IN);
    GPIO_SetDir(LED2_GPIO_Port, LED2_Pin, GPIO_OUT);
    GPIO_SetDir(LED1_GPIO_Port, LED1_Pin, GPIO_OUT);
    GPIO_SetPinLevel(LED2_GPIO_Port, LED2_Pin, GPIO_LEVEL_LOW);
    GPIO_SetPinLevel(LED1_GPIO_Port, LED1_Pin, GPIO_LEVEL_LOW);
    GPIO_SetDrivingAbility(LED2_GPIO_Port, LED2_Pin, GPIO_DRIVING_4MA);
    GPIO_SetDrivingAbility(LED1_GPIO_Port, LED1_Pin, GPIO_DRIVING_4MA);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  file: The file name as string.
  * @param  line: The line in file as a number.
  * @retval None
  */
void Error_Handler(char *file, int line)
{
    /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to handle the driver error */
    while(1)
    {
    }
    /* USER CODE END Error_Handler_Debug */
}

/************************ (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 更加开放,你完全可以理 解为是为所欲为的免费

使用特权

评论回复
5
磨砂| | 2023-6-9 09:24 | 只看该作者
FreeRTOS 是一款 “开源免费”的实时操作系统,遵循的是 GPLv2+的许可协议。

使用特权

评论回复
6
晓伍| | 2023-6-9 09:50 | 只看该作者
FreeRTOS 和 OpenRTOS 拥有的代码是一样的,但是可从官方获取到的服务却是不一 样的。FreeRTOS 号称免费,OpenRTOS 号称收费

使用特权

评论回复
7
八层楼| | 2023-6-9 10:33 | 只看该作者
当你的产品使用了 FreeRTOS 且没有修改 FreeRTOS 内核源码的时候,你的产品的全部代码都可以闭源,不用开源,但是当 你修改了 FreeRTOS 内核源码的时候,就必须将修改的这部分开源,反馈给社区,其它应用部 分不用开源

使用特权

评论回复
8
观海| | 2023-6-9 10:47 | 只看该作者
阅读 RTOS 的源码,深究内核和每个组件的实现方式,这个过程枯燥且痛苦

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

101

主题

797

帖子

2

粉丝