Bootstrap

IMX6ULL之使用汇编操作GPIO

        类比于其他的MCU或者微处理器来说,首先学习的是操作GPIO点亮一颗LED灯。通过观察原理图找到与LED灯相关的GPIO口,通过控制GPIO的高低电平即可控制LED的亮灭。只需要该IO口输出低电平即可。

硬件连接

一.STM32初始化示例

以下是一段STM32的GPIO初始化程序:

    可以看到STM32的初始化流程包括以下几个步骤:

1.使能端口时钟

2.配置需要使用的引脚

3.配置GPIO的输入输出模式

4.配置GPIO口的速度

5.输出高低电平

二、IMX6ULL初始化流程

作为处理器来说,IMX6ULL的初始化与STM32的初始化极为相似。初始化包括以下几个部分

1.使能时钟

2.IO口复用

3.配置IO的电气属性

4.配置GPIO输入输出

2.1时钟使能

要想使用处理器内部的功能首先得使能内部的时钟。

打开imx6ull的数据手册,找到时钟控制器模块。

   里面主要有7个控制时钟的寄存器

CCM Clock Gating Register 是时钟控制器的时钟门寄存器,控制系统时钟的通断,主要由

CCM Clock Gating Register 0~6 七个寄存器控制。这里为了简单,可以将七个时钟寄存器全部置

0xFFFFFFFF

表示时钟全部打开

2.2 IO口复用

由上述的硬件原理图可知,控制LED的IO口为IO3

IO口的复用功能主要在参考手册32章

这里将该寄存器的值设置为0x05表示,复用为GPIO1

2.3 IO口功能配置

由上述的硬件原理图可知,控制LED的IO口为IO3

2.4 GPIO功能配置

这节初始化主要参考数据手册28章,配置GPIO的输入输出模式

这节寄存器众多,只需要关注GPIO_DR 、GPIO_GDIR这两个寄存器即可

GPIO_DR寄存器,数据位寄存器,这个寄存器定义GPIO的输出值,当信号被配置在寄存器中。

读取该寄存器也能获取GPIO电平值。

这里可以将第三位设置为低电平,但是其他的io口都用不上,于是可以全部置0

GPIO方向位,该32位的寄存器,可以控制寄存器的位数,从而控制寄存器的方向。当某一个的值位0时,表示是输出模式,数据为1时表示时输出模式。

输入输出模式的话要设置成输出模式,输出模式才能控制io口的电平

三、汇编程序编写

创建一个名为led.s的文件,在文件中输入以下代码

.global    _start @全局标号

_start:
            ldr r0,   =0x020c4068  /* 向寄存器CCM_CCGR0中写入数据 */
            ldr r1,  =0xffffffff
            str r1, [r0]
   
            ldr r0, =0x020c406c     /* 向寄存器CCM_CCGR1中写入数据 */
            str r1 , [r0]

            ldr r0, =0x020c4070     /* 向寄存器CCM_CCGR2中写入数据 */
            str r1 , [r0]

            ldr r0, =0x020c4074     /* 向寄存器CCM_CCGR3中写入数据 */
            str r1 , [r0]

            ldr r0, =0x020c4078     /* 向寄存器CCM_CCGR4中写入数据 */
            str r1 , [r0]

            ldr r0, =0x020c407c     /* 向寄存器CCM_CCGR5中写入数据 */
            str r1 , [r0]

            ldr r0, =0x020c4080     /* 向寄存器CCM_CCGR6中写入数据 */
            str r1 , [r0]

            /*配置GPIO1——IO3 */
            ldr  r0,   =0x02e00068    
            ldr r1,  =0x00000005    
            str r1, [r0]

            /* 配置GPIO1_IO03的电气属性 
             * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
             * 寄存器地址 020e02f4
             * bit 0   0 低
             * bit 5-3 驱动能力
             * bit 7-6 速度
             * bit 11 ODMODE
             * bit 12   1
             * bit 13   0
             * bit 15-14  上下拉电阻
             * bit 16: 0   
             */
             ldr r0, =0x020e02f4
             ldr r1, =0x10b0
             str r1, [r0]

             
             ldr r0, =0x0209c004    /*控制GDTR寄存器为输出模式*/
             ldr r1, =0x8
             str r1, [r0]

             ldr r0, =0x0209c000    /*控制DR寄存器输出低电平*/
             ldr r1, =0
             str r1, [r0]

loop:
    b loop

四、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

Makefile的目标是要生成一个led.bin文件,上述代码中 led.bin为目标文件

led.s为依赖文件。

arm-linux-gnueabihf-gcc -g -c led.s -o led.o

使用交叉编译器编译,其中-g是生成调试信息,-c是编译文件不链接文件。

即 使用交叉编译器编译 led.s文件,产生调试信息,生成led.o文件,且不链接。

arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

其中arm-linux-gnueabihf-ld 后面的-ld表示链接文件。-Ttext表示开始的地址。

使用交叉编译器对led.o从0x87800000处开始链接文件,最终生成一个led.elf的链接文件

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

-objcopy表示使用一个objcopy的工具,进行文件格式转换, -O binary 以二进制格式输出

-S 去掉符号表和调试信息 -g保留调试信息。

arm-linux-gnueabihf-objdump -D led.elf > led.dis

-objdump,是一个可以进行反汇编的工具 -D表示所有部分进行反汇编。最终会生成一个led.dis反汇编文件。

五、烧录代码

给烧录器权限

chmod 777 imxdownload

查看是否有SD卡设备

ls /dev/sd*

这样可以看到文件目录下的所有的磁盘信息

我这里的磁盘为sdb,如果不知道磁盘是哪个,可以拔插读卡器来确定。

向sd卡中烧录bin文件,这里要根据自己的sd卡识别的磁盘区域进行读写

./imxdownload led.bin /dev/sdb

烧写完成后,可以看到以下烧录信息

给板子上电后,可以看到led灯亮

;