IMX6ULL开发平台Linux-LED实验

发布者:EnchantingEyes最新更新时间:2025-03-05 来源: cnblogs关键字:开发平台  Linux  LED实验 手机看文章 扫描二维码
随时随地手机看文章

在前面的章节中,我们学习了解了字符设备驱动,以及如何在设备树文件中添加设备信息,接下来就来看一下i.MX6UL终结者开发板的实际硬件是如何添加的。我们先以最简单的LED设备来看一下具体的注册流程。

36.1 LED设备注册流程

在i.MX6UL终结者开发板上有一个LED设备,如果想要通过Linux系统/dev目录下的设备节点来控制LED,就需要在内核中添加LED的驱动,具体的流程可以分为下面几个步骤:

① 硬件原理图分析,确定控制LED的GPIO信息。

② 根据GPIO信息在设备树文件中添加pinctrl信息

③ 在设备树中创建LED的设备节点,并加入GPIO信息

④ 编写LED设备驱动程序

接下来根据上面这四步来添加一下LED的设备驱动。

36.2 LED硬件原理图分析

LED设备的硬件原理图如下所示:

LED设备的原理图很简单,LED一端接3.3V电源,另一端为控制引脚:GPIO_3,通过控制GPIO_3的高低电平来控制LED的亮灭。所以我们确认LED设备只使用了一个控制引脚:GPIO_3。

36.3 修改设备树文件

在引脚原理图分析中确认了LED的控制GPIO信息,接下来就要修改设备树文件。

36.3.1 添加pinctrl信息

在i.MX6UL终结者开发板中使用GPIO_3这个引脚来控制LED设备。打开topeet_emmc_4_3.dts文件在iomux节点的imx6ul-evk子节点下创建一个名为“pinctrl_led”的子节点,具体内容如下:

&iomuxc {

        pinctrl-names = 'default';

        pinctrl-0 = <&pinctrl_hog_1>;

        imx6ul-evk {

pinctrl_led: gpio-led {

fsl,pins = ;

};

}

};

在pinctrl_gpio_leds节点中将GPIO_3引脚的复用功能定义为GPIO1_IO03,即为一个普通的输入输出引脚。宏定义MX6UL_PAD_GPIO1_IO03__GPIO1_IO03定义在arch/arm/boot/dts/imx6ul-pinfunc.h目录下。

36.3.2 添加LED设备节点

在topeet_emmc_4_3.dts文件下,在根节点“/”下创建LED节点,节点名为“gpioled”,具体内容如下:

1 gpioled {

2  #address-cells = <1>;

3 #size-cells = <1>;

4 compatible = 'gpioled';

5 pinctrl-names = 'default';

6 pinctrl-0 = <&pinctrl_led>;

7 led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;

8 status = 'okay';

9 };

第6行,pinctrl-0 属性设置 LED 灯所使用的GPIO对应的 pinctrl 节点。

第7行,led-gpio属性指定了LED使用的GPIO为GPIO1的IO3引脚,低电平有效,在驱动程序中会获取led-gpio属性的内容来得到GPIO编号,因为gpio子系统的操作控制函数需要GPIO编号。

添加完LED的设备节点后,还有一个重要的步骤,就是检查GPIO引脚有没有被其他设备使用。一个引脚只能配置成一个功能,如果有其他设备也使用了这个GPIO,那么会导致在LED驱动程序中GPIO初始化失败。这一点非常重要。

检查GPIO引脚有没有被其他设备使用包括两个方面:

① 检查pinctrl设置

② 检查这个GPIO有没有被别的设备使用

LED设备使用的是GPIO1_IO03,首先检查GPIO1_IO03这个引脚有没有其他pinctrl节点的设置。在topeet_emmc_4_3.dts文件中找到了如下内容:

pinctrl_tsc: tscgrp {

      fsl,pins = <

               MX6UL_PAD_GPIO1_IO01__GPIO1_IO01        0xb0

               MX6UL_PAD_GPIO1_IO02__GPIO1_IO02        0xb0

               MX6UL_PAD_GPIO1_IO03__GPIO1_IO03        0xb0

               MX6UL_PAD_GPIO1_IO04__GPIO1_IO04        0xb0

              >;

  };

GPIO1_IO03引脚也在pinctrl_tsc节点中定义了,pinctrl_tsc 节点是 TSC(电阻触摸屏接口)的 pinctrl 节点,而在i.MX6UL终结者开发板中并没有用到这个接口,因此我们要将pinctrl_tsc节点下的GPIO1_IO03引脚的定义注释掉。和 C 语言一样,在要屏蔽的内容前后加上“/*”和“*/”符号即可。

既然有其他设备配置了GPIO1_IO03引脚的pinctrl信息,应该会有使用使用这个pinctrl节点的设备节点,在topeet_emmc_4_3.dts文件中查找一下pinctrl_tsc或者直接查找“gpio1 3”,查找内容如下:

 

1 &tsc {

2        pinctrl-names = 'default';

3        pinctrl-0 = <&pinctrl_tsc>;

4        xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;

5        measure-delay-time = <0xffff>;

6        pre-charge-time = <0xfff>;

7        status = 'disabled';

8 };

可以看出第4行xnur-gpio属性使用了“gpio1 3”,同意需要把这一行也注释掉。然后继续按照上面步骤搜索,看看还有没有其他设备使用了GPIO1_IO03引脚。

设备树编写完成以后使用“make dtbs”命令重新编译设备树,然后使用新编译出来的 topeet_emmc_4_3.dtb 文件启动 Linux 系统。启动成功以后进入“/proc/device-tree”目录中查看“gpioled”节点是否存在,如果存在的话就说明设备树基本修改成功(具体作用还要驱动验证),结果如下图所示:

请继续:IMX6ULL开发平台Linux-LED实验(二)

上部分内容IMX6ULL开发平台Linux-LED实验(一)36.4 编写LED驱动程序

本实验例程路径:i.MX6UL终结者光盘资料/06_Linux驱动例程/02_gpioled

在设备树文件中添加完LED设备信息后,就可以编写LED的驱动程序了,创建gpioled.c文件,具体驱动内容如下所示:

  1   #include

  2   #include

  3   #include

  4   #include

  5   #include

  6   #include

  7   #include

  8   #include

  9   #include

10   #include

11   #include

12   #include

13   #include

14   #include

15   #include

16   #include

17

18   #define GPIOLED_CNT 1 /* 设备号个数 */

19   #define GPIOLED_NAME 'gpioled' /* 名字 */

20   #define LEDOFF 0 /* 关灯 */

21   #define LEDON 1 /* 开灯 */

22

23   /* gpioled 设备结构体 */

24   struct gpioled_dev{

25         dev_t devid; /* 设备号 */

26         struct cdev cdev; /* cdev */

27         struct class *class; /* 类 */

28         struct device *device; /* 设备 */

29         int major; /* 主设备号 */

30         int minor; /* 次设备号 */

31         struct device_node *nd; /* 设备节点 */

32         int led_gpio; /* led 所使用的 GPIO 编号 */

33   };

34

35   struct gpioled_dev gpioled; /* led 设备 */

36

37   /*

38    * @description : 打开设备

39    * @param – inode : 传递给驱动的 inode

40    * @param – filp : 设备文件,file 结构体有个叫做 private_data 的成员变量

41    * 一般在 open 的时候将 private_data 指向设备结构体。

42    * @return : 0 成功;其他 失败

43    */

44   static int led_open(struct inode *inode, struct file *filp)

45   {

46         filp->private_data = &gpioled; /* 设置私有数据 */

47         return 0;

48   }

49

50   /*

51    * @description : 从设备读取数据

52    * @param – filp : 要打开的设备文件(文件描述符)

53    * @param - buf : 返回给用户空间的数据缓冲区

54    * @param - cnt : 要读取的数据长度

55    * @param – offt : 相对于文件首地址的偏移

56    * @return : 读取的字节数,如果为负值,表示读取失败

57    */

58   static ssize_t led_read(struct file *filp, char __user *buf,

59                 size_t cnt, loff_t *offt)

60   {

61         return 0;

62   }

63

64   /*

65    * @description : 向设备写数据

66    * @param - filp : 设备文件,表示打开的文件描述符

67    * @param - buf : 要写给设备写入的数据

68    * @param - cnt : 要写入的数据长度

69    * @param – offt : 相对于文件首地址的偏移

70    * @return : 写入的字节数,如果为负值,表示写入失败

71    */

72   static ssize_t led_write(struct file *filp, const char __user *buf,

73                 size_t cnt, loff_t *offt)

74   {

75         int retvalue;

76         unsigned char databuf[1];

77         unsigned char ledstat;

78         struct gpioled_dev *dev = filp->private_data;

79

80         retvalue = copy_from_user(databuf, buf, cnt);

81         if(retvalue < 0) {

82                 printk('kernel write failed!rn');

83                 return -EFAULT;

84         }

85

86         ledstat = databuf[0]; /* 获取状态值 */

87

88         if(ledstat == LEDON) {

89                 gpio_set_value(dev->led_gpio, 0); /* 打开 LED 灯 */

90         } else if(ledstat == LEDOFF) {

91                 gpio_set_value(dev->led_gpio, 1); /* 关闭 LED 灯 */

92         }

93         return 0;

94   }

95

96   /*

97    * @description : 关闭/释放设备

98    * @param – filp : 要关闭的设备文件(文件描述符)

99    * @return : 0 成功;其他 失败

100    */

101   static int led_release(struct inode *inode, struct file *filp)

102   {

103         return 0;

104   }

105

106   /* 设备操作函数 */

107   static struct file_operations gpioled_fops = {

108         .owner = THIS_MODULE,

109         .open = led_open,

110         .read = led_read,

111         .write = led_write,

112         .release = led_release,

113   };

114

115   /*

116    * @description : 驱动入口函数

117    * @param : 无

118    * @return : 无

119    */

120   static int __init led_init(void)

121   {

122         int ret = 0;

123

124         /* 设置 LED 所使用的 GPIO */

125         /* 1、获取设备节点:gpioled */

126         gpioled.nd = of_find_node_by_path('/gpioled');

127         if(gpioled.nd == NULL) {

128                 printk('gpioled node cant not found!rn');

129                 return -EINVAL;

130         } else {

131                 printk('gpioled node has been found!rn');

[1] [2]
关键字:开发平台  Linux  LED实验 引用地址:IMX6ULL开发平台Linux-LED实验

上一篇:【IMX6ULL学习笔记】一、Linux开发环境搭建
下一篇:4412开发板-Android4.4典型功能相关源码修改及定制

推荐阅读最新更新时间:2026-03-22 14:03

IMX6ULL开发Linux设备树实验
在上一节迅为IMX6ULL开发板已经对DTS的语法做了比较详细的介绍,在本节中根据前面讲解的语法,从头到尾编写一个小型的设备树文件。我们会以一个虚拟的设备作为参考,提前假设一些外部设备和功能。当然这个虚拟的设备没有任何的意思,只是为了复习掌握前面学习的设备树语法。在实际产品的开发过程中,我们不需要从头编写一个dts设备树文件,一般都是使用soc厂商提供的dts文件,我们只需要根据自己的实际情况修改添加自己的内容即可。 下面这个假设的设备,制造商为“Acme”,并命名为“Coyote's Revenge”,具体功能如下: l 一个32位ARM CPU l 处理器本地总线连接到内存映射的串行口、spi 总线控制器、i2c
[单片机]
Linux内核启动流程-迅为IMX6ULL开发板(二)
start_kernel是所有Linux平台进入系统内核初始化后的入口函数,它主要完成剩余的与 硬件平台相关的初始化工作,在进行一系列与内核相关的初始化后,调用第一个用户进程- init 进程并等待用户进程的执行,这样整个 Linux内核便启动完毕。 30.3.1 start_kernel 函数 start_kernel 通过调用众多的子函数来完成 Linux 启动之前的一些初始化工作,由于start_kernel 函数里面调用的子函数太多,而这些子函数又很复杂,因此我们简单介绍一下一些重要的子函数。start_kernel 函数定义在文件 init/main.c中。精简并添加注释后的 start_kernel 函数内容如下:
[单片机]
迅为IMX6ULL开发Linux驱动初探-最简单的设备驱动-helloworld
经过前面的学习,我们了解了驱动开发的框架,本章节将带领大家实验操作,写最简单的驱动-helloworld。 Linux 设备驱动会以内核模块的形式出现,因为 linux 内核的整体架构就非常庞大,包含的组件也非常多,如果把所有的功能都编译到 linux 内核中会使得内核非常臃肿,为了解决这个问题,更方便地新增和删除功能,linux 提供了这样的机制,这种机制被称为模块。为了大家对模块有一个感性的认识,我们先来看一个最简单的驱动-helloworld。 驱动分为四个部分:  头文件  驱动模块的入口函数和出口函数  声明信息  功能实现 我们在 windows 上面新建一个 helloworld.c 文件,这里使用 sour
[单片机]
迅为<font color='red'>IMX6ULL</font><font color='red'>开发</font>板<font color='red'>Linux</font>驱动初探-最简单的设备驱动-helloworld
迅为IMX6ull开发Linux系统EC20 4G模块移植
1.4G网络连接 对于嵌入式Linux而言,4G网络连接是一个比较容易实现的功能,大多数的4G模块接口都是MiniPCIE接口,但是深入了解一下就会发现,4G模块的通信接口都是USB,所以4G模块的驱动就是USB驱动,只要USB驱动正常,4G模块在硬件上就能正常通信。下面看一下4G模块的硬件原理图: 在原理图中,U25是4G模块的MiniPCIE接口,然后通信引脚会接到U15的HUB芯片上,所以4G模块会被识别成USB设备,CON5是SIM卡接口,在使用4G模块时,需要先插入SIM卡。在i.MX6UL终结者开发板上使用的EC20 4G模块,如图 2. EC20 4G模块配置 2.1. 添加USB设备信息 要使用EC20 4G
[单片机]
迅为<font color='red'>IMX6ull</font><font color='red'>开发</font>板<font color='red'>Linux</font>系统EC20 4G模块移植
迅为IMX6ULL开发Linux INPUT子系统实验-运行测试
输入设备总类繁杂,包括按键,键盘, 触摸屏 ,鼠标,摇杆等等,它们本身都是字符设备,不过内核为了能将这些设备的共性抽象出来,简化驱动的开发,建立了一个 Input 子系统。用户只需要根据内核提供的 input 子系统下提供的 API 函数接口,完成设备的注册即可。在本章节中我们来学习一下如何使用 Linux 内核中的 input 子系统。 1.运行测试 1.1 编译驱动程序 和前面章节中驱动测试程序一样需要一个 Makefile 文件,只是将 obj-m 的值改为 key_input.o,Makefile 文 件内容如下: KERNELDIR := /home/topeet/kernel/linux-imx-rel_imx_4.1
[单片机]
迅为<font color='red'>IMX6ULL</font><font color='red'>开发</font>板<font color='red'>Linux</font> INPUT子系统<font color='red'>实验</font>-运行测试
IMX6ULL学习笔记】一、Linux开发环境搭建
注:参考【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.6 一、Ubuntu 和 Windows 文件互传 在开发的过程中会频繁的在 Windows 和 Ubuntu 下进行文件传输,比如在 Windwos 下进行代码编写,然后将编写好的代码拿到 Ubuntu 下进行编译。Windows 和 Ubuntu 下的文件互传我们需要使用 FTP 服务,设置方法如下: 1、开启 Ubuntu 下的 FTP 服务 打开 Ubuntu 的终端窗口,然后执行如下命令来安装 FTP 服务: sudo apt-get install vsftpd 等待软件自动安装,安装完成后使用 VI 命令打开/etc/vsftpd.conf,如下:
[单片机]
【<font color='red'>IMX6ULL</font>学习笔记】一、<font color='red'>Linux</font><font color='red'>开发</font>环境搭建
IMX6ULL学习笔记】九、Linux内核移植
一、在 Linux 中添加自己的开发板 1、添加开发板默认配置文件 将 arch/arm/configs 目 录 下 的 imx_v7_mfg_defconfig 重新复制一份,命名为 imx_kodo_emmc_defconfig,命令如下: cd arch/arm/configs cp imx_v7_mfg_defconfig imx_kodo_emmc_defconfig 以后就可以使用如下命令来配置正点原子 EMMC 版开发板对应的 Linux 内核了: make imx_kodo_emmc_defconfig 2、添加开发板对应的设备树文件 添加适合 EMMC 版开发板的设备树文件,进入目录 arch/arm/b
[单片机]
【<font color='red'>IMX6ULL</font>学习笔记】九、<font color='red'>Linux</font>内核移植
IMX6ULL学习笔记】十四、Linux调用设备树
一、设备树在系统中的体现 Linux 内核启动的时候会解析设备树中各个节点的信息,并且在根文件系统的 /proc/device/tree 目录下根据节点名字创建不同文件夹,如图所示: 上图就是目录/proc/device-tree 目录下的内容,/proc/device-tree 目录下是根节点“/”的所有属性和子节点。 1、根节点“/”各个属性 根节点属性属性表现为一个个的文件(图中细字体文件),如图中的“#address-cells”、“#size-cells”、“compatible”、“model”和“name”这 5 个文件,它们在设备树中就是根节点的 5 个属性。可以输入 cat 命令来查看 model 和
[单片机]
【<font color='red'>IMX6ULL</font>学习笔记】十四、<font color='red'>Linux</font>调用设备树
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved