ARM汇编LED实验

IMX6U的GPIO功能使用的时候比2440或者51单片机要复杂一些。首先,我们必须理解一个概念, 即引脚IO功能复用(Pad multiplexing)。我们知道,对于一款Soc来说,某个引脚一般不会只能拿来做某一种特定功能。比如作为UART的TXD引脚,不仅可以用做串口的发送引脚,它还可以用来点灯。具体到某个引脚在实际板子上的用途,Soc的生产厂商自然是不知道的。为了方便芯片的使用者,I.MX6U的设计者并没有规定某个引脚只能做什么用途,而是设计了一个IO复用控制器(IOMUX Controller),由使用者通过软件来设置引脚的具体功能。而引脚的多种不同功能,被称之为IO功能复用。需要注意的是,我们耳熟能详的GPIO只不过是众多复用功能的一种。因此不能猜测,Led点灯实验必然需要通过设置IO复用功能寄存器来设置某个引脚的复用功能为GPIO。之后再通过GPIO中提供的寄存器点亮Led。此外,在Soc中,一个模块往往可以通过是否为其提供时钟来使能或者失能该模块,因此需要使用引脚的GPIO功能,还需要为其使能时钟才行。

要将 I.MX6U 的 IO 作为 GPIO 使用,我们需要一下几步:

  1. 使能 GPIO 对应的时钟;

  2. 设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置 IO 的复用功能,使其复用为 GPIO 功能;

  3. 设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置 IO 的上下拉、速度等等;

1. 引脚复用功能 + 引脚电气属性:

IOMUXC_SW_MUX_CTL_PAD:引脚复用功能 _ GPIO1_IO03

IOMUXC_SW_PAD_CTL_PAD :电气属性 _ GPIO1_IO03

2. GPIO模块:

GPIOx_DR:向GPIOx组某个引脚写0或1(低电平/高电平)

GPIOx_GDIR:设置GPIOx组某个引脚方向(输入 0 和输出 1)

GPIOx_PSR(只读):读取GPIOx组某个引脚的状态

GPIOx_ICR:设置GPIOx组某个引脚中断触发方式(低电平、高电平、下降沿、上升沿)

GPIOx_IMR:设置GPIOx组某个引脚中断屏蔽/允许

GPIOx_ISR:用来查询GPIOx组某个引脚是否产生中断

GPIOx_EDGE_SEL:设置中断触发方式为双边沿触发

3. 时钟:

CCM_CCGR0 - CCM_CCGR6:0xFFFFFFFF 打开所有外设时钟门

cpp 复制代码
    .global _start

    _start:
    ldr pc, =_reset_handler
	ldr pc, =_undefine_handler
	ldr pc, =_software_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
  
_software_handler:
    ldr pc, =_software_handler

_undefine_handler:
	ldr pc, =_undefine_handler

_reset_handler:
    // 设置irq模式
    mrs r0, cpsr
    bic r0, r0, #0x1F
    orr r0, r0, #0x12  
    msr cpsr, r0
    // 设置irq模式下的栈(32M)
    ldr sp, =0x86000000

    // 设置system模式
    mrs r0, cpsr
    bic r0, r0, #0x1F
    orr r0, r0, #0x1F
    msr cpsr, r0
    // 设置system模式下的栈
    ldr sp, =0x84000000
    // 打开所有外设时钟门
    bl _enable_clocks
    // 初始化led
    bl _led_init
    // led亮
    bl _led_on
    b finished

_led_on:
    ldr r0, =0x0209C000
    ldr r1, [r0]
    bic r1, r1, #(1 << 3)
    str r1, [r0]
    bx lr


_led_init:
    // 配置引脚复用功能:GPIO1_IO03
    ldr r0, =0x020E0068
    mov r1, #0x05
    str r1, [r0]

    // 配置引脚电气属性:默认属性(0x10B0)
    ldr r0, =0x020E02F4
    ldr r1, =0x10B0
    str r1, [r0]

    // 配置引脚方向:输出模式
    ldr r0, =0x0209C004
    ldr r1, [r0]
    orr r1, r1, #(1 << 3)
    str r1, [r0]
    bx lr

_enable_clocks:
    // CCM_CCGR0 clock enable
    ldr r0, =0x020C4068
    ldr r1, =0xFFFFFFFF
    str r1, [r0]

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

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

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

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

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

    // CCM_CCGR6 clock enable
    ldr r0, =0x020C4080
    str r1, [r0]
    bx lr


finished:
    b finished

编译流程:

1、使用arm-linux-gnueabihf-gcc编译文件

有了工具链,就可以编译我们led_asm.s文件了, 命令为:arm-linux-gnueabihf-gcc -g -c led.s -o led_.o。其中"-g"选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。"-c"选项是编译源文件,但是不链接。"-o"选项是指定编译产生的文件名字,这里我们指定 led.s 编译完成以后的文件名字为led.o。执行上述命令以后就会编译生成一个 led.o 文件。

2、使用arm-linux-gnueabihf-ld 链接文件

确定了链接地址以后就可以使用 arm-linux-gnueabihf-ld 来将前面编译出来的 led.o 文件链接到 0X87800000 这个地址,使用如下命令: arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf。

3、用arm-linux-gnueabihf-objcopy 格式转换

led.elf 文件也不是我们最终烧写到 SD 卡中的可执行文件,我们要烧写的.bin 文件,因此还需要将 led.elf 文件转换为.bin 文件,arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin。上述命令中,"-O"选项指定以什么格式输出,后面的"binary"表示以二进制格式输出,选项"-S"表示不要复制源文件中的重定位信息和符号信息,"-g"表示不复制源文件中的调试信息。

4、使用arm-linux-gnueabihf-objdump 反汇编

大多数情况下我们都是用 C 语言写试验例程的,有时候需要查看其汇编代码来调试代码,因此就 需要进行反汇编,当然这个工作目前对于我们不是必须的。一般来说可以将 elf 文件反汇编,比如如下命令: arm-linux-gnueabihf-objdump -D led.elf > led.dis。

使用命令./imxdownload led.bin /dev/sdb 。注意千万不能写成./imxdownload led.bin/dev/sda,sda是系统磁盘,会造成Ubuntu损坏的!

相关推荐
xx~t12 小时前
嵌入式学习——ARM1
linux·arm开发·嵌入式硬件·arm
xx~t12 小时前
嵌入式——ARM1(详细篇)
linux·arm开发·嵌入式硬件·arm
神威难绷泪17 小时前
arm day2 汇编
arm
H_oRIZoN_17 小时前
Linux入门DAY43 ARM 架构基础、寄存器、大小端、异常向量、交叉编译
linux·arm·linux应用编程
Doraemomo17 小时前
IMX6ULL裸机开发——I2C通信协议
arm开发·嵌入式硬件·imx6ull
幼儿园蛋小黑19 小时前
ARM 汇编入门:从基础指令到实战示例
arm
索端阳20 小时前
ARM Day02 学习总结:ARM汇编基础核心知识点梳理
汇编·学习·arm
Awh-21 小时前
ARM裸机开发 Day01 学习笔记
arm开发·arm·arm裸机
2301_815091011 天前
ARM体系结构学习笔记(一):从硬件基础、寄存器到三级流水线
arm·嵌入式开发