————————————————————————————
在设备树中添加节点信息节点属性:设备节点最好添加在好区分的地方 如一级节点处
在设备树中最重要的节点信息是设备的地址信息
/*用设备树操作 获取设备树属性内容 一般在加载驱动的时候读取设备树节点信息*/
alphaled {
#address-cells = <1>;
#size-cells =<1>;
status = "okay";
compatible = "alientek,alphaled";
//地址 地址长度
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 dtbs
编译设备树 将用新的设备树启动内核
使用cat /proc/device-tree 命令可以查看根节点的下的节点信息
——————————————————————————————————————————
LED驱动的编写 (一般用一个结构体描述一个设备里面所需要的各种信息)
/*dtsled设备结构体*/
struct dtsled_dev
{
dev_t devid; //设备号
int major; //主设备号
int minor;//次设备号
struct cdev cdev ;//包含了操作函数集 与app.C进行联系
struct class *class;//创建类
struct device *device;//创建设备
struct device_node *nd;//设备节点
};
struct dtsled_dev dtsled; //设备
——————————————————————————————————
/*入口 -注册字符设备*/中注册设备号 向内核添加字符设备 自动创建设备节点 不变
新添加
————————————————————
/*1——————获取节点*/
dtsled.nd = of_find_node_by_path("/alphaled");//从全路径中找
if(dtsled.nd == NULL)
{
ret = -EINVAL ; //查找节点失败
goto failed_findnd;
}
/*2———————获取节点各个属性信息*/
//status 字符串
ret = of_property_read_string(dtsled.nd, "status",&str);
if(ret < 0)
{
goto faield_rs;
}
else
{
printk("status = %s \r\n", str);
}
// compatible 字符串
ret = of_property_read_string(dtsled.nd, "compatible",&str);
if(ret < 0)
{
goto faield_rs;
}
else
{
printk("compatible = %s \r\n", str);
}
——————————————获取地址属性 reg
第一种方法 由于需要灯的内存映射
/*存在虚拟映射*/
/*地址映射后打虚拟地址指针*/
//#include <asm/io.h>
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;
/*获取reg属性 数组*/
ret = of_property_read_u32_array(dtsled.nd,"reg", regdate ,10);// 节点 名称 保存到哪里 几个元素
if(ret < 0)
{
ret = -EINVAL;
goto faield_read32array;
}
else
{
printk("reg date :\r\n");
for( i = 0 ; i < 10 ; i++ )
printk("%#X ",regdate[i]);
printk("\r\n");
}
IMX6U_CCM_CCGR1 = ioremap(regdate[0], regdate[1]); //该函数用于虚拟地址映射 物理地址加大小 32bit =4 byte
SW_MUX_GPIO1_IO03 = ioremap(regdate[2], regdate[3]);
SW_PAD_GPIO1_IO03 = ioremap(regdate[4], regdate[5]);
GPIO1_DR = ioremap(regdate[6], regdate[7]);
GPIO1_GDIR = ioremap(regdate[8], regdate[9]);
第二种方法 内存映射和读取一体函数
//在设备树中 由读取属性值和内存映射同时进行的函数 of_iomap 函数 获得的是reg属性
//index 起始地址加内存段长度是一个index
IMX6U_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);
————————————————————————————————————————————之后 //初始化时钟 //初始化IO复用 //初始化电气属性 //初始化GPIO 设置输入还是输出 led是输出灯 //初始化高低电平控制led