加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

arm remap

发布时间:2020-12-15 06:12:28 所属栏目:百科 来源:网络整理
导读:LPC2000系列ARM处理器重映射原理的分析与实现(转) ?? 摘要: 在ARM嵌入式软件开发过程中,经常会遇到一些重要的概念,比如重映射、分散加载等。本文结合具体的实例并以源代码的形式对这些概念进行了详细的分析,并给出了LPC2210处理器片外Flash启动和重映

LPC2000系列ARM处理器重映射原理的分析与实现(转)??

摘要: 在ARM嵌入式软件开发过程中,经常会遇到一些重要的概念,比如重映射、分散加载等。本文结合具体的实例并以源代码的形式对这些概念进行了详细的分析,并给出了LPC2210处理器片外Flash启动和重映射的实现方法。

关键字:启动代码 重映射 ARM

The Analysis and Implementation of Remapping on LPC2000 Series Microprocessor

Abstract

There are some very important concepts,such as remapping and scatterload in the development of ARM embedded software. A detailed analysis about these concepts are given on this paper with the source code,meanwhile,the implementation of boot from external flash memory and remapping on LPC2210 microprocessor is also given.

Keywords

boot code,remapping,ARM

多数嵌入式系统中,在进入主程序main之前,需要执行初始化序列对应用程序的运行环境进行配置。启动代码一般用汇编语言来编写,它主要对关键的设备进行初始化和配置,为应用程序的运行创造条件。在整个启动过程中,重映射是其中重要一环,正确的理解和实现重映射对于理解系统的工作原理极为重要。

本文的实验平台是EasyARM2210开发板,处理器为Philips LPC2210,它的片内只集成了一块位于0x40000000~0x40004000,大小为16K的SRAM,同时还扩展了一块位于0x80000000~0x801FFFFF,大小为8M字节的Flash。虽然本文的内容都是以LPC2100处理器为例来进行说明的,但对其它ARM系列的处理器来说也是适用的。

1 复位和初始化ARM处理器在复位后处于SVC模式,中断是禁止的,并且处于ARM状态。必须设置好各个异常模式堆栈的位置和大小,应用程序运行时所在的处理器模式和状态,并为它分配合适的堆栈和堆空间,以及使能中断和启用缓存(如果有的话)的时机。一般来说,你总是需要按照一个合理的顺序来初始化你的系统,

???? 整个初始化序列可以分为两个大的部分,用户代码和C库。C库初始化代码是由集成开发环境(这里使用的是ADS1.2)自动生成的,在完成任务之后,它最终将控制权转交给用户代码。__scatterload部分的作用相当于通常所说的bootloader,它会根据应用程序的设置(比如,我们可以通过分散加载文件精确的指定代码和数据在加载时和运行时的位置)自动生成代码将程序装载到用户希望的地址。__rt_entry部分的作用是执行运行时库的初始化工作。我们需要编码的是用户代码部分:首先设置各个模式的堆栈指针(由于LPC2210中没有MMU/MPU、缓存和TCM,因此这里只需要设置各个模式的堆栈指针即可,程序如list 1所示);其次,如果你使用了分散加载描述文件(由于实际系统中存储器类型的多样性,这几乎总是事实),那么必须实现函数__user_initial_stackheap( );最后是启用中断。

//list 1: 设置各种模式的堆栈指针值

Reset_Handler

??????????????IMPORT stack_base???????????? //stack_base的值在分散加载文件中设置

??????????????LDR?? r0,=stack_base

??????????????

??????????????MSR?? CPSR_c,#Mode_FIQ|I_Bit|F_Bit

??????????????SUB?? sp,r0,#offset_FIQ_Stack

??????????????MSR?? CPSR_c,#Mode_IRQ|I_Bit|F_Bit

??????????????SUB?? sp,#offset_IRQ_Stack

??????????????//…设置其它模式的堆栈指针

设置完各个模式的堆栈指针之后,要对关键的I/O设备进行初始化,对处理器时钟、存储器加速模块以及外部存储器模块进行设置。然后跳转到C库的__main,首先由C库代码按照分散加载文件的描述将代码和数据从加载地址拷贝到运行地址并对未初始化数据进行清零,然后跳转到__rt_entry对C运行时库进行初始化,最后将控制权转交给用户代码(即主程序main)。

2 存储器重映射2.1 内存布局?????? 嵌入式系统中经常同时存在多种不同类型的存储介质,从访问速度比较快的SRAM、DRAM到比较慢的FLASH ROM、E2PROM等。嵌入式系统开发者必须仔细的安排内存布局,将访问相对频繁的程序代码放到访问速度相对较快的存储器中。不同的集成开发环境提供了不同的方法帮助开发者来处理这些问题。在ADS1.2中,是通过编写分散加载文件进行描述的。

?????? 分散加载文件能够准确的将某个源文件编译后生成的目标文件加载到一个确定的内存位置,它同时指定了目标文件的加载地址和执行地址。每个目标文件都有一个唯一的加载地址和一个唯一的运行地址。如果一个目标文件的加载地址和执行地址不同,那么C库的__scatterload部分负责将它复制到执行地址处。

2.2 LPC2210处理器的重映射机制ARM是一个采用RISC体系结构的处理器内核,ARM公司本身并不生成芯片,它将ARM内核授权给生成和销售半导体的合作伙伴。虽然各个ARM芯片生产厂商所采用的内核是相同的,但是在一些细节上也是各有各的特色。本文所说的重映射都是针对LPC2000系列处理器来说的,其它公司比如Atmel、Intel等所采用的机制会有所不同。

所有的ARM系统都有一个异常向量表,它是跳转到各种异常处理程序的跳转指令列表。由于普通的跳转指令B label的跳转范围只有32M,为了实现4G范围内的任意跳转,可以采用指令LDR PC,target_addr,它将target_addr的值看作是一个地址值装载到PC中,于是跳转到那个地址处继续执行。这样向量表通常包括32字节的相对PC的跳转指令和32字节的异常处理程序地址。

通常系统对异常向量表的访问最为频繁,为了尽可能快的响应各种异常,必须考虑将异常向量表装载到何种类型的存储器中。片内RAM的访问速度最快,而且可以运行时对向量表进行修改,它无疑是向量表的理想选择。但是考虑到RAM不属于非易失性存储器,在掉电后不能保存它的内容,因此只能在系统启动后,将向量表复制到片内RAM中,并利用存储器重映射机制使向量表从片内RAM重新映射。在LPC2210中,重映射是通过寄存器MEMMAP来控制的,其用法如图2所示:

MEMMAP功能

描述

1:0

MAP1:0

00:Boot装载程序模式。异常向量从bootblock重新映射。

01:保留。该选项不使用。

10:用户RAM模式。异常向量从片内RAM重新映射。

11:用户外部存储器模式。异常向量从外部存储器重新映射。

7:2

保留

保留,不要向其写入1。

图2: MEMAP寄存器在LPC2000中,存储器重映射的部分包括异常向量区(32字节)和额外的32字节,一共是64字节,重新映射的代码位置与地址0x0~0x0000003F重叠。也就是说,当处于用户RAM模式时,如果访问0x0~0x3F的数据,实际上是在对0x40000000~0x4000003F进行访问。同样如果切换到外部存储器模式,并且同样对0x0~0x3F进行访问,就变成访问0x80000000~0x8000003F中的数据/指令了。

2.3 存储器重映射的实现为了实现对系统启动过程的精确控制,最好把与异常向量和启动代码相关的程序分别放在vectors.s和init.s这两个文件中,其中vectors.s包含了异常向量表,init.s包含了复位处理程序Reset_Handler,这样可以使用分散加载机制精确的控制异常向量表和复位处理程序在内存中的布局。在LPC2000系列处理器中异常向量表可以从片内RAM或者从片外存储器中重新映射,下面分别讨论一下这两种方式。

2.3.1 从RAM中重映射

将复位处理程序放在片外Flash存储器最低地址处,将异常向量表放在片内RAM的最低地址处,使用的分散加载文件如list 2所示。在系统复位后,外部存储器底部64个字节重新映射到地址0x0,并从中取出第一条指令

LDR??pc,=Instruct_2

于是控制流跳转到真实的ROM中继续执行。紧接着访问存储器控制寄存器使MEMMAP[1:0]=10,这样片内RAM中的异常向量表就映射到地址0x0。整个过程如图3所示。

//list 2:分散加载文件――异常向量从片内RAM重新映射

ROM_LOAD 0x80000000

{

????ROM_EXEC 0x80000000

????{??

????????init.o(Init,+First)

????????* (+RO)

????}

????IRAM 0x40000000

????{

????????vectors.o (Vect,+First)

????????* (+RW,+ZI)

????}

????//...

}

2.3.2 为ROM编写代码

上面的方法虽然能够正确的实现从RAM中重新映射异常向量,但是由于在系统复位或掉电重启后,RAM中的内容会丢失,导致程序不能运行,于是为了使程序能够正常运行,必须将异常向量表加载到非易失性存储器如Flash中。由于LPC2210处理器没有片内Flash存储器,必须正确的配置引脚13和16使系统从外部存储器启动。启动代码如list 3所示,系统启动后首先从标号Instruct_2开始执行,然后修改MEMMAP寄存器的内容(其中CM_ctl_reg等于MEMMAP寄存器的地址),于是异常向量表从片内RAM重新映射,最后将异常向量表从片外Flash拷贝到片内Flash。此后在发生异常后,处理器就自动从片内RAM取出异常处理程序的地址,从而能够显著提高程序的性能。

//list 3:部分启动代码

CM_ctl_reg??????EQU???? 0xE01FC040

RAM???????????? EQU???? 0x2

Reset_Handler

????LDR???? pc,???? =Instruct_2????????

Instruct_2

????LDR???? r1,?? =CM_ctl_reg

????LDR???? r0,?? [r1]

????AND???? r0,?? r0,#RemapMask

????ORR???? r0,#RAM

????STR???? r0,?? [r1]

????MOV???? r9??,#0x80000000

????MOV???? r10,#0x40000000

????LDMIA?? r9!,{r0-r7}

????STMIA?? r10!,{r0-r7}

????LDMIA?? r9!,{r0-r7}

在上面的复制完成之后,异常向量表就会同时出现在地址0x0、0x40000000以及0x80000000。描述映像布局的分散加载文件如列表list 4所示。注意执行区IRAM的基址不是0x40000000,而是0x40000040,因为起始的64字节是为异常向量表预留的。整个过程如果图4所示。

//list 4:分散加载文件―将异常向量

//从ROM拷贝到RAM中,并从片内RAM重新映射

ROM_LOAD 0x80000000

{

????ROM_EXEC 0x80000000

????{??

????????vectors.o (Vect,+First)??

????????* (+RO)

????}

????IRAM 0x40000040

????{

????????* (+RW,+ZI)

????}

????HEAP +0 UNINIT

????{

????????heap.o(+ZI)

????}

????STACKS 0x40004000 UNINIT

????{

LPC2000系列ARM处理器重映射原理的分析与实现(转)??

2010-09-09 15:37:47|??分类: 嵌入式 |??标签:嵌入式?? |字号?订阅

摘要: 在ARM嵌入式软件开发过程中,经常会遇到一些重要的概念,比如重映射、分散加载等。本文结合具体的实例并以源代码的形式对这些概念进行了详细的分析,并给出了LPC2210处理器片外Flash启动和重映射的实现方法。

关键字:启动代码 重映射 ARM

The Analysis and Implementation of Remapping on LPC2000 Series Microprocessor

Abstract

There are some very important concepts,the implementation of boot from external flash memory and remapping on LPC2210 microprocessor is also given.

Keywords

boot code,ARM

多数嵌入式系统中,在进入主程序main之前,需要执行初始化序列对应用程序的运行环境进行配置。启动代码一般用汇编语言来编写,它主要对关键的设备进行初始化和配置,为应用程序的运行创造条件。在整个启动过程中,重映射是其中重要一环,正确的理解和实现重映射对于理解系统的工作原理极为重要。

本文的实验平台是EasyARM2210开发板,处理器为Philips LPC2210,它的片内只集成了一块位于0x40000000~0x40004000,大小为16K的SRAM,同时还扩展了一块位于0x80000000~0x801FFFFF,大小为8M字节的Flash。虽然本文的内容都是以LPC2100处理器为例来进行说明的,但对其它ARM系列的处理器来说也是适用的。

1 复位和初始化ARM处理器在复位后处于SVC模式,中断是禁止的,并且处于ARM状态。必须设置好各个异常模式堆栈的位置和大小,应用程序运行时所在的处理器模式和状态,并为它分配合适的堆栈和堆空间,以及使能中断和启用缓存(如果有的话)的时机。一般来说,你总是需要按照一个合理的顺序来初始化你的系统,

???? 整个初始化序列可以分为两个大的部分,用户代码和C库。C库初始化代码是由集成开发环境(这里使用的是ADS1.2)自动生成的,在完成任务之后,它最终将控制权转交给用户代码。__scatterload部分的作用相当于通常所说的bootloader,它会根据应用程序的设置(比如,我们可以通过分散加载文件精确的指定代码和数据在加载时和运行时的位置)自动生成代码将程序装载到用户希望的地址。__rt_entry部分的作用是执行运行时库的初始化工作。我们需要编码的是用户代码部分:首先设置各个模式的堆栈指针(由于LPC2210中没有MMU/MPU、缓存和TCM,因此这里只需要设置各个模式的堆栈指针即可,程序如list 1所示);其次,如果你使用了分散加载描述文件(由于实际系统中存储器类型的多样性,这几乎总是事实),那么必须实现函数__user_initial_stackheap( );最后是启用中断。

//list 1: 设置各种模式的堆栈指针值

Reset_Handler

??????????????IMPORT stack_base???????????? //stack_base的值在分散加载文件中设置

??????????????LDR?? r0,=stack_base

??????????????

??????????????MSR?? CPSR_c,#Mode_FIQ|I_Bit|F_Bit

??????????????SUB?? sp,#offset_FIQ_Stack

??????????????MSR?? CPSR_c,#Mode_IRQ|I_Bit|F_Bit

??????????????SUB?? sp,#offset_IRQ_Stack

??????????????//…设置其它模式的堆栈指针

设置完各个模式的堆栈指针之后,要对关键的I/O设备进行初始化,对处理器时钟、存储器加速模块以及外部存储器模块进行设置。然后跳转到C库的__main,首先由C库代码按照分散加载文件的描述将代码和数据从加载地址拷贝到运行地址并对未初始化数据进行清零,然后跳转到__rt_entry对C运行时库进行初始化,最后将控制权转交给用户代码(即主程序main)。

2 存储器重映射2.1 内存布局?????? 嵌入式系统中经常同时存在多种不同类型的存储介质,从访问速度比较快的SRAM、DRAM到比较慢的FLASH ROM、E2PROM等。嵌入式系统开发者必须仔细的安排内存布局,将访问相对频繁的程序代码放到访问速度相对较快的存储器中。不同的集成开发环境提供了不同的方法帮助开发者来处理这些问题。在ADS1.2中,是通过编写分散加载文件进行描述的。

?????? 分散加载文件能够准确的将某个源文件编译后生成的目标文件加载到一个确定的内存位置,它同时指定了目标文件的加载地址和执行地址。每个目标文件都有一个唯一的加载地址和一个唯一的运行地址。如果一个目标文件的加载地址和执行地址不同,那么C库的__scatterload部分负责将它复制到执行地址处。

2.2 LPC2210处理器的重映射机制ARM是一个采用RISC体系结构的处理器内核,ARM公司本身并不生成芯片,它将ARM内核授权给生成和销售半导体的合作伙伴。虽然各个ARM芯片生产厂商所采用的内核是相同的,但是在一些细节上也是各有各的特色。本文所说的重映射都是针对LPC2000系列处理器来说的,其它公司比如Atmel、Intel等所采用的机制会有所不同。

所有的ARM系统都有一个异常向量表,它是跳转到各种异常处理程序的跳转指令列表。由于普通的跳转指令B label的跳转范围只有32M,为了实现4G范围内的任意跳转,可以采用指令LDR PC,target_addr,它将target_addr的值看作是一个地址值装载到PC中,于是跳转到那个地址处继续执行。这样向量表通常包括32字节的相对PC的跳转指令和32字节的异常处理程序地址。

通常系统对异常向量表的访问最为频繁,为了尽可能快的响应各种异常,必须考虑将异常向量表装载到何种类型的存储器中。片内RAM的访问速度最快,而且可以运行时对向量表进行修改,它无疑是向量表的理想选择。但是考虑到RAM不属于非易失性存储器,在掉电后不能保存它的内容,因此只能在系统启动后,将向量表复制到片内RAM中,并利用存储器重映射机制使向量表从片内RAM重新映射。在LPC2210中,重映射是通过寄存器MEMMAP来控制的,其用法如图2所示:

MEMMAP功能

描述

1:0

MAP1:0

00:Boot装载程序模式。异常向量从bootblock重新映射。

01:保留。该选项不使用。

10:用户RAM模式。异常向量从片内RAM重新映射。

11:用户外部存储器模式。异常向量从外部存储器重新映射。

7:2

保留

保留,不要向其写入1。

图2: MEMAP寄存器在LPC2000中,存储器重映射的部分包括异常向量区(32字节)和额外的32字节,一共是64字节,重新映射的代码位置与地址0x0~0x0000003F重叠。也就是说,当处于用户RAM模式时,如果访问0x0~0x3F的数据,实际上是在对0x40000000~0x4000003F进行访问。同样如果切换到外部存储器模式,并且同样对0x0~0x3F进行访问,就变成访问0x80000000~0x8000003F中的数据/指令了。

2.3 存储器重映射的实现为了实现对系统启动过程的精确控制,最好把与异常向量和启动代码相关的程序分别放在vectors.s和init.s这两个文件中,其中vectors.s包含了异常向量表,init.s包含了复位处理程序Reset_Handler,这样可以使用分散加载机制精确的控制异常向量表和复位处理程序在内存中的布局。在LPC2000系列处理器中异常向量表可以从片内RAM或者从片外存储器中重新映射,下面分别讨论一下这两种方式。

2.3.1 从RAM中重映射

将复位处理程序放在片外Flash存储器最低地址处,将异常向量表放在片内RAM的最低地址处,使用的分散加载文件如list 2所示。在系统复位后,外部存储器底部64个字节重新映射到地址0x0,并从中取出第一条指令

LDR??pc,=Instruct_2

于是控制流跳转到真实的ROM中继续执行。紧接着访问存储器控制寄存器使MEMMAP[1:0]=10,这样片内RAM中的异常向量表就映射到地址0x0。整个过程如图3所示。

//list 2:分散加载文件――异常向量从片内RAM重新映射

ROM_LOAD 0x80000000

{

????ROM_EXEC 0x80000000

????{??

????????init.o(Init,+First)

????????* (+RO)

????}

????IRAM 0x40000000

????{

????????vectors.o (Vect,+First)

????????* (+RW,+ZI)

????}

????//...

}

2.3.2 为ROM编写代码

上面的方法虽然能够正确的实现从RAM中重新映射异常向量,但是由于在系统复位或掉电重启后,RAM中的内容会丢失,导致程序不能运行,于是为了使程序能够正常运行,必须将异常向量表加载到非易失性存储器如Flash中。由于LPC2210处理器没有片内Flash存储器,必须正确的配置引脚13和16使系统从外部存储器启动。启动代码如list 3所示,系统启动后首先从标号Instruct_2开始执行,然后修改MEMMAP寄存器的内容(其中CM_ctl_reg等于MEMMAP寄存器的地址),于是异常向量表从片内RAM重新映射,最后将异常向量表从片外Flash拷贝到片内Flash。此后在发生异常后,处理器就自动从片内RAM取出异常处理程序的地址,从而能够显著提高程序的性能。

//list 3:部分启动代码

CM_ctl_reg??????EQU???? 0xE01FC040

RAM???????????? EQU???? 0x2

Reset_Handler

????LDR???? pc,???? =Instruct_2????????

Instruct_2

????LDR???? r1,?? =CM_ctl_reg

????LDR???? r0,?? [r1]

????AND???? r0,#RemapMask

????ORR???? r0,#RAM

????STR???? r0,?? [r1]

????MOV???? r9??,#0x80000000

????MOV???? r10,#0x40000000

????LDMIA?? r9!,{r0-r7}

????STMIA?? r10!,{r0-r7}

????LDMIA?? r9!,{r0-r7}

在上面的复制完成之后,异常向量表就会同时出现在地址0x0、0x40000000以及0x80000000。描述映像布局的分散加载文件如列表list 4所示。注意执行区IRAM的基址不是0x40000000,而是0x40000040,因为起始的64字节是为异常向量表预留的。整个过程如果图4所示。

//list 4:分散加载文件―将异常向量

//从ROM拷贝到RAM中,并从片内RAM重新映射

ROM_LOAD 0x80000000

{

????ROM_EXEC 0x80000000

????{??

????????vectors.o (Vect,+First)??

????????* (+RO)

????}

????IRAM 0x40000040

????{

????????* (+RW,+ZI)

????}

????HEAP +0 UNINIT

????{

????????heap.o(+ZI)

????}

????STACKS 0x40004000 UNINIT

????{

????????stack.o(+ZI)

????}

}

3 结论本文详细的介绍了基于LPC2000系列处理器的系统的初始化过程,并结合具体代码(在附带的程序中)对重映射作了细致的阐述,这些对于正确的理解和开发基于ARM的嵌入式系统具有重要的意义。

参考文献1.?????? RealView编译工具2.0版-开发者指南,ARM Ltd.

2.?????? LPC2210 User Manual-Preliminary Release,Philips Semiconductors.

3.?????? 杜春雷. ARM体系结构与编程. 清华大学出版社,2003.

????????stack.o(+ZI)

????}

}

3 结论本文详细的介绍了基于LPC2000系列处理器的系统的初始化过程,并结合具体代码(在附带的程序中)对重映射作了细致的阐述,这些对于正确的理解和开发基于ARM的嵌入式系统具有重要的意义。

参考文献1.?????? RealView编译工具2.0版-开发者指南,ARM Ltd.

2.?????? LPC2210 User Manual-Preliminary Release,Philips Semiconductors.

3.?????? 杜春雷. ARM体系结构与编程. 清华大学出版社,2003.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读