28、嵌入式操作系统的系统资源分离与任务调度

FreeRTOS与RIOT OS系统对比

嵌入式操作系统的系统资源分离与任务调度

1. 系统资源分离与系统调用

在系统资源分离方面,一些操作限制了当前任务直接访问资源的可能性。为了维持系统原有功能,系统需要导出新的安全 API 供任务请求系统操作。

以下是相关代码示例:

DMB();
mpu_set_region(3, (uint32_t)start, attr);
MPU_CTRL = 1;

系统调用方面,最新的操作系统不再允许任务直接控制系统资源,如输入输出外设,甚至不允许任务主动阻塞。操作系统通过 SVCall 异常的系统调用机制导出 API,由 isr_svc 服务例程处理,任务可通过 svc 指令随时触发。

定义了一个快捷宏 SVC() 用于切换到处理模式:

#define SVC() asm volatile ("svc 0")

封装在 C 函数中以传递参数:

static int syscall(int arg0)
{
    SVC();
}

系统调用列表如下:
| 系统调用名称 | 标识编号 |
| — | — |
| SYS_SCHEDULE | 0 |
| SYS_BUTTON_READ | 1 |
| SYS_BLUELED_ON | 2 |
| SYS_BLUELED_OFF | 3 |
| SYS_BLUELED_TOGGLE | 4 |
| SYS_REDLED_ON | 5 |
| SYS_REDLED_OFF | 6 |
| SYS_REDLED_TOGGLE | 7 |
| SYS_GREENLED_ON | 8 |
| SYS_GREENLED_OFF | 9 |
| SYS_GREENLED_TOGGLE | 10 |

isr_svc 函数用于处理这些系统调用:

void __attribute__((naked)) isr_svc(int arg)
{
    store_user_context();
    asm volatile("mrs %0, psp" : "=r"(t_cur->sp));
    if (t_cur->state == TASK_RUNNING) {
        t_cur->state = TASK_READY;
    }
    switch(arg) {
        case SYS_BUTTON_READ: /* cmd to read button value */
            button_start_read();
            break;
        case SYS_SCHEDULE: /* cmd to schedule the next task */
            t_cur = tasklist_next_ready(t_cur);
            t_cur->state = TASK_RUNNING;
            break;
        case SYS_BLUELED_ON: /* cmd to turn on blue LED */
            blue_led_on();
            break;
        /* case ... (more LED related cmds follow) */
    }
    if (t_cur->id == 0) {
        asm volatile("msr msp, %0" ::"r"(t_cur->sp));
        restore_kernel_context();
        asm volatile("mov lr, %0" ::"r"(0xFFFFFFF9));
        asm volatile("msr CONTROL, %0" ::"r"(0x00));
    } else {
        asm volatile("msr psp, %0" ::"r"(t_cur->sp));
        restore_user_context();
        mpu_task_stack_permit(((uint8_t *)((&stack_space))
                              +(t_cur->id << 10)));
        asm volatile("mov lr, %0" ::"r"(0xFFFFFFFD));
        asm volatile("msr CONTROL, %0" ::"r"(0x01));
    }
    asm volatile("bx lr");
}

任务代码示例:

void task_test0(void *arg)
{
    while(1) {
        syscall(SYS_BLUELED_ON);
        mutex_lock(&m);
        sleep_ms(500);
        syscall(SYS_BLUELED_OFF);
        mutex_unlock(&m);
        sleep_ms(1000);
    }
}

void task_test1(void *arg)
{
    syscall(SYS_REDLED_ON);
    while(1) {
        sleep_ms(50);
        mutex_lock(&m);
        syscall(SYS_REDLED_TOGGLE);
        mutex_unlock(&m);
    }
}

void task_test2(void *arg)
{
    uint32_t toggle_time = 0;
    syscall(SYS_GREENLED_OFF);
    while(1) {
        button_read();
        if ((jiffies - toggle_time) > 120) {
            syscall(SYS_GREENLED_TOGGLE);
            toggle_time = jiffies;
        }
    }
}
2. 嵌入式操作系统选择

在选择嵌入式操作系统时,需要考虑诸多因素,如硬件特性、与第三方库的集成、与外设和接口的交互功能,以及系统设计所覆盖的用例范围。

操作系统通常除了调度器和内存管理外,还包含一系列集成库、模块和工具,可能涵盖以下方面:
- 特定平台的硬件抽象层
- 常见外设的设备驱动
- 用于连接的 TCP/IP 栈集成
- 文件系统和文件抽象
- 集成电源管理系统

根据调度器中线程模型的实现,有些系统使用编译时配置的固定任务数量,而有些则支持运行时创建和终止线程。不过,动态任务创建和终止在嵌入式系统中需求较少。

复杂系统可能会因系统异常代码中的额外逻辑引入开销,不太适合关键实时操作。因此,大多数成功的实时操作系统(RTOS)保持简单架构,采用扁平内存模式运行多线程,以降低延迟并满足实时要求。

3. 流行的开源嵌入式操作系统 - FreeRTOS

FreeRTOS 是嵌入式设备中最流行的开源操作系统之一,具有近 20 年的活跃开发历史,可移植性极高,支持众多嵌入式平台和 CPU 架构。

它专注于线程的实时调度和堆内存管理,代码简洁、接口简单。第三方库和硬件制造商的示例代码常将其集成到软件套件中。

3.1 任务创建与调度

FreeRTOS 的调度器是抢占式的,具有固定优先级和通过共享互斥锁实现的优先级继承。任务优先级和栈空间大小在创建线程时确定。

使用 xTaskCreate 函数创建新任务:

xTaskCreate(task_entry_fn, "TaskName", task_stack_size,
            ( void * ) custom_params, priority, task_handle);

启动调度器:

vTaskStartScheduler();
3.2 堆内存管理

FreeRTOS 提供五种堆内存管理模式:
- Heap 1 :仅允许一次性静态堆分配,无法释放内存。
- Heap 2 :允许释放内存,但不重新组合已释放的块,适用于堆分配数量有限的情况。
- Heap 3 :封装第三方库的 malloc/free 实现,确保线程安全。
- Heap 4 :支持内存合并,减少堆碎片化,提高长期内存使用率。
- Heap 5 :与 Heap 4 机制相同,但允许定义多个非连续内存区域作为同一堆空间。

选择特定堆模型只需包含相应的源文件(如 heap_1.c 等)。堆内存管理器暴露的重要函数有 pvPortMalloc pvPortFree

3.3 其他特性

支持 MPU 和线程模式,线程可在受限模式下运行,仅能访问分配给自己的内存。低功耗管理默认限于睡眠模式,但允许重新定义调度器回调函数以实现自定义低功耗模式。

近期版本的 FreeRTOS 包含第三方代码的特定发行版,用于构建物联网系统的安全连接平台,还附带专门设计的 TCP/IP 栈和 wolfSSL 库支持安全套接字通信。

以下是 FreeRTOS 相关操作的流程图:

graph TD;
    A[开始] --> B[创建任务];
    B --> C[启动调度器];
    C --> D[任务运行];
    D --> E{是否需要内存分配};
    E -- 是 --> F[选择堆模型];
    F --> G[进行内存分配];
    E -- 否 --> D;
    D --> H{是否结束};
    H -- 是 --> I[结束];
    H -- 否 --> D;

嵌入式操作系统的系统资源分离与任务调度

4. 流行的开源嵌入式操作系统 - RIOT OS

RIOT OS 主要构建在受限微控制器上,适用于低功耗嵌入式系统,如物联网项目和长期运行且维护成本低的场景。这类系统通常使用电池供电或能量收集技术,通过无线技术与远程服务进行间歇性连接。

4.1 系统特点

RIOT OS 与 FreeRTOS 的简约理念不同,它提供了广泛的库和设备支持代码,包括网络栈和无线驱动通信,对物联网应用友好。系统核心具有高度可扩展性,部分组件可在编译时排除。

从 API 角度看,RIOT OS 尽量模仿 POSIX 接口,方便不同背景的程序员开发嵌入式应用。不过,系统采用扁平模型,未在系统层面实现权限分离,用户空间应用仍需直接引用系统内存来访问资源。

为增强安全性,可使用 MPU 检测单线程的栈溢出,方法是在栈底部设置一个小的只读区域,若线程试图越界写入,将触发异常。

4.2 网络通信与低功耗管理

RIOT OS 实现了多个通信栈模块,如 GNRC 极简 IP 栈,专为 802.15.4 网络特性定制,仅支持 IPv6,并提供套接字实现以编写轻量级物联网应用。此外,还包含 lwIP 兼容性层和 WolfSSL 模块,可提供更完整的 TCP/IP 实现和安全套接字通信。

低功耗管理通过电源管理模块集成到系统中,该模块提供了管理特定平台低功耗模式(如 Cortex - M 平台的停止和待机模式)的抽象接口。应用程序可在运行时激活低功耗模式,并利用实时时钟、看门狗定时器或其他外部信号恢复正常运行。

4.3 任务调度与创建

RIOT OS 的调度器是无滴答且基于协作的。任务可通过调用 task_yield 函数或任何阻塞函数(如访问内核功能或硬件外设的函数)显式挂起自己。系统仅在接收到硬件中断时强制中断任务。

使用 thread_create 函数创建任务:

thread_create(task_stack_mem, task_stack_size, priority, 
              flags, task_entry_fn, (void*)custom_args, "TaskName");

与 FreeRTOS 不同,RIOT OS 要求调用者手动分配任务的栈空间,这增加了调用代码的复杂度,但提供了更大的灵活性。

4.4 堆内存管理

由于 RIOT OS 设计用于内存有限的嵌入式目标,不鼓励使用动态分配内存。不过,它提供了三种堆内存管理方法:
- 一次性静态分配 :类似于 FreeRTOS 的“Heap 1”模型,内存分配后无法释放。默认情况下, malloc 函数使用此实现, free 函数无效。
- 内存数组分配器 :使用静态分配的缓冲区作为固定大小的伪动态分配请求的内存池,适用于处理多个相同大小缓冲区的场景。该分配器有自定义 API,不修改默认 malloc 函数的行为。
- 两级分离适配(TLSF)分配器 :基于为 RTOS 优化的算法,支持多个内存池,提供动态内存支持,同时满足实时截止时间要求。此模块为可选,编译后将替换一次性分配器提供的 malloc free 函数。

以下是 RIOT OS 任务创建与运行的流程图:

graph TD;
    A[开始] --> B[分配栈空间];
    B --> C[调用 thread_create 创建任务];
    C --> D[任务运行];
    D --> E{是否主动挂起};
    E -- 是 --> F[任务挂起];
    F --> G{是否有硬件中断};
    G -- 是 --> D;
    G -- 否 --> F;
    E -- 否 --> H{是否需要内存分配};
    H -- 是 --> I[选择内存管理方法];
    I --> J[进行内存分配];
    J --> D;
    H -- 否 --> D;
    D --> K{是否结束};
    K -- 是 --> L[结束];
    K -- 否 --> D;
5. FreeRTOS 与 RIOT OS 的对比
特性 FreeRTOS RIOT OS
设计理念 简约,专注于实时调度和堆内存管理 提供广泛库和设备支持,注重物联网集成
任务创建 自动分配栈空间, xTaskCreate 函数 需调用者手动分配栈空间, thread_create 函数
调度器 抢占式,固定优先级 无滴答,基于协作
堆内存管理 五种模式,功能丰富 三种模式,适配低内存场景
网络支持 需集成第三方 TCP/IP 栈 自带 GNRC 极简 IP 栈,支持 lwIP 兼容性层
低功耗管理 默认睡眠模式,可自定义 集成电源管理模块,支持多种低功耗模式
安全性 支持 MPU,线程可受限运行 可使用 MPU 检测栈溢出

通过对比可以看出,FreeRTOS 适合对实时性要求高、追求简单架构的嵌入式应用;而 RIOT OS 更适合物联网场景,尤其是对网络通信和低功耗管理有较高要求的项目。开发者可根据具体需求选择合适的操作系统。

内容概要:本文介绍了一个基于MATLAB实现的无人机三维路径规划项目,采用蚁群算法(ACO)多层感知机(MLP)相结合的混合模型(ACO-MLP)。该模型通过三维环境离散化建模,利用ACO进行全局路径搜索,并引入MLP对环境特征进行自适应学习启发因子优化,实现路径的动态调整多目标优化。项目解决了高维空间建模、动态障碍规避、局部最优陷阱、算法实时性及多目标权衡等关键技术难题,结合并行计算参数自适应机制,提升了路径规划的智能性、安全性和工程适用性。文中提供了详细的模型架构、核心算法流程及MATLAB代码示例,涵盖空间建模、信息素更新、MLP训练融合优化等关键步骤。; 适合人群:具备一定MATLAB编程基础,熟悉智能优化算法神经网络的高校学生、科研人员及从事无人机路径规划相关工作的工程师;适合从事智能无人系统、自动驾驶、机器人导航等领域的研究人员; 使用场景及目标:①应用于复杂三维环境下的无人机路径规划,如城市物流、灾害救援、军事侦察等场景;②实现飞行安全、能耗优化、路径平滑实时避障等多目标协同优化;③为智能无人系统的自主决策环境适应能力提供算法支持; 阅读建议:此资源结合理论模型MATLAB实践,建议读者在理解ACOMLP基本原理的基础上,结合代码示例进行仿真调试,重点关注ACO-MLP融合机制、多目标优化函数设计及参数自适应策略的实现,以深入掌握混合智能算法在工程中的应用方法。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值