嵌入式Linux驱动开发——汇编点灯
本文章开始记录学习嵌入式Linux的过程,使用的开发板是正点原子的阿尔法,以及左老师的书籍和视频。然后这个系列不会介绍基础知识(书上都有),主要是记录思考过程以及需要注意的点。
代码编写
使能时钟
🚀🚀这个地方的代码还是很简单的,主要就是去哪找CCM的地址,不过也不算难找,比如CCGR0,就是0x020c4068。
🚀🚀然后找到GPIO1的时钟由CCM_CCGR1 的 bit27 和 bit26 这两个位控制,将这两个位都设置位 11 即可
.global _start /* 全局标号 */
/*
* 描述: _start函数,程序从此函数开始执行此函数完成时钟使能、
* GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。
*/
_start:
/* 1、使能GPIO1时钟 */
ldr r1, =0xFFFFFFFF
ldr r0, =0X020C406C /* CCGR1 */
str r1, [r0]
.global _start
: 这是一个全局标签,标记了程序的起始位置。_start
: 这是程序的入口点,程序将从这里开始执行。ldr r1, =0xFFFFFFFF
: 这一行使能CCGR1。ldr r0, =0X020C406C
: 这一行将立即数0X020C406C
加载到寄存器r0
中,这个值是GPIO1的时钟寄存器的地址。str r1, [r0]
: 这一行将寄存器r1
中的值写入到地址为r0
的内存位置,即将生成的掩码写入到GPIO1的时钟寄存器,从而启用GPIO1时钟。
设置复用
ldr r0, =0X020E0068
: 这一行将立即数0X020E0068
加载到寄存器r0
中,这个值是SW_MUX_GPIO1_IO03_BASE寄存器的地址,也是像上面那样找。这个寄存器用于控制GPIO1_IO03引脚的复用功能。ldr r1, =0X5
: 这一行将立即数0X5
加载到寄存器r1
中。在i.MX系列处理器中,设置为5的MUX_MODE表示该引脚被设置为GPIO模式,即将该引脚设置为普通GPIO引脚功能。str r1, [r0]
: 这一行将寄存器r1
中的值写入到地址为r0
的内存位置,即将MUX_MODE设置为5,从而将GPIO1_IO03引脚的复用功能设置为GPIO1_IO03。
/* 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]
设置IO
/* 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]
设置GPIO
🚀🚀这个的地址有一点点不一样,在GPIO Memory Map/Register Definition里面。
/* 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-gcc
:使用arm-linux-gnueabihf工具链中的gcc编译器。-g
:生成带有调试信息的目标文件。-c
:表示只编译,不链接。led.s
:源文件名,这里是汇编代码文件。-o led.o
:指定输出的目标文件名为led.o,这里是编译后的目标文件。
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
:arm-linux-gnueabihf-ld
:使用arm-linux-gnueabihf工具链中的ld链接器。-Ttext 0X87800000
:指定链接地址,这里设置程序的起始地址为0X87800000。led.o
:输入的目标文件名,即刚刚生成的目标文件。-o led.elf
:指定输出的可执行文件名为led.elf,这里是链接后的可执行文件。
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
:arm-linux-gnueabihf-objcopy
:使用arm-linux-gnueabihf工具链中的objcopy工具。-O binary
:指定目标文件的格式为二进制。-S
:去除调试符号和调试信息。-g
:保留全局符号信息。led.elf
:输入的可执行文件名,即刚刚生成的可执行文件。led.bin
:指定输出的二进制文件名为led.bin,这里是转换后的二进制文件。
arm-linux-gnueabihf-objdump -D led.elf > led.dis
:arm-linux-gnueabihf-objdump
:使用arm-linux-gnueabihf工具链中的objdump工具。-D
:显示反汇编代码。led.elf
:输入的可执行文件名,即刚刚生成的可执行文件。> led.dis
:将反汇编的结果输出到led.dis文件中,这里是生成的反汇编文件。
kali@ubuntu:~/linux/driver/01_leds$ arm-linux-gnueabihf-gcc -g -c led.s -o led.o
kali@ubuntu:~/linux/driver/01_leds$ arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
kali@ubuntu:~/linux/driver/01_leds$ arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
kali@ubuntu:~/linux/driver/01_leds$ 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
🚀🚀这个Makefile文件用于管理编译、链接、转换和清理操作,具体作用如下:
-
led.bin: led.s
:定义了一个目标文件led.bin,它依赖于led.s文件。也就是说,当led.s文件被修改时,会触发后续的编译、链接、转换操作。 -
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
:编译led.s文件为目标文件led.o,这里使用了arm-linux-gnueabihf工具链中的gcc编译器,并且指定生成带有调试信息的目标文件。 -
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
:链接led.o文件为可执行文件led.elf,这里使用了arm-linux-gnueabihf工具链中的ld链接器,并且指定了链接地址为0X87800000。 -
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
:将led.elf文件转换为二进制文件led.bin,这里使用了arm-linux-gnueabihf工具链中的objcopy工具,并且指定了输出的文件格式为二进制。 -
arm-linux-gnueabihf-objdump -D led.elf > led.dis
:生成反汇编文件led.dis,这里使用了arm-linux-gnueabihf工具链中的objdump工具,并且指定了显示反汇编代码。 -
clean:
:定义了一个伪目标clean,用于清理生成的目标文件和中间文件。 -
rm -rf *.o led.bin led.elf led.dis
:删除所有的目标文件和生成的二进制文件,以及反汇编文件。
代码烧录
🚀🚀这个就是使用imxdownload,比较简单
kali@ubuntu:~/linux/driver/01_leds$ ./imxdownload led.bin /dev/sdb
I.MX6ULL bin download software
Edit by:zuozhongkai
Date:2019/6/10
Version:V1.1
log:V1.0 initial version,just support 512MB DDR3
V1.1 and support 256MB DDR3
file led.bin size = 88Bytes
Board DDR SIZE: 512MB
Delete Old load.imx
Create New load.imx
Download load.imx to /dev/sdb ......
6+1 records in
6+1 records out
3160 bytes (3.2 kB, 3.1 KiB) copied, 0.0569602 s, 55.5 kB/s