BeagleBone Black 通过内核驱动程序中断

Man*_*gío 5 c++ kernel-module embedded-linux beagleboard beagleboneblack

我正在尝试处理中断,但由于 ioread32,我收到以下错误。

\n\n

正如我在《AM335x SitaraTM 处理器 - 技术参考手册》的“25.3.3 中断特性”一章中看到的

\n\n

为了在 GPIO 引脚上发生定义的事件(电平或逻辑转换)时向主机处理器生成中断请求,必须按如下方式对 GPIO 配置寄存器进行编程:

\n\n

\xe2\x80\xa2 必须在 GPIO_IRQSTATUS_SET_0 和/或 GPIO_IRQSTATUS_SET_1 寄存器中启用 GPIO 通道的中断。

\n\n

\xe2\x80\xa2 必须在 GPIO_LEVELDETECT0、GPIO_LEVELDETECT1、GPIO_RISINGDETECT 和 GPIO_FALLINGDETECT 寄存器中选择输入 GPIO 上触发中断请求的预期事件。

\n\n
[ 1737.604270] Loading hello_interrupts module...\n[ 1737.604426] HI: Initialized GPIO #36 to IRQ #164\n[ 1737.604478] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa1ac02c\n[ 1737.612611] Internal error: : 1028 [#1] SMP THUMB2\n[ 1737.617696] Modules linked in: hello_interrupts(O+) g_multi libcomposite omap_rng mt7601Usta(O) [last unloaded: hello_interrupts]\n[ 1737.630128] CPU: 0    Tainted: G           O  (3.8.13-bone67 #1)\n[ 1737.636513] PC is at hello_interrupts_start+0x8b/0x123 [hello_interrupts]\n[ 1737.643717] LR is at _raw_read_unlock+0x7/0x8\n[ 1737.648340] pc : [<bf8f508c>]    lr : [<c04cfaf7>]    psr: 80000033\n[ 1737.648340] sp : df3fde60  ip : 00000034  fp : c006a001\n[ 1737.660481] r10: 00000001  r9 : de594200  r8 : bf8f5001\n[ 1737.666011] r7 : 00000000  r6 : bf8f30b8  r5 : 00000000  r4 : fa1ac000\n[ 1737.672920] r3 : 48000000  r2 : 00000000  r1 : 481adfff  r0 : fa1ac000\n[ 1737.679839] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA Thumb  Segment user\n[ 1737.687569] Control: 50c5387d  Table: 9f740019  DAC: 00000015\n[ 1737.693655] Process insmod (pid: 3040, stack limit = 0xdf3fc240)\n[ 1737.700025] Stack: (0xdf3fde60 to 0xdf3fe000)\n[ 1737.704659] de60: bf8f30b8 00000000 00400100 df3fc000 c08b5740 c000867f 00000000 de5c3640\n[ 1737.713323] de80: 00000000 00000000 00400100 bf8f326c bf8f3260 00000001 bf8f32a8 00000001\n[ 1737.721988] dea0: c006a001 c006bd31 bf8f326c 00007fff c0069101 e0dd7000 e0dd6fff bf8f3260\n[ 1737.730655] dec0: 00000000 b6f7dd50 df3fc000 bf8f33b4 e0dd6691 c02520d0 6e72656b 00006c65\n[ 1737.739320] dee0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000\n[ 1737.747993] df00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000\n[ 1737.756662] df20: 00000000 00000000 00000000 c0790a68 20000033 000016a8 b6fa2000 b6f7dd50\n[ 1737.765331] df40: 00000080 c000c9e4 df3fc000 00000000 00000000 c006c26f e0dd5000 000016a8\n[ 1737.774000] df60: e0dd5ae0 e0dd599f e0dd64c8 000003c8 000004c8 00000000 00000000 00000000\n[ 1737.782670] df80: 0000001c 0000001d 00000014 00000012 00000010 00000000 00000000 b6fc0088\n[ 1737.791339] dfa0: b6fc0d00 c000c841 00000000 b6fc0088 b6fa2000 000016a8 b6f7dd50 00000002\n[ 1737.800008] dfc0: 00000000 b6fc0088 b6fc0d00 00000080 00000000 b6f7dd50 000016a8 00000000\n[ 1737.808671] dfe0: 00000000 beb7969c b6f77b07 b6f01fd4 80000010 b6fa2000 c0c92420 c0c92440\n[ 1737.817378] [<bf8f508c>] (hello_interrupts_start+0x8b/0x123 [hello_interrupts]) from [<c000867f>] (do_one_initcall+0x1f/0xf4)\n[ 1737.829367] [<c000867f>] (do_one_initcall+0x1f/0xf4) from [<c006bd31>] (load_module+0x10d5/0x15b0)\n[ 1737.838872] [<c006bd31>] (load_module+0x10d5/0x15b0) from [<c006c26f>] (sys_init_module+0x63/0x88)\n[ 1737.848379] [<c006c26f>] (sys_init_module+0x63/0x88) from [<c000c841>] (ret_fast_syscall+0x1/0x46)\n[ 1737.857867] Code: 4825 f3d4 debb e036 (6ac5) f3bf \n[ 1737.884765] ---[ end trace cbd53ac03b070f86 ]---\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的代码:

\n\n
#include <linux/module.h>\n#include <linux/kernel.h>\n#include <linux/init.h>\n\n#include <linux/gpio.h>\n#include <linux/interrupt.h>\n#include <linux/io.h>\n#include <linux/irq.h>\n\nMODULE_AUTHOR("MGE");\nMODULE_DESCRIPTION("A sample driver using interrupts");\nMODULE_LICENSE("GPL");\n\n// GPIO Bank 2\n#define GPIO2_START_ADDR 0x481AC000\n#define GPIO2_SIZE (0x481ADFFF - GPIO2_START_ADDR)\n\n// GPIO memory-mapped register addresses.\n#define GPIO_IRQSTATUS_0 0x2C\n#define GPIO_IRQSTATUS_1 0x30\n#define GPIO_RISINGDETECT 0x148\n#define GPIO_FALLINGDETECT 0x14C\n\n#define PIN_A_GPIO 36\n#define PIN_A_FLAGS GPIOF_IN\n#define PIN_A_LABEL "HI_PIN_A"\n\nstatic irqreturn_t irq_handler_pin_a (int irq, void *dev_id) {\n  printk (KERN_INFO "Hello from irq_handler_pin_a...\\n");\n\n  return IRQ_HANDLED;\n}\n\nstatic int __init hello_interrupts_start (void) {\n  int retval, irq, regval;\n  void __iomem *mem;\n\n  printk (KERN_INFO "Loading hello_interrupts module...\\n");\n\n  /**\n   * Request the GPIO lines for the IRQ channels.\n   */\n  retval = gpio_request_one(PIN_A_GPIO, PIN_A_FLAGS, PIN_A_LABEL);\n\n  if (retval) {\n    printk (KERN_ERR "HI: Error: Failed to request GPIO pin#%i for IRQ (error %i)\\n", PIN_A_GPIO, retval);\n\n//    return -retval;\n  }\n\n  irq = gpio_to_irq (PIN_A_GPIO);\n  if (irq < 0) {\n    printk (KERN_ERR "HI: ERROR: Failed to obtain IRQ number for GPIO #%i (error %i)\\n", PIN_A_GPIO, irq);\n\n//    return -irq;\n  }\n\n  retval = request_irq (irq, irq_handler_pin_a, 0 /*IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING*/, PIN_A_LABEL, NULL);\n  irq_set_irq_type (irq, IRQ_TYPE_EDGE_BOTH);\n\n  if (retval) {\n    printk (KERN_ERR "HI: ERROR: The requested IRQ line#%i from GPIO#%i (error %i)\\n", irq, PIN_A_GPIO, retval);\n\n//    return -retval;\n  }\n  else {\n    printk (KERN_INFO "HI: Initialized GPIO #%i to IRQ #%i\\n", PIN_A_GPIO, irq);\n  }\n\n  /**\n   * Setup the IRQ registers with the appropriate values.\n   */\n  mem = ioremap(GPIO2_START_ADDR, GPIO2_SIZE);\n  if(!mem) {\n    printk (KERN_ERR "HI: ERROR: Failed to remap memory for GPIO Bank 2 IRQ pin configuration.\\n");\n    return 0;\n  }\n\n  // Enable the IRQ ability for GPIO_66.\n  regval = ioread32 (mem + GPIO_IRQSTATUS_0);\n  regval |= (1 << 2);\n  iowrite32 (regval, mem + GPIO_IRQSTATUS_0);\n\n  regval = ioread32 (mem + GPIO_IRQSTATUS_1);\n  regval |= (1 << 2);\n  iowrite32 (regval, mem + GPIO_IRQSTATUS_1);\n\n  // Set GPIO_66 for rising and falling edge detection.\n  regval = ioread32 (mem + GPIO_RISINGDETECT);\n  regval |= (1 << 2);\n  iowrite32(regval, mem + GPIO_RISINGDETECT);\n\n  regval = ioread32 (mem + GPIO_FALLINGDETECT);\n  regval |= (1 << 2);\n  iowrite32 (regval, mem + GPIO_FALLINGDETECT);\n\n  // Release the mapped memory.\n  iounmap (mem);\n\n  return 0;\n}\n\nstatic void __exit hello_interrupts_end(void) {\n\n  printk ("HI: Releasing IRQ resources...\\n");\n\n  free_irq (gpio_to_irq (PIN_A_GPIO), NULL);\n  gpio_free (PIN_A_GPIO);\n\n  printk (KERN_INFO "Goodbye hello_interrupts!\\n");\n}\n\nmodule_init (hello_interrupts_start);\nmodule_exit (hello_interrupts_end);\n
Run Code Online (Sandbox Code Playgroud)\n\n

有什么想法吗?\n谢谢

\n

Man*_*gío 4

问题是 GPIO2 模块时钟被禁用。

《AM335x SitaraTM 处理器 - 技术参考手册》的“8.1.12.1.30 CM_PER_GPIO2_CLKCTRL 寄存器(偏移 = B0h)[复位 = 30000h]”

位 1-0:控制强制时钟的管理方式。0x0 = 禁用:模块被软件禁用。对模块的任何 OCP 访问都会导致错误,除非是由模块唤醒(异步唤醒)引起的。0x1 = RESERVED_1:保留 0x2 = ENABLE:模块已明确启用。接口时钟(如果不用于功能)可以根据时钟域状态进行门控。功能时钟保证保持存在。只要在此配置中,电源域睡眠转换就不会发生。0x3 = 保留:保留