CMSIS-RTOS 线程间通信 Inter-Thread Communication

本文介绍RTOS环境下线程间通信的基础知识,特别是信号机制的使用。通过实例演示如何利用信号来实现线程间的同步,包括信号的设置与等待等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程间通信 Inter-Thread Communication

前面我们已经学习了如何把你的应用代码设计成独立的线程,以及如何访问RTOS的时间服务函数。在实际的工程应用中,线程间的通信是必不可少的,任何一个RTOS都会支持几种通信方式来连接各种不同的线程。CMSIS-RTOS API支持的通信方式有:信号(signals),信号量(semaphores),互斥锁(mutexes),邮箱(mailboxes)和消息队列(message queues)。所有这些首要的核心概念就是并发性。在这一章,将集中讨论多任务间的同步问题。

信号 Signals

CMSIS RTOS RTX支持单线程16种信号标志,这些信号存储在线程控制块里,一个线程会暂停执行,直到一个或一组信号标志被其他线程置位。

这里写图片描述

每个线程有16个信号标志,一个线程可能被置于等待状态,直到一种模式的信号被其他线程置位。然后此线程就会返回等待状态,并等待调度器调度到运行状态。

调用信号等待后,系统会挂起正在运行的线程,并把它置于等待事件(wait_event)状态,直到所有的信号标志被置位,线程才会恢复运行。当然也可以加入超时机制,以便让线程可以顺利返回等待状态。默认初始化超时值是0xFFFF。

osEvent osSignalWait(int32_t signals, uint32_t millisec);

调用osSignalWait之后会把信号复位,如果后面还有信号被置位,线程就可以继续执行,你可以读osEvent.value.signals的值来获取哪个标志被置位。

任何一个线程都可以置位或清除另外一个线程的信号:

int32_t osSinalSet(osThreadId thread_id, int32_t signals);
int32_t osSignalClear(osThreadId thread_id, int32_t signals);

练习:信号

在这个练习里,我们将学会如何在两个线程之间使用信号触发线程执行。

打开Pack Installer,并选择”Ex 8 Signals,然后install到你的自定义路径

从代码中可以看到,两个线程都是执行的LED闪烁程序,其中一个通过调用osDelay()暂停执行,同时置位一个信号来唤醒另外一个LED线程:

void led_Thread2(void const *argument){
    f(;;){
        LED_On(2);
        osSignalSet(T_led_ID1, 0x01);
        osDelay(500);
        LED_Off(2);
        osSignalSet(T_led_ID1, 0x01);
        osDelay(500);
    }
}

第二个线程等待信号被置位,然后才会执行LED闪烁程序:

void led_Thread1(void const *argument){
    for(;;){
        osSignalWait(0x01, osWaitFover);//无超时机制
        LED_On(1);
        osSignalWait(0x01, osWaitFover);
        LED_Off(1);
    }
}

编译工程,请启动debugger环境

打开GPIOB窗口,并全速运行代码
这里写图片描述

从窗口中可以看到两个管脚亮灭是同步的,给人的错觉就是两个LED线程是并行运行的。

这个例子虽然简单,却揭示了线程间同步的核心概念,而这又是RTOS最基本的应用。

### 基于STM32的智能家居FreeRTOS应用 #### 环境搭建与初始化设置 为了构建基于STM32并集成FreeRTOS的操作系统来管理智能家居系统的资源分配和任务调度,首先需要完成必要的硬件和软件准备工作。对于硬件部分,建议选用具备较高性能指标的STM32F4或STM32H7系列开发板,并配备相应的传感器组件如温湿度感应装置、光照强度检测单元等;同时还需要准备用于无线通讯的数据传输模块比如Wi-Fi芯片ESP8266或是蓝牙模组。 至于软件方面,则要安装适合嵌入式编程工作的IDE——STM32CubeIDE,并通过STM32CubeMX图形界面工具快速生成初始项目结构,其中包含了对FreeRTOS的支持[^1]。此外,还可以利用Keil MDK这类专业的编译平台辅助开发过程中的调试工作。 #### 创建多线程应用程序 一旦上述环境已经就绪,就可以着手设计一个多线程的应用场景了。下面给出一段简单的C语言源码片段展示如何定义两个独立运行的任务函数taskLedBlink() 和 taskSensorRead(), 它们分别负责控制LED闪烁频率以及读取来自各种类型的传感数据: ```c #include "stm32f4xx_hal.h" #include "cmsis_os.h" // LED引脚配置 #define LED_PIN GPIO_PIN_13 #define LED_GPIO_PORT GPIOD void StartDefaultTask(void const * argument); static void MX_FREERTOS_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); __HAL_RCC_GPIOD_CLK_ENABLE(); // 开启GPIO时钟 /* 初始化LED */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct); osKernelInitialize (); // Initialize CMSIS-RTOS osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, configMINIMAL_STACK_SIZE); osThreadCreate (osThread(defaultTask), NULL); MX_FREERTOS_Init(); osKernelStart (); } /* Task to blink an onboard LED */ void StartDefaultTask(void const * argument){ for(;;){ HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN); osDelay(500); } } /* Function prototypes for additional tasks can be added here */ /** * @brief This function is called from within the startup code and should not be modified. */ __weak void MX_FREERTOS_Init(void) { osThreadId_t tid; tid = osThreadNew(taskSensorRead, NULL, NULL); if(tid != NULL){ osThreadSetPriority(tid, osPriorityAboveNormal); } tid = osThreadNew(taskLedBlink, NULL, NULL); if(tid != NULL){ osThreadSetPriority(tid, osPriorityBelowNormal); } } ``` 这段代码展示了基本的任务创建流程,在`main()` 函数里调用了 `osKernelInitialize ()`, 接着定义了一个默认的任务 `defaultTask` 来周期性的切换LED状态。而在 `MX_FREERTOS_Init()` 中则进一步增加了另一个名为 `taskSensorRead` 的后台进程用来处理感知层的信息采集操作[^2]。 #### 实现高效的任务间通信机制 当涉及到更复杂的功能需求时,例如不同子系统之间的协调合作或者对外部命令作出响应等情况,就需要引入有效的IPC(Inter-process Communication)手段了。FreeRTOS提供了多种方式实现这一点,其中包括但不限于消息队列(queue),信号量(semaphore),事件标志(event flags)等等[^3]。 以上便是有关于基于STM32架构之上运用FreeRTOS操作系统来进行智能家居产品研发的一些指导性意见和技术细节说明。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值