linux下GPIO中断驱动US100传感器--Apple的学习笔记

一,前言

资源就的利用起来。linux下串口raw驱动(US100超声波)--Apple的学习笔记已经用US100玩了串口,US100还可以用GPIO和中断来玩。原理就是triq发送大于10us的高电平,然后echo脚就会回复高电平,高电平的维持时间,就代表了障碍物的距离。我之前用过gpio但是是老的API,所以本次的其中一个目标很清晰,就是用新的gpiod的API,那么头文件从 #include 要改成 #include 了。另外我对中断其实用的少,正好本次有机会用下,将来再详细了解。过程中觉得延时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";
};

三,遇到的问题

  1. insmod产生bt。
    对于不复杂的驱动,我倾向于使用misc。而misc的.name没有添加。导致bt。
  2. 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] [] (dump_backtrace) from [] (show_stack+0x20/0x24)
[   40.203300]  r7:00000000 r6:60070093 r5:00000000 r4:c0ebd85c
[   40.208991] [] (show_stack) from [] (dump_stack+0xe8/0x120)
[   40.216344] [] (dump_stack) from [] (__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] [] (__warn) from [] (warn_slowpath_fmt+0x9c/0xc0)
[   40.242315]  r7:00000009 r6:c01a9328 r5:000006c9 r4:c0b2551c
[   40.248002] [] (warn_slowpath_fmt) from [] (__free_irq+0xc0/0x330)
[   40.255956]  r9:0000003d r8:dd03e0d0 r7:dd03e068 r6:00000000 r5:dd03e000 r4:00000000
[   40.263734] [] (__free_irq) from [] (free_irq+0x48/0xa8)
[   40.270816]  r10:bf0011c4 r9:c0e9c220 r8:dd25f5d0 r7:dd20e900 r6:00000000 r5:dd03e000
[   40.278678]  r4:00000000
[   40.281235] [] (free_irq) from [] (AppleUS100_open+0x60/0x94 [US100_drv])
[   40.289798]  r7:dd20e900 r6:c0e9c234 r5:fffffff0 r4:bf0022c0
[   40.295488] [] (AppleUS100_open [US100_drv]) from [] (misc_open+0x124/0x17c)
[   40.304310]  r5:0000003c r4:bf002000
[   40.307911] [] (misc_open) from [] (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] [] (chrdev_open) from [] (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] [] (do_dentry_open) from [] (vfs_open+0x3c/0x40)
[   40.352428]  r9:00000000 r8:00000000 r7:00000002 r6:00000000 r5:00000000 r4:dd31fe90
[   40.360211] [] (vfs_open) from [] (path_openat+0x2b4/0x13e0)
[   40.367642] [] (path_openat) from [] (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] [] (do_filp_open) from [] (do_sys_open+0x168/0x218)
[   40.393263]  r8:fffff000 r7:de113000 r6:ffffff9c r5:c0e05148 r4:00000003
[   40.399997] [] (do_sys_open) from [] (sys_openat+0x1c/0x20)
[   40.407341]  r10:00000142 r9:dd31e000 r8:c01011c4 r7:00000142 r6:00085460 r5:00010134
[   40.415202]  r4:00010c30
[   40.417752] [] (sys_openat) from [] (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
  1. gpio初始化引脚不正确
    devm_gpiod_get_optional的第3个参数可以在请求引脚的同时设置电平和方向。一开始不知道,写的是0,所以insmod后不正确。
  2. do_gettimeofday函数在内核中没有了。
    用get_ktime获取ns值。
    参考网址:https://blog.csdn.net/rikeyone/article/details/98498526
  3. 中断thread下半部进入不了.
    中断上半部return的参数不对。
  4. 时间采集不准。
    采集时间放入上半部后相对正确。
  5. 采集时间差偏小
    参见如下第七和第八章节的测试。暂时原因未知,猜测为ktime不准。事后网上搜索下了下有用hrtimer是高精度的。将来有机会再了解下原理适用下。

四,第一步驱动加载及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
#              | |       |   ||||       |         |
          -0     [000] d.h.    58.200688: us100_irq_handler <-__handle_irq_event_percpu
          -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

你可能感兴趣的:(linux下GPIO中断驱动US100传感器--Apple的学习笔记)