赞
踩
1、安装好相关环境(Ubuntu 18.04)
开发板:orangepi-zero2
交叉编译器:aarch64-none-linux-gnu-
2、安装交叉编译工具:
(1)下载并安装交叉编译工具,下载地址如下:Index of /armbian-releases/_toolchain/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
下载好压缩包,将压缩包放到Ubuntu里如下所示:
输入以下命令进行压缩包的解压:
tar -xf gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz
解压完后,会有一个文件夹,输入命令进入文件夹,可看到对应的交叉编译工具:
(2)设置环境变量临时有效
1)输入以下命令,输出环境变量:
echo $PATH
2)pwd,打印当前路径:
3)设置临时环境变量,用到以下命令:
export PATH=$PATH:<路径>
4)我们再次输出环境变量,看看是否已经添加进来:
但是,这个方法只适用于当前终端,一旦当前终端关闭或者在其他终端中则无效。它是一个临时的环境变量。
(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
查看test文件是否是arm架构:
file test
如下:
证明我们交叉编译工具已经安装好,你也可以将test文件拷贝到板子上运行看是否正常。
3、将Linux SDK 的源码准备好,并放在Ubuntu上,如下所示:
4、先将Linux 内核压缩包解压出来
unzip orangepi-build-main.zip
解压后,会多出解压好的文件夹:
1、先进入我们解压好的源码文件夹,如下所示:
2、运行 buid.sh 脚本,输入如下命令:
sudo ./build.sh
它会自动帮我们下载编译工具和源码。
3、运行上述脚本后,弹出下图,我们选择 Kernel package ,然后按回车:
4、紧接着,需要我们选择开发板的型号,这里我的开发板的型号是 OrangePiZero2,选择按回车即可:
5、接着选择型号分支,我的开发板是linux 4.9的,按回车即可:
(1)current 会去编译 linux 5.13
(2)legacy 会去编译 linux 4.9
6、然后会弹出 make menuconfig 配置内核的界面,此时,可以直接修改内核的配置,这里我没有配置,直接退出,退出后就会开始编译内核源码:
(1)如果不需要修改内核的配置选项,在一开始运行 build.sh 脚本时,传入 KERNEL_CONFINGRE=no 就可以临时屏蔽弹出内核的配置界面了。
sudo ./build.sh KERNEL_CONFIIGURE=no
(2)如果你想永久禁用内核配置界面的弹出,也可以设置 orangepi-buid-main/userpatches/config-default.conf 配置文件中的 KERNEL_CONFINGRE=no ,这样就可以永久禁用这个功能了:
(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)最后会显示重复编译上一次选择的内核的编译命令,使用下面的命令无需通过图形界面选择,可以直接开始编译内核源码:
8、编译好后,生成的目录如下:
以上文件释义如下所示:
- 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 包:
我生成的如下所示:
2、将编译好的 deb 上传至 开发板的 /root 目录下:
可以通过SSH连接,使用scp命令上传
scp linux-image-legacy-sun50iw9_2.2.2_arm64.deb root@orangepi:/root
3、查看已经安装了的 deb 文件:
dpkg -l | grep linux-image
4、卸载开发板中的 deb 文件:
apt purge -y linux-image-legacy-sun50iw9
5、安装上传的 deb 文件:
dpkg -i linux-image-legacy-sun50iw9_2.2.2_arm64.deb
6、重启开发板
sudo reboot.
7、再次查看安装的 deb 文件:
可见,已经安装好了最新的 deb 文件。
1、写一个示例代码(放在orangepi-build-main/kernel/orange-pi-4.9-sun50iw9/drivers/char 下):
新建一个 pin4driver.c 文件:
文件写入代码如下:
- #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
如下所示:
3、然后我们需要回到内核的源码目录下,进行模块的编译,即 orangepi-build-main/kernel/orange-pi-4.9-sun50iw9 这个路径下:
(1)方法一:输入以下命令进行编译,这条命令是将所有内容都编译了,需要蛮久的:
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j4
编译好后,可以看到编译生成的 .ko 文件所在的路径:
(2)方法二:输入以下命令,只是编译模块,较快:
make modules ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu-
编译如下所示:
4、将编译好的 pin4driver.ko 模块,拷贝到我们的开发板(可以用scp指令拷贝,也可用U盘拷贝)
这里讲一下用U盘拷贝的方法:
(1)首先先将 pin4driver.ko 模块 拷贝到 共享文件夹中:
cp pin4driver.ko /mnt/hgfs/share/
(2)查看共享文件夹中的文件:
ls /mnt/hgfs/share/
(3)从 windows 上的共享文件夹 将 pin4driver.ko 模块 拷贝到U盘上
(4)将U盘插到板子上, 用 dmesg 命令查看识别到的是哪个设备:
可以看到内核识别到的设备是 sda1。
(5)输入指令挂载U盘,挂载到 /mnt 目录下:
sudo mount /dev/sda1 /mnt/
挂载好后,cd 进入 /mnt 目录,再 ls,即可看到U盘下的文件:
(6)用cp命令将 pin4driver.ko 模块 拷贝出来即可
(7)拷贝完后,需要取消U盘的挂载:
(8)拔出U盘即可
5、在开发板中加载驱动模块:
(1)输入以下命令即可:
sudo insmod pin4driver.ko
(2)我们看一下是否生成了pin4这个设备驱动:
模块名、主设备号与次设备号都与我们的驱动代码对上了:
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);
- }
编译运行:
为什么无法打开呢?这是因为,我们加载的驱动的权限问题,我们需要给它可读可写的权限:
修改权限,再次执行即可:
7、查看驱动层的输出语句:
输入dmesg查看:
这样子,就完成了简单的字符设备驱动开发。
(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 函数,于是,我们就会在内核里看到打印了相关的信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。