无需交叉编译,直接在树莓派4b打64位实时系统preempt RT补丁过程记录(手动篇)

无需交叉编译,直接在树莓派4b打64位实时系统preempt RT补丁过程记录(手动篇)

一. 前言

    最近在做机械臂控制相关的项目,项目对控制实时性有要求。但是,为了以后上ROS系统做准备,所以就没有选择使用STM32+RTOS的搭配。之前觉得使用CAN总线发控制指令控制电机,Linux应该凑合能用。结果使用Linux的定时器固定间隔收发数据帧,发现定时器中断会出现每秒的开头100ms都无法进入定时器中断。初步怀疑,可能此时Linux系统的任务调度打断了定时器(纯属猜测)。同时,使用定时器间隔1ms,定时器会出现不准的情况。这些情况在后期打上preempt RT内核补丁之后,问题都已解决。
    我当前树莓派4B系统内核是64位 Linux v6.1版本,当下能找到官方编译好的preempt RT是v4.19版,而且不是64位系统的,所以无法直接拿来使用。经过查找,这位名叫Menubis的博主写的技术贴,记录了如何交叉编译树莓派64位 preempt RT内核,连接如下:
64bit RT Kernel Compilation for Raspberry Pi 4B.
但是,可能是我虚拟机上的ubuntu没有设置合理,到编译阶段出现报错,升级就此打住。后来,在CSDN上xingmh写的《树莓派4B修改内核源码并编译》的帖子,他直接在树莓派4B上完成内核源码的修改和编译,这样可以简化在PC上进行交叉编译的流程,但相对来说耗时会长一些。所以,我直接将这两篇贴文结合,在树莓派4B上直接完成Preempt RT内核源码修改和编译,回避了交叉编译不知道哪出错的问题。

二. 过程记录

  1. 找一张32G的TF卡,下载树莓派官方的Imager,烧写树莓派64位系统(此时系统为非实时)的。你也可以烧写其他镜像,理论上编译过程都一样,这里以Raspberry pi os lite(64-BIT) 为例。点下“齿轮”图标,可以设置ssh和wifi,方便后面用ssh远程连接。
    Imager 界面
  2. 安装完成后,使用ssh连接树莓派(我是用MobaXterm),使用uname -a 查询系统版本。可以看到发稿时树莓派官方的64位内核为6.1.21。此时是PREEMPT 不是PREEMPT_RT。
uname -a

uname -a 结果

  1. 解锁树莓派root账户
    使用 sudo passwd root 设置root账户的密码
    使用 sudo passwd –unlock root 解锁root 账户
    使用 su root 进入root用户
sudo passwd root 
sudo passwd –unlock root
su root 

在这里插入图片描述

  1. 进入root目录,下载必要的工具
cd /root
apt-get install bc git bison flex libssl-dev make vim git
apt-get install libncurses5-dev libncursesw5-dev
  1. 在/root目录下,使用git下载树莓派官方liunx源码(我测试时,使用的是6.1,可以根据自己的系统下载对应版本)
git clone --depth=1 https://github.com/raspberrypi/linux --branch rpi-6.1.y

树莓派官方github内核源码
在这里插入图片描述
下载结束后会在/root目录下出现一个linux文件夹。
在这里插入图片描述

  1. 查看linux源码内核版本,查看Makefile文件前10行。我现在的是6.1.43。
cd linux
head -n 10 Makefile

在这里插入图片描述

  1. 下载preempt RT的内核源码, 找到适合你的版本
    PREEMPT RT 内核源码地址
    在这里插入图片描述

  注意:这里Preempt RT内核版本要与前面linux源码内核版本前两个数字要一致。比如,我上面选用的是6.1.43的内核,在rt内核要选择版本相同的内核,也的是6.1的。至于第三个数字Preempt RT内核版本的第三位数字要小于等于所选的linux内核,即:要选择6.1.43小的或者等于的。在网页中,最新的是6.1.38。
  另一个点,要选择有三个数字的,我做过实验,如果只选择像6.1-rc3这样的,编译不通过。代码如下:先退回root根目录下。

cd /root
wget https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patch-6.1.38-rt12.patch.gz
  1. Preempt RT编译工作
      进入linux文件夹,然后完成编译工作。使用gzip这个命令时,注意你下载的patch-6.1.38-rt12.patch.gz文件所存放的目录。如果你按照我的步骤,就直接使用,出现success说明patch就成功了。
    命令如下:
cd linux
gzip -cd ../patch-6.1.38-rt12.patch.gz | patch -p1 --verbose
KERNEL=kernel8
make bcm2711_defconfig

下载patch-6.1.38-rt12.patch.gz的过程:
在这里插入图片描述
patch成功。如果不成功注意你gzip这一步的文件目录。我是在linux文件夹下执行的。
在这里插入图片描述
bcm2711_defconfig 配置成功:
在这里插入图片描述

  1. Preempt RT编译设置
    进入编译器设置界面。注意你使用的ssh软件要留有足够大的屏幕空间。我用MobaXterm,如何你把命令行屏幕占比太小,这一步会出现display error的错误。
make menuconfig

在这里插入图片描述
本步骤共有三个要点:
(1)将系统设置为Real Time 系统,进行选择。
  General setup -> Preemption Model -> Fully Preemptible Kernel(Real-Time)
在这里插入图片描述
在这里插入图片描述

(2) 修改定时器频率为1000HZ。
  Kernel Features -> Timer frequency -> 1000HZ
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
(3) 修改 Timers Subsystem
   General setup -> Timers Subsystem->保证high Resolution Timers Support前面有星。
在这里插入图片描述

在这里插入图片描述
Save保存设置,返回到命令行。

  1. 开始漫长编译内核(大约3.5个小时)
    在linux文件夹下,输入以下命令:(-j8里的8是指用多少线程去跑)。如果没有错误,恭喜编译成功。
make -j8

如下图,编译成功:
在这里插入图片描述

  1. Preempt RT 内核安装
    如果一切顺利,可以使用以下命令把编译好的模块拷贝到系统目录下(一般是/lib/modules/)。
make modules_install

安装成功如下:
在这里插入图片描述

  1. 将RT内核替换当前树莓派系统内核(如果你下载的内核是2023年10月以后的,请看本文末尾)
    在linux文件夹下,arch/arm64/boot下,将生成的Image修改名字为kernel8.img,然后拷贝到/boot分区里,在/linux下输入命令如下:
cd arch/arm64/boot
mv Image kernel8.img
cp kernel8.img /boot

复制后,系统的/boot文件夹如下图:
在这里插入图片描述

  1. 更新引导配置文件,加载kernel8.img,重新启动树莓派。
    使用vim打开/boot/config.txt。
vim /boot/config.txt

在这里插入图片描述
在文件最后增加 kernel=kernel8.img。保存,重启系统。(你也可以用nano打开,我个人喜欢用vim。在此缅怀以下vim的作者Bram Moolenaar,在前几日去世了,享年62岁。感谢他为开源社区做的巨大贡献。)
在这里插入图片描述

  1. 重启后,查看系统变化。
    如果以上步骤都成功的话,待系统重启后,重新输入 uname -a 可以发现系统变为了PREEMPT_RT,说明成功升级为real time的linux。普天同庆!
uname -a

在这里插入图片描述

三.总结

github有时需要自己准备魔法才能成功下载或者有时下载速度贼慢。所以,我为大家准备好了网盘连接:
ttps://pan.baidu.com/s/1DHk3jTZm3X1dVLFtCCnO_Q? 口令:0d00
,你可以自行下载拷贝到你的树莓派上。希望大家可以积极回复,点赞,关注,以后还会出更多相关嵌入式,机器人控制,HCPS, 电子设计相关文章。


2023/12/31 修改:
官方在2023年10月之后的更新了内核,把内核目录更换了。所以,第12步 “将RT内核替换当前树莓派系统内核”,这里需要更改内核目录位置。根据网友lingrenyu提供的建议(可以看评论),最新的树莓派内核放在了/boot/firmware/下,所以make modules_install之后需要把编译好的内核、设备树、文件系统等内容复制到该目录,执行命令(编译的linux内核文件夹下):

cd /root/linux
cp arch/arm64/boot/dts/broadcom/*.dtb /boot/firmware
cp arch/arm64/boot/dts/overlays/*.dtb* /boot/firmware/overlays/
cp arch/arm64/boot/dts/overlays/README /boot/firmware/overlays/
cp arch/arm64/boot/Image /boot/firmware/kernel8.img
nano /boot/firmware/config.txt

最后一行代码使用nano打开 config.txt内核启动配置文件,在它的最后一行加上:

kernel=kernel8.img

保存,重启之后,大功告成!!!


preempt-rt是一个在Linux操作系统内核中实施实时(real-time)功能的一个软件补丁(patch),用于提高Linux操作系统实时性能。在普通的Linux内核中,时间分片是通过时间片轮转法来实现的,这意味着任务可能会在中断的时候被打断,从而导致实时任务无法按时完成。而preempt-rt补丁则引入了抢占式调度(preemptive scheduling),可以在高优先级实时任务到来时,立即中断低优先级任务,从而确保实时任务按时完成。 preempt-rt补丁还引入了一些改进,比如提高了中断处理的实时性,减少了中断的延迟。此外,它还改进了内核对多核处理器的支持,能够更好地利用多核处理器的性能,提高系统的响应能力。这使得Linux操作系统可以用于处理实时应用,比如工业控制、自动驾驶和机器人等领域。 preempt-rt补丁不仅仅是一个补丁,它还需要与其他实时工具和库一起使用,比如实时定时器和实时优先级调度策略等,来共同实现实时功能。有了preempt-rt补丁Linux操作系统就可以满足实时性要求更高的应用需求,使得开发者可以更自由地选择Linux平台来开发实时应用。 但是需要注意的是,preempt-rt补丁并不适用于所有场景。由于引入了更严格的实时约束,它可能导致系统的稳定性下降,对内存和处理器资源的需求也相应增加。因此,在使用preempt-rt补丁时,需要对系统进行全面评估,并根据实际需求进行权衡。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值