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

King3399(ubuntu文件系统)iic(i2c)功能测试

0 引言

前面两篇博文简要介绍了板子上uart部分的内容,但在驱动开发时,我们遇到的外设更多的是以i2c或spi进行通信,本文将对king3399的i2c进行测试并对硬件电路、设备树与驱动程序进行分析

如果使用的i2c设备不是mma8452,建议先看看文末枚举中的i2c设备类型,本文可扩展枚举的所有i2c设备

1 i2c接口硬件分析

通过板子电路原理图可以看到板子底板使用了三组i2c接口,这三组接口都已挂载了设备,设备分配如下表所示

i2cnumchipnote
i2c1U14ALC5651Audio
J21MIPICamera
J22MIPICamera
J106PinPin
i2c3J10HDMIVideo
i2c4U12MMA8452Accelerometer
J33MIPILCD Video
J106PinPin
U23FUSB302MPXBattery Charge

由于本人手边没有合适的设备,因此这里以板载加速度传感器(U12 MMA8452)为例进行测试,该传感器挂载在i2c4上,需要注意的是由于使用的是i2c协议通信,因此需要在i2c4的scl和sda引脚上分别接一个上拉电阻,参考MMA8452数据手册,上拉电阻使用4.7kΩ,但在分析板子的原理图时,比较疑惑,由于没有核心板的原理图,只有底板的原理图,在底板的原理图中,i2c4两只引脚网络皆没有连接上拉电阻,i2c1与i2c3网络在底板上也没有连接上拉电阻,猜测i2c的上拉电阻应该都在核心板上(另外,如果注意核心板引出的i2c网络可以看到,其网络名称定义为“GPIO1_B3/I2C4_SDA_u”和“GPIO1_B4/I2C4_SCL_u”,这里的尾缀“u”应该是“up”的缩写,意思应该是上拉,当然这仅仅是我个人猜测),这个需要注意一下,当使用板子引出的i2c端口与我们手中的其他模块进行交互时,就不再需要连接上拉电阻

在这里插入图片描述

2 MMA8452设备树分析

打开设备树文件可以看到,i2c4节点下没有设备MMA8452的子节点,(注:此处使用的设备树文件由板子镜像逆向而来,具体来源可参考脚注【a】,板子烧录镜像文件为update-rk3399-king-rk3399-ubuntu-mipi-7-1024-600-20240922-165231.img,该镜像文件由本人编译,具体编译过程可参考脚注【b】)

	i2c@ff3d0000 {pinctrl-names = "default";#address-cells = <0x01>;pinctrl-0 = <0x94>;clock-names = "i2c\0pclk";assigned-clocks = <0x86 0x0a>;assigned-clock-rates = <0xbebc200>;interrupts = <0x00 0x38 0x04 0x00>;clocks = <0x86 0x0a 0x86 0x1c>;#size-cells = <0x00>;compatible = "rockchip,rk3399-i2c";status = "okay";reg = <0x00 0xff3d0000 0x00 0x1000>;phandle = <0x130>;// 触摸屏节点goodix_ts@5d {gtp_resolution_x = <0x400>;gtp_overturn_y = <0x00>;goodix_rst_gpio = <0x41 0x04 0x01>;goodix,cfg-group0 = [41 00 04 ...省略... 00 3b 01];gtp_int_tarigger = <0x01>;goodix_irq_gpio = <0x41 0x16 0x01>;goodix,cfg-group5 = [ff 00 04 ...省略... 00 6a 01];gtp_resolution_y = <0x258>;gtp_touch_wakeup = <0x01>;compatible = "goodix,gt9xx";gtp_change_x2y = <0x00>;gtp_overturn_x = <0x00>;reg = <0x5d>;gtp_send_cfg = <0x01>;};// usb充电节点fusb302@22 {pinctrl-names = "default";pinctrl-0 = <0x95>;interrupts = <0x02 0x08>;vbus-supply = <0x96>;interrupt-parent = <0x41>;compatible = "fcs,fusb302";status = "okay";reg = <0x22>;phandle = <0x131>;...省略... };};

打开../03-硬件文档/King3399底板-硬件规格书_20180105.pdf文档可以看到“重力传感器”仅支持Android系统(如上图所示),而本人所编译的系统为ubuntu,因此设备树中无该设备节点(ubuntu一般用于台式设备,android用于便携手持设备,后者需要判断设备姿态,因此需要启用该传感器)

徒手搓一个设备树节点于我个人而言是有难度的,既然Android系统支持该设备,那么我们就可以将Android系统中的该设备点节拷贝下来,大致思路是从板子的官方Android镜像中逆向完整的设备树文件,从该逆向设备树中查找到需要的节点,步骤如下:

  1. 下载官方Android镜像文件,这里使用的是update_king_rp3399_android7.1_hdmi_20200714_171241.img,(由于本人手中只有一个hdmi接口的显示器,因此选择该镜像,若手中有配套的LCD则可以选择对应的镜像文件)

  2. 将上述镜像文件烧录到板子中,烧录过程可参考脚注【b】

  3. 将板子设置为“开发者模式”,与手机进入该模式相同,具体操作如下:

    1. 板子上电后进入主界面,将光标放到底部状态栏

      在这里插入图片描述

    2. 光标长按底部状态栏并向上拖拽,此时界面会切换到应用界面

      在这里插入图片描述

    3. 找到“设置”应用,点击进入
      在这里插入图片描述

    4. 找到“关于平板电脑”选项,点击进入
      在这里插入图片描述

    5. 找到“版本号”选项,连续点击多次,此时界面会提示“开发者模式”选项
      在这里插入图片描述
      在这里插入图片描述

    6. 退回到上一层,找到“开发者选项”选项,点击进入并勾选“USB调试”选项
      在这里插入图片描述

    7. 回到应用界面,找到“荣品功能测试”应用,点击进入,找到“重力传感器测试”项,此时翻动板子将看到xyz轴数值的变化,该步骤可验证板子上的加速度传感器是否正常工作
      在这里插入图片描述

  4. 在电脑上安装ADB,安装过程及初步使用可参考脚注【c】

  5. 将板子与电脑连接,此时电脑会自动识别到板子,在电脑的“Device Manager”可以看到已连接的“Android Device”
    在这里插入图片描述

  6. 获取Android设备fdt文件,具体操作如下:(下边的“ & rem ”是cmd的单行注释符,可理解为C语言中的“//”),win + r 并输入 cmd打开windows命令行窗口

    1. adb version & rem 查看adb版本
    2. adb devices & rem 查看连接的设备,将板子与电脑使用usb线连接后将会列如出已连接的设备
    3. adb root & rem 提升操作权限
    4. adb pull /sys/firmware/fdt & rem 从板子中pull出设备树文件,文件默认保存在电脑 C:\Users\username\fdt
  7. 将fdt文件反编译为dts文件,参考脚注【d】,具体操作如下:

    1. 将fdt文件从windows系统中复制到ubuntu系统中
    2. 在ubuntu 系统中安装反编译dtc工具,“apt install device-tree-compiler”
    3. 将fdt反编译成dts,在fdt目录执行 “dtc -I dtb -O dts fdt -o fdt.dts”
    4. 完成上述操作将在当前目录下生成fdt.dts文件,打开该文件,搜索“MMA8452”,可以看到如下节点:
     i2c@ff3d0000 {compatible = "rockchip,rk3399-i2c";reg = <0x0 0xff3d0000 0x0 0x1000>;clocks = <0x30 0xa 0x30 0x1c>;clock-names = "i2c", "pclk";interrupts = <0x0 0x38 0x4 0x0>;pinctrl-names = "default";pinctrl-0 = <0x80>;#address-cells = <0x1>;#size-cells = <0x0>;status = "okay";i2c-scl-rising-time-ns = <0x258>;i2c-scl-falling-time-ns = <0x14>;max17047@36 {status = "okay";compatible = "maxim,max17047";reg = <0x36>;charge-detect-gpio = <0x34 0x9 0x0>;battery-full-detect-gpio = <0x34 0xa 0x0>;};sensor@1d {status = "okay";compatible = "gs_mma8452";pinctrl-names = "default";pinctrl-0 = <0x81>;reg = <0x1d>;type = <0x2>;irq-gpio = <0x34 0x17 0x2>;irq_enable = <0x1>;poll_delay_ms = <0x1e>;layout = <0x4>;};fusb30x@22 {compatible = "fairchild,fusb302";reg = <0x22>;pinctrl-names = "default";pinctrl-0 = <0x82>;int-n-gpios = <0x34 0x2 0x0>;vbus-5v-gpios = <0x83 0x1a 0x0>;status = "okay";linux,phandle = <0x27>;phandle = <0x27>;};};
    

完成上述步骤后就是分析MMA8452节点,在sdk中全局搜索MMA8452(grep -i -r -n "mma8452" /home/username/sdk)可以看到如下两个相关文件:
../sdk/kernel/Documentation/devicetree/bindings/iio/accel/mma8452.txt
../sdk/kernel/Documentation/devicetree/bindings/input/sensors/rk_sensor.txt
前者为Freescale官方对MMA8452节点的描述,后者为Rockchip官方对MMA8452节点的描述,通过两者综合分析可对逆向的设备树作如下解析:

sensor@1d {// 设备状态,正常启用,Android系统支持重力检测status = "okay";// 设备兼容,用于查找设备可用驱动程序compatible = "gs_mma8452";// 引脚控制// 若 pinctrl-names 的名字被设置为 default 那么该设备的驱动加载后,// 就会将功能脚按照 pinctrl-0 的配置设置,参考脚注【f】pinctrl-names = "default";// 引脚控制,表示MMA8452用到的引脚// 示例:rockchip,pins=<1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;// 原理图中MMA8452使用的引脚为GPIO1_C7(scl、sda引脚属于i2c4总线节点)// 打开从Android逆向生成的fdt.dts,查找mma8452,// 可以看到节点mma8452-irq-gpio的phandle属性值为0x81// 其配置为 rockchip,pins = <0x1 0x17 0x0 0xbf>;// 其中,0x1表示RK_GPIO1,// 该宏定义在../sdk/u-boot/include/dt-bindings/pinctrl/rockchip.h// 0x17表示C7这只引脚,// 打开..sdk/kernel/include/dt-bindings/pinctrl/rockchip.h可以看到// #define RK_PC7  23,23转为十六进制为 0x17// 0x0表示RK_FUNC_GPIO,// 该宏定义在../sdk/kernel/include/dt-bindings/pinctrl/rockchip.h// 0xbf表示pcfg-pull-up,// Android逆向生成的fdt.dts中pcfg-pull-up的phandle值为0xbf// pcfg-pull-up的具体意义可查看../sdk/kernel/drivers/pinctrl/pinconf-generic.c 与// ../sdk/kernel/include/linux/pinctrl/pinconf-generic.hpinctrl-0 = <0x81>;// 设备地址,i2c通信时使用的地址// MMA8452芯片手册中提到可支持的i2c地址为 0011100 或 0011101// 当芯片引脚SA0 (pin 7)为高电平时,i2c地址为 0011101 (0x1d)// 当芯片引脚SA0 (pin 7)为低电平时,i2c地址为 0011100 (0x1c)// 原理图中,引脚SA0 (pin 7)为高电平(VCCA1V8_CODEC),// 因此MMA8452的i2c地址为 0011101 (0x1d)reg = <0x1d>;// 设备类型,0x2表示SENSOR_TYPE_ACCEL,加速度传感器// 该宏定义在../sdk/kernel/Documentation/devicetree/bindings/input/sensors/rk_sensor.txt type = <0x2>;// 中断引脚,用于指定设备的中断引脚// 示例:irq-gpio = <&gpio8 GPIO_A0 IRQ_TYPE_EDGE_FALLING>;// 原理图中MMA8452的中断引脚为GPIO1_C7// 其中,0x34表示GPIO1,打开从Android逆向生成的fdt.dts,查找gpio1,// 可以看到该节点的phandle属性值为0x34,// 0x17表示C7这支引脚,// 打开..sdk/kernel/include/dt-bindings/pinctrl/rockchip.h可以看到// #define RK_PC7  23,23转为十六进制为0x17,// 0x2表示下降沿触发// 打开../sdk/u-boot/include/dt-bindings/interrupt-controller/irq.h可以看到// #define IRQ_TYPE_EDGE_FALLING   2irq-gpio = <0x34 0x17 0x2>;// 中断使能,用于指定设备的中断是否使能// 0x1表示中断(irq),0x0表示上拉(pull mode)irq_enable = <0x1>;// 轮询延迟,用于指定设备的轮询延迟时间,单位为毫秒// 部分设备数据处理较复杂,采样-滤波-平滑等,为保证数据的可靠性// 需要一个最小处理周期,相关示例可参考脚注【e】poll_delay_ms = <0x1e>;// 布局,用于指定设备的参考坐标,这个变量名用的不好,让人不明所以// 通俗的讲就是类似于左手坐标系还是右手坐标系,// 当然实际可取数值为1~9,有9种,定义的比较复杂,下文会给出图示// 打开../sdk/kernel/drivers/input/sensors/sensor-dev.c// 可以看到pdata->layout共有8种情况,默认为0x01layout = <0x4>;
};

在对板子的重力传感器测试时,其设备树中“layout = <0x4>”,结果如下所示
在这里插入图片描述
可将程序(…/sdk/kernel/drivers/input/sensors/sensor-dev.c)中orientation数组的9个元素分为三组,分别构成矢量a(0,1,0),b(-1,0,0),c(0,0,1),(注:由于本人板子的z轴数值有问题,不保证此处分析准确性)

case 4:pdata->orientation[0] = 0;pdata->orientation[1] = 1;pdata->orientation[2] = 0;pdata->orientation[3] = -1;pdata->orientation[4] = 0;pdata->orientation[5] = 0;pdata->orientation[6] = 0;pdata->orientation[7] = 0;pdata->orientation[8] = 1;

分析完MMA8452在Android系统中的节点后,就可以尝试将该节点移植到板子的设备树中,在king-rk3399.dts同层目录下(…/sdk/kernel/arch/arm64/boot/dts/rockchip/rk3399)创建mma8452.dtsi子节点文件,添加节点配置如下,最后记得在king-rk3399.dts中引用该子节点文件(#include “mma8452.dtsi”),注:保险起见,在修改king-rk3399.dts前,记得先备份该文件

&i2c4 {status = "okay";mma8452@1d {status = "okay";compatible = "gs_mma8452";pinctrl-names = "default";pinctrl-0 = <&mma8452_int>;reg = <0x1d>;type = <0x2>;irq-gpio = <0x1 RK_PC7 IRQ_TYPE_EDGE_FALLING>;irq_enable = <0x1>;poll_delay_ms = <0x1e>;layout = <0x4>;};
};&pinctrl {g_sensor {mma8452_int:mma8452_int {// rockchip,pins = <0x1 0x17 0x0 0xbf>;rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>;};};
};

保存后在…/sdk/目录下执行./build.sh kernel,完成后将会在…/sdk/kernel/arch/arm64/boot/dts/rockchip/rk3399目录下更新king-rk3399.dtb文件并且还会在/home/username/ws/sdk/rockdev目录下更新boot.img,此时可利用dtc -I dtb -O dts king-rk3399.dtb -o king-rk3399-dtc.dts将更新的dtb文件反编译为dts查看是否有mma8452的节点,没有问题再将boot.img(其他文件若无改动可只单独烧录boot.img)烧录到king3399并重启

3 驱动分析

打开\02-软件文档\荣品文档\源码文件路径.xlsx可以看到,MMA8452的驱动源码位于:

…/kernel/drivers/input/sensors/accel/mma8452.c

这里主要涉及两个文件:sensor-dev.c 与 mma8452.c,此处以mma8452为切入点,将mma8452的加载流程进入如下梳理,由于SDK适配了很多类型的设备,因此文件的内容很多,框架稍显复杂,但都是常规操作,建议花点时间把整个加载处理流程过一遍,不然后边移植时无从入手(下述表格的阅读顺序为从上到下依次递进,从下依次到上也可)

functionnote
sdk/kernel/drivers/input/sensors/sensor-dev.c
EXPORT_SYMBOL(sensor_register_device);导出符号(函数或变量)的宏,使得这些符号可以被其他内核模块使用
int sensor_register_device判断传入的设备是否支持加载(存在且支持),只有在/sdk/kernel/include/linux/sensor-dev.h(enum sensor_id)中的设备才支持
sensor_probe(client, devid);从设备树中获取传感器(设备)硬件参数
static int sensor_probe
result = sensor_chip_init(sensor->client);
static int sensor_chip_init内核启动时,I2C 子系统会扫描所有已注册的 I2C 设备与驱动。内核会自动把匹配到的 I2C 设备信息封装到 struct i2c_client 结构体中,将设备 ID 信息封装到 const struct i2c_device_id 结构体里,然后把这两个结构体作为参数传递给 gsensor_mma8452_probe 函数。

而在上一步中从设备树中也读取了相应的参数,只有这两部分参数相吻合才可初始化
result = sensor_initial(sensor->client);
static int sensor_initial初始化
result = sensor->ops->init(client);init()未找到具体的实现方式
result = input_register_device(sensor->input_dev);/sdk/kernel/drivers/input/input.c
result = sensor_irq_init(sensor->client);
static int sensor_irq_init配置中断(中断引脚)、触发时间
irq = gpio_to_irq(client->irq);gpio_to_irq()未找到具体的实现方式
result = devm_request_threaded_irqdevm_request_threaded_irq()未找到具体的实现方式
/sdk/kernel/include/linux/interrupt.h
/sdk/kernel/kernel/irq/devres.c
result = gpio_request(client->irq, sensor->i2c_id->name);/sdk/kernel/drivers/gpio/gpiolib-legacy.c
result = sensor_misc_device_register(sensor, type);
static int sensor_misc_device_register根据类型(温度、光照或加速度等)指定设备操作函数(open、release)
sensor->fops.unlocked_ioctl = gsensor_dev_ioctl;
static long gsensor_dev_ioctl
copy_from_user(&rate, argp, sizeof(rate)设定采样频率
sensor_enable(sensor, SENSOR_ON);
static int sensor_enable启停设备
result = sensor_reset_rate(client, rate);
static int sensor_reset_rate设定采样频率
memcpy(&axis, &sensor->axis, sizeof(sensor->axis));获取数据
sensor_calibration_data_read(&sensor_cali_data)
static int sensor_calibration_data_read获取数据偏移(标定、补偿)
copy_to_user(argp, &axis, sizeof(axis)获取数据
sensor->fops.open = gsensor_dev_open;
static int gsensor_dev_open无操作(合并到gsensor_dev_ioctl)
sensor->fops.release = gsensor_dev_release;
static int gsensor_dev_release无操作(合并到gsensor_dev_ioctl)
/sdk/kernel/drivers/input/sensors/accel/mma8452.c
module_i2c_driver(gsensor_mma8452_driver);加载、卸载模块
static struct i2c_driver gsensor_mma8452_driveri2c设备操作函数
.probe = gsensor_mma8452_probe,
static int gsensor_mma8452_probe加载模块
return sensor_register_device(client
gsensor_mma8452_ops
static struct sensor_operate gsensor_mma8452_opsmma8452操作函数
.active = sensor_active,
static int sensor_active激活mma8452
4 驱动移植

如果将上边的加载处理流程过一遍会发现有很多步骤都可以简化,毕竟如此一套框架中适配的设备我们能够遇到的也就寥寥几个,况且框架也没有说明文档,用起来也并不称手,这里参考脚注【g】进行驱动移植,框不框架的都不是重点,得先让设备跑起来才是王道

移植前建议将mma8452手册通读一遍,里边有不少需要注意的地方,同时这个设备也有不少有用的功能值得开发与研究

移植的具体过程不赘述,逻辑都比较简单,而且本人已在程序中添加了大量注释

将文末仓库中的mma8452_module文件夹复制到虚拟机的home目录下,修改Makefile内的KERNEL_DIR 与 CROSS_COMPILE路径,这两个路径本系列博文之前有提到,可自行查看,修改完后在mma8452_module文件夹内执行 make,稍等片刻后将生成的mma8452_test.ko与mma8452_app传到板子的home目录下

scp mma8452_test.ko mma8452_app username@192.168.aaa.bbb:/home/username/xxx

在ubuntu中打开串口并开启颜色显示(下文会对此处做相关解释)

sudo minicom -s -c on

在板子上将路径切换到上述文件上传路径,并加载模块

sudo /sbin/insmod mma8452_test.ko

在板子上执行应用程序,该程序将读取1000次数据,周期为100ms

sudo ./mma8452_app 

此时将会在板子的终端打印AX、AY、AZ三组数据,同时在ubuntu的串口中打印相关日志
在这里插入图片描述
此时将会在ubuntu的minicom串口中打印如下信息
在这里插入图片描述
到此,设备的驱动就算完成了,当然这个驱动程序不管是驱动部分还是应用部分都略显粗糙,感兴趣的可以结合mma8452芯片手册与SDK的i2c驱动框架进行优化、完善与扩展,毕竟单纯的跑通没有任何实际意义

5 一些有趣的小东西
  1. vscode中的跳转

    在编辑软件中,我们会经常需要跳转到指定的函数、变量、宏定义等,在vscode中,我们可以使用快捷键Ctrl+鼠标左键进行跳转,同时也可以使用快捷键Alt+方向键反向跳转,这在阅读源码时非常有用,在进行驱动模块开发时可能会涉及到整个kernel下的driver与include下的文件,但是当我们把mma8452的相关文件都打开时,vscode并不能跳转到指定位置(由于本人的电脑性能一般,在开发驱动模块时都是在windows下,编辑完上传到ubuntu中),如果只是单纯地通过在工作空间中进行全局搜索查找效率会非常低,为解决这个问题可以进行如下操作,参考脚注【h】

    1. 下载并双击 mingw-get-setup0.6.2.exe,勾选mingw32-gcc-bin 与 mingw32-gcc-g+±bin

    2. 将MinGW添加到环境变量中(如:D:\MinGW\bin 添加到环境变量)

    3. 在F:\king3399\driver_source\路径下创建工程文件夹modutle_test,将本文提到的mma8452.c、mma8452.h等文件复制到module_test下,把module_test整个文件夹拖到vscode中,在vscode 中 ctrl + shift + P打开 c_cpp_properties.json,添加如下配置

      {"configurations": [{"name": "Win32","includePath": ["${workspaceFolder}/**","F:\\king3399\\driver_source\\" // ---添加相应目录---],"defines": ["_DEBUG","UNICODE","_UNICODE"]}],"version": 4
      }
      

      其中,在F:\king3399\driver_source\路径下包含linux与driver两个文件夹(也就是module_test同级目录下),这里是直接将ubuntu中的这两个文件夹下载到windows下

      linux来源于…/sdk/kernel/include/linux

      driver来源于…/sdk/kernel/driver

    4. 重启电脑,再次vscode打开工程,会报错,但可以正常引用不同目录下的文件并跳转

      引用示例如下:

      #include <./linux/interrupt.h>
      #include <./linux/i2c.h>
      #include <./linux/slab.h>
      #include <./linux/irq.h>
      #include <./linux/miscdevice.h>
      #include <./linux/gpio.h>
      #include <./linux/uaccess.h>
      #include <asm/atomic.h>
      #include <./linux/delay.h>
      #include <./linux/input.h>
      #include <linux/workqueue.h>
      #include <linux/freezer.h>
      #include <linux/of_gpio.h>
      #ifdef CONFIG_HAS_EARLYSUSPEND
      #include <linux/earlysuspend.h>
      #endif
      // #include <linux/sensor-dev.h>
      #include "./linux/sensor-dev.h"
      
  2. printk无法显示

    参考脚注【i】,出现这个原因是本系列的前一篇文章《King3399(ubuntu文件系统)KGDB配置与功能测试》中修改了…/sdk/kernel/arch/arm64/boot/dts/rockchip/rk3399-linux.dtsi中的bootargs,按照脚注中的解释就是“为什么我用telnet不行,而用tty终端就行?答:内核的printk把信息打到哪里去呢?这是在内核的命令行参数console=ttyXXX里指定死了,比如console=ttySAC0表示printk的信息输出到串口0”,解决这个问题的方法有两种,第一是将bootargs修改回来,由于本人需要经常使用kgdb调试,故没有修改,第二就是用串口模块将板子与虚拟机连接,并在虚拟机中打开minicom

  3. debug.h优雅地打印

    上一篇博文中留下了一个问题“调试卡在 printk”,当时的解决办法就是在模块中不使用printk,但实际我们在驱动模块开发时无法避免printk,在对mma8452的驱动源码进行移植时本人发现在mma8452.c中有一个“DBG(“%s:sensor int status :0x%x\n”,–func–,value);”,这玩意必然是printk套了个壳,但在源码中没有找到具体的实现方法,这样做的目的有二:第一,通过开关控制printk,在调试阶段启用,程序发布后禁用,提升性能,第二,有没有可能官方的SDK在使用kgdb调试时确实会卡在printk?

    debug.h文件内容很简单但确很实用,通过DEBUG_LEVEL、DEBUG_PATH与DEBUG_COLOR三个开关控制printk的显示方式,文件中有详细注释与使用方法,这里不再赘述细节,下图为实现效果(其中DEBUG_LEVEL为2,DEBUG_PATH为0,DEBUG_COLOR为1),注:须以sudo minicom -s -c on打开minicom

    在这里插入图片描述

  4. mma8452关键字

    回想写这篇博文的初衷是什么,单纯驱动mma8452?学习i2c驱动框架?貌似都不太准确,应该是通过mma8452学习i2c驱动框架,并积累与分享开发经验,毕竟真正使用mma8452这颗芯片的能有几人,能看到这篇博文有又有几人,以我个人举例,如果使用的芯片不是mma8452那么大概率不会去细读这篇博文

    在移植mma8452时在sensor-dev.h中发现一个很有用的枚举sensor_id,枚举中有大量设备型号,如果你有幸翻到本文 又 没有合适的开发例程 且 设备型号在下述枚举中,不妨看看文中的内容(其实主要也是怕自己以后遇到这些玩意不会搞)

    enum sensor_id {ID_INVALID = 0,ANGLE_ID_ALL,ANGLE_ID_KXTIK,ANGLE_ID_LIS3DH,ACCEL_ID_ALL,ACCEL_ID_LIS331,ACCEL_ID_LSM303DLX,ACCEL_ID_LIS3DH,ACCEL_ID_KXSD9,ACCEL_ID_KXTF9,ACCEL_ID_KXTIK,ACCEL_ID_KXTJ9,ACCEL_ID_BMA150,ACCEL_ID_BMA222,ACCEL_ID_BMA250,ACCEL_ID_ADXL34X,ACCEL_ID_MMA8450,ACCEL_ID_MMA845X,ACCEL_ID_MMA7660,ACCEL_ID_SC7660,ACCEL_ID_SC7A20,ACCEL_ID_SC7A30,ACCEL_ID_MPU6050,ACCEL_ID_MXC6225,ACCEL_ID_MXC6655XA,ACCEL_ID_DMARD10,ACCEL_ID_LSM303D,ACCEL_ID_MC3230,ACCEL_ID_MPU6880,ACCEL_ID_MPU6500,ACCEL_ID_LSM330,ACCEL_ID_BMA2XX,ACCEL_ID_STK8BAXX,ACCEL_ID_MIR3DA,ACCEL_ID_ICM2060X,ACCEL_ID_DA215S,ACCEL_ID_DA228E,ACCEL_ID_IAM20680,ACCEL_ID_ICM4260X,COMPASS_ID_ALL,COMPASS_ID_AK8975,COMPASS_ID_AK8963,COMPASS_ID_AK09911,COMPASS_ID_AK8972,COMPASS_ID_AMI30X,COMPASS_ID_AMI306,COMPASS_ID_YAS529,COMPASS_ID_YAS530,COMPASS_ID_HMC5883,COMPASS_ID_LSM303DLH,COMPASS_ID_LSM303DLM,COMPASS_ID_MMC314X,COMPASS_ID_HSCDTD002B,COMPASS_ID_HSCDTD004A,COMPASS_ID_AK09918,GYRO_ID_ALL,GYRO_ID_L3G4200D,GYRO_ID_L3G20D,GYRO_ID_EWTSA,GYRO_ID_K3G,GYRO_ID_MPU6500,GYRO_ID_MPU6880,GYRO_ID_LSM330,GYRO_ID_ICM2060X,GYRO_ID_IAM20680,GYRO_ID_ICM4260X,LIGHT_ID_ALL,LIGHT_ID_CM3217,LIGHT_ID_CM3218,LIGHT_ID_CM3232,LIGHT_ID_AL3006,LIGHT_ID_STK3171,LIGHT_ID_ISL29023,LIGHT_ID_AP321XX,LIGHT_ID_PHOTORESISTOR,LIGHT_ID_US5152,LIGHT_ID_STK3332,LIGHT_ID_STK3410,LIGHT_ID_EM3071X,LIGHT_ID_UCS14620,PROXIMITY_ID_ALL,PROXIMITY_ID_AL3006,PROXIMITY_ID_STK3171,PROXIMITY_ID_AP321XX,PROXIMITY_ID_STK3332,PROXIMITY_ID_STK3410,PROXIMITY_ID_EM3071X,PROXIMITY_ID_UCS14620,TEMPERATURE_ID_ALL,TEMPERATURE_ID_MS5607,PRESSURE_ID_ALL,PRESSURE_ID_BMA085,PRESSURE_ID_MS5607,HALL_ID_ALL,HALL_ID_OCH165T,SENSOR_NUM_ID,
    };
    

【a】 King3399(ubuntu文件系统)wifi设备树分析

【b】 King3399 SDK(ubuntu文件系统)编译简明教程

【c】 ADB安装及使用详解

【d】 Android系统中通过fdt文件系统反编译查看设备中真实生效的设备树配置信息

【e】 AL3220光感调试记录

【f】 RK3568 系列 6——Pinctrl 与 GPIO 的理解

【g】[野火]《嵌入式Linux驱动开发实战指南—基于LubanCat RK系列板卡》_20240727.pdf - 第 17 章 I2C 子系统–mpu6050 驱动实验

【h】vscode“检测到 #include 错误,请更新 includepath。”的问题解决办法

【i】printk无法输出到打印台问题和Linux日志文件详解

【j】 项目相关资料 pwd : 7rs4

相关文章:

King3399(ubuntu文件系统)iic(i2c)功能测试

0 引言 前面两篇博文简要介绍了板子上uart部分的内容&#xff0c;但在驱动开发时&#xff0c;我们遇到的外设更多的是以i2c或spi进行通信&#xff0c;本文将对king3399的i2c进行测试并对硬件电路、设备树与驱动程序进行分析 如果使用的i2c设备不是mma8452&#xff0c;建议先看…...

德思特新闻 | 德思特与es:saar正式建立合作伙伴关系

德思特新闻 2025年5月9日&#xff0c;德思特科技有限公司&#xff08;以下简称“德思特”&#xff09;与德国嵌入式系统专家es:saar GmbH正式达成合作伙伴关系。此次合作旨在将 es:saar 的先进嵌入式开发与测试工具引入中国及亚太市场&#xff0c;助力本地客户提升产品开发效率…...

基于原生JavaScript前端和 Flask 后端的Todo 应用

Demo地址&#xff1a;https://gitcode.com/rmbnetlife/todo-app-js-flask.git Python Todo 应用 这是一个使用Python Flask框架开发的简单待办事项(Todo)应用&#xff0c;采用前后端分离架构。本项目实现了待办事项的添加、删除、状态切换等基本功能&#xff0c;并提供了直观…...

一些Dify聊天系统组件流程图架构图

分享一些有助于深入理解Dify聊天模块的架构图 整体组件架构图 #mermaid-svg-0e2XalGLqrRbH1Jy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0e2XalGLqrRbH1Jy .error-icon{fill:#552222;}#mermaid-svg-0e2XalGLq…...

jq处理日志数据

介绍 jq 是一个轻量级且灵活的命令行 JSON 处理器。它允许你使用简单的过滤器来处理 JSON 数据&#xff0c;提取、操作和转换 JSON 文档。jq 是处理 JSON 数据的强大工具&#xff0c;特别适合在命令行环境中使用。 简单将就是&#xff1a;专门处理 json结构的字符串的工具 我…...

Matlab程序设计基础

matlab程序设计基础 程序设计函数文件1.函数文件的基本结构2.创建并使用函数文件的示例3.带多个输出的函数示例4.包含子函数的函数文件 流程控制1. if 条件语句2. switch 多分支选择语句3. try-catch 异常处理语句ME与lasterr 4. while 循环语句5. for 循环语句break和continue…...

MIT 6.S081 2020 Lab6 Copy-on-Write Fork for xv6 个人全流程

文章目录 零、写在前面一、Implement copy-on write1.1 说明1.2 实现1.2.1 延迟复制与释放1.2.2 写时复制 零、写在前面 可以阅读下 《xv6 book》 的第五章中断和设备驱动。 问题 在 xv6 中&#xff0c;fork() 系统调用会将父进程的整个用户空间内存复制到子进程中。**如果父…...

第304个Vulnhub靶场演练攻略:digital world.local:FALL

digital world.local&#xff1a;FALL Vulnhub 演练 FALL (digitalworld.local: FALL) 是 Donavan 为 Vulnhub 打造的一款中型机器。这款实验室非常适合经验丰富的 CTF 玩家&#xff0c;他们希望在这类环境中检验自己的技能。那么&#xff0c;让我们开始吧&#xff0c;看看如何…...

Unity 模拟高度尺系统开发详解——实现拖动、范围限制、碰撞吸附与本地坐标轴选择

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity 模拟高度尺系统开发详解——实现拖动、范围限制、碰撞吸附与本地坐标轴选择 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不…...

万字详解RTR RTSP SDP RTCP

目录 1 RTSP1.1 RTSP基本简介1.2 RSTP架构1.3 重点内容分析 2 RTR2.1 RTR简介2.2 RTP 封装 H.2642.3 RTP 解封装 H.2642.4 RTP封装 AAC2.5 RTP解封装AAC 3 SDP3.1 基础概念3.2 SDP协议示例解析3.3 重点知识 4 RTCP4.1 RTCP基础概念4.2 重点 5 总结 1 RTSP 1.1 RTSP基本简介 一…...

云服务器如何自动更新系统并保持安全?

云服务器自动更新系统是保障安全、修补漏洞的重要措施。下面是常见 Linux 系统&#xff08;如 Ubuntu、Debian、CentOS&#xff09;和 Windows 服务器自动更新的做法和建议&#xff1a; 1. Linux 云服务器自动更新及安全维护 Ubuntu / Debian 系统 手动更新命令 sudo apt up…...

训练中常见的运动强度分类

概述 有氧运动是耐力基础&#xff0c;乳酸阈值是耐力突破的关键&#xff0c;提升乳酸阈值可以延缓疲劳&#xff0c;无氧运动侧重速度和力量&#xff0c;混氧和最大摄氧量用于细化训练强度和评估潜力。 分类强度供能系统乳酸浓度训练目标有氧运动低&#xff08;60%-80% HR&…...

java 递归地复制文件夹及其所有子文件夹和文件

java 递归地复制文件夹及其所有子文件夹和文件 根据你的需求&#xff0c;下面是一个 Java 代码示例&#xff0c;用于递归地复制文件夹及其所有子文件夹和文件。由于你提到文件夹是数据层面的&#xff0c;这里假设你可以通过 folderById 来获取文件夹的相关信息&#xff0c;并且…...

[paddle]paddle2onnx无法转换Paddle3.0.0的json格式paddle inference模型

使用PDX 3.0rc1 训练时序缺陷检测后导出的模型无法转换 Informations (please complete the following information): Inference engine for deployment: PD INFERENCE 3.0-->onnxruntime Why convert to onnx&#xff1a;在端侧设备上部署 Paddle2ONNX Version: 1.3.1 解…...

React项目在ios和安卓端要做一个渐变色背景,用css不支持,可使用react-native-linear-gradient

以上有个模块是灰色逐渐到白的背景色过渡 如果是css&#xff0c;以下代码就直接搞定 background: linear-gradient(180deg, #F6F6F6 0%, #FFF 100%);但是在RN中不支持这种写法&#xff0c;那应该写呢&#xff1f; 1.引入react-native-linear-gradient插件&#xff0c;我使用的是…...

【数据分析】特征工程-特征选择

【数据分析】特征工程-特征选择 &#xff08;一&#xff09;方差过滤法1.1 消除方差为0的特征1.2 保留一半的特征1.3 特征是二分类时 &#xff08;二&#xff09;相关性过滤法2.1 卡方过滤2.2 F检验2.3 互信息法 &#xff08;三&#xff09;其他3.1 包装法3.2 嵌入法3.3 衍生特…...

第4节 Node.js NPM 使用介绍

本文介绍了 Node.js 中 NPM 的使用&#xff0c;我们先来了解什么是 NPM。 NPM是随同NodeJS一起安装的包管理工具&#xff0c;能解决NodeJS代码部署上的很多问题&#xff0c;常见的使用场景有以下几种&#xff1a; 允许用户从NPM服务器下载别人编写的第三方包到本地使用。允许…...

RK3399 Android7.1增加应用安装白名单机制

通过设置应用包名白名单的方式限制未授权的应用软件安装。 diff --git a/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java b/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java index af9a533..ca…...

uni-app 安卓消失的字符去哪里了?maxLength失效了!

前情提要 皮一下~这个标题我还蛮喜欢的嘿嘿嘿【附上一个自行思考的猥琐的笑容】 前段时间不是在开发uni-app的一个小应用嘛,然后今天测试发现,有一个地方在苹果是没有问题的,但是在安卓上出现了问题,附上安卓的截图 在这里我是有限制maxLength=50的,而且,赋值字符串到字…...

#AI短视频制作完整教程

目录 前期准备AI工具选择制作流程后期优化发布策略 前期准备 1. 确定视频主题和风格 内容定位&#xff1a;教育、娱乐、商业推广、个人分享目标受众&#xff1a;年龄、兴趣、平台偏好视频时长&#xff1a;15-60秒&#xff08;根据平台调整&#xff09;风格调性&#xff1a;…...

嵌入式STM32学习——串口USART 2.0(printf重定义及串口发送)

printf重定义&#xff1a; C语言里面的printf函数默认输出设备是显示器&#xff0c;如果要实现printf函数输出正在串口或者LCD显示屏上&#xff0c;必须要重定义标准库函数里调用的与输出设备相关的函数&#xff0c;比如printf输出到串口&#xff0c;需要将fputc里面的输出指向…...

【大模型】情绪对话模型项目研发

一、使用框架&#xff1a; Qwen大模型后端Open-webui前端实现使用LLamaFactory的STF微调数据集&#xff0c;vllm后端部署&#xff0c; 二、框架安装 下载千问大模型 安装魔塔社区库文件 pip install modelscope Download.py 内容 from modelscope import snapshot_downlo…...

Git 教程 | 如何将指定文件夹回滚到上一次或某次提交状态(命令详解)

在日常开发中&#xff0c;我们经常会遇到这样的情况&#xff1a; “我想把某个文件夹恢复到之前的状态&#xff0c;但又不想影响整个项目&#xff0c;怎么办&#xff1f;” 别担心&#xff01;这篇文章就教你如何用 Git 把项目中某个特定文件夹&#xff08;或文件&#xff09;回…...

【PCI】PCI入门介绍(包含部分PCIe讲解)

先解释一下寻址空间&#xff1a; 机器是32bit的话&#xff0c;意味着4G&#xff08;2的32次方&#xff09;寻址空间&#xff0c;内存条作为它的实际物理存储设备。大部分在跑内存程序运行&#xff0c;少部分用来存放其他东西。这是一个常见的4G寻址空间分布&#xff08;不一定是…...

Cloudera Manager 学习笔记

目录 1 基础概念与原理1.1 Cloudera Manager的主要作用是什么&#xff1f;1.2 与Ambari有何区别&#xff1f;1.3 Cloudera Manager 的核心功能和架构是什么&#xff1f;1.4 解释一下 Cloudera Manager 中的服务模型和角色?1.5 Cloudera Manager 是如何实现对 CDH 集群的集中管…...

Deepin 23.10安装Docker

个人博客地址&#xff1a;Deepin 23.10安装Docker | 一张假钞的真实世界 Deepin 是基于 Debian 的国产 Linux 发行版&#xff0c;安装 Docker Desktop 可能会遇到兼容性问题&#xff0c;因为 Docker Desktop 官方主要支持 Ubuntu/Debian/Red Hat/Fedora/Arch 等主流发行版&…...

使用PowerBI个人网关定时刷新数据

使用PowerBI个人网关定时刷新数据 PowerBI desktop连接mysql&#xff0c;可以设置定时刷新数据或在PowerBI服务中手动刷新数据,步骤如下&#xff1a; 第一步&#xff1a; 下载网关。以个人网关为例&#xff0c;如图 第二步&#xff1a; 双击网关&#xff0c;点击下一步&…...

数字人引领政务新风尚:智能设备助力政务服务

在信息技术飞速发展的今天&#xff0c;政府机构不断探索提升服务效率和改善服务质量的新途径。实时交互数字人在政务服务中的应用正成为一大亮点&#xff0c;通过将“数字公务员”植入各种横屏智能设备中&#xff0c;为民众办理业务提供全程辅助。这种创新不仅优化了政务大厅的…...

深入剖析Java类加载机制:双亲委派模型的突破与实战应用

引言&#xff1a;一个诡异的NoClassDefFoundError 某金融系统在迁移到微服务架构后&#xff0c;突然出现了一个诡异问题&#xff1a;在调用核心交易模块时&#xff0c;频繁抛出NoClassDefFoundError&#xff0c;但类明明存在于classpath中。经过排查&#xff0c;发现是由于不同…...

Kotlin JVM 注解详解

前言 Kotlin 作为一门现代 JVM 语言&#xff0c;提供了出色的 Java 互操作性。为了更好地支持与 Java 代码的交互&#xff0c;Kotlin 提供了一系列 JVM 相关注解。这些注解不仅能帮助我们控制 Kotlin 代码编译成 Java 字节码的行为&#xff0c;还能让我们的 Kotlin 代码更好地…...