微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于S3C44B0芯片的uClinux内核引导过程分析

基于S3C44B0芯片的uClinux内核引导过程分析

时间:04-20 来源:互联网 点击:

前 言

随着计算机硬件技术的不断发展,功能强大、资源丰富的嵌入式芯片,成为研究人员开发专业应用领域产品的首选。三星公司生产的S3C44B0芯片,采用ARM7TDM I内核,具有功耗小、成本低的特点,是一款专门针对移动终端及PDA手持设备市场的产品。近几年,源码开放的L inux系统迅速发展,很快成为跨平台操作系统中的佼佼者,并且出现了专门针对嵌入式系统的产品———uClinux。在S3C44B0芯片上移植 uClinux操作系统,能够充分发挥该芯片系统资源丰富(相对单片机而言)的特点,开发出功能强大的应用产品。

嵌入式系统的启动引导程序与硬件严格相关,对编写人员的要求较高,而在移植uClinux后又大大增加了引导程序的复杂程度,因此这部分代码往往是各个嵌入式产品开发厂商严格保密的部分。下面将以一款市场上成熟的基于S3C44B0芯片的嵌入式开发板为蓝本,对引导uClinux内核的过程进行分析。

系统引导过程分析

嵌入式系统中uClinux内核的系统引导过程通常可以分为3个阶段,即boot阶段、系统初始化阶段和uClinux内核引导阶段。通常情况下boot阶段和系统初始化阶段的工作由一段被称为bootloader的代码完成,而内核引导则是由事先编译好了的uClinux可执行镜像来实现。

系统内存组织

由于嵌入式系统的硬件环境千差万别,即使选用同一种型号的嵌入式芯片,其外围设备也大不相同,特别是存储设备的组织,将直接关系到引导程序的实现。对于 S3C44B0芯片,其生产厂家规定在系统加电自举后,从0x00000000处开始执行(其他芯片如ARM9系列可以通过地址映射改变该地址) ,故此处通常安排的是Flash 地址空间,用于保存bootloader启动代码以及uClinux映象。对于S3C44B0 芯片, RAM 地址被固定在0x0c000000到0x0fffffff的64兆,开发人员可以根据自己的需要再组织RAM,如本开发板存储器地址安排如下:

此外,考虑到Flash运行速度的问题,通常采取的做法是将系统初始化阶段的代码和uClinux内核镜像拷贝到RAM中执行。下面将分3个阶段分析系统引导过程。

boot阶段

boot阶段的主要工作是设置系统中断向量、完成对CPU内部寄存器的初始化、系统RAM初始化、为运行C程序组织堆栈、拷贝初始化阶段代码到RAM、跳转到C程序入口。该阶段代码直接在Flash中运行,为提高执行效率采用汇编语言编写。

(1) 设置中断向量。设置S3C44B0芯片的8种系统中断的中断向量地址(包括复位中断、未定义指令中断、软件中断、指令预取异常中断、数据异常中断、地址异常中断、IRQ 中断和F IQ 中断) ,该地址空间从系统RAM的起始地址开始安排。通常情况下,在Flash的起始部分,存放的就是针对各中断向量地址的无条件跳转指令。

__entry :

B ResetHandler

/* for reset vector */

LDR PC, = 0x0c00000c

/* 0x0c00000: 未定义指令中断向量地址*/

……

/* 中间省略类似跳转*/

LDR PC, = 0x0c000024

/* 0x0c000024: F IQ中断向量地址*/

(2) CPU内部寄存器初始化。通过配置CPU运行于SVC模式(采用改变CPSC寄存器中CPU运行模式位的方式来实现) ,并设置相关寄存器,以实现对基本硬件的初始化工作,包括关闭中断、初始化CPU通用端口和设置CPU频率等。进入SVC模式汇编代码如下:

MRS a1, CPSR /* 保存当前状态寄存器值*/

BICa1, a1, #MODE_MASK /* 清除运行模式位*/

ORR a1, a1, #SUP_MODE/* 设置为超级用户模式*/

ORR a1, a1, #LOCKOUT /* 关闭F IQ和IRQ */

MSR CPSR_cxsf, a1 /* 保存到当前状态寄存器*/

(3) 系统RAM初始化。初始化系统RAM的主要目的是为下面使用RAM空间的操作做好准备工作,如进行代码拷贝及堆栈初始化等。这部分工作可以分为两个步骤。首先,根据系统配置的存储器特性,初始化相关存储块控制寄存器的值, 在S3C44B0 中存储空间被分为BANK0到BANK7共8个块,分别由BANKCON0到BANKCON7控制各块存储器的读写时钟数和片选时钟数等信号参数,对于采取不同存储芯片的嵌入式系统,可以通过查阅芯片手册来获取该信息,并写入相关寄存器。

LDR r0, = rBANKCON0

LDR r1, = 0x700

STR r1, [ r0 ]

/* 中间省略BANK1到BANK6*/

LDR r0, = rBANKCON7

LDR r1, = 0x18000

STR r1, [ r0 ]

LDR r0, = rREFRESH

LDR r1, = 0xac03e1

STR r1, [ r0 ]

LDR r0, = rBANKSIZE

LDR r1, = 0x16

STR r1, [ r0 ]

然后,对存储器空间中需要清零的区域进行清零操作,该区域的范围往往是由开发人员通知编译器的,主要是用来存放C语言中全局变量等。

LDR a1, = Image_ZI_Base /* 获取清零区域基地址*/

MOV a3, #0 /* 清零a3寄

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top