ARM-Linux 完全入门
1.准备部分
1.1 虚拟机安装
- 准备VMware软件、ubuntu系统镜像
- 安装过程
- VMware安装
破解(自己百度破解码,多试几个网址,会有能用的) - Ubuntu安装
- 配置联网
桥接
虚拟机Ubuntu系统必须能连接到外网,不然不能更新软件安装包
配置虚拟机网络
第一步
1.重启虚拟机网络编辑器(还原配置)
第二步
2.重启虚拟机网络适配器(移除再添加)
第三步
3.重启虚拟机网络服务器
sudo service network-manager stop
sudo rm /var/lib/NetworkManager/NetworkManager.state
sudo service network-manager start
1.2 板子获取
2.Linux基础命令
2.1.操作方式
2.1.1界面
2.1.2命令行
- 打开终端 Ctrl+Alt+t
- 一个窗口打开第二个 Ctrl+Shift+t
- 新窗口打开第二个 Ctrl+Alt+t
- 字体放大 Ctrl+(+)
- 字体缩小 Ctrl+(-)
2.2 文件和目录操作
ls -l -a lsusb lsmod
cd ~ …
pwd
mkdir
touch
rm
mv
cat
2.3 管理员
2.3.1 管理员权限
sudo
2.3.1 管理员用户
创建root用户 sudo passwd root
切换用户 su + 用户名
2.4 安装应用
2.4.1 apt
- sudo apt install (package name)
- sudo apt update 使用 apt 更新包数据库
- sudo apt upgrade 使用 apt 升级已安装的软件包
2.4.2 换源
2.4.2.1 界面方式
- 点Ubuntu左下角菜单,选紫色的SoftWare&Updates 软件
- 点Download from 选择other
- 再选择C开头的china,然后点mirrors.aliyun.com,最后点Choose Server
- 进行密码验证 最后点close
- 然后点reload
- sudo apt update
- sudo apt upgrade
2.4.2.1 命令方式
一切皆文件
2.5 文本处理
2.5.1 vim
2.5.1.1安装方式
sudo apt install vim
2.5.1.2使用方法
2.5.1.2.1命令模式
默认,此模式下,可使用方向键(上、下、左、右键)或 k、j、h、i 移动光标的位置,还可以对文件内容进行复制、粘贴、替换、删除等操作
2.5.1.2.2输入模式
使 Vim 进行输入模式的方式是在命令模式状态下输入 i、I、a、A、o、O 等插入命令,当编辑文件完成后按 Esc 键即可返回命令模式
快捷键
小写i/a :在当前光标所在位置插入随后输入的文本,光标后的文本相应向右移动
小写x:删除光标所在位置的字符(命令模式下)
小写dd:删除光标所在行(命令模式下)
2.5.1.2.3编辑模式
编辑模式用于对文件中的指定内容执行保存、查找或替换等操作。在命令模式状态下按“:”键,此时 Vim 窗口的左下方出现一个“:”符号,这是就可以输入相关指令进行操作了
相关命令
- Esc +:wq
- Esc +:wq!
- Esc+:q
- Esc+:!
- 显示行 Esc + :set nu
- 搜索文本 :Esc+:/文本
查看上一个: N 查看下一个 :n
2.5.2 gedit
2.5.3 nano
2.6 缩和解压缩
tar
打包示例 tar -cvf test.tar*.c
解压示例 tar -xvf test.tar
2.7 查找
2.7.1 find
查找文件
sudo find /home/ling -name "*.c'
2.7.2 grep
查找文件中的字符
grep "d" a.c
dmesg
dmesg | grep usb
2.8 基础编辑测试
- gcc
sudo apt install gcc
编译 gcc - file
- chmod
文件所有者(Owner)
用户组(Group)
其它用户(Other Users)
sudo chmod 777 test.c
2.9 misc
- ifconfig
- echo
- ping
- ps axu 查看系统中所有运行进程
- top
- kill
- uname -a
- shutdown 60秒延时关闭系统
shutdown now 立即关闭 - reboot
- ctrl+c 终止进程 SIGINT
- ctrl+z 挂起程序
-jobs 查看当前终端的后台任务
fg 将挂起的任务恢复到前台运行
bg 将挂起的任务放到后台继续运行
kill %1 终止编号为1的后台任务
3.环境搭建
3.1 注意
串口: windows要选择到底连接哪里(windows/linux)
Windows关机之前,虚拟机要关闭
3.2 ssh(方便切换)
3.2.1Ubuntu
sudo apt-get install openssh-server
ifconfig
3.2.2Windows
MobaXterm
3.3 传文件
3.3.1 FTP
3.3.1.1Ubuntu
- sudo apt-get install vsftpd
- sudo vim /etc/vsftpd.conf
找到 #write_enable=YES
把#删掉,然后保存
- sudo /etc/init.d/vsftpd restart
3.3.1.2 Windows
安装 FileZilla
3.3.2.3 注意:
如果连接不上,关闭Linux(sudo ufw disable)和Windows防火墙
3.3.2 samba
3.3.2.1Ubuntu
1.sudo apt-get upgrade
2.sudo apt-get update
3.sudo apt-get dist-upgrade
4.sudo apt-get install samba samba-common
5.samba -V #如果出现下面版本号说明已经安装了samba服务器
6.sudo mkdir /home/share
7.sudo chmod 777 /home/share
8.sudo smbpasswd -a ling#需要确认输入两个相同的密码确认
9.sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak #备份 smb.conf 配置文件
10.sudo vim /etc/samba/smb.conf #在配置文件smb.conf的最后添加下面的内容(里面的信息要改成自己的)
11.sudo service smbd restart(或者/etc/init.d/samba restart) #重启samba服务器
[global]; 创建工作组 设定 Samba Server 所要加入的工作组或者域 workgroup = WORKGROUP ; 为了防止出现中文目录乱码的情况。其中根据你的local,UTF-8 有可能需要改成 cp936; display charset = UTF-8unix charset = UTF-8dos charset = cp936 ; 是否允许guest用户访问guest ok = no; 注:如果 #security 存在就直接修改,不存在就创建; security = user ; 安全模式 我们设置用户安全级别security = user ; 说明:用来定义用户名映射,比如可以将root换成administrator、admin等。不过要事先在smbusers文件中定义好。; 比如:root = administrator admin,这样就可以用administrator或admin这两个用户来代替root登陆Samba Server,更贴近windows用户的习惯。username map = /etc/Samba/smbusers ; 共享名,该共享标签,该名字为在电脑上看到的共享名 注意网络映射的路径是这标签名字不是共享路径的名字
[share]; 该共享描述comment = Shared Folder with username and password ; 共享文件夹路径path = /home/ling/; 表示是否允许匿名访问该共享目录public = no; 配置的Samba访问账号 指明可以访问的用户valid users = ling; 表示是否可以在 Window Explorer中显示该目录browsable = no; 指明新建立的文件的属性create mask = 777 ; 指明新建立的目录的属性directory mask = 777; force group 和force user 规定创建的文件或文件夹的拥有者和组拥有者是谁 ; 一般这两个值来空,则表示拥有者和组拥有者为创建文件者。 如设定值,如force group=ling; Force user=yhq,则不管是谁创建的文件和文件夹,拥有者都为yhq和yhq组。; force user强制把建立文件的属主是谁。如果我有一个目录,让guest可以写,那么guest就可以删除,; 如果我用force user=yhq强制建立文件的属主是yhq,同时限制create mask = 0755,; 这样guest就不能删除了。force user = lingforce group = ling; available用来指定该共享资源是否可用available = yes ; 共享路径读权限 设置共享是否可浏览,如果no则表示隐藏,需要通过"//ip/共享目录"进行访问browseable = yes; 共享路径写权限writable = yes
3.3.2.2 Windows
-
打开文件管理器
点击此电脑 -
选择映射网络驱动器
-
添加
\虚拟机IP地址\share
eg:\192.168.31.169\share -
输入用户名&密码
3.3.2.3 注意
如果连接不上,关闭Linux(sudo ufw disable)和Windows防火墙
3.3.3 scp
3.3.4 共享文件夹
4.系统编译
4.1 交叉编译器安装
- cd /usr/local
sudo mkdir arm
cd arm - 把交叉编译工具链拷贝到/usr/local/arm文件夹(FTP)
sudo chmod 777 arm - 解压 sudo tar -vxf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
- 环境变量修改
- 查看环境变量
env
printenv
echo $PATH - 修改环境变量
sudo vim /etc/profile
最后面新一行添加
export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin
- 重启sudo reboot
- 测试 arm-linux-gnueabihf-gcc -v
- 编译
4.2 Uboot
4.2.1综述
是一套裸机程序,可以理解为板子上电的初始化
Uboot的源代码,启动流程,都值得分析,面试会问
4.2.2 编译
- 安装编译必用工具
sudo apt-get install lzop libncurses5-dev u-boot-tools
- 拷贝迅为Uboot源代码
cd ~
mkdir Linux
mkdir uboot
cd uboot
拷贝FTP
- 解压
tar -xvf uboot-imx-rel_imx_4.1.15_2.1.0_ga_20200512.tar.gz
cd uboot-imx-rel_imx_4.1.15_2.1.0_ga/
- 编译
./create.sh
sudo apt install make
Makefile
- .config
- make menuconfig
- Kconfig
- 生成文件
- uboot.imx
- uboot.bin
4.2.3流程
4.2.3.1汇编部分
- 关
- 中断
- 看门狗
- cache
- mmu
- …
- 进入SVC模式
- 基本硬件初始化
- 时钟
- 串口
- flash
- 闪存
- 初始化堆栈
- 自搬移
- 重定位
- 内存运行块
4.2.3.1C语言部分
- 初始化大部分硬件
- 网卡
- 屏幕
- usb
- …
- 把内核搬到内存
4.2.4Uboot源码简要分析
4.2.4.1汇编部分
- 跳转到reset
arch/arm/lib/vectors.S
- arch/arm/cpu/armv7/start.S
-
reset
-
cpu_init_cp15
-
cpu_init_crit
-
arch/arm/cpu/armv7/lowlevel_init.S
-
arch/arm/lib/crt0.S
4.2.4.1C语言部分
-
common/board_f.c
board_init_f
-
common/board_r.c
board_init_r
run_main_loop
-
common/main.c
4.2.5 create.sh
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
make distclean
make mx6ul_topeet_emmc_defconfig #.config
make #Makefile
怎么修改.config? make menuconfig
menuconfig界面怎么生成的? Kconfig
4.3 内核
4.3.1 编译过程
- 拷贝迅为kernel源代码
cd ~
cd Linux
mkdir kernel
cd kernel
拷贝 FTP
- 解压
tar -xvf linux-imx-rel_imx_4.1.15_2.1.0_ga_20200903.tar.gz
cd linux-imx-rel_imx_4.1.15_2.1.0_ga
- 编译
./create.sh - 编译后自动生成的文件
- arch/arm/boot
image 非压缩文件
zimage
uimage - arch/arm/boot/dts 设备树
4.3.2 内核源码
- 各个文件都是什么意思
- 源码查看软件 Source Insight 4.0
- 把解压完的内核源码从虚拟机拷贝到Windows
- 新建Source Insight工程
4.3.3 编译脚本
- #!/bin/bash
bash脚本 - make imx_v7_defconfig
- arch\arm\configs
- .config
- make uImage LOADADDR=0x10008000 -j16
- make modules
- 驱动编译的两种方式
- 将驱动编译进内核:obj-y:yes内建
- 将驱动编译进ko文件:obj-m:module模块
- make *.dtb
4.1 设备树
4.1.1功能
包含芯片&板子 外设信息
系统驱动会匹配设备树,匹配成功后加载驱动
驱动代码怎么读取设备树信息?
4.1.2 路径
arch/arm/boot/dts
4.1.3dts
- dtsi soc级
- dts 板级
- topeet_emmc_hdmi.dts
imx6ull-14x14-evk-emmc.dts
imx6ull-14x14-evk.dts
imx6ull.dtsi
4.1.4 dtc(device-tree-compiler 编译器)
- 编译
- 反编译
dtc -I dtb -O dts -o test001.dts topeet_emmc_hdmi.dtb
4.1.4dtb :Blob
4.2 根文件系统proc
根文件系统制作rcs
5.烧录调试
5.1调试模式V1
5.1.1原理
Uboot从板子emmc启动
内核、设备树、根文件系统从服务端(远程)
- tftp:远程下载内核、网络、设备树
- nfs:挂载网络根文件系统network file system
5.1.2 网络搭建
5.1.2.1硬件环境要求
- 板子网口2通过网线直接连接电脑
- 电脑没有网口 可以买一个网卡转usb
- 电脑有网口,但是用来连接网络了(不是WIFI上网)
也可以买一个网口转USB
5.1.2.2 tftp搭建
虚拟机Linux作为服务端
- cd ~
- mkdir tftpfile
- sudo chmod 777 tftpfile
- sudo apt-get install tftp-hpa tftpd-hpa
- sudo vim /etc/default/tftpd-hpa
修改为如下内容,具体路径根据自己实际情况
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/wfeng/tftpfile"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-l-c-s"
- sudo service tftpd-hpa restart
5.1.2.3 nfs搭建
1.下载
sudo apt-get install nfs-kernel-server rpcbind
2.创建文件夹
cd ~
mkdir nfs
- 修改文件
sudo vim /etc/exports
最后面添加
/home/ling/nfs *(rw,sync,no_root_squash)
具体添加内容 路径 根据自己的实际情况
wq保存退出
5. 重启nfs服务:
sudo /etc/init.d/nfs-kernel-server restart
5.1.2.4双网卡模式设置
5.1.2.4.1 Windows端
将与板子网线连接的电脑网口的网卡设置成静态IP
网线分别插在电脑网口和开发板网口上,开发板上电
-
找到网卡
-
双击点开设置IP地址
-
可以按照如图设置,设置完记得点确定
5.1.2.4.2 VMware虚拟机设置
-
虚拟机点编辑,然后点虚拟网络编辑器
-
点更改设置
-
点添加网络(我添加的是VMnet1,名字不重要)
-
把主机模式改为桥接模式
-
选择那会改为静态IP的网卡
5.1.2.4.3 Ubuntu设置
-
虚拟机名字处点右键,然后点设置
-
点添加
-
选择网络适配器
-
此时会出现一个新的网络适配器,选中,改为自定义,然后选择那会的虚拟网卡,我的是VMnet1
-
打开虚拟机终端,输入ifconfig,会看到两个网卡,如果没有就重启一下Ubuntu(和图片网卡名字不一致无所谓,第二个网卡没有IP地址)
-
打开设置
-
选择网络,找到第二个没有IP的网卡,点开开关,然后点设置(齿轮)
-
如果两个网卡的紫色开关不能同时打开,需要按照下图给两个网卡添加不同的Profile,具体添加方式见下一步
-
两个紫色开关可以同时打开的话,就忽略下图
-
选IPV4,再选manual,再添加IP信息
-
输入ifconfig
如图显示两张网卡
- 一个是DHCP动态获取,用于上网
- 一个是静态IP,用于与板子通信
ping
5.1.2.5板子uboot网络设置
- 板子连接串口,打开MobaXterm串口,115200
- 板子上电,在截图中数字归零之前按键盘任意按键,进入uboot设置
- 输入 printenv 可以查看uboot当前环境变量
- 修改网络相关环境变量
- 服务器IP,linux的IP
setenv serverip 192.168.31.200
- 网关
setenv gatewayip 192.168.31.1
- 开发板uboot的IP地址
setenv ipaddr 192.168.2.120
- 子网掩码
setenv netmask 255.255.255.0
- 设置网卡地址
setenv ethaddr 42:03:07:3B:15:5F
- 保存环境变量
saveenv
这一步一定要做,要保存,保存到了emmc中
6. 重启
reset
- 测试
互相ping
- 重启板子,重新进入uboot
- 插上网线,打开虚拟机
- ping 虚拟机和windows的IP,如图所示能ping通即可
显示 alive就是ping通了,,活着,,,
- 注意:用虚拟机和windows ping uboot 是不通的
也不是ping不通,是uboot代码里面没有ping回复机制,或者说没有相关代码 - 如果想恢复uboot默认环境变量
env default -a
saveenv
5.1.3 修改uboot引导方式
5.1.3.1 把kernel、设备树、根文件系统放在对应的文件夹
- tftffile 放内核和设备树
- zImage:linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/boot/zlmage
- topeet_emmc_hdmi.dtb:/arch/arm/boot/dts/topeet_emmc_hdmi.dtb
- nfs 放根文件系统
- filezila传输 :网盘文件rootfs.tar.bz2
- samba传输 :网盘文件rootfs.tar.bz2
解压 :tar -xvf rootfs.tar.bz2
5.1.3.2 进入uboot设置环境变量界面
- uboot前3秒内按任意键,进入uboot
- 修改bootcmd
setenv bootcmd 'tftp 80800000 zImage; tftp 83800000 topeet_emmc_hdmi.dtb; bootz 80800000 - 83800000'
下载内核 下载设备树 加载内核和设备树
3. 修改bootargs
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.31.200:/home/ling/nfs ip=192.168.31.120:192.168.31.200:192.168.31.1:255.255.255.0::eth0:off'
!!!上面的 /home/ling/nfs 不要复制啊!!!!!!,改成你自己的nfs路径哦
可以pwd看看自己的路径名
4, 保存到emmc
saveenv
- 重启
reset
5.1.3.3 出现nfs挂载失败问题(nfs版本问题)
解决方法
- Ubuntu打开文件
sudo vim /etc/default/nfs-kernel-server
- 末尾添加
RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog"
前面不要有#
3. 保存
wq!
- 重启nfs
sudo /etc/init.d/nfs-kernel-server restart
5.1.3.4 挂载成功后
- 用户名 root
- 密码 topeet
5.2烧写到emmc
5.2.1烧写软件的使用
5.2.1.1烧写要准备的
把要烧写的固件放在这个路径里,这个是必须的
下面这个路径是Windows的烧写工具路径,别搞错了
mfgtools_for_6ULL\Profiles\Linux\OS Firmware\files\linux
5.2.1.1固件包括
- Uboot文件
Uboot源码编译生成 uboot.imx - 内核文件
内核源码编译生成 zImage
路径arch/arm/boot - 设备树
内核源码编译生成 路径arch/arm/boot/dts
- topeet_emmc_4_3.dtb
- topeet_emmc_5_0.dtb
- topeet_emmc_7_0.dtb
- topeet_emmc_9_7.dtb
- topeet_emmc_10_1.dtb
- topeet_emmc_1024x600.dtb
- topeet_emmc_hdmi.dtb
- 根文件系统
5.2.2进入USB烧录模式
5.2.2.1把imx6ul板子拨码开关拨到USB烧录模式
5.2.2.2数据线连接到板子上标有OTG的USB口
另一端直接连接电脑USB口
5.2.2.3打开烧录软件mfgtools_for_6ULL
注意事项
- mfgtools_for_6ULL\Profiles\Linux\OS Firmware\files\linux里面的固件必须全
- 用右键管理员权限打开MfgTool2.exe
- 尽量关掉虚拟机
- 如果打不开,或者报错,去任务管理器关闭残余进程
5.2.2.4开发板上电
5.2.2.5看到烧录软件显示 符合 HID 标准的供应商定义设备后
点击start 开始烧录
5.2.2.6看到显示右图,代表烧录完成
5.2.2.7关闭软件先点Stop,再点Exit
5.2.3进入emmc启动模式
- 烧录完成后,开发板断电
- 拨码开关拨到 EMMC启动方式
- 数据线插到板子上标有 UART的USB口上
- 打开MobaXterm,选择对应串口,波特率115200
- 开发板上电
- 系统启动
用户名:root
密码:topeet
6.应用入门
6.1oled&mpu6050使用
- 硬件购买
- 0.96OLED屏幕
- 2.00mm转2.54mm母对母杜邦线
- 硬件接法
- 应用编译
arm-linux-gnueabihf-gcc app.c -o app -lm
- 驱动编译
内核模块
ko文件
- 单独编译
- 单独加载
insmod
rmmod
lsmod
- 放在网络文件系统里就可以
设备树的修改
iic地址
- 七位
- 八位
Z:\Linux\kernel\linux-imx-rel_imx_4.1.15_2.1.0_ga\arch\arm\boot\dts\imx6ull-14x14-evk.dts
mpu6050@68 {compatible = "mpu6050,INV_MPU6050";//interrupt-parent = <&gpio5>;//interrupts = <0 0>;reg = <0x68>;status = "okay";//position = <1>;};oled@3c {compatible = "i2c_oled";reg = <0x3c>;status = "okay";};
6.2应用源码分析
文件描述符
dmesg查看内核打印的相关信息
dmesg | grep 6050
6.3一切皆文件
6.3.1. 虚拟文件系统
虚拟文件系统提供了一种统一的接口,使得用户空间程序可以通过文件系统的方式来访问各种设备和资源
- 文件描述符
- open、close、read、write
6.3.2 简单文件读写测试
/*************************************************************************> File Name: test.c> Author: csgec> Mail: 12345678@qq.com > Created Time: 2025年04月10日 星期四 14时51分38秒************************************************************************/#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include<stdio.h>
int main(){int fd;char buff[]="iamlpy777\n";fd=open("./a.txt",O_RDWR|O_CREAT);if(fd<0){printf("can not open file");return fd;}write(fd,buff,sizeof(buff));memset(buff,'\0',sizeof(buff));lseek(fd,0,SEEK_SET);read(fd,buff,sizeof(buff));printf("buff:%s\n",buff);close(fd);return 0;
}
6.4自启动
6.4.1自启动修改文件
- /etc/init.d/rcS
- /etc/rc.local
- systemd
编写服务配置步骤
新建sh
创建服务
编辑服务
sudo gedit /etc/systemd/system/my_script.service
6.4.2绝对路径
相对路径
6.4.3后台执行
&
6.4.4异步通知
ctrl + c
kill -9 pid
-1SIGHUP 挂起信号 通常用于重新加载配置
-2SIGINT 中断信号(Ctrl+C) 终止前台进程
-9SIGKILL强制终止 立即终止,不可拦截
-15 SIGTERM默认终止信号(kill 的默认行为) 允许进程清理资源后退出
-19 SIGSTOP暂停进程(Ctrl+Z) 进程进入暂停状态,可恢复
7.驱动入门
7.1什么是驱动
7.1.1物理驱动
电机驱动
7.1.2软件驱动
框架
7.1.2.1应用层
7.1.2.2内核层
- 系统调用
- open
- read
- write
- ioctrl
- close
- 虚拟文件系统
- 驱动代码
- 字符设备驱动
- 网络设备驱动
- 块设备驱动
- 设备接口
7.1.2.3硬件层
各种硬件设备
7.2驱动的分类
7.2.1字符设备驱动
按字节流顺序访问
- 串口
- 鼠标键盘
- 摄像头
7.2.2网络设备驱动
- 基于TCP/IP协议
- 有线网卡(百兆、千兆、万兆)
- 无线网卡
- socket
7.2.3块设备驱动
按块随机访问
- 硬盘
- 存储卡
多个自己一块
7.3学驱动学的是什么
代码框架
内核模块三要素
- 入口
module_init:insmod - 出口
module_exit:rmmod - 许可证
MODULE_LICENSE(“GPL”);
开源协议
7.4MPU6050驱动流程
7.4.1 module_init(mpu6050_driver_init);
7.4.2 mpu6050_driver_init
7.4.3 i2c_add_driver(&mpu6050_driver);
i2c_register_driver(THIS_MODULE, driver)
7.4.4 mpu6050_driver
- .probe = mpu6050_probe
- .remove = mpu6050_remove
- .id_table = gtp_device_id
- .driver
- .name = “mpu6050”
- .owner = THIS_MODULE
- .of_match_table = mpu6050_of_match_table
{.compatible = “mpu6050,INV_MPU6050”},
7.4.5 mpu6050_probe
7.4.5.1分配设备号 alloc_chrdev_region(&mpu6050_devno, 0, DEV_CNT, DEV_NAME);
- 设备号
- 主设备号
- 次设备号
- 查看主次设备号
cd /dev/
ls -l
- 动态创建
- 静态创建
- /proc
- 内核数据的映射
- 系统信息查询接口:cat /proc/cpuinfo
-验证你注册的主设备号是否已经生效 cat /proc/devices - 查看中断号是否被注册 :cat /proc/interrupts
- 系统信息查询接口:cat /proc/meminfo
- /sys
7.4.5.2 初始化字符设备结构体cdev_init(&mpu6050_chr_dev, &mpu6050_chr_dev_fops);
7.4.5.2.1. mpu6050_chr_dev_fops
- .open = mpu6050_open 函数作用:打开设备时调用。
mpu6050_init # 进行MPU6050初始化
内部会调用:
i2c_write_mpu6050(mpu6050_client, PWR_MGMT_1, 0X00)
i2c_transfer(mpu6050_client->adapter, &send_msg, 1);
即:通过 I2C 向 MPU6050 写控制寄存器,通常是唤醒 MPU6050(PWR_MGMT_1 = 0x00)
- .read = mpu6050_read
函数作用:用户调用 read() 读取数据时执行。
流程如下
i2c_read_mpu6050(); // 发起 I2C 读取动作
i2c_transfer(mpu6050_client->adapter, mpu6050_msg, 2); // I2C 收发
copy_to_user(buf, mpu6050_result, cnt); // 将读取到的数据复制到用户空间
- mpu6050_release
释放设备,一般在 close() 时调用。
printk("\n mpu6050_release \n");
7.4.5.2.2绑定设备和fops结构体
fops:file_operations 的缩写,是 Linux 内核中字符设备驱动的一个核心结构体,用于定义用户空间调用设备文件时,内核该如何响应。
fops 是一个“函数指针表”,决定了 open()、read()、write() 等操作对应调用驱动中的哪个函数
7.4.5.3 添加设备cdev_add(&mpu6050_chr_dev, mpu6050_devno, DEV_CNT);
7.4.5.4创建设备类 class_create(THIS_MODULE, DEV_NAME);
7.4.5.5 创建设备节点device_create(class_mpu6050, NULL, mpu6050_devno, NULL, DEV_NAME)
7.4.6 module_exit(mpu6050_driver_exit)
i2c_del_driver(&mpu6050_driver)
7.5IOLED驱动流程
7.5.1模块载入入口module_init(oled_init)
7.5.2oled_init函数中的核心操作
i2c_add_driver(&oled_driver);
将 oled_driver 注册到 I2C 总线,系统会根据设备树或板级信息自动调用 .probe = oled_probe。
7.5.3 oled_driver结构体定义
.name = "oled",
.owner = THIS_MODULE,
.probe = oled_probe,
.remove = oled_remove,
.id_table = oled_id,
.of_match_table = oled_of_match_table,
这部分表明该驱动支持的设备匹配方式,包括设备树或设备 ID。
7.5.4oled_probe 函数中是驱动的核心逻辑:
字符设备注册流程
alloc_chrdev_region(&devid, 0, 1, "oled"); // 1. 分配设备号
cdev_init(&i2c_cdev, &oled_fops); // 2. 初始化字符设备,并绑定 fops
cdev_add(&i2c_cdev, devid, 1); // 3. 添加到内核
class_create(THIS_MODULE, "oled_class"); // 4. 创建类
device_create(...); // 5. 创建设备节点
oled_fops 是 file_operations 函数指针表:
struct file_operations oled_fops = {.open = oled_open,.write = oled_write,.release = oled_release,.unlocked_ioctl = oled_ioctl,
};
各个函数含义:
函数 | 作用 |
---|---|
oled_open | 初始化硬件,调用 oled_hw_init() ,内部通过 oled_write_cmd() 进行 I2C 配置 ,oled_clear() :oled_write_cmd/oled_write_data;oled_pos(0,0) :oled_write_cmd |
oled_write | 向设备写入数据,使用 copy_from_user() 获取用户数据,调用 OLED_ShowString() 显示字符串(内部调用 OLED_ShowChar() → oled_write_data() → i2c_transfer() ) |
oled_ioctl | 控制命令,调用 switch-case 来控制显示等功能 |
oled_release | 关闭设备,释放资源(或者打印日志) |
7.6模块卸载:
module_exit(oled_exit)
在卸载函数中调用:
i2c_del_driver(&oled_driver); // 卸载驱动
8.存储器分类
8.1寄存器
8.2RAM
断电之后,数据消失
- DRAM
- 电脑的内存条
- 靠电容存储信息
- 特点:容量大、成本低、需不断刷新(动态)
- SRAM
- CPU的多级缓存,cache
- 靠门电路来存储
- 特点:速度快、功耗低、但价格贵、容量小,不需要刷新
8.3ROM
断电之后,数据长久保存,主要用于固化程序,如 BIOS、启动程序等。
-
RAM
最早期,不能写 只能读 -
PROM
可编程只读存储器(Programmable ROM)
只能写入一次数据 -
EPROM
可编程可擦除只读存储器(Erasable Programmable Read Only Memory)
紫外线擦除
需整块擦除、再重新编程 -
EEPROM
带电可擦可编程只读存储器(EEPROM)
支持电擦除、反复写入,但速率较慢
-
NorFlash
一次可以读取一个字,每个bit都可以被寻址
优点:可直接执行代码(XIP),读速度快
缺点:写入速度慢、成本高 -
NandFlash
优点:容量大、价格便宜,广泛用于数据存储
应用:SSD、U盘、SD卡、eMMC
eMMC:= NandFlash + 控制器 + 标准封装接口(用于嵌入式系统)
分类 | 子类 | 特点或用途 |
---|---|---|
RAM | DRAM | 内存条,动态刷新,便宜 |
SRAM | CPU缓存,不刷新,贵但快 | |
ROM | PROM | 只能编程一次 |
EPROM | 紫外线擦除 | |
EEPROM | 电擦除,重复写入,广泛用于闪存 | |
NorFlash | XIP,读取快 | |
NandFlash | 写入快、便宜、容量大(SSD、U盘等) | |
eMMC | 嵌入式存储解决方案(手机、MCU等) |
相关文章:
ARM-Linux 完全入门
1.准备部分 1.1 虚拟机安装 准备VMware软件、ubuntu系统镜像安装过程 VMware安装 破解(自己百度破解码,多试几个网址,会有能用的)Ubuntu安装 配置联网 桥接 虚拟机Ubuntu系统必须能连接到外网,不然不能更新软件安装…...
前端二进制数据指南:从 ArrayBuffer 到高级流处理
前端开发中,二进制数据是处理文件、图像、音视频、网络通信等场景的基础。以下是核心概念和用途的通俗解释: 前端二进制数据介绍 1. 什么是前端二进制数据? 指计算机原始的 0 和 1 格式的数据(比如一张图片的底层代码ÿ…...
深入理解构造函数,析构函数
目录 1.引言 2.构造函数 1.概念 2.特性 3.析构函数 1.概念 2.特性 1.引言 如果一个类中什么都没有,叫作空类. class A {}; 那么我们这个类中真的是什么都没有吗?其实不是,如果我们类当中上面都不写.编译器会生成6个默认的成员函数。 默认成员函数:用户没有显…...
数值分析知识重构
数值分析知识重构 一 Question 请构造一下数值分析中的误差概念以及每一个具体数值方法的误差是如何估计的? 二 Question 已知 n 1 n1 n1个数据点 ( x i , y i ) , i 0 , 1 , ⋯ , n (x_i,y_i),i0,1,\cdots,n (xi,yi),i0,1,⋯,n,请使用多种方法建立数据之间…...
全端同步!ZKmall开源商城如何用B2B2C模板让消费者跨设备购物体验无缝衔接?
在数字化浪潮席卷下,消费者的购物行为不再局限于单一设备。早晨用手机小程序浏览商品,中午在 PC 端对比参数,晚上通过平板下单,跨设备购物已成常态。然而,设备间数据不同步、操作体验割裂等问题,严重影响购…...
Redis Sentinel如何实现高可用?
Redis Sentinel 通过以下核心机制实现高可用: 1. 监控(Monitoring) Sentinel 集群会持续监控主节点(Master)和从节点(Slave)的状态: 定期发送 PING 命令检测节点是否存活…...
环形缓冲区 ring buffer 概述
环形缓冲区 ring buffer 概述 1. 简介 环形缓冲区(ring buffer),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流。也称作环形缓冲区(circular buffer),环形队列&…...
Spring源码之解决循环依赖 三级缓存
目录 三级缓存核心原理 循环依赖的解决过程 1. Bean A创建过程中提前曝光工厂 2. Bean B创建时发现依赖A,从缓存获取 3. Bean A继续完成初始化 三级缓存的作用总结 二级缓存为何不够解决缓存依赖? 三级缓存如何解决? 为什么不直接在…...
山东大学计算机图形学期末复习9——CG12上
CG12上 几何管线末端:顶点已组装成基本图元(Primitives,如点、线、三角形)。 主要任务: 裁剪:视锥体是一个三维空间区域(由近裁剪面、远裁剪面和侧面组成),超出该区域的图…...
关于软件测试开发的一些有趣的知识
文章目录 一、什么是测试?二、为什么要软件测试软件测试三、测试的岗位有哪些四 、软件测试和开发的区别五、走测试岗位为什么还要学开发。4、优秀的测试人员具备的素质我为什么走测试岗位 一、什么是测试? 其实这个问题说简单也不简单,说难…...
在Solana上使用 Scaled UI Amount 扩展
本指南提供 Solana Web3.js (Legacy v 1.x) 和 Solana Kit (v 2.x) 版本。选择适当的选项卡以查看你首选库的代码片段和说明: Solana Web3.js (Legacy)Solana Kit 概述 Solana Token-2022 程序 引入了强大的扩展,增强了代币功能,使其超越了…...
线性表之数组与栈详解
线性表之数组与栈详解 前言一、数组(Array)1.1 数组的基本概念1.2 数组的实现与操作1.3 数组的应用场景1.4 数组的优缺点 二、栈(Stack)2.1 栈的基本概念2.2 栈的实现方式2.3 栈的应用场景 2.4 栈的优缺点 三、数组与栈的对比总结…...
车载以太网驱动智能化:域控架构设计与开发实践
title: 车载以太网驱动专用车智能化:域控架构设计与开发实践 date: 2023-12-01 categories: 新能源汽车 tags: [车载以太网, 电子电气架构, 域控架构, 专用车智能化, SOME/IP, AUTOSAR] 引言:专用车智能化转型的挑战与机遇 专用车作为城市建设与工业运输…...
【Redis】redis用作缓存和分布式锁
文章目录 1. 缓存1.1 Redis作为缓存1.2 缓存更新、淘汰策略1.3 缓存预热、缓存穿透、缓存雪崩和缓存击穿1.3.1 缓存预热(preheating)1.3.2 缓存穿透(penetration)1.3.3 缓存雪崩(avalanche)1.3.4 缓存击穿&…...
深度学习中独热编码(One-Hot Encoding)
文章目录 独热编码独热编码的作用独热编码的优点独热编码的缺点场景选择独热编码(PyTorch实现)替代方案 实际使用分析:对对象类型使用独热编码为什么使用独热编码是合适的?📌 场景说明:📌 为什么…...
如何根据竞价数据判断竞价强度,是否抢筹等
竞价强度判断方法 价格变化幅度 观察开盘价与前一交易日收盘价的差距 :如果一只股票在开盘集合竞价阶段价格大幅高于前一交易日收盘价,说明市场对该股票的预期较为积极,可能有资金在主动抬高价格,这是一种较强的竞价强度表现。例如…...
Codex与LangChain结合的智能代理架构:重塑软件开发的未来
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言:当代码生成遇见智能决策 想象以下场景: 凌晨三点:你需要紧急修复一个遗留系统的内存泄漏漏洞,但代码注释缺失且逻辑复杂; 产品经理需求变更:要求在24小时内将现有…...
2025年PMP 学习十八 第11章 项目风险管理 (11.5~11.7)
2025年PMP 学习十八 第11章 项目风险管理 (11.5~11.7) 第11章 项目风险管理 序号过程过程组1规划风险管理规划2识别风险规划3实施定性风险分析规划4实施定量风险分析规划5规划风险应对执行6实施风险应对执行7监控风险监控 文章目录 2025年PMP 学习十八…...
2025年PMP 学习十七 第11章 项目风险管理 (11.1~11.4)
2025年PMP 学习十七 第11章 项目风险管理 (11.1~11.4) 第11章 项目风险管理 序号过程过程组1规划风险管理规划2识别风险规划3实施定性风险分析规划4实施定量风险分析规划5规划风险应对执行6实施风险应对执行7监控风险监控 文章目录 2025年PMP 学习十七…...
impala
Impala,它是 Cloudera 开发的开源 实时 SQL 查询引擎,专为 Hadoop 设计。与 Presto 类似,Impala 用于交互式分析,但架构和设计理念有所不同。以下是 Impala 的核心特点和工作原理: 一、Impala 核心架构 1. 组件组成 …...
湖北理元理律师事务所:债务优化中的双维支持实践解析
在债务压力与生活质量失衡的社会议题下,法律服务机构的功能边界正在从单一的法律咨询向复合型支持延伸。湖北理元理律师事务所通过“法律心理”双维服务模式,探索债务优化与生活保障的平衡路径,其方法论或为行业提供实践参考。 法律框架&…...
Redis设计与实现——Redis命令参考与高级特性
Redis命令参考 数据类型相关命令 SET:设置键值,支持过期时间、不存在/存在条件。GET:获取键值,若键不存在返回 nil。INCR/DECR:将键的整数值增1/减1,键不存在时初始化为0。MSET/MGET:批量设置…...
TCP/UDP协议原理和区别 笔记
从简单到难吧 区别就是TCP一般用于安全稳定的需求,UDP一般用于不那么需要完全数据的需求,比如说直播,视频等。 再然后就是TPC性能慢于UDP。 再然后我们看TCP的原理(三次握手,数据传输,四次挥手࿰…...
JavaScript基础-对象的相关概念
在JavaScript中,对象是核心的数据结构之一,几乎所有的高级功能都围绕着对象展开。理解对象的基本概念、创建方法以及操作方式对于掌握JavaScript至关重要。本文将详细介绍JavaScript中对象的相关概念,包括对象的定义、属性的操作、原型链和面…...
如何通过交流沟通实现闭环思考模式不断实现自身强效赋能-250517
感谢一直以来和我交流沟通的朋友们。 闭环思考 文字部分(25-05-04)这一天是青年节,在这一天与青年朋友交流这个是事先规划好的: “可以猜一猜,博士会被撤销吗?导师会被处理吗?千万不要回复&…...
震荡指标工具
一、引言 - 可视化数字烛台工具是对传统蜡烛图的补充,旨在帮助交易者更有效地进入和退出交易,提高交易利润。 - 通过分析蜡烛图,结合烛台震荡指标,提出了一个辅助视觉工具来辅助交易决策。 二、烛台指标与交易策略 -图表通过平均开…...
【自然语言处理与大模型】大模型(LLM)基础知识④
(1)微调主要用来干什么? 微调目前最主要用在定制模型的自我认知和改变模型对话风格。模型能力的适配与强化只是辅助。 定制模型的自我认知:通过微调可以调整模型对自我身份、角色功能的重新认知,使其回答更加符合自定义…...
返回码的方案对比和思考
前言 一般我们定义 Restful 接口返回码,常见的就是 const 定义 code , StatusToText() 来实现定义 msg, 在封装1 ~ 2个返回方法(success、error)就可以实现,只是突然想到这样设计是违反开闭原则的…...
Flink 的任务槽和槽共享
在 Apache Flink 中,任务槽(Task Slot) 和 槽共享组(Slot Sharing Group) 是资源管理和任务调度的关键机制。它们决定了 Flink 如何在集群中分配资源并执行任务。 一、任务槽(Task Slot) 1. 定…...
实验七 基于Python的数字图像水印算法
一、实验目的 掌握图像水印的应用; 掌握我国版权保护的发展现状; 掌握常见的数字图像水印算法。 二、实验内容 学习内容补充: 数字水印的鲁棒性评价主要采用含水印图像提取出的水印与原始水印的相似程度,使用归一化相关(NC,Nor…...
C语言:在 Win 10 上,gcc 如何编译 gtk 应用程序
在 Windows 10 上使用 g(或 gcc)编译基于 GTK 的 C 语言程序是完全可行的,且相比 Tcc 更为推荐,因为 g(GNU 编译器套件)对 GTK 的支持更加完善,配置也更简单。以下是详细步骤和注意事项…...
Vue.js---watch 的实现原理
4.7 watch 的实现原理 watch本质上就是使用了effect以及options.scheduler 定义watch函数: // watch函数:传入参数source以及回调函数function watch(source , cb) {effect(() > source.foo,{scheduler(){// 回调函数cb()}})}watch接收两个参数分别是source和c…...
Linux_ELF文件
目录 前言: 一、ELF文件的类型 二、ELF文件的组成格式 1. ELF头部(ELF Header) 2. 节头表(Section Header Table) 3. 程序头表(Program Header Table) 4. 节(Sections)与段(Segments) 三、ELF文件从形成到加载轮廓 1、ELF可执行文件形成过程 2、 可执行文…...
磁盘I/O子系统
一、数据写入磁盘流程 当执行向磁盘写入数据操作的时候,会发生如下的一系列基本操作。假设文件数据存在于磁盘扇区上,并且已经被读入到页缓存中。 进程使用write()系统调用写入文件。内核更新映射到文件的page cache。内核线程pdflush负责把页缓存刷入…...
【2025 技术指南】如何创建和配置国际版 Apple ID
想要体验更丰富的应用生态、使用国际版专属服务,或访问更多开发者工具?一个国际版 Apple ID 能帮你实现这些需求。本教程将详细介绍如何注册国际版 Apple ID 并正确配置支付信息,全程操作简单,适合开发者和技术爱好者参考。 一、准…...
C++(20): 文件输入输出库 —— <fstream>
目录 一、 的核心功能 二、核心类及功能 三、核心操作示例 1. 文本文件写入(ofstream) 2. 文本文件读取(ifstream) 3. 二进制文件操作(fstream) 四、文件打开模式 五、文件指针操作 六、错误处理技巧…...
05、基础入门-SpringBoot-HelloWorld
05、基础入门-SpringBoot-HelloWorld ## 一、Spring Boot 简介 **Spring Boot** 是一个用于简化 **Spring** 应用初始搭建和开发的框架,旨在让开发者快速启动项目并减少配置文件。 ### 主要特点 - **简化配置**:采用“约定优于配置”的原则,减…...
深入理解指针(6)
目录 1 sizeof和strlen的对⽐ 1.1 sizeof 编辑1.2strlen 1.3 sizeof 和 strlen的对⽐ 2 数组和指针笔试题解析 2.1 ⼀维数组 编辑 2.2 字符数组 3 指针运算笔试题解析 3.1 题⽬1: 编辑3.2 题目2 3.3 题目3 3.4 题目4 3.5 题目5 3.6 题目6 3.7…...
力扣HOT100之二叉树:108. 将有序数组转换为二叉搜索树
这道题之前做过,思路又给忘了,这道题用递归做是最简单的。 由于得到的数组是有序的,我们只需要取出中间位置的元素medium作为根节点,然后medium左边的剩余元素组成根节点的左子树,medium右边的剩余元素组成根节点的右子…...
手撕I2C和SPI协议实现
手撕I2C和SPI协议实现 目录 I2C协议原理I2C位操作实现I2C驱动代码编写SPI协议原理SPI位操作实现SPI驱动代码编写 I2C协议原理 I2C(Inter-Integrated Circuit)是一种串行通信总线,使用两根线:SCL(时钟线)…...
452. Minimum Number of Arrows to Burst Balloons
题目描述 这道题用leetcode官方的解答反而搞复杂了。本题其实就是求重叠区间的交集。先按照区间左端点从小到大排序。然后拿出第一个区间作为【当前区间交集】的初始值。遍历后面的区间看那个区间和【当前交集】是否有重叠。如果有重叠则将【当前交集】和【当前区间】求交集并更…...
React 中,闭包陷阱
文章目录 前言1. 经典闭包陷阱示例过期状态问题 2. 解决方案2.1 正确声明依赖数组2.2 使用 useRef 捕获最新值**2.3 使用函数式更新(针对状态更新)****2.4 使用 useCallback 冻结闭包** **3. 异步操作中的闭包陷阱****事件监听示例** **4. 自定义 Hooks …...
代码复现5——VLMaps
项目地址 1 Setup # 拉取VLMaps仓库,成功运行后会在主目录生成文件夹vlmapsgit clone https://github.com/vlmaps/vlmaps.git#通过 conda 创建虚拟环境conda create -n vlmaps python=3.8 -yconda activate vlmaps #激活环境cd vlmaps # 切换到项目文件下bash install.ba…...
qt6 c++操作qtableview和yaml
保存qtableview数据到yaml文件从yaml文件读取数据到qtableview qtableview在UI界面拖放。 代码是问chat百度的深度探索。 - name: a1address: db1.dbw10type: int - name: a2address: db1.dbx1.0type: bool写到yaml,写前检查 bool plot1::isRowValid(const QStan…...
使用UniApi调用百度地图API的需要注意的地方
目录 前言 一、百度开放平台 1、功能简介 2、地点搜索服务 3、按行政区划检索API 二、Uniapi集成百度API 1、API集成流程 2、访问接口的定义 3、业务调用集成 三、可能遇到的问题 1、指定输出格式无效 2、返回数据的总数 四、总结 前言 在之前的系列博客中…...
(9)python开发经验
文章目录 1 os.path.join()拼接路径2 条件变量3 添加临时环境变量 更多精彩内容👉内容导航 👈👉Qt开发 👈👉python开发 👈 1 os.path.join()拼接路径 os.path.join() 是 Python 中处理文件路径拼接的核心函…...
windows 10 做服务器 其他电脑无法访问,怎么回事?
一般我们会先打开win10自己的防火墙策略,但是容易忽略 电脑之间 路由器上的防火墙,此时也需要查看一下,可以尝试先关闭路由器防火墙,如果可以了,再 设置路由器上的防火墙规则。 将路由器的上网设置 改成 路由模式 &a…...
mysql中limit深度分页详细剖析【爽文】
目录 一 mysql中limit深度分页 1.1 背景描述 1.2 mysql深度分页很慢原因 1.2.1 mysql的sql执行流程 1.2.2 mysql的深度分页很慢原因 1.3 解决办法 1.3.1 覆盖索引 1.3.2 子查询 1.3.3 标签查询 1.3.4 分区表 一 mysql中limit深度分页 1.1 背景描述 Limit深度分页造…...
【C++ Qt】布局管理器
每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 🤔绪论: 在Qt开发中,界面布局的合理设计是提升用户体验的关键。早期,开发者常采用绝对定位的方式摆放控件,即通…...
Windows系统永久暂停更新操作步骤
目录 Windows系统永久暂停更新操作步骤 打开运行窗口进入注册表编辑器 导航路径图示 新建并配置DWORD值 新建值操作图示数值设置图示 在系统设置中应用暂停 暂停选项图示 注意事项 打开运行窗口 按下键盘上的 Win键 R 组合键,调出“运行”对话框。 进入组策略编…...