在这里插入图片描述

每日一句正能量

真正的善,是先对自己慈悲,再对世界温柔。
对外人极尽温柔,对自己冷酷刻薄。结果要么耗竭,要么委屈。对自己慈悲≠自私,而是先填满自己的能量池,溢出来的部分,才是健康可循环的温柔。否则,温柔会变成交换、牺牲或道德绑架。


一、引言:多核时代的嵌入式挑战

随着半导体工艺的发展,嵌入式处理器已从单核时代迈入多核时代。从NXP i.MX7(Cortex-A7 + Cortex-M4)、Xilinx Zynq MPSoC(Cortex-A53 + Cortex-R5)到STM32MP1(Cortex-A7 + Cortex-M4),异构多核SoC已成为工业控制、汽车电子、通信设备等领域的主流选择。

然而,多核架构给嵌入式开发者带来了新的技术挑战:

  1. 架构选择困境:面对AMP(非对称多处理)和SMP(对称多处理)两种架构,如何根据应用场景做出正确选择?
  2. 核间通信复杂度:不同核心运行不同操作系统时,如何实现高效、可靠的数据交换?
  3. 负载均衡难题:在SMP架构下,如何让多个核心协同工作,避免"一核有难、多核围观"的局面?

本文将深入剖析AMP与SMP的技术原理、核间通信机制和负载均衡策略,帮助开发者在实际项目中做出最优架构决策。


二、AMP与SMP架构对比

2.1 架构定义与核心差异

在这里插入图片描述

AMP(Asymmetric Multiprocessing,非对称多处理)

  • 每个核心运行独立的操作系统实例(如Core 0运行Linux,Core 1运行FreeRTOS)
  • 各核心拥有独立的内存空间,通过共享内存区域进行通信
  • 核心之间是主从关系对等关系,各自承担不同角色
  • 典型应用:工业网关、汽车ECU、通信基站

SMP(Symmetric Multiprocessing,对称多处理)

  • 所有核心运行同一个操作系统实例(如FreeRTOS SMP)
  • 所有核心共享统一的内存地址空间
  • 核心之间是完全对等关系,由全局调度器统一调度
  • 典型应用:高吞吐网络处理、并行信号处理、通用多任务系统

2.2 关键特性对比

维度 AMP SMP
OS支持 每个核心可运行不同OS 所有核心运行同一OS
内存模型 独立内存 + 共享内存区域 统一共享内存
调度方式 各OS独立调度 全局统一调度
实时性 强(实时核不受干扰) 中(需考虑调度开销)
开发复杂度 高(需处理核间通信) 低(类似单核开发)
适用场景 异构系统、实时+非实时 同构系统、高并行计算

三、核间通信(IPC)机制详解

3.1 核间通信架构

在AMP架构中,核间通信是系统的核心挑战。以Linux + FreeRTOS的典型配置为例:

在这里插入图片描述

核间通信的核心组件:

  1. 共享内存(Shared Memory):作为数据传输的物理载体
  2. 软件中断(SGI/IPI):用于通知对方核心有新数据到达
  3. 内存屏障(DMB/DSB):确保缓存一致性

3.2 OpenAMP框架

OpenAMP(Open Asymmetric Multi-Processing)是目前最主流的AMP核间通信框架,它提供了标准化的生命周期管理(LCM)和进程间通信(IPC)能力。

OpenAMP三大核心组件:

组件 功能 对应Linux子系统
RemoteProc 远程处理器生命周期管理(启动/停止/加载固件) Linux remoteproc
RPMsg 基于消息的核心间通信 Linux rpmsg
VirtIO 虚拟设备抽象层,管理共享内存和vring Linux virtio

RPMsg消息格式:

+------------------+------------------+------------------+
|   src (32bit)    |   dst (32bit)    |   reserved       |
|  (源端点地址)     |  (目标端点地址)   |   (保留对齐)      |
+------------------+------------------+------------------+
|   len (16bit)    |   flags (16bit)  |   Payload...     |
|  (数据长度)       |   (标志位)        |   (用户数据)     |
+------------------+------------------+------------------+

3.3 核间通信代码实战

以下是在STM32MP1平台上,基于OpenAMP实现Linux(Cortex-A7)与FreeRTOS(Cortex-M4)核间通信的完整示例:

/* ============================================
 * AMP核间通信示例 - FreeRTOS侧 (Cortex-M4)
 * 平台: STM32MP1
 * 框架: OpenAMP + RPMsg
 * ============================================ */

#include "openamp.h"
#include "rpmsg.h"
#include "FreeRTOS.h"
#include "task.h"

/* 共享内存配置 (由设备树定义) */
#define RPMSG_SHARED_MEMORY_BASE    0x10040000
#define RPMSG_SHARED_MEMORY_SIZE    0x40000   /* 256KB */

/* RPMsg端点配置 */
#define RPMSG_SERVICE_NAME          "rpmsg-sensor"
#define RPMSG_ENDPOINT_ADDR         0x401     /* 本地端点地址 */

/* 消息结构体 */
typedef struct {
    uint32_t sensor_id;
    float temperature;
    float humidity;
    uint32_t timestamp;
} SensorData_t;

/* RPMsg端点实例 */
static struct rpmsg_endpoint lept;
static volatile uint8_t g_rpmsg_ready = 0;

/* ==========================================
 * RPMsg接收回调函数
 * 当Linux端发送消息时触发
 * ========================================== */
static int rpmsg_recv_callback(struct rpmsg_endpoint *ept, void *data,
                                size_t len, uint32_t src, void *priv)
{
    (void)ept;
    (void)src;
    (void)priv;
    
    /* 解析接收到的控制命令 */
    if (len >= sizeof(uint32_t)) {
        uint32_t cmd = *(uint32_t *)data;
        switch (cmd) {
            case 0x01:  /* 启动传感器采集 */
                vTaskResume(xSensorTaskHandle);
                break;
            case 0x02:  /* 停止传感器采集 */
                vTaskSuspend(xSensorTaskHandle);
                break;
            case 0x03:  /* 配置采样率 */
                if (len >= sizeof(uint32_t) * 2) {
                    uint32_t rate = ((uint32_t *)data)[1];
                    vSetSampleRate(rate);
                }
                break;
            default:
                break;
        }
    }
    return RPMSG_SUCCESS;
}

/* ==========================================
 * OpenAMP初始化
 * ========================================== */
static void vOpenAMPInit(void)
{
    /* 1. 初始化libmetal (硬件抽象层) */
    struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
    metal_init(&metal_params);
    
    /* 2. 初始化RemoteProc资源 */
    struct remoteproc rproc;
    struct remoteproc_ops rproc_ops = {
        .init = NULL,
        .remove = NULL,
        .start = NULL,
        .stop = NULL,
    };
    
    remoteproc_init(&rproc, &rproc_ops, NULL, NULL, NULL, NULL);
    
    /* 3. 创建VirtIO设备 */
    struct virtio_device vdev;
    /* ... 配置VirtIO设备和vring ... */
    
    /* 4. 初始化RPMsg */
    rpmsg_init_vdev(&rvdev, &vdev, NULL, NULL, NULL);
    
    /* 5. 创建RPMsg端点 */
    rpmsg_create_ept(&lept, RPMSG_SERVICE_NAME, RPMSG_ENDPOINT_ADDR,
                     RPMSG_ADDR_ANY, rpmsg_recv_callback, NULL);
    
    g_rpmsg_ready = 1;
}

/* ==========================================
 * 传感器数据采集任务
 * 通过RPMsg向Linux端发送数据
 * ========================================== */
static void vSensorTask(void *pvParameters)
{
    SensorData_t sensorData;
    uint32_t seqNum = 0;
    
    (void)pvParameters;
    
    /* 等待RPMsg就绪 */
    while (!g_rpmsg_ready) {
        vTaskDelay(pdMS_TO_TICKS(10));
    }
    
    for (;;) {
        /* 读取传感器数据 */
        sensorData.sensor_id = 0x01;
        sensorData.temperature = fReadTemperature();
        sensorData.humidity = fReadHumidity();
        sensorData.timestamp = xTaskGetTickCount();
        
        /* 通过RPMsg发送数据到Linux端 */
        /* 使用非阻塞发送,避免影响实时性 */
        int ret = rpmsg_send(&lept, &sensorData, sizeof(SensorData_t));
        
        if (ret < 0) {
            /* 发送失败处理 - 缓冲区满 */
            /* 可选择丢弃或重试 */
        }
        
        seqNum++;
        vTaskDelay(pdMS_TO_TICKS(100));  /* 100ms采样周期 */
    }
}

/* ==========================================
 * 主函数入口
 * ========================================== */
int main(void)
{
    /* 硬件初始化 */
    HAL_Init();
    SystemClock_Config();
    
    /* 初始化OpenAMP */
    vOpenAMPInit();
    
    /* 创建传感器任务 */
    xTaskCreate(vSensorTask, "SensorTask", 512, NULL, 
                configMAX_PRIORITIES - 1, &xSensorTaskHandle);
    
    /* 启动调度器 */
    vTaskStartScheduler();
    
    /* 不会到达这里 */
    for (;;);
}

Linux侧(Cortex-A7)用户空间代码:

/* ============================================
 * Linux侧 RPMsg通信示例
 * 通过rpmsg_char设备与Cortex-M4通信
 * ============================================ */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define RPMSG_DEVICE    "/dev/rpmsg0"
#define CMD_START       0x01
#define CMD_STOP        0x02
#define CMD_SET_RATE    0x03

typedef struct {
    uint32_t sensor_id;
    float temperature;
    float humidity;
    uint32_t timestamp;
} SensorData_t;

int main(void)
{
    int fd = open(RPMSG_DEVICE, O_RDWR);
    if (fd < 0) {
        perror("Failed to open rpmsg device");
        return -1;
    }
    
    /* 发送启动命令 */
    uint32_t startCmd = CMD_START;
    write(fd, &startCmd, sizeof(startCmd));
    
    /* 设置采样率为50ms */
    uint32_t rateCmd[2] = {CMD_SET_RATE, 50};
    write(fd, &rateCmd, sizeof(rateCmd));
    
    /* 接收传感器数据 */
    SensorData_t data;
    while (1) {
        ssize_t len = read(fd, &data, sizeof(SensorData_t));
        if (len == sizeof(SensorData_t)) {
            printf("Sensor[%lu]: Temp=%.2f°C, Humid=%.2f%%, TS=%lu\n",
                   data.sensor_id, data.temperature, 
                   data.humidity, data.timestamp);
        }
    }
    
    close(fd);
    return 0;
}

四、SMP架构负载均衡机制

4.1 SMP调度架构

FreeRTOS从V11.0.0版本开始,将SMP支持合并到主线内核中,实现了真正的对称多处理。

在这里插入图片描述

SMP调度的核心特点:

  1. 单一内核映像:所有核心运行同一个FreeRTOS内核
  2. 全局任务队列:所有就绪任务共享同一个队列
  3. 自动负载均衡:调度器自动将任务分配到负载最轻的核心
  4. 处理器亲和性:支持将任务绑定到特定核心(CPU Affinity)

4.2 负载均衡策略

策略 描述 优点 缺点
全局队列调度 所有核心共享一个全局就绪队列 负载最均衡 队列竞争开销大
分区调度 每个核心维护独立的就绪队列 无队列竞争 负载可能不均衡
混合调度 高优先级任务全局调度,低优先级分区 兼顾均衡与性能 实现复杂
任务窃取 空闲核心从忙碌核心"窃取"任务 自适应负载均衡 缓存局部性损失

4.3 SMP代码配置示例

/* ============================================
 * FreeRTOS SMP配置与任务亲和性示例
 * 平台: ESP32 / STM32H7 / 其他多核MCU
 * ============================================ */

#include "FreeRTOS.h"
#include "task.h"

/* SMP相关配置 (FreeRTOSConfig.h) */
#define configNUMBER_OF_CORES           2       /* 核心数量 */
#define configUSE_CORE_AFFINITY         1       /* 启用CPU亲和性 */
#define configUSE_TASK_PREEMPTION       1       /* 启用抢占 */
#define configUSE_TIME_SLICING          1       /* 启用时间片轮转 */

/* 任务亲和性掩码 */
#define NO_AFFINITY                     tskNO_AFFINITY
#define CORE_0_ONLY                     (1 << 0)
#define CORE_1_ONLY                     (1 << 1)
#define BOTH_CORES                      ((1 << 0) | (1 << 1))

/* ==========================================
 * 创建绑定到特定核心的任务
 * ========================================== */
void vCreateAffinityTasks(void)
{
    /* 网络处理任务 - 绑定到Core 0 */
    /* 原因: 网络中断在Core 0上处理,避免缓存失效 */
    xTaskCreateAffinitySet(
        vNetworkTask,           /* 任务函数 */
        "NetworkTask",          /* 任务名称 */
        4096,                   /* 栈大小 */
        NULL,                   /* 参数 */
        configMAX_PRIORITIES - 2, /* 高优先级 */
        CORE_0_ONLY,            /* 仅运行在Core 0 */
        &xNetworkTaskHandle     /* 任务句柄 */
    );
    
    /* 电机控制任务 - 绑定到Core 1 */
    /* 原因: 需要确定性实时响应,避免被其他任务干扰 */
    xTaskCreateAffinitySet(
        vMotorControlTask,
        "MotorControl",
        2048,
        NULL,
        configMAX_PRIORITIES - 1, /* 最高优先级 */
        CORE_1_ONLY,              /* 仅运行在Core 1 */
        &xMotorTaskHandle
    );
    
    /* 日志记录任务 - 可在任意核心运行 */
    /* 原因: 非关键任务,由调度器自动负载均衡 */
    xTaskCreateAffinitySet(
        vLoggingTask,
        "LoggingTask",
        2048,
        NULL,
        2,                       /* 低优先级 */
        BOTH_CORES,              /* 可在任意核心运行 */
        &xLoggingTaskHandle
    );
    
    /* 数据处理任务 - 无亲和性,自动负载均衡 */
    xTaskCreateAffinitySet(
        vDataProcessingTask,
        "DataProc",
        4096,
        NULL,
        5,                       /* 中优先级 */
        NO_AFFINITY,             /* 无亲和性,调度器自动分配 */
        &xDataTaskHandle
    );
}

/* ==========================================
 * 运行时动态调整任务亲和性
 * ========================================== */
void vAdjustTaskAffinity(void)
{
    /* 场景: 系统负载变化时动态调整 */
    
    /* 获取当前各核心负载 */
    UBaseType_t uxCore0Load = uxTaskGetCoreLoad(0);
    UBaseType_t uxCore1Load = uxTaskGetCoreLoad(1);
    
    /* 如果Core 0负载过高,将非关键任务迁移到Core 1 */
    if (uxCore0Load > 80 && uxCore1Load < 50) {
        vTaskCoreAffinitySet(xLoggingTaskHandle, CORE_1_ONLY);
    }
    
    /* 如果Core 1负载过高,将非关键任务迁移到Core 0 */
    if (uxCore1Load > 80 && uxCore0Load < 50) {
        vTaskCoreAffinitySet(xLoggingTaskHandle, CORE_0_ONLY);
    }
}

/* ==========================================
 * 中断亲和性配置
 * 将特定中断绑定到特定核心处理
 * ========================================== */
void vConfigureInterruptAffinity(void)
{
    /* 将ETH中断绑定到Core 0 */
    /* 确保网络数据包始终在同一核心处理,提高缓存命中率 */
    vPortSetInterruptAffinity(ETH_IRQn, CORE_0_ONLY);
    
    /* 将电机编码器中断绑定到Core 1 */
    /* 确保电机控制中断不被网络流量延迟 */
    vPortSetInterruptAffinity(ENCODER_IRQn, CORE_1_ONLY);
    
    /* 将定时器中断分发到两个核心 */
    vPortSetInterruptAffinity(TIM_IRQn, BOTH_CORES);
}

4.4 SMP中的同步原语

在SMP架构中,多个核心可能同时访问共享资源,需要特殊的同步机制:

/* ==========================================
 * SMP环境下的自旋锁 (Spinlock)
 * 用于保护极短临界区,避免任务切换开销
 * ========================================== */
static portMUX_TYPE xSpinLock = portMUX_INITIALIZER_UNLOCKED;

void vCriticalSectionExample(void)
{
    /* 获取自旋锁 - 阻塞其他核心进入 */
    taskENTER_CRITICAL(&xSpinLock);
    
    /* 临界区代码 - 访问共享资源 */
    gSharedCounter++;
    gSharedData[index] = value;
    
    /* 释放自旋锁 */
    taskEXIT_CRITICAL(&xSpinLock);
}

/* ==========================================
 * SMP环境下的递归互斥锁
 * 用于保护较长临界区,允许同一任务递归获取
 * ========================================== */
static SemaphoreHandle_t xRecursiveMutex = NULL;

void vMutexInit(void)
{
    xRecursiveMutex = xSemaphoreCreateRecursiveMutex();
}

void vProtectedFunction(void)
{
    if (xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) {
        /* 访问共享资源 */
        vUpdateSharedResource();
        
        /* 递归调用另一需要同一锁的函数 */
        vAnotherProtectedFunction();
        
        xSemaphoreGiveRecursive(xRecursiveMutex);
    }
}

五、缓存一致性与内存屏障

5.1 多核缓存一致性挑战

在多核系统中,每个核心拥有独立的L1 Cache。当多个核心访问同一内存地址时,可能出现缓存不一致的问题:

在这里插入图片描述

典型问题场景:

  1. Core 0写入数据到共享内存,但数据仅存在于Core 0的Cache中(Modified状态)
  2. Core 1读取同一地址,如果直接从自己的Cache读取,会得到旧值
  3. 需要通过缓存一致性协议(MESI)内存屏障指令确保数据一致性

5.2 ARM内存屏障指令

/* ==========================================
 * ARM Cortex-M/R/A 内存屏障指令详解
 * ========================================== */

/* DMB - Data Memory Barrier
 * 确保屏障前的所有内存访问完成后再执行屏障后的内存访问
 * 使用场景: 核间数据同步、DMA操作 */
#define DMB()   __asm volatile ("dmb" ::: "memory")

/* DSB - Data Synchronization Barrier
 * 确保所有缓存、TLB、分支预测操作完成
 * 使用场景: 上下文切换、系统状态变更 */
#define DSB()   __asm volatile ("dsb" ::: "memory")

/* ISB - Instruction Synchronization Barrier
 * 刷新流水线,确保后续指令重新从内存获取
 * 使用场景: 代码动态修改、MPU配置变更 */
#define ISB()   __asm volatile ("isb" ::: "memory")

/* ==========================================
 * 核间通信中的内存屏障使用示例
 * ========================================== */

/* 共享内存结构体 */
typedef struct {
    volatile uint32_t flag;     /* 数据就绪标志 */
    volatile uint32_t data;     /* 共享数据 */
    volatile uint32_t seq;      /* 序列号 */
} SharedMem_t;

/* Core 0 写入数据 */
void vCore0WriteData(SharedMem_t *shm, uint32_t value)
{
    /* 1. 写入数据 */
    shm->data = value;
    shm->seq++;
    
    /* 2. 数据内存屏障 - 确保数据写入完成 */
    DMB();
    
    /* 3. 设置标志 - 通知Core 1数据就绪 */
    shm->flag = 1;
    
    /* 4. 触发软件中断通知Core 1 */
    vTriggerSGI(1, 1);  /* 向Core 1发送SGI中断 */
}

/* Core 1 读取数据 */
uint32_t vCore1ReadData(SharedMem_t *shm)
{
    uint32_t value;
    
    /* 等待标志被设置 (在中断处理中检查) */
    while (shm->flag == 0) {
        /* 等待或休眠 */
        __WFE();  /* 等待事件 */
    }
    
    /* 数据同步屏障 - 确保看到最新的数据 */
    DSB();
    
    /* 读取数据 */
    value = shm->data;
    
    /* 清除标志 */
    shm->flag = 0;
    
    DMB();  /* 确保标志清除被其他核心看到 */
    
    return value;
}

六、典型应用场景分析

6.1 AMP场景:工业智能网关

在这里插入图片描述

场景描述:工业智能网关需要同时处理复杂的网络协议(Linux侧)和实时的电机控制(FreeRTOS侧)。

架构选择:AMP

核心 操作系统 职责 实时性要求
Core 0 Linux Web服务器、数据库、网络协议栈、文件系统 软实时
Core 1 FreeRTOS 电机PID控制、传感器采集、安全监控、紧急停止 硬实时

核间通信:通过RPMsg实现传感器数据上报和控制命令下发,延迟<1ms。

优势

  • 实时核不受Linux调度抖动影响,保证电机控制确定性
  • Linux提供丰富的网络协议和文件系统支持
  • 两个域独立开发、独立升级,降低耦合度

6.2 SMP场景:高吞吐网络处理器

场景描述:网络数据包处理需要高吞吐量,单个核心无法满足100Mbps+的处理需求。

架构选择:SMP

任务分配

  • Core 0:网络数据包接收(中断处理)、协议解析
  • Core 1:数据包转发、加密/解密、QoS处理
  • 负载均衡:高优先级数据包处理任务可在任意核心运行,调度器自动分配

优势

  • 统一代码库,开发维护简单
  • 自动负载均衡,充分利用多核性能
  • 任务可在核心间迁移,提高系统弹性

七、架构选择决策树

在这里插入图片描述

决策流程:

  1. 是否需要运行不同OS?(如Linux + RTOS)

    • → 选择 AMP
    • → 继续下一步
  2. 所有核心是否运行同一RTOS?

    • → 选择 SMP
    • → 考虑虚拟化或Hypervisor方案

关键决策因素:

因素 推荐AMP 推荐SMP
需要运行Linux + RTOS
需要强实时隔离
核心同构(相同架构)
需要自动负载均衡
开发资源有限
需要独立域升级
高并行计算需求

八、常见问题与最佳实践

8.1 AMP常见问题

问题 原因 解决方案
核间通信延迟高 频繁使用中断通知 采用批量传输 + 环形缓冲区
共享内存数据损坏 缺少内存屏障 在关键位置插入DMB/DSB
RPMsg通道建立失败 资源表配置错误 检查设备树和resource_table
实时核被Linux干扰 共享外设冲突 通过设备树明确划分外设归属

8.2 SMP常见问题

问题 原因 解决方案
任务在核心间频繁迁移 缺少CPU亲和性设置 为关键任务设置xTaskCoreAffinitySet
自旋锁导致死锁 中断上下文获取锁 使用taskENTER_CRITICAL_FROM_ISR
缓存伪共享 多个核心访问同一缓存行 按缓存行对齐(64字节)分离数据
负载不均衡 任务优先级设计不当 使用混合调度策略

8.3 性能优化建议

/* ==========================================
 * SMP性能优化: 避免缓存伪共享
 * ========================================== */

/* 错误示例 - 多个核心频繁修改同一缓存行 */
struct BadLayout {
    uint32_t core0_counter;  /* Core 0修改 */
    uint32_t core1_counter;  /* Core 1修改 - 同一缓存行! */
    uint32_t core2_counter;  /* Core 2修改 - 同一缓存行! */
};

/* 正确示例 - 按缓存行对齐分离 */
struct __attribute__((aligned(64))) GoodLayout {
    uint32_t counter;
    uint8_t padding[60];  /* 填充至64字节缓存行 */
};

struct GoodLayout gCoreCounters[3];  /* 每个核心独立缓存行 */

/* ==========================================
 * AMP性能优化: 批量传输减少中断
 * ========================================== */

/* 批量发送传感器数据,减少RPMsg中断频率 */
#define BATCH_SIZE  16

void vBatchSendSensorData(void)
{
    static SensorData_t batchBuffer[BATCH_SIZE];
    static uint8_t batchIndex = 0;
    
    /* 采集数据到批量缓冲区 */
    batchBuffer[batchIndex].temperature = fReadTemp();
    batchBuffer[batchIndex].humidity = fReadHumidity();
    batchIndex++;
    
    /* 批量发送 */
    if (batchIndex >= BATCH_SIZE) {
        rpmsg_send(&lept, batchBuffer, sizeof(SensorData_t) * BATCH_SIZE);
        batchIndex = 0;
    }
}

九、总结与展望

AMP与SMP代表了嵌入式多核系统的两种截然不同的设计哲学:

AMP强调隔离与异构,通过让不同核心运行最适合其角色的操作系统,实现功能与实时性的最佳平衡。OpenAMP框架的标准化使得Linux + RTOS的异构组合成为工业界的成熟方案。

SMP强调统一与对称,通过单一操作系统映像和全局调度器,实现开发简化与自动负载均衡。FreeRTOS SMP的成熟让嵌入式开发者也能享受到多核并行处理的便利。

在实际项目中,选择AMP还是SMP取决于以下核心问题:你的系统是否需要同时运行不同操作系统?是否需要强实时隔离?

随着RISC-V多核架构的兴起和ARM Cortex-X系列性能核心的普及,嵌入式多核系统将继续向更高性能、更低功耗的方向发展。无论选择AMP还是SMP,掌握核间通信机制和负载均衡策略,都是每一位嵌入式开发者必备的核心技能。


转载自:https://blog.csdn.net/u014727709/article/details/162508769
欢迎 👍点赞✍评论⭐收藏,欢迎指正

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐