FreeRTOS多核支持

个人博客:blogs.wurp.top

简介

1. 多核支持概述

在传统的单核系统中,FreeRTOS 通常运行在一个 CPU 核心上,负责任务调度、中断处理和资源管理。然而,在多核系统中,多个核心可以并行执行不同的任务或线程,从而提升系统的性能和响应能力。

2. 多核支持方式

共享内存模型:多个核心共享同一块内存,通过锁机制协调访问。分布式模型:每个核心独立运行一个 FreeRTOS 实例,各自维护自己的任务队列和资源。

3. FreeRTOS典型应用场景

  • 分布式计算任务:

    每个核心运行独立的任务,分别处理不同的计算任务。通过队列或信号量协调任务之间的数据交换。

  • 实时任务与非实时任务分离:

    将实时任务分配给一个核心,非实时任务分配给另一个核心。使用互斥锁或信号量保证任务间的同步。

  • 多核协同处理:

    多个核心协同完成复杂任务(如图像处理、网络通信等)。通过共享内存或消息队列进行数据传输。

FreeRTOS多核架构

1. 单核与多核系统的区别

特性单核系统多核系统
运行环境一个 CPU 核心多个 CPU 核心
任务调度抢占式或时间片轮转可以分配到不同核心
资源管理单一核心管理需要协调多个核心
通信与同步简单更加复杂
性能与效率适合小规模应用更高并发和性能
开发与调试相对简单更加复杂

2. FreeRTOS多核支持的实现方式

  • 在 FreeRTOS 中,多核支持主要分为以下两种架构类型:

    架构类型描述
    SMP(对称多处理)所有核心共享相同的内存和资源,由同一个 FreeRTOS 内核管理。
    AMP(异步多处理)每个核心运行独立的 FreeRTOS 实例,彼此之间通过通信机制进行交互
  • FreeRTOS 支持多种多核平台,包括但不限于:

    ARM Cortex-M7/M4/M3:支持 SMP 和 AMP 模式。

    RISC-V:支持多核架构。

    Xilinx Zynq UltraScale+ MPSoC:支持多核 FreeRTOS 配置。

    TI AM335x 系列:支持多核 FreeRTOS 应用。

3. 多核任务调度机制

  • FreeRTOS 的任务调度是基于优先级的抢占式调度。在多核环境中,调度机制如下:

    • 本地调度:每个核心维护自己的就绪任务列表,并根据优先级进行调度。
    • 任务迁移:某些版本支持任务在不同核心之间迁移,以平衡负载。
    • 中断处理:中断可以在任意核心上处理,但需要确保中断服务程序(ISR)的可重入性和同步。

多核支持的关键技术

1. 互斥锁(Mutex)

  • 在多核环境中,多个核心可能会同时访问共享资源。为了防止竞态条件,FreeRTOS 提供了互斥锁(xSemaphoreCreateMutex())来确保同一时间只有一个核心可以访问 共享资源。
    SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();void vTaskFunction(void *pvParameters) {if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {// 访问共享资源xSemaphoreGive(xMutex);}
    }
    

2. 信号量(Semaphore)

  • 信号量用于控制对共享资源的访问或任务之间的同步。FreeRTOS 提供了二值信号量(Binary Semaphore)、计数信号量(Counting Semaphore)和递归信号量 (Recursive Semaphore)。
    SemaphoreHandle_t xBinarySemaphore = xSemaphoreCreateBinary();void vTaskFunction(void *pvParameters) {if (xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdTRUE) {// 任务执行逻辑xSemaphoreGive(xBinarySemaphore);}
    }
    

3. 队列(Queue)

  • 队列是 FreeRTOS 中任务间通信的核心机制之一。在多核系统中,可以通过队列传递数据或事件,实现跨核通信。
    QueueHandle_t xQueue = xQueueCreate(10, sizeof(int));void vTaskFunction(void *pvParameters) {int data = 42;xQueueSend(xQueue, &data, portMAX_DELAY);
    }
    

4. 任务调度器(Scheduler)

  • 在多核系统中,FreeRTOS 可以配置为在多个核心上运行独立的调度器。每个核心的任务调度器独立运行,但可以通过共享资源进行协调。
    // 启动任务调度器(适用于多核)
    vTaskStartScheduler();
    

FreeRTOS多核配置(以ARM Cortex-M7为例)

1. 硬件支持:确保使用的微控制器支持多核架构(如双核Cortex-M7)。

2. 内核配置:

  • 启用configMULTI_CORE选项。
  • 设置configNUM_CORES为实际的核数。
  • 任务创建:
    使用xTaskCreatePinnedToCore()函数将任务绑定到特定的核心。
  • 资源同步:
    使用xSemaphoreCreateBinary()或xQueueCreate()等机制进行任务间的通信。
  • 中断配置:
    将关键中断绑定到特定的核心,避免抢占问题。

3. 示例代码

#include "FreeRTOS.h"
#include "task.h"
void vTaskFunction(void *pvParameters) {while (1) {// 任务逻辑vTaskDelay(pdMS_TO_TICKS(1000));}
}
int main(void) {xTaskCreatePinnedToCore(vTaskFunction, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL, 0);xTaskCreatePinnedToCore(vTaskFunction, "Task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL, 1);vTaskStartScheduler();for (;;);
}

多核任务调度

1. 任务分配策略

在多核系统中,合理的任务分配策略能够提升系统的性能和稳定性。常见的任务分配策略包括:

  • 静态分配(Static Allocation)

    任务在启动时就被分配到特定的核心。适用于对实时性要求高且任务数量固定的场景。

    优点:可预测性强,减少任务迁移开销。

    缺点:灵活性差,难以适应动态负载变化。

  • 动态分配(Dynamic Allocation)

    任务根据当前核心的负载情况动态分配。适用于负载不稳定的场景。

    优点:提高资源利用率,优化系统性能。

    缺点:可能增加任务迁移的开销。

  • 基于优先级的分配(Priority-Based Allocation)

    高优先级任务优先分配到空闲的核心。适用于对响应时间敏感的应用。

    优点:保证关键任务的实时性。

    缺点:可能导致低优先级任务长时间得不到执行。

  • 基于负载的分配(Load-Balanced Allocation)

    根据每个核心的负载情况动态分配任务。适用于多核系统中负载不均的场景。

    优点:平衡各核心负载,提高整体性能。

    缺点:需要额外的负载监控机制。

2. 负载均衡

  • 目标:负载均衡的目标是将任务均匀地分配到各个核心上,避免某些核心过载而其他核心空闲,从而提高系统吞吐量和响应速度。

  • 实现方式
    动态任务迁移:根据各核心的负载情况,自动将任务迁移到较为空闲的核心上运行。

    任务优先级调整:通过调整任务优先级,确保高优先级任务能够及时得到处理。

    负载监控:定期检查各核心的负载状态,为调度决策提供依据。

3. 任务优先级与抢占

  • 任务优先级

    在 FreeRTOS 中,每个任务都有一个优先级值,用于决定其调度顺序。优先级越高,任务越有可能被调度执行。
    优先级范围
    通常为 0 到 (configMAX_PRIORITIES - 1);0 表示最低优先级,configMAX_PRIORITIES - 1 表示最高优先级。
    优先级设置

    xTaskCreate(vTaskFunction,        // 任务函数"TaskName",           // 任务名称STACK_SIZE,           // 堆栈大小NULL,                 // 任务参数tskIDLE_PRIORITY + 1, // 任务优先级&xTaskHandle          // 任务句柄
    );
    
  • 抢占机制

    reeRTOS 支持 抢占式调度,即高优先级任务可以中断低优先级任务的执行。

    抢占规则

    当高优先级任务就绪时,它会立即抢占当前正在运行的低优先级任务。抢占行为仅在任务处于“就绪状态”时发生。

    抢占模式

    完全抢占:高优先级任务可以随时抢占低优先级任务。

    部分抢占:某些情况下,抢占可能受限(如任务处于临界区)。

    在多核环境中,任务的优先级和抢占行为仍然遵循上述规则,但可能会受到以下因素影响:

      任务绑定:如果任务绑定到特定核心,则优先级和抢占仅在该核心内生效。核心间通信:跨核心的任务交互需要考虑同步机制,例如使用队列、信号量等。
    

4. 多核任务同步机制

同步机制描述
互斥锁(Mutex)用于保护共享资源,确保同一时间只有一个任务可以访问资源。
信号量(Semaphore)用于任务之间的通信,控制对共享资源的访问。
队列(Queue)用于任务之间传递数据或事件信息。
事件组(Event Group)用于任务之间传递多个事件的状态信息。
任务通知(Task Notification)一种轻量级的通信方式,用于任务之间的直接通知。

多核通信与同步

1. 消息队列与信号量

  • 消息队列是一种用于任务间或中断服务程序与任务之间传递数据的机制。它支持先进先出(FIFO)或后进先出(LIFO)的数据传输方式。

    QueueHandle_t xQueue;// 创建消息队列
    xQueue = xQueueCreate(10, sizeof(uint32_t));// 发送消息
    uint32_t data = 0x1234;
    xQueueSend(xQueue, &data, portMAX_DELAY);// 接收消息
    uint32_t receivedData;
    xQueueReceive(xQueue, &receivedData, portMAX_DELAY);
    
  • 信号量是一种用于控制对共享资源访问的同步机制。它可以用来实现任务间的同步、互斥访问等。

    // 创建二值信号量
    SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();// 获取信号量(阻塞等待)
    xSemaphoreTake(xSemaphore, portMAX_DELAY);// 释放信号量
    xSemaphoreGive(xSemaphore);
    

2. 共享内存与互斥锁

  • 共享内存是一种允许多个任务或核心访问同一块内存区域的机制。在 FreeRTOS 中,通常通过以下方式实现共享内存:

    使用全局变量或静态变量。

    使用 Heap 区域分配的动态内存(如 pvPortMalloc())。

    使用特定的内存映射机制(依赖于硬件平台)。

  • 互斥锁是一种用于保护共享资源的同步机制,确保在同一时间只有一个任务可以访问受保护的代码段。

    SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();void TaskA(void *pvParameters) {while (1) {xSemaphoreTake(xMutex, portMAX_DELAY); // 获取互斥锁// 访问共享内存xSemaphoreGive(xMutex); // 释放互斥锁}
    }void TaskB(void *pvParameters) {while (1) {xSemaphoreTake(xMutex, portMAX_DELAY); // 获取互斥锁// 访问共享内存xSemaphoreGive(xMutex); // 释放互斥锁}
    }
    

3. 事件组与标志位

  • 事件组是 FreeRTOS 中一种用于任务间通信和同步的机制,主要用于任务等待多个事件的发生,或者通知其他任务某个事件已经发生。
    // 定义事件组
    EventGroupHandle_t xEventGroup;// 初始化事件组
    xEventGroup = xEventGroupCreate();// 任务 A:等待事件
    void vTaskA(void *pvParameters)
    {EventBits_t uxBits;// 等待事件 0x01 和 0x02 同时发生uxBits = xEventGroupWaitBits(xEventGroup, 0x03, pdTRUE, pdTRUE, portMAX_DELAY);if ((uxBits & 0x01) && (uxBits & 0x02)){// 所有事件已触发}
    }// 任务 B:设置事件
    void vTaskB(void *pvParameters)
    {// 设置事件 0x01xEventGroupSetBits(xEventGroup, 0x01);// 设置事件 0x02xEventGroupSetBits(xEventGroup, 0x02);
    }
    
  • 标志位是事件组的一个子集,通常用于表示简单的状态变化。它比事件组更轻量,适合用于单个状态的标记。
    // 定义标志位
    volatile uint32_t ulFlag = 0;// 任务 A:等待标志位
    void vTaskA(void *pvParameters)
    {while (1){if (ulFlag & 0x01){// 标志位 0x01 被设置ulFlag &= ~0x01; // 清除标志位}vTaskDelay(pdMS_TO_TICKS(100));}
    }// 任务 B:设置标志位
    void vTaskB(void *pvParameters)
    {while (1){// 设置标志位 0x01ulFlag |= 0x01;vTaskDelay(pdMS_TO_TICKS(500));}
    }
    

4. 多核中断处理

  • 在 FreeRTOS 中支持多核系统(如基于多核处理器的嵌入式设备),多核之间的通信和同步是实现任务协调的关键。
    // 将任务绑定到核心
    void vTaskFunction(void *pvParameters) {while (1) {// 任务逻辑}
    }// 创建任务并绑定到核心
    xTaskCreatePinnedToCore(vTaskFunction, "Task", 2048, NULL, 1, NULL, 1);// 设置中断处理函数
    void vMyInterruptHandler(void) {// 中断处理逻辑xTaskGenerateSoftwareInterrupt(0); // 触发任务
    }
    

结论

FreeRTOS多核支持的优势

  • 提高系统性能

    多核架构允许同时执行多个任务,从而提升系统的整体性能。FreeRTOS 支持将任务分配到不同的核心上运行,充分利用多核处理器的计算能力。

  • 增强实时性

    在多核系统中,关键任务可以被分配到特定的核心上运行,避免因其他任务的干扰而影响实时响应。这有助于实现更精确的时序控制和更低的延迟。

  • 任务隔离与安全性

    多核支持使得不同任务可以在独立的内核上运行,减少任务之间的相互干扰。提高了系统的稳定性和安全性,尤其适用于需要高可靠性的应用。

  • 灵活的任务调度

    FreeRTOS 支持多种任务调度策略,并可根据多核架构进行优化。用户可以根据需求选择适合的调度方式,以适应不同的应用场景。

  • 简化开发与维护

    使用多核 FreeRTOS 可以通过模块化设计,将功能拆分到不同的核心上,便于开发和维护。开发者可以专注于各自核心上的功能实现,降低整体复杂度。

  • 兼容现有生态

    FreeRTOS 的多核支持与现有的 API 和工具链保持兼容,开发者无需重写大量代码即可利用多核优势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95672.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95672.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CUDA中的基本概念

要学习cuda的同学相信已经对其有一定的了解了,至少直到它是干什么的了。这篇文章主要是对cuda编程中的主要概念进行总结,有了一个大致的轮廓后就好入手了。 异构架构 异构架构即使用CPU和GPU共同进行计算。GPU不能作为一个独立的运行平台(程序…

【LINUX网络】HTTP协议基本结构、搭建自己的HTTP简单服务器

目录 1. 初识HTTP 2. URL 2.1 基本结构 2.2 URL中的?与urldecode\urlencode 易混淆:URL和HTTP传输请求两者是什么关系? HTTP的宏观结构 3. DEMO CODE loop模块,核心逻辑 HttpServer 初代版本(DEMO 0.0) DEMO 1.0 DEMO…

Spring Boot 静态函数无法自动注入 Bean?深入解析与解决方案

在 Spring Boot 项目中,开发者常遇到一个典型问题:在静态方法或静态变量中尝试使用 Autowired 注入 Bean 时,始终得到 null 值。本文将深入剖析这一问题的根源,并提供多种可靠解决方案。问题重现:为什么注入失败&#…

存储过程作为系统逻辑核心的架构思考 —— 以 SaaS 系统为例

在企业级系统尤其是 SaaS 架构中,技术选型一旦确定,就意味着底层数据库类型基本不会轻易更换。既然如此,我们可以更大胆地将数据库能力本身纳入系统设计的核心,而不仅仅把它当成一个被动的存储引擎。存储过程(Stored P…

Ubuntu20.04下Remmina的VNC密码忘记后重置

你遇到的错误: ** error creating password: /home/ysc/.vnc/passwd storepasswd: No such file or directory说明:x11vnc -storepasswd 无法创建密码文件,因为 .vnc 目录不存在。 虽然你可能以为路径是对的,但系统找不到 /home/y…

从“存得对”到“存得准”:MySQL 数据类型与约束全景指南

目录 一、为什么需要数据类型与约束? 二、MySQL 数据类型全览 1. 数值类型:精确 VS 近似 2. 日期时间类型:别让“0000-00-00”出现 3. 字符串类型:CHAR、VARCHAR、TEXT、BLOB 4. JSON 类型:文档与关系共舞 5. 空…

Effective C++ 条款42:了解 typename 的双重含义

Effective C 条款42:了解typename的双重含义 核心思想:在模板声明中,typename和class可互换使用,但在模板内部,typename必须用于显式指明嵌套从属类型名称(nested dependent type name)&#xf…

ENCOPIM, S.L. 参展 AUTO TECH China 2025 广州国际汽车技术展览会

ENCOPIM, S.L. 参展 AUTO TECH China 2025 广州国际汽车技术展览会2025年11月21-24日中国进出口商品交易会展馆D区(广州)AUTO TECH China 2025同期:第二十三届广州车展即将盛大开幕展商推荐ENCOPIM, S.L.展位号:3916企业简介:ENCOPIM, S.L.于…

30 HTB Soccer 机器 - 容易

主要知识点 第一阶段:侦查 nmap nmap快速扫描: oxdfhacky$ nmap -p- --min-rate 10000 10.10.11.194 Starting Nmap 7.80 ( https://nmap.org ) at 2023-06-04 13:32 EDT Nmap scan report for 10.10.11.194 Host is up (0.093s latency). Not shown:…

阿里云机器翻译接口SDK-RAM权限配置

用户授权翻译权限在数字化时代,短信作为企业与用户沟通的重要桥梁,其高效、可靠的送达直接影响业务转化与用户体验。SDK(软件开发工具包)的出现极大简化了短信功能的集成过程,让开发者能够快速在应用中嵌入短信验证、通…

ESXI 6.7服务器时间错乱问题

1. 设置ESXI服务器:在此主机上手动配置日期和时间管理-服务-ntpd-鼠标右键-策略-手动启动和停止,状态已停止管理-系统-时间和日期-编辑设置-检查是否选择了【在此主机上手动配置日期和时间】ntp服务状态已停止ntp服务器已停止2. 停止所有虚拟机自动更新时…

CV 医学影像分类、分割、目标检测,之【皮肤病分类】项目拆解

CV 医学影像分类、分割、目标检测,之【皮肤病分类】项目拆解第1-12行:导入库第14-17行:读取标签文件第19-21行:获取疾病名称第23-26行:获取图片名列表第28-35行:筛选有标签的图片第38-43行:提取…

【JavaEE】多线程 -- 线程状态

目录六大状态举例说明六大状态 New 新建状态:线程还没出创建,只有Thread 实例化的对象,调用start 方法之前的状态。Runnable 运行状态:被系统调度后,CPU 正在执行的,Ready 就绪态,系统调度&…

网络流初步

网络流初步 文章目录网络流初步概念介绍最大流费用流概念介绍 网络流不同之处在于它的本质图论,但是把图论的某些概念换了一个说法而已,初步只要了解网络流的各个概念就可以明白的很快。 下述概念是本人自己定义的,对于网络流的题目做的还不…

[系统架构设计师]系统架构基础知识(一)

[系统架构设计师]系统架构基础知识(一) 一.计算机系统基础知识 1.计算机系统概述 硬件软件及网络组成的系统 2.计算机硬件基础知识 冯 诺依曼结构:运算器,控制器,存储器,输入设备,输出设备 专用…

深入解析Java代理模式:灵活控制对象访问的核心技术

在日常开发中,我们常遇到这样的场景:需要控制对象访问权限、优化高成本操作,或给方法添加额外功能(如日志、事务)。代理模式(Proxy Pattern) 正是解决这类问题的金钥匙。作为结构型设计模式的代…

【学习笔记】Java并发编程的艺术——第9章 Java中的线程池

第9章 Java中的线程池 线程池优势: ①减少资源消耗 ②提高响应速度 ③统一管理 9.1 线程池的实现原理 当任务来后 ①判断核心线程池是否已满,若未满,创建一个核心线程来执行任务 ②若无空闲核心线程且核心线程已满,则将任务放入任…

Mybatis学习笔记(九)

常见问题与解决方案 简要描述:总结MyBatis-Plus开发过程中常见的问题、错误及其解决方案,帮助开发者快速定位和解决问题。 核心概念: 常见错误:开发中经常遇到的错误类型性能问题:性能相关问题的排查和解决配置问题&am…

数据类型 list

一、介绍类似于数组,顺序表,deque结构图特点:元素有序,元素允许重复由于头尾高效插入删除,可以模拟栈,队列二、常见 list 命令1、lpush key elem [elem ...]头插元素,返回值列表长度2、lrange k…

pyqt5无法显示opencv绘制文本和掩码信息

背景:pyqt5无法显示opencv绘制的标签和mask;我们在使用YOLO做实例分割做推理时,会使用opencv做后处理结果绘制(含标签绘制和掩码绘制);结果opencv绘制的解码却无法在pyqt的解码上面显示。pyqt转换代码如下&…