第5章old嵌入式系统.ppt_第1页
第5章old嵌入式系统.ppt_第2页
第5章old嵌入式系统.ppt_第3页
第5章old嵌入式系统.ppt_第4页
第5章old嵌入式系统.ppt_第5页
已阅读5页,还剩108页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章Bootloader开发基础 1 3 2 4 Bootloader的概念 功能与特点 Bootloader的一般过程 常用嵌入式Linux的Bootloader U boot简要分析 章节内容 什么是Bootloader Boot LoadBoot 启动 上电 Load 加载 系统 引导加载程序 Bootloader 是系统加电后运行的第一段软件代码 Bootloader是与系统硬件环境高度相关的初始化软件 它担负着初始化硬件和引导操作系统的双重责任 对了解嵌入式系统底层运行机制 优化和快速启动的研究都有重要的意义 用户 嵌入式Linux软件开发层次 硬件 Bootloader 内核 文件系统 应用程序 Bootloader的实例 智能手机iOS越狱Android刷rom rootPC机 PC机中的引导加载程序 两部分组成BIOS 其本质就是一段固件程序 位于硬盘MBR中的OSBootLoader 如LILO和GRUB等 流程BIOS在完成硬件检测和资源分配后 将硬盘MBR中的BootLoader读到系统的RAM中 然后将控制权交给OSBootLoaderOSBootLoader的主要运行任务就是将内核映象从硬盘上读到RAM中 然后跳转到内核的入口点去运行 即开始启动操作系统 嵌入式系统中引导加载程序 系统的加载启动任务完全由Bootloader来完成流程加电启动Bootloader 硬件初始化 加载内核 比如在一个基于ARM7TDMI的嵌入式系统中 系统在上电或复位时通常都从地址0 x00000000处开始执行 而在这个地址处安排的通常就是系统的Bootloader程序 BootLoader的概念 在操作系统内核运行之前运行的一段小程序功能初始化硬件设备建立内存空间的映射图调整系统的软硬件环境 以便操作系统内核启动不通用依赖于硬件CPU依赖于主板board不同的CPU有不同的BootLoader有些BootLoader支持多CPU 如U Boot等 BootLoader的安装媒介 系统加电或复位后 所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令 比如 基于ARM7TDMI的CPU在复位时通常都从地址0 x00000000取它的第一条指令 基于CPU构建的嵌入式系统通常都有某种类型的固态存储设备被映射到这个预先安排的地址上 比如 ROM EEPROM或FLASH等 因此在系统加电后 CPU将首先执行Bootloader程序 固态存储设备的典型空间分配结构 Bootloader一般通过jtag烧写 其余部分可以通过Bootloader烧写 控制BootLoader的设备或机制 主机和目标机之间一般通过串口建立连接BootLoader软件在执行时通常会通过串口来进行I O 比如输出打印信息到串口从串口读取用户控制字符等 最常用的串口通信软件Linux minicomWindows 附件中的超级终端 BootLoader的启动过程 BootLoader的启动过程可以是单阶段 SingleStage 或一些只需完成很简单功能的bootloader可能是单阶段的多阶段 Multi Stage 通常多阶段的BootLoader能提供更为复杂的功能 以及更好的可移植性从固态存储设备上启动的BootLoader大多都是2阶段的启动过程 也即启动过程可以分为stage1和stage2两部分 BootLoader的操作模式 大多数BootLoader包含两种不同的操作模式启动加载 Bootloading 模式和下载 Downloading 模式这种区别仅对于开发人员才有意义从最终用户的角度看 BootLoader的作用就是加载操作系统 并不存在上述两种模式的区别 启动加载模式 也称为自主 Autonomous 模式BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行 整个过程并没有用户的介入 这种模式是BootLoader的正常工作模式在嵌入式产品发布时 BootLoader必须工作在该模式下 下载模式 目标机的BootLoader通过串口或网络等通信手段从主机 Host 下载文件比如内核映像和根文件系统映像Host targetram targetFLASH该模式的使用时机通常在第一次安装内核与根文件系统时被使用也用于此后的系统更新工作于该模式下的BootLoader通常都会向它的终端用户提供一个简单的命令行接口 BootLoader的操作模式 一些功能强大的BootLoader通常同时支持这两种工作模式如Blob和U Boot允许用户在这两种工作模式之间进行切换比如 Blob在启动时处于正常的启动加载模式 但是它会延时10秒等待终端用户按下任意键而将blob切换到下载模式 如果在10秒内没有用户按键 则blob继续启动Linux内核 与bootloader两种模式相关的问题 uClinux包编译好后 可根据需要编译出各种镜像文件也就是按照板子内存预定位置生成的二进制映象 一般是内核和文件系统的复合体常见有image ram 常称为ram版内核 和image rom 常称为rom版内核 通过在make时指定的不同编译选项生成 ram版内核 一般不压缩 通过bootloader加载到目标板内存的指定位置 然后可用bootloader跳转过去就把uclinux引导启动了bootloader ram版内核内核 驱动相关调试期间常用方式 rom版内核 不严格的理解可以说是把bootloader ram版烧写到flash内上电或reset后首先执行bootloader初始化硬件功能 然后把压缩的内核映象解压释放到sdram指定地址 接着自动引导内核 启动uclinux调试应用软件常用rom版镜像 BootLoader与主机之间的通信 最常见通信设备是串口传输协议通常是xmodem ymodem zmodem之一 但串口传输的速度有限更好的选择是以太网使用TFTP协议主机方必须有一个软件提供TFTP服务 BootLoader的主要任务 系统假设 内核映像与根文件系统映像都被加载到RAM中运行 尽管在嵌入式系统中它们也可直接运行在ROM或Flash这样的固态存储设备中 但这种做法无疑是以运行速度的牺牲为代价的 从操作系统的角度看 BootLoader的总目标就是正确地调用内核来执行 1 3 2 4 Bootloader的概念 功能与特点 Bootloader的一般过程 常用嵌入式Linux的Bootloader U boot简要分析 章节内容 BootLoader的典型结构框架 由于BootLoader的实现依赖于CPU体系结构 大多数BootLoader都分为stage1和stage2两大部分Stage1依赖于CPU体系结构 如设备初始化代码通常用汇编语言实现 短小精悍Stage2通常用C语言可以实现复杂功能代码具有较好的可读性和可移植性 BootLoader的stage1 Stage1直接运行在固态存储设备上 通常包括以下步骤硬件设备初始化为加载BootLoader的stage2准备RAM空间拷贝BootLoader的stage2到RAM空间中设置好堆栈跳转到stage2的C入口点 Stage1 硬件初始化 这是BootLoader一开始就执行的操作目的 为stage2及kernel的执行准备好基本硬件环境通常包括屏蔽所有的中断为中断提供服务通常是OS或设备驱动程序的责任 在BootLoader阶段不必响应任何中断中断屏蔽可以通过写CPU的中断屏蔽寄存器或状态寄存器来完成比如ARM的CPSR寄存器 Stage1 硬件初始化 cont d 设置CPU的速度和时钟频率RAM初始化包括正确地设置系统中内存控制器的功能寄存器以及各CPU外的内存 MemoryBank 的控制寄存器等 初始化LED典型地 通过GPIO来驱动LED 其目的是表明系统的状态是OK还是Error 若板子上无LED 也可通过初始化UART向串口打印BootLoader的Logo字符信息来完成这一点 关闭CPU内部指令 数据cache Stage1 为stage2准备RAM空间 为获得更快的执行速度 通常stage2被加载到RAM中执行因此必须为加载stage2准备好一段可用的RAM空间空间大小 应考虑stage2可执行映象的大小 堆栈空间因为stage2通常是C语言代码此外 最好对齐到memorypage大小 通常是4KB 一般而言1MB已足够 Stage1 为stage2准备RAM空间 具体的地址范围可以任意安排比如blob将它的stage2可执行映像安排系统的RAM中0 xc0200000开始的1M空间内值得推荐的是可以将stage2安排到整个RAM空间的最顶1MB也即 RamEnd 1MB 开始处假设空间大小 stage2 size 字节 起始和终止地址分别为 stage2 start和stage2 end 均与4字节对齐 则有 stage2 end stage2 start stage2 size Stage1 为stage2准备RAM空间 必须确保所安排的地址范围的确为可读写的RAM空间 即必须进行有效性测试Blob的内存有效性测试方法 记为test mempage 以内存页为被测单位 测试每个页面头两个字是否可读写 test mempage 1 保存被测页面头两个字的内容 2 向这两个字中写入任意的数字 比如 向第一个字写入0 x55 第2个字写入0 xaa 3 立即将这两个字的内容读回 应当与写入的内容一致 否则此页面地址范围不是一段有效的RAM空间4 再次向这两个字中写入任意的数字 比如 向第一个字写入0 xaa 第2个字中写入0 x55 5 立即将这两个字的内容读回 判断依据同36 恢复这两个字的原始内容 Stage1 为stage2准备RAM空间 测试结束后 为了得到一段干净的RAM空间范围 可以将所安排的RAM空间范围进行清零操作 Stage1 拷贝stage2到RAM中 拷贝时要确定 Stage2的可执行映象在固态存储设备的存放起始地址和终止地址RAM空间的起始地址 Stage1 设置堆栈指针sp 对C语言编写的程序应当准备运行堆栈通常设置在上述1MBRAM空间的最顶端sp stage2 end 4 注 堆栈是向下生长的此外 在设置堆栈指针前 也可关闭led灯 以提示用户即将跳转到stage2 系统的物理内存布局 Stage1 跳转到stage2的C入口点 在上述一切都就绪后 就可以跳转到BootLoader的stage2去执行了 比如 在ARM系统中 这可以通过修改PC寄存器为合适的地址来实现 关于C入口点的疑惑 stage2的代码通常用C语言来实现 以便于实现更复杂的功能和取得更好的代码可读性和可移植性 但是与普通C语言应用程序不同的是 在编译和链接bootloader这样的程序时 不能使用glibc库中的任何支持函数 那么从哪里跳转进main 函数呢 直接使用main函数的起始地址 最直接的想法就是直接把main 函数的起始地址作为整个stage2执行映像的入口点 无法通过main 函数传递函数参数 无法处理main 函数返回的情况 trampoline 弹簧床 的概念 一种更为巧妙的方法是利用trampoline 弹簧床 的概念 用汇编语言写一段trampoline小程序 并将它来作为stage2可执行映象的执行入口点 在trampoline中用CPU跳转指令跳入main 函数中去执行 当main 函数返回时 CPU执行路径显然再次回到trampoline程序 简而言之 用这段trampoline小程序作为main 函数的外部包裹 externalwrapper 一个简单的trampoline程序示例 blob text globl trampoline trampoline blmain ifmaineverreturnswejustcallitagain b trampoline 可以看出 当main 函数返回后 我们又用一条跳转指令重新执行trampoline程序 当然也就重新执行main 函数 这也就是trampoline 弹簧床 一词的意思所在 BootLoader的stage2 通常包括以下步骤初始化本阶段要使用到的硬件设备检测系统内存映射 memorymap 将kernel映像和根文件系统映像从flash上读到RAM空间中为内核设置启动参数调用内核 Stage2 初始化要用的硬件设备 这通常包括 初始化至少一个串口 以便和终端用户进行I O输出信息 初始化计时器等 在初始化这些设备之前 也可重新把LED灯点亮 以表明已进入main 函数执行设备初始化完成后 可以输出一些打印信息 程序名字字符串 版本号等 Stage2 检测系统内存映射 所谓内存映射就是指在整个4GB物理地址空间中有哪些地址范围被分配用来寻址系统的RAM单元 比如 SA 1100CPU中 从0 xC000 0000开始的512M被用作系统的RAM地址空间SamsungS3C44B0XCPU中 从0 x0c00 0000到0 x1000 0000间的64M被用作系统的RAM地址空间 CPU预留的地址空间VS 实际使用的地址空间 虽然CPU通常预留出一大段足够的地址空间给系统RAM 但是在搭建具体的嵌入式系统时却不一定会实现CPU预留的全部RAM地址空间 也即具体的嵌入式系统往往只把CPU预留的全部RAM地址空间中的一部分映射到RAM单元上 而让剩下的那部分预留RAM地址空间处于未使用状态 因此BootLoader的stage2必须在它想干点什么 比如 将存储在flash上的内核映像读到RAM空间中 之前检测整个系统的内存映射情况也即它必须知道CPU预留的全部RAM地址空间中的哪些被真正映射到RAM地址单元 哪些是处于 unused 状态的 内存映射的描述 如下数据结构用来描述RAM地址空间中的一段连续的地址范围 typestructmemory area struct u32start 内存区域的起始地址u32size 内存区域的大小 字节数 intused 内存区域的状态 memory area t used 0 11 这段地址范围已被实现 也即真正地被映射到RAM单元上0 这段地址范围并未被系统所实现 处于未使用状态 内存映射的描述 整个CPU预留的RAM地址空间可以用一个memory area t类型的数组来表示 如memory area tmemory map NUM MEM AREAS 0 NUM MEM AREAS start 0 size 0 used 0 表示检测内存映射之前的初始状态 内存映射检测算法 数组初始化 每个区域的used标志设为0将整个空间中所有页面的前32位 4个字节 写为0依次检测每个页面是否有效 使用test mempage算法 若当前页面无效若当前区域已映射 则当前区域检测结束若当前页面有效判断该页面是否由其他页面映射而来 若是同3 1否则若当前区域已映射 则增加有效页面到当前区域中若当前区域为一个新的区域 则初始化该区域并增加当前页面到当前区域中 在用上述算法检测完系统的内存映射情况后 BootLoader也可以将内存映射的详细信息打印到串口 Stage2 加载映像 规划内存占用的布局 包括内核映像所占用的内存范围 根文件系统所占用的内存范围 主要考虑基地址和映像的大小 例如 对内核映像 一般考虑从 MEM START 0 x8000 开始约1MB的内存范围内嵌入式Linux的内核一般都不操过1MB 为什么要把从MEM START到MEM START 0 x8000这段32KB大小的内存空出来呢 这是因为Linux内核要在这段内存中放置一些全局数据结构 如 启动参数和内核页表等信息 对根文件系统映像 一般从MEM START 0 x0010 0000开始 如果用Ramdisk作为根文件系统映像 则其解压后的大小一般是1MB 加载映像 从Flash上拷贝像ARM这样的嵌入式CPU通常都在统一的内存地址空间中寻址Flash等固态存储设备从Flash上读取数据与从RAM单元中读取数据并没有什么不同 用一个简单的循环就可完成从Flash设备上拷贝映像的工作 从Flash上拷贝 while count dest src theyareallalignedwithwordboundary count 4 bytenumber Stage2 设置内核的启动参数 在嵌入式Linux系统中 需要由boot loader设置的参数有 内核参数 如页面大小 根设备内存映射情况命令行参数initrd映像参数起始地址 大小Ramdisk参数解压后的大小 设置内核的启动参数 Linux2 4 x之后的内核都采用标记列表 taggedlist 的形式来传递启动参数启动参数标记列表以标记ATAG CORE开始 以标记ATAG NONE结束数据结构tag以及tag header在linux的源码Include asm setup h中定义 Setup h thelistendwithanATAG NONEnode defineATAG NONE0 x00000000Structtag header u32size size以字数为单位 u32tag Tag Structtag structtag headerhdr union structtag corecore structtag mem32mem structtag videotextvideotext structtag cmdlinecmdline 需要设置的tag 嵌入式Linux系统中 通常需要bootloader设置的常见启动参数有 ATAG CORE ATAG MEM ATAG CMDLINE ATAG RAMDISK ATAG INITRD Tag举例 ATAG RAMDISK示例Params structtag BOOT PARAMAS Params hdr tag ATAG RAMDISK Params hdr size tag size tag ramdisk Params u ramdisk start 0 Params u ramdisk size RAMDISK SIZE Params u ramdisk flags 1 Params tag next Params ATAG NONE示例Staticvoidsetup end tag void Params hdr tag ATAG NONE Params hdr size 0 Stage2 调用内核 调用方法 直接跳转到内核的第一条指令处 也即RAM中内核被加载的地址处对于ARMLinux系统 在跳转之前必须满足 CPU寄存器的设置 R0 0 R1 机器类型ID R2 传递给内核的启动参数起始地址 CPU模式 必须禁止中断 IRQs和FIQs CPU必须处于SVC模式 Cache和MMU的设置 MMU必须关闭 指令Cache可以打开也可以关闭 数据Cache必须关闭 BootLoader的工作到此为止 从此操作系统接管所有的工作 1 3 2 4 Bootloader的概念 功能与特点 Bootloader的一般过程 常用嵌入式Linux的Bootloader U boot简要分析 章节内容 开源的BootLoader ARMbootPPCBootu BootRedBootBlobViViOpenBIOSFreeBIOSLinuxBIOS 目前 ARMboot已经和PPCBoot合并到U Boot中 ARMboot ARMboot属于自由软件 是针对ARMCPU编写的通用BootLoader 其作用是对CPU以及主板进行初始化加载操作系统或者其他bootimage支持目前市面上的多种ARM板 也可以很容易的移植到新的开发板上目前ARMboot已经与PPCBoot合并 u boot支持PPC ARM等多种CPU ARMboot加载BootImage的方式 本地Flash设备JFFS2文件系统IDE设备网络串口传输在程序开发调试阶段 一般采用网络加载方式 可以极大地加快开发速度 下载并安装ARMboot Armboot源码公开 可以在 为了使用arm elf 打头的交叉编译命令 需要修改armboot 1 1 0 Makefile中的CROSS COMPILE变量的值arm linux 为arm elf 修改armbootinclude configs conifg ep7312 h 以ep7312开发板为例 配置armboot 支持ep7312开发板makeep7312 configBuildsudomakeall 生成的目标文件有三个 armboot ELF格式armboot bin 二进制映像文件格式armboot srec Motolola的一种格式此外在根目录的tftpboot目录下也有一个armboot bin备份 进入ARMboot命令界面 ARMboot的命令 u boot UniversalBoot uboot是在ppcboot以及armboot的基础上发展而来支持很多处理器 比如PowerPC ARM MIPS和x86 项目主页 源文件的修改 如果使用arm elf toolsMakefile中的CROSS COMPILE arm linux改为arm elf修改include configs ep7312 hcpu arm720t config mkinclude asm arm processor hmakeep7312 configsudomakeall 进入u boot的界面 RedBoot RedBootRedHatEmbeddedDebugandBootstrap的缩写 是RedHat公司的一个标准嵌入式系统引导和调试环境 Blob BlobBootLoaderObject的缩写 是一款功能强大的Bootloader 它遵循GPL 源代码完全开放 Blob最初是Jan DerkBakker和ErikMouw为一块名为LART LinuxAdvancedRadioTerminal 的板子写的 该板使用的处理器是StrongARMSA 1100 现在Blob已经被移植到了很多CPU上 ViVi ViVi是由韩国MIZI公司开发的专门用于ARM产品线的一种BootLoader VIVI目前只支持使用串口和主机通信 必须使用一条串口电缆来连接目标板和主机 ViVi的源代码下载地址为 1 3 2 4 Bootloader的概念 功能与特点 Bootloader的一般过程 常用嵌入式Linux的Bootloader U boot简要分析 章节内容 U boot介绍 UniversalBootloader opensource的bootloaderPPCbootarmboot支持多种处理器PPC ARM MIPS x86 m68k NIOS Microblaze支持多种开发板超过216种 几乎常见的开发板均在其中 U Boot设计原则 易于移植到其他架构 支持新型处理器以及新的开发板易于调试 通过串口输出可以容易调试特征和命令均可以重新配置尽可能保持小size尽可能保持可靠 用户接口 CLI simplecommandlineinterface通过串口执行命令Bournecompatibleshell HUSHshellfromBusybox 基本命令集 InformationCommandsbdinfo printBoardInfostructure coninfo printconsoledevicesandinformations flinfo printFLASHmemoryinformation iminfo printheaderinformationforapplicationimage imls listallimagesfoundinflash help printonlinehelp 基本命令集 MemoryCommandsbase printorsetaddressoffset crc32 checksumcalculation cmp memorycompare cp memorycopy md memorydisplay mm memorymodify auto incrementing mtest simpleRAMtest mw memorywrite fill nm memorymodify constantaddress loop infinitelooponaddressrange 基本命令集 FlashMemoryCommandscp memorycopy programflash flinfo printFLASHmemoryinformation erase eraseFLASHmemory protect enableordisableFLASHwriteprotection 基本命令集 ExecutionControlCommandsautoscr runscriptfrommemory bootm bootapplicationimagefrommemory bootelf BootfromanELFimageinmemory bootvx BootvxWorksfromanELFimage go startapplicationataddress addr 基本命令集 NetworkCommandsbootp bootimagevianetworkusingBOOTP TFTPprotocol cdp PerformCiscoDiscoveryProtocolnetworkconfiguration dhcp invokeDHCPclienttoobtainIP bootparams loadb loadbinaryfileoverserialline kermitmode loads loadS Recordfileoverserialline nfs bootimagevianetworkusingNFSprotocol ping sendICMPECHO REQUESTtonetworkhost rarpboot bootimagevianetworkusingRARP TFTPprotocol tftpboot bootimagevianetworkusingTFTPprotocol 高级命令集 LogbufferManipulationCommandsBedbugEmbeddedDebuggerCommandsPOST HardwareDiagnoseCommands u boot的体系结构 u boot的体系结构 u boot是一个层次式结构串口驱动 UARTDriver 以太网驱动 EthernetDriver Flash驱动 Flash驱动 USB驱动 USBDriver 内存分布 U BOOT内存分布 U Boot引导内核 U Boot引导内核启动时向内核传递了一个命令行 内核根据这个命令行的参数来对系统进行相应的设置 在linux核启动时 必须要挂载一个根文件系统 根文件系统可以通过网络文件系统和本地文件系统两种方式提供 在U Boot里面与此有关的设置是bootargs这个环境变量 通过NFS启动linux 利用NFS来向linux提供根文件系统主要是方便调试 大家可以把自己的文件系统先在主机上做好 利用NFS进行挂载 成功了之后再把它做成本地文件系统 设置如下 setenvbootargsroot dev nfsrwnfsroot ip 这里 root dev nfs 是告诉内核使用NFS来来挂载根文件系统 后面的 rw 表示挂载的根文件系统是可读可写的 后面的 nfsroot 指明了网络文件系统所在的主机和路径 下面的 ip 配置为内核的网络设置提供了参数 其中表示使用NFS需要用到的设备名称 表示内核自动配置的使用方法 关于这个命令行的详细用法大家可以参照linux Documentation nfsroot txt这个文件 下面以我的目标系统为例 setenvbootargsroot dev nfsrwnfsroot 10 22 9 99 opt eldk ppc 82xxip 10 22 9 98 10 22 9 99 10 22 9 99 255 255 255 0 aubrey eth1 off 通过本地文件系统启动linux 当前所有的FLASH文件系统都是基于MTD MemoryTechnologyDevice 层的 通过MTD来向linux提供文件系统的 设置bootargs参数如下 setenvbootargsroot dev mtdblock1rwip 10 22 9 98 10 22 9 99 10 22 9 99 255 255 255 0 aubrey eth1 off这里MTD会提供两种类型的设备 dev mtd0表示字符型设备 直接的读写和擦除需要使用这种设备接口 而与文件系统相关的操作例如mount我们就必须用 dev mtdblock0这种块设备接口 常用U BOOT命令 help COMMAND 打印命令的详细说明BOOT helptftpsetenvNAMEVALUE设置环境变量BOOT setenvipaddr192 168 2 120printenv NAME 打印环境变量的值BOOT printenvipaddrsaveenv把环境变量保存到flash中BOOT saveenvloadb ADDRBAUDRATE 串口下载BOOT loadb0 x1000115200tftpADDRFILENAME以太网下载BOOT tftp0 x1000linux bin goADDR从某地址运行程序BOOT go0 x1000flDESTSRCLENGTH烧写FLASHBOOT fl0 x200000000 x100000000 x20000md b w l ADDR显示内存数据BOOT md0 x1000bootelf ADDR 从某地址运行elf格式的程序BOOT bootelf0 x1000 编译U Boot 编译命令 root localhost cdu boot 1 0 2 root localhost makedistclean root localhost make config root localhost make编译结果u boot inELFformatu boot bin arawbinaryimageu boot srec inMotorolasrecformat Start S 在U boot众多文件中 最重要莫过于start S文件U boot源码中不止一个start s文件 实际上每种被u boot支持的CPU都会在它相应的文件夹中找到它自己的start s文件start S是U boot程序的开始点 CPU启动后需要执行的第一条命令就是该文件的开始start S被放在flash中cpu加电或复位的起始处 作为系统的第一条执行的指令 start S代码结构 1 定义入口一个可执行的Image必须有一个入口点并且只能有一个唯一的全局入口 通常这个入口放在Rom flash 的0 x0地址 例如start S中的 globl start start 这个工作主要是修改连接器脚本文件 lds 链接脚本文件 程序由各个段组成 连接脚本文件是告诉连接器从什么地址开始放置这些段 那为什么我们在PC上编程是没有写过链接脚本语言呢 gcc等编译器内置有缺省的连接脚本 如果采用缺省脚本 则生成的目标代码需要操作系统才能加载运行 为了能在嵌入式系统上直接运行 需要编写自己的连接脚本文件 链接脚本文件 GNU编译器生成的目标文件缺省为elf格式 elf文件由若干段 section 组成 如不特殊指明 由C源程序生成的目标代码中包含如下段 text 正文段 包含程序的指令代码 RO da

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论