学海荡舟手机网

主页 > 实用文摘 > 教育文摘_15 > > 详细内容

ARM7TDMI-S在嵌入式系统中的Bootloader代码设计_嵌入式系统论文

 摘要:arm7tdmi-s是arm公司设计的一款32位精简指令集处理器内核,lpc210x系列是飞利浦半导体公司生产的基于arm7tdmi-s内核的芯片。在嵌入式系统设计中,针对嵌入式处理器和操作系统的bootloader代码的设计是一个难点。本文根据用lpc2106进行嵌入式系统设计的实际经验,出基于arm7tdmi-s内核的嵌入式处理器芯片的bootloader代码设计的一般流程;给出lpc2106芯片在基于μc/os-ii操作系统的嵌入式应用中,bootloader程序的详细设计流程及其中的一些关键技术和代码。

    关键词:arm7tdmi-s嵌入式系统 bootloader代码 lpc2106 μc/os-ii

引言

芯片的bootloader代码(即启动代码)就是芯片复位后进入操作系统之前执行的一段代码,主要是为运行操作系统提供基本的运行环境,如初始化cpu堆栈、初始化存储器系统等。bootloader代码与cpu芯片的内核结构、具体芯片和使用的操作系统等因素有关。其功能有点类似于pc机的bios(basic input/output system,基本输入输出系统)程序,但是由于嵌入式系统的软硬件都要比pc机的简单,所以它的bootloader代码要比bios程序简单得多。

嵌入式系统被定义为:以应用中为心,以计算机技术为基础,软件硬件可裁剪,适用于系统对功能、可靠性、成本、何种、功耗有严格要求的专用计算机系统。嵌入式系统的核心部件是嵌入式处理器。随着嵌入式系统在人们日常生活中的广泛运用,嵌入式处理器得到前所未有的飞速发展。基于arm核的嵌入式处理器芯片种类繁多。由于arm公司只设计内核的不生产具体的芯片,即便是基于同一种内核,不同厂家生产的芯片差别很大,因此不易编写出统一的bootloader代码。arm公司针对这一问题而采取的策略是,不提供完事的bootloader代码(arm公司的开发工具ads提供了一些功能代码),bootloader代码不足的部分由芯片厂商提供或者由用户自己编写。飞利浦公司没有提供lpc210x系列的bootloader代码,所以用户只能自己编写bootloader代码。

1 arm7tdmi-s和lpc210x

arm7tdmi-s是目前比较低端的arm核—arm核不是芯片,它与其它部件如ram、rom、片内外设组合在一起才构成实际的芯片。arm7是用于对成本和功耗都非常敏感的消费应用的低价位、低功耗的32位核。其主要特点如下:冯.诺依曼结构、3段流水线、0.9mips/mhz;非常低的功耗;嵌入式ice-rt(in circuit emulation-real time,实时在线仿真)逻辑。

lpc2104/2105/2106基于一个支持实时仿真和跟踪的arm7tdmi-s内核,并带有128kb的高速flash存储器,128位宽度的存储器接口和独特的加速结构,使32位代码能够在最大时钟速率下运行。由于lpc2104/2105/2106具有非常小的尺寸和极低的功耗,它们非常适合于那些将小型化作为主要要求的应用,例如存储取控制和pos机。带有宽范围的串行通信接口、片内多达64kb的sram,由于具有大的缓冲区和强大的处理器能力,它们非常适合于通信网关和协议转换器、软件调制解调器、声音识别以及低端的图像处理。而多个32位定时器、pwm输出和32个gpio,使它们特别适用于工业控制和医疗系统。lpc2106是lpc210x系列的一种,其它两种为lpc2104/2105。它们都基于arm7tdmi-s内核。三种芯片唯一的区别就是sram的容量大小:lpc2106是64kb,而lpc2104是16kb,lpc2105是32kb。

2 bootloader代码

2.1 bootloader代码的作用

嵌入式系统的资源有限,应用程序通常都是固化在rom中运行。rom中的程序执行前,需要对系统硬件和软件运行环境进行初始化。这些工作是用汇编语言和c语言编写的bootloader代码完成的。在arm处理器的嵌入式系统中,bootloader代码的作用主要有以下几点:

*初始化cpu各种模式的堆栈和寄存器;

*初始化系统中要使用的各种片内外设;

*初始化目标板;

*引导操作系统。

2.2 bootlader代码设计的一般流程

bootloader代码是嵌入式系统中应用程序的开头部分,它与应用程序一起固化在rom中,并首先在系统上运行。设计好bootloader代码是设计嵌入式程序的关键,也是系统能够正常工作的前提。bootloader代码所执行的操作主要信赖于cpu内核的类型,以及正在开发的嵌入式系统软件中需要使用cpu芯片上的哪些资源。bootloader代码的一般流程(即bootloader代码应该进行的操作)如图1所示。

2.3 基于lpc2104和μc/os-ii是多任务的实时操作系统。针对该款芯片和多任务实时操作系统的bootloader程序的流程如图2所示。

2.3.2 关键代码分析

;中断向量表,给出了cpu芯片出现异常时应该转去执行的程序地址

vectors

ldr pc,resetaddr

ldr pc,undefinedaddr

ldr pc,swi_addr

ldr pc,swi_addr

ldr pc,prefetchaddr

ldr pc,dataabortaddr

dcd 0xb9205f80

ldr pc,[pc,#-0xff0]

ldr pc,fiq_addr

resetaddr dcd reset

undefinedaddr dcd undefined

swi_addr dcd softwareinterrupt

prefetchaddr dcd prefetchabort

dataabortaddr dcd dataabort

nouse dcd 0

irq_addr dcd 0

fiq_addr dcd fiq_handler

;initstack函数,其功能是初始化cpu各种模式的堆栈

initsatck

mov r0,lr ;因芯片模式切换,故将程序返回地址保存至r0,同时在初始化堆栈完成后使用r0返回

msr cpsr_c,#0xd3 ;设置管理模式堆栈

ldr sp,stacksvc

msr cpsr_c,#0xd2 ;设置中断模式堆栈

ldr sp,stackirq

msr cpsr_c,#0xd1 ;设置快速中断模式堆栈

ldr sp,stackfiq

msr psr_c,#0xd7 ;设置中止模式堆栈

ldr sp,stackabt

msr cpsr_c,#0xdb ;设置未定义模式堆栈

ldr sp,stackund

msr cpsr_c,#0xdf ;设置系统模式堆栈

ldr sp,stackusr

mov pc,r0

stackusr dcd usrstackspace+(usr_stack_legth-1)*4

stackrvc dcd svcstackspace+(svc_stack_legth-1)*4

stackirq dcd irqstackspace+(irq_stack_legth-1)*4

stackfiq dcd fiqstackspace+(fiq_stack_legth-1)*4

stackabt dcd abtstackspace+(abt_stack_legth-1)*4

stackund dcd undtstackspace+(und_stack_legth-1)*4

;系统初始化代码

reset

bl initstack ;调用initstack函数初始化芯片各种模式的堆栈

bl targetresetinit ;调用targetresetinit函数对系统进行基本初始化

b _main ;跳转到ads提供的启动代码_main函数处,它初始化函数库并最终引导cpu进入操作系统的main()函数

    上面的程序代码只包含了流程图中的几个主机步骤。这些步骤都是必不可少的,其余的步骤都在targetresetinit函数中加以实现。本例中的targerreset init函数如下:

void targetresetinit(void)

{/*设置系统各部分时钟*/

pllcon=1;

#if((fcclk /4)/fpclk==1

vpbdiv=0;

#endif

#if((fcclk/4)/fpclk==2

vpbdiv=2;

#endif

#if((fcclk/4)/fpclk==4

vpbdiv=1;

#endif

#if(fcco/fcclk)==1

pllcfg=((fcclk/fosc)-1)|(1<<5);

#endif

#if(fcco/fcclk)==2

pllcfg=((fcclk/fosc)-1|(2<<5);

#endif

#if(fcco/fcclk)==4

pllcfg=((fcclk/fosc)-1|(3<<5);

#endif

#if(fcco/fcclk)==8

pllcfg=((fcclk/fosc)-1)|(4<<5);

#endif

pllfeed=0xaa;

pllfeed=0x55;

while(pllstat &(1<<10)==0)

pllcon=3;

pllfeed=0xaa;

pllfeed=0x55;

/*设置存储器加速模块*/

mamcr=2;

#if fcclk<20000000

mamtim=1;

#else

#if fcclk<40000000

mamtim=2;

#else

mamtm=3;

#endif

#endif

/*初始化vic,使芯片在进入μc/os-ii多任务环境前关中断*/

vicintenclr=0xffffffff;

vicvectaddr=0;

vicintselect=0;

/*其它步骤的代码与实际的软件功能相关,不具有代表性,故在此不列出*/

}

3 结论

本文介绍的bootloader代码已经在基于philips公司的lpc2106芯片开发的系统上运行并测试通过。针对不同的cpu芯片编写bootloader代码,首先要了解该cpu的内核结构、指令系统,其次是具体芯片的结构和各种片上资源,以及所采用的操作系统。以上所列的设计流程不是一成不变的,在具体应用中要权衡取舍。