2裸机:汇编驱动LED

I 点亮LED的过程

在这里插入图片描述

II cortex -A7 汇编指令

汇编的作用:初始化一些soc外设

由于汇编不像C等语言,可移植性强,我们使用GCC交叉编译器编译,所以汇编代码就要符合GNU语法

汇编由一条一条指令构成,需要查看cortex—A7的汇编指令手册。

1存储器访问指令LDR STR

LDR:用于将存储器中的数据加载到寄存器Rx中,也可以将一个数赋值给某个寄存器。
STR:将寄存器中的数据写入到存储器中

LDR R0,  = 0x0209c004   @将地址:0x0209c004  赋给 寄存器R0
LDR R1, [R0]          @读取地址为0x0209c004的存储器上的数据,到R1寄存器中
LDR R0,  = 0x0209c004   @将地址:0x0209c004  赋给 寄存器R0
LDR R1,  = 0x20000002   @将数据:0x20000002  赋给 寄存器R1
STR R1, [R0]          @将R1中保存的值 写入到 地址为0x0209c004的存储器

2跳转指令B

直接跳转到目标代码处,如果有没被执行的指令将不会被执行

III 代码

涉及使用寄存器的地址:

引脚时钟寄存器:
0X020C4068 		/* CCGR0 */
0X020C406C  	/* CCGR1 */
0X020C4070  	/* CCGR2 */
0X020C4074  	/* CCGR3 */
0X020C4078  	/* CCGR4 */
0X020C407C  	/* CCGR5 */
0X020C4080  	/* CCGR6 */
GPIO1_3功能复用寄存器:
0X020E0068	
GPIO1_3电气特性设置寄存器:
0X020E02F4
GPIO1组工作方向寄存器(GDIR)0X0209C004
GPIO1组电平输出设置寄存器(DR)
0209C000
.global _start  /* 全局标号 */

_start:

	/* 1、使能所有时钟 */
	ldr r0, =0X020C4068 	/* CCGR0 */
	ldr r1, =0XFFFFFFFF  
	str r1, [r0]		
	
	ldr r0, =0X020C406C  	/* CCGR1 */
	str r1, [r0]

	ldr r0, =0X020C4070  	/* CCGR2 */
	str r1, [r0]
	
	ldr r0, =0X020C4074  	/* CCGR3 */
	str r1, [r0]
	
	ldr r0, =0X020C4078  	/* CCGR4 */
	str r1, [r0]
	
	ldr r0, =0X020C407C  	/* CCGR5 */
	str r1, [r0]
	
	ldr r0, =0X020C4080  	/* CCGR6 */
	str r1, [r0]
	

	/*复用功能设置为:GPIO  寄存器:SW_MUX_GPIO1_IO03_BASE*/
	ldr r0, =0X020E0068	
	ldr r1, =0X5	
	str r1,[r0]

	/* 3、配置GPIO1_IO03的电气属性	寄存器:W_PAD_GPIO1_IO03_BASE
	 *bit 16:0 波形整形关闭
	 *bit [15:14]: 00 引脚下拉
     *bit [13]: 0 pue功能:保持
     *bit [12]: 1 pue功能开启
     *bit [11]: 0 关闭开漏输出
     *bit [7:6]: 10 速度100Mhz
     *bit [5:3]: 110 R0/6驱动能力
     *bit [0]: 0 低压摆率
     = 0x10B0
	 */
    ldr r0, =0X020E02F4	
    ldr r1, =0X10B0
    str r1,[r0]

	/* 4、设置GPIO1组的IO03的方向为输出 */ /*寄存器GPIO1_GDIR */
    ldr r0, =0X0209C004	
    ldr r1, =0X0000008		
    str r1,[r0]

	/* 5、打开LED0
	 * 设置GPIO1_IO03输出低电平,所幸把整组都设置为低电平
	 *//*寄存器GPIO1_DR */
	ldr r0, =0X0209C000	
   ldr r1, =0		
   str r1,[r0]

/*
 * 描述:	loop死循环
 */
loop:
	b loop 	

IV 编译程序

嵌入式系统CPU从flash读指令,从ram中取数据,指令总线和数据总线分开

1将.c.s文件编译成.o
	arm-linux-gnueabihf-gcc  -g -c  原文件(led.s) -o 输出文件(led.o) 
2将所有的.o文件链接成.elf(可执行文件)
    链接就是将所有.o文件链接在一起,并且链接到指定的地方(起始地址)
    链接起始地址就是代码运行的起始地址。
    对于6ULL来说,链接起始地址应该指向RAM地址,RAM分为内部RAM和外部RAM(也就是DDR)。
    6ULL内部RAM(128k)地址范围:0x900000~0x91ffff
    	外部DDR(512M)的地址范围:0x80000000~0x9fffffff
    
    -本次裸机开发:选用外部DDR,裸机代码起始地址为0x87800000,
    -要使用DDR就必须要初始化DDR,对于I.MX来说,bin文件不能直接运行,需要加一个头部,
     这个头部信息包含了DDR的初始化参数,I.MX系列SOC内部boot rom 会从SD卡,EMMC,
     等外置存储设备中读取头部信息然后初始化DDR,并将bin文件拷贝到指定地方(起始地址)
     即bin的运行地址要和链接起始地址一致,位置无关代码除外
	arm-linux-gnueabihf-ld -Ttext 0X87800000 原文件(led.o) -o 输出文件(led.elf) 
3将elf文件转化为bin文件 (烧写所需)
	arm-linux-gnueabihf-objcopy -O binary -S -g 原文件(led.elf)  输出文件(led.bin) 

PS:反汇编

arm-linux-gnueabihf-objdump -D  原文件(led.elf) > 输出文件(led.dis) 

V 烧写bin文件

-stm32烧写到内部flash
-6ULL支持sd卡,emmcNADA ,nor,SPI flash等启动
-本次裸机开发选择sd卡烧写
-烧写是指将bin文件烧写到sd卡的绝对地址上
-而且对于I.MX而言,不能直接烧写bin文件,必须先在bin文件前面添加头部,完成这个工作需要原子的imxdownload软件
 将其放到bin的同一文件夹

./imxdownload <参数1> <参数2>
参数1:目标文件(bin)
参数2:目标sd卡(df -h 查看位置,名称)


chmod 777 imxdownload 赋予执行权限
./imxdownload  led.bin  /dev/sdb  

该工具会向led.bin添加一个头部生成新的 imx 文件,这个文件就是最终烧录到sd卡中的文件

VI 将编译过程写成makefile文件

led.bin:led.s #led.bin 依赖 led.s 生成led.s的方法在下面
        arm-linux-gnueabihf-gcc -g -c led.s -o led.o
        arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
        arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
        arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
        rm -rf *.o led.bin led.elf led.dis
        

猜你喜欢

转载自blog.csdn.net/helloworld573/article/details/106532370