美文网首页
树莓派提高实时性的几种方式(使用python测试)

树莓派提高实时性的几种方式(使用python测试)

作者: 阿呆0412 | 来源:发表于2019-01-31 11:05 被阅读0次

    前言

    本文基于python3.5+, 树莓派型号为3b+

    1. 关于树莓派的实时性

    2. 几种思路与实现

    2.1 提高优先级

    提高优先级可以通过wiringpi库提供的piHiPri(pri)方法实现
    其中,pri为int类型,取值范围为[0,99], 根据python中的实际测试,0为默认值,1优先级最高,99最小(此处貌似和资料不一致,但是实际测试是这样),使用方法为在执行前调用piHiPri()方法,具体代码如下:

    import wiringpi
    wiringpi.piHiPri(pri)
    

    2.2 绑定CPU

    绑定cpu需要两个操作:

    • 在系统中屏蔽掉一个或多个cpu
    • 代码中绑定cpu

    屏蔽cpu的实现方法:
    /boot/cmdline.txt 中末尾添加isolcpus=x
    其中x为屏蔽的核心 X=3时为树莓派中的最后一个cpu(树莓派3b为例,cpu编号为0-3)
    此处注意,添加的isolcpus=x不能起新行,需要写在原行的末尾,如:

    
    dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=3a7978f6-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait isolcpus=3
    
    

    添加后重启系统,使用htop命令查看cpu占用(没有可以用apt-get install htop安装),如下图:

    htop命令下的cpu占用情况
    此时系统自身调度不会再占用最后一个cpu(此处显示序号为4,因为是从1开始的,在系统中实际编号为3)

    绑定cpu的方式:
    python中,可以使用affinity库来绑定制定cpu(没有可以用pip install affinity 安装),affinity库一共提供了两个方法:

    • affinity.get_process_affinity_mask(pid)
    • affinity.set_process_affinity_mask(dwMask)

    第一个方法传入pid,返回dwMask值,dwMask为CPU序号掩码,1(0001)代表只运行在CPU1,2(0010)代表只运行在CPU2,3(0011)代表可以运行在CPU1和CPU2,以此类推。
    第二个方法传入dwMask, 返回0为成功,-1为失败.该方法需要root用户权限.
    参考代码如下:

    def run():
        while True:
            pass
    
    p = multiprocessing.Process(target=run)
    p.start()
    pid = p.pid
    print(affinity.get_process_affinity_mask(pid))
    affinity.set_process_affinity_mask(pid, 15L)
    print(affinity.get_process_affinity_mask(pid))
    

    2.3 实时linux系统移植

    出于通用性的考虑,本文只讨论linux系统的patch

    2.3.1 RT-linux

    Linux是典型的分时应用系统,对于实时性要求很高的应用,必须对内核本身动手术。而RTLinux则采取了一种比较聪明也比较折中的办法:他们实现一个最底层的精简的调度器,用于调度实时线程,原来的内核本身则成为实时调度器的一个优先级最低的任务。这样,当有实时任务时,普通内核已经建立于其上的普通进程被强制中断,实时线程被强制执行;只有当若有实时线程都让出cpu之后,普通内核才被运行,再由普通内核去调度执行普通的应用程序

    移植方法:
    (1)首先下载树莓派linux源代码:
    git clone https://github.com/raspberrypi/linux.git

    注意,由于该repo比较大,而git其实不支持断点续传(git init + git fetch + git checkout的方式实测并不能续传,每次断链再次fetch都是从头开始),所以建议只clone一个分支,且令depth为1,下载成功后再下载历史记录(如果需要),则命令改为:
    git clone --depth=1 --single-branch --branch rpi-4.14.y git https://github.com/raspberrypi/linux.git

    本文选用4.14,目前最新的树莓派内核版本为为4.14

    (2)下载patch文件:
    https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/4.14/

    patch压缩包,在本地解压出.patch文件,并移动到clone好的linux/文件夹下即可

    (3)给linux内核打patch
    进入clone好的linux文件夹,执行命令
    cat *.patch | patch -p1

    (4)下载编译
    git clone https://github.com/raspberrypi/tools ~/tools

    (5)配置PATH变量,注意32bit和64bit系统存在差异(如果是其他版本的树莓派则不是arm-bcm2708,1代为):
    32位系统:

    echo PATH=\$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin >> ~/.bashrc
    source ~/.bashrc
    

    64位系统:

    echo PATH=\$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin >> ~/.bashrc
    source ~/.bashrc
    sudo apt-get install libc6:i386
    sudo apt-get install lib32stdc++6
    sudo apt-get install lib32z1
    

    如果文件夹或路径不同注意自己改名,zsh同理
    另外一些文章提到了另外一些依赖,如果可能也尽量安装(并不知道有何种影响,一般的报错可以先行google查询):

    sudo apt-get install bc
    sudo apt-get install libncurses5-dev libncursesw5-dev
    sudo apt-get install zlib1g:i386
    sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5
    

    (6)配置交叉编译设置
    进入linux目录,修改Makefile文件
    vim Makefile
    找到如下语句
    ARCH ?= arm,修改为 :
    CROSS_COMPILE ?= /home/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
    同样路径注意修改

    (7)检查依赖
    运行make menuconfig查看是否有报错,根据报错信息安装依赖或自行google

    (8)进行编译

    KERNEL=kernel7 
    make bcm2709_defconfig
    make zImage modules dtbs
    

    如需多核加速编译可以加–j8参数等

    (9)部署到内存卡
    插入sd卡和读卡器(格式化,分区等参考fdisk等命令)
    注意此sd卡已有rasbian系统
    挂载:

    mkdir mnt 
    mkdir mnt/fat32 
    mkdir mnt/ext4 
    sudo mount /dev/sdb1 mnt/fat32 
    sudo mount /dev/sdb2 mnt/ext4
    

    安装:
    sudo make INSTALL_MOD_PATH=mnt/ext4 modules_install

    备份与拷贝内核:

    sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img 
    sudo cp arch/arm/boot/zImage mnt/fat32/$KERNEL.img 
    sudo cp arch/arm/boot/dts/*.dtb mnt/fat32/ 
    sudo cp arch/arm/boot/dts/overlays/*.dtb* mnt/fat32/overlays/ 
    sudo cp arch/arm/boot/dts/overlays/README mnt/fat32/overlays/ 
    sudo umount mnt/fat32 
    sudo umount mnt/ext4
    

    (10)启动树莓派,检查是否安装成功
    运行uname -a查看是否有RT字段

    2.3.2 PREEMPT_RT

    2.4 利用中断

    2.5 连接外设(实时钟发生器)

    2.6 超频

    3. 测试

    影响延迟的变量包括:

    • cpu是否满载(或其他cpu是否满载)
    • 是否使用python(考虑到解释器的延迟)

    3.1 提高优先级

    3.2 绑定cpu

    3.3 实时操作系统移植

    3.4 利用中断

    4. 总结

    后记

    参考

    相关文章

      网友评论

          本文标题:树莓派提高实时性的几种方式(使用python测试)

          本文链接:https://www.haomeiwen.com/subject/mhkksqtx.html