UBOOT详细解读

合集下载

uboot代码完全解析

uboot代码完全解析
1.相关文件 ....................................................................................................................................28 2.数据结构 ....................................................................................................................................28 3.ENV 的初始化...........................................................................................................................30
目录
u-boot-1.1.6 之 cpu/arm920t........................................................................2 u-boot 中.lds 连接脚本文件的分析 ...................................................................................................12 分享一篇我总结的 uboot 学习笔记(转) .....................................................................................15 U-BOOT 内存布局及启动过程浅析 ...................................................................................................22 u-boot 中的命令实现 ..........................................................................................................................25 U-BOOT 环境变量实现 ........................................................................................................................28

刷入uboot和大分区的方法

刷入uboot和大分区的方法

刷入uboot和大分区的方法一、概念解释1.1 uboot是什么U-boot是一种开源的引导加载程序,它通常用于嵌入式系统的启动过程中,负责引导操作系统的启动和初始化硬件设备。

在嵌入式系统中,uboot扮演着非常重要的角色,它的稳定性和可靠性直接影响整个系统的稳定性。

1.2 分区的作用分区是将存储设备按照一定的规则划分成多个逻辑部分的过程。

对于嵌入式系统而言,合理的分区管理可以提高存储设备的利用率,同时也方便系统的管理和维护。

二、刷入uboot的步骤2.1 确定目标设备我们需要明确要刷入uboot的目标设备是什么,是一个嵌入式开发板还是其他类型的设备。

不同的设备可能需要不同的uboot版本和刷入方法。

2.2 获取uboot源码接下来,我们需要从冠方或者其他可靠渠道获取uboot的源码。

一般来说,冠方的源码是最稳定和可靠的选择,我们可以从冠方的仓库或者全球信息站上下载源码。

2.3 编译uboot获取源码之后,我们需要根据目标设备的硬件配置,对源码进行编译。

在编译之前,我们需要配置好交叉编译工具链和相关的环境变量,确保编译过程顺利进行。

2.4 刷入uboot当uboot源码编译完成之后,我们需要将编译生成的二进制文件刷入目标设备的存储设备中。

这个过程可能涉及到串口或者其他调试工具的使用,需要特别注意刷入过程中的各项参数和配置。

2.5 测试uboot刷入完成后,我们需要对uboot进行测试,确保它能够正常启动,并且能够正确识别硬件设备。

三、创建大分区的步骤3.1 确定分区方案在创建大分区之前,我们需要确定硬盘或者TF卡的分区方案,包括分区的数量、大小和格式等。

3.2 使用分区工具常用的分区工具有fdisk、parted等,我们可以使用这些工具来创建和调整分区。

在使用分区工具时,需要特别注意当前存储设备上是否有重要的数据,避免误操作导致数据丢失。

3.3 格式化分区创建完分区之后,我们需要对分区进行格式化,以便后续的数据存储和管理。

UBOOT源码分析

UBOOT源码分析

UBOOT源码分析UBOOT是一种开放源码的引导加载程序。

作为嵌入式系统启动的第一阶段,它负责初始化硬件设备、设置系统环境变量、加载内核镜像以及跳转到内核开始执行。

Uboot的源码是开放的,让我们可以深入了解其内部工作机制和自定义一些功能。

Uboot源码的文件组织结构非常清晰,主要分为三个大类:目录、文件和配置。

其中目录包含了一系列相关的文件,文件存放具体的源码实现代码,配置文件包含了针对特定硬件平台的配置选项。

Uboot源码的核心部分是启动代码,位于arch目录下的CPU架构相关目录中。

不同的CPU架构拥有不同的启动代码实现,如arm、x86等。

这些启动代码主要包括以下几个关键功能:1. 初始化硬件设备:Uboot首先需要初始化硬件设备,例如设置时钟、中断控制器、串口等设备。

这些初始化操作是在启动代码中完成的。

通过查看该部分代码,我们可以了解硬件的初始化过程,以及如何配置相关寄存器。

2. 设置启动参数:Uboot启动参数存储在一个称为"bd_info"的数据结构中,它包含了一些关键的设备和内存信息,例如DRAM大小、Flash 大小等。

这些参数是在启动代码中设置的,以便内核启动时能够正确识别硬件情况。

3. 加载内核镜像:Uboot负责加载内核镜像到内存中,以便内核可以正确执行。

在启动代码中,会通过读取Flash设备或者网络等方式,将内核镜像加载到指定的内存地址处。

加载过程中,可能会进行一些校验和修正操作,以确保内核数据的完整性。

4. 启动内核:在内核镜像加载完成后,Uboot会设置一些寄存器的值,并执行一个汇编指令,跳转到内核开始执行。

此时,Uboot的使命即结束,控制权交由内核处理。

除了启动代码,Uboot源码中还包含了许多其他功能模块,如命令行解析器、存储设备驱动、网络协议栈等。

这些功能模块可以根据需求进行配置和编译,以满足不同平台的需求。

例如,可以通过配置文件选择启用一些功能模块,或者自定义一些新的功能。

2440超详细U-BOOT(UBoot介绍+H-jtag使用+Uboot使用)

2440超详细U-BOOT(UBoot介绍+H-jtag使用+Uboot使用)

凌FL2440超详细U-BOOT作业(UBoot介绍+H-jtag使用+Uboot使用)Bootloader是高端嵌入式系统开发不可或缺的部分。

它是在操作系统内核启动之前运行的一段小程序。

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

现在主流的bootloader有U-BOOT、vivi、Eboot等。

本次作业先做Uboot的烧写吧。

希望通过这个帖子,能让更多的初学者朋友了解一些UBoot的知识,也希望高手朋友对我的不足予以斧正。

首先说一下什么是Uboot:U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目。

从FAD SROM、8xxROM、PPCBOOT逐步发展演化而来。

其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。

但是U-Boot不仅仅支持嵌入式Linu x系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。

其目前要支持的目标操作系统是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS。

这是U-Boot中Universal的一层含义,另外一层含义则是U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、x86、ARM、NIOS、XScale等诸多常用系列的处理器。

这两个特点正是U-Boot项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入式操作系统。

uboot启动流程分析

uboot启动流程分析

uboot启动流程分析Uboot启动流程分析。

Uboot是一种常用的嵌入式系统启动加载程序,它的启动流程对于嵌入式系统的正常运行至关重要。

本文将对Uboot启动流程进行分析,以便更好地理解其工作原理。

首先,Uboot的启动流程可以分为以下几个步骤,Reset、初始化、设备初始化、加载内核。

接下来我们将逐一进行详细的分析。

Reset阶段是整个启动流程的起点,当系统上电或者复位时,CPU会跳转到Uboot的入口地址开始执行。

在这个阶段,Uboot会进行一些基本的硬件初始化工作,包括设置栈指针、初始化CPU寄存器等。

接着是初始化阶段,Uboot会进行一系列的初始化工作,包括初始化串口、初始化内存控制器、初始化时钟等。

这些初始化工作是为了确保系统能够正常地运行,并为后续的工作做好准备。

设备初始化阶段是Uboot启动流程中的一个重要环节,它包括对外设的初始化和检测。

在这个阶段,Uboot会初始化各种外设,如网卡、存储设备等,并对其进行检测,以确保它们能够正常工作。

最后一个阶段是加载内核,Uboot会从存储设备中加载操作系统的内核镜像到内存中,并跳转到内核的入口地址开始执行。

在这个过程中,Uboot会进行一些必要的设置,如传递启动参数给内核,并最终将控制权交给内核。

总的来说,Uboot的启动流程是一个非常重要的过程,它涉及到系统的硬件初始化、外设的初始化和内核的加载等工作。

只有当这些工作都顺利完成时,系统才能够正常地启动运行。

因此,对Uboot启动流程的深入理解对于嵌入式系统的开发和调试具有重要意义。

通过本文对Uboot启动流程的分析,相信读者对Uboot的工作原理有了更清晰的认识。

希望本文能够对大家有所帮助,谢谢阅读!。

深度解析:嵌入式之uboot

深度解析:嵌入式之uboot

深度解析:嵌入式之uboot1.为什么要有uboot1.1、计算机系统的主要部件(1)计算机系统就是以CPU为核心来运行的系统。

典型的计算机系统有:PC机(台式机+笔记本)、嵌入式设备(手机、平板电脑、游戏机)、单片机(家用电器像电饭锅、空调)(2)计算机系统的组成部件非常多,不同的计算机系统组成部件也不同。

但是所有的计算机系统运行时需要的主要核心部件都是3个东西:CPU + 外部存储器(Flash/硬盘) + 内部存储器(DDR SDRAM/SDRAM/SRAM)1.2、PC机的启动过程(1)部署:典型的PC机的BIOS程序部署在PC机主板上(随主板出厂时已经预制了),操作系统部署在硬盘上,内存在掉电时无作用,CPU在掉电时不工作。

(2)启动过程:PC上电后先执行BIOS程序(实际上PC的BIOS就是NorFlash),BIOS程序负责初始化DDR内存,负责初始化硬盘,然后从硬盘上将OS镜像读取到DDR中,然后跳转到DDR中去执行OS直到启动(OS启动后BIOS 就无用了) 1.3、典型嵌入式linux系统启动过程(1)典型嵌入式系统的部署:uboot程序部署在Flash(能作为启动设备的Flash)上、OS部署在FLash(嵌入式系统中用Flash代替了硬盘)上、内存在掉电时无作用,CPU在掉电时不工作。

(2)启动过程:嵌入式系统上电后先执行uboot、然后uboot负责初始化DDR,初始化Flash,然后将OS从Flash中读取到DDR中,然后启动OS(OS启动后uboot就无用了)总结:嵌入式系统和PC机的启动过程几乎没有两样,只是BIOS 成了uboot,硬盘成了Flash。

1.4、android系统启动过程(1)Android系统的启动和Linux系统(前面讲的典型的嵌入式系统启动)几乎一样。

几乎一样意思就是前面完全一样,只是在内核启动后加载根文件系统后不同了。

(2)可以认为启动分为2个阶段:第一个阶段是uboot到OS启动;第二个阶段是OS启动后到rootfs加载到命令行执行;现在我们主要研究第一个阶段,android的启动和linux的差别在第二阶段。

uboot命令解释与运行分析

uboot命令解释与运行分析

uboot命令解释与运行分析题记: 省略200字这一回来分析一下uboot中命令行的解释, 所以我们直接从main_loop开始分析.1. 从汇编阶段进入c阶段的第一个函数是start_xxx, 如/lib_unicore/board.c中的start_unicoreboot. 前半部分调用了若干初始化函数来进行部分硬件的初始化, 并设置一下环境. 这里不是我们本回要讨论的所以一一跳过. 在start_xxx的最后调用了main_loop(), 而且还是被一个死循环死死圈住了;2. 现在我们已经进入了这个圈套那么只能往里钻了. common/main.c文件中的main_loop().上面代码主要是对自启动部分的描述, 其中命令执行部分是在run_command中进行的, 这个等在后文分析. 如果我们没有bootcmd 或者在延时中被打断, 那么代码会继续向下执行3.read_line()读取到命令行后会调用common/main.c文件中的run_command().现在是分析run_command()的时候了,不管是从环境变量还是终端获得命令,都是由run_command()来处理的.中场休息,下面要进入处理cmdbuf的循环中了, 长征马上开始以;分割. 忽略'\;'for(inquotes = 0, sep = str;*sep; sep++){if((*sep=='\'')&&(*(sep-1)!='\\'))inquotes=!inquotes;if(!inquotes &&(*sep ==';')&&( sep != str)&&(*(sep-1)!='\\'))break;}//如果上面for循环找到一条以';'结束的命令, 那么sep指向命令末尾token = str;if(*sep){str = sep + 1;*sep ='\0';}elsestr = sep;process_macros (token, finaltoken);if((argc = parse_line (finaltoken, argv))== 0){rc =-1;4.就此打断一下, 我们要分析一下find_cmd了, 不能再跳过了. find_cmd()在.u_boot_cmd段中寻找该命令的cmd_tbl_t结构, 找到后返回该结构. 该命令的结构是通过定义在include/command.h中的宏定义U_BOOT_CMD登记进.u_boot_cmd段中的.5. 刚才我们在长征的半路翻越了一座雪山, 现在继续回到while循环中if(cmdtp->cmd == do_bootd){if(flag & CMD_FLAG_BOOTD){puts("'bootd' recursion detected\n");rc =-1;continue;}else{flag |= CMD_FLAG_BOOTD;}}#endif//长征马上结束, 胜利就在眼前! 调用结构体中注册的cmd函数, 何时注册的呢? 上面不远处介绍的U_BOOT_CMD!if((cmdtp->cmd)(cmdtp, flag, argc, argv)!= 0){ rc =-1;}repeatable &= cmdtp->repeatable;if(had_ctrlc ())return-1;}。

uboot 命令详解

uboot 命令详解

u-boot 技术文档1.U boot 命令详解1.1查看帮助命令使用help 或者?1.2环境变量打印环境变量:printenv设置环境变量:setenv(不会保存)保存环境变量:saveenv这个时候就有了1.3nandflash命令使用nand查看nandflash 所有指令擦除nand erase1.4norflash命令查看Flash信息命令: flinfo加/解写保护命令: protect擦除命令: erase1.5内存命令nm1.5USB指令使用help usb 查看usb具体指令使用usb 启动使用usb tree查看信息f atls usb 0 罗列u盘信息1.5.1实例演练usb指令烧写1.6实例演练ftp指令烧写环境变量中体现了开发板上的IP地址为192.168.0.2,网关为192.168.0.1,要求电上的tftp 服务器的IP为192.168.0.1;运行电脑上tftp服务器,指定好根目录,将内核和根文件系统放在根目录下。

注:线接上后,电脑上的本地连接可能是显示网络电缆没插好,这很正常!在使用过程中它们会自动去连接!<2>分别下载内核和根文件系统到内存0x30008000开始的空间先检查坏块nand bad再擦除坏块清理某个区域0x560000 0x3b22c00将根文件系统加载到0x30008000然后再将根文件系统写到0x560000 0x3b22c00这个位置然后重启:重复上面的步骤:nand erase 0x60000 0x267000将内核文件保存到0x60000 0x267000这块区域运行1.8系统重启指令2.U boot 内核移植在cpu/arm920t/start.S中添加以下代码在修改并添加为以下代码在include/configs/mini2440.h修改为如下:将以下代码修改为:将以下代码修改为:将以下代码修改为:在drivers/mtd/nand/s3c2410_nand.h 在最后下面代码上添加如下带码:。

Uboot命令详解

Uboot命令详解

U-Boot提供了更加详细的命令帮助,通过help命令还可以查看每个命令的参数说明。

由于开发过程的需要,有必要先把U-Boot命令的用法弄清楚。

接下来,根据每一条命令的帮助信息,解释一下这些命令的功能和参数。

1、bootmdKNLinux联盟bootm [addr [arg ...]]- boot application image stored in memorypassing arguments &#39;arg ...&#39;; when booting a Linux kernel,&#39;arg&#39; can be the address of an initrd imagebootm命令可以引导启动存储在内存中的程序映像。

这些内存包括RAM和可以永久保存的Flash。

第1个参数addr是程序映像的地址,这个程序映像必须转换成U-Boot的格式。

第2个参数对于引导Linux内核有用,通常作为U-Boot格式的RAMDISK映像存储地址;也可以是传递给Linux内核的参数(缺省情况下传递bootargs环境变量给内核)。

dKNLinux联盟2、bootpbootp [loadAddress] [bootfilename]bootp命令通过bootp请求,要求DHCP服务器分配IP地址,然后通过TFTP协议下载指定的文件到内存。

第1个参数是下载文件存放的内存地址。

第2个参数是要下载的文件名称,这个文件应该在开发主机上准备好。

3、cmpcmp [.b, .w, .l] addr1 addr2 count- compare memorycmp命令可以比较2块内存中的内容。

.b以字节为单位;.w以字为单位;.l以长字为单位。

注意:cmp.b中间不能保留空格,需要连续敲入命令。

第1个参数addr1是第一块内存的起始地址。

第2个参数addr2是第二块内存的起始地址。

uboot启动代码详细讲解

uboot启动代码详细讲解

·1 引言在专用的嵌入式板子运行 GNU/Linux 系统已经变得越来越流行。

一个嵌入式 Linux 系统从软件的角度看通常可以分为四个层次:1. 引导加载程序。

固化在固件(firmware)中的 boot 代码,也就是 Boot Loader,它的启动通常分为两个阶段。

2. Linux 核。

特定于嵌入式板子的定制核以及核的启动参数。

3. 文件系统。

包括根文件系统和建立于 Flash 存设备之上文件系统,root fs。

4. 用户应用程序。

特定于用户的应用程序。

有时在用户应用程序和核层之间可能还会包括一个嵌入式图形用户界面。

常用的嵌入式 GUI 有:MicroWindows 和 MiniGUI 等。

引导加载程序是系统加电后运行的第一段软件代码。

回忆一下 PC 的体系结构我们可以知道,PC 机中的引导加载程序由 BIOS(其本质就是一段固件程序)和位于硬盘 MBR 中的 OS Boot Loader(比如,LILO 和 GRUB 等)一起组成。

BIOS 在完成硬件检测和资源分配后,将硬盘 MBR 中的 Boot Loader 读到系统的 RAM 中,然后将控制权交给 OS Boot Loader。

Boot Loader 的主要运行任务就是将核映象从硬盘上读到 RAM 中,然后跳转到核的入口点去运行,也即开始启动操作系统。

而在嵌入式系统中,通常并没有像 BIOS 那样的固件程序(注,有的嵌入式 CPU 也会嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由 Boot Loader 来完成。

比如在一个基于 ARM7TDMI core 的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000 处开始执行,而在这个地址处安排的通常就是系统的 Boot Loader 程序。

·2 bootloader简介简单地说,Boot Loader (引导加载程序)就是在操作系统核运行之前运行的一段小程序,它的作用就是加载操作系统,它是系统加电后运行的第一段软件代码。

UBOOT超详细命令解析

UBOOT超详细命令解析

U-boot发展到现在,他的命令行模式已经非常接近Linux下的shell了,命令行模式模式下支持“Tab”键的命令补全和命令的历史记录功能。

而且如果你输入的命令的前几个字符和别的命令不重复,那么你就只需要打这几个字符即可,比如我想看这个U-boot的版本号,命令就是“ version”,但是在所有的命令中没有其他任何一个的命令是由“v”开头的,所以只需要输入“v”即可。

[u-boot@MINI2440]# versionU-Boot 2009.11 ( 4月 04 2010 - 12:09:25)[u-boot@MINI2440]# vU-Boot 2009.11 ( 4月 04 2010 - 12:09:25)[u-boot@MINI2440]# baseBase Address: 0x00000000[u-boot@MINI2440]# baBase Address: 0x00000000由于U-boot支持的命令实在太多,一个一个细讲不现实,也没有必要。

所以下面我挑一些烧写和引导常用命令介绍一下,其他的命令大家就举一反三,或者“help”吧!(1)获取帮助命令:help 或 ?功能:查看当前U-boot版本中支持的所有命令。

[u-boot@MINI2440]#help?- alias for'help'askenv - get environment variables from stdinbase - print or set address offsetbdinfo - print Board Info structurebmp - manipulate BMP image databoot - boot default, i.e., run 'bootcmd'bootd - boot default, i.e., run 'bootcmd'bootelf - Boot from an ELF image in memorybootm - boot application image from memorybootp - boot image via network using BOOTP/TFTP protocolbootvx - Boot vxWorks from an ELF imagecmp - memory compareconinfo - print console devices and informationcp - memory copycrc32 - checksum calculationdate - get/set/reset date &timedcache - enable or disable data cachedhcp - boot image via network using DHCP/TFTP protocolecho - echo args to consoleeditenv - edit environment variableeeprom - EEPROM sub-systemerase - erase FLASH memoryexit-exit scriptfatinfo - print information about filesystemfatload - load binary file from a dos filesystemfatls -list files in a directory (default/)flinfo - print FLASH memory informationfsinfo - print information about filesystemsfsload - load binary file from a filesystem imagego - start application at address 'addr'help - print online helpi2c - I2C sub-systemicache - enable or disable instruction cacheiminfo - print header information for application image imls -list all images found in flashimxtract- extract a part of a multi-imageitest -return true/false on integer compareloadb - load binary file over serial line(kermit mode) loads - load S-Record file over serial lineloadx - load binary file over serial line(xmodem mode) loady - load binary file over serial line(ymodem mode) loop - infinite loop on address rangels -list files in a directory (default/)md - memory displaymm - memory modify (auto-incrementing address)mmc - MMC sub-systemmtest - simple RAM read/write testmw - memory write(fill)nand - NAND sub-systemnboot - boot from NAND devicenfs - boot image via network using NFS protocolnm - memory modify (constant address)ping -send ICMP ECHO_REQUEST to network hostprintenv- print environment variablesprotect - enable or disable FLASH write protection rarpboot- boot image via network using RARP/TFTP protocol reginfo - print register informationreset- Perform RESET of the CPUrun - run commands in an environment variablesaveenv - save environment variables to persistent storage setenv -set environment variablesshowvar - print local hushshell variablessleep- delay execution for some timesource - run script from memorytest- minimal test like /bin/shtftpboot- boot image via network using TFTP protocolunzip - unzip a memory regionusb - USB sub-systemusbboot - boot from USB deviceversion - print monitor version如果你想获取某条命令的更详细的帮助,可以使用:help <你想要查的指令>或者?<你想要查的指令>,甚至 h <你想要查的指令缩写>。

《UBoot开发》课件

《UBoot开发》课件
UBoot开发
嵌入式系统开发中,UBoot是一项重要的工作。本课程将介绍UBoot的基本结 构、配置和移植,以及常见的应用场景和未来发展趋势。
什么是UBoot
概念和作用
UBoot是一种开源引导加载程序,用于在底层硬件上启动系统,提供了丰富的功能和配置选 项。
UBoot与Linux内核的关系
UBoot和Linux内核之间的交互非常紧密,UBoot启动后会通过设备树传递必要的参数给内核。
UBoot的移植
1
移植的流程和方法
UBoot的移植需要考虑到硬件与软件的匹
实际移植案例分享
2
配性,需要进行配置和编译,并通过调 试工具进行调试。
通过实际案例分析和实验验证,演示了
如何将UBoot移植到指定的硬件平台。
UBoot的调试
调试方法和技巧
对于UBoot出现的问题,需要使用调试工具进行诊断 和修复,例如GDB、KGDB、JTAG等。
结语
感谢大家参加本次UBoot开发课程,希望通过本课程的学习,您可以提高嵌入式系统开发的能力。
UBoot的基本结构
源码结构
UBoot的源码按照模块划分,包含了启动代码、设备 驱动、文件系统和网络协议栈等各个方面。
启动流程
UBoot的启动流程分为初始化、检测和启动三个阶段, 其核心在于加载并执行内核映像。
UBoot的配置
1
配置文件概述
UBoot的配置采用Kconfig和Makefile的组合方式,用户可以自由选择编译需要的 模块和功能。
UBoot常见问题及解决方法
一些常见问题包括无法启动、设备树错误以及编译 错误等,需要耐心分析和尝试不同的解决方法。
UBoot的应用
1 典型应用场景

uboot分析和笔记

uboot分析和笔记

uboot一、uboot是ppcboot和armboot合并而成,现在主流的bootloader为uboot和redboot二、bootm addr_kernel addr_initrd三、移植uboot时最好(一定)要找到一个自己板子的原形(即自己的板子是在这个板子上做一些修改而来的)的版本,这样就可以事半功倍。

这样要修改的地方就比较少,也比较容易了。

uboot支持很多平台,与一个具体平台相关的主要有三个地方:1、./include/configs/xxxxx.h, 主要定义了flash、sdram的起始地址等信息,一般要修改flash的起始地址、大小,有时候会有位宽等。

2、./board/xxxxx/*,这个目录下主要有两三个.c文件,主要为该平台的初始化和flash操作的函数。

有时候flash的操作需要修改,不过一般都是找一个现有的支持该flash的驱动,一般情况在uboot 别的./board/平台下就会有现成的,拷贝过了就可以了。

3、./cpu/xxxxxx/arch_xxx/xxxxxx/*, 一般是此cpu的初始等函数。

四、具体移植的时候最多涉及到的会是./include/configs/xxxx.h,如果有现成的平台(uboot现在支持绝大部分我们常用的平台),可能只需要对着原来的xxxx.h文件,修改几个我们在硬件上修改了的地方,一般会是flash的起始地址、大小;内存大小(内存的起始地址应该都是0);uboot设置信息保存的地址和长度;console 口和它的波特率;默认的设置;uboot的入口地址等(具体情况可能会有一些变化),如果不是从相同的平台移植,可能会比较麻烦,因为这时候要修改一些和此cpu相关的一些寄存器、频率和内存等硬件方面的东西了(也在这个xxxx.h中),虽然这时改动的地方也不多,但是会很痛苦,因为经常不知道要改哪里或者改为多少。

所以可能需要参考cpu的datasheet和到网上找一些资料了并且慢慢试了。

U-Boot启动过程--详细版的完全分析

U-Boot启动过程--详细版的完全分析

(一)U-Boot启动过程--详细版的完全分析我们知道,bootloader是系统上电后最初加载运行的代码。

它提供了处理器上电复位后最开始需要执行的初始化代码。

在PC机上引导程序一般由BIOS开始执行,然后读取硬盘中位于MBR(Main Boot Record,主引导记录)中的Bootloader(例如LILO或GRUB),并进一步引导操作系统的启动。

然而在嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动就完全由bootloader来完成。

它主要的功能是加载与引导内核映像一个嵌入式的存储设备通过通常包括四个分区:第一分区:存放的当然是u-boot第二个分区:存放着u-boot要传给系统内核的参数第三个分区:是系统内核(kernel)第四个分区:则是根文件系统如下图所示:u-boot是一种普遍用于嵌入式系统中的Bootloader。

Bootloader介绍Bootloader是进行嵌入式开发必然会接触的一个概念,它是嵌入式学院<嵌入式工程师职业培训班>二期课程中嵌入式linux系统开发方面的重要内容。

本篇文章主要讲解Bootloader 的基本概念以及内部原理,这部分内容的掌握将对嵌入式linux系统开发的学习非常有帮助!Bootloader的定义:Bootloader是在操作系统运行之前执行的一小段程序,通过这一小段程序,我们可以初始化硬件设备、建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。

意思就是说如果我们要想让一个操作系统在我们的板子上运转起来,我们就必须首先对我们的板子进行一些基本配置和初始化,然后才可以将操作系统引导进来运行。

具体在Bootloader中完成了哪些操作我们会在后面分析到,这里我们先来回忆一下PC的体系结构:PC机中的引导加载程序是由BIOS和位于硬盘MBR中的OS Boot Loader(比如LILO和GRUB等)一起组成的,BIOS在完成硬件检测和资源分配后,将硬盘MBR中的Boot Loader读到系统的RAM中,然后将控制权交给OS Boot Loader。

uboot传递内核参数全解析

uboot传递内核参数全解析

uboot传递内核参数全解析一:启动参数的传递过程启动参数是包装在数据结构里的,在linux kernel启动的时候,bootloader把这个数据结构拷贝到某个地址,在改动PC跳向内核接口的同时,通过通用寄存器R2来传递这个地址的值,下面这句话就是uboot跳向linuxkernel的代码(bootm命令)theKernel (0, bd->bi_arch_number, bd->bi_boot_params);thekernel其实不是个函数,而是指向内核入口地址的指针,把它强行转化为带三个参数的函数指针,会把三个参数保存到通用寄存器中,实现了向kernel传递信息的功能,在这个例子里,会把R0赋值为0,R1赋值为机器号R2赋值为启动参数数据结构的首地址因此,要向内核传递参数很简单,只要把启动参数封装在linux预定好的数据结构里,拷贝到某个地址(一般约定俗成是内存首地址+100dex)二:启动参数的数据结构启动参数可保存在两种数据结构中,param_struct和tag,前者是2.4内核用的,后者是2.6以后的内核更期望用的但是,到目前为止,2.6的内核也可以兼容前一种结构,两种数据结构具体定义如下(arm cpu):struct param_struct {union {struct {unsigned long page_size; /* 0 */unsigned long nr_pages; /* 4 */unsigned long ramdisk_size; /* 8 */unsigned long flags; /* 12 */#define FLAG_READONLY 1#define FLAG_RDLOAD 4#define FLAG_RDPROMPT 8unsigned long rootdev; /* 16 */unsigned long video_num_cols; /* 20 */unsigned long video_num_rows; /* 24 */unsigned long video_x; /* 28 */unsigned long video_y; /* 32 */unsigned long memc_control_reg; /* 36 */unsigned char sounddefault; /* 40 */unsigned char adfsdrives; /* 41 */unsigned char bytes_per_char_h; /* 42 */unsigned char bytes_per_char_v; /* 43 */unsigned long pages_in_bank[4]; /* 44 */unsigned long pages_in_vram; /* 60 */unsigned long initrd_start; /* 64 */unsigned long initrd_size; /* 68 */unsigned long rd_start; /* 72 */unsigned long system_rev; /* 76 */unsigned long system_serial_low; /* 80 */unsigned long system_serial_high; /* 84 */unsigned long mem_fclk_21285; /* 88 */} s;char unused[256];} u1;union {char paths[8][128];struct {unsigned long magic;char n[1024 - sizeof(unsigned long)];} s;} u2;char commandline[COMMAND_LINE_SIZE];};param_struct只需要设置cmmandline,u1.s.page_size,u1.s.nr_pages三个域,具体使用可参见下面的例子对于tag来说,在实际使用中是一个struct tag组成的列表,在tag->tag_header中,一项是u32 tag(重名,注意类型)其值用宏ATAG_CORE,ATAG_MEM,ATAG_CMDLINE,ATAG_NONE等等来表示,此时下面union就会使用与之相关的数据结构同时,规定tag列表中第一项必须是ATAG_CORE,最后一项必须是ATAG_NONE,比如在linux代码中,找到启动参数之后首先看tag列表中的第一项的tag->hdr.tag是否为ATAG_CORE,如果不是,就会认为启动参数不是tag 结构而是param_struct结构,然后调用函数来转换.在tag->tag_header中,另一项是u32 size,表示tag的大小,tag组成列表的方式就是指针+size,实际使用中用tag_next (params).tag的具体使用见三中的例子struct tag {struct tag_header hdr;union {struct tag_core core;struct tag_mem32 mem;struct tag_videotext videotext;struct tag_ramdisk ramdisk;struct tag_initrd initrd;struct tag_serialnr serialnr;struct tag_revision revision;struct tag_videolfb videolfb;struct tag_cmdline cmdline;struct tag_acorn acorn; //Acorn specificstruct tag_omap omap; //OMAP specificstruct tag_memclk memclk; //DC21285 specific} u;};需要注意的是,这两个数据结构在uboot中和linux中分别有定义,这个定义必须一直才能正常传递参数如果实际使用中不一致的话就不能正常传递,可以自行修改三:通过两种数据结构传递参数的具体例子1:例子一:通过param_struct让uboot中的go命令可以传递参数分析:go的代码在common/cmd_boot.c中,里面并没有拷贝启动参数的代码,转向内核的时候也没有传送启动参数所在的地址,因此添加如下代码用于拷贝参数,可以看到,对于param_struct只需要设置cmmandlineu1.s.page_size,u1.s.nr_pages三个域char *commandline = getenv("bootargs");struct param_struct *lxy_params=(struct param_struct *)0x80000100;printf("setup linux parameters at 0x80000100\n");memset(lxy_params,0,sizeof(struct param_struct));lxy_params->u1.s.page_size=(0x1<<12); //4K 这个是必须有的,否则无法启动lxy_params->u1.s.nr_pages=(0x4000000)>>12; //64M 这个是必须有的,否则无法启动memcpy(lxy_params->commandline,commandline,strlen(commandline)+1);printf("linux command line is: \"%s\"\n",lxy_params->commandline);然后还要向内核传递参数地址,将下面一行代码修改:rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]); //需要被修改的代码rc = ((ulong(*)(int,int,uint))addr) (0, gd->bd->bi_arch_number,gd->bd->bi_boot_params);//修改之后的代码2:例子二:bootm命令中通过拷贝tag传递参数为方便阅读,进行了少许修改,但功能不变,该函数参数为存放启动参数的地址static void setup_linux_tag(ulong param_base){struct tag *params = (struct tag *)param_base;char *linux_cmd;char *p;memset(params, 0, sizeof(struct tag));/* step1: setup start tag */params->hdr.tag = ATAG_CORE;params->hdr.size = tag_size(tag_core);params->u.core.flags = 0;params->u.core.pagesize = LINUX_PAGE_SIZE;params->u.core.rootdev = 0;params = tag_next(params);/* step2: setup cmdline tag */params->hdr.tag = ATAG_CMDLINE;linux_cmd = getenv("bootargs");/* eat leading white space */for (p=linux_cmd; *p==' '; p++) {/* do nothing */;}params->hdr.size = (sizeof(struct tag_header)+strlen(linux_cmd)+1+4) >> 2;memcpy(params->u.cmdline.cmdline, linux_cmd, strlen(linux_cmd)+1);params = tag_next(params);/* step3: setup end tag */params->hdr.tag = ATAG_NONE;params->hdr.size = 0;}四:其他在uboot中,进行设置tag的函数都在lib_arm/armlinux.c中,在这些函数前面是有ifdef的#if defined (CONFIG_SETUP_MEMORY_TAGS) || \defined (CONFIG_CMDLINE_TAG) || \defined (CONFIG_INITRD_TAG) || \defined (CONFIG_SERIAL_TAG) || \defined (CONFIG_REVISION_TAG) || \defined (CONFIG_LCD) || \defined (CONFIG_VFD)因此,如果你的bootm命令不能传递内核参数,就应该是在你的board的config文件里没有对上述的宏进行设置,定义一下即可。

uboot分析

uboot分析

uboot分析BootLoader指系统启动后,在操作系统内核运行之前运行的一段小程序。

通过BootLoader,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。

通常,BootLoader是严重地依赖于硬件而实现的,特别是在嵌入式世界。

因此,在嵌入式世界里建立一个通用的BootLoader 几乎是不可能的。

尽管如此,我们仍然可以对BootLoader归纳出一些通用的概念来,以指导用户特定的BootLoader设计与实现。

BootLoader的操作模式一般分为自启动模式和交互模式。

自启动模式:BootLoaderd从目标机上的某个固态设备上将操作系统加载到RAM中运行,整个过程没有用户的介入;交互模式:目标机上的BootLoader将通过串口或网络等通信手段从开发板上下载内核映像和根文件系统映像等到RAM中,可以写到目标机上的固态存储介质中,或者直接进行系统的引导。

也可以通过串口接收用户的命令。

BootLoader基本功能:初始化相关硬件;把BootLoader自搬移到内存中;执行用户的命令(访问环境变量;通过网络/串口通信;读写RAM/Flash);加载并执行内核。

一个嵌入式Linux系统从软件的角度看通常可以分为四个部分:BootLoader、Linux内核、跟文件系统及用户的应用程序。

BootLoader处于系统的最底层,运行于系统启动的最初阶段。

系统加电或复位后,所有CPU都会从某个地址开始执行,这是由处理器设计决定的。

比如,X86的复位向量在高地址端,ARM处理器在复位时从地址0x00000000取第一条指令。

嵌入式系统的开发板都要把板上ROM或Flash映射到这个地址。

因此,必须把Bootloader程序存储在相应的Flash位置。

系统加电后,CPU将首先执行它。

BootLoader的启动过程可以是单阶段的,也可以是多阶段的。

uboot编译原理

uboot编译原理

uboot编译原理一、什么是UBoot是一个复杂的综合的裸机程序,支持各种。

UBoot就是一个Bootloader,用于启动linux系统的程序,它是上电以后的第一个程序。

它最重要的就是初始化DDR,linux在DDR中运行的,由于Linux内存比较大,放到内部的ROM中是远远不够的。

Linux镜像一开始存在EMMC,NAND FLASH , 等外置存储中。

那么我们需要将linux镜像从外置存储拷贝到DDR中,就需要Uboot程序来做。

主要为系统启动做准备。

Uboot获取1. 可得到,但是我们通常不使用这些Uboot,因为做芯片的厂商才了解自己的东西,工程师往往会在设计时考虑使用哪个版本的uboot。

2.SOC厂商官网获得,这个是厂商根据芯片定制版的uboot。

3.开发版厂商,会参考SOC厂商发布的uboot的进行对开发版产品的uboot进行修改。

Uboot启动内核的流程开发版上电以后,就会加载uboot程序,它是上电后的第一个程序。

然后打印出一些uboot信息,读取uimage /zImage , 读取设备树之后就开始启动内核了。

二、编译Uboot下载开发版厂提供的内核,以后编译uboot1.准备交叉编译工具链,在uboot目录内可以检查到,即输入arm-n,按Tab键可补齐即可,如果不行,就将用户目录下的.bashrc文件拷贝过来,然后执行source .bashrc即可。

如果是新系统,就要安装这些依赖源。

sudoapt-getinstall lib32ncurses5 lib32tinfo5 libc6-i3862.编译内核执行下列命令即可完成zxc123@ubuntu:~/IMX6ULL/ebf_6ull_uboot$ export CROSS_COMPILE=arm-linux-gnueabihf-zxc123@ubuntu:~/IMX6ULL/ebf_6ull_uboot$ exportARCH=armzxc123@ubuntu:~/IMX6ULL/ebf_6ull_uboot$ make ARCH=arm mx6ull_14x14_evk_defconfigzxc123@ubuntu:~/IMX6ULL/ebf_6ull_uboot$ make -j12除了上面这种方法以外,也可以在uboot顶层makefile中设置ARCH,CROSS_COMPILE变量的信息。

uboot 流程 概述

uboot 流程 概述

uboot 流程概述
uboot是一款常用的开源引导程序,用于启动嵌入式系统。

它可以加载操作系统内核,初始化硬件设备,设置环境变量等,同时还提供了一些常用的命令行工具。

在开发嵌入式系统时,学习 uboot 是必不可少的。

uboot 的启动流程可以简单概括如下:
1. ROM 阶段:当嵌入式系统上电时,ROM 芯片中的引导程序会首先运行,它的作用是初始化 CPU 和内存,并且将 uboot 的启动地址加载到内存中。

2. SPL 阶段:uboot 的二进制文件通常很大,不能一次性加载完毕。

因此,uboot 的第一个阶段(也称为 SPL,Secondary Program Loader)会被加载到内存中,它的作用是提供一些基本的硬件初始化功能,同时可以将 uboot 的剩余部分加载到内存中。

3. uboot 阶段:当 SPL 完成任务后,uboot 的主程序被加载到内存中。

在这个阶段,uboot 会完成一系列初始化工作,如初始化串口、网卡、USB 等硬件设备,然后会启动一个交互式的命令行界面,等待用户输入命令。

4. 内核启动阶段:当用户输入启动命令后,uboot 会加载操作系统内核到内存中,并将控制权传递给内核。

内核会接管硬件设备,并开始执行系统的初始化工作。

总的来说,uboot 的启动流程比较复杂,但是掌握了它的基本原理,可以更好地理解嵌入式系统的启动过程,从而优化系统性能,提
升开发效率。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

大多数bootloader都分为stage1和stage2两部分,u-boot也不例外。

依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

1、Stage1 start.S代码结构u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:(1)定义入口。

由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。

(2)设置异常向量(Exception Vector)。

(3)设置CPU的速度、时钟频率及终端控制寄存器。

(4)初始化内存控制器。

(5)将ROM中的程序复制到RAM中。

(6)初始化堆栈。

(7)转到RAM中执行,该工作可使用指令ldr pc来完成。

2、Stage2 C语言代码部分lib_arm/board.c中的start arm boot是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数只要完成如下操作:(1)调用一系列的初始化函数。

(2)初始化Flash设备。

(3)初始化系统内存分配函数。

(4)如果目标系统拥有NAND设备,则初始化NAND设备。

(5)如果目标系统有显示设备,则初始化该类设备。

(6)初始化相关网络设备,填写IP、MAC地址等。

(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

3、U-Boot的启动顺序(示例,其他u-boot版本类似)cpu/arm920t/start.S@文件包含处理#include <config.h>@由顶层的mkconfig生成,其中只包含了一个文件:configs/<顶层makefile中6个参数的第1个参数>.h#include <version.h>#include <status_led.h>/**************************************************************************** Jump vector table as in table 3.1 in [1]***************************************************************************/注:ARM微处理器支持字节(8位)、半字(16位)、字(32位)3种数据类型@向量跳转表,每条占四个字节(一个字),地址范围为0x0000 0000~@0x0000 0020@ARM体系结构规定在上电复位后的起始位置,必须有8条连续的跳@转指令,通过硬件实现。

他们就是异常向量表。

ARM在上电复位后,@是从0x00000000开始启动的,其实如果bootloader存在,在执行@下面第一条指令后,就无条件跳转到start_code,下面一部分并没@执行。

设置异常向量表的作用是识别bootloader。

以后系统每当有@异常出现,则CPU会根据异常号,从内存的0x00000000处开始查表@做相应的处理/******************************************************;当一个异常出现以后,ARM会自动执行以下几个步骤:;1.把下一条指令的地址放到连接寄存器LR(通常是R14).---保存位置;2.将相应的CPSR(当前程序状态寄存器)复制到SPSR(备份的程序状态寄存器)中---保存CPSR ;3.根据异常类型,强制设置CPSR的运行模式位;4.强制PC(程序计数器)从相关异常向量地址取出下一条指令执行,从而跳转到相应的异常处理程序中*********************************************************/.globl _start /*系统复位位置,整个程序入口*/@_start是GNU汇编器的默认入口标签,.globl将_start声明为外部程序可访问的标签,.globl 是GNU汇编的保留关键字,前面加点是GNU汇编的语法_start: b start_code @0x00@ARM上电后执行的第一条指令,也即复位向量,跳转到start_code@reset用b,就是因为reset在MMU建立前后都有可能发生@其他的异常只有在MMU建立之后才会发生ldr pc, _undefined_instruction /*未定义指令异常,0x04*/ldr pc, _software_interrupt /*软中断异常,0x08*/ldr pc, _prefetch_abort /*内存操作异常,0x0c*/ldr pc, _data_abort /*数据异常,0x10*/ldr pc, _not_used /*未适用,0x14*/ldr pc, _irq /*慢速中断异常,0x18*/ldr pc, _fiq /*快速中断异常,0x1c*/@对于ARM数据从内存到CPU之间的移动只能通过L/S指令,如:ldr r0,0x12345678为把0x12345678内存中的数据写到r0中,还有一个就是ldr伪指令,如:ldr r0,=0x12345678为把0x12345678地址写到r0中,mov只能完成寄存器间数据的移动,而且立即数长度限制在8位_undefined_instruction: .word undefined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word fiq@.word为GNU ARM汇编特有的伪操作,为分配一段字内存单元(分配的单元为字对齐的),可以使用.word把标志符作为常量使用。

如_fiq:.word fiq即把fiq存入内存变量_fiq中,也即是把fiq放到地址_fiq中。

.balignl 16,0xdeadbeef@.balignl是.balign的变体@ .align伪操作用于表示对齐方式:通过添加填充字节使当前位置@满足一定的对齐方式。

.balign的作用同.align。

@ .align {alignment} {,fill} {,max}@其中:alignment用于指定对齐方式,可能的取值为2的次@幂,缺省为4。

fill是填充内容,缺省用0填充。

max是填充字节@数最大值,如果填充字节数超过max, 就不进行对齐,例如:@ .align 4 /* 指定对齐方式为字对齐*/【参考好野人的窝,于关u-boot中的.balignl 16,0xdeadbeef的理解/84511571.html】/**************************************************************************** Startup Code (called from the ARM reset exception vector)** do important init only if we don't start from memory!* relocate armboot to ram* setup stack* jump to second stage**************************************************************************@保存变量的数据区,保存一些全局变量,用于BOOT程序从FLASH拷贝@到RAM,或者其它的使用。

@还有一些变量的长度是通过连接脚本里得到,实际上由编译器算出@来的_TEXT_BASE:@因为linux开始地址是0x30000000,我这里是64M SDRAM,所以@TEXT_BASE = 0x33F80000 ???.word TEXT_BASE /*uboot映像在SDRAM中的重定位地址*/@TEXT_BASE在开发板相关的目录中的config.mk文档中定义, 他定@义了代码在运行时所在的地址, 那么_TEXT_BASE中保存了这个地@址(这个TEXT_BASE怎么来的还不清楚).globl _armboot_start_armboot_start:.word _start@用_start来初始化_armboot_start。

(为什么要这么定义一下还不明白)/** These are defined in the board-specific linker script.*/@下面这些是定义在开发板目录链接脚本中的.globl _bss_start_bss_start:.word __bss_start@__bss_start定义在和开发板相关的u-boot.lds中,_bss_start保存的是__bss_start标号所在的地址。

.globl _bss_end_bss_end:.word _end@同上,这样赋值是因为代码所在地址非编译时的地址,直接取得该标号对应地址。

@中断的堆栈设置#ifdef CONFIG_USE_IRQ/* IRQ stack memory (calculated at run-time) */.globl IRQ_STACK_STARTIRQ_STACK_START:.word 0x0badc0de/* IRQ stack memory (calculated at run-time) */.globl FIQ_STACK_STARTFIQ_STACK_START:.word 0x0badc0de#endif/** the actual start code*/@复位后执行程序@真正的初始化从这里开始了。

其实在CPU一上电以后就是跳到这里执行的reset:/** set the cpu to SVC32 mode*/@更改处理器模式为管理模式@对状态寄存器的修改要按照:读出-修改-写回的顺序来执行@31 30 29 28 --- 7 6 - 4 3 2 1 0N Z C V I F M4 M3 M2 M1 M00 0 0 0 0 User26 模式0 0 0 0 1 FIQ26 模式0 0 0 1 0 IRQ26 模式0 0 0 1 1 SVC26 模式1 0 0 0 0 User 模式1 0 0 0 1 FIQ 模式1 0 0 1 0 IRQ 模式1 0 0 1 1 SVC 模式1 0 1 1 1 ABT 模式1 1 0 1 1 UND 模式1 1 1 1 1 SYS 模式mrs r0,cpsr@将cpsr的值读到r0中bic r0,r0,#0x1f@清除M0~M4orr r0,r0,#0xd3@禁止IRQ,FIQ中断,并将处理器置于管理模式msr cpsr,r0@以下是点灯了,这里应该会牵涉到硬件设置,移植的时候应该可以不要blcoloured_LED_initblred_LED_on@针对AT91RM9200进行特殊处理#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)/** relocate exception table*/ldr r0, =_startldr r1, =0x0mov r2, #16copyex:subs r2, r2, #1@sub带上了s用来更改进位标志,对于sub来说,若发生借位则C标志置0,没有则为1,这跟adds指令相反!要注意。

相关文档
最新文档