最近在看RT_THread, 其中对于内核的移植,感觉需要非常了解CPU架构,汇编指令集,这边就以官方wiki文档学习理解。
先放上原文,之后有疑问的地方对文档做批注来加深学习。
经过前面内核章节的学习,大家对 RT-Thread 也有了不少的了解,但是如何将 RT-Thread 内核移植到不同的硬件平台上,很多人还不一定熟悉。内核移植就是指将 RT-Thread 内核在不同的芯片架构、不同的板卡上运行起来,能够具备线程管理和调度,内存管理,线程间同步和通信、定时器管理等功能。移植可分为 CPU 架构移植和 BSP(Board support package,板级支持包)移植两部分。
本章将展开介绍 CPU 架构移植和 BSP 移植,CPU 架构移植部分会结合 Cortex-M CPU 架构进行介绍,因此有必要回顾下上一章《中断管理》介绍的 “Cortex-M CPU 架构基础” 的内容,本章最后以实际移植到一个开发板的示例展示 RT-Thread 内核移植的完整过程,读完本章,我们将了解如何完成 RT-Thread 的内核移植。
CPU 架构移植
在嵌入式领域有多种不同 CPU 架构,例如 Cortex-M、ARM920T、MIPS32、RISC-V 等等。为了使 RT-Thread 能够在不同 CPU 架构的芯片上运行,RT-Thread 提供了一个 libcpu 抽象层来适配不同的 CPU 架构。libcpu 层向上对内核提供统一的接口,包括全局中断的开关,线程栈的初始化,上下文切换等。
RT-Thread 的 libcpu 抽象层向下提供了一套统一的 CPU 架构移植接口,这部分接口包含了全局中断开关函数、线程上下文切换函数、时钟节拍的配置和中断函数、Cache 等等内容。下表是 CPU 架构移植需要实现的接口和变量。
libcpu 移植相关 API
函数和变量 | 描述 |
---|---|
rt_base_t rt_hw_interrupt_disable(void); | 关闭全局中断 |
void rt_hw_interrupt_enable(rt_base_t level); | 打开全局中断 |
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit); | 线程栈的初始化,内核在线程创建和线程初始化里面会调用这个函数 |
void rt_hw_context_switch_to(rt_uint32 to); | 没有来源线程的上下文切换,在调度器启动第一个线程的时候调用,以及在 signal 里面会调用 |
void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); | 从 from 线程切换到 to 线程,用于线程和线程之间的切换 |
void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); | 从 from 线程切换到 to 线程,用于中断里面进行切换的时候使用 |
rt_uint32_t rt_thread_switch_interrupt_flag; | 表示需要在中断里进行切换的标志 |
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; | 在线程进行上下文切换时候,用来保存 from 和 to 线程 |
实现全局中断开关
无论内核代码还是用户的代码,都可能存在一些变量,需要在多个线程或者中断里面使用,如果没有相应的保护机制,那就可能导致临界区问题。RT-Thread 里为了解决这个问题,提供了一系列的线程间同步和通信机制来解决。但是这些机制都需要用到 libcpu 里提供的全局中断开关函数。它们分别是:
/* 关闭全局中断 */
rt_base_t rt_hw_interrupt_disable(void);
/* 打开全局中断 */
void rt_hw_interrupt_enable(rt_base_t level);
下面介绍在 Cortex-M 架构上如何实现这两个函数,前文中曾提到过,Cortex-M 为了快速开关中断,实现了 CPS 指令,可以用在此处。
CPSID I ;PRIMASK=1, ; 关中断
CPSIE I ;PRIMASK=0, ; 开中断
关闭全局中断
在 rt_hw_interrupt_disable() 函数里面需要依序完成的功能是:
1). 保存当前的全局中断状态,并把状态作为函数的返回值。
2). 关闭全局中断。
基于 MDK,在 Cortex-M 内核上实现关闭全局中断,如下代码所示:
;/*
; * rt_base_t rt_hw_interrupt_disable(void);
; */
rt_hw_interrupt_disable PROC ;PROC 伪指令定义函数
EXPORT rt_hw_interrupt_disable ;EXPORT 输出定义的函数,类似于 C 语言 extern
MRS r0, PRIMASK ; 读取 PRIMASK 寄存器的值到 r0 寄存器
CPSID I ; 关闭全局中断
BX LR ; 函数返回
ENDP ;END