芯灵思Sinlinx A64 linux 通过设备树写LED
发表于:2024-11-24 作者:千家信息网编辑
千家信息网最后更新 2024年11月24日,开发平台 芯灵思Sinlinx A64内存: 1GB 存储: 4GB详细参数 https://m.tb.cn/h.3wMaSKm开发板交流群 641395230全志A64设备树结构体#include
千家信息网最后更新 2024年11月24日芯灵思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安全错误
数据库的锁怎样保障安全
传统软件开发模式弊端
自动售货机配套软件开发
软件服务费和软件开发费用
校园网中有哪几种服务器
哪里有免费经济类数据库
服务器 有限元分析
软件开发讲方案的能力
软件开发报哪个专业
上海觅糖互联网科技公司
服务器进不了二三区
登录服务器不安全的方式
pdb 数据库
红讯软件开发
数据库数据模型有哪四种
点点到家网络技术
汇德行网络技术武汉有限公司
t3建立的数据库已存在
wow单机修改数据库
小公司做软件开发可以么
计算机网络安全教材
中国人民银行信息数据库会有什么
怎样检查服务器是否中毒
科大讯飞鼠标怎么扩大数据库
java软件开发地址
竞聘演讲稿网络技术部
文献检索数据库
备份数据库的方式
crm链接数据库
日本服务器数据丢失
计算机网络技术什么学科