I.MX6ULL裸机LED驱动实验过程
时间:2022-10-28 23:30:00
查看数据,编写驱动程序
首先检查底板数据找到led看硬件数据LED需要GPIO3
GPIO3对应着GPIO1_IO03.
查看芯片的参考手册GPIO03有两个寄存器分别为复用寄存器:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO配置寄存器:IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03。
但在此之前需要使能GPIO1时钟。
什么是使能时钟?
我们在进行STM32编程时,你会发现,无论你想做什么,你必须做的第一件事就是使时钟能够。随着电子产品集成越来越高,功耗和加热越来越严重,芯片制造商非常无助,开始找到避免这个问题的方法,当然,最直接的想法是使用多少功能,每个外部时钟设置开关,让用户能够准确控制,关闭不必要的设备,以达到节约电源的目的。如果你不使用它,完全关闭它,尽可能减少芯片功耗,所以有这么多时钟和时钟IO配置。说白了,时钟的功能就像一个小开关,你要用什么寄存器就先打开相应的开关,即:即使是相应的时钟。
寻找时钟寄存器gpio1找到GOIO1的时钟由CCM_CCGR1 的 bit27 和 bit26 控制这两个位置,设置这两个位置 11 即可。
找到了复用寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”的地址为
0X020E0068,然后设置此寄存器 GPIO1_IO03 这个 IO 复用为 GPIO 功能,也就是 ALT5。
找到 GPIO1_IO03 配置寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03”的地址为
0X020E02F4,配置LED硬件信息。
本实验中 GPIO1_IO03 它被用作输出功能, GPIO1_GDIR 的 bit3 要设置为 一、表示输出。
接着创建led.s代码如下:
.global _start @全局标号 _start: /*所有外设时钟 */ ldr r0, =0x020c4068 @CCGR0 ldr r1, =0xffffffff @要向CCGR0写入的数据 str r1, [r0] @将0xffffffff写入到CCGR0中 ldr r0, =0x020c406c @CCGR1 str r1, [r0] ldr r0, =0x020c4070 @CCGR2 str r1, [r0] ldr r0, =0x020c4074 @CCGR3 str r1, [r0] ldr r0, =0x020c4078 @CCGR4 str r1, [r0] ldr r0, =0x020c407c @CCGR5 str r1, [r0] ldr r0, =0x020c4080 @CCGR6 str r1, [r0] /* 配置 GPIO1_IO03 PIN的复用为GPIO,也就是设置 * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03=5 * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03寄存器地址为0X020E0068 */ ldr r0, =0x020E0068 @IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 ldr r1, =0x5 @要写的数据 str r1, [r0] @将5写入到IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03中 /* 配置GPIO1_IO03的电气属性 也就是寄存器: * IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 * IOMUXC_SW_PD_CTL_PAD_GPIO1_IO03寄存器地址为0x020e02f4 * * bit0: 0 低速率 * bit5:3: 110 R0/6驱动能力 * bit7:6: 10 100MHz速度 * bit11: 0 关闭开路输出 * bit12: 1 使能pull/kepper * bit13: 0 kepper * bit15:14:00 100K下拉 * bit16: 0 关闭hys */
ldr r0, =0x020e02f4
ldr r1, =0x10b0
str r1, [r0]
/* 设置GPIO * 设置GPIO1_GDIR寄存器,设置GPIO1_GPIO03为输出 * GPIO1_GDIR寄存器地址为0x0209c004,设置GPIO1_GDIR寄存器bit3为1, * 也就是设置GPIO1_IO03为输出。 */
ldr r0, = 0x0209c004
ldr r1, = 0x8
str r1, [r0]
/* 打开LED,也就是设置GPIO1_IO03为0 * GPIO1_DR寄存器地址为0x0209c000 */
ldr r0, =0x0209c000
ldr r1, =0
str r1, [r0]
loop:
b loop
第 2 行定义了一个全局标号_start,代码就是从_start 这个标号开始顺序往下执行的。
第 11 行使用 ldr 指令向寄存器 r0 写入 0X020C4068,也就是 r0=0X020C4068,这个是CCM_CCGR0 寄存器的地址。
第 12 行使用 ldr 指令向寄存器 r1 写入 0XFFFFFFFF,也就是 r1=0XFFFFFFFF。因为我们要开启所有的外设时钟,因此 CCM_CCGR0~CCM_CCGR6 所有寄存器的 32 位都要置 1,也就是写入 0XFFFFFFFF。
第 13 行使用 str 将 r1 中的值写入到 r0 所保存的地址中去,也就是给 0X020C4068 这个地址写入 0XFFFFFFFF,相当于 CCM_CCGR0=0XFFFFFFFF,就是打开 CCM_CCGR0 寄存器所控制的所有外设时钟。
第 15~31 行都是向 CCM_CCGRX(X=1~6)寄存器写入 0XFFFFFFFF。这样我就通过汇编代码使能了 I.MX6U 的所有外设时钟。
第35~37行是设置GPIO1_IO03的复用功能, GPIO1_IO03的复用寄存器地址为0X020E0068,寄 存 器 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的 MUX_MODE 设 置 为 5 就 是 将GPIO1_IO03 设置为 GPIO。
第 49~51 行 是 设 置 GPIO1_IO03 的 配 置 寄 存 器 , 也 就 是 寄 存 器IOMUX_SW_PAD_CTL_PAD_GPIO1_IO03 的值,此寄存器地址为 0X020E02F4,代码里面已经
给出了这个寄存器详细的位设置。
第 54~63 行是设置 GPIO 功能,经过上面几步操作, GPIO1_IO03 这个 IO 已经被配置为了GPIO 功能,所以还需要设置跟 GPIO 有关的寄存器。第 54~56 行是设置 GPIO1->GDIR 寄存器,将 GPIO1_IO03 设置为输出模式,也就是寄存器的 GPIO1_GDIR 的 bit3 置 1。
第 61~63 行设置 GPIO1->DR 寄存器,也就是设置 GPIO1_IO03 的输出,我们要点亮开发板上的 LED0,那么 GPIO1_IO03 就必须输出低电平,所以这里设置 GPIO1_DR 寄存器为 0。
第 68~69 行是死循环,通过 b 指令, CPU 重复不断的跳到 loop 函数执行,进入一个死循环
编译程序
①、使用arm-linux-gnueabihf-gcc,将.c .s文件变为.o
②、将所有的.o文件连接为elf格式的可执行文件。
③、将elf文件转为bin文件。
④、将elf文件转为汇编,反汇编。
arm-linux-gnueabihf-gcc -g -c led1.s -o led1.o
arm-linux-gnueabihf-ld -Ttext 0x87800000 led1.o -o led1.elf
arm-linux-gnueabihf-objcopy -O binary -S -g led1.elf led1.bin
arm-linux-gnueabihf-objdump -D led1.elf > led1.dis
本教程所有裸机例程的链接地址都在 DDR
中,链接起始地址为 0X87800000。 I.MX6U-ALPHA 开发板的 DDR 容量有两种: 512MB 和256MB,起始地址都为 0X80000000,只不过 512MB 的终止地址为 0X9FFFFFFF,而 256MB 容量的终止地址为 0X8FFFFFFF。之所以选择 0X87800000 这个地址是因为后面要讲的 Uboot 其链接地址就是 0X87800000,这样我们统一使用 0X87800000 这个链接地址,不容易记混。
代码烧写
将自带的烧写工具imxdownload放在工程目录下给予可执行权限
找到TF卡格式化为FAT32格式连接到虚拟机上。通过命令/dev/sd*查看节点,插入后多的一个节点就是TF卡的设备节点
运行./imxdownload led.bin /dev/sdb(我的节点是sdb)
生成load.imx说运行成功。
将TF卡插到sd卡槽里将拨码开关设置为1和7开,插上电源打开开关就可以看到红灯亮