基于gnu-arm-linux的LPC2220的简单工程模板
来源:互联网 发布:郑州大学网络教育学费 编辑:程序博客网 时间:2024/06/01 15:29
1:源头
2:例程实现的功能
初始化LPC2220芯片:
1,实现LPC2220中断向量表。
2,设置ARM芯片各个模式运行时所需的堆栈空间。本例程中将系统模式的堆栈设置在LPC2220内部RAM的最顶端,即0x40004000。这里是因为芯片默认的运行模式就是系
统模式,也即我们的用户程序都是在系统模式下运行的。又因为ARM芯片默认是从高地址向低地址使用堆栈,因此将LPC2220内部RAM的最顶端设置为系统模式下的堆栈
指针。其他模式的堆栈设置在0x400000000开始的内部RAM中。具体怎么实现的,我们下面例程代码中会讲解。
3,初始化目标板,主要设置各种总线时钟、向量表映射、存储BANK设置、存储器加速模块、实时时钟等系统控制模块。
4:将RW段从NorFlash COPY到SDram中,清零ZI段。
5:跳转到main函数执行。
6:使用标准库并实现printf,用于调试。
7:利用printf打印全局变量,局部变量内容,地址。用来说明全局变量,局部变量以及链接器链接等相关知识。
3:过程中遇到的困难
第一个是我想使用LPC2220的外部BANK1,我使用的硬件板,BANK1上接的是RAM,一开始程序怎么也调试不过,以为是链接脚本书写错误。但后来发现是对LPC2220的引脚功能设置的问题。这不是什么知识点,但让我在这上面浪费了不少时间,特此记录一下,以安慰我那颗受伤的心。所以,记得一些硬件资源要先看datasheet初始化好后再使用。
第二个是编译代码的时候,出现一堆的undefinedreference to `__umoddi3'之类的错误,而且我还发现了只要我代码里有取整取余等操作时就会报上述错误,真是百思不得其解,后来到网上去查资料,得出这个错误确实是因为使用了除法导致的。而且,ARM7不支持除法指令,需要软件进行辅助除法运算,而一般是通过标准库的形式提供。我们使用ADS1.2,keil等集成IDE开发程序时,它们自带的库里有对除法的支持。而我现在使用的编译链是从网上下载的别人编译好的arm-linux-gcc3.4.1,可能不支持除法、软浮点支持。我不知道怎么解决这个问题,所以,干脆我使用了我自己使用源码编译的交叉编译链(4.6.0版本的)。我编译交叉连的时候选择了除法、软浮点支持。问题得以解决。具体交叉编译链的制作,参考:制作S3C6410的交叉编译链(arm-linux-gcc4.6.0)。
第三个问题是编译的时候提示undefinedreference to `__exidx_start' undefined reference to`__exidx_end'等错误,而且是当我使用sprintf等相关格式化字符串的时候就提示这些错误,我没有找到合适的解决方案。所以,我参考网络资源自己实现了简单的格式化函数。这不是根本解决之道,我对使用gnu开发工具链进行嵌入式开发如何使用标准库函数也存在很多疑点。
4:部分例程代码
@******************************************************************************@ 文件名 :startup.s@ 功 能:初始化LPC2220:初始化各种运行模式的堆栈空间,各种exception@ 入口。@ 说明 :此工程为gcc for arm的工程,书写此工程启动代码目的是学习嵌入式开发过程中@ 的一些要点知识。gcc for arm 是开源的编译,链接器,可以学习程序开发的更多@ 细节。其他商业开发工具隐藏太多细节,不利于其初学者学习。@ 备注 :大家可以根据工程需要修改其内容。 @ 作者 :张连聘@ 创建时间:2014-07-27@******************************************************************************@define the stack size for each mode@定义各种运行模式堆栈大小.equ FIQ_STACK_LEGTH ,256 .equ IRQ_STACK_LEGTH ,9*8 .equ ABT_STACK_LEGTH ,256 .equ UND_STACK_LEGTH ,256.equ NoInt ,0x80.equ NoFIQ ,0x40.equ USR32Mode ,0x10.equ SVC32Mode ,0x13.equ SYS32Mode ,0x1f.equ IRQ32Mode ,0x12.equ FIQ32Mode ,0x11.equ PINSEL2 ,0xE002C014.equ BCFG0 ,0xFFE00000.equ BCFG1 ,0xFFE00004.equ BCFG2 ,0xFFE00008.equ BCFG3 ,0xFFE0000C@The imported labels @引入的外部标号在这声明 .extern FIQ_Exception @Fast interrupt exceptions handler 快速中断异常处理程序 .extern main @The entry point to the main function C语言主程序入口 .extern TargetResetInit @initialize the target board 目标板基本初始化 .extern SoftwareInterrupt.extern Copydata.extern ClearBssData.global Reset.text@interrupt vectors@中断向量表Reset: LDR PC, ResetAddr LDR PC, UndefinedAddr LDR PC, SWI_Addr LDR PC, PrefetchAddr LDR PC, DataAbortAddr .word 0xb9205f80 LDR PC, [PC, #-0xff0] LDR PC, FIQ_AddrResetAddr:.word ResetInitUndefinedAddr: .word UndefinedSWI_Addr:.word SoftwareInterruptPrefetchAddr:.word PrefetchAbortDataAbortAddr: .word DataAbortNouse: .word 0IRQ_Addr:.word 0FIQ_Addr: .word FIQ_Handler@未定义指令Undefined: B Undefined @取指令中止PrefetchAbort: B PrefetchAbort@取数据中止DataAbort: B DataAbort@快速中断FIQ_Handler: STMFD SP!, {R0-R3, LR} LDR PC, =FIQ_Exception LDMFD SP!, {R0-R3, LR} SUBS PC, LR, #4/***********************************************************************************************************函数名称: InitStack**功能描述: Initialize the stacks 初始化堆栈**输 入: None **输 出 : None **全局变量: None **调用模块: None ********************************************************************************************************/InitStack: MOV R0, LR@Build the SVC stack@设置中断模式堆栈 MSR CPSR_c, #0xd2 LDR SP, StackIrq@Build the FIQ stack@设置快速中断模式堆栈 MSR CPSR_c, #0xd1 LDR SP, StackFiq@Build the DATAABORT stack@设置中止模式堆栈 MSR CPSR_c, #0xd7 LDR SP, StackAbt@Build the UDF stack@设置未定义模式堆栈 MSR CPSR_c, #0xdb LDR SP, StackUnd@Build the SYS stack@设置系统模式堆栈 MSR CPSR_c, #0xdf LDR SP, =StackUsr BX R0/***********************************************************************************************************函数名称: ResetInit**功能描述: RESET 复位入口**输 入: None **输 出 : None **全局变量: None **调用模块: None **-------------------------------------------------------------------------------------------------------********************************************************************************************************/ResetInit:@Initial the extenal bus controller@初始化外部总线控制器,根据目标板决定配置LDR R0, =PINSEL2 LDR R1, =0x0f814914STR R1, [R0] LDR R1, =0x0f814914 LDR R0, =BCFG0 LDR R1, =0x1000ffef STR R1, [R0] LDR R0, =BCFG1 LDR R1, =0x1000ffef STR R1, [R0] LDR R0, =BCFG2 LDR R1, =0x0000fbef STR R1, [R0] LDR R0, =BCFG3 LDR R1, =0x10001460 STR R1, [R0] BL InitStack @ Initialize the stack 初始化堆栈 BL TargetResetInit @ Initialize the target board 目标板基本初始化BL CopydataBL ClearBssData B main @ Jump to the entry point of C program 跳转到c语言入口 StackIrq: .word IrqStackSpace +(IRQ_STACK_LEGTH - 1)*4StackFiq: .word FiqStackSpace +(FIQ_STACK_LEGTH - 1)*4StackAbt: .word AbtStackSpace +(ABT_STACK_LEGTH - 1)*4StackUnd: .word UndtStackSpace +(UND_STACK_LEGTH - 1)*4 /* 分配堆栈空间 */.bss .align 4 IrqStackSpace: .space IRQ_STACK_LEGTH * 4 @Stack spaces for Interrupt ReQuest Mode 中断模式堆栈空间FiqStackSpace: .space FIQ_STACK_LEGTH * 4 @Stack spaces for Fast Interrupt reQuest Mode 快速中断模式堆栈空间AbtStackSpace: .space ABT_STACK_LEGTH * 4 @Stack spaces for Suspend Mode 中止义模式堆栈空间UndtStackSpace: .space UND_STACK_LEGTH * 4 @Stack spaces for Undefined Mode 未定义模式堆栈.endmain.c
/******************************************************************************* 文件名 :main.c* 功 能:初始化系统后,利用P2.28控制led灯闪烁* * 作者 :张连聘* 创建时间:2014-07-27*******************************************************************************/#include "LPC2220.h"#include "uart0.h"#include "print.h"#define LEDCON (1<<28) void Delay(int ms);void myprintf(char *fmt,...);int globalvalue = 8;int main(void){int localvalue =88;IO2DIR = LEDCON; //配置P2.28为输出口PINSEL0 = 0x00000005; // 设置I/O连接到UART0 UART0_Init();while (1){myprintf("the globalvalue is %d\r\n",globalvalue);myprintf("the address of globalvalue is 0X%x\r\n",&globalvalue);myprintf("the localvalue is %d\r\n",localvalue);myprintf("the address of localvalue is 0X%x\r\n",&localvalue);myprintf("\n\n\n\n");Delay(50);IO2SET = LEDCON; //点亮LED灯Delay(10);IO2CLR = LEDCON; //熄灭LED灯Delay(10);//UART0_SendStr((unsigned char const *)str);}return 0;}/******************************************************************************* 名 称:Delay* 功 能:软件延时* 入口参数:ms * 出口参数:无******************************************************************************/void Delay(int ms){int i,j;for(i=0;i<5000;i++)for(j=0;j<ms;j++);}void myprintf(char *fmt,...){ va_list ap; char string[256]; va_start(ap,fmt); myvsprintf(string,fmt,ap); UART0_SendStr(string); va_end(ap);}void FIQ_Exception(void){}link_script.lds
/*链接脚本文件。*/OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(Reset) MEMORY{ rom (rx) : ORIGIN = 0x80000000, LENGTH = 2M ram (!rx) : ORIGIN = 0x81000000, LENGTH = 16M stack (!rx) : ORIGIN = 0x40000000, LENGTH = 64K}SECTIONS{. = 0x80000000 ;.text : {startup.o(.text)*(.text) _end_text = .;} >rom.rodata :{*(.rodata)} >rom. = 0x40000000;.MYSTACK :{_datastack_start = . ;startup.o(.bss)} >stack . = 0x40004000 ;StackUsr = . ;_datastack_end = . ;. = 0x81000000 ;.data :AT (ADDR(.rodata)+SIZEOF(.rodata)){_data_src = ADDR(.rodata)+SIZEOF(.rodata);_start_data = . ;*(.data)_end_data = . ;} >ram.bss :AT (ADDR(.data)+SIZEOF(.data)){_bss_start = . ;*(.bss)_bss_end = . ;} >ram}
Makefile
CC=arm-linux-gcc LD=arm-linux-ldCFLAGS := -Wall -c -g -mcpu=arm7tdmiOBJCOPY=arm-linux-objcopyOBJDUMP=arm-s3c6410-linux-gnueabi-objcopyOBJECTS :=startup.o target.o uart0.o print.o main.o control_led.bin:control_led_elf$(OBJDUMP) -O binary -S $^ $@control_led_elf:$(OBJECTS)$(LD) -Bstatic -Tlink_script.lds $^ -Map control_led_elf.map -o $@ \-L/usr/local/S3C6410/arm-s3c6410-linux-gnueabi/lib/gcc/arm-s3c6410-linux-gnueabi/4.6.0 \ -L/usr/local/S3C6410/arm-s3c6410-linux-gnueabi/lib \-L/usr/local/S3C6410/arm-s3c6410-linux-gnueabi/arm-s3c6410-linux-gnueabi/sysroot/usr/lib \--start-group -lgcc -lgcc_eh -lgcov -lc --end-group%.o:%.s$(CC) $(CFLAGS) -o $@ $<%.o:%.c$(CC) $(CFLAGS) -o $@ $<.PHONY : cleanclean:rm -f control_led.bin control_led_elf *.o
5:重点知识概要
AT (ADDR(.rodata)+SIZEOF(.rodata))
{
_data_src = ADDR(.rodata)+SIZEOF(.rodata);
_start_data = . ;
*(.data)
_end_data = . ;
} >ram
{
extern char _data_src,_start_data,_end_data;
char * data_src=&_data_src;
char * data_des=&_start_data;
char * data_end=&_end_data;
int len =data_end - data_des;
while(len>=0)
{
*data_des++= *data_src++;
len --;
}
int main(void)
{
int localvalue =88;
IO2DIR = LEDCON; //配置P2.28为输出口
PINSEL0 = 0x00000005; // 设置I/O连接到UART0
UART0_Init();
while (1)
{
myprintf("the globalvalue is %d\r\n",globalvalue);
myprintf("the address of globalvalue is 0X%x\r\n",&globalvalue);
myprintf("the localvalue is %d\r\n",localvalue);
myprintf("the address of localvalue is 0X%x\r\n",&localvalue);
myprintf("\n\n\n\n");
the address of globalvalue is 0X81000000
the localvalue is 88
the address of localvalue is 0X40003ff4
6:未实现的功能
7:总结
8:附录
本例程中源码下载:
基于gnu-arm交叉编译链的LPC2220的简单工程模板
- 基于gnu-arm-linux的LPC2220的简单工程模板
- 基于uthash的GNU/linux下简单hash_table模板类
- arm的gnu环境
- 用GNU工具开发基于ARM的嵌入式系统
- 用GNU工具开发基于ARM的嵌入式系统(zt)
- [转]用GNU工具开发基于ARM的嵌入式系统
- LPC2220启动编程的一些感想
- Linux系统的GNU下的ARM汇编指令详解
- GNU ARM汇编--(十五)linux下的printascii
- 新建基于固件库的工程模板-M3
- 新建基于寄存器版本的工程模板
- 简单描述为什么编译Android C程序所用的交叉编译工具链是arm-linux-androideabi-xx不是GNU开发的工具链arm-linux-gnueabi-xx?
- GNU/Linux的GNU是什么意思
- GNU ARM汇编--(十二)arm汇编指令的B真的那么简单吗?
- GNU ARM汇编--(十二)arm汇编指令的B真的那么简单吗?
- CodeSourcery's GNU Toolchains的改名命令集:转arm-none-linux-gnueabi-到arm-linux-
- 基于Arm 的linux 的启动分析
- 基于Arm 的linux 的启动分析
- 3.3-多个栈组合模拟一个栈
- struts1源码学习6(doPost和doGet)
- 如何调用DLL
- Jquery json jsp实例
- Leetcode--Divide Two Integers
- 基于gnu-arm-linux的LPC2220的简单工程模板
- HDU 4902 Nice boat(线段树 区间更新)
- ural 1932 The Secret of Identifier (容斥原理)
- HDU 4786 Fibonacci Tree 最小生成树 kruskal算法
- FFT.c
- hdu 1398 Square Coins
- 2014年辛星vim教程秋季版正式完工,特发此贴纪念下
- 国外大牛写的HOOK
- TOJ 3851. Variable Names