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