AT91RM9200启动机制简析

AT91RM9200启动机制简析


本文以H9200M开发板为例,简单分析一下AT91RM9200处理器的启动机制

一 H9200M开发板简介
1.ATMEL的AT91RM9200微处理器
  AT91RM9200微处理器是一款由ATMEL设计生产的嵌入式ARM微处理器,内含一个
ARM920T核和以下主要片内外围
1) ARM920T ARM-Thumb 微处理器核
2) 片内存储器
   128K ROM: 地址 0x00100000 内有厂家固化的启动代码
   16K SRAM: 地址 0x00200000 通常在此配置堆栈区
3) 外部总线接口 EBI
   支持SDRAM,Static Memory,Burst Flash,和nand Flash等
4) 片内外围电路    5) 网卡接口       6) 双USB2.0主口
7) USB从口         8) 多媒体卡接口   9) IEEE 1149.1JTAG边界扫描接口 MCI
10)三个异步串行控制器 SSC            11)四个同步/异步收发器 USART
12)主/从串行外围接口 SPI             13)两个三通道16位的定时/计数器 TC
14)两线接口 TWI
2.NOR Flash存储器
  4M 数据宽度16位存放启动代码,Linux内核,用户程序等
  通过J201跳线选择 Chip Select 0(0x10000000) 或 Chip Select 7(0x80000000)
3.NOR Flash存储器
  64M 16位 映射到Chip Select 3 (0x40000000)
4.SDRAM 存储器
  32M 由两块16位的SDRAM并联成32位的存储系统 作为程序的运行空间(内存)
  映射到Chip Select 1 (0x20000000)
5.异步串行通讯口
  Debug UART:用于软件调试与开发
  UART0:用于与PC及Modem通讯
6.UD485接口
7.以太网MAC
8.USB接口
9.IIC存储器
  用于存储IP地址、MAC地址及系统加密等
10.系统总线驱动
11.跳线及LED显示
12.JTAG接口
13.复位电路
14.电源电路

二 启动模式选择(BMS)

AT91RM9200芯片的PA31/BMS引脚的电平高低来决定选择哪种启动模式
当J100跳线1-2短接时,BMS为低电平(BMS=0),复位后从片外Flash启动
当J100跳线2-3短接时,BMS为高电平(BMS=1),复位后从片内ROM启动
启动(复位)时首先执行的是位于0x00000000处的指令
1.片内启动(BMS=1)
  片内ROM代码主要包含两部分:bootloader和Uploader
  当BMS=1时,ROM地址被重映射为0x00000000,内部固化的启动代码开始运行,首先
激活bootloader对设备进行初始化,接下来从片外"非挥发"的存储器中寻找有效的
可执行代码.首先要分析该存储器的前32字节(即ARM异常向量入口代码,当ARM发生
异常时转向不同的处理程序进行处理),若是执行跳转或载入与PC 寻址相关的PC
ARM 指令,则认为是有效代码,分析计算要下载代码的长度,然后将确定大小的代码
载入到片内SRAM的起始地址(0x00200000)处,随后该地址被映射为0x00000000并开
始执行下载的代码(相当于bootloader的stage1阶段,启动过程详见uboot的启动流
程).
  若没有找到有效的代码,Boot Uploader被激活,建立外部通讯通道(调试串口
Debug UART 或USB),启动xmodem协议,等待用户上传代码(loader.bin),载入片内
SRAM并执行(进行必要的初始化),进入uboot启动流程.
  Uboot启动后,即可将起动程序(boot.bin ramdisk uboot.bin),Linux内核及应用
程序烧到Flash中固化,复位后即可从片外Flash启动.
2.片外启动(BMS=0)
  当BMS=0时,片外含有启动代码的Flash被映射到0x00000000,并由此处开始执行.
注:引导程序为变量与堆栈在内部SRAM 开辟一片存储区域。为防止上载错误,载入
的应用程序至少要小于SRAM 3K.

 

 

From   http://dearboy.blog.com.cn/archives/2006/1640436.shtml

 

at91rm9200 : Atmel 公司生产的基于arm9核的Soc处理器.

以下先给出at91rm9200引导流程图

Boot program Flow Diagram

Device Setup
|
|
Boot SPI DataFlash Boot --> Download from DataFlash --> run
|
|
TWI EEPROM Boot --> Download from EEPROM --> run
|
|
Parallel Boot --> Download from 8-bit Device -->
|
| Xmodem protocol
| |---DBGU Serial Download ---------------------> run
|____|
| DFU protocol
|-----USB download -----------------------> run

在这里我主要介绍通过片内引导和片外引导, 片内引导主要采用串口下载并引导u-boot,并完成程序被烧写到Flash上,
然后就可以通过跳线的方式从片外引导执行已经烧写到片外Flash上的引导程序(bootloader).

这里要提及的是at91rm9200内部本身有128k的片内rom,其固化了一个bootloader和uploader, 用来支持程序的
下载和引导,而且其内部固化的程序提供了很多内部服务接口(Internel Service)供我们来使用,例如Xmodem,Tempo
DataFlash, CRC, Sine服务接口,这样我们就可以利用它所提供的Service interface API完成程序的下载。
这里主要介绍Xmodem接口服务。

at91rm9200内部固化的代码在设计上采用了面向对象的设计方法,如下:


typedef struct _AT91S_Service
{
char data;
char (*MainMethod)();
char (*ChildMethod)();
}AT91S_Service, *AT91PS_Service;

char AT91F_MainMethod()
{

}
char AT91F_ChildMethod()
{

}

/*init the Service */
AT91PS_Service AT91F_OpenDevice(AT91PS_Service pService)
{
pService->data = 0;
pService->MainMethod = AT91F_MainMethod;
pService->ChildMethod = AT91F_ChildMethod;
}

//使用方法如下
AT91S_Service service;
AT91PS_Service pService = AT91F_OpenDevice(&service);
pService->AT91F_MainMethmod();
.....

通过如上代码片断可以看出它采用了类似面向对象的设计方法。
其实如果各位朋友接触过的话或者看过这本书的话,应该很容易便接受它。
下面以Xmodem服务为例子介绍:


at91rm9200内部提供的服务包含了几个服务对象, 这些对象在片内启动xmodem协议Host端和Targe端通讯时会用到.


typedef struct _AT91S_RomBoot
{
const unsigned int version;
// Peripheral descriptors
const AT91S_MEMCDesc MEMC_DESC;
const AT91S_STDesc SYSTIMER_DESC;
const AT91S_Pio2Desc PIOA_DESC;
const AT91S_Pio2Desc PIOB_DESC;
const AT91S_USART2Desc DBGU_DESC;
const AT91S_USART2Desc USART0_DESC;
const AT91S_USART2Desc USART1_DESC;
const AT91S_USART2Desc USART2_DESC;
const AT91S_USART2Desc USART3_DESC;
const AT91S_TWIDesc TWI_DESC;
const AT91S_SPIDesc SPI_DESC;

// Objects entry
const AT91PF_OpenPipe OpenPipe;
const AT91PF_OpenSBuffer OpenSBuffer;
const AT91PF_OpenSvcUdp OpenSvcUdp;
const AT91PF_OpenSvcXmodem OpenSvcXmodem;
const AT91PF_OpenCtlTempo OpenCtlTempo;
const AT91PF_OpenDfuDesc OpenDfuDesc;
const AT91PF_OpenUsbDesc OpenUsbDesc;
const AT91PF_OpenSvcDataFlash OpenSvcDataFlash;
const AT91PF_SVC_CRC16 CRC16;
const AT91PF_SVC_CRCCCITT CRCCCITT;
const AT91PF_SVC_CRCHDLC CRCHDLC;
const AT91PF_SVC_CRC32 CRC32;
// Array
const AT91PS_SVC_CRC_BIT_REV Bit_Reverse_Array;
const AT91PS_SINE_TAB SineTab;
const AT91PF_Sinus Sine;
} AT91S_RomBoot;

//AT91S_Pipe
typedef struct _AT91S_Pipe
{
// A pipe is linked with a peripheral and a buffer
AT91PS_SvcComm pSvcComm;
AT91PS_Buffer pBuffer;

// Callback functions with their arguments
void (*WriteCallback) (AT91S_PipeStatus, void *);
void (*ReadCallback) (AT91S_PipeStatus, void *);
void *pPrivateReadData;
void *pPrivateWriteData;

// Pipe methods
AT91S_PipeStatus (*Write) (
struct _AT91S_Pipe *pPipe,
char const * pData,
unsigned int size,
void (*callback) (AT91S_PipeStatus, void *),
void *privateData
);

AT91S_PipeStatus (*Read) (
struct _AT91S_Pipe *pPipe,
char *pData,
unsigned int size,
void (*callback) (AT91S_PipeStatus, void *),
void *privateData
);

AT91S_PipeStatus (*AbortWrite)(struct _AT91S_Pipe *pPipe);
AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);
AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);
AT91S_PipeStatus (*Reset)(struct _AT91S_Pipe *pPipe);
char (*IsWritten)(struct _AT91S_Pipe *pPipe, char const *pVoid);
char (*IsReceived) (struct _AT91S_Pipe *pPipe, char const *pVoid);
} AT91S_Pipe;

//AT91S_Buff
typedef struct _AT91S_SBuffer
{
AT91S_Buffer parent;
char *pRdBuffer;
char const *pWrBuffer;
unsigned int szRdBuffer;
unsigned int szWrBuffer;
unsigned int stRdBuffer;
unsigned int stWrBuffer;
} AT91S_SBuffer;

// AT91S_SvcTempo
typedef struct _AT91S_SvcTempo
{

// Methods:
AT91S_TempoStatus (*Start) (
struct _AT91S_SvcTempo *pSvc,
unsigned int timeout,
unsigned int reload,
void (*callback) (AT91S_TempoStatus, void *),
void *pData);
AT91S_TempoStatus (*Stop) (struct _AT91S_SvcTempo *pSvc);

struct _AT91S_SvcTempo *pPreviousTempo;
struct _AT91S_SvcTempo *pNextTempo;

// Data
unsigned int TickTempo; //* timeout value
unsigned int ReloadTempo;//* Reload value for periodic execution
void (*TempoCallback)(AT91S_TempoStatus, void *);
void *pPrivateData;
AT91E_SvcTempo flag;
} AT91S_SvcTempo;

// AT91S_CtrlTempo
typedef struct _AT91S_CtlTempo
{
// Members:

// Start and stop for Timer hardware
AT91S_TempoStatus (*CtlTempoStart) (void *pTimer);
AT91S_TempoStatus (*CtlTempoStop) (void *pTimer);

// Start and stop for Tempo service
AT91S_TempoStatus (*SvcTempoStart) (
struct _AT91S_SvcTempo *pSvc,
unsigned int timeout,
unsigned int reload,
void (*callback) (AT91S_TempoStatus, void *),
void *pData);
AT91S_TempoStatus (*SvcTempoStop) (struct _AT91S_SvcTempo *pSvc);
AT91S_TempoStatus (*CtlTempoSetTime)(struct _AT91S_CtlTempo *pCtrl, unsigned int NewTime);
AT91S_TempoStatus (*CtlTempoGetTime)(struct _AT91S_CtlTempo *pCtrl);
AT91S_TempoStatus (*CtlTempoIsStart)(struct _AT91S_CtlTempo *pCtrl);
AT91S_TempoStatus (*CtlTempoCreate) (struct _AT91S_CtlTempo *pCtrl,struct _AT91S_SvcTempo *pTempo);
AT91S_TempoStatus (*CtlTempoRemove) (struct _AT91S_CtlTempo *pCtrl,struct _AT91S_SvcTempo *pTempo);
AT91S_TempoStatus (*CtlTempoTick) (struct _AT91S_CtlTempo *pCtrl);

// Data:

void *pPrivateData; // Pointer to devived class
void const *pTimer; // hardware
AT91PS_SvcTempo pFirstTempo;
AT91PS_SvcTempo pNewTempo;
} AT91S_CtlTempo;


//以下代码是上面几个对象的使用范例,通过这样就可以完成Host端和Targe端之间的xmodem通讯,并可以下载代码了。

AT91S_RomBoot const *pAT91;
AT91S_SBuffer sXmBuffer;
AT91S_SvcXmodem svcXmodem;
AT91S_Pipe xmodemPipe;
AT91S_CtlTempo ctlTempo;

AT91PS_Buffer pXmBuffer;
AT91PS_SvcComm pSvcXmodem;
unsigned int SizeDownloaded;

/* Init of ROM services structure */
pAT91 = AT91C_ROM_BOOT_ADDRESS;//这里取得内部ROM服务的入口地址

/* Tempo Initialization */
pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));
ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));

/* Xmodem Initialization */
pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);
pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);
pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);
xmodemPipe.Read(&xmodemPipe, (char *)AT91C_UBOOT_BASE_ADDRESS, AT91C_UBOOT_MAXSIZE,
AT91F_XmodemProtocol, 0);
while(XmodemComplete !=1);


//上面部分主要针对at91rm9200片内启动时我们可以使用的片内接口服务介绍,玩H9200的朋友可以参考一下便知道缘由。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值