很多没有接触过嵌入式的,或者习惯IDE开发的朋友,上来就是个main函数,今天从启动代码开始,真正从0开始点个灯。
嵌入式Linux学习系列全部文章:嵌入式Linux学习—从裸机到应用教程大全
板子和芯片无所谓,其实都差不多,会看手册,看原理图都一样,
我所用板子的SOC:S3C2440,ARM架构
启动代码为一段汇编语言所写的代码,
主要作用为关看门狗,设置栈,设置时钟,跳转main函数执行等。
这篇文章中的启动代码只需要设置栈,跳转main。
- .text
- .global _start
- _start:
- //初始化堆栈
- LDR SP,=4096
- //NOR启动 LDR SP,=0x40000000+4096
- //跳转至main
- BL main
- //无限循环
- halt:
- B halt
看不懂汇编的可以先看http://t.csdn.cn/bNpxd
这里简单说一下,.text代表代码段,.global声明全局变量,_start标号就是真正启动开始的地方。
LDR SP,=4096伪指令,设置栈的地址(Nand启动)
如果不是从Nand启动则LDR SP,=0x40000000+4096
我是如何知道这个栈地址的?
看芯片手册,找到memory controller那一章就有说明
如图:
代码复制到片内SRAM执行,片内SRAM大小为4KB,将栈设置到片内SRAM顶端。
学过单片机的朋友可能知道,想要实现某个功能无非就是
1.配置相应控制寄存器
2.设置相应数据寄存器
我想让我板子上的LED灯亮,得先找到LED连接的引脚,
看原理图
我想让这个LED_1亮,根据原理图配置相应引脚为输出,电平为低电平就行。
继续看连到了芯片上的哪一个引脚(IO端口)。

看了原理图,发现原来是GPF4
查芯片手册,看看GPF4要怎么配置

于是代码就出来了
- #include
- int main()
- {
- //设置IO为输出,设置IO对应引脚为低电平,GPF4
- unsigned int *GPFCON,*GPFDAT;
- GPFCON = 0x56000050;
- GPFDAT = 0x56000054;
- *GPFCON = 0x00000100;
- *GPFDAT = 0;
- return 0;
- }
我们得让启动代码start.S和C代码连接起来,
可以手动先编译,再链接,但是真实开发过程往往很多bug,老是输入编译,链接命令很麻烦,所以写个Makefile。
- all:
- arm-linux-gcc -c -o led.o led.c
- arm-linux-gcc -c -o start.o start.S
- arm-linux-ld -Ttext 0 start.o led.o -o led.elf
- arm-linux-objcopy -O binary -S led.elf led.bin
- clean:
- rm *.bin *.o *.elf
不会写Makefile的朋友可以翻一翻我的文章。
然后一个make命令就得到了二进制文件led.bin
烧到板子上,灯就亮了。
这就是从启动代码开始的全部过程。