当前位置: 首页 > article >正文

#驱动开发

内核模块  字符设备驱动  中断、内核定时器

裸机开发和驱动开发的区别?

裸机开发

驱动开发(基于内核)

相同点

都能够控制硬件(本质:操作寄存器)

不同点

用C语言给对应的地址里面写值

按照一定的框架格式往地址里面写值

单独编译单独执行

依赖内核编译、执行

同时只能执行一份代码

同时执行多份代码

只需要一个main函数

依赖内核的框架来操作硬件

STM32启动流程详解(超全,startup_stm32xx.s分析)_stm32启动过程详解-CSDN博客文章浏览阅读3.8k次,点赞32次,收藏84次。启动模式只决定程序烧录的位置,加载完程序之后会有一个重映射(映射到0x00000000地址位置);真正产生复位信号的时候,CPU还是从开始位置执行。值得注意的是STM32上电复位以后,代码区都是从0x00000000开始的,三种启动模式只是将各自存储空间的地址映射到0x00000000中。_stm32启动过程详解https://blog.csdn.net/m0_56694518/article/details/135032170?spm=1001.2014.3001.5501

驱动里面操作LED灯的寄存器 

驱动模块是依赖内核框架执行代码

ARM裸机直接操作的是物理内存,直接拿到寄存器地址写值。

驱动是基于内核,操作的是虚拟内存,使用之前先映射实际物理内存。

Linux系统组成

硬件层:led 鼠标 键盘 lcd 触摸屏 摄像头 u盘 emmc 猫 路由器 dm9000

0-3G的用户空间是每个进程单独拥有0-3G的空间

系统调用(软中断swi)   应用层通过系统调用与底层交互,swi将应用层切换到内核层。

驱动代码就在内核空间(在3-4G内核空间, 共用空间)

注:1G的物理内存映射成0~4G的虚拟内存,每个进程都可以访问内核,0~3G是每个进程单独拥有的,3G~4G是所有的共有的。代码运行在物理内存上,向虚拟内存上面写值,其实是写在物理内存上面的

宏内核和微内核(了解)

宏内核:集中管理的架构,负责多种系统资源的调度和管理;

将进程、文件、网络、内存、设备等功能集成到一个内核中,具备直接操作硬件的能力。

优点:执行效率高,操作系统资源可以直接在内核中实现,减少了进程间通信带来的性能损失,提高了系统的执行速度。

缺点:内核的代码量非常大,不易拓展,且单个模块的崩溃可能会影响整个系统的运行。

eg:ubuntu、Android

微内核:更侧重于模块化和移植性,通过传递请求的方式实现不同模块之间的交互

将最基本的操作系统功能放到内核中,其他服务和程序在微内核之上构建,并在用户态下运行。(设计分界线不同)

优点:系统灵活性和可扩展性好,系统可靠性高

缺点:代码运行效率低->通过API接口让整个系统运行起来

eg:Window 、鸿蒙

驱动移植

步骤:

需要有对应的驱动代码(.c)

修改对应目录的Makefile - drivers-》char)-》obj-$(CONFIG_LED) +=led.o

修改对应目录里的Kconfig(tristate " ...... " )

make menuconfig-》配置自己的驱动为M(模块的)

make modules(在最顶层目录)

把编译产生的.ko结尾的驱动文件,放到nfs(/opt/6818/rootfs/rootfs)目录下使用

安装insmod led.ko

卸载rmmod led

静态编译:生成的执行文件不依赖于外部库文件,可以直接运行,且程序运行效率较高。

动态编译:可执行文件和库分开写,生成的可执行程序需要依赖于外部的库文件。

内部编译:在内核源码树中编译

外部编译:在内核源码树外编译

驱动模块

驱动的框架

入口(安装):资源申请

出口(卸载):资源释放

许可证:GPL(开源的---》Linux开源-----》GPL许可证)

Linux内核许可规则

Linux内核许可规则 — The Linux Kernel documentation

驱动程序编写

#include <linux/init.h>
#include <linux/module.h>

//申请资源
//static - 限定作用域,延长生命周期
//存储类型 数据类型 指定存放内存区域 函数名(形参)
static int __init hello_init(void)
{
    return 0;
}

//释放资源
static void __exit hello_exit(void)
{
}

module_init(hello_init);    //入口:申请资源   本质-回调一个自己写的函数
module_exit(hello_exit);    //出口:释放资源
MODULE_LICENSE("GPL");      //许可证:公共许可协议(开源协议)

ctags的安装和使用

方法1

1.ctags

ctags工具是将指定目录以及子目录添加索引文件,可以实现快速搜索文件内容(宏定义、取别名以及结构体)

2.ctags创建索引文件

安装ctags:

sudo apt-get install ctags

在/usr/include目录下执行命令:

sudo ctags -R

执行完毕之后,会生成一个tags的索引文件

3、默认只能在/usr/include使用,所以需要设置为全局

打开家目录下的.vimrc文件,然后添加一句话:

set tags+=/usr/include/tags

5.3 ctags工具的使用

追代码:

vim -t 结构体名/宏定义名/取别名

vi -t 结构体名/宏定义名/取别名

如果要查看所有定义的位置:在底行模式下输入

tselect 结构体名/宏定义名/取别名

继续追指定的内容:

将光标放在这个内容的任意位置,然后点击快捷键ctrl ]

返回上一次的文件:

ctrl t

例如:追一下sockaddr_in结构体,查看结构体成员

继续查看这个结构体中成员的类型

查看完毕后返回到最开始的结构体

方法2

把ctags_set文件夹拷贝到Ubuntu里

cd ctags_set

sudo chmod 774 ctags_set.sh

sudo ./ctags_set.sh

验证:在~目录下

vi -t sockaddr_in

生成tags 文件 :在相应目录下 ctags -R

在代码中追变量: ctrl + ]

返回代码中 : ctrl + t

mv tags /home/hq/kernel/kernel-3.4.39

可以不执行:

==================================

在内核源码目录下 执行

make tags

========================

cd ~

sudo vim .vimrc

在.vimrc 最后添加

set set tags+=内核源码绝对路径/tags

例如set tags+=/home/hq/kernel/kernel-3.4.39/tags

驱动Makefile编写

KERNELDIR = /home/hq/kernel/kernel-3.4.39	#开发板路径
#KERNELDIR = /lib/modules/$(shell uname -r)/build	#PC机

PWD = $(shell pwd)    #驱动文件的路径

all:
	make -C $(KERNELDIR) M=$(PWD) modules
	#基于内核框架将驱动代码编译生成驱动模块
	#需要在内核的顶层目录下执行 make modules
	#-C:指定到哪个路径下执行这个命令
	#M:赋值,要将哪个路径下的驱动文件编译生成驱动模块
    #注:进入内核目录下执行make modules这条命令,如果不指定 M=$(PWD) 会把内核目录下的.c文件编译生成.ko

.PHONY:clean
clean:
	make -C $(KERNELDIR) M=$(PWD) clean
	
obj-m += hello.o

Source Insight工具

软件安装

激活码:SI3US-719473-71478

使用(配置工程)

配置信息:*.c;*.h;*.S;*.lds;*defconfig;*Makefile;*.mak;*.dts;*.dtsi

软件使用

ctrl+/ 可以搜索变量及函数

按住ctrl左击鼠标可以追变量或者函数

打印函数

在Linux中可以使用

grep "printk" * -nR

搜索函数,搜到以后,在里面任意找到一个,看函数原形

	printk (打印级别 "内容");
	printk(KERN_ERR "Fail%d",a);
	printk(KERN_ERR "%s:%s:%d\n",__FILE__,__func__,__LINE__);//(驱动在哪一个文件,哪一个函数,哪一行)

内核打印级别

vi -t KERN_ERR(查看内核打印级别)//也可直接在SI中按住ctrl左击跳转进行查看

0 ------------------ 7

最高的 最低的

终端打印级别

#define console_loglevel (console_printk[0])    //终端的级别
#define default_message_loglevel (console_printk[1])//消息的默认级别
#define minimum_console_loglevel (console_printk[2])//终端的最大级别
#define default_console_loglevel (console_printk[3])//终端的最小级别

查看虚拟机终端级别

cat /proc/sys/kernel/printk

只有当消息的级别大于终端级别,消息才会被显示

打印函数代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>

static int __init hello_init(void)
{
    printk("hello world\n");
    printk(KERN_CRIT "%s %s %d\n",__FILE__,__func__,__LINE__);
    printk(KERN_INFO "%s %s %d\n",__FILE__,__func__,__LINE__);
    return 0;
}

static void __exit hello_exit(void)
{
    printk("bai bai le nin lei\n");
    printk(KERN_CRIT "%s %s %d\n",__FILE__,__func__,__LINE__);
    printk(KERN_INFO "%s %s %d\n",__FILE__,__func__,__LINE__);
}

module_init(hello_init);    //入口:申请资源
module_exit(hello_exit);    //出口:释放资源
MODULE_LICENSE("GPL");      //许可证:公共许可协议(开源协议)

但对与咱们的这个Ubuntu被开发者修改过,所有消息不会主动回显

命令使用

sudo insmod hello.ko 安装驱动模块

sudo rmmod hello 卸载驱动模块

lsmod 查看模块

dmesg 查看消息

sudo dmesg -C 直接清空消息不回显

sudo dmesg -c 回显后清空

修改系统的默认级别

su root

echo 4 3 1 7 > /proc/sys/kernel/printk

虚拟机的默认情况:

修改开发板的默认级别

查看开发板的默认级别

cat /proc/sys/kernel/printk

如果想修改开发板对应的打印级别

vi etc/init.d/rcS

echo 5 5 1 7 > /proc/sys/kernel/printk

//当系统重新启动,rcS中的命令会全部重新执行一遍

rootfs/etc/init.d/rcS里面添加上以后再起板子,板子的级别就为如下:

etc/init.d/rcS:一些启动虚拟机需要启动的东西都可以放在这个文件中,启动系统时同时启动。

echo 5 5 1 7 > /proc/sys/kernel/printk

放到板子跟文件系统对应这个文件中。

安装驱动和卸载驱动时,消息会打印。


http://www.kler.cn/a/293189.html

相关文章:

  • LabVIEW开发相机与显微镜自动对焦功能
  • 物理设备命名规则(Linux网络服务器 15)
  • Linux相关习题-gcc-gdb-冯诺依曼
  • 【go从零单排】Random Numbers、Number Parsing
  • 【Qt】Macbook M1下载安装
  • GitLab 如何跨版本升级?
  • 什么是RPC
  • 使用SVD(奇异值分解)进行降维的奇妙之旅
  • STM32外设SPI(串行通信),W25Q64(8Mb)
  • 软件测试面试(平安保险)
  • 容器化技术在非结构化数据中台的部署研究
  • 父类是给java项目SpringCloud微服务 中SpringBoot解决继承父类后 maven标红
  • java下一页怎么实现的
  • 消息中间件都有哪些
  • MongoDB-副本集-Replica Sets
  • 设计模式 | 原型模式
  • 数学建模强化宝典(14)Fisher 最优分割法
  • 电脑硬盘数据丢失了怎么恢复?简单实用的硬盘数据找回的方法
  • JS生成二维码QRCode代码
  • EI会议推荐-第二届大数据与数据挖掘国际会议(BDDM 2024)
  • 地平线SuperDrive首秀:千人研发投入,出场即「比肩第一梯队」
  • C++ STL-List容器概念及应用方法详解
  • 如何优化Oracle数据库的SQL性能?
  • MySQL5.7.36之高可用架构部署-MHA-VIP漂移
  • 【无标题】一起学习LeetCode热题100道(67/100)
  • Pikachu靶场之RCE漏洞详解