0X. Linux嵌入式系统(课堂笔记)

目录

一. 开发板桥接

二. 开发板白屏

三. 0324-MPU6050开发

3.1 函数详解

3.2 常用 ioctl 请求码(request)

3.3  头文件详解

四. 获取鼠标信息

4.1 获取鼠标信息

4.2 内核修改并编译

五. QT基础使用

六. 内核打印Hello world

七. 内核GPIO

八. 内核i2c通信,mpu信息获取

8.1 input_button

8.2 kmpu


一. 开发板桥接

 1.连接开发板:sudo minicom -D /dev/ttyUSB0

    密码:emb
    用户:root
    password:root

2.开发板桥接虚拟机:

    用usb桥接,虚拟机有线链接PCI关闭,以太网设置手动,主机192.168.1.99,子网掩码设置
    桥接完成后:ping ip地址(互相)

3.通过联网,拷贝文件到开发板

    虚拟机编译:arm-linux-gnueabihf-gcc -o hello.out hello.c
    拷贝到开发板:scp hello.out root@192.168.1.10:/home/root

二. 开发板白屏

 (1)开发板白屏示例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;int main() {int fd = open("/dev/fb0",O_RDWR,0);ioctl(fd,FBIOGET_FSCREENINFO,&finfo);ioctl(fd,FBIOGET_VSCREENINFO,&vinfo);int screensize = vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;printf("screensize:%d Byte\r\n",screensize);printf("x:%d, y:%d, %d", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);int* fb_buffer=(int*)mmap(NULL,screensize,PROT_READ | PROT_WRITE, MAP_SHARED, fd,0);memset(fb_buffer, 0xff, screensize);munmap(fb_buffer, screensize);close(fd);return 0;
}

(2)开发板按键示例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;int main() {int fd = open("/dev/mem",O_RDWR|O_SYNC);if(fd < 0){perror("Cant Open /dev/mem!\r\n");return -1;}void* a=mmap(NULL, 0x1000,PROT_READ | PROT_WRITE, MAP_SHARED, fd,0xf8000000);if((int)a == -1){perror("mmap fail!\r\n");close(fd);return -1;}int tmp = *(unsigned int*)(a + 0x12c);*((unsigned int*)(a + 0x12c)) = tmp | 0x00400000;munmap(a, 0x1000);a = mmap(NULL, 0x1000,PROT_READ | PROT_WRITE, MAP_SHARED, fd,0xe000a000);if((int)a == -1){perror("mmap fail!\r\n");close(fd);return -1;}tmp = *(unsigned int*)(a + 0x048);printf("GPIO0:%d\r\n", tmp);munmap(a, 0x1000);close(fd);return 0;
}

点灯:960\906

cd /sys/class/gpio/
echo 960 > export                       
cd gpio960                              
ls                              
echo out > direction            
# 灭灯 
echo 1 > value

三. 0324-MPU6050开发

#include<stdio.h>
#include<fcntl.h>
#include<sys/ioctl.h>
#include<unistd.h>
#include<linux/i2c-dev.h>int main()
{int fd;if((fd = open("/dev/i2c-0", O_RDWR)) < 0){perror("open i2c-0 fail!\n");return -1;}unsigned char buf[] = {0};unsigned char wrbuf[] = {0x75};ioctl(fd, I2C_SLAVE, 0x68);write(fd, wrbuf, 1);read(fd, buf, 1);printf("%x\r\n", buf[0]);return 0;
}

返回值:0x68 

获取mpu6050返回值

#include<stdio.h>
#include <linux/i2c.h>  
#include <linux/i2c-dev.h>  
#include <sys/ioctl.h>     
#include <fcntl.h>          
#include <unistd.h>         int main()
{int fd;if((fd = open("/dev/i2c-0", O_RDWR)) < 0){perror("open i2c-0 fail!\n");return -1;}unsigned char buf[] = {0};unsigned char wrbuf[] = {0x6B,0x00};ioctl(fd, I2C_SLAVE, 0x68);struct i2c_rdwr_ioctl_data transmit;struct i2c_msg msgs[2];write(fd, wrbuf, 2);char wbuf[1] = {0x3B};char rbuf[10] = {0};msgs[0].len = 1;msgs[0].buf = wbuf;msgs[0].addr =0x68;msgs[0].flags = I2C_M_STOP;msgs[1].len = 6;msgs[1].buf = rbuf;msgs[1].addr = 0x68;msgs[1].flags = I2C_M_RD | I2C_M_STOP; transmit.msgs=msgs;transmit.nmsgs = 2;ioctl(fd, I2C_RDWR, &transmit);printf("%x %x\r\n", rbuf[0], rbuf[1]);return 0;
}

3.1 函数详解

功能:Unix/Linux 系统中用于 设备 I/O 控制(Input/Output Control)的头文件,允许用户程序与设备驱动进行交互,执行设备特定的操作(如配置、状态查询等)

函数原型:#include <sys/ioctl.h>

int ioctl(int fd, unsigned long request, ... /* void *arg */);
参数说明
参数类型说明
fdint已打开的设备文件的文件描述符(如 /dev/tty/dev/sda 等)。
requestunsigned long设备控制命令(由驱动定义,如 TIOCGWINSZ 获取终端大小)。
...void * 或 int可选参数,通常是指向数据的指针(如结构体)或整数值。

返回值:​​​​​​

成功:返回 0 或驱动定义的非负值(具体取决于 request)。

失败:返回 -1,并设置 errno 表示错误原因(如 EBADF 表示无效的文件描述符)。

主要功能

终端控制(调整窗口大小、获取终端属性)。

网络设备配置(获取/设置网卡参数)。

存储设备管理(如硬盘格式化、读取扇区)。

自定义设备驱动交互(如 LED 控制、传感器数据读取)。

3.2 常用 ioctl 请求码(request

<sys/ioctl.h> 定义了许多标准请求码,例如:

(1) 终端控制(Terminal I/O)

请求码功能
TIOCGWINSZ获取终端窗口大小(struct winsize)。
TIOCSWINSZ设置终端窗口大小。
TCGETS获取终端属性(struct termios)。
TCSETS设置终端属性。

(2) 网络设备控制(Socket I/O)

请求码功能
SIOCGIFADDR获取网络接口 IP 地址(struct ifreq)。
SIOCSIFADDR设置网络接口 IP 地址。
SIOCGIFFLAGS获取接口标志(如 UPRUNNING)。

(3) 存储设备控制(Disk I/O)

请求码功能
HDIO_GETGEO获取磁盘几何信息(struct hd_geometry)。
BLKRRPART重新读取分区表。

3.3 <linux/i2c-dev.h> 头文件详解

1.主要功能

定义 I2C 设备控制相关的 ioctl 命令

设置 I2C 从设备地址(I2C_SLAVE)。

执行 I2C 读写操作(I2C_RDWR)。

控制 I2C 总线(I2C_FUNCSI2C_SLAVE_FORCE 等)。

提供 I2C 数据传输结构体

struct i2c_msg:描述单个 I2C 消息(读/写操作)。

struct i2c_rdwr_ioctl_data:用于批量传输多个消息。

支持标准 I2C 和 SMBus(System Management Bus)协议

适用于传感器、EEPROM、RTC 等 I2C 设备。

2. 关键函数原型与 ioctl 命令

(1) 设置从设备地址

ioctl(fd, I2C_SLAVE, addr);  // 设置默认通信的 I2C 从设备地址
参数说明
fd打开的 I2C 设备文件描述符(如 /dev/i2c-1)。
addr7 位 I2C 从设备地址(0x03~0x77)。
返回值成功返回 0,失败返回 -1(设置 errno)。

(2) 执行 I2C 读写(I2C_RDWR

struct i2c_rdwr_ioctl_data packets;
ioctl(fd, I2C_RDWR, &packets);  // 执行组合读写操作

参数struct i2c_rdwr_ioctl_data 结构体:

struct i2c_rdwr_ioctl_data {struct i2c_msg *msgs;  // 消息数组int nmsgs;             // 消息数量
};

struct i2c_msg 结构体:

struct i2c_msg {__u16 addr;     // 从设备地址__u16 flags;    // 标志(I2C_M_RD 表示读)__u16 len;      // 数据长度__u8 *buf;      // 数据缓冲区
};
标志位

I2C_M_RD:读操作(否则为写操作)。

I2C_M_TEN:使用 10 位地址(默认 7 位)。

返回值成功返回 0,失败返回 -1

(3) 查询适配器功能(I2C_FUNCS

unsigned long funcs;
ioctl(fd, I2C_FUNCS, &funcs);  // 获取 I2C 适配器支持的功能
返回值funcs 是一个位掩码,表示适配器支持的功能(如 I2C_FUNC_I2CI2C_FUNC_SMBUS_READ_BYTE)。

(4) 其他常用 ioctl 命令

命令功能
I2C_SLAVE_FORCE强制设置从设备地址(即使设备忙)。
I2C_TENBIT启用 10 位地址模式(默认 7 位)。
I2C_PEC启用 SMBus 数据包错误检查(PEC)。

四. 获取鼠标信息

4.1 获取鼠标信息

    cd /dev/input/sudo cat mouse0cdcd work/cd 03usrSpaceDriver/gedit input.c
#include <linux/input.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>int main()
{struct input_event event;int fd=open("/dev/input/mouse)",O_RDWR);int nread = read(fd, &event,sizeof(event));printf("type:%d, code:%d, value:%d\r\n", event.type, event.code, event.value);return 0;
}
gcc input.c -o input.out	// 编译
./input.out					// 运行

4.2 内核修改并编译

# 内核修改并编译
# 拷贝开发板的配置文件
scp root@192.168.1.10:/proc/config.gz ./
# 解压配置文件config.gz
gzip -d config.gz
# 将解压后的文件移动到kernel/.config,命名为.config隐藏文件
mv config kernel/.config
# 进入kernel
cd kernel/
ls
# 图形化界面选择
make ARCH=arm menuconfig
# 编译内核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- LOADADDR=0x00008000 uImage
# 若有修改,则要更新

五. QT基础使用

1. 新建并拷贝qt生成的python文件到开发板 

# 新建qt文件
designer 
# 将qt文件转换为py文件
pyuic5 -x pyqt1.ui -o pyqt1.py 
# 传输到开发板上运行
scp pyqt1.py root@192.168.1.10:/home/root 

2. 在运行qt的python脚本之前要先添加环境变量,选择自己需要的环境变量添加

# Qt-embedded需要的环境变量
# • 指定显示设备
export QT_QPA_PLATFORM=linuxfb
# • 指定输入设备(触摸屏)
export QT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/event0
export QWS_MOUSE_PROTO=evdevtouch:/dev/input/event0
# • 指定输入设备(鼠标)
export QT_QPA_GENERIC_PLUGINS=evdevmouse:/dev/input/event0
export QWS_MOUSE_PROTO=evdevmouse:/dev/input/event0

 3. 运行拷贝的pyqt脚本

python pyqt1.py

六. 内核打印Hello world

        1. 编写内核模块

/* mhello.c */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int hello_init(void)
{pr_alert("Hello, world\n");return 0;
}
static void hello_exit(void)
{pr_alert("Goodbye, world\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");
MODULE_DESCRIPTION("A simple Hello World Module");

        2. 编写Makefile  内核模块编译为可加载模块(obj-m为输出文件名,根据c文件不同名称进行修改)

ifneq ($(KERNELRELEASE),)
obj-m := mhello.o
else
KDIR := /home/emb-zynq/kernel/
all:$(MAKE) -C $(KDIR) M=$$PWD
endif

        3. 将生成的.ko文件拷贝到开发板并执行

        (1)更新内核

# kernel/arch/arm/boot$ 将此文件下 uImage 文件 覆盖开发板 /media/card 下的uImage
scp uImage root@192.168.1.10:/media/card 直接覆盖
# 重启开发板 
reboot

        (2)交叉编译并拷贝.ko到开发板并执行

# 交叉编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
# 也可以在当前终端添加临时环境变量,再运行
# export ARCH=arm
# export CROSS_COMPILE=arm-linux-gnueabihf-
# make# scp 将.ko文件传入开发板
scp mhello.ko root@192.168.1.10:/home/root
# 动态加载内核模块
insmod mhello.ko
# 查看加载的内核模块
lsmod
# 卸载内核模块
rmmod mhello.ko

七. 内核GPIO

        内核获取gpio状态

# 交叉编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
# 也可以在当前终端添加临时环境变量,再运行
# export ARCH=arm
# export CROSS_COMPILE=arm-linux-gnueabihf-
# make# scp 将.ko文件传入开发板
scp gpios.ko root@192.168.1.10:/home/root
# 动态加载内核模块
insmod gpios.ko# 注册设备号
mknod /dev/gpios c 245 0
# 查看设备状态
cat /dev/gpios# 卸载内核模块
rmmod gpios.ko

        内核使用led灯

# 交叉编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
# 也可以在当前终端添加临时环境变量,再运行
# export ARCH=arm
# export CROSS_COMPILE=arm-linux-gnueabihf-
# make# scp 将.ko文件传入开发板
scp led-gpios.ko.ko root@192.168.1.10:/home/root
# 动态加载内核模块
insmod led-gpios.ko.ko# 注册设备号
mknod /dev/led0 c 245 0
mknod /dev/led1 c 245 0
mknod /dev/led2 c 245 0
# 点灯
./ledapp /dev/led0
./ledapp /dev/led1
./ledapp /dev/led2# 卸载内核模块
rmmod led-gpios.ko

八. 内核i2c通信,mpu信息获取

8.1 input_button

编译和测试

编译button.c驱动程序和inputtest.c测试程序 修改前面例子中的Makefile,运行make命令编译驱动程序button.c产生button.ko 修改并编译测试应用:arm-linux-gnueabihf-gcc inputtest.c –o inputtest 下载button.ko 和inputtest到目标板。 加载设备驱动:insmod ./button.ko, 查看/dev/input/event*,找到新增的event文件。 用cat命令查看event文件,按动按键观察输出。 执行测试程序./inputtest /dev/input/event1,观察输出

8.2 kmpu

        mount命令:查看设备

练习

        • 编译并加载MPU6050驱动kmpu.c,观察输出结果。

        • 修改并更新设备树文件system.dtb,更新后reboot

        • 设备树文件示例:

scp root@192.168.1.10:/media/card/system.dtb ./
# dtb 改 dts
dtc -I dtb -O dts system.dtb -o system.dts
# 修改system.dts
# dts 改 dtb
dtc -I dts -O dtb system.dts -o system.dtb
#重启开发板
reboot# 编译kmpu.c
make# 将kmpu.c拷贝到开发板
scp kmpu.ko root@192.168.1.10:/home/root/test/0416/kmpu
# insmod加载设备
insmod kmpu.ko

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/904684.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/904684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qml中的TextArea使用QSyntaxHighlighter显示高亮语法

效果图&#xff0c;左侧显示行号&#xff0c;右侧用TextArea显示文本内容&#xff0c;并且语法高亮。 2025年5月8号更新 1、多行文本注释 多行文本注释跟普通的高亮规则代码不太一样&#xff0c;代码需要修改&#xff0c;这里以JavaScript举例。 先制定多行文本注释规则&…

【Python从入门到精通】--‘@‘符号的作用

在Python中&#xff0c;符号主要有三种用途&#xff1a;装饰器&#xff08;Decorator&#xff09;、矩阵乘法运算符&#xff08;Python 3.5&#xff09;以及类型提示中的修饰符&#xff08;如typing&#xff09;。 目录 1.--装饰器&#xff08;Decorator&#xff09; 2.--矩…

VAE和Stable Diffusion的关系

文章目录 ✅ 简单回顾&#xff1a;什么是 VAE&#xff1f;&#x1f504; Stable Diffusion 和 VAE 的关系&#xff1a;&#x1f3af; 编码器&#xff1a;&#x1f4a5; 解码器&#xff1a; &#x1f914; 那 Stable Diffusion 本身是 VAE 吗&#xff1f;&#x1f9e0; 简要对比…

PyTorch_点积运算

点积运算要求第一个矩阵 shape:(n, m)&#xff0c;第二个矩阵 shape: (m, p), 两个矩阵点积运算shape为&#xff1a;(n,p) 运算符 用于进行两个矩阵的点乘运算torch.mm 用于进行两个矩阵点乘运算&#xff0c;要求输入的矩阵为3维 &#xff08;mm 代表 mat, mul&#xff09;to…

02_JVM

1、JVM虚拟机组成及内存分配 三大部分&#xff1a; 类装载子系统JVM虚拟机字节码执行引擎 其中&#xff0c;JVM虚拟机运行时数据区&#xff08;内存模型&#xff09;包含五部分&#xff1a;堆、栈&#xff08;线程&#xff09;、方法区&#xff08;元空间&#xff09;、本地…

基于FPGA控制PCF8591开展ADC采样,以采样烟雾模块输出模拟电压为例(IIC通信)

基于FPGA控制PCF8591开展ADC采样 前言一、芯片手册阅读1.设备地址2.字节地址3.IIC通信协议 二、仿真分析三、代码分析总结视频演示 前言 这段时间做设计总是遇到一些传感器模块输出模拟电压&#xff0c;采集模拟电压进而了解传感器输出的浓度占比&#xff0c;在淘宝上找到了一…

在Python和C/C++之间共享std::vector<std::vector<int>>数据

在Python和C/C之间共享std::vector<std::vector>数据 在Python和C/C之间共享嵌套向量数据(std::vector<std::vector<int>>)可以通过几种方法实现。以下是几种常见的方法&#xff1a; 方法1: 使用Cython Cython是连接Python和C的很好选择&#xff0c;它可以…

Linux NVIDIA 显卡驱动安装指南(适用于 RHEL/CentOS)

&#x1f4cc; 一、禁用 Nouveau 开源驱动 NVIDIA 闭源驱动与开源的 nouveau 驱动冲突&#xff0c;需先禁用&#xff1a; if [ ! -f /etc/modprobe.d/blacklist-nouveau.conf ]; thenecho -e "blacklist nouveau\noptions nouveau modeset0" | sudo tee /etc/modpr…

Python爬虫实战:获取千库网各类素材图片,为设计师提供参考

一、引言 在当今设计领域,丰富的素材积累对设计师而言至关重要。千库网作为一个素材资源丰富的平台,拥有海量的各类素材图片。然而,手动从该网站收集素材不仅耗时,而且效率低下。Python 作为一种功能强大的编程语言,具备丰富的库和工具,可用于开发高效的爬虫程序。通过 …

vue截图-html2canvas

使用html2canvas进行截图操作 在 Vue 中使用 ​​html2canvas​​ 将 HTML 元素&#xff08;如包含贝塞尔曲线的 Canvas/SVG&#xff09;转换为图片 下载html2canvas npm install html2canvas在页面中使用&#xff0c;要截取哪个div的内容&#xff0c;先给这个div加一个ref标…

介绍Unity中的Dictionary

在 Unity&#xff08;C#&#xff09;中&#xff0c;Dictionary 是一个非常常用的数据结构&#xff0c;它提供 键值对&#xff08;Key-Value Pair&#xff09; 的存储方式。类似于 Python 的 dict 或 JavaScript 的对象&#xff08;Object&#xff09;&#xff0c;但它是强类型的…

MySQL 常用函数(详解)

目录 一、数学函数1.1 四舍五入函数1.2 求绝对值函数二、日期时间函数2.1 获取当前日期和时间三、字符串函数3.1 字符串拼接函数3.2 提取子字符串函数四、聚合函数4.1 计算平均值函数4.2 计算最大值函数五、转换函数5.1 类型转换函数六、总结MySQL 提供了丰富的内置函数,涵盖了…

SOFA编译-Ubuntu20.04-SOFA22.12

一、事前说明 单纯的编译sofa是很简单的&#xff0c;但是想要同时编译SofaPython3则比较难了&#xff0c;我编译了v22.12分支&#xff0c;其他版本sofa的编译也可以参考此篇教程&#xff0c;需注意的是&#xff1a; 1、确定SOFA需要的Python版本&#xff0c;sofa22.12需要的是…

静态BFD配置

AR2配置 int g0/0/0 ip add 10.10.10.2 quit bfd quit bfd 1 bind peer-ip 10.10.10.1 source-ip 10.10.10.2 auto commit AR1配置 int g0/0/0 ip add 10.10.10.1 int g0/0/1 ip add 10.10.11.1 quit bfd quit bfd 1 bind peer-ip 10.0.12.2 source-ip 10.0.12.1 auto co…

关键字where

C# 中的 where 关键字主要用在泛型约束&#xff08;Generic Constraints&#xff09;中&#xff0c;目的是对泛型类型参数限制其必须满足的条件&#xff0c;从而保证类型参数具备特定的能力或特性&#xff0c;增强类型安全和代码可读性。 约束写法说明适用场景举例C#版本要求w…

Arm核的Ubuntu系统上安装Wireshark

Arm核的Ubuntu系统上安装Wireshark 一、安装wireshark 安装命令&#xff1a; sudo apt-get install wireshark-qt 如下图所示&#xff1a; 安装过程弹出如下界面&#xff1a; 鼠标选择Yes&#xff0c;点回车键确认 安装完成。 二、打开wireshark 输入命令行打开wireshark …

编专利或委托他人编专利属于学术不端行为吗?

原文链接&#xff1a;编专利或委托他人编专利属于学术不端行为吗&#xff1f; 自己编专利或委托他人编专利属于学术不端吗&#xff1f; 5月4日&#xff0c;一篇题为《针对性护理干预在子宫肌瘤围手术期的情绪和生活质量临床应用效果》的论文&#xff0c;受到网友的广泛议论。…

Music AI Sandbox:打开你的创作新世界

AI 和音乐人的碰撞 其实&#xff0c;Google 早在 2016 年就启动了一个叫 Magenta 的项目&#xff0c;目标是探索 AI 在音乐和艺术创作上的可能性。一路走来&#xff0c;他们和各种音乐人合作&#xff0c;终于在 2023 年整出了这个 Music AI Sandbox&#xff0c;并且通过 YouTub…

Java游戏服务器开发流水账(2)开发中Maven的管理

Maven 是一款流行的 Java 项目管理工具&#xff0c;它基于项目对象模型&#xff08;Project Object Model&#xff0c;POM&#xff09;的概念来管理项目的构建、依赖和文档等。游戏服务器开发中也会使用. 项目构建 生命周期管理&#xff1a;Maven 定义了一套清晰的项目构建生…

枚举 · 例8扩展-校门外的树:hard

登录—专业IT笔试面试备考平台_牛客网 代码区&#xff1a; #include<algorithm> #include<iostream> #include<vector>using namespace std; struct TREE{int left,right; }; bool compare(const TREE&a,const TREE& b ){if(a.left!b.left){return…