温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

芯灵思Sinlinx A64 linux 通过设备树写LED

发布时间:2020-06-26 14:47:45 来源:网络 阅读:341 作者:sinlinx123 栏目:系统运维

开发平台 芯灵思Sinlinx A64

内存: 1GB 存储: 4GB
详细参数 https://m.tb.cn/h.3wMaSKm
开发板交流群 641395230

全志A64设备树结构体

#include <linux/of.h> //设备树里的每个设备及每个设备子节点都用此结构体描述

struct device_node { const char *name; const char *type; phandle phandle; const char *full_name; struct property *properties; //属性 struct property *deadprops; /* removed properties */ struct device_node *parent; //在设备子节点对象,指向属于的设备对象 struct device_node *child; //在设备对象,指向子节点 struct device_node *sibling; //指向同级的下一个对象. struct device_node *next; /* next device of same type */ //应是指向device_type是同样的对象 struct device_node *allnext; /* next in list of all nodes */ ... };

//下面函数用于获取设备树里的设备节点及设备子节点
extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
//通过名字查找相应的设备节点
static inline int of_get_child_count(const struct device_node *np);
//获取指定设备的子节点个数
extern struct device_node *of_find_node_by_path(const char *path);
//通过路径来获取设备节点,可用于获取设备子节点
extern struct device_node *of_find_node_by_type(struct device_node *from, const char *type); //通过指定的device_type来获取设备节点

//下面函数用于获取设备节点或设备子节点的属性

static inline int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) extern int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value); extern int of_property_read_u8_array(const struct device_node *np, const char *propname, u8 *out_values, size_t sz); extern int of_property_read_u16_array(const struct device_node *np, const char *propname, u16 *out_values, size_t sz); extern int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz); extern int of_property_read_u64(const struct device_node *np, const char *propname, u64 *out_value); extern int of_property_read_string(struct device_node *np, const char *propname, const char **out_string)

首先增加节点,修改dtsi文件。
vim /lichee/linux-3.10/arch/arm64/boot/dts/sun50iw1p1-pinctrl.dtsi
芯灵思Sinlinx A64 linux 通过设备树写LED

芯灵思Sinlinx A64 linux 通过设备树写LED

驱动代码:

 #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/cdev.h> #include <asm/uaccess.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/gpio.h> #include <linux/sys_config.h> #define MY_DEVICE_NAME "my_led_device" // 获取到设备树中到节点 static int gpio = -1; int get_irqno_from_node(void) { struct gpio_config config; struct device_node *np = of_find_node_by_path("/leds"); if(np){ printk("find node ok\n"); } else{ printk("find node failed\n"); } gpio = of_get_named_gpio_flags(nd, "gpios", i, (enum of_gpio_flags *)&config);// 从设备树中读取gpios的GPIO配置编号和标志 if(!gpio_is_valid(gpio)){ //判断该 GPIO 编号是否有效,有效gpio_request 则申请占用该 GPIO。如果初始化过程出错,需要调用 gpio_free 来释放之前申请过且成功的 GPIO printk("gpio isn't valid\n"); return -1; } if(gpio_request(gpio, "leds") < 0) printk("gpio request failed %d\n", gpio); gpio_direction_output(gpio, 1); //关灯 return 0; } static int my_open (struct inode *node, struct file *filp) { if(gpio) { printk("open ok\n"); } else { return -EINVAL; } return 0; } static ssize_t my_write (struct file *filp, const char __user *buf, size_t size, loff_t *off) { unsigned char val; copy_from_user(&val, buf, 1); printk(" gpl_dat address 0x%x\n",gpl_dat); if (val) { gpio_direction_output(gpio, 0); //关灯 printk("led on\n"); } else { gpio_direction_output(gpio, 1); //关灯 printk("led off\n"); } return 1; } static const struct file_operations my_led_fops = { //step 1 :定义file_operations结构体 .open = my_open, .write = my_write, }; //step 1 : static struct class *led_class; static struct cdev *pcdev; //定义一个cdev指针 static dev_t n_dev; //第一个设备号(包含了主和次) static int __init led_device_init(void) {//step 2 :注册 int ret = -1; pcdev = cdev_alloc();//分配cdev结构空间 if(pcdev == NULL) { printk(KERN_EMERG" cdev_alloc error\n"); ret = -ENOMEM; /* 分配失败 */ return ret; } //2. 动态申请设备号 ret = alloc_chrdev_region(&n_dev, 0 , 2, MY_DEVICE_NAME); if(ret < 0 ) { //释放前面成功的资源 kfree(pcdev); /*释放cdev结构空间 */ printk(KERN_EMERG"alloc_chrdev_region error\n"); return ret; } cdev_init(pcdev, &my_led_fops); //初始化cdev结构 /* 建立cdev和file_operations之间的连接 */ /* 或这样初始化cdev结构 pcdev->owner = THIS_MODULE; pcdev->ops = &my_led_fops; */ ret = cdev_add(pcdev, n_dev, 2) ;// 向内核里面添加一个驱动,注册驱动 if(ret < 0 ) { //释放前面成功的资源 unregister_chrdev_region(n_dev, 2); /* 释放前面申请的调和号*/ kfree(pcdev); /* 释放cdev结构空间 */ printk(KERN_EMERG"alloc_chrdev_region error\n"); return ret; } /*自动创建设备节点/dev/SinlinxA64_LED*/ led_class = class_create(THIS_MODULE, "myled"); device_create(led_class, NULL, n_dev, NULL, "SinlinxA64_LED"); get_irqno_from_node(); printk(KERN_EMERG"cdev ok\n"); return 0; } static void __exit led_device_exit(void) { //step 2 :注销 //注销cdev结构 cdev_del(pcdev); //释放设备号 unregister_chrdev_region(n_dev, 2); /*起始设备号(主、次) 连续的次设备号数量*/ //释放cdev结构空间 kfree(pcdev); device_destroy(led_class, n_dev); class_destroy(led_class); gpio_free(gpio); printk(KERN_EMERG"cdev_del ok\n"); } module_init(led_device_init); module_exit(led_device_exit); MODULE_LICENSE("GPL"); 

参考文章:https://blog.csdn.net/jklinux/article/details/82382066

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI