打印
[STM32H7]

STM32 的实时操作系统入门

[复制链接]
115|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kmnqhaha|  楼主 | 2024-12-9 17:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在嵌入式系统中,使用实时操作系统来管理任务和资源是一个常见的需求。
STM32 微控制器作为一种广泛使用的嵌入式平台,支持多种 RTOS 的移植,包括 FreeRTOS 和 embOS 等。
RTOS 使得多任务并行执行、任务调度、时间管理以及同步操作变得更加简便和高效。

在本教程中,我们将探讨如何在 STM32 上移植 FreeRTOS,并基于 RTOS 进行应用设计,涵盖任务创建、时间管理、消息队列、信号量等功能。

1. RTOS 介绍:FreeRTOS 与 embOS
1.1 FreeRTOS
FreeRTOS 是一个开源的实时操作系统内核,它非常轻量,适合用于嵌入式系统。
FreeRTOS 支持多任务调度、内存管理、任务间通信、定时器等功能。
它是最常用的嵌入式 RTOS 之一,广泛支持 STM32 和其他微控制器平台。

1.2 embOS
embOS 是由 Segger 提供的一种高效的实时操作系统,专为嵌入式应用设计。
embOS 提供多任务调度、时间管理、互斥锁、信号量等高级特性。
虽然它是商业软件,但具有优异的性能和可靠性。

使用特权

评论回复
沙发
kmnqhaha|  楼主 | 2024-12-9 17:09 | 只看该作者
FreeRTOS 在 STM32 上的移植与使用
下面我们将详细介绍如何在 STM32 上移植 FreeRTOS,并实现一个基本的多任务调度应用。

2.1 在 STM32CubeMX 中启用 FreeRTOS
创建 STM32 项目: 使用 STM32CubeMX 创建一个新的 STM32 项目,选择合适的 STM32 微控制器例如 STM32F103、STM32F407 等。

启用 FreeRTOS: 在 STM32CubeMX 中,导航到 Middleware -> FreeRTOS,启用 FreeRTOS 支持。CubeMX 会自动为你配置 FreeRTOS 内核,并生成相应的代码框架。

配置 FreeRTOS: 在 STM32CubeMX 中,可以设置 FreeRTOS 的参数,如堆栈大小、任务优先级等。CubeMX 会生成 FreeRTOSConfig.h 文件,允许开发者自定义 FreeRTOS 配置选项。

生成代码: 配置完成后,点击 Project -> Generate Code,STM32CubeMX 将自动生成项目代码,并为 FreeRTOS 提供初始化代码。

打开项目: 打开生成的 STM32 项目通常是 Keil、IAR 或 STM32CubeIDE。

使用特权

评论回复
板凳
kmnqhaha|  楼主 | 2024-12-9 17:09 | 只看该作者
FreeRTOS 的核心概念
任务: 每个任务代表一个可独立执行的代码块。任务是操作系统调度的最小单元。
任务调度: FreeRTOS 提供了基于优先级的任务调度,可以按任务的优先级顺序执行任务。
时间管理: 通过定时器、延时等功能管理任务的执行时机。
任务同步: 使用信号量、消息队列等机制进行任务间同步与通信。

使用特权

评论回复
地板
kmnqhaha|  楼主 | 2024-12-9 17:10 | 只看该作者
创建和调度任务
在 FreeRTOS 中,任务创建和调度非常简单。任务通常是一个无限循环,处理具体的应用逻辑。

以下是如何创建和调度任务的代码示例:

c
复制代码
#include "FreeRTOS.h"
#include "task.h"

// 任务句柄
TaskHandle_t Task1Handle = NULL;
TaskHandle_t Task2Handle = NULL;

// 任务1函数
void Task1(void *pvParameters)
{
    while(1)
    {
        // 任务1执行代码
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);  // 切换 GPIO 状态
        vTaskDelay(pdMS_TO_TICKS(1000));  // 延时1秒
    }
}

// 任务2函数
void Task2(void *pvParameters)
{
    while(1)
    {
        // 任务2执行代码
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);  // 切换 GPIO 状态
        vTaskDelay(pdMS_TO_TICKS(500));  // 延时0.5秒
    }
}

int main(void)
{
    // HAL 初始化
    HAL_Init();

    // FreeRTOS 启动之前的初始化
    SystemClock_Config();

    // 创建任务
    xTaskCreate(Task1, "Task1", 128, NULL, 1, &Task1Handle);
    xTaskCreate(Task2, "Task2", 128, NULL, 2, &Task2Handle);

    // 启动调度器
    vTaskStartScheduler();

    // 如果调度器成功启动,程序不会执行到这里
    while(1);
}

使用特权

评论回复
5
kmnqhaha|  楼主 | 2024-12-9 17:10 | 只看该作者
调度器与任务调度
在 FreeRTOS 中,调度器负责根据任务的优先级顺序来执行任务。
调度器在 vTaskStartScheduler() 被调用时启动,任务将在各自的优先级上运行。

vTaskDelay:用于延时任务,参数是延时的 tick 数。pdMS_TO_TICKS() 用于将毫秒转换为 FreeRTOS 的 tick。
任务优先级:任务创建时指定的优先级决定了其在调度中的执行顺序。高优先级任务会抢占低优先级任务。
2.5 任务同步与通信:信号量、队列
FreeRTOS 提供了多种任务间同步和通信的机制,如信号量、消息队列、事件组等。

使用特权

评论回复
6
kmnqhaha|  楼主 | 2024-12-9 17:10 | 只看该作者
信号量
信号量用于控制任务间的资源访问,避免冲突。

c
复制代码
SemaphoreHandle_t xSemaphore = NULL;

// 在任务1中获取信号量
void Task1(void *pvParameters)
{
    while(1)
    {
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE)
        {
            // 获取到信号量,执行任务
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// 在任务2中释放信号量
void Task2(void *pvParameters)
{
    while(1)
    {
        // 执行任务
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
        xSemaphoreGive(xSemaphore);  // 释放信号量
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
   
    // 创建信号量
    xSemaphore = xSemaphoreCreateBinary();

    // 创建任务
    xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
    xTaskCreate(Task2, "Task2", 128, NULL, 2, NULL);

    // 启动调度器
    vTaskStartScheduler();
    while(1);
}

使用特权

评论回复
7
kmnqhaha|  楼主 | 2024-12-9 17:11 | 只看该作者
消息队列
消息队列用于在任务之间传递数据,避免共享内存访问的冲突。

c
复制代码
QueueHandle_t xQueue = NULL;

// 任务1:发送数据到队列
void Task1(void *pvParameters)
{
    int32_t data = 100;
    while(1)
    {
        xQueueSend(xQueue, &data, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// 任务2:接收数据并处理
void Task2(void *pvParameters)
{
    int32_t receivedData;
    while(1)
    {
        if (xQueueReceive(xQueue, &receivedData, portMAX_DELAY) == pdTRUE)
        {
            // 处理接收到的数据
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        }
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    // 创建消息队列
    xQueue = xQueueCreate(10, sizeof(int32_t));

    // 创建任务
    xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
    xTaskCreate(Task2, "Task2", 128, NULL, 2, NULL);

    // 启动调度器
    vTaskStartScheduler();
    while(1);
}

使用特权

评论回复
8
kmnqhaha|  楼主 | 2024-12-9 17:11 | 只看该作者
STM32 上的 FreeRTOS 移植与使用能够有效地管理多任务、任务同步与通信。在使用 FreeRTOS 时,开发者需要理解任务调度、优先级管理、任务间同步与通信等基本概念。通过合理使用任务、信号量、消息队列等机制,能够更高效地设计嵌入式系统应用。

随着开发的深入,你还可以使用 定时器、互斥锁、事件组 等功能,进一步提升系统的实时性与效率。

使用特权

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

本版积分规则

41

主题

225

帖子

1

粉丝