========================《一步一步写嵌入式操作系统——ARM编程方法与实践》(第一章、第二章)读书笔记===================
----------------------------------------搭建开发环境-----------------------------
安装编译器:
1、得到交叉编译工具:leeos_tools_for_linux.tar.gz
2、将编译器解压到指定目录下
cd /usr
tar zxvf leeos_tools_for_linux.tar.gz
3、配置环境变量
echo "PATH=\$PATH:/usr/leeos_tools_for_linux/bin">>/etc/profile
4、使profile文件生效
source /etc/profile
安装虚拟机:
1、得到虚拟硬件SkyEye源代码 skyeye-1.2.6_rc1.tar.bz2
2、安装
tar jxvf skyeye-1.2.6_rc1.tar.bz2
cd skyeye-1.2.6_rc1
./configure
make
make install
-------------------------------------------开发实例一(使用命令编译)-------------------------------------
1、编写代码
#define UFCON0 ((volatile unsigned int *)(0x50000020))
void helloworld(void){
const char * p = "helloworld";
while(*p){
*UFCON0 = *p++;
}
while(1);
}
注:物理地址0x50000020代表的是s3c2410的串口FIFO寄存器地址
文件保存后命名为helloworld.c
2、编译代码
arm-elf-gcc -O2 -c helloworld.c
注:命令执行后得到一个名为“helloworld.o”的文件
3、链接
arm-elf-ld -e helloworld -Ttext 0x0 helloworld.o -o helloworld
注:参数-e的作用是指定程序的运行入口为helloworld函数,参数-Ttext的作用是指定该程序的运行基地址
命令最后得到一个ELF格式的可执行程序helloworld
4、得到纯二进制代码
arm-elf-objcopy -O binary helloworld helloworld.bin
注:arm-elf-objcopy命令将ELF格式文件中的二进制代码抽离出来,
生成“helloworld.bin”文件,该文件为纯执行二进制代码
5、编写SkyEye的配置文件
cpu: arm920t
mach: s3c2410x
#physical memory
mem_bank: map = M, type = RW, addr = 0x00000000, size = 0x00800000, file=./helloworld.bin
#all peripherals I/O mapping area
mem_bank: map = I, type= RW, addr = 0x48000000, size = 0x20000000
注:文件保存后命名为skyeye.conf
注意文件末尾有一个回车键
6、运行程序
skyeye
注:将skyeye.conf 与 helloworld.bin放在同一个目录下
-------------------------------------开发实例二(使用脚本链接目标文件)----------------------------------------------------
1、编写代码
#define UFCON0 ((volatile unsigned int *)(0x50000020))
void helloworld(void){
const char * p = "helloworld";
while(*p){
*UFCON0 = *p++;
}
while(1);
}
2、编译代码
arm-elf-gcc -O2 -c helloworld.c
注:命令执行后得到一个名为“helloworld.o”的文件
3、编写链接脚本
ENTRY(helloworld)
SECTIONS
{
. = 0x00000000;
.text :{
*(.text)
}
. = ALIGN(32);
.data :{
*(.data)
}
. = ALIGN(32);
.bss :{
*(.bss)
}
}
注:文件保存为helloworld.lds
4、链接
arm-elf-ld -T helloworld.lds helloworld.o -o helloworld
注:命令执行后得到helloworld
5、得到纯二进制代码
arm-elf-objcopy -O binary helloworld helloworld.bin
注:arm-elf-objcopy命令将ELF格式文件中的二进制代码抽离出来,
生成“helloworld.bin”文件,该文件为纯执行二进制代码
6、编写skyeye配置文件
cpu: arm920t
mach: s3c2410x
#physical memory
mem_bank: map = M, type = RW, addr = 0x00000000, size = 0x00800000, file=./helloworld.bin
#all peripherals I/O mapping area
mem_bank: map = I, type= RW, addr = 0x48000000, size = 0x20000000
注:文件保存后命名为skyeye.conf
注意文件末尾有一个回车键
7、运行程序
skyeye
注:将skyeye.conf 与 helloworld.bin放在同一个目录下
--------------------------------开发实例三(用汇编语言)------------------------------------------
1、编写汇编代码
.arch armv4
.global helloworld
.equ REG_FIFO, 0x50000020
.text
.align 2
helloworld:
ldr r1,=REG_FIFO
adr r0,.L0
.L2:
ldr r2,[r0],#0x1;首先从寄存器R0所指向的地址中读取一个字节的数据存储在R2中,然后R0中的值自加1
str r2,[r1];将寄存器R2中的值,存储到R1地址处
cmp r2,#0x0;将比较的两个数相减,然后去影响标志位
bne .L2;如果不相等就跳转到.L2处
.L1:
b .L1 ;死循环
.align 2
.L0:
.ascii "helloworld\n\n\0"
注:文件保存为helloworld.s
2、编译
arm-elf-gcc -O2 -c helloworld.s
注:编译后得到helloworld.o目标文件
3、链接
arm-elf-ld -e helloworld -Ttext 0x0 helloworld.o -o helloworld
注:参数-e的作用是指定程序的运行入口为helloworld函数,参数-Ttext的作用是指定该程序的运行基地址
命令最后得到一个ELF格式的可执行程序helloworld
4、得到纯二进制代码
arm-elf-objcopy -O binary helloworld helloworld.bin
注:arm-elf-objcopy命令将ELF格式文件中的二进制代码抽离出来,
生成“helloworld.bin”文件,该文件为纯执行二进制代码
5、编写SkyEye的配置文件
cpu: arm920t
mach: s3c2410x
#physical memory
mem_bank: map = M, type = RW, addr = 0x00000000, size = 0x00800000, file=./helloworld.bin
#all peripherals I/O mapping area
mem_bank: map = I, type= RW, addr = 0x48000000, size = 0x20000000
注:文件保存后命名为skyeye.conf
注意文件末尾有一个回车键
6、运行程序
skyeye
注:将skyeye.conf 与 helloworld.bin放在同一个目录下
-------------------------------------开发实例四(汇编和C的混合编程)------------------------------------------------------------
1、编写汇编代码:
.arch armv4
.global _start
.equ REG_FIFO, 0x50000020
.text
.align 2
_start:
ldr r0,=REG_FIFO
adr r1,.L0
bl helloworld;b1指令在运行时,能够自动地保存程序的返回地址
.L1:
b .L1
.align 2
.L0:
.ascii "helloworld\n\n\0"
注:保存为文件start.s
2、编写C语言代码
int helloworld(unsigned int *addr, const char *p){
while(*p){
*addr = *p++;
}
return 0;
}
注:根据AAPCS(ARM过程调用标准)的规定,当函数发生调用的时候,函数的参数会保存在ARM核心寄存器R0~R3
中,如果函数多于4个,则剩下的参数会保存在堆栈中。
保存为文件helloworld.c
3、编译start.s文件
arm-elf-gcc -O2 -c start.s
注:编译后得到start.o目标文件
4、编译helloworld.c文件
arm-elf-gcc -O2 -c helloworld.c
注:编译后得到helloworld.o目标文件
5、链接两个目标文件
arm-elf-ld -e _start -Ttext 0x0 start.o helloworld.o -o helloworld
6、得到纯执行代码
arm-elf-objcopy -O binary helloworld helloworld.bin
--------------------------------------开发实例五(使用Makefile)-----------------------------------------------------
1、编写Makefile文件
CC=arm-elf-gcc
LD=arm-elf-ld
OBJCOPY=arm-elf-objcopy
CFLAGS= -O2 -g
ASFLAGS= -O2 -g
LDFLAGS= -Thelloworld.lds -Ttext 30000000
OBJS=start.o helloworld.o
.c.o:
$(CC) $(CFLAGS) -c $<
.s.o:
$(CC) $(ASFLAGS) -c $<
helloworld:$(OBJS)
$(CC) -static -nostartfiles -nostdlib $(LDFLAGS) $? -o $@ -lgcc
$(OBJCOPY) -O binary $@ helloworld.bin
clean:
rm *.o helloworld helloworld.bin -f
注:保存为文件Makefile
2、得到start.s 、helloworld.c 、helloworld.lds文件
3、make
注:执行命令之后得到helloworld.bin文件
4、make clean
注:执行命令之后,中间文件都被删除