当前位置:网站首页>IMX6ULL—汇编LED灯

IMX6ULL—汇编LED灯

2022-08-09 17:06:00 梅山剑客

I.MX6U IO 命名

参考手册的第 32 章:
在这里插入图片描述
分为SNVS域和通用的,本质上都是一样的。

“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”的是 GPIO 命名,命名形式就是“IOMUXC_SW_MUC_CTL_PAD_XX_XX”,后面的“XX_XX”就是 GPIO 命名,比如:GPIO1_IO01、UART1_TX_DATA、JTAG_MOD 等等。

I.MX6U IO 复用

以“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”这个 IO 为例:
在这里插入图片描述
可以看到有个名为:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00 的寄存器,寄存器地址为 0X020E005C,这个寄存器是 32 位的,但是只用到了最低 5 位,其中bit0 - bit3(MUX_MODE)就是设置 GPIO1_IO00 的复用功能的。GPIO1_IO00 一共可以复用为 9种功能 IO,分别对应 ALT0~ALT8,其中 ALT5 就是作为 GPIO1_IO00。GPIO1_IO00 还可以作为 I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID 等。这个就是 I.MX6U 的 IO 复用。

如果只想看每个 IO 能复用什么外设的话可以直接查阅《IMX6ULL 参考手册》的第 4 章“Chapter 4 External Signals and Pin Multiplexing”。如果要编写代码,设置某个 IO 的复用功能的话就需要查阅第 32 章“Chapter 32: IOMUX Controller(IOMUXC)”,第 32 章详细的列出了所有 IO 对应的复用配置寄存器。

I.MX6U IO 配置

GPIO1_IO00 有如下两个书签:

IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00
IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00

在这里插入图片描述
IOMUX_SW_MUX_CTL_PAD_GPIO1_IO00 是用来配置GPIO1_IO00 复用功能的。

IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 是用来配置 GPIO1_IO00 的,包括速度设置、驱动能力设置、压摆率设置等等。

I.MX6U GPIO 配置

在这里插入图片描述
如上图左 下 角 的 IOMUXC 框 图 里 面 就 有 SW_MUX_CTL_PAD_* 和SW_PAD_CTL_PAD_*两种寄存器。这两种寄存器前面说了用来设置 IO 的复用功能和 IO 属性配置。左上角部分的 GPIO 框图就是,当 IO 用作 GPIO 的时候需要设置的寄存器,一共有八个:DR、GDIR、PSR、ICR1、ICR2、EDGE_SEL、IMR 和 ISR

DR 寄存器

输出:0或者1
在这里插入图片描述
此寄存器是 32 位的,一个 GPIO 组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应
一个 GPIO。

要设置 GPIO1_IO00 输出高电平,那么就应该设置 GPIO1.DR=1。

当 GPIO被配置为输入模式以后,此寄存器就保存着对应 IO 的电平值,每个位对对应一个 GPIO,例如,当 GPIO1_IO00 这个引脚接地的话,那么 GPIO1.DR 的 bit0 就是 0。

GDIR 寄存器

在这里插入图片描述
设置 GPIO 为输入,就设置相应的位为 0,如果要设置为输出的话就设置为 1。比如要设置 GPIO1_IO00 为输入,那么 GPIO1.GDIR=0;

PSR 寄存器

在这里插入图片描述
同样的 PSR 寄存器也是一个 GPIO 对应一个位,读取相应的位即可获取对应的 GPIO 的状态,也就是 GPIO 的高低电平值。功能和输入状态下的 DR 寄存器一样。

ICR1和ICR2寄存器

ICR1用于配置低16个GPIO,ICR2 用于配置高 16 个 GPIO。
在这里插入图片描述
ICR1 用于 IO0-15 的配置, ICR2 用于 IO16~31 的配置。ICR1 寄存器中一个 GPIO 用两个位,这两个位用来配置中断的触发方式,和 STM32 的中断很类似,可配置的选线如表。
在这里插入图片描述

IMR 寄存器—中断屏蔽寄存器

在这里插入图片描述
IMR 寄存器也是一个 GPIO 对应一个位,IMR 寄存器用来控制 GPIO 的中断禁止和使能,如果使能某个 GPIO 的中断,那么设置相应的位为 1 即可,反之,如果要禁止中断,那么就设置相应的位为 0 即可。例如,要使能 GPIO1_IO00 的中断,那么就可以设置 GPIO1.MIR=1。

ISR寄存器—中断状态寄存器

在这里插入图片描述
ISR 寄存器也是 32 位寄存器,一个 GPIO 对应一个位,只要某个 GPIO 的中断发生,那么ISR 中相应的位就会被置 1。所以,可以通过读取 ISR 寄存器来判断 GPIO 中断是否发生,相当于 ISR 中的这些位就是中断标志位。当处理完中断以后,必须清除中断标志位,清除方法就是向 ISR 中相应的位写 1,也就是写 1 清零。

EDGE_SEL 寄存器—边沿选择寄存器

在这里插入图片描述

EDGE_SEL 寄存器用来设置边沿中断,这个寄存器会覆盖 ICR1 和 ICR2 的设置,同样是一个 GPIO 对应一个位。如果相应的位被置 1,那么就相当与设置了对应的 GPIO 是上升沿和下降沿(双边沿)触发。例如,设置 GPIO1.EDGE_SEL=1,那么就表示 GPIO1_IO01 是双边沿触发中断,无论 GFPIO1_CR1 的设置为多少,都是双边沿触发。

关于 GPIO 的寄存器就讲解到这里,因为 GPIO 是最常用的功能,详细的讲解了 GPIO的 8 个寄存器。 I.MX6U 的 IO 是需要配置和输出的、是可以设置输出高低电平,也可以读取 GPIO 对应的电平。

I.MX6U GPIO 时钟使能

CCM_CCGR0 结构体如图:
在这里插入图片描述
CCM_CCGR0 是个 32 位寄存器,其中每 2 位控制一个外设的时钟,比如 bit31:30 控制着GPIO2 的外设时钟,两个位就有 4 种操作方式,如表所示:
在这里插入图片描述
如果要打开 GPIO2 的外设时钟,那么只需要设置CCM_CCGR0 的 bit31 和 bit30 都为1即可,也就是CCM_CCGR0=3 << 30。反之,如果要关闭GPIO2 的外设时钟,那就设置 CCM_CCGR0 的 bit31和bit30都为0即。

总结一下,要将 I.MX6U 的 IO 作为 GPIO 使用,需要以下几步:
①、使能 GPIO 对应的时钟。

②、设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置 IO 的复用功能,使其复用为 GPIO 功能。

③、设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置 IO 的上下拉、速度等等。

④、第②步已经将 IO 复用为了 GPIO 功能,所以需要配置 GPIO,设置输入/输出、是否使用中断、默认输出电平等。

汇编点灯实例

在这里插入图片描述

1、使能 GPIO1 时钟

GPIO1 的时钟由 CCM_CCGR1 的 bit27 和 bit26 这两个位控制,将这两个位都设置位 11 即可。

2、设置 GPIO1_IO03 的复用功能

找到 GPIO1_IO03 的复用寄存器“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”的地址为0X020E0068,然后设置此寄存器,将 GPIO1_IO03 这个 IO 复用为 GPIO 功能,也就是 ALT5。

3、配置 GPIO1_IO03

找到 GPIO1_IO03 的配置寄存器“IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03”的地址为0X020E02F4,根据实际使用情况,配置此寄存器。

4、设置 GPIO

将 GPIO1_IO03 复用为了 GPIO 功能,所以需要配置 GPIO。找到 GPIO3 对应的 GPIO 组寄存器地址,在《IMX6ULL 参考手册》的 1357 页,如图所示:
在这里插入图片描述
实验中 GPIO1_IO03 是作为输出功能的,因此 GPIO1_GDIR 的 bit3 要设置为 1,表示输出。

5、控制 GPIO 的输出电平

经过前面几步,GPIO1_IO03 已经配置好了,只需要向 GPIO1_DR 寄存器的 bit3 写入 0 即可控制 GPIO1_IO03 输出低电平,打开 LED,向 bit3 写入 1 可控制 GPIO1_IO03 输出高电平,关闭 LED。

.global _start  /* 全局标号 */
//定义了一个全局标号_start,代码就是从_start 这个标号开始顺序往下执行的。
/* * 描述: _start函数,程序从此函数开始执行此函数完成时钟使能、 * GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。 */
_start:
	/* 例程代码 */
	/* 1、使能所有时钟 */
	//CCGR0 
	ldr r0, =0X020C4068 	/* 使用 ldr 指令向寄存器 r0 写入 0X020C4068,也就是 r0=0X020C4068,这个是CCM_CCGR0 寄存器的地址*/
	ldr r1, =0XFFFFFFFF /*使用 ldr 指令向寄存器 r1 写入 0XFFFFFFFF,也就是 r1=0XFFFFFFFF。因为要开启所有的外设时钟,因此 CCM_CCGR0~CCM_CCGR6 所有寄存器的 32 位都要置 1,也就是写入 0XFFFFFFFF。*/ 
	str r1, [r0]		/*使用 str 将 r1 中的值写入到 r0 所保存的地址中去,也就是给 0X020C4068 这个地址写入 0XFFFFFFFF,相当于 CCM_CCGR0=0XFFFFFFFF,就是打开 CCM_CCGR0 寄存器所控制的所有外设时钟。*/
	
	//开启CCGR1的时钟
	ldr r0, =0X020C406C  	/* CCGR1 */
	str r1, [r0]
	//开启CCGR2的时钟
	ldr r0, =0X020C4070  	/* CCGR2 */
	str r1, [r0]
	//开启CCGR3的时钟
	ldr r0, =0X020C4074  	/* CCGR3 */
	str r1, [r0]
	//开启CCGR4的时钟
	ldr r0, =0X020C4078  	/* CCGR4 */
	str r1, [r0]
	//开启CCGR5的时钟
	ldr r0, =0X020C407C  	/* CCGR5 */
	str r1, [r0]
	//开启CCGR6的时钟
	ldr r0, =0X020C4080  	/* CCGR6 */
	str r1, [r0]
	

	/* 2、设置GPIO1_IO03复用为GPIO1_IO03 */
	ldr r0, =0X020E0068	/* 将寄存器SW_MUX_GPIO1_IO03_BASE加载到r0中 */
	ldr r1, =0X5		/* 设置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE为5 */
	str r1,[r0]

	/* 3、配置GPIO1_IO03的IO属性 *bit 16:0 HYS关闭 *bit [15:14]: 00 默认下拉 *bit [13]: 0 kepper功能 *bit [12]: 1 pull/keeper使能 *bit [11]: 0 关闭开路输出 *bit [7:6]: 10 速度100Mhz *bit [5:3]: 110 R0/6驱动能力 *bit [0]: 0 低转换率 */
    ldr r0, =0X020E02F4	/*寄存器SW_PAD_GPIO1_IO03_BASE */
    ldr r1, =0X10B0
    str r1,[r0]

	/* 4、设置GPIO1_IO03为输出 */
    ldr r0, =0X0209C004	/*寄存器GPIO1_GDIR */
    ldr r1, =0X0000008		
    str r1,[r0]

	/* 5、打开LED0 * 设置GPIO1_IO03输出低电平 */
	ldr r0, =0X0209C000	/*寄存器GPIO1_DR */
   ldr r1, =0		
   str r1,[r0]

/* * 描述: loop死循环 */
loop:
	b loop 				

	

编译命令

arm-linux-gnueabihf-gcc -g -c led.s -o led.o
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
arm-linux-gnueabihf-objdump -D led.elf > led.dis

makefile文件

led.bin:led.s
	 arm-linux-gnueabihf-gcc -g -c led.s -o led.o
	 arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
	 arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
	 arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
	rm -rf *.o led.bin led.elf led.dis

连接脚本文件

arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^
示例代码 10.4.2.2 imx6ul.lds 链接脚本代码
1 SECTIONS{
    
2 . = 0X87800000;
	3 .text :
	4 {
    
	5 start.o 
	6 main.o 
	7 *(.text)
	8 }
	9 .rodata ALIGN(4) : {
    *(.rodata*)} 
	10 .data ALIGN(4) : {
     *(.data) } 
	11 __bss_start = .; 
	12 .bss ALIGN(4) : {
     *(.bss) *(COMMON) } 
	13 __bss_end = .;
14 }

代码烧写

烧写格式:

./imxdownload <.bin file> <SD Card>

其中.bin 就是要烧写的.bin 文件,SD Card 就是要烧写的 SD 卡。

./imxdownload led.bin /dev/sdd //不能烧写到/dev/sda 或 sda1 设备里面!那是系统磁盘

现象

在这里插入图片描述

原网站

版权声明
本文为[梅山剑客]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_46152793/article/details/126240023