香橙派(orangePiZero2):交叉编译、内核编译及驱动开发

这篇具有很好参考价值的文章主要介绍了香橙派(orangePiZero2):交叉编译、内核编译及驱动开发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、准备工作

1、安装好相关环境(Ubuntu 18.04)

开发板:orangepi-zero2

交叉编译器:aarch64-none-linux-gnu-

2、安装交叉编译工具:

(1)下载并安装交叉编译工具,下载地址如下:Index of /armbian-releases/_toolchain/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

下载好压缩包,将压缩包放到Ubuntu里如下所示:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

输入以下命令进行压缩包的解压:

tar -xf gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

解压完后,会有一个文件夹,输入命令进入文件夹,可看到对应的交叉编译工具:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

(2)设置环境变量临时有效

        1)输入以下命令,输出环境变量:

        echo $PATH

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

        2)pwd,打印当前路径:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

        3)设置临时环境变量,用到以下命令:

        export PATH=$PATH:<路径>         

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

        4)我们再次输出环境变量,看看是否已经添加进来:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

        但是,这个方法只适用于当前终端,一旦当前终端关闭或者在其他终端中则无效。它是一个临时的环境变量。

(3)设置永久有效

        修改工作目录的 .bashrc 是一个隐藏文件,用来配置命令终端(这里要注意每个人的工作目录可能不太一样,不要盲目复制命令,有些命令是需要改动的)。

vi /home/wsm/.bashrc

注意:上面路径中的wsm是我自己的工作目录,每个人的不一样,需要按照自己的工作目录修改

在最后一行加上:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/wsm/orangePiZero2/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin

保存并退出,然后输入以下命令,使其生效:

source /home/wsm/.bashrc

(5)测试,验证是否成功:

在虚拟机编写一个hello.c的文件如下:

/*************************************************************************
        > File Name: helloc.c
        > Author:阿哈、小吴
        > Mail: 1971363937@qq.com 
        > Created Time: Sun 05 Nov 2023 06:23:58 AM PST
************************************************************************/

#include <stdio.h>
 
int main(void){
      printf("hello!\n");
      return 0;
}

用交叉编译工具编译为 test可执行文件:

aarch64-none-linux-gnu-gcc hello.c -o test

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

查看test文件是否是arm架构:

file test

如下:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

        证明我们交叉编译工具已经安装好,你也可以将test文件拷贝到板子上运行看是否正常。

3、将Linux SDK 的源码准备好,并放在Ubuntu上,如下所示:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

4、先将Linux 内核压缩包解压出来

unzip orangepi-build-main.zip

解压后,会多出解压好的文件夹:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

二、编译 Linux 内核

1、先进入我们解压好的源码文件夹,如下所示:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

2、运行 buid.sh 脚本,输入如下命令:

sudo ./build.sh

它会自动帮我们下载编译工具和源码。

3、运行上述脚本后,弹出下图,我们选择 Kernel package ,然后按回车:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

4、紧接着,需要我们选择开发板的型号,这里我的开发板的型号是 OrangePiZero2,选择按回车即可:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

5、接着选择型号分支,我的开发板是linux 4.9的,按回车即可:

(1)current 会去编译 linux 5.13

(2)legacy 会去编译 linux 4.9

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

6、然后会弹出 make menuconfig 配置内核的界面,此时,可以直接修改内核的配置,这里我没有配置,直接退出,退出后就会开始编译内核源码:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

        (1)如果不需要修改内核的配置选项,在一开始运行 build.sh 脚本时,传入 KERNEL_CONFINGRE=no 就可以临时屏蔽弹出内核的配置界面了。

sudo ./build.sh KERNEL_CONFIIGURE=no

        (2)如果你想永久禁用内核配置界面的弹出,也可以设置 orangepi-buid-main/userpatches/config-default.conf 配置文件中的 KERNEL_CONFINGRE=no ,这样就可以永久禁用这个功能了:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

        (3)编译内核的时候,如果提示错误信息为 Your display is too small to run MenuConfig! ,这是由于你的 Ubuntu PC 的终端界面太小,导致 MenuConfig 的界面无法显示,这时,只要重新把终端调大,然后重新运行 build.sh 脚本即可。

7、编译内核源码时,提示的部分信息说明如下(了解)

        (1)Linux 内核源码的版本信息:

        [ o.k. ]Compiling legacy Kernel [ 4.9.170 ]

        (2)使用的交叉编译工具链的版本:

         [ o.k. ]Compiler version [ aarch64-none-linux-gnu-gcc 9.2.1 ]

        (3)内核默认使用的配置文件以及它存放的路径:

         [ o.k. ]Using kernel config file [ config/kernel/linux-sun50iw9-legacy.config ]

        (4)如果 KERNEL_CONFINGRE=yes ,内核最终使用的配置文件 .config 会复制到 output/config 中,如果没有对内核配置进行修改,最终的配置文件和默认的配置文件是一致的:

        [ o.k. ]Exporting new kernel config [ output/config/linux-sun50iw9-legacy.config ]

        (5)编译生成的内核相关的 deb 包的路径:

        [ o.k. ]Target directory [ output/debs ]

        (6)编译生成的内核镜像 deb 包的包名:

        [ o.k. ]File name [ linux-image-legacy-sun50iw9_2.2.0_arm64.deb ]

        (7)编译使用的时间:

        [ o.k. ]Runtime [ 5 min ]

        (8)最后会显示重复编译上一次选择的内核的编译命令,使用下面的命令无需通过图形界面选择,可以直接开始编译内核源码:  香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

8、编译好后,生成的目录如下:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

以上文件释义如下所示:

a. build.sh: 编译启动脚本
b. external: 包含编译镜像需要用的配置文件、特定功能的脚本以及部分程序的源码,编译镜像过程中缓存的 rootfs 压缩包也存放在 external 中
c. kernel: 存放 linux 内核的源码,里面名为 orange-pi-4.9-sun50iw9 的文件夹存 放 的 就 是 H616 系 列 开 发 板 legacy 分 支 的 内 核 源 码 , 里 面 名 为orange-pi-5.13-sunxi64 的文件夹存放的就是 H616 开发板 current 分支的内核源码(如果只编译了 legacy 分支的 linux 镜像,那么则只能看到 legacy 分支的内核源码;如果只编译了 current 分支的 linux 镜像那么则只能看到current 分支的内核源码),内核源码的文件夹的名字请不要手动修改,如果修改了,编译系统运行时会重新下载内核源码
d. LICENSE: GPL 2 许可证文件
e. README.md: orangepi-build 说明文件
f. output: 存放编译生成的 u-boot、linux 等 deb 包、编译日志以及编译生成的镜像等文件
g. scripts: 编译 linux 镜像的通用脚本
h. toolchains: 存放交叉编译工具链
i. u-boot: 存放 u-boot 的源码,里面名为 v2018.05-sun50iw9 的文件夹存放的就是 H616 系列开发板 legacy 分支的 u-boot 源码,里面名为 v2021.07-sunxi的文件夹存放的就是 H616 开发板 current 分支的 u-boot 源码(如果只编译了current 分支的 linux 镜像,那么则只能看到 current 分支的 u-boot源码),u-boot 源码的文件夹的名字请不要手动修改,如果修改了,编译系统运行时会重新下载 u-boot 源码
j. userpatches: 存放编译脚本需要用到的配置文件

编译好的内核文件就在 kernel 下。

三、内核移植

1、查看我们编译生成的内核相关的 deb 包:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

我生成的如下所示: 香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

2、将编译好的 deb 上传至 开发板的 /root 目录下:

可以通过SSH连接,使用scp命令上传

scp linux-image-legacy-sun50iw9_2.2.2_arm64.deb root@orangepi:/root

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

3、查看已经安装了的 deb 文件:

dpkg -l | grep linux-image

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

4、卸载开发板中的 deb 文件:

apt purge -y linux-image-legacy-sun50iw9

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

5、安装上传的 deb 文件:

dpkg -i linux-image-legacy-sun50iw9_2.2.2_arm64.deb

6、重启开发板

sudo reboot.

7、再次查看安装的 deb 文件:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

可见,已经安装好了最新的 deb 文件。

四、驱动编译

1、写一个示例代码(放在orangepi-build-main/kernel/orange-pi-4.9-sun50iw9/drivers/char 下):

新建一个 pin4driver.c 文件:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

文件写入代码如下:

#include <linux/fs.h>        //file_operations声明
#include <linux/module.h>    //module_init  module_exit声明
#include <linux/init.h>      //__init  __exit 宏定义声明
#include <linux/device.h>    //class  devise声明
#include <linux/uaccess.h>   //copy_from_user 的头文件
#include <linux/types.h>     //设备号  dev_t 类型声明
#include <asm/io.h>          //ioremap iounmap的头文件

// 将该文件放在 orangepi-build-main/kernel/orange-pi-4.9-sun50iw9/drivers/char 下
static struct class *pin4_class;
static struct device *pin4_class_dev;

static dev_t devno;                //设备号
static int major =231;                     //主设备号
static int minor =0;                       //次设备号
static char *module_name="pin4";   //模块名

//led_read函数
static ssize_t pin4_read(struct file *file1,char __user *buf,size_t count, loff_t *ppos)
{
    printk("pin4_read\n");  //内核的打印函数和printf类似
    return 0;
}

//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{
    printk("pin4_open\n");  //内核的打印函数和printf类似
    return 0;
}

//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{

    printk("pin4_write\n"); 
    return 0;
}

static struct file_operations pin4_fops = {

    .owner = THIS_MODULE,
    .open  = pin4_open,
    .write = pin4_write,
    .read  = pin4_read,
};

int __init pin4_drv_init(void)  //真实入口 
{
    int ret;
    devno = MKDEV(major,minor);  //创建设备号
    ret   = register_chrdev(major, module_name,&pin4_fops);  //注册驱动  告诉内核,把这个驱动加入到内核驱动的链表中

    pin4_class=class_create(THIS_MODULE,"myfirstdemo");//由代码在Dev下自动生成设备
    pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);  //创建设备文件

    return 0;
}
void __exit pin4_drv_exit(void)
{

    device_destroy(pin4_class,devno);
    class_destroy(pin4_class);
    unregister_chrdev(major, module_name);  //卸载驱动

}
module_init(pin4_drv_init);  //入口 内核加载该驱动的时候,这个宏会被调用
module_exit(pin4_drv_exit);  //出口,卸载模块函数
MODULE_LICENSE("GPL v2");

2、怎么样才能编译到这个驱动代码呢?需要我们去修改 Makefile,如下所示:

注意:我们修改的是 orangepi-build-main/kernel/orange-pi-4.9-sun50iw9/drivers/char 这个路径下的 Makefile 文件!!!

我们需要编译成模块的方式,obj-m 就是模块的编译方式,我们需要在Makefile中添加:

obj-m += pin4driver.o

如下所示:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

3、然后我们需要回到内核的源码目录下,进行模块的编译,即 orangepi-build-main/kernel/orange-pi-4.9-sun50iw9 这个路径下:

(1)方法一:输入以下命令进行编译,这条命令是将所有内容都编译了,需要蛮久的:

make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j4

编译好后,可以看到编译生成的 .ko 文件所在的路径:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

(2)方法二:输入以下命令,只是编译模块,较快:

make modules ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu-

编译如下所示:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

4、将编译好的 pin4driver.ko 模块,拷贝到我们的开发板(可以用scp指令拷贝,也可用U盘拷贝)

这里讲一下用U盘拷贝的方法:

(1)首先先将 pin4driver.ko 模块 拷贝到 共享文件夹中:

cp pin4driver.ko /mnt/hgfs/share/

(2)查看共享文件夹中的文件:

ls /mnt/hgfs/share/

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

(3)从 windows 上的共享文件夹 将 pin4driver.ko 模块 拷贝到U盘上

(4)将U盘插到板子上, 用 dmesg 命令查看识别到的是哪个设备:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

可以看到内核识别到的设备是 sda1

(5)输入指令挂载U盘,挂载到 /mnt 目录下:

sudo mount /dev/sda1 /mnt/

挂载好后,cd 进入 /mnt 目录,再 ls,即可看到U盘下的文件:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

(6)用cp命令将 pin4driver.ko 模块 拷贝出来即可

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

(7)拷贝完后,需要取消U盘的挂载:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

(8)拔出U盘即可

5、在开发板中加载驱动模块:

(1)输入以下命令即可:

sudo insmod pin4driver.ko

(2)我们看一下是否生成了pin4这个设备驱动:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

模块名、主设备号与次设备号都与我们的驱动代码对上了:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

6、接下来就是测试

我们需要写一个应用程序来去调用我们的驱动程序:

写一个test.c程序如下(这是用户空间的代码):

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main()
{
        int fd;
        fd = open("/dev/pin4",O_RDWR);
        if(fd<0){
                printf("open failed!\n");
                perror("res");
        }else{
                printf("open success!\n");
        }
        fd = write(fd,'1',1);
}

编译运行:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

为什么无法打开呢?这是因为,我们加载的驱动的权限问题,我们需要给它可读可写的权限:

修改权限,再次执行即可:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

7、查看驱动层的输出语句:

输入dmesg查看:

香橙派toolchains交叉编译用哪个,香橙派,Linux驱动开发,linux

这样子,就完成了简单的字符设备驱动开发。

五、总结

        (1)通过insmod将模块,加载到内核中去,它会去 module_init 函数 加载驱动模块,再会去调用我们写的 pin4_drv_init 驱动入口函数,而这个函数又会去通过 register_chardev 函数去注册驱动,把这个驱动(整个file_operations结构体变量)加入到内核链表中。

        (2)当驱动装载成功后,会在 /dev/ 文件下生成 一个驱动(如pin4),但是要注意,我们需要给这个驱动一个所有用户均可读可写的权限。

        (3)(用户空间)应用程序中的 open 函数会去通过 系统调用sys_call(软中断,中断号是0x80) “陷入” 到内核空间(sys_call会调用sys_open),然后根据文件名找到相关的设备号,根据设备号从驱动链表里面找出驱动,如果找到了驱动就返回一个 fd 文件句柄。 

        (4)因为它会去调用驱动里面的 open 函数,于是,我们就会在内核里看到打印了相关的信息。文章来源地址https://www.toymoban.com/news/detail-770849.html

到了这里,关于香橙派(orangePiZero2):交叉编译、内核编译及驱动开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android驱动开发之如何编译和更换内核

    编译内核可以使用图形化的界面配置,也可以直接使用脚本。在X86_64模拟器环境下,不用交叉编译,而交叉编译工具很容易出现兼容问题,一般也只能使用芯片厂商提供的工具,而不是GNU提供的工具。 android内核开发流程以及架构变化了很多,详情请看 内核官网 内核版本选择

    2024年04月26日
    浏览(23)
  • 带wiringPi库的交叉编译 ---宿主机x86Ubuntu,目标机ARMv8 aarch64(香橙派)

    带wiringPi库的交叉编译如何进行 先交叉编译wiringPi库,编译出的库适合香橙派,这时候交叉编译可执行程序的平台和链接库的格式也是正确的 ,然后通过-I和-L来指定链接的wiringPi库的头文件和库的位置,但是现在还没有学习过,后面学了补上 此时如果把wiringPi库拿到Ubuntu上进

    2024年02月15日
    浏览(36)
  • QT学习笔记-oracle oci数据库驱动交叉编译并移植到ARM开发板

    在上一文《QT学习笔记-QT安装oracle oci驱动》中介绍了在Windows环境下使用QT访问oracle数据库时遇到驱动无法加载问题的解决办法,大体思路是对QT源码中数据库驱动的源码oci进行编译,要想通过编译需要依赖对应数据库的头文件和库(可以通过下载oracle instant client),编译通过

    2024年02月13日
    浏览(44)
  • Linux驱动开发一、RK3568把hello编译到Linux内核中运行。‘rk_vendor_read’未定义的引用

    1、在字符设备目录下建立hello目录 ~/Linux/rk356x_linux/kernel/drivers/char/hello 2、进入hello目录,新建hello.c、Makefile、Kconfig三个文件 3、Kconfig是打开make menuconfig配置界面是后的选项,这Kconfig是在字符设备下的。 config后面的HELLO就是对应配置后在kernel目录下的**.config中的CONFIG_HELLO配置

    2024年02月11日
    浏览(52)
  • 编译OpenWrt内核驱动

      编译OpenWrt内核驱动可以参考OpenWrt内部其它驱动的编写例程,来修改成自己需要的驱动 1.1、搭建环境   下载OpenWrt的官方源码: 1.2、安装编译依赖项 1.3、更新 feeds   进入openwrt目录后执行以下指令 1.4、配置编译选项   根据自己的平台来选择编译选项 1.5、下载 dl

    2024年02月09日
    浏览(34)
  • Linux驱动实践:带你一步一步编译内核驱动程序

    记得以前我在开始学习驱动开发的时候,找来很多文章、资料来学习,但是总是觉得缺少了点全局视角。 就好像:我想看清一座山的全貌,但总是被困在一个、又一个山谷中一样。 主要的困惑有 3 点: 每一篇文章的介绍都是正确的,但是如果把很多文章放在一起看,就会

    2023年04月24日
    浏览(39)
  • 【Linux驱动】内核模块编译 —— make modules 的使用(单模块编译、多模块编译)

    编译驱动一般采用的是将驱动编译成模块(.ko 文件),然后加载到内核,这其中就用到了 make modules 命令。 目录 一、单模块编译 1、一个 c 文件编译成一个 ko 文件 2、多个文件编译成一个 ko 文件 二、多模块编译(多文件多模块) 下面是最简易的单文件单模块编译,假设我们

    2024年02月10日
    浏览(40)
  • 安卓RK3399编译驱动MPU6050,实现内核层与HAL层驱动

    今天我们一起学习一下如何实现对一款有驱动代码的传感器适配安卓系统 开发板:某AR眼镜公司的开发板RK3399 1. 什么是设备树(.dts) DTS即Device Tree Source 设备树源码, Device Tree是一种描述硬件的数据结构,它起源于 OpenFirmware (OF)。 其主要目的是定义MCU各个引脚的接线功能,通过

    2024年02月04日
    浏览(32)
  • RK3568驱动指南|驱动基础进阶篇-进阶1 编译进内核的驱动系统是如何运行的?

    瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网

    2024年02月01日
    浏览(38)
  • 音视频开发之旅——音频基础概念、交叉编译原理和实践(LAME的交叉编译)(Android)

    本文章已授权微信公众号郭霖(guolin_blog)转载。 本文主要讲解的是 音频基础概念 、 交叉编译原理和实践(LAME的交叉编译) ,是基于 Android平台 ,示例代码如下所示: AndroidAudioDemo 另外, iOS平台 也有相关的文章,如下所示: 音视频开发之旅——音频基础概念、交叉编译

    2024年04月25日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包