(第2版).

Slides:



Advertisements
Similar presentations
1 I/O 设备访问方式和类型. 2 Overview n The two main jobs of a computer: l I/O (Input/Output) l processing n The control of devices connneted to the computer is.
Advertisements

什么是SOPC: SOPC是英文System On a Programmable Chip的缩写,称为片上可编程系统。SOPC将传统的EDA技术、计算机系统、嵌入式系统、数字信号处理等融为一体,综合了各自的优势,且在结构上形成一块芯片。 为什么用SOPC:SOPC是现代电子技术和电子系统设计的发展趋势,建立了电子系统设计的新模式。用户利用SOPC开发平台,自行设计高速、高性能的DSP处理器、特定功能的CPU及其外围接口电路,创建结构最为简洁的电子系统。
课前回顾.
高等医药院校药学类第三轮规划教材——大学计算机基础
嵌入式控制系统 学时:45,1~12周,第13周闭卷考试 实验课:18学时,穿插在本课程间进行
Memory Pool ACM Yanqing Peng.
第一章 计算机基础知识 计算机的发展简史 1 计算机软件系统 6 计算机的定义和分类 2 微型计算机的组成 7 计算机的特点和用途 3
操作系统结构.
基于Android的开源平板电脑 (FSPAD723)系统构成分析
基于ARM和linux的开发 华中科技大学 武汉创维特 2017/3/20.
嵌入式操作系统 陈天洲、陈文智.
UClinux在3000平台上的移植.
计算机与信息技术应用基础 徐东雨 计算机中心
性能测试培训 在组设置中可使用此模板作为演示培训材料的起始文件。 节
《计算机操作员》精品 课件 淮南市潘集职教中心
第四章 BootLoader开发 附-s3c2410/s3c2440处理器介绍
單晶片MCS-51 C語言入門實習 第1章 微電腦與單晶片MCS-51架構 作者:董勝源.
Building Embedded Linux 2
第一章 嵌入式系统开发基础 本章介绍了嵌入式系统开发的基础知识,从嵌入式计算机的历史由来、嵌入式系统的定义、嵌入式系统的基本特点、嵌入式系统的分类及应用、嵌入式系统软硬件各部分组成、嵌入式系统的开发流程、嵌入式技术的发展趋势等方面进行了介绍,涉及到嵌入式系统开发的基本内容,使读者系统地建立起的嵌入式系统整体概念。
内核移植实例.
C H A P T E R 11 体系结构对操作系统的支持.
CPU資料處理 醫務管理暨醫療資訊學系 陳以德 副教授: 濟世CS 轉
ARM存储器结构 ARM架构的处理器的存储器寻址空间有4G字节 ,存储空间可以分为 :
淘宝核心系统数据库组 余锋 利用新硬件提升数据库性能 淘宝核心系统数据库组 余锋
C H A P T E R 10 存储器层次.
1-1 微電腦系統單元 1-2 微電腦系統架構 1-3 微控制器(單晶片微電腦) 1-4 類比與數位訊號介面
1-1 微電腦系統單元 1-2 微電腦系統架構 1-3 微控制器(單晶片微電腦) 1-4 類比與數位訊號介面
Bootloader技术分析.
YM100开发实验板 演讲人:熊小燕 2009年月12月16日
5 Computer Organization (計算機組織).
嵌入式系統架構 長高科技 顏旭偉.
作業系統 第八章 記憶體管理.
2018/11/ /11/23 TRAINING-LZW.
路由器的组成 路由器的前面板除了LED灯外没有其它东西,LED灯主要是指示电源是否开启。
第14章 Bootloader基本概念與燒錄.
嵌入式系统教案 武汉创维特信息技术有限公司 2018/11/27.
怎样从0开始写bootloader? 李明 北京亚嵌教育研究中心
CH.8 硬體管理.
模块五: 数控系统参数的备份与恢复 本章学习内容.
单片机应用技术 项目一 循环彩灯装置 第2讲 51单片机的结构与引脚 《单片机应用技术》精品课程组 湖北职业技术学院机电工程系.
在專用的嵌入式板子運行 GNU/Linux 系統已經變得越來越流行。一個嵌入式 Linux 系統從軟體的角度看通常可以分為四個層次:
u-boot环境变量和常用命令 广州创龙电子科技有限公司
嵌入式系统设计与实例开发 ——ARM与C/OS-Ⅱ 第六讲 基于ARM的嵌入式硬件结构设计.
電腦的硬體架構.
操作系统实验 lab1-系统引导
嵌入式系统的Boot Loader技术 陈文智 浙江大学计算机学院 2009年5月.
知识点:1、PLC系统起动前检查项目、 定期检查项目、日常维护 内容与步骤 2、掌握PLC诊断流程及故障 排除
第2章 ARM微处理器硬件结构 计算机体系结构分类 ARM版本及系列 ARM处理器结构 存储系统机制.
Ch9 Communicating with Hardware
嵌入式系统设计与实例开发 ——ARM与C/OS-Ⅱ 北京航空航天大学 智能嵌入式技术工作室 王田苗 魏洪兴.
内核移植基础.
(第2版).
组员:吴迪&王柳杨&金虎&陈武荣&谭金柏
Linux Debugging ls,ps,top,etc. printk() /proc i386提供的调试机制(断点,信号,单步执行)
Author:BobZhang Copy Right 2007
8051單晶片 蘇恆生 老師.
第2章ARM/THUMB微处理器结构及指令系统
靜宜大學專用 PowerPoint 檔案 數位教材
Chapter 7 掌控記憶體.
嵌入式Linux开发流程 成都研究所操作系统团队.
ARM Developer Suite 介 绍.
RFID應用 紅綠燈自動轉換 基本系統 成果發表(實作)
四川工商学院 单片机原理及应用 刘 强
第七章 半导体存储器.
Chapter 7 掌控記憶體.
第六章 記憶體.
ARM简介及BootLoader介绍 黄大荣
UART通信实验(二) McBSP软件模拟异步通信
第二章ADS1.2开发环境创建与简介.
FPPA 程式設計 這一章開始正式進入FPPA程式設計的世界,我會從一個簡單的程式開始解說,一邊介紹專案開發時最常應用的技巧還有程式控制的手段,一邊把系統規畫的概念導入給大家,讓大家對專案的規畫能有一個初步的概念。
Presentation transcript:

(第2版)

主讲内容 第8章 嵌入式系统Boot Loader技术 第9章 嵌入式Linux操作系统移植 第10章 嵌入式Linux设备驱动程序开发

Boot Loader的基本概念 8.1 BootLoader(vivi)的代码分析 8.2

8.1 Boot Loader的基本概念 Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。

8.1.1 Boot Loader的相关设备和机制 通常,Boot Loader 是严重地依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的 Boot Loader 几乎是不可能的。尽管如此,我们仍然可以对 Boot Loader 归纳出一些通用的概念来,以指导用户特定的 Boot Loader 设计与实现。 1. Boot Loader 所支持的 CPU 和嵌入式板 每种不同的 CPU 体系结构都有不同的 Boot Loader。有些 Boot Loader 也支持多种体系结构的 CPU,比如 U-Boot 就同时支持 ARM 体系结构和MIPS(Million Instructions Per Second)体系结构。除了依赖于 CPU 的体系结构外,Boot Loader 实际上也依赖于具体的嵌入式板级设备的配置。这也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种 CPU 而构建的,要想让运行在一块板子上的 Boot Loader 程序也能运行在另一块板子上,通常也都需要修改 Boot Loader 的源程序。 2. Boot Loader 的安装媒介(Installation Medium) 系统加电或复位后,所有的 CPU 通常都从某个由 CPU 制造商预先安排的地址上取指令。比如,基于 ARM7TDMI core 的 CPU 在复位时通常都从地址 0x00000000 取它的第一条指令。而基于 CPU 构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROM、EEPROM 或 FLASH 等)被映射到这个预先安排的地址上。因此在系统加电后,CPU 将首先执行 Boot Loader 程序。

3. 用来控制 Boot Loader 的设备或机制 主机和目标机之间一般通过串口建立连接,Boot Loader 软件在执行时通常会通过串口来进行 I/O,比如:输出打印信息到串口,从串口读取用户控制字符等。 4. Boot Loader 的启动过程是单阶段(Single Stage)还是多阶段(Multi-Stage) 通常多阶段的 Boot Loader 能提供更为复杂的功能,以及更好的可移植性。从固态存储设备上启动的 Boot Loader 大多都是 2 阶段的启动过程,也即启动过程可以分为 stage 1 和 stage 2 两部分。而至于在 stage 1 和 stage 2 具体完成哪些任务将在下面讨论。 5. Boot Loader 的操作模式 (Operation Mode) 大多数 Boot Loader 都包含两种不同的操作模式:"启动加载"模式和"下载"模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看,Boot Loader 的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。 6. BootLoader 与主机之间进行文件传输所用的通信设备及协议 最常见的情况就是,目标机上的 Boot Loader 通过串口与主机之间进行文件传输,传输协议通常是 xmodem/ymodem/zmodem 协议中的一种。但是,串口传输的速度是有限的,因此通过以太网连接并借助 TFTP 协议来下载文件是个更好的选择。

8.1.2 Boot Loader的启动过程 在专用的嵌入式板子运行 GNU/Linux 系统已经变得越来越流行。一个嵌入式 Linux 系统从软件的角度看通常可以分为四个层次: 1. 引导加载程序。包括固化在固件(firmware)中的 boot 代码(可选),和 Boot Loader 两大部分。 2. Linux 内核。特定于嵌入式板子的定制内核以及内核的启动参数。 3. 文件系统。包括根文件系统和建立于 Flash 内存设备之上文件系统。通常用 ram disk 来作为 root fs。 4. 用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。常用的嵌入式 GUI 有:MicroWindows 和 MiniGUI 等。

8.1.3 Boot Loader的操作模式 大多数 Boot Loader 都包含两种不同的操作模式:"启动加载"模式和"下载"模式, 启动加载(Boot loading)模式:这种模式也称为"自主"(Autonomous)模式。也即 Boot Loader 从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入。这种模式是 Boot Loader 的正常工作模式,因此在嵌入式产品发布的时侯,Boot Loader 显然必须工作在这种模式下。 下载(Downloading)模式:在这种模式下,目标机上的 Boot Loader 将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 Boot Loader 保存到目标机的 RAM 中,然后再被 Boot Loader 写到目标机上的FLASH 类固态存储设备中。Boot Loader 的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 Boot Loader 的这种工作模式。工作于这种模式下的 Boot Loader 通常都会向它的终端用户提供一个简单的命令行接口。

8.1.4 Boot Loader的总体设计 嵌入式系统中内核映像与根文件系统映像也可以直接在 ROM 或 Flash 这样的固态存储设备中直接运行。但这种做法无疑是以运行速度的牺牲为代价的。 从操作系统的角度看,Boot Loader 的总目标就是正确地调用内核来执行。 另外,由于 Boot Loader 的实现依赖于 CPU 的体系结构,因此大多数 Boot Loader 都分为 stage1 和 stage2 两大部分。依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在 stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而 stage2 则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。

Boot Loader 的 stage1 通常包括以下步骤(以执行的先后顺序): 硬件设备初始化。 为加载 Boot Loader 的 stage2 准备 RAM 空间。 拷贝 Boot Loader 的 stage2 到 RAM 空间中。 设置好堆栈。 跳转到 stage2 的 C 入口点。 Boot Loader 的 stage2 通常包括以下步骤(以执行的先后顺序): 初始化本阶段要使用到的硬件设备。 检测系统内存映射(memory map)。 将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中。 为内核设置启动参数。 调用内核。

Stage1: 1、 基本的硬件初始化 这是 Boot Loader 一开始就执行的操作,其目的是为 stage2 的执行以及随后的 kernel 的执行准备好一些基本的硬件环境。它通常包括以下步骤(以执行的先后顺序): (1) 屏蔽所有的中断。 (2)设置 CPU 的速度和时钟频率。 (3) RAM 初始化。 (4) 初始化 LED。 (5) 关闭 CPU 内部指令/数据 cache。

2.为加载 stage2 准备 RAM 空间 先保存 memory page 一开始两个字的内容。 向这两个字中写入任意的数字。比如:向第一个字写入 0x55,第 2 个字写入 0xaa。 然后,立即将这两个字的内容读回。显然,我们读到的内容应该分别是 0x55 和 0xaa。如果不是,则说明这个 memory page 所占据的地址范围不是一段有效的 RAM 空间。 再向这两个字中写入任意的数字。比如:向第一个字写入 0xaa,第 2 个字中写入 0x55。 然后,立即将这两个字的内容立即读回。显然,我们读到的内容应该分别是 0xaa 和 0x55。如果不是,则说明这个 memory page 所占据的地址范围不是一段有效的 RAM 空间。 恢复这两个字的原始内容。测试完毕。

3、 拷贝 stage2 到 RAM 中 拷贝时要确定两点: 一、 stage2 的可执行映象在固态存储设备的存放起始地址和终止地址; 二、RAM 空间的起始地址。 4、 设置堆栈指针 sp 堆栈指针的设置是为了执行 C 语言代码作好准备。通常我们可以把 sp 的值设置为(stage2_end-4) 此外,在设置堆栈指针 sp 之前,也可以关闭 led 灯,以提示用户我们准备跳转到 stage2。 经过上述这些执行步骤后,系统的物理内存布局应该如下图8-2所示。

5、跳转到 stage2 的 C 入口点 在上述一切都就绪后,就可以跳转到 Boot Loader 的 stage2 去执行了。比如,在 ARM 系统中,这可以通过修改 PC 寄存器为合适的地址来实现。

Stage2: 1、初始化本阶段要使用到的硬件设备 这通常包括: (1)初始化至少一个串口,以便和终端用户进行 I/O 输出信息; (2)初始化计时器等。 在初始化这些设备之前,也可以重新把 LED 灯点亮,以表明我们已经进入 main() 函数执行。 设备初始化完成后,可以输出一些打印信息,程序名字字符串、版本号等。

2、 检测系统的内存映射(memory map) (1) 内存映射的描述 可以用如下数据结构来描述 RAM 地址空间中的一段连续(continuous)的地址范围: typedef struct memory_area_struct { u32 start; /* the base address of the memory region */ u32 size; /* the byte number of the memory region */ int used; } memory_area_t;

(2) 内存映射的检测 for(i = 0; i < NUM_MEM_AREAS; i++) memory_map[i].used = 0; for(addr = MEM_START; addr < MEM_END; addr += PAGE_SIZE) * (u32 *)addr = 0; for(i = 0, addr = MEM_START; addr < MEM_END; addr += PAGE_SIZE) { if ( current memory page isnot a valid ram page) { if(memory_map[i].used ) i++; continue; } if(* (u32 *)addr != 0) { if ( memory_map[i].used ) if (memory_map[i].used == 0) { memory_map[i].start = addr; memory_map[i].size = PAGE_SIZE; memory_map[i].used = 1; } else { memory_map[i].size += PAGE_SIZE;

3、 加载内核映像和根文件系统映像 (1) 规划内存占用的布局 这里包括两个方面: 内核映像所占用的内存范围; 根文件系统所占用的内存范围。 (2)从 Flash 上拷贝 由于像 ARM 这样的嵌入式 CPU 通常都是在统一的内存地址空间中寻址 Flash 等固态存储设备的,因此从 Flash 上读取数据与从 RAM 单元中读取数据并没有什么不同。用一个简单的循环就可以完成从 Flash 设备上拷贝映像的工作: while(count) { *dest++ = *src++; count -= 4; };

4、设置内核的启动参数 Linux 2.4.x 以后的内核都期望以标记列表(tagged list)的形式来传递启动参数。启动参数标记列表以标记 ATAG_CORE 开始,以标记 ATAG_NONE 结束。每个标记由标识被传递参数的 tag_header 结构以及随后的参数值数据结构来组成。数据结构 tag 和 tag_header 定义在 Linux 内核源码的include/asm/setup.h 头文件中:

5、 调用内核 Boot Loader 调用 Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到 MEM_START+0x8000 地址处。在跳转时,下列条件要满足: (1) CPU 寄存器的设置: R0=0; R1=机器类型 ID;关于 Machine Type Number,可以参见 linux/arch/arm/tools/mach-types。 R2=启动参数标记列表在 RAM 中起始基地址; (2) CPU 模式: 必须禁止中断(IRQs和FIQs); CPU 必须 SVC 模式; (3) Cache 和 MMU 的设置: MMU 必须关闭; 指令 Cache 可以打开也可以关闭; 数据 Cache 必须关闭;

8.2 BootLoader(vivi)的代码分析 Bootloader有很多种,如本文将要阅读的vivi,除此之外还有uboot,redboot,lilo等等。Vivi 是韩国mizi公司专门为三星s3c2440芯片设计的Bootloader。 vivi也可以分为2个阶段,阶段1的代码在arch/s3c2440/head.S中,阶段2的代码从init/main.c的main函数开始。

阶段1 1. 关WATCH DOG (disable watch dog timer) 上电后,WATCH DOG默认是开着的 2 阶段1 1.关WATCH DOG (disable watch dog timer) 上电后,WATCH DOG默认是开着的 2.禁止所有中断 (disable all interrupts) vivi中不会用到中断,中断是系统的事,bootloader可不能去干这事的(不过这段代码实在多余,上电后中断默认是关闭的) 3.初始化系统时钟启动MPLL,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz,“CPU bus mode”改为“Asynchronous bus mode”。 4.初始化内存控制寄存器(memsetup):S3c2440共有15个寄存器,在此开始初始化13个寄存器。 5.检查是否从掉电模式唤醒(Check if this is a wake-up from sleep)若是,则调用WakeupStart函数进行处理。 6.点亮所有LED (All LED on)点一下灯,通知外面的同志,告诉他们有情况发生。

7.初始化UART0 (set GPIO for UART & InitUART) (1)设置GPIO,选择UART0使用的引脚 (2)初始化UART0,设置工作方式(使用FIFO)、波特率115200 8N1、无流控等。这可是使用串口与s3c2440通信的条件啊,在终端也要如此设置。 8.跳到内存测试函数 9.如果定义了以Nand flash方式启动,则此时要将vivi所有代码(包括阶段1和阶段2)从Nand flash复制到SDRAM中 (1)设置nand flash控制寄存器 (2)设置堆栈指针 (3)设置即将调用的函数nand_read_ll的参数 (4)调用nand_read_ll进行复制 10.跳到bootloader的阶段2运行,亦即调用init/main.c中的main函数(get read to call C functions) (1)重新设置堆栈 (2)设置main函数的参数 (3)调用main函数

阶段2 从init/main.c中的main函数开始,终于步入C语言的世界了。Main函数总共有5步 1、Step 1:reset_handler() 2、Step 2:board_init() board_init调用2个函数用于初始化定时器和设置各GPIO引脚功能 3、Step 3:建立页表和启动MMU mem_map_init函数用于建立页表 mmu_init()函数用于启动MMU 4、Step 4:heap_init() 第4步调用了heap_init(void)函数,并返回值。该值是函数heap_init()调用的mmalloc_init()函数的返回值。其实,这步就是申请一块内存区域。

5、Step 5:mtd_dev_init() 在linux系统中,我们通常会用到不同的存储设备,特别是FLASH设备。为了在使用新的存储设备时,我们能更简便地提供它的驱动程序,在上层应用和硬件驱动的中间,抽象出MTD设备层。驱动层不必关心存储的数据格式如何,比如是FAT32、ETX2还是FFS2或其它。它仅仅提供一些简单的接口,比如读写、擦除及查询。如何组织数据,则是上层应用的事情。MTD层将驱动层提供的函数封装起来,向上层提供统一的接口。这样,上层即可专注于文件系统的实现,而不必关心存储设备的具体操作。