将操作系统移植到新的芯片架构

RT-Thread 维护者从将嵌入式系统操作系统移植到不同芯片架构中学到的经验。
55 位读者喜欢这篇文章。
diagram of planning a cloud

Opensource.com

曾经有人问我,为什么计算机被称为“计算机”,而它们做的事情远不止计算数字。现代电脑可以浏览互联网、播放音频和视频、为视频游戏和电影生成精美的图形、模拟和预测复杂的天气模式和流行病风险、将建筑和工程蓝图变为现实等等。

计算机之所以能做到这一切,是因为所有这些问题都可以表达为数值方程,而计算机的 CPU——它的中央处理器——实际上只不过是一个简单的计算器。

要让 CPU 向硬盘发送信号以写入数据,或向显示器发送信号以显示图像,它必须接收指令。这些指令以“代码”的形式出现,这是说有人必须编写一个与 CPU “说”相同语言的 *程序* 的简洁方式。CPU 理解 *机器语言*,这是一种几乎无法理解的位数组,大多数人都不屑于手动编写。相反,我们使用 C、C++、Java、Python 等编程语言。这些语言被解析并编译成机器语言,然后传递给 CPU。

如果你试图用 CPU 不理解的语言来指示它,CPU 就不知道该怎么做。你可以通过尝试从 Raspberry Pi 启动 x86_64 RHEL 镜像来体验这种沟通不畅的相当平淡的结果。如果它能工作就好了,但它不能。

将操作系统移植到新的架构

RT-Thread 项目 为嵌入式系统程序员提供了一个开源操作系统 (OS)。嵌入式领域非常多样化,拥有大量的物联网 (IoT)、定制工业和业余爱好者设备。RT-Thread 的目标是让 *每个人* 都能轻松进行嵌入式编程,无论你使用什么设备。有时,这意味着将操作系统移植到新的架构,无论是相同架构但指令集略有不同的芯片,还是全新的架构。

起初,解决这个问题可能有点吓人——你可能不知道从哪里或如何开始。本文收集了 RT-Thread 维护者在将 RTOS 移植到新的芯片架构时学到的经验教训。

开始之前你需要知道什么

这是一个看似难以逾越的过程的高级视图。这可能因你的项目而异,但从概念上讲,它是相对普遍的,即使某些细节有所不同

  1. 准备一个 C 语言执行环境
  2. 确认可以通过串口发送和接收字符
  3. 确认上下文切换代码有效
  4. 支持硬件定时器
  5. 确认中断例程可以通过串口接收和解析数据

执行模型

对于大多数高级架构,操作系统和用户应用程序以不同的特权级别运行。这可以防止故障代码影响操作系统的集成和安全性。例如,在 ARMv7-A 架构中,操作系统通常在系统模式下运行,而在 ARMv8-A 中,操作系统可以在 EL2 或 EL3 特权级别运行。

通常,芯片在启动时以最高特权级别执行启动代码。之后,操作系统会将特权级别切换到其目标模式。

1. 执行 C 代码

此步骤中的关键操作是将 块起始符号 (.bss) 部分设置为零并设置堆栈指针。

在 C 语言实现中,未初始化的全局变量和静态变量通常存储在 .bss 部分中,该部分不占用存储设备中的任何空间。加载程序时,会在内存中分配相应的空间并将其初始化为零。当操作系统启动时,它必须自己完成这项工作。

另一方面,操作系统必须初始化堆栈空间并设置堆栈指针。由于 C 语言程序在进入和退出函数时将局部变量保存在堆栈上并恢复,因此必须在调用任何 C 函数之前设置堆栈指针。RT-Thread 必须为每个新创建的线程执行此步骤。

2. 使用至少一个串口驱动程序

RT-Thread 通过串口输出信息和日志,这也有助于在移植过程中调试代码。在此阶段,不需要通过串口*接收*数据。当我们第一次通过串口看到我们熟悉的 RT-Thread 徽标时,我们就知道我们走对了路!

3. 确认上下文切换逻辑

任务的上下文是其整个执行环境,其中包含通用寄存器、程序计数器、堆栈帧的位置等等。创建新线程时,RT-Thread 必须手动分配和设置其上下文,以便调度程序可以像处理其他线程一样切换到新线程。

有三件事需要注意

  • 首先,当 RT-Thread 启动时,默认情况下禁用中断。首次启用任务调度程序时启用它们;此过程在上下文切换期间用汇编语言实现。
  • 其次,当下一次调度将在线程退出时启动,即空闲线程回收拥有的资源时。
  • 第三,将数据压入堆栈的顺序必须与从堆栈弹出数据的顺序一致。

通常,你希望正常进入 main 函数和 msh 控制台。但是,由于未实现串口输入中断,因此在此阶段无法实现输入控制。实现串口中断后,可以进行 msh 输入。

4. 设置定时器

RT-Thread 需要一个定时器来定期生成中断;这用于计算自系统启动以来经过的节拍数。节拍数用于提供软件中断功能,并指示内核何时开始调度任务。

设置时间片的值可能是一件棘手的事情。通常是 10 毫秒到 1 毫秒。如果在较慢的 CPU 上选择较小的时间片,则大部分时间都花在任务切换上——从而不利于完成其他任何事情。

5. 确认串口工作正常

在此步骤中,我们通过串口与 RT-Thread msh 交互。我们发送命令,按 Enter 键,然后看着 msh 执行该命令并显示结果。

此过程通常不难实现。但有一点警告:不要忘记在处理完串口中断后清除某些平台上的中断标志。

一旦串口工作正常,移植过程就基本完成了!

忙起来

要将你的项目移植到不同的芯片架构,你需要非常清楚你所针对的芯片的架构。熟悉你项目中最关键点的底层代码。通过交叉引用芯片的手册并结合大量的实际工作经验,你将了解芯片特权模式、寄存器和编译方法。

如果你没有需要移植到新芯片的项目,请加入我们;RT-Thread 项目始终可以利用帮助将 RTOS 移植到新芯片!作为一个开源项目,RT-Thread 正在改变开源嵌入式编程的格局。请在 RT-Thread Club 介绍你自己并寻求帮助!


本文基于 如何在不同的芯片架构上移植操作系统? _发表在 DEV 社区,并经许可重新发布。_

下一步阅读
Avatar
我喜欢我的隐私。

评论已关闭。

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.