一,前言
资源就的利用起来。linux下串口raw驱动(US100超声波)--Apple的学习笔记已经用US100玩了串口,US100还可以用GPIO和中断来玩。原理就是triq发送大于10us的高电平,然后echo脚就会回复高电平,高电平的维持时间,就代表了障碍物的距离。我之前用过gpio但是是老的API,所以本次的其中一个目标很清晰,就是用新的gpiod的API,那么头文件从 #include <linux/gpio.h>要改成 #include <linux/gpio/consumer.h>了。另外我对中断其实用的少,正好本次有机会用下,将来再详细了解。过程中觉得延时10us占用cpu而且不准,所以改成pwm来输出10us非常准。这个US100还比较有的玩,将来我还会再玩一次,重新设计驱动,并且将参数都设计到设备树中。工程已经上传我的gitee,见工程14。
二,设备树修改
依然使用上一篇博客的uart引脚,但是mode设置为7,设置为GPIO,然后设备树设置中断为both边缘触发。
ussensor_pins: pinmux_ussensor_pins {
pinctrl-single,pins = <
AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE7) //Echo:gpio0.14
AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE7) //Triq :gpio0.15
>;
};
ussensor:ussensor0 {
compatible = "applecai,AppleUS100";
interrupt-parent = <&gpio0>;
interrupts = <14 IRQ_TYPE_EDGE_BOTH>; /* input pin:gpio0.14 raise and falling*/
echo-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; /* input pin */
triq-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; /* output pin */
pinctrl-names = "default";
pinctrl-0 = <&ussensor_pins>;
status = "okay";
};
三,遇到的问题
- insmod产生bt。
对于不复杂的驱动,我倾向于使用misc。而misc的.name没有添加。导致bt。 - us2运行第二次后,产生bt
原因request_irq后,free_irq的devid参数传的不正确。后来直接用devm_request_irq就不用free了。另外irqflag参数我之前理解为填写边缘触发等,但是看了源码后才知道理解错误,参考其它driver,我这里改成了shared中断。
[ 38.242019] us100 device id is 10485820
[ 40.143138] genirq: Flags mismatch irq 61. 00000003 (us100-echo-gpio) vs. 00000003 (us100-echo-gpio)
[ 40.156380] ------------[ cut here ]------------
[ 40.161045] WARNING: CPU: 0 PID: 119 at kernel/irq/manage.c:1737 __free_irq+0xc0/0x330
[ 40.168996] Trying to free already-free IRQ 61
[ 40.173457] Modules linked in: US100_drv(O) [last unloaded: US100_drv]
[ 40.180028] CPU: 0 PID: 119 Comm: us2 Tainted: G O 5.4.61 #39
[ 40.187105] Hardware name: Generic AM33XX (Flattened Device Tree)
[ 40.193224] Backtrace:
[ 40.195694] [<c010e59c>] (dump_backtrace) from [<c010e934>] (show_stack+0x20/0x24)
[ 40.203300] r7:00000000 r6:60070093 r5:00000000 r4:c0ebd85c
[ 40.208991] [<c010e914>] (show_stack) from [<c0964ec8>] (dump_stack+0xe8/0x120)
[ 40.216344] [<c0964de0>] (dump_stack) from [<c0140b84>] (__warn+0xd0/0x108)
[ 40.223340] r10:60070013 r9:c0b255b4 r8:c0e05148 r7:000006c9 r6:00000009 r5:c01a9328
[ 40.231203] r4:c0b2551c r3:00000000
[ 40.234797] [<c0140ab4>] (__warn) from [<c0140f7c>] (warn_slowpath_fmt+0x9c/0xc0)
[ 40.242315] r7:00000009 r6:c01a9328 r5:000006c9 r4:c0b2551c
[ 40.248002] [<c0140ee4>] (warn_slowpath_fmt) from [<c01a9328>] (__free_irq+0xc0/0x330)
[ 40.255956] r9:0000003d r8:dd03e0d0 r7:dd03e068 r6:00000000 r5:dd03e000 r4:00000000
[ 40.263734] [<c01a9268>] (__free_irq) from [<c01a963c>] (free_irq+0x48/0xa8)
[ 40.270816] r10:bf0011c4 r9:c0e9c220 r8:dd25f5d0 r7:dd20e900 r6:00000000 r5:dd03e000
[ 40.278678] r4:00000000
[ 40.281235] [<c01a95f4>] (free_irq) from [<bf0000f0>] (AppleUS100_open+0x60/0x94 [US100_drv])
[ 40.289798] r7:dd20e900 r6:c0e9c234 r5:fffffff0 r4:bf0022c0
[ 40.295488] [<bf000090>] (AppleUS100_open [US100_drv]) from [<c06564c4>] (misc_open+0x124/0x17c)
[ 40.304310] r5:0000003c r4:bf002000
[ 40.307911] [<c06563a0>] (misc_open) from [<c02f57b0>] (chrdev_open+0xe8/0x1bc)
[ 40.315255] r10:00000000 r9:00000000 r8:dd20e900 r7:c0e05148 r6:dd25f5d0 r5:c0a5c750
[ 40.323117] r4:de298880 r3:c06563a0
[ 40.326719] [<c02f56c8>] (chrdev_open) from [<c02ebc90>] (do_dentry_open+0x134/0x414)
[ 40.334586] r10:dd20e900 r9:00000000 r8:c02f56c8 r7:dd20e908 r6:dd25f5d0 r5:00000000
[ 40.342447] r4:dd20e900
[ 40.344997] [<c02ebb5c>] (do_dentry_open) from [<c02ed7dc>] (vfs_open+0x3c/0x40)
[ 40.352428] r9:00000000 r8:00000000 r7:00000002 r6:00000000 r5:00000000 r4:dd31fe90
[ 40.360211] [<c02ed7a0>] (vfs_open) from [<c0301740>] (path_openat+0x2b4/0x13e0)
[ 40.367642] [<c030148c>] (path_openat) from [<c0303b9c>] (do_filp_open+0x80/0xec)
[ 40.375160] r10:00000142 r9:dd31e000 r8:00000001 r7:c0e05148 r6:dd31ff50 r5:dd31fe90
[ 40.383023] r4:00000003
[ 40.385571] [<c0303b1c>] (do_filp_open) from [<c02edaec>] (do_sys_open+0x168/0x218)
[ 40.393263] r8:fffff000 r7:de113000 r6:ffffff9c r5:c0e05148 r4:00000003
[ 40.399997] [<c02ed984>] (do_sys_open) from [<c02edbe4>] (sys_openat+0x1c/0x20)
[ 40.407341] r10:00000142 r9:dd31e000 r8:c01011c4 r7:00000142 r6:00085460 r5:00010134
[ 40.415202] r4:00010c30
[ 40.417752] [<c02edbc8>] (sys_openat) from [<c0101000>] (ret_fast_syscall+0x0/0x28)
[ 40.425441] Exception stack(0xdd31ffa8 to 0xdd31fff0)
[ 40.430518] ffa0: 00010c30 00010134 ffffff9c 0005e160 00000000 00000000
[ 40.438736] ffc0: 00010c30 00010134 00085460 00000142 00000000 00000000 00000000 be9c6d24
[ 40.446950] ffe0: 000858b0 be9c6ce0 000104d0 00027a14
[ 40.452022] ---[ end trace 16d04ba7b422cf72 ]---
/dev/AppleUS100: Device or resource busy
- gpio初始化引脚不正确
devm_gpiod_get_optional的第3个参数可以在请求引脚的同时设置电平和方向。一开始不知道,写的是0,所以insmod后不正确。 - do_gettimeofday函数在内核中没有了。
用get_ktime获取ns值。
参考网址:https://blog.csdn.net/rikeyone/article/details/98498526 - 中断thread下半部进入不了.
中断上半部return的参数不对。 - 时间采集不准。
采集时间放入上半部后相对正确。 - 采集时间差偏小
参见如下第七和第八章节的测试。暂时原因未知,猜测为ktime不准。
四,第一步驱动加载及probe测试成功
查看设备号
# cd /sys/class/misc/
# ls
AppleUS100 loop-control vga_arbiter
cpu_dma_latency ubi_ctrl
# cd AppleUS100/
# ls
dev power subsystem uevent
# cat dev
10:60
查看驱动
# ls -al
total 0
drwxr-xr-x 3 root root 0 Jan 1 00:03 .
drwxr-xr-x 21 root root 0 Jan 1 00:03 ..
lrwxrwxrwx 1 root root 0 Jan 1 00:03 driver -> ../../../bus/platform/drivers/appleUS100
-rw-r--r-- 1 root root 4096 Jan 1 00:03 driver_override
-r--r--r-- 1 root root 4096 Jan 1 00:03 modalias
lrwxrwxrwx 1 root root 0 Jan 1 00:03 of_node -> ../../../firmware/devicetree/base/ussensor0
drwxr-xr-x 2 root root 0 Jan 1 00:03 power
lrwxrwxrwx 1 root root 0 Jan 1 00:03 subsystem -> ../../../bus/platform
-rw-r--r-- 1 root root 4096 Jan 1 00:03 uevent
驱动框架,irq识别正确,APP open和close正常
# insmod US100_drv.ko
[ 101.155869] irq num is 61
[ 139.464344] us100 probe!
[ 139.469573] appleUS100 ussensor0: GPIO lookup for consumer triq
[ 139.475713] appleUS100 ussensor0: using device tree for GPIO lookup
[ 139.482121] of_get_named_gpiod_flags: parsed 'triq-gpios' property of node '/ussensor0[0]' - status (0)
[ 139.491590] gpio gpiochip0: Persistence not supported for GPIO 15
[ 139.497749] no flags found for triq
[ 139.501265] miscUS100_dev.cmdpin is 15
[ 139.501273] appleUS100 ussensor0: GPIO lookup for consumer echo
[ 139.511012] appleUS100 ussensor0: using device tree for GPIO lookup
[ 139.517374] of_get_named_gpiod_flags: parsed 'echo-gpios' property of node '/ussensor0[0]' - status (0)
[ 139.526854] gpio gpiochip0: Persistence not supported for GPIO 14
[ 139.533002] no flags found for echo
[ 139.536513] miscUS100_dev.echopin is 14
# ./us2
[ 139.539789] us100 device id min is 60
ok
# ./us2
[ 141.592831] irq num is 61
ok
^C
# ./us2
[ 147.848742] irq num is 61
ok
# cat /proc/interrupts
CPU0
16: 1626 INTC 68 Level gp_timer
18: 0 INTC 3 Level arm-pmu
19: 8 INTC 12 Level 49000000.edma_ccint
21: 0 INTC 14 Level 49000000.edma_ccerrint
28: 0 INTC 96 Level 44e07000.gpio
29: 313 INTC 72 Level 44e09000.serial
30: 146 INTC 70 Level 44e0b000.i2c
42: 0 INTC 98 Level 4804c000.gpio
43: 37 INTC 64 Level mmc0
45: 0 INTC 30 Level 4819c000.i2c
46: 0 INTC 32 Level 481ac000.gpio
47: 0 INTC 62 Level 481ae000.gpio
48: 46 INTC 28 Level mmc1
52: 1273 INTC 41 Level 4a100000.ethernet
53: 763 INTC 42 Level 4a100000.ethernet
56: 0 44e07000.gpio 6 Edge 48060000.mmc cd
57: 0 INTC 7 Level tps65217-irq
IPI0: 0 CPU wakeup interrupts
IPI1: 0 Timer broadcast interrupts
IPI2: 0 Rescheduling interrupts
IPI3: 0 Function call interrupts
IPI4: 0 CPU stop interrupts
IPI5: 0 IRQ work interrupts
IPI6: 0 completion interrupts
Err: 0
# rmmod US100_drv.ko
五,GPIO引脚控制测试通过
在框架中的open添加了GPIOD及申请IRQ的代码,在read函数中添加控制triq引脚电平及延时10us。示波器测试通过,并且echo脚有正确的返回。
# insmod US100_drv1.ko
[ 322.604133] irq num is 61
[ 384.515868] us100 probe!
[ 384.521094] appleUS100 ussensor0: GPIO lookup for consumer triq
[ 384.527249] appleUS100 ussensor0: using device tree for GPIO lookup
[ 384.533660] of_get_named_gpiod_flags: parsed 'triq-gpios' property of node '/ussensor0[0]' - status (0)
[ 384.543162] gpio gpiochip0: Persistence not supported for GPIO 15
[ 384.549298] miscUS100_dev.cmdpin is 15
[ 384.549307] appleUS100 ussensor0: GPIO lookup for consumer echo
[ 384.559046] appleUS100 ussensor0: using device tree for GPIO lookup
[ 384.565426] of_get_named_gpiod_flags: parsed 'echo-gpios' property of node '/ussensor0[0]' - status (0)
[ 384.574912] gpio gpiochip0: Persistence not supported for GPIO 14
[ 384.581043] miscUS100_dev.echopin is 14
# ./us2
[ 384.584160] us100 device id min is 60
ok
# ./us2
[ 390.780167] irq num is 61
ok
image.png
六,将10us的高电平有io控制改为PWM控制通过
用pwm控制就非常准。
image.png
七,用示波器来验证时间差,时间差偏小。
# ./us2
ok
[ 417.304899] last is 417302210883,now is 417302621549,dis:410666
[ 417.307555] dis:69
distance is 69
410666ns,但是示波器显示为424us
image.png
八,用ftrace验证时间差
ftrace硬中断上半部会进入2次,时间差为58.201850-58.200688=1162us。ktime记录的时间为ns,一个为58198435298,另外一个为58199583631,差值为1148us。也说明ktime函数偏小。
# insmod US100_drv6.ko
[ 19.069904] US100_drv6: loading out-of-tree module taints kernel.
[ 19.078024] us100 probe!
[ 19.080617] appleUS100 ussensor0: GPIO lookup for consumer triq
[ 19.086760] appleUS100 ussensor0: using device tree for GPIO lookup
[ 19.093172] of_get_named_gpiod_flags: parsed 'triq-gpios' property of node '/ussensor0[0]' - status (0)
[ 19.102676] gpio gpiochip0: Persistence not supported for GPIO 15
[ 19.108812] miscUS100_dev.cmdpin is 15
[ 19.108822] appleUS100 ussensor0: GPIO lookup for consumer echo
[ 19.118563] appleUS100 ussensor0: using device tree for GPIO lookup
[ 19.124945] of_get_named_gpiod_flags: parsed 'echo-gpios' property of node '/ussensor0[0]' - status (0)
[ 19.134430] gpio gpiochip0: Persistence not supported for GPIO 14
[ 19.140561] miscUS100_dev.echopin is 14
# mount -t debugfs nodev /sys/kernel/debug
# cd /sys/kernel/debug/tracing
# echo 0 > tracing_on
# echo us100_irq_handler > set_ftrace_filter
# echo function > current_tracer
# echo 1 > tracing_on
# cd /usr/study/
# ./us2
ok
[ 19.142810] us100 device id min is 60
[ 58.201906] last is 58198435298,now is 58199583631,dis:1148333
distance is 195
# cd /sys/kernel/debug/tracing
# cat trace | head -20
# tracer: function
#
# entries-in-buffer/entries-written: 2/2 #P:1
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
<idle>-0 [000] d.h. 58.200688: us100_irq_handler <-__handle_irq_event_percpu
<idle>-0 [000] d.h. 58.201850: us100_irq_handler <-__handle_irq_event_percpu
九,多进程验证
今天在昨天的基础上将自定义的设备结构体从全局变量,改成了通过指针传递,然后在open函数通过struct miscUS100 *dev = container_of(filp->private_data,struct miscUS100, miscdev);来获取,依然放入工程14,文件名为US100_drv8.c。并且添加了锁,当一个进程打开文件处理后,其它进程不能打开此文件。测试通过。
Welcome to Buildroot
buildroot login: root
# cd /usr/study/
# insmod US100_drv8.ko
[ 13.282705] US100_drv8: loading out-of-tree module taints kernel.
[ 13.290724] appleUS100 ussensor0: GPIO lookup for consumer echo
[ 13.296902] appleUS100 ussensor0: using device tree for GPIO lookup
[ 13.303306] of_get_named_gpiod_flags: parsed 'echo-gpios' property of node '/ussensor0[0]' - status (0)
[ 13.312806] gpio gpiochip0: Persistence not supported for GPIO 14
# ./us2
[ 13.318939] miscUS100_dev.echopin is 14
[ 14.755360] appleUS100 ussensor0: irq num is 61
[ 14.772369] appleUS100 ussensor0: last is 14768965835,now is 14770115335,dis:1149500
distance is 195
# ./us2 &
# [ 22.226804] appleUS100 ussensor0: irq num is 61
[ 22.291166] appleUS100 ussensor0: last is 22288684127,now is 22288873502,dis:189375
distance is 32
./us2
[ 23.939970] US100 is busy
/dev/AppleUS100: Device or resource busy
# ./us2
[ 25.143762] US100 is busy
/dev/AppleUS100: Device or resource busy
# ./us2
[ 27.298167] US100 is busy
/dev/AppleUS100: Device or resource busy
[1]+ Done ./us2
# ./us2
[ 32.293119] appleUS100 ussensor0: irq num is 61
[ 32.358104] appleUS100 ussensor0: last is 32355629628,now is 32355829503,dis:199875
distance is 33
^C
# ./us2
[ 36.579675] appleUS100 ussensor0: irq num is 61
[ 36.644860] appleUS100 ussensor0: last is 36642381796,now is 36642584587,dis:202791
distance is 34
^C
# ./us2
[ 39.601888] appleUS100 ussensor0: irq num is 61
[ 39.667097] appleUS100 ussensor0: last is 39664613254,now is 39664820879,dis:207625
distance is 35
网友评论