STM32裸机开发(3) — 使用汇编点亮LED灯

2023-05-16

STM32裸机开发(3) — 使用汇编点亮LED灯

一、启动流程

对于STM32F103从flash的启动流程如下:

  • 首先设置栈:CPU会从0x08000000读取值,用来设置SP(不使用C语言可以不设置,或者在程序里设置SP)
  • 然后跳转:CPU从0x08000004得到地址值,根据它的BIT0切换为ARM状态或Thumb状态,然后跳转
    • 对于cortex M3/M4,它只支持Thumb状态,所以0x08000004上的值bit0必定是1
    • 0x08000004上的值 = Reset_Handler + 1
  • 接着就从Reset_Handler继续执行

二、在keil-MDK下编写程序

打开keil,新建工程,选择STM32F103ZE
在这里插入图片描述
新建start.s文件,编写如下代码;



                PRESERVE8							;指示编译器8字节对齐
                THUMB								;指示编译器以后的指令为THUMB指令								


; Vector Table Mapped to Address 0 at Reset
				AREA    RESET, CODE, READONLY		;定义只读数据段,标记为RESET,其实放在CODE区,位于0地址
				EXPORT  __Vectors					;在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用
					
__Vectors       DCD     0                			;当前地址写入一个字(32bit)数据,值为0x00000000,实际是应该填入栈顶地址 
                DCD     Reset_Handler              	;当前地址写入一个字(32bit)数据,值为Reset_Handler的值,即程序入口地址

				AREA    |.text|, CODE, READONLY		;定义代码段,标记为.text

; Reset handler	;利用PROC、ENDP这一对伪指令把程序段分为若干个过程,使程序的结构加清晰
Reset_Handler   PROC								;过程的开始 
				EXPORT  Reset_Handler	[WEAK]		;[WEAK] 弱定义,意思是如果在别处也定义该标号(函数),在链接时用别处的地址。

				; 1、使能 GPIOB 
				LDR R0, =(0x40021000 + 0x18)
				LDR R1, [R0]
				ORR R1, R1, #(1<<3)
				STR R1, [R0]
				
				; 2、把GPIOB5设置为输出引脚
				LDR R0, =(0x40010C00 + 0x00)
				LDR R1, [R0]
				ORR R1, R1, #(1<<20)
				STR R1, [R0]
				
				; 3、设置GPIOB5的输出寄存器
				LDR R2, =(0x40010C00 + 0x0C)
				
				;4、loop循环
Loop				
				; 5、设置GPIOB5输出高
				LDR R1, [R2]
				ORR R1, R1, #(1<<5)
				STR R1, [R2]
				
				LDR R0, =1000000
				BL delay
				
				; 6、设置GPIOB5输出低
				LDR R1, [R2]
				BIC R1, R1, #(1<<5)
				STR R1, [R2]
				
				LDR R0, =1000000
				BL delay
				
				B Loop
                ENDP								;过程的结束

delay
				SUBS R0, R0, #1
				BNE delay
				BX LR

                ALIGN 								;填充字节使地址对齐
                END									;整个汇编文件结束

然后添加如下两行在编译中执行的命令:

fromelf  --bin  --output=led.bin  Objects\led.axf
fromelf  --text  -a -c  --output=led.dis  Objects\led.axf

或者如下通用命令,和上面的命令是等效的

fromelf --bin -o "$L@L.bin" "#L"
fromelf --text -a -c --output="$L@L.dis" "#L"

第一行生成.bin文件,第二行生成反汇编.dis文件
在这里插入图片描述
然后点击构建,可以看到,已经生成了led.bin文件和反汇编led.dis文件
在这里插入图片描述
打开led.disled.bin文件,可以看到,因为stm32f103的cotex-m3内核使用的是Thumb指令集,所以其指令长度既有16位又有32位;按stm32在flash模式下的启动顺序,先在0x0800000地址下获取栈地址,在0x08000000地址下获取程序入口地址+1的值,其中最后一位1表示thumb指令。
在这里插入图片描述
将其烧写到开发板,可以看到其LED灯闪烁
在这里插入图片描述

三、使用gcc编译程序

编写在gcc下使用的start.s汇编代码


  .syntax unified                   /* 指明当前汇编文件的指令是ARM和THUMB通用格式 */
  .cpu cortex-m3                    /* 指明cpu核为cortex-m3 */
  .fpu softvfp                      /* 软浮点 */
  .thumb                            /* thumb指令 */

.global  _reset                     /* .global表示_start是一个全局符号 */

.word 0x00000000                    /* 当前地址写入一个字(32bit)数据,值为0x00000000,实际上应为栈顶地址 */
.word _reset+1                      /* 当前地址写入一个字(32bit)数据, 值为_reset标号代表的地址+1,即程序入口地址*/

_reset:                             /* 标签_start,汇编程序的默认入口是_start */
    /* 1、使能 GPIOB */
    LDR R0, = (0x40021000 + 0x18)   /* 将APB2外设时钟使能寄存器的地址值写入R0 */
    LDR R1, [R0]                    /* 读取该寄存器的值 */      
    ORR.W R1, R1, #(1<<20)             /* 修改读出的值 */
    STR R1, [R0]                    /* 写入修改后的值到该寄存器 */

    /* 2、把GPIOB5设置为输出引脚 */
    LDR R0, = (0x40010c00 + 0x00)
    LDR R1, [R0]
    ORR.W R1, R1, #(1<<20)
    STR R1, [R0]

    /* 3、设置GPIOB5的输出寄存器 */
    LDR R2, = (0x40010c00 + 0x0c)

    /* 4、loop循环 */
loop:
    /* 5、设置GPIOB5输出高 */
    LDR R1, [R2]
    ORR.W R1, R1, #(1<<5)
    STR R1, [R2]

    LDR R0, =1000000
    BL delay

    /* 6、设置GPIOB5输出低 */
    LDR R1, [R2]
    BIC.W R1, R1, #(1<<5)
    STR R1, [R2]

    LDR R0, =1000000
    BL delay 

    b loop

delay:
    SUBS R0,R0,#1
    BNE delay
    BX LR

以及Makefile文件如下


led.bin:start.S
	arm-none-eabi-gcc -c start.s -o led.o
	arm-none-eabi-ld led.o -Ttext 0X80000000 -o led.elf
	arm-none-eabi-objcopy led.elf -O ihex led.hex
	arm-none-eabi-objcopy led.elf -O binary -S led.bin
	arm-none-eabi-objdump -D -m cortex-m3 led.elf > led.dis

clean:
	rm -rf *.o led.elf led.hex led.bin led.dis

然后执行make命令,如下所示,编译成功,
在这里插入图片描述
将其烧写到开发板,可以看到其LED灯闪烁
在这里插入图片描述

四、比较MDK和GCC编译差别

分别比较两个.dis文件,如下所示,按stm32在flash模式下的启动顺序,先在0x0800000地址下获取栈地址,在0x08000000地址下获取程序入口地址+1的值,其中最后一位1表示thumb指令。
另外发现其中有一个位置不同,但在汇编文件中使用的指令是相同的,这是因为gcc编译器会强制将SUBS有两个相同寄存器指令转换为单个寄存器操作。
在这里插入图片描述
参考链接如下:强制GNU AS使用替代方法

五、附录

上一篇:STM32裸机开发(2) — 点亮第一个LED
下一篇:STM32裸机开发(4) — 编写C语言点亮LED灯

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32裸机开发(3) — 使用汇编点亮LED灯 的相关文章

  • 135-基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真+源程序

    资料编号 135 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 电机 超声波传感器 制作一个基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真 2 通过DHT11传感器检测当前
  • rt-thread studio中新建5.02版本报错

    先吐槽一下 rt thread studio出现BUG真多 好多时间都是在找BUG 但里面用好多控件还是挺好用的 真是又爱又恨 所以一般使用功能不多的话还是用keil多一点 创建5 02版本工程之后直接进行编译 直接会报下面这个错误 资源
  • STM32F103概要

    The STM32F103x4 STM32F103x6 STM32F103xC STM32F103xD and STM32F103xE are a drop in replacement for STM32F103x8 B medium d
  • [MM32硬件]搭建灵动微MM32G0001A6T的简易开发环境

    作为学习单片机的经典 自然是通过GPIO点亮LED 或者是响应按钮的外部中断例程 这我们看看SOP8封装的芯片MM32G0001A6T得引脚 除了VDD和GND固定外 我们可以使用PA14 PA1 PA13 PA15 PA2 PA3这六个G
  • HAL 锁定和解锁函数如何使用以及为什么?

    我试图理解另一位程序员编写的代码 它使用了I C http en wikipedia org wiki I C2 B2C通信以将数据写入 STM32 微控制器的 EEPROM 一般来说 我理解他的代码是如何工作的 但我不明白他为什么使用HA
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • STM32F207 I2C 测试失败

    我正在使用 STM32F207 微控制器在 STM3220G EVAL 板上学习嵌入式开发 我尝试通过连接同一芯片上的两个 I2C2 和 I2C3 模块并发送 接收字符来测试 I2C 接口 这是我当前编写的代码 使用 mdk arm 5 i
  • 无法使用 OpenOCD 找到脚本文件

    我正在尝试按照本教程将 OpenOCD 与我的 ST 发现板一起使用 https japaric github io discovery README html https japaric github io discovery READM
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • STM32H5 Nucleo-144 board开箱

    文章目录 开发板资料下载 目标 点亮LD1 绿 LD2 黄 和LD3 红 三个LED灯 开箱过程 博主使用的是STM32CubeMX配置生成代码 具体操作如下 打开STM32CubeMX File gt New project 选择开发板型
  • 核心耦合内存在 STM32F4xx 上可执行吗?

    尝试从 STM32F429s CCM 运行代码 但每当我命中 CCM 中的第一条指令时 我总是会遇到硬故障 并且 IBUSERR 标志被设置 该指令有效且一致 STM32F4xx 是否可能不允许从 CCM 执行 数据访问效果良好 alios
  • 从没有中断引脚并且在测量准备好之前需要一些时间的传感器读取数据的最佳方法

    我正在尝试将压力传感器 MS5803 14BA 与我的板 NUCLEO STM32L073RZ 连接 根据 第 3 页 压力传感器需要几毫秒才能准备好读取测量值 对于我的项目 我对需要大约 10 毫秒来转换原始数据的最高分辨率感兴趣 不幸的
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • STM32内部时钟

    我对 STM32F7 设备 意法半导体的 Cortex M7 微控制器 上的时钟系统感到困惑 参考手册没有充分阐明这些时钟之间的差异 SYSCLK HCLK FCLK 参考手册中阅读章节 gt RCC 为 Cortex 系统定时器 SysT
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能
  • Android 2.1 的 Camera.Parameters.FLASH_MODE_TORCH 替换

    我正在尝试编写一个需要 LED 闪光灯进入手电筒模式的应用程序 问题是 Android 2 1不支持这种模式 因此我还不能支持该平台 这不是问题 但我正在为我的未婚夫编写它 而她的 Epic 4G 目前只有 2 1 我发现一些代码示例使用了

随机推荐

  • IntelliJ IDEA插件之Background Image Plus +

    IntelliJ IDEA插件之Background Image Plus 43 下载地址安装插件概述 下载地址 下载地址 安装插件 安装方式 概述 IDEA 背景修改插件
  • IntelliJ IDEA插件之Free MyBatis plugin

    IntelliJ IDEA插件之Free MyBatis plugin 下载地址安装插件概述 下载地址 下载地址 安装插件 安装方式 概述 mapper接口与对应xml文件对应
  • MySQL Workbench 8.0 CE 汉化包下载

    MySQL Workbench 8 0 CE 汉化包下载 下载地址 xff1a 汉化文件下载 下载提示 xff1a 下载过程进度文件页面右键另存为即可保存文件到本地 1 把下载好的文件后放到此目录下替换此文件 C Program Files
  • IntelliJ IDEA插件之CodeGlance

    IntelliJ IDEA插件之CodeGlance 下载插件安装插件概述 下载插件 下载地址 安装插件 安装方式 概述 将类似于Sublime中的代码的微型地图嵌入到编辑器窗格中 使用您自定义的颜色对亮色和深色主题进行语法突出显示
  • IDEA Easy Code使用记录

    下载安装 xff08 忽略 xff09 设置 设置在idea的 Other Settings里面 分4个选项 Type Mapper 类型映射 xff08 数据字段和java包装器映射 xff09 Template Setting 模板设置
  • windows 10 安装MySQL5.7.25(支持多个MySQL实例)

    windows 10 安装MySQL5 7 25 下载安装包解压到对应路径 创建my ini 配置文件 xff0c 内容如下 span class token punctuation span mysql span class token
  • MySQL explain学习(MySQL版本5.7.25)

    MySQL explain学习 xff08 MySQL版本5 7 25 xff09 idselect typetablepartitionstype xff08 重要 xff09 possible keyskeykey lenrefrows
  • JAVA服务器端接入微信APP支付记录

    微信开发文档地址 xff1a https pay weixin qq com wiki doc api app app php chapter 61 8 1 业务流程图如下 xff1a 商户系统和微信支付系统主要交互说明 xff1a 步骤1
  • 小程序插入激励视频广告教程

    小程序插入激励视频广告教程 相关链接 xff1a 小程序插入banner广告小程序插入插屏广告 今天登陆小程序的后台 xff0c 收到了官方通知 xff0c 小程序激励式视频广告组件日前已上线 xff0c 也就是说可以在小程序中插入激励视频
  • Latex公式中符号上下分别加横线的写法

    下划线 xff1a underline p 效果 xff1a p underline p p 上划线 xff1a overline p 效果 xff1a
  • Error: Unable to find a match

    Error Unable to find a match 当服务器安装软件包出现 xff1a Error Unable to find a match 错误 要么是软件名称写错 xff0c 要么是根本没有这个软件包 缺少系统或者软件repo
  • 网易云音乐缓存文件

    1 Ubuntu版的网易云音乐已经懒得加密了吗 名字里甚至都已经带了md5码的加密方法 ls cache netease cloud music CachedSongs 567602 128 55881971d77b3ec1a5a134e2
  • win10远程连接ubuntu18.04 xrdp+xfce4+fcitx+terminal

    第 1 步 下载脚本 要下载脚本 xff0c 您有多种选择 您可以从终端发出以下命令 wget https www c nergy be downloads xRDP xrdp installer 1 3 zip 您也可以简单地使用浏览器并
  • MySQL增加字段SQL语句

    使用ALTER TABLE向MySQL数据库的表中添加字段 xff0c 向buildBaseInfo中添加字段 ALTER TABLE table name ADD COLUMN column name VARCHAR 100 DEFAUL
  • 搭建PyQt环境(Vs Code)

    1 安装Python 在win10的应用商店中直接搜索Python xff0c 下载并安装 在python官网下载安装也一样 xff0c 但是可能会缺少Python Launcher或者没有添加进系统环境变量 xff0c 造成不必要的麻烦
  • Error: Invalid or corrupt jarfile jar

    遇到的问题 xff1a IDEA打包可执行jar包 xff0c 报错Error Invalid or corrupt jarfile jar 检索问题 xff0c 看到各种千奇百怪的方法 xff0c 比如 xff1a 修改文件后使用jar命
  • 移动VMware虚拟机

    参考连接 xff1a 将VMware虚拟机移到其它磁盘 xff08 C盘 gt D盘 xff09 追梦赤子心刘大哥的博客 CSDN博客 vmware 虚拟机迁移硬盘 操作成功 xff01
  • Linux下常用防火墙命令

    CentOS7 的防火墙配置跟以前版本有很大区别 xff0c CentOS7这个版本的防火墙默认使用的是firewall xff0c 这里有个参考地址 xff1a https www cnblogs com sucretan2010 p 1
  • ubuntu Server上安装桌面环境

    详情请移步至原创主页https www linuxidc com Linux 2018 12 156031 htm 写的不错 而且自己操作过
  • STM32裸机开发(3) — 使用汇编点亮LED灯

    STM32裸机开发 xff08 3 xff09 使用汇编点亮LED灯 一 启动流程 对于STM32F103从flash的启动流程如下 xff1a 首先设置栈 xff1a CPU会从0x08000000读取值 xff0c 用来设置SP 不使用