开发平台 芯灵思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 <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

芯灵思Sinlinx A64 linux 通过设备树写LED驱动(附参考代码,未测试)的更多相关文章

  1. 芯灵思Sinlinx A64 Linux&qt编译安装

    开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 详细参数 https://m.tb.cn/h.3wMaSKm 开发板交流群 641395230 前提条件搭建好CentOS环境 ...

  2. 芯灵思Sinlinx A64开发板 Linux内核等待队列poll ---阻塞与非阻塞

    开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm 开发板交流群 641395230 阻塞:阻塞调用是指调用结果 ...

  3. 芯灵思Sinlinx A64开发板Linux内核定时器编程

    开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm 开发板交流群 641395230 Linux 内核定时器是内 ...

  4. 芯灵思Sinlinx A64 开发板移植SQLite3

    开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm 开发板交流群 641395230 首先到 http://ww ...

  5. 芯灵思Sinlinx A64开发板设置qt程序自启动

    开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm 对于开发板开机启动程序的设置可以这样做通过串口连接开发板 v ...

  6. Linux 获取设备树源文件(DTS)里描述的资源

    Linux 获取设备树源文件(DTS)里的资源 韩大卫@吉林师范大学 在linux使用platform_driver_register() 注册 platform_driver 时, 需要在 plat ...

  7. Linux 获取设备树源文件(DTS)里的资源【转】

    本文转载自:http://blog.csdn.net/keleming1/article/details/51036000 http://www.cnblogs.com/dyllove98/archi ...

  8. Linux dts 设备树详解(二) 动手编写设备树dts

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 前言 硬件结构 设备树dts文件 前言 在简单了解概念之后,我们可以开始尝试写一个 ...

  9. Linux dts 设备树详解(一) 基础知识

    Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 1 前言 2 概念 2.1 什么是设备树 dts(device tree)? 2. ...

随机推荐

  1. jQuery 命名空间的使用

    jQuery 命名空间的使用: 1.利用 trigger 触发子元素带命名空间的事件,那么父元素带相同命名空间的事件也会被触发,而父元素没有命名空间的事件不会被触发. 2.利用 trigger 触发子 ...

  2. intellij idea 程序包不可见问题

    刚用intellij idea不久,出现了个程序包不可见的问题. 原因:jdk9的问题,用的是jdk9就会出现这个问题. 解决办法:把jsk9换成jdk1.8就能解决.

  3. JSON与JS对象的区别

    <script> var obj2={};//这只是JS对象 var obj3={width:100,height:200};/*这跟JSON就更不沾边了,只是JS的 对象 */ var ...

  4. 集成学习-Adaboost

    Adaboost 中文名叫自适应提升算法,是一种boosting算法. boosting算法的基本思想 对于一个复杂任务来说,单个专家的决策过于片面,需要集合多个专家的决策得到最终的决策,通俗讲就是三 ...

  5. API响应

    保证API响应的正确性,就是你需要做的大部分工作.postman的response viewer部分会协助你完成该工作且使其变得简单. 一个API的响应包含body,headers,响应状态码.pos ...

  6. ubuntu16.04运行ros的时候编译工作空间catkin_make出现的一个问题Could not find a package configuration file provided by

    最近在进行ros里面的gazebo仿真之前需要对自己创建的工作空间进行编译,但是进行编译的时候输入catkin_make出现如下错误提示 查阅ROS问答社区之后发现两个比较有用的链接,如下 https ...

  7. ueditor的用法

    今天做了一下百度富文本编辑器,遇到了一些问题,现在来总结一下: (1)jQuery没有引用,解决方法:引用jQuery并且放在所有的js前面 (2)没有报错,但是样式显示不出来.解决方法:css引用的 ...

  8. 2018-计算机系机试(第二批)-C-数字字符个数

    C. 数字字符个数 单点时限: 1.0 sec 内存限制: 256 MB 输入一行信息,输出其中包含的数字字符个数. 例如:输入 a<4 >w,输出 1 . 输入格式 一行字符串 (可能含 ...

  9. 常见的CSS

    /***** Selector Hacks ******/ /* IE6 and below */ * html #uno { color: red } /* IE7 */ *:first-child ...

  10. 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contai

    之前一直使用的mysql5,突然换成8之后,有许多地方不一样,今天就碰到一个. 在使用sql语句创建表时,报错:  1055 - Expression #1 of ORDER BY clause is ...