芯灵思Sinlinx A64 linux 通过设备树写LED
发表于:2024-12-04 作者:千家信息网编辑
千家信息网最后更新 2024年12月04日,开发平台 芯灵思Sinlinx A64内存: 1GB 存储: 4GB详细参数 https://m.tb.cn/h.3wMaSKm开发板交流群 641395230全志A64设备树结构体#include
千家信息网最后更新 2024年12月04日芯灵思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安全错误
数据库的锁怎样保障安全
第一个自主研发的服务器
如何通过网络安全等级测评师
电脑网络技术应用考试成绩
网络安全 专家库
黄浦区数据软件开发品质保障
郑州越云网络技术有限公司
经济技术开发区光航网络技术
战疫情保网络安全
龙之谷2有哪些服务器
java数据库教程ppt
爱思服务器不能更新游戏怎么办
考勤系统软件开发计划书
天津嵌入式软件开发推荐
客户无法解析域名服务器
奥运会期间网络安全工作总结报告
法律英文版本数据库
淘宝 什么数据库
判断数据库的字符类型
火龙之心数据库
为什么总显示无法打开服务器
逃离塔克夫为什么没有服务器列表
盘锦璐麦特网络技术服务中心
sql 数据库隔离事务
lol登录服务器后游戏消失
跨数据库 guid
sql数据库数据库定期备份
综合性软件开发是什么意思
网络技术员的岗位介绍
数据库开发相关技术
5G+网络技术原理