0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【i.MX6ULL】驱动开发5——设备树原理与点亮LED

码农爱学习 来源:码农爱学习 作者:码农爱学习 2022-05-21 21:41 次阅读

上篇文章(【i.MX6ULL】驱动开发4--点亮LED(寄存器版))介绍了在驱动程序中,直接操作寄存器了点亮LED。本篇,介绍另外一种点亮LED的方式——设备树,该方式的本质也是操作寄存器,只是寄存器的相关信息放在了设备树中,配置寄存器时需要使用OF函数从设备树中读取处寄存器数据后再进行配置。

1 什么是设备树

1.1 背景介绍

Linux3.x之前是没有设备树的,设备树是用来描述一个硬件平台的板级细节。对应ARM-Linux开发,这些板级描述文件存放在linux内核的 /arch/arm/plat-xxx和/arch/arm/mach-xxx 中。随着ARM硬件设备的种类增多,与板子相关的设备文件也越来越多,这就导致Linux内核越来越大,而实际这些ARM硬件相关的板级信息与Linux内核并无相关关系。

2011年,Linux之父Linus Torvalds发现这个问题后,就通过邮件向ARM-Linux开发社区发了一封邮件,不禁的发出了一句“This whole ARM thing is a f*cking pain in the ass”。之后,ARM社区就引入了PowerPC等架构已经采用的设备树(Flattened Device Tree)机制,将板级信息内容都从Linux内核中分离开来,用一个专属的文件格式来描述,即现在的.dts文件。

poYBAGKI6LGAS9MzAAH1OTNPFEE751.png

1.2 设备树介绍

设备树的作用就是描述硬件平台的硬件资源。它可以被bootloader传递到内核,内核可以从设备树中获取硬件信息。

设备树描述硬件资源时有两个特点:

以树状结构描述硬件资源。以系统总线为树的主干,挂载到系统地总线的IIC控制器、SPI控制器等为树的枝干,IIC控制器下的IIC设备资源,又可以再分IIC1和IIC2,而IIC1上又可以连接MPU6050这类的IIC器件...

可以像头文件那样,一个设备树文件引用另外一个设备树文件,实现代码重用。例如多个硬件平台都使用i.MX6ULL作为主控芯片,可以将 i.MX6ULL 芯片的硬件资源写到一个单独的设备树文件中(.dtsi文件)。

pYYBAGKI6LmAT0VEAADvtS9Yakk301.png

1.3 DTS、DTSI、DTB、DTC

poYBAGKI6MCABo6SAABN6VFYebY423.png

DTS ,Device Tree Source,是设备树源码文件

DTSI ,Device Tree Source Include,是设备树源码文件要用到的头文件

DTB ,Device Tree Binary,是将DTS 编译以后得到的二进制文件

DTC ,Device Tree Compiler,是将.dts 编译为.dtb需要用到的编译工具

DTC工具源码在Linux内核的scripts/dtc目录下,scripts/dtc/文件夹下Makefile的内容为:

  • hostprogs-y:= dtc
    always:= $(hostprogs-y)

    dtc-objs:= dtc.o flattree.o fstree.o data.o livetree.o treesource.o srcpos.o checks.o util.o
    dtc-objs+= dtc-lexer.lex.o dtc-parser.tab.o
    ......省略

可以看出,DTC工具依赖于dtc.c、flattree.c、fstree.c等文件,最终编译并链接出DTC这个主机文件

2 设备树框架与DTS语法

2.1 设备树代码分析

在学习设备树时,可以先看一下NXP关于i.MX6ULL已有的设备树文件,来大致了解一下设备树文件是什么样子的。

2.1.1 imx6ull-14x14-evk-emmc.dts

下面是/arch/arm/boot/dts/imx6ull-14x14-evk-emmc.dts

#include "imx6ull-14x14-evk.dts"

&usdhc2 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
	bus-width = <8>;
	non-removable;
	status = "okay";
};

该文件就这几行,描述了emmc版本板子的usdhc信息。该文件的主要的功能是通过头文件的形式包含了另一个imx6ull-14x14-evk.dts设备树文件。

DTS语法:设备树是可以使用“#include”引用其它文件(.dts、.h、.dtsi)

2.1.2 imx6ull-14x14-evk.dts

下面是/arch/arm/boot/dts/imx6ull-14x14-evk.dts

/dts-v1/;

#include 
#include "imx6ull.dtsi"

/ {
	model = "Freescale i.MX6 ULL 14x14 EVK Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

	chosen {
		stdout-path = &uart1;
	};

	memory {
		reg = <0x80000000 0x20000000>;
	};

	reserved-memory {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;

		linux,cma {
			compatible = "shared-dma-pool";
			reusable;
			size = <0x14000000>;
			linux,cma-default;
		};
	};

	backlight {
		compatible = "pwm-backlight";
		pwms = <&pwm1 0 5000000>;
		brightness-levels = <0 4 8 16 32 64 128 255>;
		default-brightness-level = <6>;
		status = "okay";
	};

	pxp_v4l2 {
		compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
		status = "okay";
	};

	regulators {
		compatible = "simple-bus";
		//省略...
	};
	
	//省略...
};

&cpu0 {
	arm-supply = <®_arm>;
	soc-supply = <®_soc>;
	dc-supply = <®_gpio_dvfs>;
};

&clks {
	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
	assigned-clock-rates = <786432000>;
};

//省略...

&wdog1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_wdog>;
	fsl,wdog_b;
};

该文件也是先包含一些头文件,然后是一个斜杠+一些大括号,后面还出现了&符号

DTS语法:

/ {⋯} 斜杠+大括号,表示根节点,一个设备只有一个根节点

(注:一个dts包含另一个dts,两个文件里的根节点,其实也是同一个根节点)

xxx {⋯} 根节点内部单独的大括号,表示子节点,如reserved-memory {...}、pxp_v4l2 {...}等

&xxx {⋯} 根节点外部单独的&符号与大括号,表示节点的追加内容,如&cpu0 {...}等

2.1.3 imx6ull.dtsi

#include 
#include "imx6dl-pinfunc.h"
#include "imx6qdl.dtsi"

/ {
	aliases {
		i2c3 = &i2c4;
	};

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

		cpu0: cpu@0 {
			compatible = "arm,cortex-a9";
			device_type = "cpu";
			//省略...
		};

		cpu@1 {
			compatible = "arm,cortex-a9";
			device_type = "cpu";
			reg = <1>;
			next-level-cache = <&L2>;
		};
	};

	reserved-memory {
		//省略...
	};

	soc {
		//省略...
		ocram: sram@00905000 {
			compatible = "mmio-sram";
			reg = <0x00905000 0x1B000>;
			clocks = <&clks IMX6QDL_CLK_OCRAM>;
		};
		//省略...
	};
};

//省略...

&vpu_fsl {
	iramsize = <0>;
};

该文件是设备树的头文件,其格式与设备树基本相同。

DTS语法:节点标签

节点名“cpu”前面多了个“cpu0”, 这个“cpu0”就是我们所说的节点标签。通常节点标签是节点名的简写,它的作用是当其它位置需要引用时可以使用节点标签来向该节点中追加内容。

2.2 设备节点基本格式

设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键-值对。

node-name@unit-address{
	属性1 = ...
	属性2 = ...
	子节点...
}

2.2.1 节点名称

node-name用于指定节点名称,其长度为1~31个字符:

数字:0~9

字母:a~z A~Z

英文符号:, . _ + -

节点名应使用字母开头,并能描述设备类别(根节点用斜杠表示,不需要节点名)

2.2.2 单元地址

@unit-address用于指定单元地址,其中@符号表示一个分隔符,unit-address是实际的单元地址,它的值要和节点reg属性的第一个地址一致,如果没有reg属性值,则可以省略单元地址

2.2.3 节点属性

在节点的大括号“{}”中包含的内容是节点属性, 一个节点可以包含多个属性信息,例如根节点的属性model = "Freescale i.MX6 ULL 14x14 EVK Board",编写设备树最主要的内容是编写节点的节点属性。属性包括自定义属性标准属性,下面来看几个标准属性:

model属性:用于指定设备的制造商型号,多个字符串使用“,”分隔开

compatible 属性:由一个或多个字符串组成,是用来查找节点的方法之一

status属性:用于指示设备的“操作状态” ,通过status可以禁用或启用设备

reg属性:描述设备资源在其父总线定义的地址空间内的地址,通常情况下用于表示一块寄存器的起始地址(偏移地址)和长度

#address-cells 和 #size-cells:这两个属性同时存在,在设备树ocrams结构中,用在有子节点的设备节点,用于设置子节的“reg”属性的“书写格式”

ranges属性:它是一个地址映射/转换表,由子地址、父地址和地址空间长度这三部分组成:

child-bus-address: 子总线地址空间的物理地址, 由父节点的#address-cells 确定此物理地址所占用的字长

parent-bus-address:父总线地址空间的物理地址,同样由父节点的#address-cells 确定此物理地址所占用的字长

length:子地址空间的长度,由父节点的#size-cells 确定此地址长度所占用的字长

2.2.4 特殊节点

aliases子节点:其作用是为其他节点起一个别名,例如:

  • aliases {
    i2c3 = &i2c4;
    };

chosen子节点:该节点位于根节点下,它不代表实际硬件, 它主要用于给内核传递参数,例如:

  • chosen {
    stdout-path = &uart1;
    };

表示系统标准输出 stdout 使用串口 uart1。

3 设备树编程之OF函数

内核提供了一系列函数用于从设备节点获取设备节点中定义的属性,这些函数以 of_ 开头,称为OF函数。在编写设备树版的LED驱动时,在进行硬件配置方面,就是要用这些OF函数,将寄存器地址等信息从设备树文件中获取出来,然后进行GPIO配置

先来列举一下这些函数:

poYBAGKI6fOARKSHAAKYzv0jvRg056.png

3.1 查找节点的OF函数

of_find_node_by_name

通过节点名字查找指定的节点

/**
 * from: 开始查找的节点,若为NULL表示从根节点开始查找整个设备树
 * name: 要查找的节点名字
 * return: 找到的节点,若为NULL表示查找失败
 */
struct device_node *of_find_node_by_name(struct device_node *from, const char *name); 

of_find_compatible_node

根据device_type和compatible这两个属性查找指定的节点

/**
 * from: 开始查找的节点,若为NULL表示从根节点开始查找整个设备树
 * type: 要查找的节点对应的type字符串,也就是device_type属性值
 * return: 找到的节点,若为NULL表示查找失败
 */
struct device_node *of_find_node_by_type(struct device_node *from, const char *type) 

of_find_matching_node_and_match

通过of_device_id匹配表来查找指定的节点

/**
 * from: 开始查找的节点,若为NULL表示从根节点开始查找整个设备树
 * type: 要查找的节点对应的type字符串,也就是device_type属性值,为NULL表示忽略掉device_type属性
 * compatible: 要查找的节点所对应的compatible属性列表
 * return: 找到的节点,若为NULL表示查找失败
 */
struct device_node *of_find_compatible_node(struct device_node *from,  
                                             const char *type,  
                                             const char *compatible)  

of_find_node_by_path

通过路径来查找指定的节点

/**
 * path: 带有全路径的节点名
 * return: 找到的节点,若为NULL表示查找失败
 */
inline struct device_node *of_find_node_by_path(const char *path) 

3.2 查找父/子节点的OF函数

of_get_parent

用于查找父节点

/**
 * node: 要查找的父节点的节点
 * return: 找到的父节点
 */
struct device_node *of_get_parent(const struct device_node *node) 

of_get_next_child

用迭代的方式查找子节点

/**
 * node: 父节点
 * prev: 前一个子节点,也就是从哪一个子节点开始迭代的查找下一个子节点,为NULL表示从第一个子节点开始
 * return: 找到的下一个子节点
 */
struct device_node *of_get_next_child(const struct device_node *node, 
                                            struct device_node *prev) 

3.3 提取属性值的OF函数

of_find_property

查找指定的属性

/**
 * np: 设备节点
 * name: 属性名字
 * lenp: 属性值的字节数
 * return: 找到的属性
 */
property *of_find_property(const struct device_node *np, 
                                         const char *name, 
                                                int *lenp) 

of_property_count_elems_of_size

用于获取属性中元素的数量

/**
 * np: 设备节点
 * propname: 属性名字
 * elem_size: 元素长度
 * return: 属性元素数量
 */
int of_property_count_elems_of_size(const struct device_node *np, 
                                                  const char *propname,  
                                                         int elem_size) 

of_property_read_u32_index

用于从属性中获取指定标号的u32类型数据值

/**
 * np: 设备节点
 * propname: 属性名字
 * index: 要读取的值标号
 * out_value: 读取到的值 
 * return: 0读取成功,负值读取失败
 */
nt of_property_read_u32_index(const struct device_node *np, 
                                            const char *propname, 
                                                   u32 index,  
                                                   u32 *out_value) 

of_property_read_u8_array

用于读取属性中 u8类型的数组数据(类似的函数还有u16、u32 和 u64)

/**
 * np: 设备节点
 * propname: 属性名字
 * out_values: 读取到的数组值
 * return: 0读取成功,负值读取失败
 */
int of_property_read_u8_array(const struct device_node *np, 
                                            const char *propname,  
                                                    u8 *out_values,  
                                                size_t sz) 

of_property_read_u8

用于读取只有一个整形值的属性(类似的函数还有u16、u32 和 u64)

/**
 * np: 设备节点
 * propname: 属性名字
 * out_values: 读取到的数组值
 * return: 0读取成功,负值读取失败
 */
int of_property_read_u8(const struct device_node *np,  
                                      const char *propname, 
                                              u8 *out_value)

of_property_read_string

用于读取属性中字符串值

/**
 * np: 设备节点
 * propname: 属性名字
 * out_values: 读取到的字符串值
 * return: 0读取成功,负值读取失败
 */
int of_property_read_string(struct device_node *np,  
                                    const char *propname, 
                                    const char **out_string) 

of_n_addr_cells

用于获取#address-cells 属性值

/**
 * np: 设备节点
 * return: 获取到的#address-cells属性值
 */
int of_n_addr_cells(struct device_node *np)

of_n_size_cells

用于获取#size-cells 属性值

/**
 * np: 设备节点
 * return: 获取到的#size-cells属性值
 */
int of_n_size_cells(struct device_node *np) 

3.4 其他常用的OF函数

of_device_is_compatible

用于查看节点的compatible属性是否有包含compat指定的字符串,也就是检查设备节点的兼容性

/**
 * device: 设备节点
 * compat: 要查看的字符串
 * return: 0不包含,正数包含
 */
int of_device_is_compatible(const struct device_node *device, 
                                          const char *compat) 

of_get_address

用于获取地址相关属性

/**
 * dev: 设备节点
 * index: 要读取的地址标号
 * size: 要读取的地址标号
 * flags: 参数
 * return: 读取到的地址数据首地址,NULL表示失败
 */
const __be32 *of_get_address(struct device_node *dev,  
                                            int index,  
                                            u64 *size, 
                                   unsigned int *flags) 

of_translate_address

用于将设备树读取到的地址转换为物理地址

/**
 * dev 设备节点
 * in_addr: 要转换的地址
 * return: 得到的物理地址
 */
u64 of_translate_address(struct device_node *dev,  
                               const __be32 *in_addr) 

of_address_to_resource

用于将reg属性值,转换为resource结构体类型

/**
 * dev: 设备节点
 * index: 地址资源标号
 * r: 得到的 resource 类型的资源值
 * return: 0成功,负值失败
 */
int of_address_to_resource(struct device_node *dev,  
                                          int index, 
                              struct resource *r) 

of_iomap

用于直接内存映射

/**
 * np: 设备节点
 * index: reg属性中要完成内存映射的段
 * return: 经过内存映射后的虚拟内存首地址,为NULL表示失败
 */
void __iomem *of_iomap(struct device_node *np,  
                                      int index) 

4 设备树LED驱动程序与实验

回忆之前的LED字符设备驱动的编写方法:直接在驱动文件regled.c中定义有关寄存器物理地址,然后使用io_remap函数进行内存映射得到对应的虚拟地址,最后操作寄存器对应的虚拟地址完成对GPIO的初始化

使用设备树编写字符设备驱动,主要的一点区别是:使用设备树向Linux内核传递相关的寄存器物理地址,Linux驱动文件使用OF函数从设备树中获取所需的属性值,然后使用获取到的属性值来初始化相关的IO,所以,其本质还是配置寄存器。

所以,使用设备树进行LED驱动,需要的修改主要为:

修改imx6ull-myboard.dts设备树文件,在其中添加RGB-LED的设备节点

编写RGB-LED驱动程序,获取设备树中的相关属性值,并使用相关的属性值进行GPIO的初始化

编写RGB-LED应用程序,控制RGB-LED的亮灭

4.1 修改设备树文件

/ {
	model = "Freescale i.MX6 ULL 14x14 EVK Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
    
    //省略...
    
	/*myboard led*/
	myboardled {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "myboard-led";
		status = "okay";
		reg = < 0X020C406C 0x04    /*CCM_CCGR1_BASE*/	
                0X02290014 0x04    /*SW_MUX_SNVS_TAMPER3_BASE*/
				0X02290058 0x04    /*SW_PAD_SNVS_TAMPER3_BASE*/
				0X020AC000 0x04    /*GPIO5_DR_BASE*/
				0X020AC004 0x04 >; /*GPIO5_GDIR_BASE*/
	};
};

编译设备树,在内核源码的根目录下(我的是~/myTest/imx6ull/kernel/nxp_kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga),执行如下make命令即可单独编译自己修改的设备树

make imx6ull-myboard.dtb

4.2 测试设备树

4.2.1 测试环境切换

由于这次是修改了设备树文件,而我的板子已经烧录了固件到emmc,因此,这次实验,重新将板子设为从SD卡启动uboot并从网络启动NFS文件系统的方式,方便修改测试设备树。(板子从网络启动的方式,可参考之前的文章i.MX6ULL嵌入式Linux开发4-根文件系统构建),若之前SD的uboot配置还在,将板子切换到SD卡启动,并确保网络畅通,即可从网络启动。

若nfs服务器(ubuntu虚拟器)的IP发生变化,需要和之前一样进行类似如下的bootargs和bootcmd配置:

setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.5.104:/home/xxpcb/myTest/nfs/rootfs,proto=tcp,nfsvers=4 rw ip=192.168.5.102:192.168.5.104:192.168.5.1:255.255.255.0::eth1:off' 
setenv bootcmd 'tftp 80800000 nxp/zImage; tftp 83000000 nxp/imx6ull-myboard.dtb; bootz 80800000 - 83000000' 
saveenv
boot

注意这里的192.168.5.104是我的ubuntu的IP,192.168.5.102是板子的IP。

4.2.2 设备树修改后的效果

在测试设备树之前,可以先看一下目前板子的设备树中都有什么:

poYBAGKI6weAJ82hAAAhBz5FlOk271.png

将编译后的dtb文件放到网络启动位置,比如我的是复制到这里:

xxpcb@ubuntuTest:~/myTest/imx6ull/kernel/nxp_kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/boot/dts$ cp imx6ull-myboard.dtb ~/myTest/tftpboot/nxp/

然后重启板子,再次查看/proc/device-tree/目录:

poYBAGKI6xqAYtJ_AABrX1plbTM354.png

可以看到,出现了新加的myboardled节点,进入myboardled目录下,可以看到其属性信息。

4.3 修改LED驱动程序

驱动程序整体框架和上一篇的寄存器版配置程序基本相同,主要的不同是修改硬件配置的方式,

/*
 * @description   : LED硬件初始化(IO映射、时钟、GPIO配置)
 * @param         : 无
 * @return        : 0 成功;其他 失败
 */
static int dtsled_hardware_init(void)
{
    u32 val = 0;
    int ret;
    u32 regdata[14];
    const char *str;
    struct property *proper;

    /* 获取设备树中的属性数据 */
    /* 1、获取设备节点:myboardled */
    dtsled.nd = of_find_node_by_path("/myboardled");
    if(dtsled.nd == NULL) 
    {
        printk("myboardled node nost find!\r\n");
        return -EINVAL;
    } 
    else 
    {
        printk("myboardled node find!\r\n");
    }

    /* 2、获取compatible属性内容 */
    proper = of_find_property(dtsled.nd, "compatible", NULL);
    if(proper == NULL) 
    {
        printk("compatible property find failed\r\n");
    } 
    else 
    {
        printk("compatible = %s\r\n", (char*)proper->value);
    }

    /* 3、获取status属性内容 */
    ret = of_property_read_string(dtsled.nd, "status", &str);
    if(ret < 0)
    {
        printk("status read failed!\r\n");
    } 
    else 
    {
        printk("status = %s\r\n",str);
    }

    /* 4、获取reg属性内容 */
    ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 10);
    if(ret < 0) 
    {
        printk("reg property read failed!\r\n");
    } 
    else 
    {
        u8 i = 0;
        printk("reg data:\r\n");
        for(i = 0; i < 10; i++)
        {
            printk("%#X ", regdata[i]);
        }
        printk("\r\n");
    }

    /* 初始化LED */
#if 0
    /* 1、寄存器地址映射(使用ioremap) */
    IMX6U_CCM_CCGR1      = ioremap(regdata[0], regdata[1]);
    SW_MUX_SNVS_TAMPER3  = ioremap(regdata[2], regdata[3]);
    SW_PAD_SNVS_TAMPER3  = ioremap(regdata[4], regdata[5]);
    GPIO5_DR             = ioremap(regdata[6], regdata[7]);
    GPIO5_GDIR           = ioremap(regdata[8], regdata[9]);
#else
    /* 1、寄存器地址映射(直接使用of_iomap) */
    IMX6U_CCM_CCGR1      = of_iomap(dtsled.nd, 0);
    SW_MUX_SNVS_TAMPER3  = of_iomap(dtsled.nd, 1);
    SW_PAD_SNVS_TAMPER3  = of_iomap(dtsled.nd, 2);
    GPIO5_DR             = of_iomap(dtsled.nd, 3);
    GPIO5_GDIR           = of_iomap(dtsled.nd, 4);
#endif

    /* 2、使能GPIO1时钟 */
    //省略... 后面的配置与上一篇的相同
}

上面的程序修改部分,从整个LED驱动的框架来看,修改的只是如下图中的黄色框部分:

pYYBAGKI6yuAUHczAAHJtFqyndM608.png

4.4 实验测试

编译设备树版的LED驱动程序,并将编译好的ko文件发送到nfs文件系统对应的文件夹下。

LED是应用程序不需要修改,仍使用上一篇文章中的程序即可。

poYBAGKI6zWAUIZzAAHMb0RRzhE854.png

测试方法与之前基本相同:

poYBAGKI6z2AL_VoAACIdMUcgOg160.png

使用设备树的方式,再次点亮LED:

pYYBAGKI60aAYOiNAAC-QqGhKlk901.png

5 总结

本篇介绍了设备树的基本原理以及设备树的使用方法,在上一篇点亮LED的代码基础上,通过设备树的方式,实现了LED点灯,总结一下主要的修改就是先在设备树中添加LED节点,然后在驱动文件中通过OF函数来读取设备树中的寄存器信息,再进行GPIO的初始化,其它部分的程序与上一篇的基本一样。

poYBAGKI602AaQxgAAB98U7Hbag233.png

审核编辑:符乾江

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5068

    文章

    19014

    浏览量

    303132
  • 驱动
    +关注

    关注

    12

    文章

    1825

    浏览量

    85172
  • Linux
    +关注

    关注

    87

    文章

    11222

    浏览量

    208891
收藏 人收藏

    评论

    相关推荐

    i.MX6ULL 驱动开发7—按键输入捕获与GPIO输入配置与高低电平读取

    本篇主要介绍了i.MX6ULL的按键检测的使用,主要的知识点是设备的修改,以及GPIO的输入配置与高低电平的读取。
    的头像 发表于 05-24 09:11 6126次阅读
    <b class='flag-5'>i.MX6ULL</b> <b class='flag-5'>驱动</b><b class='flag-5'>开发</b>7—按键输入捕获与GPIO输入配置与高低电平读取

    使用i.MX6ULL开发板进行Linux根文件系统的完善

    上一篇推文讲了怎么移植根文件系统,并在i.MX6ULL开发板中运行起来,但是会出现一些提示,现在来进行根文件的完善。
    发表于 10-17 11:13 762次阅读

    移植NXP官方linux 5.4内核到i.MX6ULL开发

    本文描述移植NXP官方 linux 5.4 内核到i.MX6ULL开发板。
    发表于 12-19 11:10 2003次阅读

    移植5.4内核到迅为I.MX6ULL开发

    ),选择5.4.3内核编译生成的对应镜像和设备文件(关于i.MX6ULL终结者开发板镜像的烧写,大家可以参考开发板使用手册的:第六章
    发表于 06-29 10:13

    i.MX6ULL开发板硬件资源

    迅为i.MX6ULL 终结者开发板硬件资源非常丰富,几乎将 i.MX6ULL 芯片的所有资源都扩展引出到底板上了,底板提供了丰富的外设接口,开发板的尺寸是 190mm*125mm,充分
    发表于 12-29 06:18

    初识 i.MX6ULL 寄存器

    裸机开发_L1_汇编LED实验0. 本节目标1. 硬件层电路2. 初识 i.MX6ULL 寄存器2.1 i.MX6ULL 时钟控制寄存器2.2 i.
    发表于 12-20 07:13

    关于i.MX6ULL配置GPIO

    正如学习C语言时写的第一段代码都是“HelloWorld!”,接触一款新的处理器时往往是从点亮一个LED开始;而点亮一个LED,则需要操作这款芯片的GPIO外设。那么作为广受欢迎的
    发表于 08-05 10:37

    I.MX6ULL无法枚举USB2514是为什么?

    你好目前,I.MX6ULL开发存在一些问题。其中之一是OTG USB2无法正常挂载USB2514,无法正确枚举下游设备,只显示设备id。usb设计要注意什么。
    发表于 04-03 06:55

    如何在i.MX6ULL上为PF1510配置i2c?

    我们计划将 PF1510 与 i.MX6ULL 处理器一起使用。我看到这个设备示例: https://github.com/Freescale/linux-fslc/blob
    发表于 05-17 14:02

    飞凌i.MX6ULL开发板的评测,再次进阶拥有更高的性价比

    处理器MCIMX6Y2开发设计,采用先进的ARMCortex-A7内核,运行速度高达800MHz。i.MX6ULL应用处理器包括一个集成的电源管理模块,降低了外接电源的复杂性,并简化了上电时序。
    发表于 10-27 11:55 1464次阅读
    飞凌<b class='flag-5'>i.MX6ULL</b><b class='flag-5'>开发</b>板的评测,再次进阶拥有更高的性价比

    基于NXP i.MX6ULL处理器的FETMX6ULL-C核心板

    合作伙伴,飞凌不负美誉,基于i.MX6ULL匠心打造的FETMX6ULL-S核心板一经问世便好评不断,且已有数百家来自工业、医疗、电力、物联网等行业的用户采用此款核心板快速完成了整机产品的开发上市。
    发表于 04-11 15:05 1135次阅读
    基于NXP <b class='flag-5'>i.MX6ULL</b>处理器的FETMX<b class='flag-5'>6ULL</b>-C核心板

    i.MX6ULL驱动开发4——点亮LED(寄存器版)

    本篇主要介绍了如何通过操作寄存器来点亮i.MX6ULL开发板上的led,通过编写LED对应的驱动
    的头像 发表于 05-21 21:26 2939次阅读
    【<b class='flag-5'>i.MX6ULL</b>】<b class='flag-5'>驱动</b><b class='flag-5'>开发</b>4——<b class='flag-5'>点亮</b><b class='flag-5'>LED</b>(寄存器版)

    基于i.MX6ULL点亮LED

    都说入门一款芯片的第一步是点亮LED,但是i.MX6ULL入门门槛比较高,特别是通过自学入门的,这个系列已经写了好久了,最近打算在项目不急的时候加快一下学习进度,现在就开始学习一下怎么点亮
    的头像 发表于 03-06 09:09 785次阅读

    【北京迅为】i.MX6ULL开发板移植 Debian 文件系统

    【北京迅为】i.MX6ULL开发板移植 Debian 文件系统
    的头像 发表于 02-10 15:34 1108次阅读
    【北京迅为】<b class='flag-5'>i.MX6ULL</b><b class='flag-5'>开发</b>板移植 Debian 文件系统

    基于i.MX6ULL的掉电检测设计与软件测试

    基于i.MX6ULL的掉电检测设计与软件测试基于i.MX6ULL平台设计实现掉电检测功能,首先选择一路IO,利用IO电平变化触发中断,在编写驱动时捕获该路GPIO的中断,然后在中断响应函数中发
    的头像 发表于 11-09 10:40 809次阅读
    基于<b class='flag-5'>i.MX6ULL</b>的掉电检测设计与软件测试