目录
一、Buildroot
1.1介绍
文件系统
1.一个完整的操作系统需要包含大量的文件
2.在嵌入式开发中目前应用最广泛的文件系统制作工具就是 buildroot,busybox
3.buildroot 制作文件系统(了解)
二、杂项驱动编程
1.1 驱动编程做的内容
2.2 特点
2.3 设备号
2.4 相关 API
杂项设备注册
杂项设备注销
三、GPIO 子系统
3.1 介绍
3.2 GPIO 号
3.3 相关 API
GPIO 号的申请
GPIO 输出方向的设置
GPIO 电平的设置
GPIO 的释放
四、文件接口
一、Buildroot
1.1介绍
环境搭建过程,是根据板子官方的《用户手册》/《快速入门手册》
环境搭建中不可避免的要遇到问题:
1、给售后打电话 2、百度/看板子官方的论坛 3、凭经验
文件系统
1.一个完整的操作系统需要包含大量的文件
例如:Linux 系统
etc:环境配置文件
lib:库文件
bin:二进制文件 --- 里面是各种各样的可执行程序 --- 系统的部分指令 ls
sbin:管理员用户可以执行的一部分指令 reboot
dev:设备文件 等
这些系统必要的文件中有大量的子文件/目录,而我们是无法完全掌握每个文件的具体内容 ,所以文件系统的制作是需要依靠工具的
每个系统的文件,大体相同,局部不同
不同:系统中集成的库
相同:可以依赖文件系统制作工具完成
2.在嵌入式开发中目前应用最广泛的文件系统制作工具就是 buildroot,busybox
busybox 是比较早的文件系统制作工具
制作的文件系统非常纯粹 --- 基本没有其它的工具库,都需要开发者自己去移植,移植库需要不停的编译和复制
buildroot 给开发者降低了开发难度
buildroot 的文件系统其实也是由 busybox 做的,buildroot 集成了 busybox
buildroot 的优势在于可以直接通过 make menuconfig 图形化配置界面,去勾选系统中想要加入的库文件,在编译过程中会直接将勾选的库加入到文件系统中,不需要移植,不需要适配
buildroot 的缺点:编译时间非常长,并且对硬件要求比较高
buildroot 第一次编译的时间在 8~12 小时
大部分编译对运行内存要求极高 --- 是为了 build(编译)库
内核数越多,相对来说,编译的越快
一部分库他需要去外国网站下载,速度极慢,慢到一定程度,就断开了
dl 文件就是影响编译比较大的因素,其中放的都是下载的各种各样的库
buildroot 是开源的,也可以去下载,将已经下载好的 dl 库放进来,可以大大减少 buildroot 的编译时间
3.buildroot 制作文件系统(了解)
如果制作了后,后续需要重新编译 SDK,自己做的文件系统仅仅可以让系统运行起来,还需要加各种库,需要百度搜索,在制作之前先把 SDK 生成的配置文件给删除
解决 Buildroot 终端没有终端提示符,在板子的终端
vi /etc/profile.d/myprofile.shPS1='[\u@\h]:\w$ 'export PS1保存退出
文件系统复原
gedit device/rockchip/rk3588/BoardConfig-rk3588s-evb1-lp4x-v10-yyt.mk
export RK_CFG_BUILDR00T=rockchip_rk3588s
然后
./build.sh lunch 选5
然后
./build.sh
LVGL 在 buildroot 中选中
嵌入式设备才支持 LVGL 生成的可执行程序
除此之外还需要勾选 SDL 库
这样 buildroot 生成的文件系统中的交叉编译工具才支持编译 LVGL 的程序,这个交叉编译工具的名字带有 build
二、杂项驱动编程
1.1 驱动编程做的内容
Linux 下一切皆文件
每一个硬件设备在系统中用文件体现的:
键盘(/dev/input/event1)和鼠标(/dev/input/event2)
驱动开发就是将硬件设备 --- 描述在系统中
例如:让一个 LED 灯用文件控制 --- 本质依然是 GPIO 操作
上系统之后,无法直接使用 GPIO
在系统中只能通过文件间接控制
将硬件设备变成一个文件
通过操作文件去操作这个设备
通过 open、read、write、close 实现不同的操作
例如:可以通过 open 文件接口去开灯
通过 close 文件接口去关灯
用单片机直接可以控制 GPIO,也可以开关灯
那么我为什么要做驱动:MCU 性能有限 --- 可以做控制,但是做 UI 一类的比较弱
在字符设备驱动开发中有三种开发方法 :杂项 Linux2.6 经典
演示:杂项和 Linux2.6
2.2 特点
1、最简单的驱动开发方法
2、唯一 一个可以主动生成设备文件的驱动开发方法
3、主设备号固定为 10,次设备号 0~255
杂项设备开发方法的缺点:设备文件有限
0~255 还有系统占用的次设备号
设备文件:
字符设备文件开发 --- ✓
块设备文件开发
网络设备文件开发
2.3 设备号
设备号是区分不同设备文件的唯一标识
完整的设备号总共 32 位
高 12 位是主设备号,低 20 位是次设备号
区分不同文件的唯一标识 --- 节点号
节点号的查看 --- ls -i
目前做的是字符设备编程 --- 会向系统注册设备文件
开发方放的学习就像 MCU 的不同编程方式
寄存器:代码及其简洁,代码可读性极差
库函数:好记,代码可读性强,代码篇幅过长
HAL 库:通过点一点就可以完成简单的功能 --- 代码必须写在固定位置
学习的是一个框架 --- 固化的流程
杂项的开发流程
1、搭建驱动开发的框架
2、杂项设备注册
3、杂项核心结构体定义
4、杂项核心结构体填充
5、杂项设备注销
2.4 相关 API
关键字:misc
头文件:#include <linux/miscdevice.h>
杂项设备注册
函数原型
int misc_register(struct miscdevice *misc)
函数参数
struct miscdevice
{//杂项驱动编程的核心结构体int minor; //次级的 --- 次设备号//次设备号会被占用 --- 255 表示随机分配const char *name; //生成的设备文件名//这个名字会出现在/dev/下const struct file_operations *fops; //文件接口核心结构体{使用的头文件是:#include <linux/fs.h>对于当前情况下,只需要填写一个内容struct module *owner; //在内核中固定填写 THIS_MODULE}}
函数返回值
成功返回 0,失败返回负的错误码
杂项设备注销
函数原型
void misc_deregister(struct miscdevice *misc)
函数参数
同上
三、GPIO 子系统
3.1 介绍
GPIO 子系统是 Linux 内核中用于管理通用输入输出(GPIO)引脚的核心框架,提
供标准化的 API 接口以简化硬件操作。它通过抽象硬件细节,允许开发者通过设备树
配置和驱动接口控制引脚方向、电平读写及中断功能,并与 Pinctrl 子系统协同完成引
脚复用与配置。
用于控制 GPIO
四个 LED 灯:核心板有两个,底板有两个,蜂鸣器在底板
两个用户按键:在底板
哪个板子就看哪个板子的原理图(核心板、底板)
LED1 对应的是 --- GPIO0_D0 LED2 对应的是 --- GPIO1_D5
GPIO 子系统使用的主要是 GPIO 号
3.2 GPIO 号
GPIO 号在瑞芯微系列的芯片(RK,RV rockchip)中是可以根据 GPIO 的名字算出来的
GPIO 号的计算方式
GPIOx_yz :x*32+(y-A)*8+z
例如:LED1 的 GPIO0_D0 0*32+(D-A)*8+0 = 3*8 = 24
GPIO1_D5 → 1*32+(D-A)*8+5 = 61
GPIO 的使用过程
GPIO 号的申请
GPIO 输出方向的设置
GPIO 电平的设置
GPIO 的释放
3.3 相关 API
关键字:gpio
头文件:#include <linux/gpio.h>
GPIO 号的申请
函数原型
int gpio_request(unsigned int gpio, const char *label)
函数参数
gpio:要申请 GPIO 的 GPIO 号
label:是一个标签,不要重复,给个字符串就行
函数返回值
成功返回 0,失败返回负数
GPIO 输出方向的设置
函数原型
int gpio_direction_output(unsigned int gpio, int value)
函数参数
gpio:要设置的 GPIO 号
value:初始电平
1 高电平
0 低电平
函数返回值
成功返回 0,失败返回负数
GPIO 电平的设置
函数原型
void gpio_set_value(unsigned int gpio, int value)
函数参数
gpio:要设置的 GPIO 号
value:设置电平值
GPIO 的释放
函数原型
void gpio_free(unsigned gpio)
函数参数
gpio:要释放的 GPIO 号
四、文件接口
用户直接操作的是系统,系统会通过文件接口(open,close 等)和内核的文件接口(重新定义 struct file_operations 结构体中的文件指针),完成控制硬件设备
struct file_operations {int (*open) (struct inode *, struct file *)int (*release) (struct inode *, struct file *)}
struct inode --- 在系统中调用 open 文件接口其实本质上是调用内核的(*open)接口,这个结构体中存放了应用层文件的信息 --- 其中就有设备号 --- 在多节点会用到
struct file --- 在多节点会用到,更多的时候这个结构体会作为形参作为实参传入另外一个函数中
注意 :
在加载函数中,先申请的资源,在卸载函数中,后释放
先申请的资源有可能会让后申请的资源使用,在使用过程中被释放可能会导致内核错误