Linux之PWM风扇驱动
Linux之PWM风扇驱动背景该驱动主要是用于PWM模块去驱动散热风扇,使用通用的PWM接口,只要主控Soc的PWM模块使用的是标准通用的PWM框架,则可以适用于任何主控Soc,与具体的硬件无关。
用户空间接口驱动程序给用户空间提供了相应hwmon的sysfs接口: /sys/class/hwmon/hwmon-x/,主要是对PWM的读写操作和风扇转速的读操作:
static int pwm_fan_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
int ret;
if (val < 0 || val > MAX_PWM)
return -EINVAL;
ret = __set_pwm(ctx, val);
if (ret)
return ret;
...
USB转串口CH343驱动
USB转串口CH343驱动背景在网上用9.9淘的一块ESP32-C3(RISC-V)的小开发板上,用的CH343的USB转串口。最近打算学习用Rust开发ESP32-C3,在Ubuntu上搭建开发环境的时候发现,Ubuntu20.04上默认使用的是 CDC-ACM 驱动,即生成的节点为/dev/ttyACM0,但是用Rust开发ESP32-C3,需要使用 VCP 驱动,于是在网上找到了官方(WCH-南京沁恒)的一份Linux驱动源码:https://github.com/WCHSoftGroup/ch343ser_linux
里面的文档也说明了使用 CDC-ACM 驱动的一些局限性:
The CDC-ACM driver has limited capabilities to control specific devices. This generic driver does not have any knowledge about specific device protocols. Because of this, device manufacturers can create ...
Rust之cargo简单熟悉
Rust之cargo简单熟悉还记得上一篇文章 –《Rust简单开发环境搭建》中,helloworld的例子是用cargo来管理的,今天我们就来聊聊这个cargo
cargo是什么?为什么需要这个cargo?cargo是Rust的包管理器,Rust的包分为2种,一种是二进制可执行的包,一种是库的包,默认情况下就是第一种binary包
在Rust里,一个库或者可执行程序叫做一个crate,一般简单情况下,我们可以直接使用Rust的编译器rustc来编译这个crate,但如果编译这个crate需要许多编译参数,包含许多依赖,或者需要其他构建工具,手动去操作就会很麻烦,而且也很难管理,这样包管理器cargo就应运而生了
cargo主要做以下4个工作:
引入两个包含包信息的元数据文件
获取并构建包的依赖项
用正确的参数调用rustc或其他构建工具来生成包
引入规则约定,使使用Rust包变得更容易
包结构下面是用cargo生成的包目录结构:
.
├── Cargo.lock
├── Cargo.toml
├── src/
│ ├── lib.rs
│ ├── main.rs
│ └ ...
Rust简单开发环境搭建
Rust简单开发环境搭建整个环境搭建默认在X86的Linux环境(Ubuntu)下进行
环境搭建首先,要熟悉下 Rust 的几个基本东东:
rustup: Rust 版本管理器
cargo: Rust 包管理器
rustc: Rust 编译器
安装使用官方推荐的rustup方式进行安装,使用下面的一条命令即可:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
耐心等待,安装完成后,查看 Rust 版本:
$ rustc --version
rustc 1.69.0 (84c898d65 2023-04-16)
$ cargo version
cargo 1.69.0 (6e9a83356 2023-04-12)
切换版本切换 rustc 的版本, nightly或stable:
rustup install xxx(nightly/stable)
rustup default xxx(nightly/stable)
卸载Rust同样的,卸载 Rust 使用rustup即可:
rustup self un ...
fb的notifier
fb的notifier背景最近调试了一个BUG:一个平板使用hall传感器检测键盘保护套的开合,但是发现有时候合上保护套时,屏幕并没有关闭。
最后发现是CONFIG_FB=y配置没打开,导致hall传感器驱动里的fb的notifier没起作用,从而使获取的 suspend/resume 的状态异常,具体的细节不在这详述了,这里主要想扩展并记录下这个fb的notifier。
使用有时候,我们需要监听显示屏的一些事件,根据事件的状态来进行一些操作,比如常见的关闭显示屏时,触摸屏进入休眠等等
确认内核配置确认已打开CONFIG_FB_NOTIFY配置, 只要CONFIG_FB打开默认就打开了CONFIG_FB_NOTIFY
CONFIG_FB_CMDLINE=y
CONFIG_FB_NOTIFY=y
CONFIG_FB=y
代码实现这里主要以常用的FB_EVENT_BLANK事件为例,下面是部分伪代码实现:
struct yyy {
...
struct notifier_block fb_notif; /*FB callbac ...
SPI接口的ADC驱动调试
SPI接口的ADC驱动调试背景最近在学习IIO子系统,顺带调试了个SPI接口的ADC驱动,所以在这简单记录下。这里只简单介绍了适配一个简单SPI接口ADC驱动的流程,不过多深入框架子系统,更多关于IIO子系统的介绍,请见下一篇:
驱动开发dtsdts主要修改或新增以下几点:
spi master控制器相关配置
spi设备节点配置
引脚复用配置
如spi节点配置例子:
&spi0 {
status = "okay";
num-cs = <1>; /* Total number of chip selects */
aaa: aaa@0 {
status = "okay";
reg = <0>; /* Chip select used by the device. */
compatible = "yyy,xxx&quo ...
spidev相关
spidev相关背景有时候会发现,一些外挂的spi的flash或者外设用了spidev这个驱动,没有适配特定的驱动,到底spidev是个啥呢?
spidev:SPI userspace API下面是内核官方文档解释:
SPI devices have a limited userspace API, supporting basic half-duplexread() and write() access to SPI slave devices. Using ioctl() requests,full duplex transfers and device I/O configuration are also available.
它主要包括核内的spidev驱动,相当于spi设备的万能通用驱动, 类似于通用phy驱动,主要代码:
drivers/spi/spidev.c
include/uapi/linux/spi/spidev.h
使用dts匹配驱动设备匹配通用的spidev驱动即可,其他属性参数根据设备硬件特性来写,都是通用的spi属性,和spi.h头文件里面 ...
Termux初探
Termux初探Termux是啥
Termux是一个Android终端模拟器和带有Linux环境的应用程序 无需Root或设置即可直接使用。 自动安装最小的基本系统 - 使用 APT 包管理器可以获得其他软件包
初探前提条件:
一台Android的机器(手机或平板都可)
可以连接外网
有root权限更好
下载安装官方apk下载站点:https://f-droid.org/en/packages/com.termux/
下载最新版本APK并安装到目标机器(Android)上..
启动点击图标启动或命令行启动:
am start com.termux/.HomeActivity
源及软件包管理
更新源及软件包:因为众所周知的原因,我们需要换成国内的镜像源,这里我们换成清华的源,可以直接使用官方的管理工具termux-change-repo进行切换,运行该工具,选择mirrors.tuna.tsinghua.edu.cn即可
更新软件包:
pkg update
pkg upgrade
安装必要软件根据自己需要安装必要软件包:
pkg install vim curl wget git ...
Kernel之共享中断
Kernel之共享中断背景最近有个测试用例的需求,是关于中断管理的。在现有的硬件基础上,实现以下功能:
缺省情况下提供默认的中断处理程序
能使能和屏蔽某一特定中断
后面用共享中断实现了这个测试用例
共享中断有时候多个设备可能共享一根硬件中断线,在现实应用场景中广泛存在,特别像PCI控制器,GPIO等,所以内核提供了这种中断共享的机制。
下面是中断共享的使用及注意点:
共享中断的多个设备在申请中断时,都应加上 IRQF_SHARED 标志,而且一个设备以IRQF_SHARED申请某中断成功的前提是该中断未被申请,或该中断虽然被申请了,但是之前申请该中断的所有设备也都以IRQF_SHARED标志申请该中断。
尽管内核模块可访问的全局地址都可以作为request_irq(…,void*dev_id)的最后一个参数dev_id,但是设备结构体指针显然是可传入的最佳参数。
在中断到来时,会遍历执行共享此中断的所有中断处理程序,直到某一个函数返回IRQ_HANDLED。在中断处理程序顶半部中,应根据硬件寄存器中的信息比照传入的dev_id参数迅速地判断是否为本设备的中断,若不是,应迅速返回 ...
Kernel之通知链
Kernel之通知链背景最近在调触摸屏,看代码时偶然看到了通知链相关的代码,加上之前刚好了解了一点通知链相关的东东,所以特此记录下。在触摸屏驱动中的主要功能就是在开关屏的时候通知TP进行resume和suspend操作,大致的伪代码如下,以我看的elan的TP驱动为例:
...
/* 通知链的事件回调函数,收到通知TP进行resume和suspend操作 */
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct fb_event *evdata = data;
int *blank;
struct elan_ts_data *ts =
container_of(self, struct elan_ts_data, fb_notif);
if (evdata && evdata->data && event == FB_EVENT_BLANK && ts ...
Linux蓝牙文件传输速率低问题分析及延伸
Linux蓝牙文件传输速率低问题分析及延伸[TOC]
背景最近调试了一个BUG:在两台装Kylin的PC之间,连接蓝牙,然后相互传输文件,速率只有20几Kb/s。正常情况有100多Kb/s。
使用了obex协议传输文件
分析分析系统日志,未有明显的错误或警告日志
开始抓包分析发送方的抓包:从上图可以看出,在发送obex包的时候,中间夹杂着很多sco的语音包
接收方的抓包:从上图可以看出,在接收obex包的时候,中间也夹杂着很多sco的语音包,而且obex包被拆包了,拆成了好几个包
当2台电脑连接成功后,应用上层会默认切换音频通路及输入输出设备,并默认会开启SCO语音链路。经验证,手动切换输入设备,obex传输文件速度就会恢复成正常的100多Kb/s。还有一种方式,在已配对并且非连接状态下,进行蓝牙文件传输,速率也是正常的
从发送和接收的抓包来看,抓到的发送和接收obex包的时候都有分包,只不过发送分包大些,接收的分包小些。
延伸:ACL数据包及L2CAP分包重组文件传输走的是ACL链路,ACL数据包及L2CAP分包重组我们看看ACL的数据包格式:其中header中有个与分包组包相关 ...
btmon获取hci数据流程
btmon获取hci数据流程背景最近在看蓝牙相关的驱动代码,追到hci接收数据处理函数hci_rx_work()(net/bluetooth/hci_core.c),瞄到下面一段代码:
...
while ((skb = skb_dequeue(&hdev->rx_q))) {
/* Send copy to monitor */
hci_send_to_monitor(hdev, skb);
...
}
在hci发送数据的处理函数hci_send_frame()中也有类似的代码片段:
...
/* Time stamp */
__net_timestamp(skb);
/* Send copy to monitor */
hci_send_to_monitor(hdev, skb);
if (atomic_read(&hdev->promisc)) {
/* Send copy to the sockets */
hci_send_to_sock(hdev, skb);
}
... ...