R Field - 2020年8月
type: channel
link: http://www.ramlife.org/2020/08/
description: 通玄小论
items: ssh 图形界面
items: 驱动开发中，某些 api 的区别和关联
items: wifi 透传模块 hf-lpt220 常用命令
items: 100ask 韦东山 驱动大全 子系统 input 学习笔记
items: iar 定位 包含错误的路径
items: eaidk 610 aiot 学习笔记
items: win10 微软拼音 双拼 紫光方案
items: 100ask 韦东山 驱动大全 I2C驱动 学习笔记

ssh 图形界面
type: item
date: 2020-08-31T14:07:00+08:00
description: 想要 ssh 到服务器上的特定用户，并使用含 x 的程序，比如说 gitk。 ssh -X user@192.168.0.2 参考： https://blog.csdn.net/fdd096030079/article/details/80986266 https://blog.csdn.net/xxradon/article/details/86636340

驱动开发中，某些 api 的区别和关联
type: item
date: 2020-08-29T10:33:00+08:00
description: 字符设备注册 register_chrdev 和 cdev_init + cdev_add 是 Linux 内核中用于注册字符设备的两种不同方法。它们在 使用场景 和 实现方式 上有显著区别。 register_chrdev 特点 一次性注册： 通过一个函数调用完成字符设备的注册。 自动分配主设备号和创建设备节点（如果使用 devfs 或 udev）。 简单易用： 适合简单的字符设备驱动，代码量少，开发速度快。 静态分配： 通常用于静态分配主设备号，无法灵活管理多个次设备号。 旧版接口： 是 Linux 内核早期提供的接口，逐渐被 cdev_init + cdev_add 取代。 使用场景 适用于简单的字符设备驱动。 当设备只需要一个主设备号，且不需要管理多个次设备号时。 适合快速原型开发或学习阶段的驱动程序。 cdev_init + cdev_add 特点 分步注册： cdev_init 初始化字符设备结构体。 cdev_add 将字符设备注册到内核中。 灵活管理： 支持动态分配主设备号和次设备号。 可以管理多个次设备号（如多个设备实例）。 现代接口： 是 Linux 内核推荐的字符设备注册方式，功能更强大，灵活性更高。 与设备模型集成： 可以与内核的设备模型（如 sysfs、udev）集成，支持设备节点的动态创建和管理。 使用场景 适用于复杂的字符设备驱动。 当设备需要动态分配主设备号或管理多个次设备号时。 当需要与内核的设备模型集成（如通过 device_create 创建设备节点）时。 适合生产环境中的驱动程序开发。 主要区别 特性 REGISTER_CHRDEV CDEV_INIT + CDEV_ADD 注册方式 一次性注册 分步注册 设备号管理 静态分配主设备号 动态分配主设备号和次设备号 次设备号支持 不支持管理多个次设备号 支持管理多个次设备号 设备模型集成 不支持内核设备模型（如 sysfs、udev） 支持内核设备模型 灵活性和功能 功能简单，灵活性较低 功能强大，灵活性高 适用场景 简单设备驱动，快速原型开发 复杂设备驱动，生产环境开发 内核版本支持 旧版接口，逐渐被淘汰 现代接口，推荐使用 总结 register_chrdev： 简单易用，适合快速开发简单的字符设备驱动。 功能有限，不支持动态设备号管理和内核设备模型集成。 逐渐被淘汰，不建议在新代码中使用。 cdev_init + cdev_add： 灵活强大，适合开发复杂的字符设备驱动。 支持动态设备号管理、多个次设备号和内核设备模型集成。 是现代 Linux 内核推荐的字符设备注册方式。 在实际开发中，建议优先使用 cdev_init + cdev_add，因为它提供了更强大的功能和更高的灵活性，能够更好地满足现代设备驱动的需求。 创建设备节点 旧方法：mknod， 新方法：device_create。 mknod 函数原型 int mknod(const char *pathname, mode_t mode, dev_t dev); 使用场景 用户空间手动创建设备节点 mknod /dev/my_device c 240 0 缺点 手动管理：需要手动创建设备节点，增加了使用复杂度。 权限问题：需要手动设置权限，可能导致权限不足或安全问题。 缺乏动态性：设备节点无法动态创建或删除，无法适应设备的热插拔。 device_create 函数原型 struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...); 使用场景 在内核驱动中自动创建设备节点。 device_create(my_class, NULL, dev, NULL, "my_device"); 优点 自动管理：设备节点由内核自动创建，无需手动干预。 权限控制：设备节点的权限由内核自动设置，符合安全规范。 动态支持：支持设备的热插拔，设备节点可以动态创建或删除。 集成设备模型：与内核的设备模型（如 sysfs、udev）集成，提供更强大的功能。 为什么要使用新函数？ 自动化和动态化 新方法通过内核自动创建设备节点，支持设备的热插拔和动态管理，减少了手动操作的复杂性。 权限和安全性 新方法由内核自动设置设备节点的权限，避免了手动设置权限可能带来的安全问题。 集成设备模型 新方法与内核的设备模型（如 sysfs、udev）紧密集成，提供了更强大的设备管理功能（如属性文件、事件通知等）。 一致性和可维护性 新方法符合现代 Linux 内核的设计理念，代码更加一致和可维护。 总结 旧方法：mknod 用于在用户空间手动…

wifi 透传模块 hf-lpt220 常用命令
type: item
date: 2020-08-25T17:06:00+08:00
description: wifi 透传模块 hf-lpt220 常用命令，也就是 AT 命令： [...]

100ask 韦东山 驱动大全 子系统 input 学习笔记
type: item
date: 2020-08-23T14:45:00+08:00
description: input 子系统介绍 参考资料 Linux 5.x内核文档 Documentation\input\input-programming.rst Documentation\input\event-codes.rst Linux 4.x内核文档 Documentation\input\input-programming.txt Documentation\input\event-codes.txt input 种类 按键：EV_KEY，比如键盘 相对位移：EV_REL，比如鼠标 绝对位移：EV_ABS，比如触摸屏 杂项：EV_MSC 软件：EV_SW LED：EV_LED 声音：EV_SND 会自动发出重复按键：EV_REP 电源开关、按键：EV_PWR 驱动框架 input device, 主要了解的是 gpio 和 uinput. uinput 主要用于用户态的键盘输入模拟用。 app 输入系统框架及调试 输入系统框架 数据的流程如下： APP发起读操作，若无数据则休眠； 用户操作设备，硬件上产生中断； 输入系统驱动层对应的驱动程序处理中断：读取到数据，转换为标准的输入事件，向核心层汇报。所谓输入事件就是一个“struct input_event”结构体。 核心层可以决定把输入事件转发给上面哪个handler来处理： 从handler的名字来看，它就是用来处输入操作的。有多种handler，比如：evdev_handler、kbd_handler、joydev_handler等等。 最常用的是evdev_handler：它只是把input_event结构体保存在内核buffer等，APP来读取时就原原本本地返回。它支持多个APP同时访问输入设备，每个APP都可以获得同一份输入事件。 当APP正在等待数据时，evdev_handler会把它唤醒，这样APP就可以返回数据。 APP对输入事件的处理：APP获得数据的方法有2种：直接访问设备节点(比如/dev/input/event0,1,2,...)，或者通过tslib、libinput这类库来间接访问设备节点。这些库简化了对数据的处理。 调试 hexdump /dev/input/event0 命令行获取输入设备当前的数据。点击触摸屏就可以看到数据刷新。 ls /dev/input/* -l 查看输入设备节点 cat /proc/bus/input/devices 查看详细的设备信息 详细设备信息解析 主要是 include\linux\input.h 中 struct input_dev 里面的值的表示。 struct input_dev { const char *name; const char *phys; const char *uniq; struct input_id id; unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; unsigned long sndbit[BITS_TO_LONGS(SND_CNT)]; unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; ... I:id of the device(设备ID) 该参数由结构体struct input_id来进行描述，驱动程序中会定义这样的结构体： // include\uapi\linux\input.h struct input_id { __u16 bustype; __u16 vendor; __u16 product; __u16 version; }; N:name of the device 设备名称 P:physical path to the device in the system hierarchy 系统层次结构中设备的物理路径。 S:sysfs path 位于sys文件系统的路径 U:unique identification code for the devi…

iar 定位 包含错误的路径
type: item
date: 2020-08-21T19:00:00+08:00
description: 当 iar 工程在多个地方复制使用的时候，有时候定位函数的时候，会提示错误的路径。 解决方法： project --> clean，清除， 然后 rebuild all，就可以了。

eaidk 610 aiot 学习笔记
type: item
date: 2020-08-21T10:44:00+08:00
description: eaidk 610 平台，aiot 套件学习笔记 [...]

win10 微软拼音 双拼 紫光方案
type: item
date: 2020-08-20T19:10:00+08:00
description: win10 上面的微软拼音有多种 双拼方案，也可以自定义方案，因为习惯紫光方案，所以自定义修改即可。 [...]

100ask 韦东山 驱动大全 I2C驱动 学习笔记
type: item
date: 2020-08-09T09:52:00+08:00
description: I2C 介绍 i2c device driver: 如何读写数据，组织命令数据等，比如命令中需要包含命令、地址等数据，还有收到原始数据后如何解析。 i2c controller driver: 如何按照 i2c 的协议，来传输 device driver 的数据。 i2c 数据通道 普通用法, 芯片有 i2c 控制器，使用 i2c 设备驱动: app <-> some driver <-> adapt driver <-> device 芯片没有 i2c 控制器，使用 gpio 模拟i2c 控制，使用 i2c 设备驱动: app <-> some driver <-> i2c-gpio.c <-> device app 希望自己组织数据，跳过 i2c 设备驱动，来使用 i2c 控制器驱动: app <-> i2c-dev.c <-> adapt driver <-> device app 希望自己组织数据，跳过 i2c 设备驱动，使用 gpio 模拟i2c驱动: app <-> i2c-dev.c <-> i2c-gpio.c <-> device app 使用 i2c-dev.c 自己组织数据，这种一般成为用户态驱动程序。 SMBus 协议 SMBus 是 i2c 的子集。在以下方面要求更加严格: 电压范围，1.8 - 5V 最小时钟频率 10KHz，最大的 SCL 拉低占用时间也有限制 开始的地址匹配时，必须 ack，用于判断设备状态是否正常。 增加 restart 信号，可以省略停止信号。 SMBus 和 i2c 的最大区别，是 block r/w 的时候，SMBus 要求在寄存器地址后，正式数据前，必须增加一个长度数据。 i2c 系统的重要结构体 i2c_adapter controller 对应的结构体是 i2c_adapter, 主要的成员是：第几个i2c控制器， 传输函数。 struct i2c_adapter { // 传输函数 const struct i2c_algorithm *algo; /* the algorithm to access the bus */ // 第几个 bus 上的控制器 int nr; i2c_client device 对应的结构体是 i2c_client，最重要的成员是: 设备地址。 struct i2c_client { // 可以用来表示少部分的 10位地址，或者其他情况。 unsigned short flags; /* div., see below */ unsigned short addr; /* chip address - NOTE: 7bit */ /* addresses are stored in the */ /* _LOWER_ 7 bits */ // device 具体挂载在哪个总线对应的 adapter 下面? struct i2c_adapter *adapter; /* the adapter we sit on */ i2c_msg int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); 传输函数中，第一个参数 adap 指明了是第几个 i2c 控制器；第二个参数是传输数据，其中包含了芯片地址、数据 buf、数据长度；第三个参数 num 是 msg 的个数，比如读取数据，那么就需要两个 msg，前一个是寄存器地址 msg，第二个是数据读取命令 msg，所以需要一次创建好多个 msg. struct i2c_msg { __u16 addr; /* slave address */ // flags 标识 read / write __u16 flags; __u16 len; /* msg length */ __u8 *buf; /* pointer to msg data */ }; i2c_transfer 直接使用 master_xfer 传输比较麻烦，可以使用 int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 来传输，内部调用了 master_xfer. 无需驱动直接访问 i2c 正常情况，需要自己写 i2c 驱动程序，然后 app 通过驱动程序来工作。 但是，如果不像自己写 i2c 驱动程序，那么可以通过内核自带驱动 i2c-dev.c 再通过 i2c_adapter 就可以和 i2c 设备进行通信。 app 如何使用 i2c-dev.c, 可以参考 i2c-tools 这个软件。 i2c-tools 操作 i2c，需要确定三个东…