0%

I.MX6U Assembly LED Driver

程序设计

点灯流程

  1. 使能指定 GPIO 的时钟
  2. 设置 IO 的复用功能
  3. 配置 GPIO 输出功能、上拉、速度等等
  4. 设置 GPIO 输出高电平或低电平

点灯汇编代码

代码中的地址参考《i.MX 6ULL Applications Processor Reference Manual》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
.global _start	@ global symbol

_start:
ldr r1, =0xffffffff
mov r2, #6
ldr r0, =0x020c4080 @ CCM_CCGR6
ldr r2, =0x020c4068 @ CCM_CCGR0

CCGR_loop_init:
str r1, [r0]
sub r0, #4
cmp r2, r0
ble CCGR_loop_init

ldr r0, =0x020e0068 @ IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
ldr r1, =0x5
str r1, [r0]

ldr r0, =0x020e02f4 @ IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
ldr r1, =0x10b0
str r1, [r0]

ldr r0, =0x0209c004 @ GPIO1_GDIR
ldr r1, =0x8
str r1, [r0]

loop:
ldr r0, =0x0209c000 @ GPIO1_DR
ldr r1, =0x0
str r1, [r0]

ldr r0, =0x1f78a400 @ 528M
ldr r1, =0xfbc5200 @ 264M
delay1:
sub r0, #100
cmp r0, r1
bge delay1

ldr r0, =0x0209c000 @ GPIO1_DR
ldr r1, =0x8
str r1, [r0]

ldr r0, =0x1f78a400 @ 528M
ldr r1, =0xfbc5200 @ 264M
delay2:
sub r0, #100
cmp r0, r1
bge delay2

b loop

程序编译

编译

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

上述命令就是将 led.s 编译为 led.o,其中“-g”选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。“-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文件名字。

链接

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

上述命令中-Ttext 就是指定链接地址,“-o”选项指定链接生成的 elf 文件名,这里命名为 led.elf。

格式转换

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

烧录要用到bin文件,上述命令中,“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息。

反汇编

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

有时候需要查看其汇编代码来调试代码,因此就需要进行反汇编,一般可以将 elf 文件反汇编,上述代码中的“-D”选项表示反汇编所有的段。

Makefile脚本

1
2
3
4
5
6
7
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

注意:每一个命令行必须以 注意:每一个命令行必须以[Tab]字符开始,不能是空格开始,[Tab] 字符告诉 make 此行是一个命令行,make 按照命令完成相应的动作。这也是书写按照命令完成相应的动作,这也是书写 Makefile 中容易产生,而且比较隐蔽的错误。报错信息:Makefile:2: *** 遗漏分隔符 (null)。 停止。

反汇编

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Disassembly of section .text:

87800000 <_start>:
87800000: e3e01000 mvn r1, #0
87800004: e3a02006 mov r2, #6
87800008: e59f0078 ldr r0, [pc, #120] ; 87800088 <delay2+0x10>
8780000c: e59f2078 ldr r2, [pc, #120] ; 8780008c <delay2+0x14>

87800010 <CCGR_loop_init>:
87800010: e5801000 str r1, [r0]
87800014: e2400004 sub r0, r0, #4
87800018: e1520000 cmp r2, r0
8780001c: dafffffb ble 87800010 <CCGR_loop_init>
87800020: e59f0068 ldr r0, [pc, #104] ; 87800090 <delay2+0x18>
87800024: e3a01005 mov r1, #5
87800028: e5801000 str r1, [r0]
8780002c: e59f0060 ldr r0, [pc, #96] ; 87800094 <delay2+0x1c>
87800030: e59f1060 ldr r1, [pc, #96] ; 87800098 <delay2+0x20>
87800034: e5801000 str r1, [r0]
87800038: e59f005c ldr r0, [pc, #92] ; 8780009c <delay2+0x24>
8780003c: e3a01008 mov r1, #8
87800040: e5801000 str r1, [r0]

87800044 <loop>:
87800044: e59f0054 ldr r0, [pc, #84] ; 878000a0 <delay2+0x28>
87800048: e3a01000 mov r1, #0
8780004c: e5801000 str r1, [r0]
87800050: e59f004c ldr r0, [pc, #76] ; 878000a4 <delay2+0x2c>
87800054: e59f104c ldr r1, [pc, #76] ; 878000a8 <delay2+0x30>

87800058 <delay1>:
87800058: e2400064 sub r0, r0, #100 ; 0x64
8780005c: e1500001 cmp r0, r1
87800060: aafffffc bge 87800058 <delay1>
87800064: e59f0034 ldr r0, [pc, #52] ; 878000a0 <delay2+0x28>
87800068: e3a01008 mov r1, #8
8780006c: e5801000 str r1, [r0]
87800070: e59f002c ldr r0, [pc, #44] ; 878000a4 <delay2+0x2c>
87800074: e59f102c ldr r1, [pc, #44] ; 878000a8 <delay2+0x30>

87800078 <delay2>:
87800078: e2400064 sub r0, r0, #100 ; 0x64
8780007c: e1500001 cmp r0, r1
87800080: aafffffc bge 87800078 <delay2>
87800084: eaffffee b 87800044 <loop>
87800088: 020c4080 andeq r4, ip, #128 ; 0x80
8780008c: 020c4068 andeq r4, ip, #104 ; 0x68
87800090: 020e0068 andeq r0, lr, #104 ; 0x68
87800094: 020e02f4 andeq r0, lr, #244, 4 ; 0x4000000f
87800098: 000010b0 strheq r1, [r0], -r0
8780009c: 0209c004 andeq ip, r9, #4
878000a0: 0209c000 andeq ip, r9, #0
878000a4: 1f78a400 svcne 0x0078a400
878000a8: 0fbc5200 svceq 0x00bc5200

和我写的汇编代码都是一一对应的,只是把直接数放在了代码段的最后,ldr通过pc+offset来取。

从反汇编来看还把ldr一些短的直接数改成了mov指令。