STMicroelectronics 系列:STM32L0 系列_(13).STM32L0的实时操作系统支持

STM32L0的实时操作系统支持

实时操作系统的概述

实时操作系统(Real-Time Operating System,RTOS)是一种能够在指定时间内完成任务的操作系统。它主要用于嵌入式系统中,确保系统在预定的时间内响应外部事件。实时操作系统通常分为硬实时(Hard Real-Time)和软实时(Soft Real-Time)两种类型。硬实时系统要求在严格的时间限制内完成任务,否则可能导致严重的后果;软实时系统则允许一定的延迟,但尽量减少延迟以提高系统性能。

在嵌入式开发中,使用RTOS可以有效地管理任务调度、资源分配和中断处理,从而提高系统的可靠性和响应速度。STM32L0系列单片机支持多种RTOS,包括FreeRTOS、RT-Thread、ThreadX等。本节将详细介绍STM32L0系列单片机如何使用FreeRTOS来实现多任务管理。

FreeRTOS的简介

FreeRTOS是一个免费的、开源的实时操作系统,适用于小型嵌入式系统。它具有以下特点:

  • 轻量级:占用资源少,适合资源受限的嵌入式系统。

  • 可移植性:支持多种硬件平台,包括ARM Cortex-M系列。

  • 可配置性:用户可以根据需求配置不同的功能模块。

  • 任务调度:支持多种任务调度算法,确保任务按优先级执行。

  • 中断管理:有效管理中断,确保中断处理的及时性和可靠性。

  • FreeRTOS提供了一系列API,用于任务创建、任务调度、信号量、互斥量、队列等操作,使得开发者可以方便地编写多任务应用程序。

    STM32L0系列单片机上的FreeRTOS配置

    安装FreeRTOS库

    首先,需要在STM32CubeMX中配置FreeRTOS库。以下是具体步骤:

    1. 打开STM32CubeMX:启动STM32CubeMX软件。

    2. 选择目标单片机:在项目配置中选择STM32L0系列单片机。

    3. 配置时钟:根据项目需求配置系统时钟。

    4. 添加FreeRTOS:在“Middleware”选项卡中,选择“FreeRTOS”并添加到项目中。

    5. 配置FreeRTOS参数:在“FreeRTOS”配置页面中,设置任务优先级、栈大小等参数。

    6. 生成代码:点击“生成代码”按钮,生成包含FreeRTOS配置的初始化代码。

    配置FreeRTOS参数

    在生成的代码中,可以在FreeRTOSConfig.h文件中配置FreeRTOS的参数。以下是一些关键参数的配置:

    
    // FreeRTOSConfig.h
    
    
    
    #define configUSE_PREEMPTION                    1
    
    #define configMAX_PRIORITIES                    5
    
    #define configUSE_TICKLESS_IDLE                 0
    
    #define configUSE_PORT_OPTIMISATIONS             0
    
    #define configCPU_CLOCK_HZ                      ( SystemCoreClock )
    
    #define configTICK_RATE_HZ                      ( ( TickType_t ) 1000 )
    
    #define configMINIMAL_STACK_SIZE                ( ( uint16_t ) 128 )
    
    #define configMAX_TASK_NAME_LEN                 ( 12 )
    
    #define configUSE_TRACE_FACILITY                1
    
    #define configUSE_16_BIT_TICKS                  0
    
    #define configUSE_MUTEXES                       1
    
    #define configUSE_RECURSIVE_MUTEXES             1
    
    #define configUSE_COUNTING_SEMAPHORES           1
    
    #define configUSE_QUEUE_SETS                    1
    
    #define configUSE_TIME_SLICING                  1
    
    #define configUSE_NEWLIB_REENTRANT              1
    
    #define configUSE_IDLE_HOOK                     0
    
    #define configUSE_TICK_HOOK                     0
    
    #define configUSE_APPLICATION_TASK_TAG          0
    
    #define configUSE_TASK_NOTIFICATIONS            1
    
    #define configSUPPORT_STATIC_ALLOCATION         1
    
    #define configSUPPORT_DYNAMIC_ALLOCATION        1
    
    #define configTOTAL_HEAP_SIZE                   ( ( size_t ) ( 8 * 1024 ) )
    
    #define configMAX_TASK_NOTIFICATION_ARRAY_ENTRIES 3
    
    #define configMAX_TASK_NOTIFICATION_VALUE       ( ( uint32_t ) 0xffff )
    
    #define configUSE_MUTEX_LIST_ITEM_FLAG          1
    
    #define configQUEUE_REGISTRY_SIZE               8
    
    #define configCHECK_FOR_STACK_OVERFLOW          2
    
    #define configUSE_TASK_LISTING                  1
    
    #define configUSE_STATS_FORMATTING_FUNCTIONS    1
    
    #define configUSE_MALLOC_FAILED_HOOK            1
    
    #define configUSE_DNS_CACHE                     0
    
    #define configUSE_DNS_CACHE_DISABLE              1
    
    #define configUSE_IDLE_TASK_AS_TIMER_SERVICE    0
    
    #define configUSE_TIMERS                        1
    
    #define configTIMER_TASK_PRIORITY                ( 3 )
    
    #define configTIMER_QUEUE_LENGTH                5
    
    #define configTIMER_TASK_STACK_DEPTH             ( configMINIMAL_STACK_SIZE * 2 )
    
    #define configUSE_NEWLIB_REENTRANT              1
    
    #define configUSE_HEAP                          4
    
    #define configUSE_CORTUS                    0
    
    #define configUSE_FPU                           0
    
    #define configUSExFFFF                          0
    
    

    初始化FreeRTOS

    在生成的代码中,FreeRTOS的初始化通常在main.c文件中完成。以下是一个简单的初始化示例:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, NULL);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
        }
    
    }
    
    

    任务调度

    FreeRTOS使用优先级抢占式调度算法来管理任务。每个任务都有一个优先级,优先级高的任务会优先执行。如果多个任务优先级相同,FreeRTOS会使用时间片轮转调度算法。

    在上述示例中,Task1Task2分别创建了两个任务,优先级分别为1和2。Task2的优先级更高,因此在两个任务同时可运行时,Task2会优先执行。

    任务间的通信

    FreeRTOS提供了多种任务间通信机制,包括信号量、互斥量和队列。以下是一个使用信号量进行任务间通信的示例:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    #include "semphr.h"
    
    
    
    // 信号量句柄
    
    SemaphoreHandle_t xBinarySemaphore;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建二进制信号量
    
        xBinarySemaphore = xSemaphoreCreateBinary();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, NULL);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:发送信号量
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            xSemaphoreGive(xBinarySemaphore); // 发送信号量
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:接收信号量
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            if (xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdTRUE)
    
            {
    
                HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            }
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
        }
    
    }
    
    

    任务同步

    任务同步是指确保多个任务按照一定的顺序执行。FreeRTOS提供了多种同步机制,包括事件组、信号量和互斥量。以下是一个使用事件组进行任务同步的示例:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    #include "event_groups.h"
    
    
    
    // 事件组句柄
    
    EventGroupHandle_t xEventGroup;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建事件组
    
        xEventGroup = xEventGroupCreate();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, NULL);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:设置事件
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            xEventGroupSetBits(xEventGroup, 0x01); // 设置事件位0x01
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:等待事件
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            EventBits_t uxBits = xEventGroupWaitBits(xEventGroup, 0x01, pdFALSE, pdTRUE, portMAX_DELAY);
    
            if (uxBits & 0x01)
    
            {
    
                HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            }
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
        }
    
    }
    
    

    任务间的资源共享

    在多任务系统中,任务间的资源共享是一个常见问题。为了避免资源竞争,可以使用互斥量。以下是一个使用互斥量保护共享资源的示例:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    #include "semphr.h"
    
    
    
    // 共享资源
    
    uint32_t sharedResource = 0;
    
    
    
    // 互斥量句柄
    
    SemaphoreHandle_t xMutex;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建互斥量
    
        xMutex = xSemaphoreCreateMutex();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, NULL);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:访问共享资源
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE)
    
            {
    
                sharedResource++;
    
                HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
                xSemaphoreGive(xMutex);
    
            }
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:访问共享资源
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE)
    
            {
    
                sharedResource--;
    
                HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
                xSemaphoreGive(xMutex);
    
            }
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
        }
    
    }
    
    

    中断处理

    FreeRTOS支持中断处理,可以在中断服务例程中切换任务。以下是一个在中断服务例程中使用FreeRTOS API的示例:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    #include "queue.h"
    
    
    
    // 队列句柄
    
    QueueHandle_t xQueue;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    // 中断服务例程
    
    void EXTI0_1_IRQHandler(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建队列
    
        xQueue = xQueueCreate(10, sizeof(uint32_t));
    
    
    
        // 配置外部中断
    
        HAL_GPIO_EXTI_Config(GPIOA, GPIO_PIN_0);
    
        HAL_NVIC_SetPriority(EXTI0_1_IRQn, 1, 0);
    
        HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, NULL);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:接收中断消息
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            uint32_t message;
    
            if (xQueueReceive(xQueue, &message, portMAX_DELAY) == pdTRUE)
    
            {
    
                HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            }
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:发送中断消息
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
        }
    
    }
    
    
    
    // 中断服务例程
    
    void EXTI0_1_IRQHandler(void)
    
    {
    
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    
    }
    
    
    
    // 中断处理函数
    
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    
    {
    
        if (GPIO_Pin == GPIO_PIN_0)
    
        {
    
            uint32_t message = 1;
    
            xQueueSendFromISR(xQueue, &message, NULL);
    
            portYIELD_FROM_ISR(xQueueSendFromISR(xQueue, &message, NULL));
    
        }
    
    }
    
    

    任务优先级和时间片轮转

    FreeRTOS支持优先级抢占式调度和时间片轮转调度。优先级抢占式调度确保高优先级任务优先执行,而时间片轮转调度则在相同优先级的任务之间分配CPU时间。

    在上述示例中,Task1Task2的优先级分别为1和2。Task2的优先级更高,因此在两个任务同时可运行时,Task2会优先执行。如果Task1Task2的优先级相同,FreeRTOS会使用时间片轮转调度算法。

    任务的生命周期管理

    FreeRTOS提供了任务创建、删除和挂起等API,用于管理任务的生命周期。以下是一个示例,展示如何创建和删除任务:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    
    
    // 任务句柄
    
    TaskHandle_t xTaskHandle1 = NULL;
    
    TaskHandle_t xTaskHandle2 = NULL;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, &xTaskHandle1);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, &xTaskHandle2);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:周期性执行
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:周期性执行
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
        }
    
    }
    
    
    
    // 删除任务
    
    void DeleteTask1(void)
    
    {
    
        vTaskDelete(xTaskHandle1);
    
    }
    
    
    
    // 删除任务
    
    void DeleteTask2(void)
    
    {
    
        vTaskDelete(xTaskHandle2);
    
    }
    
    

    任务的挂起和恢复

    FreeRTOS允许任务挂起和恢复,从而实现更复杂的任务调度。挂起任务可以暂时停止任务的执行,而恢复任务则可以让被挂起的任务重新开始执行。这种机制对于优化系统资源使用和任务调度非常有用。

    以下是一个示例,展示如何挂起和恢复任务:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    
    
    // 任务句柄
    
    TaskHandle_t xTaskHandle1 = NULL;
    
    TaskHandle_t xTaskHandle2 = NULL;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, &xTaskHandle1);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, &xTaskHandle2);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:周期性执行
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:周期性执行,并控制任务1的挂起和恢复
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
    
    
            // 挂起任务1
    
            vTaskSuspend(xTaskHandle1);
    
            vTaskDelay(pdMS_TO_TICKS(2000)); // 延迟2000ms
    
    
    
            // 恢复任务1
    
            vTaskResume(xTaskHandle1);
    
            vTaskDelay(pdMS_TO_TICKS(3000)); // 延迟3000ms
    
        }
    
    }
    
    

    任务的删除

    除了挂起和恢复任务,FreeRTOS还提供了删除任务的功能。删除任务可以释放任务使用的资源,从而优化系统性能。以下是一个示例,展示如何创建和删除任务:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    
    
    // 任务句柄
    
    TaskHandle_t xTaskHandle1 = NULL;
    
    TaskHandle_t xTaskHandle2 = NULL;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    // 删除任务的函数
    
    void DeleteTask1(void);
    
    void DeleteTask2(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, &xTaskHandle1);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, &xTaskHandle2);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:周期性执行
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:周期性执行,并控制任务1的删除
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
    
    
            // 删除任务1
    
            DeleteTask1();
    
            vTaskDelay(pdMS_TO_TICKS(2000)); // 延迟2000ms
    
    
    
            // 重新创建任务1
    
            xTaskCreate(Task1, "Task1", 128, NULL, 1, &xTaskHandle1);
    
            vTaskDelay(pdMS_TO_TICKS(3000)); // 延迟3000ms
    
        }
    
    }
    
    
    
    // 删除任务1
    
    void DeleteTask1(void)
    
    {
    
        if (xTaskHandle1 != NULL)
    
        {
    
            vTaskDelete(xTaskHandle1);
    
            xTaskHandle1 = NULL; // 重置任务句柄
    
        }
    
    }
    
    
    
    // 删除任务2
    
    void DeleteTask2(void)
    
    {
    
        if (xTaskHandle2 != NULL)
    
        {
    
            vTaskDelete(xTaskHandle2);
    
            xTaskHandle2 = NULL; // 重置任务句柄
    
        }
    
    }
    
    

    任务的优先级调整

    在FreeRTOS中,任务的优先级可以在任务创建后进行调整。调整任务优先级可以动态改变任务的执行顺序,从而更好地适应系统的运行需求。以下是一个示例,展示如何调整任务的优先级:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    
    
    // 任务句柄
    
    TaskHandle_t xTaskHandle1 = NULL;
    
    TaskHandle_t xTaskHandle2 = NULL;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    // 调整任务优先级的函数
    
    void AdjustTaskPriority(void);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建任务
    
        xTaskCreate(Task1, "Task1", 128, NULL, 1, &xTaskHandle1);
    
        xTaskCreate(Task2, "Task2", 128, NULL, 2, &xTaskHandle2);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:周期性执行
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:周期性执行,并调整任务1的优先级
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
    
    
            // 调整任务1的优先级
    
            AdjustTaskPriority();
    
            vTaskDelay(pdMS_TO_TICKS(2000)); // 延迟2000ms
    
        }
    
    }
    
    
    
    // 调整任务1的优先级
    
    void AdjustTaskPriority(void)
    
    {
    
        if (xTaskHandle1 != NULL)
    
        {
    
            // 降低任务1的优先级
    
            vTaskPrioritySet(xTaskHandle1, 1);
    
    
    
            // 增加任务1的优先级
    
            vTaskPrioritySet(xTaskHandle1, 3);
    
        }
    
    }
    
    

    任务的定时功能

    FreeRTOS提供了一种定时任务的机制,可以创建定时器任务,这些任务会在指定的时间间隔内执行。以下是一个示例,展示如何创建和使用定时器任务:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    #include "timers.h"
    
    
    
    // 定时器句柄
    
    TimerHandle_t xTimer1 = NULL;
    
    TimerHandle_t xTimer2 = NULL;
    
    
    
    // 定时器回调函数
    
    void Timer1Callback(TimerHandle_t xTimer);
    
    void Timer2Callback(TimerHandle_t xTimer);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 创建定时器
    
        xTimer1 = xTimerCreate("Timer1", pdMS_TO_TICKS(500), pdTRUE, (void *) 1, Timer1Callback);
    
        xTimer2 = xTimerCreate("Timer2", pdMS_TO_TICKS(1000), pdTRUE, (void *) 2, Timer2Callback);
    
    
    
        // 启动定时器
    
        if (xTimer1 != NULL)
    
        {
    
            xTimerStart(xTimer1, 0);
    
        }
    
        if (xTimer2 != NULL)
    
        {
    
            xTimerStart(xTimer2, 0);
    
        }
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 定时器1的回调函数
    
    void Timer1Callback(TimerHandle_t xTimer)
    
    {
    
        (void) xTimer;
    
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
    }
    
    
    
    // 定时器2的回调函数
    
    void Timer2Callback(TimerHandle_t xTimer)
    
    {
    
        (void) xTimer;
    
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
    }
    
    

    任务的内存管理

    FreeRTOS提供了动态和静态内存管理机制,以适应不同的应用场景。动态内存管理使用分配函数(如pvPortMalloc)和释放函数(如vPortFree)来管理任务的内存。静态内存管理则使用预分配的内存来创建任务,从而避免动态内存分配的开销。

    以下是一个示例,展示如何使用静态内存管理来创建任务:

    
    // main.c
    
    
    
    #include "main.h"
    
    #include "stm32l0xx_hal.h"
    
    #include "FreeRTOS.h"
    
    #include "task.h"
    
    
    
    // 静态任务控制块和堆栈
    
    StaticTask_t xTaskBuffer1;
    
    StackType_t xStack1[128];
    
    
    
    StaticTask_t xTaskBuffer2;
    
    StackType_t xStack2[128];
    
    
    
    // 任务句柄
    
    TaskHandle_t xTaskHandle1 = NULL;
    
    TaskHandle_t xTaskHandle2 = NULL;
    
    
    
    // 任务处理函数
    
    void Task1(void *argument);
    
    void Task2(void *argument);
    
    
    
    int main(void)
    
    {
    
        HAL_Init();
    
        SystemClock_Config();
    
    
    
        // 使用静态内存创建任务
    
        xTaskHandle1 = xTaskCreateStatic(Task1, "Task1", 128, NULL, 1, xStack1, &xTaskBuffer1);
    
        xTaskHandle2 = xTaskCreateStatic(Task2, "Task2", 128, NULL, 2, xStack2, &xTaskBuffer2);
    
    
    
        // 启动调度器
    
        vTaskStartScheduler();
    
    
    
        // 以下是永远不会执行的代码
    
        while (1)
    
        {
    
        }
    
    }
    
    
    
    // 任务1:周期性执行
    
    void Task1(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    
            vTaskDelay(pdMS_TO_TICKS(500)); // 延迟500ms
    
        }
    
    }
    
    
    
    // 任务2:周期性执行
    
    void Task2(void *argument)
    
    {
    
        (void) argument;
    
    
    
        for (;;)
    
        {
    
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
    
            vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟1000ms
    
        }
    
    }
    
    

    总结

    通过上述示例,我们可以看到FreeRTOS在STM32L0系列单片机上的应用。FreeRTOS提供了一套丰富的API,用于任务创建、调度、通信、同步、资源管理和中断处理。这些功能使得开发多任务嵌入式系统变得更加高效和可靠。

    在实际开发中,根据项目的需求选择合适的配置和功能模块是非常重要的。FreeRTOS的可配置性使得开发者可以根据系统的资源和性能需求进行优化,从而实现最佳的系统性能。希望本节的内容对您在STM32L0系列单片机上使用FreeRTOS有所帮助。

    作者:kkchenkx

    物联沃分享整理
    物联沃-IOTWORD物联网 » STMicroelectronics 系列:STM32L0 系列_(13).STM32L0的实时操作系统支持

    发表回复