请选择 进入手机版 | 继续访问电脑版
查看: 1000|回复: 2

[原创] RT-Thread 框架下的 SMP 支持

[复制链接]

该用户从未签到

6

主题

9

帖子

0

注册会员

Rank: 2

积分
79
最后登录
2024-2-28
发表于 2023-2-7 20:26:05 | 显示全部楼层 |阅读模式
RT-Thread 框架下的 SMP 支持前言
最近报名参加了恩智浦社区的 LPC55S69 开发板测评活动,由于其搭载的是一颗  Cortex-M33 Dual Core 的 CPU,而且有大佬已经支持了 RT-Thread 的 BSP,就考虑使其支持 RT-Thread 框架下的 SMP,最近就一直在研究 SMP,并在 Raspberry-Pico 上做了一些实验。以下是一些我在学习过程中的心得体会,不对的地方欢迎大家指正交流~
SMP 简介
SMP: 对称多处理(Symmetrical Multi-Processing)简称 SMP,是指在一个计算机上汇集了一组处理器 (多 CPU), 各 CPU 之间共享内存子系统以及总线结构。虽然同时使用多个CPU,但是从管理的角度来看,它们的表现就像一台单机一样。系统将任务队列对称地分布于多个CPU之上,从而极大地提高了整个系统的数据处理能力。RT-Thread 自 v4.0.0 版本开始支持 SMP,在对称多核上可以通过使能 RT_USING_SMP 来开启。
系统上电后,各 CPU 的启动流程如下图所示:

各CPU启动流程

各CPU启动流程

每个次级 CPU 自身硬件部分的初始化不能由 CPU0 完成,因为其自身硬件不能由其它 CPU 访问。
关于 CPU 已经支持了 SMP 的平台
RT-Thread 的 libcpu 中有一些芯片类型已经支持了 SMP 功能,例如 Cortex-A 系列。对于这样的平台,SMP 的移植工作就会简单很多,我们只需要实现 rt_hw_secondary_cpu_up() ,secondary_cpu_c_start() ,rt_hw_secondary_cpu_idle_exec() 这三个函数即可,具体的移植介绍可以参考 RT-Thread 文档中心SMP 介绍与移植
关于 CPU 还未支持 SMP 的平台
RT-Thread 中还有一些 CPU 是没有支持 SMP 的,例如 Cortex-M 系列的大部分 CPU,练手的 PICO 是 M0 ,准备开发的 LPC55S69 是 M33,都是还没有支持 SMP 的。对于这样的平台移植 SMP 就会相对麻烦。除了 rt_hw_secondary_cpu_up() ,secondary_cpu_c_start() ,rt_hw_secondary_cpu_idle_exec() 这三个函数,我们还需要补充 SMP 所需要的底层支持,主要是中断和调度部分,从而实现更加复杂的共享资源保护,以及线程间的通讯和调度。
推荐大家先去看看 RT-Thread 文档中心的相关资料,以及这篇文章:[RT-Thread学习笔记] 中断锁、调度锁与死锁,最好再去看看 rt-thread\src 目录下的 scheduler.c 源码。其中有许多 SMP 的相关实现。
CPU ID
scheduler.c 中已经有 SMP 的相关支持,但是会发现,还需要 CPU 的个数及其对应的 ID 等重要参数。所以我们首先要是实现的是 rt_hw_cpu_id() 这个函数。这个需要对应自己开发平台的实际情况。
OS Tick
在 SMP 系统中,每个 CPU 维护自己独立的 tick 值,用作任务运行计时以及时间片统计。除此之外,CPU0 还通过 tick 计数来更新系统时间,并提供系统定时器的功能,次级 CPU 不需要提供这些功能。这部分也是要针对使用的开发开发平台进行配置。
处理器间中断 IPI
处理器间中断(Inter-Processor Interrupt)负责 CPU 之间的相互通讯及处理,针对不同开发的平台,我们还需要实现以下函数:
/* 该函数用来向 CPU 位图中表示的 CPU 集合发送指定编号的 IPI 信号 */
void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)

/* 函数为当前 CPU 设置指定编号 IPI 信号的处理函数 */
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)调度与同步
临界区保护是需要特别注意的。对于 SMP 通过关中断的方式并不能阻止多个 CPU 对共享资源的并发访问,需要通过自旋锁机制进行保护(在次级 CPU 启动中就需要使用)。我们就还需要实现以下几个函数:
rt_hw_spin_lock_init()  /* 初始化已分配的 spinlock 变量 */

rt_hw_spin_lock()       /* 获取 spinlock,忙等待直到获取成功 */

rt_hw_spin_unlock()     /* 释放 spinlock  */
需要定义自旋锁:
typedef union {
    unsigned long slock;
    struct __arch_tickets {
        unsigned short owner;
        unsigned short next;
    } tickets;
} rt_hw_spinlock_t;
不使用 SMP 的时候,在进行调度等需要临界资源保护的情况下,是通过 rt_hw_interrupt_disable/enable  来屏蔽中断进行保护,但是在 SMP 中,对 rt_hw_interrupt_disable/enable 进行了替换,从而保证对共享资源访问的互斥:
/* 在 rthw.h 中 */
#ifdef RT_USING_SMP
    #define rt_hw_interrupt_disable rt_hw_local_irq_disable
    #define rt_hw_interrupt_enable  rt_hw_local_irq_enable
#endif
因为 SMP 使用了多核,调度和同步的情况相较于单个处理器更加复杂和重要,这部分是移植的重点。需要针对开发平台的不同,对以下函数进行重写(对于 Cortex-M 内核,需要注意辅助上下文切换的 PendSV 也是一种中断):
/* 实现从当前线程切换到目标线程,在 Cortex-M 内核里 rt_hw_context_switch() 和 rt_hw_context_switch_interrupt() 功能一致 */
rt_hw_context_switch_interrupt:
rt_hw_context_switch:

/* 实现没有来源线程切换到目标线程 */
rt_hw_context_switch_to:

/* PendSV 中断处理函数,在 Cortex-M 内核里 PendSV 辅助完成上下文切换 */
PendSV_Handler:
这部分需要在 context_gcc.S 文件中实现。
移植 SMP 的重点是调度与同步,大家在移植之前,最好对 RT-Thread 的调度流程和中断机制有一定的学习和理解,这部分可以参考 RT-Thread 文档中心,最好能配合着理解源码的实现。我对 RT-Thread 框架下的 SMP 目前的理解就是以上这些,欢迎大家交流讨论。
ref:

回复

使用道具 举报

  • TA的每日心情
    慵懒
    昨天 23:06
  • 签到天数: 1467 天

    [LV.10]以坛为家III

    203

    主题

    2万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    92135
    最后登录
    2024-3-28
    发表于 2023-2-8 12:20:53 | 显示全部楼层
    刚好55s69是双核的
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-2-26 09:09
  • 签到天数: 13 天

    [LV.3]偶尔看看II

    7

    主题

    950

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1906
    最后登录
    2024-3-29
    发表于 2023-2-12 14:02:46 | 显示全部楼层
    你那边移植好后,我估计就可以看看多核同时跑时的效果和单核有啥区别了,还没玩过多核的情况下跑RTT
    ~~~~~~~~~~~~
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-3-29 19:55 , Processed in 0.260933 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表