参考:1.https://blog.csdn.net/gushaofeng/article/details/53572717
2.https://blog.csdn.net/huangbin0709/article/details/51931347
-
制作交叉编译工具
不能使用 ubuntu16.04 自带的 arm-linux-gcc 3.45编译不同版本内核 Linux3.4.2,这时需要更换交叉编译器,更换方法也非常简单。
(1) 把arm-linux-gcc-4.3.2.tar.bz2 上传到 ubuntu,为了统一管理,上传到新创建的 tools 目录,先新建 tools 目录。
(2) 解压交叉编译器(一般解压到/目录)
book@www.100ask.org:~/tools$sudo tar -jxvf arm-linux-gcc-4.3.2.tar.bz2 –C /
(3) 在解压后的目录找到 arm-linux-gcc, 记住它的绝对路径, 解压到根目录的话应该是:/usr/local/arm/4.3.2/bin
(4)添加环境变量
book@www.100ask.org: sudo vi /etc/environment
用”#”号注释掉之前的路径,添加一行并保存退出:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/arm/4.3.2/bin"
(5)使环境变量生效: source /etc/environment
这时候交叉编译器版本变为 4.3.2
注:如果ubantu为64位,可能arm-linux-gcc会出问题,解决方法:
在ubuntu64位系统中将arm-linux-gcc添加到环境变量中后,运行arm-linux-gcc可能会出现如下错误提示:/usr/local/arm/4.4.3/bin/arm-linux-gcc: 15: exec: /usr/local/arm/4.4.3/bin/.arm-none-linux-gnueabi-gcc: not found。
解决方法:使用sudo apt install ia32-libs安装32位库,如果出现 “然而下列软件包会取代它:lib32ncurses5 lib32z1”,则安装“sudo apt-get install lib32ncurses5 lib32z1”,如果不成功,提示“有几个软件包无法下载,要不运行 apt-get update 或者加上 --fix-missing 的选项再试试?”,则使用“sudo apt-get update”更新安装包,然后再“sudo apt-get install lib32ncurses5 lib32z1”即可。
2.编写程序
- 制作好交叉编译工具链后,怎么确定是否有效呢,当然是编译一个程序烧写到板上跑一下了。这里我们以点亮LED灯为例描述如何使用我们制作的交叉编译工具链编译裸板程序。
首先,需要了解下Nor flash,Nand flash,片内内存,片外内存,地址空间这几个概念。其中,Nor flash是CPU可以直接通过硬件信号读取的,不需要配置,但是Norflash的写操作是需要配置和实现驱动的。片内内存不需要配置,CPU可以直接通过硬件信号读写。这是因为Nor flash和片内内存在硬件设计上就已经固化了他们的电气特性。而Nand flash的读写都必须配置,并且需要实现驱动。CPU通过相应的Nand flash控制器间接的读写数据。片外内存的读写也是需要配置的,通过内存控制器进行配置,配置好后CPU就可以发出合适的硬件信号进行直接读写。
通常,Nor flash,片内内存,片外内存是统一编址的,他们在CPU的地址空间内,而Nand flash是独立编址的。原因就是前面的描述,CPU无法直接访问Nand flash的地址。S3C2440的地址空间如下,注意,不同启动模式下,片内内存(Internal SRAM)的地址是不一样的。
这里的地址空间只是存储器的地址空间,还有CPU内部的寄存器地址空间,这些地址也是可以直接访问的,同常在高位地址。S3C2440的寄存器地址空间为0x4800000~0x5fffffff。
因为Norflash和片内内存不需要配置就可以读取,因此开发板只能从这两个地方启动。具体就是把代码烧写到Nor flash或者Nand flash处,如果在Nand flash,启动时硬件会自动拷贝代码到4KB的内部RAM。GT2440开发板nGCS0接的是Norflash。无论哪种模式启动,上电后CPU跳转到0地址处开始执行。如果在片内内存中,我们必须用4KB的代码完成Nand flash,内存控制器的初始化,并且把代码搬运到片外内存中。如果在Nor flash中,我们同样需要初始化内存控制器。由于裸板程序较小,不会超过4KB,因此我们暂时不需要做这些操作(如果在Norflash中我们可直接运行的代码量更大)。
此外,ARM处理器还有多种异常。系统上电和看门狗超时都会产生复位异常,跳转到0地址处执行。因此如果没有喂狗程序,我们必须先关闭看门狗,这是裸板程序必须实现的操作。此外,如果我们需要进入C语言代码,C语言都是由函数构成的。函数的调用需要堆栈,因此我们也要设置堆栈寄存器SP。注意SP必须指向我们当前CPU可以直接读写的内存(当前只有4KB内部RAM是可以直接读写的)。因此如果我们从Nor flash启动,在没有设置内存控制器前,我们是不能进入C代码的。这里我们将从Nand flash启动。
下面,我们开始写代码点亮LED等。GT2440的LED管脚如下:
我们在汇编代码start.s中关闭看门狗,初始化堆栈SP。
.text
.global _start
_start:
ldr r0,=0x53000000
mov r1,#0
str r1,[r0] /*关闭看门狗*/
ldr sp,=1024*4 /*不能超过内部ram,sdram还没有初始化*/
bl main
loop:
b loop
在C代码test.c中,我们点亮LED灯。注意GPIO寄存器是CPU内部寄存器,不需要配置即可直接读写。
#define GPBCON (*(volatile unsigned int *)0x56000010)
#define GPBDAT (*(volatile unsigned int *)0x56000014)
int main(int argc, char *argv[])
{
GPBCON = 1 << 10 | 1 << 12 | 1 << 14 | 1 << 16;/*设置LED管脚为输出模式*/
GPBDAT = ~(0x1 << 5); /*点亮其中两盏灯*/
return 0;
}
Makefile如下:
ARCH=arm
CC=$(ARCH)-linux-gcc
LD=$(ARCH)-linux-ld
OBJCOPY=$(ARCH)-linux-objcopy
led.bin:start.s test.c
$(CC) -g -c start.s test.c
$(LD) -Ttext 0x0 -g start.o test.o -o led_elf
#裸板程序,非操作系统环境,必须去除ELF可执行文件中的操作系统头部,转换为二进制文件
$(OBJCOPY) -O binary -S led_elf led.bin
clean:
rm -rf led.bin led_elf *.o
把led.bin烧写到Nand flash中,设置开发板从Nand flash中启动,我们发现LED灯被成功点亮了。