ARM裸机学习3——用汇编语言点亮 LED

目录

一、汇编启动代码

二、开发板介绍

三、代码编写

[3.1 开启时钟](#3.1 开启时钟)

[3.2 配置IO复用功能与电器属性](#3.2 配置IO复用功能与电器属性)

3.3GPIO配置

3.4复位异常函数

[3.5 Makefile](#3.5 Makefile)

四、代码的编译

4.1环境配置

[4.2 文件发送虚拟机------使用FTP传输协议](#4.2 文件发送虚拟机——使用FTP传输协议)

[4.3 编译下载](#4.3 编译下载)

五、实验现象

六、重要概念


一、汇编启动代码

完善的汇编启动代码如下:

  • keil版:

    ;汇编启动代码_keil
    ;"方言版"汇编启动代码

    复制代码
      area reset ,readonly,code
      preserve8
      code32
      entry
    
      ;中断向量表的这个顺序不能变
      ldr pc,=_reset_handler
      ldr pc,=_undefine_handler
      ldr pc,=_svc_handler
      ldr pc,=_prefetch_abort_handler
      ldr pc,=_data_abort_handler
      ldr pc,=_reserved_handler
      ldr pc,=_irq_handler
      ldr pc,=_fiq_handler

    _fiq_handler
    ldr pc, =_fiq_handler

    _irq_handler
    ldr pc, =_irq_handler

    _reserved_handler
    ldr pc, =_reserved_handler

    _data_abort_handler
    ldr pc, =_data_abort_handler

    _prefetch_abort_handler
    ldr pc, =_prefetch_abort_handler

    _svc_handler
    import c_svc_handler
    stmfd sp!,{r0-r12,lr}
    bl c_svc_handler
    ldmfd sp!,{r0-r12,pc}^ ;^代表恢复时 恢复工作模式

    _undefine_handler
    ldr pc, =_undefine_handler

    _reset_handler
    ;设置SVC模式下的栈
    ldr sp,=0x40001000

    复制代码
      ;切换到USR模式
      mrs r0,cpsr
      bic r0,r0,#0x1F
      orr r0,r0,#0x10
      msr cpsr_c,r0
    
      ;设置USR模式下的栈
      ldr sp,=0x40001000
      sub sp,sp,#1024
    
      import main
      b main    ;跳过去就不回来了

    finished
    b finished ;防止程序跑飞

    复制代码
      end
  • vscode版本

    ;汇编启动代码_vs code
    ;以后用这个,这是符合GNU标准的

    复制代码
      .global _start  //全局变量

    _start: //加冒号代表函数
    ldr pc, =_reset_handler
    ldr pc, =_undefine_handler
    ldr pc, =_svc_handler
    ldr pc, =_prefetch_abort_handler
    ldr pc, =_data_abort_handler
    ldr pc, =_reserved_handler
    ldr pc, =_irq_handler
    ldr pc, =_fiq_handler

    _fiq_handler:
    ldr pc, =_fiq_handler

    _irq_handler:
    ldr pc, =_irq_handler

    _reserved_handler:
    ldr pc, =_reserved_handler

    _data_abort_handler:
    ldr pc, =_data_abort_handler

    _prefetch_abort_handler:
    ldr pc, =_prefetch_abort_handler

    _svc_handler:
    ldr pc, =_svc_handler

    _undefine_handler:
    ldr pc, =_undefine_handler

    _reset_handler:
    // irq mode
    mrs r0, cpsr
    bic r0, r0, #0x1F
    orr r0, r0, #0x12
    msr cpsr, r0
    // irq stack
    ldr sp, =0x86000000

    复制代码
      // system mode
      mrs r0, cpsr
      bic r0, r0, #0x1F
      orr r0, r0, #0x1F
      msr cpsr, r0
      // system stack
      ldr sp, =0x84000000
    
      //bss清零
      bl _bss_clear
      //go main  //GNU组织下,不用导入函数
      b main

    _bss_clear:
    ldr r0, =_bss_start
    ldr r1, =_bss_end
    loop:
    mov r2, #0
    str r2, [r0]
    add r0, r0, #4
    cmp r0, r1
    blt loop

    复制代码
      b main

    finished:
    b finished

二、开发板介绍

正点原子:mini版、阿尔法版

本次课程实验使用的开发板是由正点原子提供的IMX6ULL-Mini。大多数情况下,一个嵌入式系统硬件部分包括核心板和底板两个部分。核心板 主要是将Soc所需的必要器件如RAM,NAND(eMMC)等器件组织在一起,这部分电路设计难度相对较大。底板部分通常是由集成商设计。二者通过接插件连接起来。这样的设计大大降低了开发难度,节约了开发时间。

核心板资源

启动方式设置

LED:

蓝色的LED1:器件丝印

红色LED0:网络标号

**GPIO:**有五组(GPIO1-GPIO5)

三、代码编写​​​​​​​

  • 配置寄存器(根据参考手册)
  • IOMUXC:引脚复用功能寄存器

IOMUXC_SW_MUX _CTL_PAD_GPIO1 IO03:配置为GPIO功能 0x05

  • IOMUXC_SW_PAD _CTL_PAD_GPIO1 I003 配置电器属性寄存器:如上拉电阻下拉电阻(减轻硬件工程师工作量)0x10B
  • GPIO_DR:写0或写1控制led状态0x0209C000
  • GPIO_GDIR:配置为输出模式0209C004

3.1 开启时钟

为后续编程方便,这里编写时钟开启函数,打开所有时钟,后续可直接调用此函数

cpp 复制代码
_enable_clocks:
    // CCGR0 clock
    ldr r0, =0x020C4068
    ldr r1, =0xFFFFFFFF
    str r1, [r0]

    // CCGR1 clock
    ldr r0, =0x020C406C
    str r1, [r0]

    // CCGR2 clock
    ldr r0, =0x020C4070
    str r1, [r0]

    // CCGR3 clock
    ldr r0, =0x020C4074
    str r1, [r0]

    // CCGR4 clock
    ldr r0, =0x020C4078
    str r1, [r0]

    // CCGR5 clock
    ldr r0, =0x020C407C
    str r1, [r0]

    // CCGR6 clock
    ldr r0, = 0x020C4080
    str r1, [r0]

    bx lr

3.2 配置IO复用功能与电器属性

cpp 复制代码
_init_led:
    // gpio1_io03 iomuxmode
    ldr r0, =0x020E0068
    mov r1, #0x05
    str r1, [r0]

    // gpio1_io03 pad
    ldr r0, =0x020E02F4
    ldr r1, =0x10B0
    str r1, [r0]

    // gpio1_io03 output
    ldr r0, =0x0209C004
    ldr r1, [r0]
    orr r1, r1, #(1 << 3)
    str r1, [r0]

    bx lr

3.3GPIO配置

cpp 复制代码
_led_on:
    // led on
    ldr r0, =0x0209C000
    ldr r1, [r0]
    bic r1, r1, #(1 << 3)
    str r1, [r0]

    bx lr

3.4复位异常函数

cpp 复制代码
_reset_handler:            
    // irq mode
    mrs r0, cpsr
    bic r0, r0, #0x1F
    orr r0, r0, #0x12
    msr cpsr, r0
    // irq stack
    ldr sp, =0x86000000

    // system mode
    mrs r0, cpsr
    bic r0, r0, #0x1F
    orr r0, r0, #0x1F
    msr cpsr, r0
    // system stack
    ldr sp, =0x84000000

    // enable clock
    bl _enable_clocks
    // led init
    bl _init_led
    // led on
    bl _led_on
    b finished
    
finished:
	b finished	  

3.5 Makefile

cpp 复制代码
led.bin : led.S
	#使用arm-linux-gnueabihf-gcc编译文件
	arm-linux-gnueabihf-gcc -g -c led.S -o led_.o 
	#使用arm-linux-gnueabihf-ld 链接文件
	arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
	#用arm-linux-gnueabihf-objcopy 格式转换
	arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

	#使用arm-linux-gnueabihf-objdump 反汇编
	arm-linux-gnueabihf-objdump -D led.elf > led.dis

clear:
	rm -rf*.o led.bin led.elf led.dis

四、代码的编译

4.1环境配置

  • 虚拟机配置:
  • 乌班图环境配置
  • 下载vsftpd

重启FTP服务

  • 配置:
  • 安装编译器

装编译器

修改编译器路径

重启虚拟机

  • Windows系统环境配置

下载软件

4.2 文件发送虚拟机------使用FTP传输协议

讲Windows下编辑好的程序传输的虚拟机

4.3 编译下载

  • 使用make将汇编程序编译为led.bin
  • 使用imxdownload将led.bin下载到SD卡

五、实验现象

代码烧写到SD卡后,一上电板载led就亮起了

六、重要概念

  • 什么是编译器、连接器、格式转换器和反汇编器?

编译器(gcc):将汇编源文件(.S)转为目标文件(.o),进行语法检查和指令翻译;

链接器(ld):将目标文件链接到指定内存地址,解决符号引用(如程序入口 _start);

格式转换器(objcopy):将 ELF 文件(包含调试 / 符号信息)转为开发板可直接执行的二进制文件(.bin);

反汇编器(objdump):将 ELF 文件转回汇编代码,用于调试(验证指令是否正确翻译)。

相关推荐
ShineWinsu6 小时前
常见网络连接问题分类
arm开发
Flamingˢ1 天前
ZYNQ + OV5640 + HDMI 视频系统调试记录:一次 RGB888 与 RGB565 引发的黑屏问题
arm开发·嵌入式硬件·fpga开发·vim·音视频
Flamingˢ1 天前
YNQ + OV5640 视频系统开发(二):OV5640_Data IP 核源码解析
arm开发·嵌入式硬件·网络协议·tcp/ip·fpga开发·vim·音视频
Flamingˢ1 天前
ZYNQ + OV5640 视频系统开发(三):AXI VDMA 帧缓存原理
arm开发·嵌入式硬件·fpga开发·vim·音视频
EnglishJun2 天前
ARM嵌入式学习(十四)--- IMX6ULL的I2C通信实现
arm开发·学习
Freak嵌入式2 天前
ESP32 实现在线动态安装库和自动依赖安装-使用uPyPI包管理平台
arm开发·ide·嵌入式·micropython·电子·upypi
.普通人2 天前
Arm_Cortex-M3权威指南
arm开发
平凡的阳阳2 天前
千里通 RK3576 ARM架构智能边缘计算盒
arm开发·架构·边缘计算
ai产品老杨3 天前
异构计算时代的视频底座:基于 X86/ARM 与 GPU/NPU 的边缘云协同架构解析
arm开发·架构·音视频