RT-Thread SMP介绍与移植

SMP:(Symmetrical Multi-Processing)对称多处理,简称SMP,是指在一个计算机上汇集了一组处理器(多CPU),各CPU之间共享内存子系统以及总线结构。

RT-Thread自v4.0.0版本开始支持SMP,在对称多核上可以通过使能RT_USING_SMP来开启。

多核启动

系统上电后,每个CPU都会在ROM中的代码控制下独自运行,但是只有主处理器(简称CPU0)跳转到RT-Thread的初始化入口处,而其它的处理器(简称次级CPU)则会暂停在某个状态下,等待CPU0将它们唤醒

CPU0完成RT-Thread的全局初始化过程,包括外设初始化,中断控制器的中断分发部分初始化、全局变量的初始化、全局内核对象的创建等等。

最终,CPU0在执行main线程之前,唤醒其它的次级CPU,引导它们执行次级CPU的初始化代码,这段代码会让各个次级CPU去完成自身相关的硬件初始化,并开启任务调度。

此后,系统进入正常运行阶段。系统启动阶段各个 CPU 的动作如下图所示:
在这里插入图片描述
每个次级CPU自身硬件部分的初始化不能由CPU0完成,因为其自身硬件不能由其它CPU访问

CPU0启动流程

在SMP平台上,启动核心CPU0的启动流程和单核CPU上的启动过程相同,主要流程如图所示:
在这里插入图片描述
由于硬件平台和编译器的不同,系统上电后执行的初始化代码和启动流程并不相同,但是系统最终统一调用入口函数rtthread_startup()来启动RT-Thread。
该函数设置硬件平台、初始化操作系统各组件、创建用户main线程,并最终开启当前CPU的任务调度机制,开始正常工作。

当开启了CPU0的任务调度器之后,CPU0上通常存在两个线程:main线程和idle线程,用户可以通过修改配置选项或者通过RT-Thread提供的接口创建新的线程,调度器依据优先级和线程状态从中选择就绪线程执行。

次级CPU启动流程

如果定义了配置选项RT_USING_SMP,CPU0的main线程在运行过程中会执行函数rt_hw_secondary_cpu_up()以启动其它CPU核心。

该函数由移植内核的开发人员提供,完成以下两个操作:

  1. 设置次级CPU的启动入口地址;
  2. 加电启动次级CPU。

在RAMv7-A中,次级CPU的启动入口地址固定设置为secondary_cpu_start,该标号定义在文件libcpu/arm/cortex-a/start_gcc.S中,主要包括设置当前CPU的内核栈,建立MMU内存映射表,然后跳转到函数secondary_cpu_c_start()执行。

函数secondary_cpu_c_start()是所有次级CPU的初始化函数,它同样与硬件平台密切相关,由移植系统的开发者提供,需要完成以下步骤:

  1. 初始化当前CPU的中断控制器,设置中断向量表;
  2. 设置定时器为当前CPU产生tick中断;
  3. 获取内核自旋锁_cpus_lock以保护全局任务表,调用函数rt_system_scheduler_start()开启当前CPU的任务调度器。

全志T3芯片采用GIC中断控制器,系统通过Generic Timer定时器提供tick中断计数,函数secondary_cpu_c_start()代码如下:

在这里插入图片描述
每个次级CPU启动之后,从全局任务表和当前CPU的局部任务表中选取优先级最高的任务执行,在优先级相同的情况下,优先选择当前CPU的局部任务表中的任务执行。

在不存在其它任务的情况下,每个CPU调度自己的idle任务执行。
其中,CPU0的idle任务循环执行函数rt_thread_idle_execute(),而次级CPU的idle任务循环执行函数rt_hw_secondary_cpu_idle_exec()。
在这里插入图片描述

任务特性

RT-Thread中的任务分为以下状态:

  • 运行态:任务正在某个CPU上执行;
  • 就绪态:任务随时可以被执行,但尚未分配到CPU,因此等待在某个就绪态任务表中;
  • 挂起态:任务因条件不满足(等待超时或者数据到来等),而不能够被执行。
  • 关闭态:任务已经被删除,正在等待被回收。

在进入正常运行阶段后,每个CPU都独自地运行中断处理、调度器以及任务的代码。RT-Thread在多核系统上运行时存在以下特性:

  1. 同一时刻,一个任务(线程)只会运行在一个CPU上;
  2. 每个CPU互斥地访问全局调度器数据,以确定将要在当前CPU上运行的任务;
  3. 支持将任务绑定在某一个CPU上运行。

调度策略

为了实现上述目标,RT-Thread调度器实现了两种就绪任务队列:

  1. 全局就绪任务表rt_thread_ready_table[],包含没有绑定CPU的就绪任务;
  2. CPU局部就绪任务表ready_table[],每个CPU对应一个,包含绑定到对应CPU的就绪任务。典型的CPU绑定任务是每个CPU自己的idle任务。

当CPU需要切换任务执行时,任务调度器查找系统中优先级最高的就绪任务执行,即全局就绪任务表和当前CPU的局部就绪任务表中优先级最高的任务。在优先级相同的情况下,优先选取局部任务表中的任务。

相对应的是,如果一个任务由其它状态变为就绪状态,则进行如下处理:

  1. 如果它不是CPU绑定任务,则把它挂入全局就绪表,并向其它的所有CPU发送IPI中断,通知它们检查是否需要切换任务,因为其它CPU的当前任务的优先级可能低于此就绪态任务,因而会发生优先级抢占。
  2. 如果它是一个CPU绑定任务,检查它是否比对应CPU的当前任务优先级高,如果是则发生优先级抢占,否则把它挂入对应CPU的局部就绪任务表。整个过程不通知其它CPU。

处理器间中断IPI

当单个CPU上运行的任务改变了系统状态,或者触发了某个事件,需要通过处理器间中断(Inter-Processor Interrupt)通知其它CPU,其它CPU在收到该信号后,调用注册的相应例程进行处理。

void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)

OS Tick

在SMP系统中,每个CPU维护自己独立的tick值,用作任务运行计时以及时间片统计。
除此之外,CPU0还通过tick计数来更新系统时间,并提供系统定时器的功能,次级CPU不需要提供这些功能。

在初始化次级 CPU 的过程中,每个 CPU 需要使能各自的 tick 定时器,并注册相应的 tick 中断处理函数。使能 tick 定时器的操作与具体的硬件平台相关,需要移植内核的开发者提供;而 tick 中断处理函数主要完成两个动作:

设置 tick 定时器的状态。
增加当前 CPU 的 tick 计数。

自旋锁spinlock

在SMP系统中,通过关中断的方式不能阻止多个CPU对共享资源的并发访问,需要通过自旋锁机制进行保护。
和互斥锁类似,在任何时刻,自旋锁最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。
不同的是,对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。而自旋锁不会引起调用者睡眠,而是循环查询直到该自旋锁的保持者已经释放了锁。

初始化已分配的spinlock变量:

void rt_spin_lock_init(struct rt_spinlock *lock)

获取spinlock,忙等待直到获取成功:

void rt_spin_lock(struct rt_spinlock *lock)

释放spinlock:

void rt_spin_unlock(struct rt_spinlock *lock)

如下函数禁止当前CPU中断后获取spinlock,忙等待直到获取成功:

rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock)

任务绑定

通常系统中的就绪任务位于全局就绪任务表中,每个任务在哪个CPU上调度运行是随机的。
通过将就绪任务放入到某个CPU局部就绪任务表列表中,RT-Thread允许将任务与CPU绑定,即该任务只能够在指定的CPU上。

rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *args)

当参数cmd的值为RT_THREAD_CTRL_BIND_CPU时,函数将线程thread绑定到参数arg指定的CPU上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/315817.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

超级好看的个人主页源码

源码介绍 超级好看的个人主页源码HTML,使用了 HTML、CSS 和 JavaScript 技术,带音乐播放器 需要修改什么到代码里面自行修改,记事本就可以打开,总之,这个个人主页源码非常漂亮和实用,使用了许多现代的 Web 技术来创建一个响应式、…

个人网站制作 Part 3 用JS添加高级交互(表单验证、动态内容更新) | Web开发项目

文章目录 👩‍💻 基础Web开发练手项目系列:个人网站制作🚀 使用JavaScript进行交互🔨表单验证🔧步骤 1: 添加JavaScript文件🔧步骤 2: 更新表单HTML 🔨动态内容更新🔧步骤…

API设计:从基础到最佳实践

1*vWvkkgG6uvgmJT8GkId98A.png 在这次深入探讨中,我们将深入了解API设计,从基础知识开始,逐步进阶到定义出色API的最佳实践。 作为开发者,你可能对许多这些概念很熟悉,但我将提供详细的解释,以加深你的理解…

冷风机系统的拟定和制冷循环的热力计算

一,冷风机系统的概述 单元式冷风机是一种不带加湿器的非热泵型单元式空气调节机,只能用于夏季降温,按标准 GB/T 17758-1999《单元式空气调节机组》的规定1,单元式冷风机应能使室内温度保持在(18℃-25℃)1℃,相对温度 (…

数据洞察力,驱动企业财务变革

我们不得不面对一个现实,就是数据量的剧增。加上大部分企业并不愿意删除历史数据,以防未来预测分析时需要,这造成数据就像一个雪球,越滚越大。然而,过多的数据和数据不足一样会成为企业发展和理解分析的障碍。从海量数…

Android Studio安卓读取EM4100 TK4100卡卡号源码

本示例使用的读卡器&#xff1a;https://item.taobao.com/item.htm?spma1z10.5-c.w4002-21818769070.35.44005b43nb1q2h&id562957272162 <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmln…

Python学习从0到1 day3 python变量和debug

没关系&#xff0c;这破败的生活压不住我 ——24.1.13 一、变量的定义 1.什么是量&#xff1f; 量是程序运行中的最小单元 2.什么是变量呢&#xff1f; ①变量是存储数据的容器 ②变量存储的数据时临时的&#xff0c;变量只有在程序运行过程中是有效的&#xff0c;当程序执行结…

TreesVariety

树木品种 - 树木和植物捆绑包。与“植被引擎”兼容的包装 通用和HDRP的树木包在这里 树木品种: ● 支持Unity Wind; ● 11种树木,7种植物; ● Unity树创建器树(可编辑); ● 与内置管道配合使用; ● 支持地形广告牌。 树木: ● 8棵桦树; ● 4块枫木; ● 8块橡木; ●…

第八讲 单片机驱动彩色液晶屏 控制RA8889软件:显示图片

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…

【排序篇1】插入排序、希尔排序

目录 一、插入排序二、希尔排序 一、插入排序 思路&#xff1a; 插入排序就像玩扑克牌&#xff0c;抽出一张牌作为比较的元素&#xff0c;与前面的牌依次进行比较&#xff0c;小于继续往前比较&#xff0c;大于等于停下插入到当前位置。 图示&#xff1a; void InsertSort(…

DNS域名解析以及操作流程

dns:将域名转化为IP地址的过程&#xff0c;域名方便人们记忆&#xff0c;ip地址过长&#xff0c;且都是数字&#xff0c;不方便记忆&#xff0c;所以才出现了域名。 怎么实现访问域名等于访问ip地址 1.老方法&#xff1a;写入文件里 /etc/hosts 左边 IP地址 右边域名 格式例…

S1-05二进制信号量和计数器信号量

二进制信号量 二进制信号量&#xff0c;又叫二值信号量&#xff0c;要么是0&#xff0c;要么是1&#xff0c;也是通过Take和Give方式获取和释放&#xff0c;用于控制对共享资源的访问。在每次访问共享资源之前需要获取二进制信号量&#xff0c;若已被获取则任务会被阻塞直到二…

技术专栏——你所不知道的 RocketMQ 的集群管理:副本机制

这些精彩的技术类型的体系化文章&#xff0c;后面我会放到公众号上&#xff0c;并集中在合集“分布式消息中间件专栏”中&#xff0c;欢迎大家去订阅我的公众号和视频号“架构随笔录”&#xff0c;大家可以订阅合集&#xff0c;这样更加方便喔&#xff0c;后面会出电子版本&…

电脑上不安装Oracle,但是虚拟机装了Oracle,怎么连接到虚拟机里的Oracle数据库呢?

1、准备工作 1.1、确定数据库版本信息 注&#xff1a;如果知道数据库的版本信息&#xff0c;这个步骤可以跳过。 比较简单的方法&#xff0c;直接看数据库的安装位置&#xff0c;也就是数字&#xff08;但是这个方法确定就是&#xff0c;不好确定是多少位的数据库&#xff09;…

AI智能分析网关V4烟火检测算法解决方案

一、背景需求 根据国家消防救援局公布的数据显示&#xff0c;2023年共接报处置各类警情213.8万起&#xff0c;督促整改风险隐患397万处。火灾危害巨大&#xff0c;必须引起重视。传统靠人工报警的方法存在人员管理难、场地数量多且分散等问题&#xff0c;无法有效发现险情降低…

微信小程序(二)事件绑定

注释很详细&#xff0c;直接上代码 新增内容&#xff1a; 点击事件绑定注册页面设置页面初始化数据事件处理函数的实现更新数据并更新视图 源码&#xff1a; index.wxml <!-- 页面的数据绑定 --> <view>{{msg}}</view> <!-- 绑定点击事件 --> <but…

openssl3.2 - 官方demo学习 - cipher - aesgcm.c

文章目录 openssl3.2 - 官方demo学习 - cipher - aesgcm.c概述笔记END openssl3.2 - 官方demo学习 - cipher - aesgcm.c 概述 AES-256-GCM 在这个实验中验证了EVP_CIPHER_fetch()中算法名称字符串的来源定位. 在工程中配置环境变量PATH, 且合并环境. 这样就不用将openSSL的D…

【Python】编程练习的解密与实战(四)

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《Python | 编程解码》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1fa90;1. 初识Python &a…

Spring Boot - Application Events 的发布顺序_ApplicationStartedEvent

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c;它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…

linux 服务器上安装 ftp(亲测有效)

目录 1 需求2 安装 1 需求 服务器上需要安装ftp 2 安装 1 下载地址 https://developer.aliyun.com/packageSearch?wordvsftpd或者 https://rpmfind.net/linux/rpm2html/search.php?queryvsftpd2 如何判断 服务器是否安装了ftp rpm -qa | grep vsftpd出现提示则表示已安装…