基于gcc的编程模板

嵌入式编程中,需要预先设置好的东西比较多,在初学嵌入式时,经常发现在看完某方面文档后,仍然编写出的程序达不到预定效果,在学习更多知识后才会了解,原来还有一些特殊方面需要提前设置好。因此,本文作为裸机程序编写第一篇,介绍一下之后使用的程序模板。这个模板力求精简,发挥最基础的作用。主要包含以下文件:

github地址:https://github.com/EleVenPerfect/S3C2440/tree/master/none-OS/

1.head.s

head.s是整个程序的最最前面的程序,它以汇编语言编写,负责设置堆栈、设置系统时钟、设置内存、关闭看门狗等作用,在最后它引导程序进入main函数,开始执行main中的程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@******************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@******************************************************************************

.extern main
.text
.global _start
_start:
Reset:
ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
// bl是位置无关码,相当于:PCnew = PC + 偏移
// PCnew = (4+8) + 0x28 = 0x34

//ldr pc, =disable_watch_dog /* 这样写将出错 */

bl clock_init @ 设置MPLL,改变FCLK、HCLK、PCLK
bl memsetup @ 设置存储控制器以使用SDRAM
bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
ldr pc, =on_sdram @ 跳到SDRAM中继续执行
on_sdram:
ldr sp, =0x34000000 @ 设置栈指针
ldr lr, =halt_loop @ 设置返回地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop

2.init.c

在head.s中,我们看到,有直接跳转函数的代码,这部分在init.c内,是以c语言编写的负责实际完成关闭看门狗、设置内存、设置系统时钟、将程序复制到内存的。至于为什么不在head.s中实现,因为很多操作相对复杂,用C更便捷吧。它的源码较长,可以在我的github上查看。

需要注意的是,我的内存初始化代码适用于TQ2440开发板的内存,对于不同的内存芯片,需要修改参数。

3.mian.c

通常学习过编程的人都知道,main.c是整个程序的开始,这个模板也不例外,在完成最初级的设置后,程序跳转到main.c开始执行用户代码。

4.Makefile

Makefile是这个项目的负责编译控制的文件,在gcc下,通过使用Makefile可以使用make命令直接将程序编译成开发板需要的镜像文件。

同时,可以自定义其他指令,如模板文件中,定义了make clean命令,负责删除编译生成的文件,便于重新编译。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
objs := head.o init.o serial.o main.o

000.bin: $(objs)
arm-linux-ld -Ttext 0x000000 -o timer_elf $^
arm-linux-objcopy -O binary -S timer_elf $@
arm-linux-objdump -D -m arm timer_elf > timer.dis

%.o:%.c
arm-linux-gcc -Wall -nostdlib -O2 -c -o $@ $<

%.o:%.S
arm-linux-gcc -Wall -nostdlib -O2 -c -o $@ $<

clean:
rm -f timer.bin timer_elf timer.dis *.o

同时,可以自定义其他指令,如模板文件中,定义了make clean命令,负责删除编译生成的文件,便于重新编译。

5.S3C2440.h

S3C2440.h文件负责定义S3C2440处理器的各个寄存器地址,这样在编程中就不需要查看某个寄存器的地址,直接使用名称来表示。

还有为方便调试,预先编写好的串口程序,可作为程序的调试工具。在程序出现问题是,可通过串口打印数据判断错误原因。

欢迎关注我的公众号,和我一起学习嵌入式知识。


基于gcc的编程模板
http://atime.cc/2017/01/31/基于gcc的编程模板/
作者
ATIME
发布于
2017年1月31日
许可协议