实验0汇编led驱动

本文详细介绍了在I.MX6ULLMini版开发板上使用汇编语言进行LED驱动编程,包括Cortex-A汇编原理、STM32GPIO初始化、汇编指令示例以及如何使用makefile编译和烧写程序。还提到了使用imxdownload工具进行SD卡烧写的过程。
摘要由CSDN通过智能技术生成

实验开发板  :正点原子I.MX6ULL Mini版

实验所需:TF卡,读卡器,电源线

一、汇编LED原理分析

1.为什么要学习Cortex-A汇编:

①、需要用汇编初始化一些SOC外设。

②、使用汇编初始化DDR,I.MX6U不需要。

③、设置sp指针,一般指向DDR,设置好C语言运行环境。

2.ALPHA开发板LED灯硬件原理分析:

STM32 IO初始化流程:

①、使能GPIO时钟。

②、设置IO复用,将其复用为GPIO

③、配置GPIO的电气属性。

④、使用GPIO,输出高/低电平。

3.I.MX6ULL IO初始化:

①、使能时钟,CCGR0~CCGR6这7个寄存器控制着6ULL所有外设时钟的使能。为了简单,设置CCGR0~CCGR6这7个寄存器全部为0XFFFFFFFF,相当于使能所有外设时钟。

②、IO复用,将寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03的bit3~0设置为0101=5,这样GPIO1_IO03就复用为GPIO。

③、寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03是设置GPIO1_IO03的电气属性。包括压摆率、速度、驱动能力、开漏、上下拉等。

④、配置GPIO功能,设置输入输出。设置GPIO1_DR寄存器bit3为1,也就是设置为输出模式。设置GPIO1_DR寄存器的bit3,为1表示输出高电平,为0表示输出低电平。

二、汇编简介

汇编由一条一条指令构成,指令就涉及到汇编指令。

@注释符号  

Instruction指令   

add地址,也可以作为函数名

bx 返回值

模板:

add:

Instruction @comment

内部寄存器操作指令

存储器操作指令

示例:

Int a,b;

a=b;

假设a地址为0X20,b地址为0x30

LDR R0, =0X30

LDR R1, [R0]

LDR R0, =0X20

STR R1, [R0]

压栈和出栈指令

示例:

 STMFD SP!,{R0~R3, R12}  @R0~R3,R12 入栈

 STMFD SP!,{LR}  @LR 入栈

 LDMFD SP!, {LR}  @先恢复 LR

 LDMFD SP!, {R0~R3, R12}  @再恢复 R0~R3, R12下·

跳转指令

算术运算指令

逻辑运算指令 (一般只用加减)

三、编写驱动

实验0汇编led驱动----代码补充-CSDN博客

四、编译程序

1、编译程序

①、使用arm-linux-gnueabihf-gcc将.c .s文件变为.o

②、将所有的.o文件连接为elf格式的可执行文件。

③、将elf文件转为bin文件。

④、将elf文件转为汇编,反汇编。

(1)交叉编译器 arm-linux-gnueabihf-gcc 

arm-linux-gnueabihf-gcc -g -c led.s -o led.o

其中“-g”选项是产生调试信息,GDB 能够使用这些 调试信息进行代码调试。“-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文 件名字,这里我们指定 led.s 编译完成以后的文件名字为 led.o

(2)arm-linux-gnueabihf-ld 用来将众多的.o 文件链接到一个指定的链接位置。

arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

上述命令中-Ttext 就是指定链接地址,“-o”选项指定链接生成的 elf 文件名,这里我们命名为 led.elf

 (3)arm-linux-gnueabihf-objcopy 格式转换

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

上述命令中,“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,

选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试 信息。

 (4)arm-linux-gnueabihf-objdump 反汇编

arm-linux-gnueabihf-objdump -D led.elf > led.dis

上述代码中的“-D”选项表示反汇编所有的段

2. makefile解读
1 objs := start.o main.o
2 
3 ledc.bin:$(objs)
4 arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^
5 arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
6 arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
7 
8 %.o:%.s
9 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
10 
11 %.o:%.S
12 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
13 
14 %.o:%.c
15 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
16 
17 clean:
18 rm -rf *.o ledc.bin ledc.elf ledc.dis
1 objs := start.o main.o:定义一个变量objs,它包含了start.o和main.o两个目标文件。

2 ledc.bin:$(objs):生成ledc.bin文件的规则,依赖于objs中的目标文件。

3 arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^:使用arm-linux-gnueabihf-ld链接器命令,将objs中的目标文件链接成一个可执行文件ledc.elf,-Ttext参数指定了链接地址为0X87800000。

 自动变量“$^”,“$^”的意思是所有依赖文件的集合,在这里就是 objs 这个变量的值: start.o 和 main.o。

4 arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@:使用arm-linux-gnueabihf-objcopy命令,将ledc.elf文件转换为二进制格式的ledc.bin文件
  本行也用到了自动变量 “$@”,“$@”的意思是目标集合,在这里就是“ledc.bin”,那么本行就相当于: arm-linux-gnueabihf-objcopy -O binary -S ledc.elf ledc.bin
5 arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis:使用arm-linux-gnueabihf-objdump命令,将ledc.elf文件反汇编为ledc.dis文件。

6  %.o:%.s:定义了一条规则,用于将.s汇编文件编译成.o目标文件。

7 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<:使用arm-linux-gnueabihf-gcc编译器命令,将.s文件编译成.o目标文件。

8 %.o:%.S:定义了一条规则,用于将.S汇编文件编译成.o目标文件。

9 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<:使用arm-linux-gnueabihf-gcc编译器命令,将.S文件编译成.o目标文件。

10 %.o:%.c:定义了一条规则,用于将.c源文件编译成.o目标文件。

11 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<:使用arm-linux-gnueabihf-gcc编译器命令,将.c文件编译成.o目标文件。

12 clean::定义了一个clean目标,用于删除生成的文件。
      rm -rf *.o ledc.bin ledc.elf ledc.d

剩下的就是针对不同的文件类型将其编译成对应的.o 文件,其实就是汇编.s(.S)和.c 文件,比如 start.s 就会使用第 6行的规则来生成对应的 start.o 文件。第 7 行就是具体的命令,这行也用到了自动变量“$@”和“$<”,其中“$<”的意思是依赖目标集合的第一个文件。比如 start.s 要编译成 start.o 的话第 6 行和第 7 行就相当于:

start.o:start.s

arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o start.o start.s



链接:

链接就是将所有.o文件链接在一起,并且链接到指定的地方。本实验链接的时候要指定链接起始地址。链接起始地址就是代码运行的起始地址。

对于6ULL来说,链接起始地址应该指向RAM地址。RAM分为内部RAM和外部RAM,也就是 DDR。6ULL内部RAM地址范围0X900000~0X91FFFF。也可以放到外部DDR中,对于I.MX6U-ALPHA开发板,512MB字节DDR版本的核心板,DDR范围就是0X80000000~0X9FFFFFFF。对于256MB的DDR来说,那就是0X80000000~0X8FFFFFFF

Bin的运行地址一定要和链接起始地址一致。位置无关代码除外。

五、烧写bin文件

STM32烧写到内部FLASH。

6ULL支持SD卡、EMMC、NAND、nor、SPI flash等等启动。裸机例程选择烧写到SD卡里面。

在ubuntu下向SD卡烧写裸机bin文件。烧写不是将bin文件拷贝到SD卡中,而是将bin文件烧写到SD卡绝对地址上。而且对于I.MX而言,不能直接烧写bin文件,比如先在bin文件前面添加头部。完成这个工作,需要使用正点原子提供的imxdownload软件。

Imxdownload使用方法,确定要烧写的SD卡文件,我的是/dev/sdb。

cd /dev/sd*  获取tf卡的位置

给予imxdownload可执行权限:

chmod 777 imxdownload

烧写:

./imxdownload led.bin /dev/sdb    sdb为你sd卡的分区

Imxdownlaod会向led.bin添加一个头部,生成新的load.imx文件,这个load.imx文件就是最终烧写到SD卡里面去的。

   拔下SD卡后插入开发板, boot拨码

    

LED0 被正常点亮,可能 LED0 之前会有一点微亮,那是因为 I.MX6U IO 默认电平可能让 LED0 导通了,但是 IO 的默认配置内部可能有很大的电阻,所以电流就 很小,导致 LED0 微亮

  • 52
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuqiu1186

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值