免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1576 | 回复: 0
打印 上一主题 下一主题

基于ARM核的Bootloader代码的分析与设计(LPC2210) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-03-12 12:56 |只看该作者 |倒序浏览
摘要:Bootloader是系统上电或复位后首先运行的一段代码,Bootloader代码(即启动代码)的好坏对整个系统的运行效率有着重要的影响, 而Bootloader代码与芯片的特性有着紧密的联系。本文根据用LPC2210在ADS(ARM Developer Suite)开发环境下进行嵌入式系统设计的实际经验,总结出基于ARM7TDMI内核的LPC2210处理器的Bootloader代码设计的详细流程及其中的一些关键技术和代码
关键词:ARM7TDMI核   ADS   Bootloader代码   LPC2210
前言:
基于ARM核的微处理器是目前嵌入式领域应用最广泛的RISC微处理器,以其低成本、低功耗、高性能等优点占据了嵌入式系统应用领域的领先地位。基于ARM核的芯片多数为复杂的片上系统集成, 在芯片上电或复位时,需要专门的一段代码来完成对系统的初始化。启动代码就是芯片上电或复位后进入应用程序main( )函数前执行的一段代码,它主要为运行C程序提供基本的运行环境。
1 启动代码的流程
Bootloader(启动)代码类似于PC机的BIOS(基本输入输出系统),它从系统上电或复位开始接管CPU,Bootloader根据实现的功能不同,其复杂程度也各不相同,一般随具体的目标系统和开发系统有所区别,使得每一种芯片的启动代码差别较大,不易编出统一的启动代码,但通常包括以下几个步骤:
·设置程序入口指针
·设置中断向量表
·初始化存储器系统
·初始化CPU各种模式的堆栈和寄存器
·初始化目标系统中要使用的各种片内外设
·初始化用户程序执行环境
·引导主应用程
2  基于LPC2210的Bootloader关键代码设计
2.1  LPC2210的Bootloader代码流程:
根据前面介绍的一般步骤,利用ARM公司推出的ADS开发工具,设计出LPC2210的Bootloader的具体流程(如图1)和关键代码。
Philips公司生产的LPC2210是基于ARM7TDMI核的RISC微处理器,特别适用于工业控制、医疗系统、访问控制。ADS是ARM公司推出的ARM核微处理器集成开发工具,成熟的版本是ADS1.2, ADS由命令行开发工具、ARM实时库、GUI开发环境、实用程序和支持软件组成,支持软件调试及JTAG硬件仿真调试,支持汇编、C和C++源程序。


2.2设置中断向量表
ARM芯片上电或复位后,系统进入管理模式、ARM状态、PC(R15)指向0x00000000地址处,所以必须保证向量表代码定位在0x00000000处,或者映射到0x00000000处,LPC2210系统上电或复位时,存储器映射控制寄存器(MEMMAP)等于0,Boot Block被重映射到地址0x00000000处,选择从Boot Block读取中断向量。中断向量表为每一个中断设置1个字(4个字节)的存储空间,存放一条跳转指令,通过这条指令使PC指针指向相应的中断服务程序入口,继而执行相应的中断处理程序。LPC2210的中断向量表和其它基于ARM核的芯片中断向量表较类似,只要注意LPC2210要使向量表所有数据32位累加和为零(0x00000000~0x0000001C的8个字的机器码累加), 才能使用户的程序脱机运行,限于篇幅,在此省略中断向量表的代码。

2.3初始化存储器系统
初始化存储器系统是初始化代码中的一个重要部分,因为许多操作系统在开始运行之前,希望了解存储器的组织情况。存储器系统初始化是通过软件设定FLASH、RAM存储器的地址范围,数据总线宽度。由于LPC2210是总线开放型芯片,具有4个Bank的存储器组,总线宽度可设置为8位、16位或32位。初始化存储器系统代码如下:
ResetInit
       LDR     R0, =PINSEL2
    IF :DEF: EN_CRP
        LDR     R1, =0x0f814910           ;芯片加密,禁止JTAG调试
    ELSE
        LDR     R1, =0x0f814914           ;设置总线的I/O引脚
    ENDIF
        STR     R1, [R0]
        LDR     R0, =BCFG0
        LDR     R1, =0x1000ffef
        STR     R1, [R0]                   ;设置外部第0个存储区
        LDR     R0, =BCFG1               
        LDR     R1, =0x1000ffef
        STR     R1, [R0]                   ;设置外部第1个存储区
        LDR     R0, =BCFG2
        LDR     R1, =0x2000ffef
        STR     R1, [R0]                   ;设置外部第2个存储区
        LDR     R0, =BCFG3
        LDR     R1, =0x2000ffef
        STR     R1, [R0]                   ;设置外部第3个存储区

2.4 初始化堆栈、改变处理器模式
ARM处理器有7种处理器模式,分别为:用户模式(usr)、快速中断模式(fiq)、普通中断模式(irq)、管理模式(svc)、数据访问中止模式(abt)、未定义指令中止模式(und)、系统模式(sys)。除用户模式之外的其他6种模式称为特权模式,在这些模式下,程序可以访问所有的系统资源,也可以任意进行处理器模式的切换。
每一种模式的堆栈指针寄存器(SP)都是独立的,因此对程序中需要用到的每一种模式都要给SP寄存器定义一个堆栈地址。方法是改变状态寄存器CPSR中的状态位,使处理器切换到相应的模式,然后再给SP赋值。这里有两点要注意:一、要尽量给堆栈分配快速和高带宽的存储器,因为堆栈性能的好坏对系统整体性能有非常重要的影响。二、在处理器模式切换时,不要过早地进入用户模式,因为进入用户模式就不能对CPSR进行修改切换到别的模式,这样会对接下去地程序造成影响,一般在系统初始化的最后阶段才将运行模式切换到用户模式。初始化堆栈代码如下:
InitStack   
        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     CPSR_c, #0xd7
        LDR     SP, StackAbt      ;设置中止模式堆栈
MSR     CPSR_c, #0xdb            
        LDR     SP, StackUnd      ;设置未定义模式堆栈
        MSR     CPSR_c, #0xdf
        LDR     SP, =StackUsr     ;设置用户模式堆栈
       MOV     PC, R0

2.  5初始化目标系统
为了LPC2210基本能够工作,在进入main( )函数前,须对目标系统进行一些基本的初始化工作。如:LPC2210有不同的存储器映射方式,须根据硬件来设置存储器映射方式;为了避免混乱,最好在进入main( )函数前设置系统各部分时钟等,关键代码如下:
void TargetResetInit(void)
{
#ifdef __DEBUG   
    MEMMAP = 0x3;                  
#endif
#ifdef __OUT_CHIP   
    MEMMAP = 0x3;                  
#endif
#ifdef __IN_CHIP   
    MEMMAP = 0x1;                       /*根据预定义的宏,设置存储器映射方式*/                  
#endif
/* 设置系统各部分时钟 */
    PLLCON = 1;                        /*使能PLL(锁相环),但不连接PLL*/
#if (Fpclk / (Fcclk / 4)) == 1
    VPBDIV = 0;
#endif
#if (Fpclk / (Fcclk / 4)) == 2
    VPBDIV = 2;
#endif
#if (Fpclk / (Fcclk / 4)) == 4
    VPBDIV = 1;                           
#endif                                   /*设置外设时钟(VPB时钟pclk)与系统时钟(cclk)的分频比*/
#if (Fcco / Fcclk) == 2
    PLLCFG = ((Fcclk / Fosc) - 1) | (0 #endif
#if (Fcco / Fcclk) == 4
    PLLCFG = ((Fcclk / Fosc) - 1) | (1 #endif
#if (Fcco / Fcclk) == 8
    PLLCFG = ((Fcclk / Fosc) - 1) | (2 #endif
#if (Fcco / Fcclk) == 16
    PLLCFG = ((Fcclk / Fosc) - 1) | (3 #endif
    PLLFEED = 0xaa;
    PLLFEED = 0x55;                      /*使用芯片要求的访问序列把数据写入PLL相关寄存器*/
    while((PLLSTAT & (1     PLLCON = 3;
    PLLFEED = 0xaa;
    PLLFEED = 0x55;                      /*使PLL连上系统*/
/* 设置存储器加速模块(MAM) */
    MAMCR = 0;                          /*关闭MAM*/
#if Fcclk     MAMTIM = 1;
#else
#if Fcclk     MAMTIM = 2;
#else
    MAMTIM = 3;                        /*根据Fcclk的大小来设置MAM定时寄存器*/
#endif
#endif
    MAMCR = 2;                        /*使能MAM*/
/* 初始化VIC */
VICIntEnClr = 0xffffffff                   ;禁止所有中断
VICVectAddr = 0                        ;设置向量地址寄存器(VICVectAddr)的值为0
VICIntSelect = 0                         ;将所有中断设置为IRQ中断
程序中的Fcclk、Fcco、Fpclk须在头文件中定义。

2.6 初始化应用程序
当所有的初始化工作完成后,调用ADS提供的__main, __main是ADS的编译系统提供的一个函数,负责完成C运行时库的初始化和应用程序执行环境的初始化,最后自动跳转到用户的main( )函数。代码为:
B    __main
3   结论
启动代码是嵌入式程序的开头部分,它直接面对处理器内核和硬件控制器进行编程,并首先在系统上运行,因此写好启动代码是设计好嵌入式系统的关键。本文介绍的Bootloader代码已经在Philips公司的LPC2210处理器上测试通过并运行稳定。对不同的ARM核芯片编写Bootloader代码,不但要了解ARM内核结构、指令系统,还要了解具体芯片的结构和各种片上资源。
参考文献
1           杜春雷.ARM体系结构与编程[M].北京:清华大学出版社.2004
2           马忠梅等.ARM嵌入式处理器结构与应用基础[M].北京:北京航空航天大学出版社.2003
3           周立功等.ARM微控制器基础与实践[M].北京:北京航空航天大学出版社.2003
4           Andrew N.Sloss、Dominic Symes、Chris Wright著.ARM嵌入式系统开发―软件设计与优化[M].沈建华译.北京:北京航空航天大学出版社.2005


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/58640/showart_494437.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP