驱动程序
#include <linux/init.h> #include <linux/module.h> #include<linux/timer.h> #include<linux/of.h> #include<linux/of_gpio.h> /*myleds{ led1=<&gpioe 10 0>; led2=<&gpiof 10 0>; led3=<&gpioe 8 0>; };*/ //分配定时器对象 struct timer_list timer; struct device_node *dnode; int gpiono1,gpiono2,gpiono3; //定时器处理函数 int n=1; void timer_handler(struct timer_list *timer) { switch (n) { case 1: gpio_set_value(gpiono1,!gpio_get_value(gpiono1)); n++; break; case 2: gpio_set_value(gpiono2,!gpio_get_value(gpiono2)); n++; break; case 3: gpio_set_value(gpiono3,!gpio_get_value(gpiono3)); n=1; break; default: break; } mod_timer(timer,jiffies+HZ); } int gpio_led1(int gpiono,struct device_node *dnode) { //根据设备树节点解析gpio编号 gpiono= of_get_named_gpio(dnode,"led1",0); if(gpiono<0) { printk("解析led1_gpio编号失败\n"); return -EIO; } printk("解析led1_gpio编号成功\n"); //申请gpio编号 gpio_request(gpiono,NULL); //设置gpio为输出并且初始化数值为0 gpio_direction_output(gpiono,0); return gpiono; } int gpio_led2(int gpiono,struct device_node *dnode) { //根据设备树节点解析gpio编号 gpiono= of_get_named_gpio(dnode,"led2",0); if(gpiono<0) { printk("解析led2_gpio编号失败\n"); return -EIO; } printk("解析led2_gpio编号成功\n"); //申请gpio编号 gpio_request(gpiono,NULL); //设置gpio为输出并且初始化数值为0 gpio_direction_output(gpiono,0); return gpiono; } int gpio_led3(int gpiono,struct device_node *dnode) { //根据设备树节点解析gpio编号 gpiono= of_get_named_gpio(dnode,"led3",0); if(gpiono<0) { printk("解析led_3gpio编号失败\n"); return -EIO; } printk("解析led3_gpio编号成功\n"); //申请gpio编号 gpio_request(gpiono,NULL); //设置gpio为输出并且初始化数值为0 gpio_direction_output(gpiono,0); return gpiono; } static int __init mycdev_init(void) { //1.解析对应设备的设备树的节点 //2.根据解析得到的设备树节点结构体去解析得到对应的gpio编号 //3.向内核申请要使用的gpio编号 //4.设置gpio编号对应的gpio管脚为输出模式,并设置输出的是高电平还是低电平 //5.设置输出的是高电平还是低电平 //6.int gpio_get_value(unsigned gpio)是获取gpio编号对应灯的状态 //7.将gpio编号从内核中注销 //解析设备树节点 dnode=of_find_node_by_name(NULL,"myleds"); if(dnode==NULL) { printk("解析设备树节点失败\n"); return -EIO; } gpiono1=gpio_led1(gpiono1,dnode); gpiono2=gpio_led2(gpiono2,dnode); gpiono3=gpio_led3(gpiono3,dnode); //定时器初始化 //指定定时阈值 timer.expires=jiffies+HZ; timer_setup(&timer,timer_handler,0); add_timer(&timer); return 0; } static void __exit mycdev_exit(void) { gpio_free(gpiono1); gpio_free(gpiono2); gpio_free(gpiono3); del_timer(&timer); } module_init(mycdev_init); module_exit(mycdev_exit); MODULE_LICENSE("GPL");
设备树
/dts-v1/; #include "stm32mp157.dtsi" #include "stm32mp15xa.dtsi" #include "stm32mp15-pinctrl.dtsi" #include "stm32mp15xxac-pinctrl.dtsi" #include "stm32mp15xx-fsmp1x.dtsi" / { model = "HQYJ STM32MP157 FSMP1A Discovery Board"; compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; aliases { serial0 = &uart4; serial5 = &usart3; }; chosen { stdout-path = "serial0:115200n8"; }; reserved-memory { gpu_reserved: gpu@d4000000 { reg = <0xd4000000 0x4000000>; no-map; }; optee_memory: optee@0xde000000 { reg = <0xde000000 0x02000000>; no-map; }; }; mynode@0x12345678{ astring="hello 21091"; uint =<0xaabbccdd 0x11223344>; binarry=[00 0c 29 7b f9 be]; mixed ="hello",[11 22],<0x12345678>; }; leds{ core-leds{ led1=<&gpioz 5 0>; led2=<&gpioz 6 0>; led3=<&gpioz 7 0>; }; extend-leds{ led1=<&gpioe 10 0>; led2=<&gpiof 10 0>; led3=<&gpioe 8 0>; }; }; keyirq{ key_gpio = <&gpiof 9 0>,<&gpiof 7 0>,<&gpiof 8 0>; interrupt-parent = <&gpiof>; //指定中断的父节点 interrupts=<9 0>,<7 0>,<8 0>; //9中断的index号,0中断的触发方式(默认) }; myplatform{ compatible = "hqyj,hello2"; led1 = <&gpioe 10 0>; interrupt-parent = <&gpiof>; //指定中断的父节点 interrupts=<9 0>; }; mynode@0x12345678{ compatible = "hqyj,mynode"; astring = "hello 22101"; uint = <0xaabbccdd 0x11223344>; binarry = [00 0c 29 7b f9 be]; mixed = "hello",[11 22],<0x12345678>; }; myleds{ led1=<&gpioe 10 0>; led2=<&gpiof 10 0>; led3=<&gpioe 8 0>; }; }; &i2c1{ pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c1_pins_b>; pinctrl-1 = <&i2c1_sleep_pins_b>; i2c-scl-rising-time-ns = <100>; i2c-scl-falling-time-ns = <7>; status = "okay"; /delete-property/dmas; /delete-property/dma-names; si7006@40{ compatible = "sl,si7006"; reg = <0x40>; }; }; &spi4{ pinctrl-names = "default", "sleep"; pinctrl-0 = <&spi4_pins_b>; pinctrl-1 = <&spi4_sleep_pins_b>; cs-gpios = <&gpioe 11 0>; //片选 status = "okay"; m74hc595@0{ compatible = "hqyj,m74hc595"; reg = <0>; spi-max-frequency = <10000000>; //10Mhz }; };
通过GPIO子系统编写LED驱动,应用程序控制LED灯亮灭
最新推荐文章于 2023-08-01 19:23:47 发布
该代码实现了一个Linux内核模块,用于通过设备树配置GPIO来控制LED灯。它使用了定时器在三个LED之间切换状态,每次切换时改变一个LED的电平。驱动程序首先解析设备树节点获取GPIO编号,然后申请GPIO、设置为输出模式,并初始化。定时器处理函数根据状态切换LED,并通过`mod_timer`重新设置定时器。
摘要由CSDN通过智能技术生成