#|阿尔法点亮LED灯(一)汇编语言


文章目录

  • 前言
  • 一、GPIO介绍
    • 1.MX6U IO 复用
    • 2.MX6U IO 配置
    • 3.GPIO 配置
    • 4.GPIO 时钟使能
    • 5.==GPIO的使用步骤==
  • 二、程序编写
    • 1.使能 GPIO1 时钟
    • 2.设置 GPIO1_IO03 的复用功能
    • 3.配置 GPIO1_IO03属性
    • 4.设置GPIO1_IO03为输出
    • 5.控制 GPIO 的输出电平
  • 三、编写Makefile
    • 1.arm-linux-gnueabihf-gcc 编译文件
    • 2.arm-linux-gnueabihf-ld链接文件
    • 3.arm-linux-gnueabihf-objcopy 格式转换
    • 4.arm-linux-gnueabihf-objdump 反汇编
    • 5.Makefile
  • 四、烧录代码
    • 1.赋予可执行权限
    • 2.挂载SD卡
    • 3.烧写bin文件
  • 总结

前言 点亮阿尔法板子的的LED,点灯的过程基本上和STM32一样的,但是,阿尔法是在Linux下进行编写烧录的,环境的匹配花费了我巨大的时间,中间还因为不小心向系统磁盘写入数据,系统直接崩了,又得重来..... 提示:以下是本篇文章正文内容,下面案例可供参考
一、GPIO介绍 【#|阿尔法点亮LED灯(一)汇编语言】阿尔法GPIO命名规则
eg:
1.IOMUXC_SW_MUCCTL_PAD_XX_XX =>(IO复用功能)
2.IOMUXC_SW
- PAD_CTL_PAD_XX_XX => (IO属性配置)
其是根据某个IO所拥有的功能来命名的,比如GPIO1_IO01做GPIO引脚
第一个和第二个主要是MCU和PAD的区别
1.MX6U IO 复用 以IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO01为例
#|阿尔法点亮LED灯(一)汇编语言
文章图片

只要低5位用到了,我们来看看低4位
#|阿尔法点亮LED灯(一)汇编语言
文章图片

设置不同的0,1就是这个IO选择不同的复用功能(是不是和32差不多啊)
其中bit0-bit3(MUX_MODE)就是设置 GPIO1_IO00 的复用功能的。GPIO1_IO00 一共可以复用为 9种功能 IO,分别对应 ALT0~ALT8,其中 ALT5 就是作为 GPIO1_IO00
2.MX6U IO 配置 以IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO01为例
#|阿尔法点亮LED灯(一)汇编语言
文章图片

寄存器地址为 0X020E02E8,只用到了其中的低 17 位
GPIO 功能图:
#|阿尔法点亮LED灯(一)汇编语言
文章图片

1.HYS
用来使能迟滞比较器,为 0 的时候禁止迟滞比较器,为 1 的时候使能迟滞比较器
2.PUS
用来设置上下拉电阻的
位设置 含义
00 100下拉
01 47k上拉
10 100k上拉
11 22k上拉
3.PUE
用来设置 IO 使用上下拉还是状态保持器。当为 0 的时候使用状态保持器,当为 1 的时候使用上下拉
4.ODE
当 IO 作为输出的时候,此位用来禁止或者使能开
路输出,此位为 0 的时候禁止开路输出,当此位为 1 的时候就使能开路输出功能
5.SPEED
设置 IO 速度
位设置 速度
00 低速50M
01 中速100M
10 中速100M
11 最大速度200M
6.DSE
当 IO 用作输出的时候用来设置 IO 的驱动能力
位设置 速度
000 输出驱动关闭
001 R0
010 R0/2
011 R0/3
100 R0/4
101 R0/5
110 R0/6
111 R0/7
注:3.3V 下 R0 是 260Ω, 1.8V 下 R0 是 150Ω,接 DDR 的时候是 240Ω
值越大驱动能力更强
7.SRE
设置压摆率,为 0 的时候是低压摆率,为 1的时候是高压摆率。压摆率指IO 电平跳变所需要的时间,比如从 0 到 1 需要多少时间,时间越小波形就越陡,说明压摆率越高;反之,时间越多波形就越缓,压摆率就越低
所以,寄存器 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 是用来配
置 GPIO1_IO00 的,包括速度设置、驱动能力设置、压摆率设置
3.GPIO 配置 IOMUXC_SW_MUX_CTL_PAD_XX_XX 和IOMUXC_SW_PAD_CTL_PAD_XX_XX 这两种寄存器都是配置 IO 的, GPIO 是一个 IO 众多复用功能中的一种, 所以,还需要对其 GPIO 的功能进行配置
GPIO结构如图
#|阿尔法点亮LED灯(一)汇编语言
文章图片

当 IO 用作 GPIO 的时候需要设置的寄存器,DR、 GDIR、 PSR、 ICR1、 ICR2、 EDGE_SEL、 IMR 和 ISR一个八个,MX6U 一共有
GPIO1~GPIO5 共五组 GPIO,每组 GPIO 都有这 8 个寄存器
(1) DR (数据寄存器)寄存器
此寄存器是 32 位的,一个 GPIO 组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应一个 GPIO。当 GPIO 被配置为输出功能以后,向指定的位写入数据那么相应的 IO 就会输出相应的高低电平;当 GPIO被配置为输入模式, 寄存器就保存着对应 IO 的电平值,每个位对对应一个 GPIO
eg:设置 GPIO1_IO00 输出高电平,那么就应该设置 GPIO1.DR=1
(2) GDIR(方向寄存器) 寄存器
用来设置某个 GPIO 的工作方向的,即输入(0)/输出(1)
eg:设置 GPIO1_IO00 为输入,那么 GPIO1.GDIR=0
(3)PSR( 状态寄存器) 寄存器
读取相应的位即可获取对应的 GPIO 的状态,也就是 GPIO 的高低电平值
(3)ICR1/ ICR2(中断控制寄存器)寄存器
ICR1用于配置低16个GPIO,ICR2 用于配置高 16 个 GPIO,一个 GPIO GPIO用两个位来配置中断的触发方式
位设置 方式
00 低电平触发
01 高电平触发
10 上升沿触发
11 下降沿触发
eg:设置GPIO1_IO15为上升沿触发中断,GPIO1.ICR1= 2<<30
(4) IMR(中断屏蔽寄存器) 寄存器
用来控制 GPIO 的中断禁止(0)和使能(1)
eg:要使能 GPIO1_IO00 的中断,设置 GPIO1.MIR=1
(5)ISR(中断状态寄存器)
只要某个 GPIO 的中断发生,ISR 中相应的位就会被置 1, 通过读取 ISR 寄存器来判断 GPIO 中断是否发生(中断标志位), 当我们处理完中断以后,必须清除中断标志位,清除方法就是向 ISR 中相应的位写 1,也就是写 1 清零
(6)EDGE_SEL(边沿选择寄存器)寄存器
设置边沿中断,会覆盖 ICR1 和 ICR2 的设置,如果相应的位被置 1,那么就相当与设置了对应的 GPIO 是上升沿和下降沿(双边沿)触发
eg:设置 GPIO1.EDGE_SEL=1,表示 GPIO1_IO01 是双边沿触发中断,无论 GFPIO1_CR1 的设置为多少,都是双边沿触发
这些寄存器都是用来配置GPIO的输入/输出,高/低电平…
4.GPIO 时钟使能 阿尔法每个外设对应一个外设时钟,CMM 有
CCM_CCGR0~CCM_CCGR6 这 7 个寄存器,这 7 个寄存器控制着 MX6U 的所有外设时钟开关,都是32 位寄存器,其中每 2 位控制一个外设的时钟
#|阿尔法点亮LED灯(一)汇编语言
文章图片

不同的位控制着不同外设的时钟,在这里为了方便,将所有外设时钟都打开
5.GPIO的使用步骤 1.使能 GPIO 对应的时钟
2.设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置 IO 的复用功能,使其复用为 GPIO 功能
3.设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置 IO 的上下拉、速度的属性
4.配置 GPIO,设置输入/输出、是否使用中断、默认输出电平
二、程序编写 LED灯原理图
#|阿尔法点亮LED灯(一)汇编语言
文章图片

ARM汇编指令
1.LDR Rd, [Rn , #offset]
从存储器 Rn+offset 的位置读取数据存放到 Rd 中
2.STR Rd, [Rn, #offset]
将 Rd 中的数据写入到存储器中的 Rn+offset 位置
1.使能 GPIO1 时钟
ldr r0, =0X020C4068@CCGR0寄存器地址赋值给r0,并将r1的数据写入r0 ldr r1, =0XFFFFFFFF@ 为32位全位1,开启全部外设时钟 str r1, [r0] ldr r0, =0X020C406C@CCGR1寄存器地址赋值给r0,并将r1的数据写入r0 str r1, [r0] ldr r0, =0X020C4070@CCGR2寄存器地址赋值给r0,并将r1的数据写入r0 str r1, [r0] ldr r0, =0X020C4074@CCGR3寄存器地址赋值给r0,并将r1的数据写入r0 str r1, [r0] ldr r0, =0X020C4078@CCGR4寄存器地址赋值给r0,并将r1的数据写入r0 str r1, [r0] ldr r0, =0X020C407C@CCGR5寄存器地址赋值给r0,并将r1的数据写入r0 str r1, [r0] ldr r0, =0X020C4080@CCGR6寄存器地址赋值给r0,并将r1的数据写入r0 str r1, [r0]

2.设置 GPIO1_IO03 的复用功能 配置后四位为0101,即0x00000005
#|阿尔法点亮LED灯(一)汇编语言
文章图片

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

3.配置 GPIO1_IO03属性 #|阿尔法点亮LED灯(一)汇编语言
文章图片

配置为0x000010b0
@配置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为输出 #|阿尔法点亮LED灯(一)汇编语言
文章图片

第3为设置为1,表示输出模式
ldr r0, =0X0209C004@寄存器GPIO1_GDIR ldr r1, =0X0000008 str r1,[r0]

5.控制 GPIO 的输出电平 由于LED的一端接的VCC,只要在另一端写入0即可
ldr r0, =0X0209C000@寄存器GPIO1_DR ldr r1, =0 str r1,[r0]

三、编写Makefile 1.arm-linux-gnueabihf-gcc 编译文件 将 led.s 编译为 led.o
arm-linux-gnueabihf-gcc -g -c led.s -o led.o

“-g”选项是产生调试信息, GDB 能够使用这些调试信息进行代码调试。“-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文件名字,这里我们指定 led.s 编译完成以后的文件名字为 led.o
2.arm-linux-gnueabihf-ld链接文件 arm-linux-gnueabihf-ld 用来将众多的.o 文件链接到一个指定的链接位置
因为要把文件烧写到 SD 卡,以SD卡启动,所以,要设置链接地址(可执行文件其运行起始地址),链接地址都在 DDR中,链接起始地址为 0X87800000
将led.o 文件链接到 0X87800000 地址
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

-o”选项指定链接生成的 elf 文件名(elf可执行文件)
3.arm-linux-gnueabihf-objcopy 格式转换 led.elf 文件也不是最终烧写到 SD 卡中的可执行文件,要烧写的.bin 文件,因此还需要将 led.elf 文件转换为.bin 文件
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,
选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息
4.arm-linux-gnueabihf-objdump 反汇编 有时候需要查看其汇编代码来调试代码,因此就需要进行反汇编,一般可以将 elf 文件反汇编
arm-linux-gnueabihf-objdump -D led.elf > led.dis

led.dis就是生成的汇编文件
5.Makefile 使用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

编译工程:make
清理工程:make clean
四、烧录代码 需要用imxdownload将编译出来的.bin 文件烧写到 SD 卡,将它复制到该目录下,但是,必须给这个文件权限才可以执行
1.赋予可执行权限
chmod 777imxdownload

边为绿色后,说明可以执行了
2.挂载SD卡 第一次我就是问题出现在这里的,把该写到sd卡的数据,不下心写到系统磁盘里面去了,到处系统崩溃,又重新配置了编译环境,极其痛苦
可以使用ls /dev/sd* 命令退出sd的设备名称
#|阿尔法点亮LED灯(一)汇编语言
文章图片

这里我的就是sd卡名称:== /dev/sdb==
3.烧写bin文件 使用 imxdownload 向 SD 卡烧写 led.bin 文件,命令格式
./imxdownload <.bin file> >

.bin 就是要烧写的.bin 文件, SD Card 就是你要烧写的 SD 卡
./imxdownload len.bin /dev/sdb

执行完可以看到文件大小和出现loda.imx
#|阿尔法点亮LED灯(一)汇编语言
文章图片

最终烧写到 SD 卡里面的就是这load.imx 文件,而非led.bin
注意:将sd卡插入到开发板上,还要设置阿尔法的启动方式
设置BOOT_CFG为10000010(外部存储启动方式)

总结 提示:这里对文章进行总结:

    推荐阅读