04 IMX6ULL裸机开发:程序示例(LED程序)

创建时间:2022/1/14 11:28
更新时间:2022/2/16 17:12
作者:gi51wa2j
标签:100ask_IMX6ULL_v11, bingo, 操作, 正文

一、硬件知识-LED原理图

1.1 本节程序流程

①看原理图,确定控制LED 的引脚;

②看主芯片的芯片手册,确定如何设置控制这个引脚;

③写程序。

1.2 硬件知识

方式1:使用引脚输出3.3V点亮LED,输出0V熄灭LED。

方式2:使用引脚拉低到0V点亮LED,输出3.3V熄灭LED。

方式3:使用引脚输出1.2V点亮LED,输出0V熄灭LED。(引脚驱动能力不足时使用三极管)

方式4:使用引脚输出0V点亮LED,输出1.2V熄灭LED。

二、100ASK_IMX6ULL的LED程序

代码
4_led.zip
原理图:网盘开发板配套资料“05_Hardware (原理图)/Base_board/100ask_imx6ull_v1.1.pdf”。

2.1 看原理图确定引脚及操作方法

从上图可知,这个 LED 用到了GPIO5_3引脚。
在芯片手册里,这引脚的名字是:GPIO5_IO03,可以根据名字搜到对应的寄存器。
当这些引脚输出低电平时,对应的LED被点亮;输出高电平时,LED熄灭。

2.2 所涉及的寄存器操作

(CCM使能是自行添加的,此图添加使能更方便理解GPIO工作所需寄存器使用)

2.2.1 使能GPIO5的时钟


设置b[31:30]就可以使能GPIO5,设置为什么值呢?
注意在imx6ullrm.pdf中,CCM_CCGR1的b[31:30]是保留位;我以前写程序时错用了imx6ul(不是imx6ull)的手册,导致程序中额外操作了这些保留位。不去设置b[31:30],GPIO5也是默认使能的。

看下图,设置为0b11:
① 00:该GPIO模块全程被关闭
② 01:该GPIO模块在CPU run mode情况下是使能的;在WAIT或STOP模式下,关闭
③ 10:保留
④ 11:该GPIO模块全程使能
/* GPIO5_IO03 */

/* a. 使能GPIO5

 * set CCM to enable GPIO5

 * CCM_CCGR1[CG15] 0x20C406C

 * bit[31:30] = 0b11

 */

2.2.2 设置GPIO5_IO03为GPIO模式

设置如下寄存器:
/* b. 设置GPIO5_IO03用于GPIO

 * set IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3

 *      to configure GPIO5_IO03 as GPIO

 * IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 0x2290014

 * bit[3:0] = 0b0101 alt5

 */

2.2.3 设置GPIO5_IO03为输出引脚,设置其输出电平

寄存器地址为:
设置方向寄存器,把引脚设置为输出引脚:
设置数据寄存器,设置引脚的输出电平:
/* c. 设置GPIO5_IO03作为output引脚

 * set GPIO5_GDIR to configure GPIO5_IO03 as output

 * GPIO5_GDIR  0x020AC000 + 0x4

 * bit[3] = 0b1

 */

 

/* d. 设置GPIO5_DR输出低电平

 * set GPIO5_DR to configure GPIO5_IO03 output 0

 * GPIO5_DR 0x020AC000 + 0

 * bit[3] = 0b0

 */

 

/* e. 设置GPIO5_IO3输出高电平

 * set GPIO5_DR to configure GPIO5_IO03 output 1

 * GPIO5_DR 0x020AC000 + 0

 * bit[3] = 0b1

 */

2.3 写程序

     led.c是重点,其他文件暂且不关心,比如Makefile、imx6ull.lds,这些文件的知识在后面再介绍。

     led_init函数会初始化LED引脚:使能、设置为GPIO模式、设置为输出引脚。

     值得关注的是第13~16行,在C语言中使用指针来访问寄存器,需要先设置指针的值,即它指向哪个地址──当然是寄存器的地址:

02 #include "led.h"

03

04 static volatile unsigned int *CCM_CCGR1                              ;

05 static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;

06 static volatile unsigned int *GPIO5_GDIR                             ;

07 static volatile unsigned int *GPIO5_DR                               ;

08

09 void led_init(void)

10 {

11      unsigned int val;

12

13      CCM_CCGR1 = (volatile unsigned int *)(0x20C406C);

14   IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = (volatile unsigned int *)(0x2290014);

15      GPIO5_GDIR  = (volatile unsigned int *)(0x020AC000 + 0x4);

16      GPIO5_DR    = (volatile unsigned int *)(0x020AC000);

17

18      /* GPIO5_IO03 */

19      /* a. 使能GPIO5

20       * set CCM to enable GPIO5

21       * CCM_CCGR1[CG15] 0x20C406C

22       * bit[31:30] = 0b11

23       */

24      *CCM_CCGR1 |= (3<<30);

25

26      /* b. 设置GPIO5_IO03用于GPIO

27       * set IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3

28       *      to configure GPIO5_IO03 as GPIO

29       * IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3  0x2290014

30       * bit[3:0] = 0b0101 alt5

31       */

32      val = *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;   //临时变量

33      val &= ~(0xf);                                       //清零

34      val |= (5);                                          //置位

35      *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = val;

36

37

38      /* c. 设置GPIO5_IO03作为output引脚

39       * set GPIO5_GDIR to configure GPIO5_IO03 as output

40       * GPIO5_GDIR  0x020AC000 + 0x4

41       * bit[3] = 0b1

42       */

43      *GPIO5_GDIR |= (1<<3);

44

45 }

46

led_ctl函数会根据参数设置LED引脚的输出电平:
47 void led_ctl(int on)

48 {

49      if (on) /* on: output 0*/

50      {

51              /* d. 设置GPIO5_DR输出低电平

52               * set GPIO5_DR to configure GPIO5_IO03 output 0

53               * GPIO5_DR 0x020AC000 + 0

54               * bit[3] = 0b0

55               */

56              *GPIO5_DR &= ~(1<<3);

57      }

58      else  /* off: output 1*/

59      {

60              /* e. 设置GPIO5_IO3输出高电平

61               * set GPIO5_DR to configure GPIO5_IO03 output 1

62               * GPIO5_DR 0x020AC000 + 0

63               * bit[3] = 0b1

64               */

65              *GPIO5_DR |= (1<<3);

66      }

67 }

2.4 程序的布局与运行

有疑问则去复习:
02 IMX6ULL裸机开发:IMX6ULL启动流程解析

2.5 编译程序

要编译程序,需要有交叉编译工具链。可以使用在线下载方式下载工具链,然后设置交叉编译工具链,请参考:
01 IMX6ULL裸机开发:初始环境搭建
然后,使用FileZilla把windows下的4_led目录上传到Ubuntu中。
最后在Ubuntu中进入4_led执行make命令即可生成led.imx、led.img

(注意:
前文在01章节中,我们在配置交叉编译环境时,配置了永久的交叉编译环境,使用make命令式,要注意Makefile文件中的命令前缀,PREFIX参数是否和之前环境配置的一样,若有不同,修改即可。
vim  ~/.bashrc
export ARCH=arm export CROSS_COMPILE=arm-buildroot-linux-gnueabihf- export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
最终结果跑如下:
注意:建议在Ubuntu中目录名不要含空格,使用中文目录名是可以的。
注意:执行make命令后会编译程序、制作映象文件,具体过程以后会详细介绍,这不是本章的内容。
注意:如果有以下错误,执行“chmod +x tools/mkimage”后再次执行make即可:

2.6上机实验

参考00 IMX6ULL裸机开发:程序工具|烧写整个系统或更新部分系统
注意:烧录时注意拨动开关是否到相应位置,USB接口是否正确链接,SD卡是否拔出
注意:烧写、运行led程序时,串口是没有输出的,这只是一个点灯程序没用到串口。
注意:编译下载时一定要注意虚拟机,是否虚拟机拦截了自己的下载程序。直接挂起接口
注意:烧写到emmc时可以直接烧写imx文件,而直接烧写TF/SD卡运行时需要烧写img文件,因为硬件规定头部需要1kb的空间