自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(29)
  • 收藏
  • 关注

原创 STM32 HAL 串口理论和实例

因为最近老板突发奇想,想要做一个轻量级的AI工具,其他保密,我负责整理采集到的数据并上传到服务器。趁此大好机会,赶紧复习一下串口的知识。一些和实际开发不相关的基础知识我就直接跳过了。

2023-09-28 15:12:20 490

原创 供应商系统工具剖析

每个命令的名称、说明、回调函数、获取参数的函数、普通参数做成了一个表。a_argc 是 main 函数的参数个数,a_argv 是 main 函数的所有参数组成的字符串。可以看到是通过 std 标准库来实现的,而且为了减少内存和提高翻问速度,队列里存放的是任务指针。其实我们关心的并不是这个工具的结构,而是这个工具的实现方法,是否有通用的软件工具开发方法?下面简单讲一下这个工具的业务处理,对比两个命令的执行流程来了解一下。软件框架上就是这样,简单的框架,复杂的任务。GetCommandByName 原型。

2023-09-20 17:02:48 149

原创 SPI驱动理论与实例分析2

/将一字节十进制数字转换成二进制 debug用,一般用于查看寄存器每个位的数值//将一字节十进制数字转换成二进制 debug用,一般用于查看寄存器每个位的数值 # define PRINTF_BINARY_PATTERN_INT8 "%c %c %c %c %c %c %c %c" # define PRINTF_BYTE_TO_BINARY_INT8(i) \(((i) & 0x80ll)?

2023-09-18 18:03:25 216

原创 PWM驱动理论与分析

瑞芯微 PWM 控制器驱动源码:/kernel/drivers/pwm/pwm-rockchip.c目前主流的 pwm 设备驱动都是集成到 sysfs 文件系统中,通过 cat 和 echo 操作来控制,我接到的任务也是这样。所以编写 pwm 设备驱动的核心就是完成 sysfs 操作集,通过 sysfs 来操作脉冲宽度。PWM的原理是通过调整周期性波形的高电平时间宽度,从而改变有效信号的占空比,实现对设备的供电控制。

2023-09-13 17:28:49 463

原创 自组织网络设计和开发

功能正常组网都是需要人工在各个节点上输入 SSID、密码、信道完成组网的;如果是远距离基站组网,那么用的设备数量就会比较少,但是距离遥远,每个站点都需要人工控制;如果是短距离组网,就意味着节点数量多,那么人工操作就会繁琐。如果可以将设备安置好位置后,一键上电,设备会自动连接,那么就可以避免繁琐重复的人工操作。前置模块wpa_supplicant 是开源项目,是 wifi 驱动的标配工具,用于管理 wifi 的所有功能。

2023-09-09 14:05:24 42

原创 无线网络隔离设计和开发

该软件用于将不同型号的无线通信设备隔离开,由于目前的无线 WIFI 都是通过 SSID 和 KEY 来连接的。虽然有黑名单系统,但是黑名单系统从底层看是禁止了特定 MAC 地址的设备连接。这样就有一个问题,不可能每次生产一批设备,都要去改变之前卖给客户的设备的黑名单吧???所以需要在连接时进行快速认证,认证结果将保存在进程中,掉电后会重新认证。这是考虑到我们的设备用于远距离基站互联,一般不会掉电,并且约定了后续会不断提供升级版本,并且特殊的机制可以预防一切客户的奇葩操作。

2023-09-06 16:47:20 80

原创 SPI驱动理论与实例分析

实例部分分为几个部分:1、正点原子 imx6ull 陀螺仪模块驱动,非常经典,基本满足所有 SPI 驱动开发;2、瑞芯微官方 SPI 设备驱动例程;由于文章长度,以下两个实战例子放在另一篇文章。3、高通 DACx0501 (ADC)模块驱动;4、高通 IDT8V97003 (无线发射接收器)模块驱动。SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。

2023-09-06 11:58:08 792

原创 LCD驱动理论与实例分析

基础篇和驱动篇使用 I.MX6U-ALPHA 开发板。实例篇使用 RK3568 开发板和 mipi LCD 模块。

2023-09-04 18:33:19 1119

原创 TSP驱动理论与实例分析

文章目录前言一、设备树编写IIC设备地址:复位管脚配置中断管脚配置二、驱动分析数据设定和数据结构probe 解析硬件相关基础设定IIC读取函数解析设备模型添加中断服务函数总结本驱动相对于原版驱动的改动将驱动添加到内核tslib 移植与使用使用内核自带的驱动前言如果是从IIC协议跳转过来的,那么还需要了解一个 input 子系统。触摸屏驱动虽然用的协议是 IIC,也就是说驱动架构是 IIC 驱动,但是在IIC驱动中又把任务都丢给了 input 子系统,而且还要再 IIC 消息中还包装硬件业务。内核未

2023-09-04 17:24:48 151

原创 IIC驱动理论与实例分析

不啰嗦,直接从驱动开讲,需要学习IIC协议基础知识的可以先看这篇文章:https://www.rstk.cn/news/369263.html?提示:需要了解 IIC 的帧格式、读写/命令模式才能彻底了解 i2c_msg 的使用。不想进半导体厂的驱动工程师直接看 设备驱动和设备驱动编写!!!

2023-09-01 02:45:51 146 1

原创 input子系统理论与实例分析

直接上图:(图片来源于正点原子笔记)(输入子系统对触摸屏狠重要,会用 TS Handler 狠重要!驱动层:输入设备的具体驱动程序,比如按键驱动程序,向内核层报告输入内容。核心层:承上启下,为驱动层提供输入设备注册和操作接口。通知事件层对输入事件进行处理。事件层:和用户空间进行交互。驱动触发消息,内核收集后产生对应的回调任务,事件层就可以执行内核发布的回调任务。为什么不直接内核执行任务?你当内核傻啊,内核主要就是调度任务,这个更重要。任务下发后就可以被更重要的任务阻塞。

2023-09-01 01:51:47 151 1

原创 如何在内核中获取当前进程状态

每个进程都有维护了一个 task_struct 结构体,这个结构体有运行进程所需要的一切。内核那么多好东西,完全是超出人脑记忆极限的。需要的时候再去找一下才是最正确的做法。一般需要的数据也不多,状态和ID才是经常用到的。

2023-08-30 16:11:05 194 1

原创 热插拔理论与实例分析

热插拔:带电的情况下装卸设备。热插拔是内核与用户空间之间,通过调用用户空间程序来实现的。当内核发生了某种热插拔事件时,内核就会调用用户空间的程序实现交互。产生机制主要有 udev、mdev,mdev 是 udev 的简化版本。udev 通过 netlink 监听内核发送的 uevent 执行相应的回调。mdev 基于 uevent_helper 机制,内核产生的 uevent_helper 所指的用户程序 mdev 来执行热插拔操作。

2023-08-29 00:44:07 90 2

原创 设备模型理论与实例分析

Linux 系统内部开启了一个监视进程,负责接收和归类注册的设备和模块,然后给新设备匹配驱动,匹配了就能用,道理就这么简单。

2023-08-29 00:11:51 50 1

原创 根文件系统构建后的第三方软件移植

SSH 全称为 Secure Shell(安全外壳协议,简称 SSH),是一种加密的网络传输协议,用于在不安全的网络中为网络服务提供安全的传输环境。ssh:ssh 软件用于替换 rlogin 与 Telnetscp 和 sftp:将文件复制到其他主机上,用于替换 rcpsshd:SSH 服务器。

2023-08-23 18:17:48 186

原创 Linux三大根文件系统移植

buildroot、yocto、ubuntu base

2023-08-23 17:29:18 402

原创 中断子系统理论与实例分析

使用自定义工作队列需要构建一个 workqueue_struct 结构体name:工作队列名create_workqueue() 可以给每个 CPU 都创建一个工作队列,创建成功返回 workqueue_struct 结构体指针,失败返回 NULL。create_singlethread_workqueue() 只给一个 CPU 创建工作队列。调度和取消调度工作队列queue_work_on() 用来调度自定义工作队列;

2023-08-04 21:45:04 59 1

原创 驱动中的高级IO处理

在驱动的 read() 中,先判断 file->f_flags 是否带有 O_NONBLOCK,即是否为非阻塞 IO,如果是,则继续判断数据就绪条件 condition 的值,数据没有就绪就直接退出 read(),并返回 -EAGAIN。timeout:为超时时间,单位为 ms,timeout 大于 0,poll 等待时间直到指定的时间,timeout 为 0,poll 立即返回,timeout 为 -1,一直等待,直到时间发生。当数据就绪后,内核才会将数据拷贝到用户空间,最后返回用户线程,开始处理数据。

2023-08-02 14:56:46 54

原创 并发竞争理论与实例分析

这么做之后,当一个线程打开该设备,如果未关闭该设备,另一个线程也打开该设备时就会陷入阻塞,直到第一个线程关闭了该设备,第二个线程才能打开设备。相应的,多线程中打开同一个设备,慢打开的时候会被阻塞,等到先打开的设备的线程执行完临界操作后关闭设备时,慢打开设备的线程才能唤醒打开设备。就是说,如果某线程需要获取锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在。相应的解决办法是,在自旋锁的使用过程中要尽可能短的时间内拥有自旋锁,而且。信号量是操作系统中最典型的用于同步和互斥的手段,本质上是一个全局变量。

2023-08-02 14:19:57 50

原创 关于VMware Ubuntu明明有大量硬盘空间却提示硬盘空间不足的问题

实际上就和window上磁盘管理工具一样,扩展的空间是未分配的,未分配的当然无法使用。起因:我编译RK3568的SDK时,编译停止了,提示硬盘空间不足。可以看到主存最大也就50G左右啊,那么大的分配空间都去哪里了?然后就查了一下ubuntu的硬件情况,这才发现了问题。15G全用上,选择创建为:扩展分区。空间应该是足够的啊,为什么会提示硬盘空间不足?将文件系统类型选择为:linux-swap。可以看到未分配的空间居然有250G。最后点击操作栏的 √ 就完成分配了。剩下15G作为 swap 分区。

2023-08-01 15:00:19 1819 4

原创 所以真的了解GPIO了吗?

以点亮LED为例。GPIO0_A2 管脚输出高电平时,VCC和地极导通,LED1点亮。

2023-07-23 12:13:33 265 1

原创 pthread_cond_t 究竟有什么花样?

pthread_cond_wait 函数一旦调用,则线程立即被阻塞,同时所拥有的互斥锁也被释放,线程一直停止在pthread_cond_wait 函数中,直到 pthread_cond_singal 函数通知对应的条件变量时接触阻塞,pthread_cond_wait 运行结束,但是返回的时会申请之前释放的互斥锁。pthread_cond_wait返回时,互斥量再次被锁住。wait 的写法多种多样,但是最常见的还是在 while 中,在 while 被唤醒的线程会因为不满足条件而再次被阻塞!

2023-07-10 17:50:31 103 1

原创 字符驱动程序设计的思路

ioctl() 传送的变量 cmd 是应用程序用于区别向设备驱动程序请求处理的内容的值,cmd 除了可区别的数字外,还包含有助于处理的几种相应的信息。首先,Linux 系统的应用层活动于用户态,用户态无法直接访问硬件。想要在应用层访问硬件就需要切换到内核态,内核态访问硬件后又切换回用户态继续工作。可能会有学完STM32的杆精说中断,应用程序哪来的途径直接使用中断,中断都是在驱动中配好的,轮不到应用层调用。触发内核态的方式有很多,系统调用是驱动中用得最广泛的一种。

2023-07-10 15:19:34 75 1

原创 设备树基础语法与实例分析

* 自定义一个管脚标号的属性 pinnum */ pinnum = < 0 1 2 3 4 >;驱动可以拿到设备树中的任意节点的任意数据,至于有没有用,用来做什么,都是驱动开发的事情了,所以开放自定义属性合理。中断控制器中,必须有一个属性 #interrupt-cells 表示其他节点使用这个中断控制器需要几个 cell 来表示使用哪一个中断。中断控制器中,必须有一个属性 interrupt-controller 表示它是中断控制器。

2023-07-10 14:31:19 534 1

原创 pthread_mutex_t 究竟有什么花样?

自己动手画了个图,一张图胜过1000行注释。

2023-07-04 20:17:14 85

原创 Linux内核双链表的用法

任何地址存放的数据是可以转换成任意类型的(存放什么类型的数据,就需要用什么类型的指针去读取),但是读写就另说了。得到的地址减去它在结构体中的偏移量,就得到了它所属的结构体的首地址。随后,取转换后的数据类型中指定的成员 MEMBER 的地址,好巧不巧,从 0 地址出发到 MEMBER 的步进长度就是 MEMBER 在结构体中的偏移量。那要看 const 在谁前面呀,在类型前面,类型不能变,在指针前面,指向的地址不能变,这里明显是在类型前面)删除结点:抓住某个结点,获取它的前后结点,再让其前后结点互相指向。

2023-06-22 11:40:54 93 1

原创 如何优雅地传递指针?

实例1的第一段代码之所以很多人没有看出问题,是因为把字符串当做了普通的字符变量,而忽略了它的一个本质,传递时是字符串的地址。change函数根本不起作用,很多新人会以为 p = “bbb” 是给字符指针变量赋值,实际上是给 p 的地址赋值,赋予了字符串 “bbb” 的地址。我的理解是对待指针参数是使用一个新的临时指针去指向参数,对待非指针变量只是新建一个值相同的变量来供内部使用。实例:写一个函数让输入指针指向一个另一个地址并对指向的内容进行处理。实例2:修改数字指针指向的内容。实例1:修改字符串内容。

2023-06-07 17:42:36 67 1

原创 如何优雅地使用全局变量?

貌似看起来没什么问题,但是一旦项目持续扩大,需要加入的全局信息越来越多,而且针对某些程序需要修改的仅仅只是其中的一部分而已,为此暴露出了整一个信息块就非常不安全。这点可以参考 Linux 设备模型源码中的 kref 的实现,对设备的使用计数,同样是维护了一个全局变量,并且也是向外提供针对性的操作方法。当 static 声明函数时,该函数同样也不需要向外部声明,同时不可直接被外部调用,但是这里是为了向外部提供针对性操作全局变量的方法。没错,其实我还是很喜欢把C语言当成 C with class 来编程的。

2023-05-31 14:52:37 116 1

原创 如何优雅地使用常量?

其实很多实际的项目中,一旦是涉及大量命令的,所谓的命令基本上都是一些简单的数字。这是个很不好的习惯,建议像下面这个。还是上面那个项目,这里是在回调函数中设置网络设备的状态,本来只是两个简单的数字,0、1,但是为了方便理解和减少调试难度,一样也统一了常量的枚举。此外,设计程序时时常会一些即时用到的字符串常量,建议都使用 define 声明,这样在排错的时候,一些低级的书写错误将会很容易调试。这是我在项目中写的一个给接收的 mac 标记设备类型的函数,重点看 DeviceFlags 枚举的作用。

2023-05-30 18:25:17 128 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除