当前位置: 首页> 财经> 金融 > 甘肃省疫情防控最新文件_网站平台推广语录_盐城seo排名_公司网络营销实施计划

甘肃省疫情防控最新文件_网站平台推广语录_盐城seo排名_公司网络营销实施计划

时间:2025/8/28 5:17:40来源:https://blog.csdn.net/weixin_44651073/article/details/142829268 浏览次数:0次
甘肃省疫情防控最新文件_网站平台推广语录_盐城seo排名_公司网络营销实施计划
1.修改设备树,添加子节点

在根节点“/”下创建一个名为“alphaled”的子节点,打开 imx6ull-alientek-emmc.dts 文件, 在根节点“/”最后加入一个alphaled子节点

属性#address-cells 和#size-cells 都为 1,表示 reg 属性中起始地址占用一个字长 (cell),地址长度也占用一个字长(cell)。

属性 compatbile 设置 alphaled 节点兼容性为“atkalpha-led”

属性 status 设置状态为“okay”。

reg 属性非常重要!reg 属性设置了驱动里面所要使用的寄存器物理地址,比 如“0X020C406C 0X04”表示 I.MX6ULL 的 CCM_CCGR1 寄存器,其中寄存器首地 址为 0X020C406C,长度为 4 个字节。

子节点如下:

alphaled {#address-cells = <1>;#size-cells = <1>;compatible = "atkalpha-led";status = "okay";reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */0X0209C000 0X04 /* GPIO1_DR_BASE */0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
};

编译设备树,用命令make dts,将重新编译的dtb文件拷贝进tftpboot目录内 ,重新启动linux内核,用cd /proc/device-tree;ls命令查看。发先新增加的设备树节点alphaled,修改设备树成功。

==============================

2.of函数进行访问设备树

设备都是以节点的形式“挂”到设备树上的,因此要想获取这个设备的其他属性信息,必须先获取到这个设备的节点。Linux 内核使用 device_node 结构体来描述一个节点,此结构体定 义在文件 include/linux/of.h 中,定义如下:

 of_find_node_by_name 函数
of_find_node_by_name 函数通过节点名字查找指定的节点,函数原型如下:

struct device_node *of_find_node_by_name(struct device_node *from,const char *name);
//参数说明:
from :开始查找的节点,如果为 NULL, 表示从根节点开始查找整个设备树。
name :要查找的节点名字。
返回值: 找到的节点,如果为 NULL 表示查找失败。


of_find_node_by_type 函数
of_find_node_by_type 函数通过 device_type 属性查找指定的节点,函数原型如下:

 struct device_node *of_find_node_by_type(struct device_node *from,const char *type);
//参数说明:
from :开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
type :要查找的节点对应的 type 字符串,也就是 device_type 属性值。
返回值: 找到的节点,如果为 NULL 表示查找失败。


of_find_compatible_node 函数
of_find_compatible_node 函数根据 device_type 和 compatible 这两个属性查找指定的节点, 函数原型如下:

struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, 
const char *compatible)


of_find_matching_node_and_match 函数
of_find_matching_node_and_match 函数通过 of_device_id 匹配表来查找指定的节点,函数原
型如下:

struct device_node *of_find_matching_node_and_match(struct device_node *from,const struct of_device_id *matches,const struct of_device_id **match)
函数参数和返回值含义如下:
from :开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
matches : of_device_id 匹配表,也就是在此匹配表里面查找节点。
match : 找到的匹配的 of_device_id 。
返回值: 找到的节点,如果为 NULL 表示查找失败


of_find_node_by_path 函数
of_find_node_by_path 函数通过路径来查找指定的节点,函数原型如下:

inline struct device_node *of_find_node_by_path(const char *path)
函数参数和返回值含义如下:
path :带有全路径的节点名,可以使用节点的别名,比如“ /backlight ”就是 backlight 这个
节点的全路径。
返回值: 找到的节点,如果为 NULL 表示查找失败


 查找父/子节点的 OF 函数
Linux 内核提供了几个查找节点对应的父节点或子节点的 OF 函数,我们依次来看一下。

of_get_parent 函数
of_get_parent 函数用于获取指定节点的父节点 ( 如果有父节点的话 ) ,函数原型如下:

struct device_node *of_get_parent(const struct device_node *node)
函数参数和返回值含义如下:
node :要查找的父节点的节点。
返回值: 找到的父节点。

of_get_next_child 函数

of_get_next_child 函数用迭代的方式查找子节点,函数原型如下:
struct device_node *of_get_next_child(const struct device_node *node,struct device_node *prev)
函数参数和返回值含义如下:
node :父节点。
prev :前一个子节点,也就是从哪一个子节点开始迭代的查找下一个子节点。可以设置为
NULL ,表示从第一个子节点开始。
返回值: 找到的下一个子节点。

==============================

3.设备信息结构体

创建设备结构体 dtsled_dev。定义一个设备结构体变量 dtsled,此变量表示 led 设备。

在设备结构体 dtsled_dev 中添加了成员变量 nd,nd 是 device_node 结构体类型指 针,表示设备节点。如果我们要读取设备树某个节点的属性值,首先要先得到这个节点,一般 在设备结构体中添加 device_node 指针变量来存放这个节点。

/* dtsled设备结构体 */
struct dtsled_dev{dev_t devid;			/* 设备号 	 */struct cdev cdev;		/* cdev 	*/struct class *class;		/* 类 		*/struct device *device;	/* 设备 	 */int major;				/* 主设备号	  */int minor;				/* 次设备号   */struct device_node *nd  /*设备节点*/
};struct dtsled_dev dtsled;	/* led设备 */

==============================

4.入口函数实现

注册字符设备 ——>添加字符设备 ——>自动创建设备节点——>获取设备树属性内容

of函数获取设备树属性内容:

通过 of_find_node_by_path 函数,路径查找得到 alphaled 节点,返回dtsled.nd,给后续其他的 OF 函数使用 

通过 of_find_property 函数获取 alphaled 节点的 compatible 属性,返回值为 property 结构体类型指针变量,property 的成员变量 value 表示属性值

通过 of_property_read_string 函数获取 alphaled 节点的 status 属性值

通过 of_property_read_u32_array 函数获取alphaled 节点的 reg 属性所有值, 并且将获取到的值都存放到 regdata 数组中。将获取到的 reg 属性值依次输出到终端上

通过采用of_iomap代替上一节的ioremap函数完成内存映射。

=============================

5.驱动函数:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>#define DTSLED_CNT      1           /* 设备号个数 */
#define DTSLED_NAME     "dtsled"    /* 名字 */#define LEDOFF  0       /* 关闭 */
#define LEDON   1       /* 打开 *//* 地址映射后的虚拟地址指针 */
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;/* desled设备结构体 */
struct dtsled_dev{dev_t   devid;          /* 设备号 */struct cdev cdev;       /* 字符设备 */struct class *class;     /* 类 */struct device *device;   /* 设备 */int major;              /* 主设备号 */int minor;              /* 次设备号 */struct device_node *nd; /* 设备节点 */
};struct dtsled_dev dtsled;   /* led设备 *//* LED灯打开/关闭 */
static void led_switch(u8 sta)
{u32 val = 0;if(sta == LEDON) {val = readl(GPIO1_DR);val &= ~(1 << 3);            /* bit3清零,打开LED灯 */writel(val, GPIO1_DR); } else if(sta == LEDOFF) {val = readl(GPIO1_DR);val |= (1 << 3);            /* bit3清零,打开LED灯 */writel(val, GPIO1_DR);}
}static int dtsled_open(struct inode *inode, struct file *filp)
{filp->private_data = &dtsled;return 0;
}static int dtsled_release(struct inode *inode, struct file *filp)
{struct dtsled_dev *dev = (struct dtsled_dev*)filp->private_data;return 0;
}static ssize_t dtsled_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos)
{struct dtsled_dev *dev = (struct dtsled_dev*)filp->private_data;int retvalue;unsigned char databuf[1];retvalue = copy_from_user(databuf, buf, count);if(retvalue < 0) {return -EFAULT;}/* 判断是开灯还是关灯 */led_switch(databuf[0]);return 0;
}/* dtsled字符设备操作集 */
static const struct file_operations dtsled_fops = {.owner = THIS_MODULE,.write	= dtsled_write,.open	= dtsled_open,.release= dtsled_release,
};/* 入口 */
static int __init dtsled_init(void)
{int ret  = 0;const char *str;u32 regdata[10];u8 i = 0;unsigned int val = 0;/* 注册字符设备 *//* 1,申请设备号 */dtsled.major = 0;   /* 设备号由内核分配 */if(dtsled.major) {  /* 定义了设备号 */dtsled.devid = MKDEV(dtsled.major, 0);ret = register_chrdev_region(dtsled.devid, DTSLED_CNT, DTSLED_NAME);} else {            /* 没有给定设备号 */ret = alloc_chrdev_region(&dtsled.devid, 0, DTSLED_CNT, DTSLED_NAME);dtsled.major = MAJOR(dtsled.devid);dtsled.minor = MINOR(dtsled.devid);}   if(ret < 0) {goto fail_devid;}/* 2,添加字符设备 */dtsled.cdev.owner = THIS_MODULE;cdev_init(&dtsled.cdev, &dtsled_fops);ret = cdev_add(&dtsled.cdev, dtsled.devid, DTSLED_CNT);if(ret < 0) goto fail_cdev;/* 3,自动创建设备节点 */dtsled.class =  class_create(THIS_MODULE, DTSLED_NAME);if (IS_ERR(dtsled.class)) {ret = PTR_ERR(dtsled.class);goto fail_class;}dtsled.device = device_create(dtsled.class, NULL, dtsled.devid, NULL, DTSLED_NAME);if (IS_ERR(dtsled.device)) {ret = PTR_ERR(dtsled.device);goto fail_device;}/* 获取设备树属性内容 */dtsled.nd = of_find_node_by_path("/alphaled");if (dtsled.nd == NULL) {    /* 失败 */ret = -EINVAL;goto fail_findnd;}/* 获取属性 */ret = of_property_read_string(dtsled.nd, "status", &str);if(ret < 0) {goto fail_rs;} else {printk("status = %s\r\n", str);}ret = of_property_read_string(dtsled.nd, "compatible", &str);if(ret < 0) {goto fail_rs;} else {printk("compatible = %s\r\n", str);}#if 0ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 10);if(ret < 0) {goto fail_rs;} else {printk("reg data:\r\n");for(i = 0; i < 10; i++) {printk("%#X ", regdata[i]);}printk("\r\n");}/* LED灯初始化 *//* 1,初始化LED灯,地址映射 */IMX6U_CCM_CCGR1 = ioremap(regdata[0], regdata[1]);SW_MUX_GPIO1_IO03 = ioremap(regdata[2], regdata[3]);SW_PAD_GPIO1_IO03 = ioremap(regdata[4], regdata[5]);GPIO1_DR = ioremap(regdata[6], regdata[7]);GPIO1_GDIR = ioremap(regdata[8], regdata[9]);
#endifIMX6U_CCM_CCGR1 = of_iomap(dtsled.nd, 0);SW_MUX_GPIO1_IO03 = of_iomap(dtsled.nd, 1);SW_PAD_GPIO1_IO03 = of_iomap(dtsled.nd, 2);GPIO1_DR = of_iomap(dtsled.nd, 3);GPIO1_GDIR = of_iomap(dtsled.nd, 4);/* 2,初始化 */val = readl(IMX6U_CCM_CCGR1);val &= ~(3 << 26);  /* 先清除以前的配置bit26,27 */val |= 3 << 26;     /* bit26,27置1 */writel(val, IMX6U_CCM_CCGR1);writel(0x5, SW_MUX_GPIO1_IO03);     /* 设置复用 */writel(0X10B0, SW_PAD_GPIO1_IO03);  /* 设置电气属性 */val = readl(GPIO1_GDIR);val |= 1 << 3;              /* bit3置1,设置为输出 */writel(val, GPIO1_GDIR);val = readl(GPIO1_DR);val |= (1 << 3);            /* bit3置1,关闭LED灯 */writel(val, GPIO1_DR);return 0;fail_rs:
fail_findnd:device_destroy(dtsled.class, dtsled.devid);
fail_device:class_destroy(dtsled.class);
fail_class:cdev_del(&dtsled.cdev);
fail_cdev:unregister_chrdev_region(dtsled.devid, DTSLED_CNT);
fail_devid:return ret;}/* 出口 */
static void __exit dtsled_exit(void)
{unsigned int val = 0;val = readl(GPIO1_DR);val |= (1 << 3);            /* bit3清零,打开LED灯 */writel(val, GPIO1_DR);/* 1,取消地址映射 */iounmap(IMX6U_CCM_CCGR1);iounmap(SW_MUX_GPIO1_IO03);iounmap(SW_PAD_GPIO1_IO03);iounmap(GPIO1_DR);iounmap(GPIO1_GDIR);/* 删除字符设备 */cdev_del(&dtsled.cdev);/* 释放设备号 */unregister_chrdev_region(dtsled.devid, DTSLED_CNT);/* 摧毁设备*/device_destroy(dtsled.class, dtsled.devid);/* 摧毁类 */class_destroy(dtsled.class);
}/* 注册驱动和卸载驱动 */
module_init(dtsled_init);
module_exit(dtsled_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");
6.应用层函数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>/**argc:应用程序参数个数*argv[]:具体的参数内容,字符串形式 *./ledAPP  <filename>  <0:1> 0表示关灯,1表示开灯* ./ledAPP /dev/dtsled 0    关灯* ./ledAPP /dev/dtsled 1    开灯*/#define LEDOFF 0
#define LEDON 1int main(int argc, char *argv[])
{int fd, retvalue;char *filename;unsigned char databuf[1];if(argc != 3) {printf("Error Usage!\r\n");return -1;}filename = argv[1];fd = open(filename, O_RDWR);if(fd < 0) {printf("file %s open failed!\r\n", filename);return -1;}databuf[0] = atoi(argv[2]); /* 将字符转换为数字 */retvalue = write(fd, databuf, sizeof(databuf));if(retvalue < 0) {printf("LED Control Failed!\r\n");close(fd);return -1;}close(fd);return 0;
}

关键字:甘肃省疫情防控最新文件_网站平台推广语录_盐城seo排名_公司网络营销实施计划

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: