芯灵思Sinlinx A64 linux 通过设备树写LED
发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,开发平台 芯灵思Sinlinx A64内存: 1GB 存储: 4GB详细参数 https://m.tb.cn/h.3wMaSKm开发板交流群 641395230全志A64设备树结构体#include
千家信息网最后更新 2025年12月01日芯灵思Sinlinx A64 linux 通过设备树写LED
开发平台 芯灵思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
驱动代码:
#include #include #include #include #include #include #include #include #include #include #include #include #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
设备
节点
结构
对象
指向
空间
驱动
有效
成功
函数
属性
分配
开发
个数
代码
内存
内核
动态
参数
同级
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
热门应用软件开发 90年代
服务器2g和4g差别
数据库象集表达式差集表达式
上海系统软件开发中心
软件开发要不要去甲方
上海知才网络技术公司
海口软件开发行业怎么样
已泄露的网站数据库
电力企业数据库运维方案
kindle软件开发
网络安全安天集团
数据库插入语句的重复数据问题
加强网络安全信息管理和应用
西安智协网络技术有限公司
密云区网络技术开发哪家好
网络安全的知识绘画
有没有培训软件开发
软件开发人员工作描述
通信网络安全的内容
珠海电商软件开发常见问题
网络安全学院的师资力量
怎样加入我的世界的服务器
网络技术专业学徒
手机网游如何重设服务器
用友数据库修改存货编码
网络安全教育内容设计
kindle软件开发
福州金鑫网络技术
网络安全与国家发展的作文
学软件开发去哪找工作