技术标签: 【Linux驱动开发】基于QEUM的实操笔记 linux 嵌入式硬件 驱动开发 单片机
工欲善其事必先利其器,搭建一个良好的开发环境是进行开发的基础,可以少出很多bug
在实践过程中发现用虚拟机会出现挺多问题,比如虚拟机网络问题导致不能安装一些库、虚拟机导致电脑蓝屏、虚拟机卡慢等等问题
平台信息:
Ubuntu版本:22.04
gcc版本: 11.4.0
主机linux内核版本: 6.5.0-15-generic
所构建的Linux内核版本:6.6.16
Linux系统安装好了之后安装qemu,在命令行输入:
sudo apt-get install qemu
sudo apt-get install qemu-system
首先编译Linux内核,我们构建Linux内核需要编译后产生的内核镜像zImage和对应的设备树文件
下载后解压,进入cd进入内核文件夹linux-6.6.16
配置内核,输入一下命令:
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make vexpress_defconfig
make menuconfig
弹出的界面不设置,按两次esc退出,
- Uboot和Linux内核移植需要根据你的板卡选择相应的默认配置信息
/boot/configs
,我们选择Vexpress-A9开发板的配置信息。- export命令:用于显示或设置环境变量,但是效果仅限于当前登录的终端,这样我们不用每次make都指定参数了
- vexpress_defconfig:是ARM Versatile Express开发板的内核默认配置文件,文件夹里有很多厂家板子的默认配置文件,放在
arch/arm/configs
接下来,我们编译内核镜像文件和设备树文件,时间有一点久,耐心等待:
make bzImage
make dtbs
编译结果注意zImage的地址和设备树的地址,后续会用到
make bzImage 的结果如下:
0BJCopy arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
make dtbs 的结果如下:
DTC arch/arm/boot/dts/arm/vexpress-v2p-ca5s.dtb
DTC arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb
DTC arch/arm/boot/dts/arm/vexpress-v2p-ca15-tc1.dtb
DTC arch/arm/boot/dts/arm/vexpress-v2p-ca15 a7.dtb
可以看到,Linux内核镜像文件zInage保存在
arch/arm/boot/zImage
,设备树文件:vexpress-v2p-ca9.dtb(在arch/arm/boot/dts/
文件夹下)
在内核文件夹里,运行qemu:
qemu-system-arm -M vexpress-a9 -smp 4 -m 256M -kernel arch/arm/boot/zImage -append "console=ttyAMA0" -dtb arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb -nographic
输出信息出现Booting Linux on physical CPU 0x0
,说明成功进入内核了,我们编译的内核和设备树没问题,但是我们没有构建和指定根文件系统,所以内核会崩溃显示---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
QEMU中,输入ctrl+a再输入x,退出QEMU,准备构建根文件系统
使用BusyBox来构建根文件系统,根文件系统的根目录和子目录中会有很多Linux 运行所必须的文件,比如库、常用的软件和命令、设备文件、配置文件等等,BusyBox 就集成了这些大量的 Linux 命令和工具
make defconfig
make menuconfig
跳出的界面里配置静态编译:Setting->Build static binary,点空格把它选上,然后Esc退出mkdir /home/rootfs
make
make install CONFIG_PREFIX=/home/rootfs
设置CONFIG_PREFIX参数,将编译结果指定存放在根文件系统目录下
创建etc,dev,mnt,sys,tmp,proc,root,lib等目录,安装动态链接库
mkdir etc,dev,mnt,sys,tmp,proc,root
sudo cp -d /usr/arm-linux-gnueabi/lib/*.so* ./lib
创建设备节点
cd dev/
sudo mknod -m 666 console c 5 1
sudo mknod -m 666 null c 1 3
sudo mknod -m 666 dev/tty1 c 4 1
sudo mknod -m 666 dev/tty2 c 4 2
sudo mknod -m 666 dev/tty3 c 4 3
sudo mknod -m 666 dev/tty4 c 4 4
创建并写入三个配置文件/etc/init.d/rcS
,/etc/fstab
,/etc/inittab
,其内容分别为:
- /etc/init.d/rcS: shell 脚本, 规定Linux 内核启动以后启动哪些文件的脚本,该文件一定要给与可执行权限!!!
- /etc/fstab:Linux 开机以后自动配置哪些需要自动挂载的分区
- /etc/inittab:内核初始化的init 程序会读取/etc/inittab这个文件,inittab 由若干条指令组成
三个文件的写法以及环境变量配置参考这篇文章:WSL2下Ubuntu22.04使用Qemu搭建虚拟Vexpress-A9开发板(三)——挂载根文件系统
/etc/init.d/rcS:
#!/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export LD_LIBRARY_PATH=/lib:/usr/lib
/bin/mount -n -t ramfs ramfs /var
/bin/mount -n -t ramfs ramfs /tmp
/bin/mount -n -t sysfs none /sys
/bin/mount -n -t ramfs none /dev
/bin/mkdir /var/tmp
/bin/mkdir /var/modules
/bin/mkdir /var/run
/bin/mkdir /var/log
/bin/mkdir -p /dev/pts
/bin/mkdir -p /dev/shm
/sbin/mdev -s
/bin/mount -a
echo "-----------------------------------"
echo "*****welcome to vexpress board*****"
echo "-----------------------------------"
/etc/fstab:
proc /proc proc defaults 0 0
none /dev/pts devpts mode=0622 0 0
mdev /dev ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
tmpfs /mnt tmpfs defaults 0 0
var /dev tmpfs defaults 0 0
ramfs /dev ramfs defaults 0 0
/etc/inittab:
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
写了shell脚本自动完成本节完善根文件系统的工作,自取,切换到
/home/rootfs
目录下执行:完善根文件系统的shell脚本
在根文件系统目录下执行下列命令,创建根文件系统镜像
cd /home
sudo qemu-img create -f raw linux.img 256M
sudo mkfs -t ext4 ./linux.img
sudo mkdir tmpfs
sudo mount -o loop ./linux.img tmpfs/
sudo cp -r rootfs/* tmpfs/
sudo umount tmpfs
sudo rm -r tmpfs
file linux.img
根文件系统镜像创建成功显示:linux.img: Linux rev 1.0 ext4 filesystem data, UUID=c0f6a2f3-b70e-480f-8726-3c2d66ce9120 (extents) (64bit) (large files) (huge files)
把编译出的内核镜像zImage和设备树文件拷贝到/home
,运行QEMU:
sudo qemu-system-arm \
-M vexpress-a9 \
-m 256M \
-kernel ./zImage \
-dtb ./vexpress-v2p-ca9.dtb \
-nographic \
-append "root=/dev/mmcblk0 rw console=ttyAMA0" \
-sd linux.img
注意:-append选项的参数,我们从sd卡启动,root所指定的位置是
/dev/mmcblk0
就是sd卡设备挂载的目录,rw
表示根文件系统是可以读写的,console 用来设置 linux 终端,表示通过什么设备来和 Linux 交互,设置console = ttyAMA0
,因为 linux启动以后板卡的串口 1 挂载在 linux 下的设备文件就是/dev/ttyAMA0
构建内核成功!可以在QEMU模拟的arm开发板中输入linux指令了
-append
选项设置文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数