1.USB下载.bin文件
2.SD卡下载.bin文件
3.安装交叉编译工具链
4.简述Makefile
5.mkv210_image.c+Makefile
6.点亮LED1原理图
7.点亮LED数据手册查阅
8.汇编点亮led
9.位运算实现
10.延时函数+LED闪烁
11.流水灯
12.反汇编工具objdump
1.USB下载.bin文件
1.安装usb驱动
2.用dnw下载,注意下载地址选择0xd0020010
2.SD卡下载.bin文件
1.SD卡烧录
2.拨码至SD卡通道启动(SD2),(提前破坏SD0通道)
3.接通电源
3.安装交叉编译工具链
1.解压tar -jxvf filename
2.环境变量
2.1 cd ~
2.2 .bashrc
2.3 最后一行 export PATH = xxxxx:&PATH
2.4 source
3.软链接(a.sh)
#!/bin/sh
ln arm-none-linux-gnueabi-addr2line -s arm-linux-addr2line
ln arm-none-linux-gnueabi-ar -s arm-linux-ar
ln arm-none-linux-gnueabi-as -s arm-linux-as
ln arm-none-linux-gnueabi-c++ -s arm-linux-c++
ln arm-none-linux-gnueabi-c++filt -s arm-linux-c++filt
ln arm-none-linux-gnueabi-cpp -s arm-linux-cpp
ln arm-none-linux-gnueabi-g++ -s arm-linux-g++
ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc
ln arm-none-linux-gnueabi-gcc-4.4.1 -s arm-linux-gcc-4.4.1
ln arm-none-linux-gnueabi-gcov -s arm-linux-gcov
ln arm-none-linux-gnueabi-gdb -s arm-linux-gdb
ln arm-none-linux-gnueabi-gdbtui -s arm-linux-gdbtui
ln arm-none-linux-gnueabi-gprof -s arm-linux-gprof
ln arm-none-linux-gnueabi-ld -s arm-linux-ld
ln arm-none-linux-gnueabi-nm -s arm-linux-nm
ln arm-none-linux-gnueabi-objcopy -s arm-linux-objcopy
ln arm-none-linux-gnueabi-objdump -s arm-linux-objdump
ln arm-none-linux-gnueabi-ranlib -s arm-linux-ranlib
ln arm-none-linux-gnueabi-readelf -s arm-linux-readelf
ln arm-none-linux-gnueabi-size -s arm-linux-size
ln arm-none-linux-gnueabi-sprite -s arm-linux-sprite
ln arm-none-linux-gnueabi-strings -s arm-linux-strings
ln arm-none-linux-gnueabi-strip -s arm-linux-strip
执行:
chmod a+x a.sh
./a.sh
测试:
打开终端
arm-linux-gcc -v
arm-linux-gcc -a.c
file a.out
4.简述Makefile
4.1Makefile中的一些基本概念:
目标:目标定格写,后面是冒号(冒号后面是依赖)
依赖:依赖是用来产生目标的原材料。
命令:命令前面一定是Tab,不能是定格,也不能说多个空格。命令就是要生成那个目标需要做的动作。
5.mkv210_image.c+Makefile
//镜像目标:依赖
led.bin: start.o
//链接
arm-linux-ld -Ttext 0x0 -o led.elf $^
//用arm-linux-objcopy工具链生成镜像
arm-linux-objcopy -O binary led.elf led.bin
//反汇编
arm-linux-objdump -D led.elf > led_elf.dis
//在ubuntu内通过gcc编译mkv210_image.c后,生成的可执行程序可以把led.bin变为210.bin(SD卡烧录)
gcc mkv210_image.c -o mkx210
./mkx210 led.bin 210.bin
%.o : %.S
//gcc -o指定名字 -c只编译不链接% .o是$@ %.S是$<
arm-linux-gcc -o $@ $< -c
%.o : %.c
//gcc -o 只编译不链接
arm-linux-gcc -o $@ $< -c
clean:
rm *.o *.elf *.bin *.dis mkx210 -f
编译要使用编译器gcc,链接要使用链接器ld
6.点亮LED原理图
1.低电平点亮
2. D22:GPJ0_3
D23:GPJ0_4
D24:GPJ0_5
D25:PWMTOUT1(GPD0_1)
7.点亮LED数据手册查阅
GPD0
GPJ0
解析:
以GPJ0为例:
GPJ0CON, R/W, Address = 0xE020_0240
GPJ0CON作用:0xE020_0240地址的32位bit分为8组,每组代表一个GPJ0_X,设置0001可以时管理led的寄存器处于输出状态
GPJ0DAT作用:0xE020_0244的地址的8位,每一位对应CON中的一组,1表示高电平,0表示低电平,结合原理图(给0点亮led)
8.汇编点亮led
/*
* 文件名: led.s
* 作者: LS
* 描述: 汇编写的第一个裸机程序
*/
_start:
// 第一步:把0x11111111写入0xE0200240(GPJ0CON)位置
ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数
ldr r1, =0xE0200240 // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令
str r0, [r1]// 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去
// 第二步:把0x0写入0xE0200244(GPJ0DAT)位置
ldr r0, =0x0
ldr r1, =0xE0200244
str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
flag:
b flag
9.位运算实现
/*
* 文件名: led.s
* 作者: ls
* 描述: 加入位运算、宏定义
*/
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
.global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
// 第一步:把所有引脚都设置为输出模式,代码不变
ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数
ldr r1, =GPJ0CON // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令
str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去
// 第二步:把中间LED(GPJ0_4)的输出设置为0,其余两颗设置为1,剩下的其他位不管
//ldr r0, =((1<<3) | (1<<5)) // 等效于0b00101000,即0x28
ldr r0, =((1<<3) | (0<<4) | (1<<5)) // 清清楚楚的看到哪个灭,哪个是亮
ldr r1, =GPJ0DAT
str r0, [r1]// 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
b .
10.延时函数+LED闪烁
/*
* 文件名: led.s
* 作者: ls
* 描述: 延时函数+LED闪烁
*/
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
.global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:
// 第一步:把所有引脚都设置为输出模式,代码不变
ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数
ldr r1, =GPJ0CON // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令
str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去
flash:
// 第二步:全部点亮
ldr r0, =((0<<3) | (0<<4) | (0<<5)) // 清清楚楚的看到哪个灭,哪个是亮
ldr r1, =GPJ0DAT
str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮
// 第三步:延时
bl delay // 使用bl进行函数调用
// 第四步:全部熄灭
ldr r0, =((1<<3) | (1<<4) | (1<<5)) // 清清楚楚的看到哪个灭,哪个是亮
ldr r1, =GPJ0DAT
str r0, [r1]
// 第五步:延时
bl delay
b flash
// 延时函数:函数名:delay
delay:
ldr r2, =9000000
ldr r3, =0x0
delay_loop:
sub r2, r2, #1 //r2 = r2 -1
cmp r2, r3 // cmp会影响Z标志位,如果r2等于r3则Z=1,下一句中eq就会成立
bne delay_loop
mov pc, lr // 函数调用返回
11.流水灯
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
#define GPDOCON 0xE02000A0
#define GPDODAT 0xE02000A4
.global _start
_start:
ldr r0, =0x11111111
ldr r1, =GPJ0CON
str r0, [r1]
ldr r4, =0x1111
ldr r5, =GPDOCON
str r4, [r5]
flash:
ldr r0, = ~(1<<3)
ldr r1, =GPJ0DAT
str r0, [r1]
ldr r4, = (1<<1)
ldr r5, =GPDODAT
str r4, [r5]
bl delay
ldr r0, = ~(1<<4)
ldr r1, =GPJ0DAT
str r0, [r1]
ldr r4, = (1<<1)
ldr r5, =GPDODAT
str r4, [r5]
bl delay
ldr r0, = ~(1<<5)
ldr r1, =GPJ0DAT
str r0, [r1]
ldr r4, = (1<<1)
ldr r5, =GPDODAT
str r4, [r5]
bl delay
ldr r4, = ~(1<<1)
ldr r5, =GPDODAT
str r4, [r5]
ldr r0, = (1<<5)|(1<<3)|(1<<4)
ldr r1, =GPJ0DAT
str r0, [r1]
bl delay
b flash
delay:
ldr r2, = 9000000
ldr r3, = 0x0
delay_loop:
sub r2,r2,#1
cmp r2,r3
bne delay_loop
mov pc ,lr
12.反汇编工具objdump
arm-linux-objdump -D led.elf > led_elf.dis
objdump是gcc工具链中的反汇编工具,作用是由编译链接好的elf格式的可执行程序反过来得到汇编源代码
-D表示反汇编 > 左边的是elf的可执行程序(反汇编时的原材料),>右边的是反汇编生成的反汇编程序
反汇编的原因有以下:
1.逆向破解。
2.调试程序时,反汇编代码可以帮助我们理解程序(我们学习时使用objdump主要目的是这个),尤其是在理解链接脚本、链接地址等概念时。
3. 把C语言源代码编译链接生成的可执行程序反汇编后得到对应的汇编代码,可以帮助我们理解C语言和汇编语言之间的对应关系。非常有助于深入理解C语言。