1、修改设备树
位置/home/milk/duo-buildroot-sdk-develop/build/boards/cv180x/cv1800b_milkv_duo_sd/dts_riscv
led1{
compatible = "led1";
gpio = <&porta 15 GPIO_ACTIVE_LOW>;
};
led_key{
compatible = "key1";
gpio = <&porta 14 GPIO_ACTIVE_LOW>;
status = "okay";
};
2、编译设备树
在/home/milk/duo-buildroot-sdk-develop下
source build/cvisetup.sh
defconfig cv1800b_milkv_duo_sd
build_uboot
编译完成后将新的cv1800b_milkv_duo_sd.dtb文件替换件SD卡具体操作
或者新生成镜像烧录到SD卡
使用ls /sys/firmware/devicetree/base/
查看一下设备树是否加载
3.编写platform平台总线driver
可以不使用platform,直接在init操作
代码如下
#include "linux/module.h"
#include "linux/init.h"
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of_irq.h>
#include <linux/timer.h>
struct device_node *key_node;//获取设备树节点
struct device_node *led_node;//获取设备树节点
int led_gpio = 0;
int key_gpio = 0;
int irq;
int value = 0;
struct timer_list mytime;
void mytimer_func(struct timer_list *timer)
{
value=!value;
if(led_gpio != 0)
gpio_set_value(led_gpio,value);
}
//需要设置 hz
static irqreturn_t key_handler(int irq,void *args)
{
printk("key_handler");
mod_timer(&mytime,jiffies +2);//20ms消抖
return IRQ_HANDLED;
}
int led_probe(struct platform_device *pdev)
{
int ret;
mytime.expires = jiffies+2;
timer_setup(&mytime,mytimer_func,0);
add_timer(&mytime);
key_node = of_find_node_by_path("/led_key");
led_node = of_find_node_by_path("/led1");
if(key_node == NULL|| led_node == NULL)
{
printk("node error\n");
return -1;
}
key_gpio = of_get_named_gpio(key_node,"gpio",0);//
led_gpio = of_get_named_gpio(led_node,"gpio",0);//
if(key_gpio < 0 || led_gpio < 0)
{
printk("gpio not found\n");
return -1;
}
printk("key_gpio = %d led_gpio = %d\n",key_gpio,led_gpio);
gpio_request(key_gpio,NULL);
gpio_direction_input(key_gpio);
gpio_request(led_gpio,NULL);
gpio_direction_output(led_gpio,0);
irq = gpio_to_irq(key_gpio);//方法一·获取中断号
printk("irq: %d\n", irq);
ret = request_irq(irq,key_handler,IRQF_TRIGGER_RISING,"led_key",NULL);
if(ret < 0)
{
printk("request_irq fail\n");
return -1;
}
return 0;
}
int led_remove(struct platform_device *pdev)
{
gpio_free(led_gpio);
gpio_free(key_gpio);
printk("led_remove\n");
return 0;
}
const struct platform_device_id led_idt_able={
.name = "led_test"
};
//如果有设备书节点 优先匹配设备属下的节点名称
const struct of_device_id of_led_table[]={
{.compatible = "key1"},
{}
};
struct platform_driver led_driver={
.probe = led_probe,
.remove = led_remove,
.driver = {
.owner = THIS_MODULE,
.name = "123",
.of_match_table = of_led_table
},
.id_table = &led_idt_able
};
static int __init led_driver_init(void)//j加载
{
int ret;
ret = platform_driver_register(&led_driver);
if(ret < 0)
{
printk("led_driver_register fail\n");
return ret;
}
printk("led_driver_register ok\n");
return 0;
}
static void led_driver_exit(void)//卸载
{
printk("byb byb world\n");
del_timer(&mytime);
free_irq(irq,NULL);
platform_driver_unregister(&led_driver);
}
module_init(led_driver_init);//绑定模块加载
module_exit(led_driver_exit);//绑定模块卸载
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lin");
MODULE_VERSION("v1.0");
4、编译
obj-m +=led_key.o
KDIR:=/home/milk/duo-buildroot-sdk-develop/linux_5.10/build/cv1800b_milkv_duo_sd
PWD?=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod *.symvers *.order *.mod.c *.cmd
5、下载到板子
使用scp或者nfs服务下载到板子,使用insmod安装.ko, lsmod 可以查看模块
scp led_key.ko root@192.168.42.1:/root/