FreeRTOS学习(五)队列与信号量

2023-05-16

文章目录

      • 1.队列
        • 1.1 队列特性
        • 1.2 队列创建
          • 1.2.1 接口函数
          • 1.2.2 内存占用
          • 1.2.3 创建过程分析
        • 1.3 入队与出队
          • 1.3.1 队列项入队
          • 1.3.1 队列项出队
      • 2.信号量
        • 2.1 二值信号量
        • 2.2 计数型信号量
        • 2.3 互斥信号量
      • 3.总结

1.队列

  FreeRTOS支持多任务操作,那么任务之间以及任务与中断之间肯定需要通讯与同步,因此,继任务相关内容学习之后,下一个重要的概念就是队列。

1.1 队列特性

  队列能够存储一定数目、大小固定的数据项目。因此创建队列时,需要指明数据的长度length和数据元素的大小 size。这里将队列类比成火车,长度length对应火车的节数,元素大小size对应每节车厢容纳人数。
  队列特性主要有:

  • FIFO,向队列中发送数据叫入队,从队列中读取数据叫出队
  • 支持值传递和引用传递,值传递时是将原数据拷贝到队列中,原数据可以删除或覆写
  • 多任务访问,不属于某个特定任务,属于公共资源
  • 入队阻塞/出队阻塞:三种阻塞机制

1.2 队列创建

1.2.1 接口函数

  队列也有动态创建xQueueCreate()和静态创建xQueueCreateStatic()两种方式。

API功能
xQueueCreate()动态创建,内存由编辑器负责分配
xQueueCreateStatic()静态创建,需要程序员提供结构体和实际储存区的地址

  以动态创建为例,其归根结底还是调用了一个通用 API xQueueGenericCreate(),这个API不仅可以创建队列,也是创建信号量的底层函数。

QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, //队列长度
                                       const UBaseType_t uxItemSize,//队列中每个消息的长度,单位为字节
                                       const uint8_t ucQueueType )	//队列类型

  重点在于ucQueueType队列类型这个参数,它一共有6种类型:

queueQUEUE_TYPE_BASE:表示队列
queueQUEUE_TYPE_SET:表示队列集合 
queueQUEUE_TYPE_MUTEX:表示互斥量
queueQUEUE_TYPE_COUNTING_SEMAPHORE:表示计数信号量
queueQUEUE_TYPE_BINARY_SEMAPHORE:表示二进制信号量
queueQUEUE_TYPE_RECURSIVE_MUTEX :表示递归互斥量

  实际上,信号量就是在队列的基础上延伸出来的,是对队列的约束。关于信号量,后面内容会讲。

1.2.2 内存占用

  与任务创建类似,队列的创建也需要两块内存,分别是队列结构体队列项存储区,这两块内存是连续的。
在这里插入图片描述

  • 队列结构体,是对队列的描述,类似于任务的TCB
  • 列表项存储区,消息真正存放的区域
    在这里插入图片描述

  队列结构体成员参数解释如下:

typedef struct QueueDefinition
{
    int8_t *pcHead;             /* 指向队列存储区起始位置,即第一个队列项 */
    int8_t *pcTail;             /* 指向队列存储区结束后的下一个字节 */
    int8_t *pcWriteTo;          /* 指向下队列存储区的下一个空闲位置 */
 
 
    union                       /* 使用联合体用来确保两个互斥的结构体成员不会同时出现 */
    {
        int8_t *pcReadFrom;     /* 当结构体用于队列时,这个字段指向出队项目中的最后一个. */
        UBaseType_t uxRecursiveCallCount;/* 当结构体用于互斥量时,用作计数器,保存递归互斥量被"获取"的次数. */
    } u;
 
 
    List_t xTasksWaitingToSend;      /* 因为等待入队而阻塞的任务列表,按照优先级顺序存储 */
    List_t xTasksWaitingToReceive;   /* 因为等待队列项而阻塞的任务列表,按照优先级顺序存储 */
 
 
    volatile UBaseType_t uxMessagesWaiting;/*< 当前队列的队列项数目 */
    UBaseType_t uxLength;            /* 队列项的数目 */
    UBaseType_t uxItemSize;          /* 每个队列项的大小 */
 
 
    volatile BaseType_t xRxLock;   /* 队列上锁后,存储从队列收到的列表项数目,如果队列没有上锁,设置为queueUNLOCKED */
    volatile BaseType_t xTxLock;   /* 队列上锁后,存储发送到队列的列表项数目,如果队列没有上锁,设置为queueUNLOCKED */
 
 
    #if ( configUSE_QUEUE_SETS == 1 )
        struct QueueDefinition *pxQueueSetContainer;
    #endif
 
 
    #if ( configUSE_TRACE_FACILITY == 1 )
        UBaseType_t uxQueueNumber;
        uint8_t ucQueueType;
    #endif
 
 
    #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
        uint8_t ucStaticAllocationFlags;
    #endif
 
 
} xQUEUE;
 
 
typedef xQUEUE Queue_t;
1.2.3 创建过程分析
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
                                       const UBaseType_t uxItemSize,
                                       const uint8_t ucQueueType )
    {
        Queue_t * pxNewQueue;
        size_t xQueueSizeInBytes;
        uint8_t * pucQueueStorage;

        configASSERT( uxQueueLength > ( UBaseType_t ) 0 );

        // 计算队列存储区大小
        xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); 

        /* Check for multiplication overflow. */
        configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) );

        /* Check for addition overflow. */
        configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) >  xQueueSizeInBytes );

        // 为队列结构体和队列项存储区申请内存
        pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */
		// 内存申请成功
        if( pxNewQueue != NULL )
        {
            // 计算队列项存储区的首地址
            pucQueueStorage = ( uint8_t * ) pxNewQueue;
            pucQueueStorage += sizeof( Queue_t ); 

            #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
                {
                    // 动态申请内存的话,那么这个成员参数设置为 pdFALSE
                    pxNewQueue->ucStaticallyAllocated = pdFALSE;
                }
            #endif /* configSUPPORT_STATIC_ALLOCATION */
			// 初始化队列结构体成员参数
            prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
        }
        else
        {
            traceQUEUE_CREATE_FAILED( ucQueueType );
            mtCOVERAGE_TEST_MARKER();
        }

        return pxNewQueue;
    }

  简要的流程图如下:主要就是分配内存,然后对队列结构体进行初始化。
在这里插入图片描述

1.3 入队与出队

1.3.1 队列项入队

  入队函数分为任务级与中断级,但这些 API 都是宏定义。
在这里插入图片描述
  任务级入队函数都是调用的同一个函数xQueueGenericSend,其参数如下

BaseType_t xQueueGenericSend( QueueHandle_t xQueue,				//队列句柄
                              const void * const pvItemToQueue, //指向要发送的消息
                              TickType_t xTicksToWait,			//阻塞时间
                              const BaseType_t xCopyPosition )	//入队方式

//入队方式主要有以下三种,分别对应后向入队、前向入队和覆写入队
#define queueSEND_TO_BACK                     ( ( BaseType_t ) 0 )
#define queueSEND_TO_FRONT                    ( ( BaseType_t ) 1 )
#define queueOVERWRITE                        ( ( BaseType_t ) 2 )

  中断级入队函数都是调用的同一个函数xQueueGenericSendFromISR,其参数如下

BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
                                     const void * const pvItemToQueue,
                                     BaseType_t * const pxHigherPriorityTaskWoken, //标记退出此函数后是否进行任务切换
                                     const BaseType_t xCopyPosition ) //入队方式,同上

  关于队列项入队的详细过程先挖个坑,后续再填。

1.3.1 队列项出队

在这里插入图片描述

2.信号量

  信号量一般用来进行资源管理任务间、任务与中断间的同步,FreeRTOS 中的信号量分为二值信号量、计数型信号量、互斥信号量和递归互斥信号量。

  • 信号量创建调用的底层API跟队列创建是同一个,只是传入参数不同
  • 这四种信号量的句柄类型是相同的SemaphoreHandle_t,本质上是队列句柄QueueHandle_t
typedef QueueHandle_t SemaphoreHandle_t;
  • 这四种信号量的创建函数不同,但释放、获取与删除时相同的

2.1 二值信号量

(1)主要特点

  • 实质上是一个队列长度为 1,队列项长度为 0 的队列
  • 没有队列项存储区,通过队列结构体的成员 uxMessageWaiting来判断队列是否为空

(2)创建函数

API功能
xSemaphoreCreateBinary()动态创建二值信号量
xSemaphoreCreateBinaryStatic()静态创建二值信号量

  创建成功后会返回信号量的句柄,创建函数其实是一个宏定义,如下

#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    #define xSemaphoreCreateBinary()    xQueueGenericCreate( ( UBaseType_t ) 1, 
    									semSEMAPHORE_QUEUE_ITEM_LENGTH,  // 宏定义 0
   										queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif

//example
SemaphoreHandle_t 		BinSemaphore;
BinSemaphore = xSemaphoreCreateBinary();
  • 二值信号量创建后是无效的,必须先调用API释放,才能使用。

(3)释放、获取与删除

API功能
xSemaphoreGive()任务级释放二值信号量
xSemaphoreGiveFromISR()中断级释放信号量
xSemaphoreTake()任务级获取信号量
xSemaphoreTakeFromISR()中断级获取信号量
vSemaphoreDelete()删除信号量

  二值信号量的释放就是向队列中发送消息,但消息为NULL,阻塞时间为0,后向入队。关键在于入队的时候,队列结构体成员 uxMessageWaiting 会加一,从而判断队列时满1还是空0

#define xSemaphoreGive( xSemaphore )    xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), 
															NULL, 
															semGIVE_BLOCK_TIME, // 阻塞时间宏,为 0
															queueSEND_TO_BACK ) // 后向入队

  获取二值信号量可以设置阻塞时间,读取成功后 uxMessageWaiting 会减一。

#define xSemaphoreTake( xSemaphore, xBlockTime )    xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )

2.2 计数型信号量

(1)主要特点

  • 队列长度大于1,队列项长度为0
  • 同样通过队列结构体成员 uxMessageWaiting来判断数量

(2)创建函数

API功能
xSemaphoreCreateCounting()动态创建计数型信号量
xSemaphoreCreateCountingStatic()静态创建计数型信号量
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount )    xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
  • 计数型信号量的释放、获取与删除操作与二值信号量相同

2.3 互斥信号量

(1)主要特点

  • 互斥量具有优先级继承机制,只能用在任务中,不能用于中断服务函数
  • 中断服务函数不能因为要等待互斥量而设置阻塞时间进入阻塞态
  • 队列长度为1,队列项长度为0
  • 任务在使用完互斥量后必须释放,否则其他资源无法使用,即互斥量是一个不能被销毁的特殊信号量

(2)创建函数

API功能
xSemaphoreCreateMutex()动态创建互斥信号量
xSemaphoreCreateMutexStatic()静态创建互斥信号量

  互斥信号量获取和释放的过程与二值信号量有些区别,主要涉及到优先级继承。
(3)优先级翻转
  优先级翻转主要发生在当两个任务H和L共用一个信号量时,

  • 当信号量为二值型时,L优先获得信号量后,会将H的优先级拉低到和自身相同,使得M任务抢先于H执行,出现优先级翻转
  • 当信号量为互斥型时,L优先获得信号量后,H会将L的优先级拉高到和自身相同,尽量避免优先级翻转
    在这里插入图片描述

3.总结

通讯方式长度约束作用
队列-值传递>0阻塞读写用于任务之间传递数据
队列-引用传递>0阻塞读写用于大块数据的高效传输
二值信号量1一方只需要申请,另一方只需要释放用于锁存1个中断代表资源的到达 / 用于任务的异步通知
计数型信号量>1一方只需要申请,另一方只需要释放用于锁存若干个中断以免中断丢失 / 用于同步代表资源的数量
互斥信号量1申请的一方必须自己进行释放用于互斥访问机制
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS学习(五)队列与信号量 的相关文章

  • 基于HAL库的FREERTOS----------二.任务API函数

    任务API函数览概 CUBEMX对 做了API的封装 很多 的函数没有封装到位 可以用原函数调用 任务API函数分别介绍 1 uxTaskPriorityGet 此函数用来获取指定任务的优先级 要使用此函数的话宏 INCLUDE uxTas
  • FreeRTOS内核配置说明---FreeRTOS Kernel V10.2.1

    FreeRTOS内核是高度可定制的 使用配置文件FreeRTOSConfig h进行定制 每个FreeRTOS应用都必须包含这个头文件 用户根据实际应用来裁剪定制FreeRTOS内核 这个配置文件是针对用户程序的 而非内核 因此配置文件一般
  • FreeRTOS config开始的宏

    FreeRTOSConfig h系统配置文件中可以自定义 FreeRTOS h中定义默认值 configAPPLICATION ALLOCATED HEAP 默认情况下FreeRTOS的堆内存是由编译器来分配的 将宏configAPPLIC
  • STM32F103移植FreeRTOS必须搞明白的系列知识---3(堆栈)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • STM32CubeMX+FreeRTOS学习笔记(一)

    嵌入式实时操作系统FreeRTOS 基本概述 在嵌入式领域当中 实时操作系统的应用越来越广泛了 目前嵌入式操作系统种类很多 例如 Clinux C OS II C OS III FreeRTOS RT Thread等等 这篇文章所记录的就是
  • FreeRTOS-内核控制函数

    FreeRTOS 内核控制函数 FreeRTOS中有一些内核函数 一般来说这些内核函数在应用层不会使用 但是内核控制函数是理解FreeRTOS中断的基础 接下来我们逐一分析这些内核函数 taskYIELD 该函数的作用是进行任务切换 这是一
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • 一文教你学会keil软件仿真

    仿真在我们调试代码中是非常重要的 通过仿真 我们可以快速定位到错误代码 或者错误逻辑的地方 这里我就以上一篇博客为例 教大家如何软件仿真 软件仿真不需要单片机 直接通过keil软件进行代码调试 一 打开工具 二 选择软件仿真 三 开始仿真
  • Freertos中vTaskDelay()是怎么用的

    1 常见的使用场景 void vLED Task void pvParameters while 1 Heartbeat LED vTaskDelay 1000 portTICK RATE MS 说明 上面这段代码的意思是 led翻转后经过
  • freeRTOS使用uxTaskGetStackHighWaterMark函数查看任务堆栈空间的使用情况

    摘要 每个任务都有自己的堆栈 堆栈的总大小在创建任务的时候就确定了 此函数用于检查任务从创建好到现在的历史剩余最小值 这个值越小说明任务堆栈溢出的可能性就越大 FreeRTOS 把这个历史剩余最小值叫做 高水位线 此函数相对来说会多耗费一点
  • 【FreeRTOS】任务通知的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS之事件

    FreeRTOS之事件 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 一 事件定义 事件 事件集 与高数上的集合意义差不多 事件啊 其实是实现任务间通信的机制 主要用于实现多任务间的同步 但是事件类型
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • FreeRTOS实时操作系统(三)任务挂起与恢复

    系列文章 FreeRTOS实时操作系统 一 RTOS的基本概念 FreeRTOS实时操作系统 二 任务创建与任务删除 HAL库 FreeRTOS实时操作系统 三 任务挂起与恢复 FreeRTOS实时操作系统 四 中断任务管理 FreeRTO
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • FreeRTOS多任务调度器基础

    Cortex M4中SysTick调度器核心 Cortex M4中的中断管理 Cortex M4中影子栈指针 Cortex M4中SVC和PendSV异常 1 Cortex M4中SysTick调度器核心 systick每一次中断都会触发内
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • C++ freeRTOS任务,非静态成员函数的无效使用

    哪里有问题 void MyClass task void pvParameter while 1 this gt update void MyClass startTask xTaskCreate this gt task Task 204
  • GNU Arm Cortex m4 上的 C++ 异常处理程序与 freertos

    2016 年 12 月更新现在还有一个关于此行为的最小示例 https community nxp com message 862676 https community nxp com message 862676 我正在使用带有 free

随机推荐

  • 【系统分析师之路】嵌入式系统章节错题集锦

    系统分析师之路 嵌入式系统章节错题集锦 系分章节错题集第01题 xff1a 红色 01 雷达设计人员在设计数字信号处理单元时 xff0c 其处理器普遍采用DSP芯片 xff08 比如 xff1a TI公司的TMS320C63xx xff09
  • 【软工】程序编码

    目录 前言正文 程序设计语言 分类 选择原则 程序编码总原则 好程序的标准 结构化程序设计 主要内容 主要原则 程序设计风格 源程序文档化 数据说明 语句结构 输入输出方法 程序设计质量评价 正确性结构清晰性易修改性 易读性 简单性 程序复
  • TPM1.2到TPM 2.0的变化

    原文地址 xff1a http www vonwei com mod 61 pad amp act 61 view amp id 61 11 TPM 1 2规范主要面向PC平台 xff0c 其103版本在2009年被接受为ISO标准 xff
  • 关于Cmake与CmakeLists(一)--背景,须知,示例

    一 背景及须知 1 背景 xff1a VS2019与VS2010在编写程序时都是创建了一个工程 xff0c 然后直接打开 sln即可 但是vscode仅仅是一个编辑器 xff0c 打开之后只有 c或者 cpp文件 xff0c 故需要手动编译
  • webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案——第五课

    webgl three js 实现室内定位 楼宇bim 实时定位三维可视化解决方案 第五课 参考文章 xff1a xff08 1 xff09 webgl three js 实现室内定位 楼宇bim 实时定位三维可视化解决方案 第五课 xff
  • Linux虚拟机在线扩容lvm类型root分区

    目录 Linux虚拟机在线扩容lvm类型root分区写在前面正文写在后面 Linux虚拟机在线扩容lvm类型root分区 写在前面 这是我在CSDN上的第一篇文章 作为一个半江湖的IT人 xff0c 这些年来也在CSDN受益很多 今天是20
  • 无vCenter创建vSAN集群

    无vCenter创建vSAN集群 最近仍有朋友在问题 xff0c vCenter如果 挂了 xff0c vSAN还能正常运行吗 xff1f 这个小文通过手动创建vSAN集群的方式来解答下这个问题吧 xff08 生产环境慎用 xff01 xf
  • 记一次mdadm软raid1升级容量

    MDRaid 2块4TB做了软RAID1 xff0c 需要升级成2块8TB盘 查看磁盘信息 xff0c SerialNumber等会儿会用到 xff0c 防止换错盘 span class token function sudo span h
  • [简洁版]youtube-dl下载命令

    简介 YouTube dl是python上的pip模块 xff08 开源 xff09 xff0c 可以用来下载YouTube Bilibili等多个平台的视频 音频文件 xff0c 可谓是居家旅行必备小工具 本文主要介绍一些常用的youtu
  • [简版]VMware强大的管理工具-PowerCLI

    一 PowerCLI介绍 什么是 PowerCLI PowerCLI 是一个命令行工具 xff0c 可以用于自动化vSphere管理 xff0c 包括网络 存储 虚拟机以及其他很多功能 PowerCLI包含超过700个命令 要安装Power
  • [简版]使用PowerCLI自定义vSphere ISO安装镜像

    一 什么情况下要自定义ISO镜像 一般来说 xff0c 对于DELL Lenovo HPE这类主流的服务器厂商 xff0c VMware官方vSphere ISO镜像或者官网的第三方客制镜像 xff08 由服务器厂商提供的封装镜像 xff0
  • [简版] 关于vSphere漏洞-OpenSLP

    一 前言 近期vSphere OpenSLP漏洞在野利用的新闻频频被爆出来 xff0c 大伙儿非常关注 由于vSphere虚拟化客户之广泛 xff0c 很多朋友都表达了自己的焦虑 xff0c 同时也会担心自己管理的vSphere虚拟化平台是
  • [简版] Linux搭建SAMBA文件共享服务

    SMB服务搭建 更多参数含义参考链接 常用配置 安装samba span class token comment Ubuntu span span class token function sudo span span class toke
  • STM32 HAL库详解

    STM32 HAL库整体总结 STM32 之二 HAL库详解 及 手动移植 本篇博客是对以上参考资源的一个二次总结与整理 1 HAL库文件结构 对于开发人员而言 xff0c 首先要清楚 HAL 库的文件结构 根据文件类型可认为以下两大类 x
  • STM32 HAL库学习(四):DMA之串口空闲中断

    STM32CubeMX 配置实现参考这里 1 串口空闲中断 1 1 UART DMA方式接收数据 STM32串口使用DMA方式接收数据可以减小CPU的开销 对于接收定长数据 xff0c 可以将DMA接收缓冲区的长度设定为待接收数据的长度 x
  • Android Studio 启动模拟器出现“Timed out after 300seconds waiting for emulator to come online“解决方案

    Android Studio 启动模拟器出现 34 Timed out after 300seconds waiting for emulator to come online 34 解决方案 参考文章 xff1a xff08 1 xff0
  • 结构体中的位定义

    1 结构体位定义 在工作中 xff0c 经常遇到按位 xff08 bit xff09 定义结构体 的情况 由于一个字节有8个位 xff0c 这时 xff0c 程序员往往对bit的位置产生困惑 现在给出2个例子 xff0c 来说明位的定义次序
  • 蓝牙基础(三):蓝牙协议栈总体认知

    蓝牙基础 xff08 三 xff09 xff1a 蓝牙协议栈总体认知 0 前言 初入门经典蓝牙学习 xff0c 网上资料参差不齐 xff0c 本博客旨在整理自己的一些总结内容 xff0c 建立整体功能认识 xff0c 以便后续深入学习 1
  • FreeRTOS学习(四)任务调度与切换

    文章目录 1 任务调度2 任务切换2 1 SVC 和 PendSV2 2 上下文2 3 切换场景2 4 PendSV Handler 3 总结 1 任务调度 在建立完任务后紧接着调用任务调度函数 xff0c 便会使系统运行起来 span c
  • FreeRTOS学习(五)队列与信号量

    文章目录 1 队列1 1 队列特性1 2 队列创建1 2 1 接口函数1 2 2 内存占用1 2 3 创建过程分析 1 3 入队与出队1 3 1 队列项入队1 3 1 队列项出队 2 信号量2 1 二值信号量2 2 计数型信号量2 3 互斥