STM32MP157AAA3裸机点灯(汇编)
MP157的A7核裸机点灯
使用的开发板为华清远见的MP157开发板,默认板内emmc已经烧写好了uboot
这篇就只记录一下汇编点灯过程,uboot等内容暂不涉及。
(MP157AAA3好大一颗)
裸机情况下与单片机操作并没有什么区别
配置交叉编译环境
这里使用的是ubuntu18虚拟机
我们如果用Linux自带的gcc编译器编译出来的程序只能在编译机器CPU架构下运行,
如果想在不同架构开发板上运行电脑编译出来的程序就需要使用交叉编译器,
STM32MP157系列为CrotexA7核心,属于ARMV7架构,所以要用对应的编译器。
这里使用交叉编译器为gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf
下载交叉编译器
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
解压
tar -vxJf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
在/usr/local目录下新建arm-linux-gcc目录
sudo mkdir /usr/local/arm-linux-gcc
进入解压后的目录复制文件到新建的目录
cd gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf
sudo cp -rd * /usr/local/arm-linux-gcc/
添加环境变量
sudo vim /etc/profile
打开文件后在最后一行添加
PATH=$PATH:/usr/local/arm-linux-gcc/bin
重新加载环境变量
source /etc/profile
测试配置是否生效
在终端输入arm-linux-gnueabihf- 然后按两下tab键,若出现以下图显示说明配置正常
到这交叉编译环境就配置完成了
写代码
查原理图确定LED引脚
这个可以根据自己开发板的原理图确定LED接在了芯片的哪个GPIO上。
在此用的这个开发板其中一个LED接在PE10上面,在此就点这个灯。
查手册
裸机想要点灯肯定要配寄存器了,配寄存器就需要查寄存器手册。
查内存映射图
根据内存映射图可以看到GPIO控制器是挂在在AHB4总线上面的。
使能GPIOE外设时钟
找到对应寄存器,然后看翻译😂
对应位置1为使能,那就把第四位置1就是使能GPIOE时钟了
寄存器地址为基地址+偏移地址,基地址为0x50000000,偏移地址为0xa28(手册上面有写)
也就是操作地址为0x0x50000a28
代码
ldr r0, =0x50000A28
ldr r1, [r0]
orr r1, r1, #(0x1 << 4)
str r1, [r0]
查看GPIOE配置寄存器基地址
根据手册可看到基地址为0x50006000
配置引脚输入输出
根据手册,可以看到配置PE10输出为20,21位置01
ldr r0, =0x50006000
ldr r1, [r0] @取原始值
bic r1, r1, #(0x3 << 20); @先清零
orr r1, r1, #(0x1 << 20); @写入对应值
str r1, [r0] @回写寄存器
设置推挽输出/开漏输出
这里设置推挽输出,所以第10位置0
ldr r0, =0x50006004
ldr r1, [r0]
bic r1, r1, #(0x1 << 10)
str r1, [r0]
设置GPIO速度
只是点个灯,速度最慢就行了,所以20,21位置0
ldr r0, =0x50006008
ldr r1, [r0]
bic r1, r1, #(0x3 << 20)
str r1, [r0]
设置上下拉
这里设置不拉
ldr r0, =0x5000600C
ldr r1, [r0]
bic r1, r1, #(0x1 << 20)
str r1, [r0]
到这GPIO初始化就完成了
下面往对应寄存器写数据就可以点灯了
点灯
输出数据寄存器,引脚对应位置1位输出高电平,置0输出低电平
循环点灯代码
@亮灯
ldr r0, =0x50006014
ldr r1, [r0]
orr r1, r1, #(0x1 << 10) @对应位置1
str r1, [r0]
@灭灯
ldr r0, =0x50006014
ldr r1, [r0]
bic r1, r1, #(0x1 << 10)
str r1, [r0]
闪烁
全部代码
asm-led.S
.text
.global _start
_start:
/* 1. led1灯的初始化*/
/* 1.1 使能GPIOE外设控制器的时钟
ldr r0, =0x50000A28
ldr r1, [r0]
orr r1, r1, #(0x1 << 4)
str r1, [r0]
/* 1.2 设置PE10引脚为输出模式
ldr r0, =0x50006000
ldr r1, [r0] @取原始值
bic r1, r1, #(0x3 << 20); @先清零
orr r1, r1, #(0x1 << 20); @写入对应值
str r1, [r0] @回写寄存器
/* 1.3 设置PE10引脚为推挽输出
ldr r0, =0x50006004
ldr r1, [r0]
bic r1, r1, #(0x1 << 10)
str r1, [r0]
/* 1.4 设置PE10引脚为低速模式
ldr r0, =0x50006008
ldr r1, [r0]
bic r1, r1, #(0x3 << 20)
str r1, [r0]
/* 1.5 设置PE10引脚禁止上拉和下拉电阻
ldr r0, =0x5000600C
ldr r1, [r0]
bic r1, r1, #(0x1 << 20)
str r1, [r0]
/* led1灯的初始化完成 */
loop:
/* 设置PE10引脚输出高电平, 点亮LED1灯
ldr r0, =0x50006014
ldr r1, [r0]
orr r1, r1, #(0x1 << 10) @对应位置1
str r1, [r0]
bl delay_1s
/* 设置PE10引脚输出低电平, 熄灭LED1灯
ldr r0, =0x50006014
ldr r1, [r0]
bic r1, r1, #(0x1 << 10)
str r1, [r0]
bl delay_1s
b loop
@ 大概1s的延时函数
delay_1s:
mov r3, #0x10000000
mm:
cmp r3, #0
subne r3, r3, #1
bne mm
mov pc, lr
.end
编译
使用添加 makefil文件
make all编译
# 定义变量
NAME=asm-led
# 定义交叉编译器的前缀的变量
CROSS_COMPILE = arm-linux-gnueabihf-
# arm-linux-gnueabihf-gcc : 交叉编译器
CC = $(CROSS_COMPILE)gcc
# arm-linux-gnueabihf-ld : 链接器
LD = $(CROSS_COMPILE)ld
# arm-linux-gnueabihf-objcopy : 格式化工具
OBJCOPY = $(CROSS_COMPILE)objcopy
# arm-linux-gnueabihf-objdump : 反汇编的工具
OBJDUMP = $(CROSS_COMPILE)objdump
#目标:依赖
# (tab键)命令
all:
@# arm-linux-gnueabihf-gcc : 编译器,编译源文件
@# -O0 : 代码的优化等级,不优化
@# -g : 添加gdb的调试信息
@# -c : 只编译不链接
$(CC) -O0 -g -c $(NAME).S -o $(NAME).o
@# arm-linux-gnueabihf-ld : 链接器,将.o文件链接生成.elf文件
@# -Ttext=0xC0008000 :代码段中第一条指令的地址为0xc0008000
$(LD) -Ttext=0xC0008000 $(NAME).o -o $(NAME).elf
@# arm-linux-gnueabihf-objcopy : 格式化工具,将elf文件转换为bin文件
@# bin文件是一个纯粹的二进制文件
@# -O binary : 输出二进制文件
$(OBJCOPY) -O binary $(NAME).elf $(NAME).bin
@# arm-linux-gnueabihf-objdump : 反汇编的命令, 将elf文件转换为.dis反汇编文件
$(OBJDUMP) -D $(NAME).elf > $(NAME).dis
clean:
rm -rf *.elf *.bin *.o *.dis
烧录
开发板上电启动,使用secureCRT链接uboot debug所用的串口serial协议链接
波特率等设置根据uboot初始化串口设置进行设置(一般是115200)
等待uboot初始化完成
输入loadb 0xc0008000进入加载代码
使用软件写入生成的bin文件
写入完成后输入go 0xc0008000回车即可运行代码
效果如下