hello.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#define GPIO 192 //PG0
#define GPIO_INT_NAME "pg0_int"
#define GPIO_HIGH gpio_get_value(GPIO)
#define GPIO_LOW (gpio_get_value(GPIO) == 0)
short int irq_any_gpio = 0;
int count =0;
enum { falling, rising } type;
static irqreturn_t r_irq_handler(int irq, void *dev_id)
{
count++;
printk(KERN_DEBUG "interrupt received (irq: %d)\n", irq);
if (irq == gpio_to_irq(GPIO))
{
type = GPIO_LOW ? falling : rising;
if(type == falling)
{
printk("gpio pin is low\n");
}
else
printk("gpio pin is high\n");
}
return IRQ_HANDLED;
}
void r_int_config(void) {
if (gpio_request(GPIO, GPIO_INT_NAME ))
{
printk("GPIO request failure: %s\n", GPIO_INT_NAME );
return;
}
if ( (irq_any_gpio = gpio_to_irq(GPIO)) < 0 ) {
printk("GPIO to IRQ mapping failure %s\n",GPIO_INT_NAME );
return;
}
printk(KERN_NOTICE "Mapped int %d\n", irq_any_gpio);
if (request_irq(irq_any_gpio,(irq_handler_t ) r_irq_handler, IRQF_TRIGGER_FALLING , GPIO_INT_NAME, NULL))
{
printk("Irq Request failure\n");
return;
}
return;
}
void r_int_release(void) {
free_irq(gpio_to_irq(GPIO), NULL);
gpio_free(GPIO);;
return;
}
int init_module1(void)
{
printk("<1>Hello World\n");
r_int_config();
return 0;
}
module_init(init_module1); // Do some better naming
module_exit(r_int_release);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("whycan");
# dmesg
[ 26.204637] interrupt received (irq: 71)
[ 26.204660] gpio pin is low
[ 26.919621] interrupt received (irq: 71)
[ 26.919642] gpio pin is low
[ 27.429350] interrupt received (irq: 71)
[ 27.429359] gpio pin is low
[ 27.694572] interrupt received (irq: 71)
[ 27.694586] gpio pin is low
[ 27.906767] interrupt received (irq: 71)
[ 27.906779] gpio pin is low
把PG0 IO脚下拉就会进入中断, 输出上面的信息.
参考链接: https://stackoverflow.com/questions/25507750/detecting-interrupt-on-gpio-in-kernel-module
参考链接: 试一试 Ubuntu 下编译第一个 Hello World 驱动并运行
http://whycan.com/t_5233.html
以下由 @哇酷小二 2021-04-15 添加:
------------------------
Makefile:
obj-m = hello.o
编译指令 (根据实际情况修改指令):
ARCH=arm CROSS_COMPILE=/opt/buildroot/output/host/bin/arm-linux-gnueabihf- make -C /opt/buildroot/output/build/linux-zero-5.2.y/ M=${PWD} modules
编译日志:
$ ARCH=arm CROSS_COMPILE=/opt/buildroot/output/host/bin/arm-linux-gnueabihf- make -C /opt/buildroot/output/build/linux-zero-5.2.y/ M=${PWD} modules
make: Entering directory '/opt/buildroot/output/build/linux-zero-5.2.y'
CC [M] /opt/buildroot/modules/test1/hello.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: modpost: missing MODULE_LICENSE() in /opt/buildroot/modules/test1/hello.o
see include/linux/module.h for more information
CC /opt/buildroot/modules/test1/hello.mod.o
LD [M] /opt/buildroot/modules/test1/hello.ko
make: Leaving directory '/opt/buildroot/output/build/linux-zero-5.2.y'
离线
离线
605364021 说:晕哥,我在4.13y内核分支已有相关驱动的情况下,想做个只控制PG0的.ko核模块通过insmod来实现控制led灯的闪烁,这样可以实现?
想用.ko内核模块实现led灯的闪烁,需要重新向内核注册设备吗?还是直接在.ko模块上实现相关功能就行?
不用了,参考:
https://whycan.cn/t_1853.html#p11754
https://stackoverflow.com/questions/10812858/how-to-use-timers-in-linux-kernel-device-drivers
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>
MODULE_LICENSE("GPL");
static struct timer_list my_timer;
void my_timer_callback( unsigned long data )
{
/* do your timer stuff here */
}
int init_module(void)
{
/* setup your timer to call my_timer_callback */
setup_timer(&my_timer, my_timer_callback, 0);
/* setup timer interval to 200 msecs */
mod_timer(&my_timer, jiffies + msecs_to_jiffies(200));
return 0;
}
void cleanup_module(void)
{
/* remove kernel timer when unloading module */
del_timer(&my_timer);
return;
}
如果搞定了, 希望可以贴个完整的上来参考一下.
最好把这个中断也加上,按下GPIO 触发闪烁, 或者调整闪烁频率.
离线