嵌入式启动流程 汇编代码解析
- 格式:docx
- 大小:14.60 KB
- 文档页数:2
如何使用C语言进行嵌入式系统开发第一章:引言嵌入式系统是一种专门设计用于特定应用领域的计算机系统,它通常由硬件平台和软件系统组成。
C语言作为一种高级编程语言,广泛应用于嵌入式系统开发中。
本文将介绍如何使用C语言进行嵌入式系统开发。
第二章:了解嵌入式系统在使用C语言进行嵌入式系统开发之前,我们需要了解嵌入式系统的基本概念和特点。
嵌入式系统通常运行在资源受限的环境中,因此需要对系统资源的管理和利用进行精确控制。
嵌入式系统的开发过程需要考虑实时性、可靠性、功耗等因素。
第三章:基础知识在使用C语言进行嵌入式系统开发之前,我们需要掌握一些基础知识。
首先是C语言的基本语法和特性,包括数据类型、运算符、控制语句等。
其次是嵌入式系统开发中常用的硬件知识,例如芯片架构、外设接口等。
还需要了解一些常用的嵌入式开发工具,如编译器、调试器等。
第四章:选择适合的开发平台嵌入式系统开发需要选择适合的开发平台。
常见的开发平台包括单片机、嵌入式Linux系统、实时操作系统等。
根据具体应用需求选择合适的开发平台,同时要考虑开发工具的可用性和便利性。
第五章:编写嵌入式系统应用程序使用C语言进行嵌入式系统开发的核心是编写应用程序。
在编写应用程序时,需要根据系统需求设计合适的算法和数据结构,实现功能模块。
同时要考虑资源的合理利用和性能的优化,以保证系统的稳定运行。
第六章:调试和测试嵌入式系统开发过程中,调试和测试是至关重要的环节。
通过调试和测试可以发现和解决系统中的问题,保证系统的可靠性和稳定性。
在调试和测试过程中,可以使用一些专业的嵌入式开发工具,如JTAG、Logic Analyzer等,来辅助分析和调试。
第七章:性能优化嵌入式系统通常具有资源受限的特点,因此性能优化是非常重要的。
通过代码优化、算法改进、资源管理等手段,可以提高系统的实时性、运行速度和功耗效率。
在进行性能优化时,需要仔细分析系统的瓶颈和热点,针对性地进行优化操作。
MIPS汇编代码MIPS汇编代码是MIPS微处理器的汇编语言,由MIPS Technologies公司开发。
它是一种低级编程语言,允许程序员直接控制处理器的寄存器和指令。
MIPS汇编代码通常用于嵌入式系统和实时系统,因为它可以提供对硬件的精细控制和高性能。
MIPS汇编代码由一系列指令组成,每条指令由一个操作码和零个或多个操作数组成。
操作码指定要执行的操作,而操作数指定操作的参数。
MIPS汇编代码中的指令可以分为以下几类:算术和逻辑指令:这些指令用于执行算术和逻辑运算,例如加、减、乘、除、与、或、非等。
数据传送指令:这些指令用于在寄存器和内存之间传送数据。
控制流指令:这些指令用于控制程序的执行流程,例如跳转、分支、调用和返回等。
系统指令:这些指令用于与系统进行交互,例如加载和存储程序和数据、读写I/O设备等。
MIPS汇编代码通常使用以下语法:label: instruction operand1, operand2, ...其中,label是指令的标签,instruction是指令的操作码,operand1、operand2等是指令的操作数。
MIPS汇编代码的程序结构通常包括以下几个部分:数据段:数据段用于存储程序中使用的数据,包括常量、变量和数组等。
代码段:代码段用于存储程序的指令。
堆栈段:堆栈段用于存储程序的局部变量和临时数据。
MIPS汇编代码的编译过程通常包括以下几个步骤:预处理:预处理阶段将源代码中的宏和条件编译指令进行处理。
汇编:汇编阶段将源代码中的指令转换成机器码。
链接:链接阶段将汇编生成的机器码与库函数和系统库进行链接,生成可执行文件。
MIPS汇编代码的优点包括:高性能:MIPS汇编代码可以提供高性能,因为它可以直接控制处理器的寄存器和指令。
精细的控制:MIPS汇编代码允许程序员对硬件进行精细的控制,这对于嵌入式系统和实时系统非常重要。
可移植性:MIPS汇编代码可以移植到不同的MIPS处理器上,因为MIPS处理器具有相同的指令集架构。
嵌入式linux系统的启动流程
嵌入式Linux系统的启动流程一般包括以下几个步骤:
1.硬件初始化:首先会对硬件进行初始化,例如设置时钟、中
断控制等。
这一步骤通常是由硬件自身进行初始化,也受到系统的BIOS或Bootloader的控制。
2.Bootloader引导:接下来,系统会从存储介质(如闪存、SD
卡等)的Bootloader区域读取引导程序。
Bootloader是一段程序,可以从存储介质中加载内核镜像和根文件系统,它负责进行硬件初始化、进行引导选项的选择,以及加载内核到内存中。
3.Linux内核加载:Bootloader会将内核镜像从存储介质中加载到系统内存中。
内核镜像是包含操作系统核心的一个二进制文件,它由开发者编译并与设备硬件特定的驱动程序进行连接。
4.内核初始化:一旦内核被加载到内存中,系统会进入内核初
始化阶段。
在这个阶段,内核会初始化设备驱动程序、文件系统、网络协议栈等系统核心。
5.启动用户空间:在内核初始化完毕后,系统将启动第一个用
户空间进程(init进程)。
init进程会读取并解析配置文件(如
/etc/inittab)来决定如何启动其他系统服务和应用程序。
6.启动其他系统服务和应用程序:在用户空间启动后,init进
程会根据配置文件启动其他系统服务和应用程序。
这些服务和应用程序通常运行在用户空间,提供各种功能和服务。
以上是嵌入式Linux系统的基本启动流程,不同的嵌入式系统可能会有一些差异。
同时,一些特定的系统也可以添加其他的启动流程步骤,如初始化设备树、加载设备固件文件等。
1嵌入式操作系统启动流程1.在通电后,初始化硬件(bootrom)2.支持VxWorks与硬件驱动通信(Image的底层驱动)3.本质上是硬件驱动、初始化的合集;2研究BSP内容:1.系统image的生成与image的种类2.image的download下载过程3.系统的启动顺序与过程4.调试环境的配置及远端调试的方式与方法5.相应BSP设置文件的修改(网络,串口..)6.BSP各文件的构成与作用.7.要对系统底层驱动清晰,也就是对CPU及有关的硬件有所熟悉.要紧是32微处理器(上电启动过程, download image的方式方法,读写ROM,地址空间分配,MMU,寄存器,中断定义,..).参照硬件资料,多读一些源码会有所帮助.3BSP要紧文件目录的构成及要紧文件的作用:3.1目录target/config/All:这个目录下的文件是所有BSP文件共享的,不是特别需要不要更换里面的任何文件.configAll.h:缺省定义了所有VxWorks的设置.假如不用缺省的设置,可在BSP目录下的config.h文件中用#define或者#undef方式来更换设置.bootInit.c:在romInit.s后,完成Boot ROM的第二步初始化.程序从romInit.s中的romInit()跳到这个文件中的romStart().来执行必要的解压与ROM image的放置.bootConfig.c:完成Boot ROM image的初始化与操纵.usrConfig.c: VxWorks image的初始化代码.3.2目录target/config/comps/src:涉及系统核心的components,要紧由target/config/All中usrConfig.c中函数调用3.3目录target/config/bspname:包含系统或者硬件有关的BSP文件.MakefileREADMEBSP公布纪录,版本,总的文档config.hconfigNet.h网络驱动的要紧设置文件,要紧对END驱动设置.romInit.ssysALib.s汇编语言文件,程序员能够把自己的汇编函数放在这个文件里,在上层调用.VxWorks image的入口点_sysInit在这个文件里,是在RAM中执行的第一个函数.sysLib.c包含一些系统有关的函数例程,提供了一个board-level的接口,VxWorks与应用程序能够以system-indepent的方式生成.这个文件还能包含目录target/config/comps/src的驱动.sysScsi.c可选文件用于Scsi设备设置与初始化.sysSerial.c可选文件用于所有的串口设置与初始化.bootrom.hexASIC文件包含VxWorks Boot ROM代码VxWorks运行在目标机上,完整的,连结后的VxWorks二进制文件.VxWorks.sym完全的,连结后带有符号表的VxWorks二进制文件VxWorks.st完全的,连结后,standalone,带有符号表的VxWorks二进制文件4VxWorks Image4.1VxWorks images consist of:•Text segment---executable instruction.•Data segment---Initilized global and static varibles.•BSS.4.2分类与工作机理:Bootrom不是VxWorks Image,不参与讨论它本质上是一段Boot program,最少的系统初始化,要紧用于启动装载VxWorks image.通常有压缩与不压缩两种形式,如bootrom与boot_uncmp.与VxWorks image的区别在于一个Bootrom调用bootConfig.c,而VxWorks调用usrConfig.c.VxWorks 本质上分为两大类:1.Vxworks分为两大类:1)Uploaded images(通过网口、串口、硬盘、软盘、DOC、ROM中加载到RAM中执行的)vxWorks - basic Tornado, shell 与symbol table 在主机端vxWorks.st(文件很大)- 独立的image,包含shell与symbol table 在目标板运行2)ROM based images(直接烧入ROM的VxWorks):VxWorks_Rom类的Vxworks又分了两类:1)驻留的resident 2)不住留的1.不住留的ROM – Based VxWorks Image2.驻留的VxWorks_rom_resident2.说的再具体点:1)可下载的Vxworks image2)ROM中烧制的Image1.vxWorks_rom - Tornado in ROM,非压缩, 在RAM 中运行2.vxWorks.res_rom_nosym - Tornado in ROM, 非压缩,在ROM 中运行3.vxWorks.st_rom - Stand-alone in ROM, 压缩, RAM 中运行4.vxWorks.res_rom - Stand-alone in ROM, 非压缩, ROM 中运行3.VxWorks在存储介质中的存放方式5启动5.1启动概述1.Bootrom 的启动最少的系统初始化,要紧用于启动装载VxWorks image.通常有压缩与不压缩两种形式,如bootrom与boot_uncmp.与VxWorks image的区别在于一个Bootrom 调用bootConfig.c,而VxWorks调用usrConfig.c.文件romInit.s中的romInit()---->文件bootInit.c中的romStart()---->文件bootConfig.c中的usrInit()----->sysHwInit()----->usrKernelInit()----->KernelInit(usrRo ot,...)其中 /target/config/all/bootConfig.c是Boot ROM设置模块.用于通过网络加载VxWorks image.usrRoot()---->bootCmdLoop(void)命令行选择,或者autobooting----->bootLoad(pLine, &entry)加载模块到内存(网络,TFFS,TSFS...)----->netifAttach()---->go(entry)----->(entry)()从入口开始执行,不返回.•各个函数的要紧作用romInit()-----power up,disable interrupt,put boot type on thestack,clears caches.romStart()-----load Image Segments into RAM.usrInit()-----Interrupt lock out,save imformation about boot type,handle all the Initialization before the kernel is actually started,then starts the kernel execution to create an initial task usrRoot().This task completes the start up.sysHwInit()-----Interrup locked,Initializeshardware,registers,activation kernelKernelInit(usrRoot,...)-----•Initializes and starts the kernel.•Defines system memory partition.•Activates a task tUsrRoot to complete initalization.•Unlocks inierrupts.•Uses usrInit()stack.usrRoot()•初始化内存分区表(memory partition library)•初始化系统系统时钟(system clock)•初始化输入输出系统(I/O system)----可选•Create devices----可选•设置网络(Configure network)--------可选•激活WDB目标通信(Activate WDB agent)---------可选•调用程序(Activate application)2.VxWorks的启动1)Loadable VxWorks的启动a)使用Bootrom进行最小系统起动b)加载程序段、数据段、BBS段c)跳转到RAM中运行的VxWorks的启动(详见下面)2)VxWork_ROM的VxWorks启动1.ROM中运行的VxWorks的启动VxWorks在ROM中运行,即写入ROM中的VxWorks是非压缩的,不需要解压,系统直接跳到ROM的首地址,运行VxWorks.注意:ROM运行的VxWorks并不支持所有的主扳,应以主扳手册为准.文件romInit.s中的romInit()---->文件bootInit.c中的romStart()---->文件usrConfig.c中的usrInit()----->sysHwInit()----->usrKernelInit()----->KernelInit(usrRo ot,...)VxWorks在ROM中运行要紧是为了节约RAM空间,以便应用程序有更大的空间运行.只把VxWorks image的data段复制到RAM的LOCAL_LOW_ADRS, text部分留在ROM并在ROM中执行.ROM中运行的VxWorks缺点是运行速度慢.2.RAM中运行的VxWorks的启动VxWorks在RAM中运行,即写入ROM中的Boot或者VxWorks Image是压缩的,需要先解压copy所有的text与data到RAM的LOCAL_LOW_ADRS中,下面sysInit()要紧是初始化RAM用的,系统直接跳到RAM的首地址,运行VxWorksusrInit()前面不压缩,即romInit(),romStart()不能压缩.文件romInit.s中的romInit()---->文件bootInit.c中的romStart()---->sysaLib.s中的sysInit()---->文件usrConfig.c中的usrInit()----->sysHwInit()----->usrKernelInit()----->KernelInit(usrRo ot,...)RAM运行的Boot或者VxWorks image的text段或者data段会从ROM复制到RAM,在RAM中运行.其中usrRoot()是VxWorks启动的第一个任务,由它来初始化 driver,network等描述:romInit.s first execute in flash,minal initiliz,then jump to romStart.romStart()开始装载与解压image到RAM,sysaLib.s是在RAM中执行的第一个函数.。
arm cortex 的启动流程ARM Cortex是一种高性能的处理器架构,广泛应用于各种嵌入式系统中。
在使用ARM Cortex处理器时,启动流程是非常重要的一步,它决定了系统的稳定性和可靠性。
下面我们来详细了解一下ARM Cortex的启动流程。
ARM Cortex处理器的启动流程可以分为两个阶段:复位阶段和启动阶段。
在复位阶段,处理器会执行一系列的初始化操作,包括清除寄存器、初始化时钟、设置中断向量表等。
在启动阶段,处理器会加载操作系统或应用程序,并开始执行。
在复位阶段,处理器会首先执行复位向量,这是一个特殊的地址,指向处理器的复位程序。
复位程序会执行一系列的初始化操作,包括清除寄存器、初始化时钟、设置中断向量表等。
其中,中断向量表是一个非常重要的数据结构,它包含了所有中断的入口地址。
在初始化时,处理器会将中断向量表加载到内存中,并设置中断向量表的地址。
在启动阶段,处理器会加载操作系统或应用程序,并开始执行。
在ARM Cortex处理器中,启动代码通常是由Bootloader程序完成的。
Bootloader程序是一个小型的程序,它负责加载操作系统或应用程序,并将控制权转交给它们。
在启动过程中,Bootloader程序会执行一系列的初始化操作,包括初始化内存、初始化外设等。
然后,它会加载操作系统或应用程序,并将控制权转交给它们。
在ARM Cortex处理器中,启动代码通常是由汇编语言编写的。
汇编语言是一种低级语言,它可以直接操作处理器的寄存器和内存。
在编写启动代码时,需要非常小心,确保代码的正确性和可靠性。
同时,还需要考虑处理器的架构和特性,以便充分发挥处理器的性能和功能。
ARM Cortex处理器的启动流程是非常重要的一步,它决定了系统的稳定性和可靠性。
在编写启动代码时,需要非常小心,确保代码的正确性和可靠性。
同时,还需要考虑处理器的架构和特性,以便充分发挥处理器的性能和功能。
常用Cortex-M汇编指令附录1列出了常用的Cortex-M汇编指令,包括:数据操作指令、转移指令、存储器数据传送指令、异常及其他指令等,上述每一类指令都按照16位指令和32位指令分别讲解。
1. 数据操作指令表1.1 16位数据操作指令SUB <Rd>, <Rn>, <Rm> Rd= Rn-RmSUB(减法)SUB SP, #<imm7> * 4 SP-= imm7*4TST(测试)TST <Rn>, <Rm> 执行Rn & Rm,并根据结果更新标志位REV <Rd>, <Rn> Rd=Rn字内的字节顺序反转REV(反转)REVH/REV16(反转)REV16 <Rd>, <Rn> Rd=Rn两个半字内的字节顺序反转SXTB(字节提取扩展符号位)SXTB <Rd>, <Rm> 从寄存器Rm中提取字节[7:0],传送到寄存器Rd中,并用符号位扩展到32位SXTH(半字提取扩展符号位)SXTH <Rd>, <Rm> 从寄存器Rm中提取半字[15:0],传送到寄存器Rd中,并用符号位扩展到32位UXTB(字节提取扩展零位)UXTB <Rd>, <Rm> 从寄存器Rm中提取字节[7:0],传送到寄存器Rd中,并用零位扩展到32位UXTH(半字提取扩展零位)UXTH <Rd>, <Rm> 从寄存器Rm中提取半字[15:0],传送到寄存器Rd中,并用零位扩展到32位表1.2 32位数据操作指令操作,Rm 的值不变LSL (逻辑左移) LSL{S}.W <Rd>, <Rn>, <Rm> Rd= Rn<<Rm LSR (逻辑右移) LSR{S}.W <Rd>, <Rn>, <Rm> Rd= Rn>>Rm MLA (乘加) MLA.W <Rd>, <Rn>, <Rm>, <Racc> Rd= Racc+Rn*Rm MLS (乘减) MLS.W <Rd>, <Rn>, <Rm>, <Racc> Rd= Racc-Rn*RmMOVW.W <Rd>, #<imm16> 将16位立即数传送到Rd 的低半字中,并把高半字清零MOVW (加载) MOVT (加载) MOVT.W <Rd>, #<imm16> 将16位立即数传送到Rd 的高半字中,Rd 的低半字不受影响 MUL (乘法) MUL.W <Rd>, <Rn>, <Rm> Rd= Rn*Rm ORR{S}.W <Rd>, <Rn>, #<imm12 Rd= Rn | imm12ORR{S}.W <Rd>, <Rn>, <Rm>{, <shift>} 先移位Rm ,然后Rd= Rn | 新Rm ORN{S}.W <Rd>, <Rn>, #<immed12) Rd= Rn | ~imm12ORR (按位或) ORN (按位或) ORN{S}.W <Rd>, <Rn>, <Rm>{, <shift>} 先移位Rm ,然后Rd= Rn | ~新Rm RBIT (位反转) RBIT.W <Rd>, <Rm> Rd=Rm 按位反转后的值 REV.W <Rd>, <Rm> Rd=Rm 字内的字节顺序反转 REV16.W <Rd>, <Rn> Rd=Rn 每个半字内的字节顺序反转 REV (反转)REVH/REV (16反转) REVSH (反转) REVSH.W <Rd>, <Rn> Rd=Rn 低半字内的字节反转后再符号扩展ROR (循环右移) ROR{S}.W <Rd>, <Rn>, <Rm> Rd= Rn 循环右移Rm 位 RRX (带进位循环右移一位)RRX.W Rd, RnRd = (Rn>>1)+(C<<31)SBFX (带符号位段提取)SBFX.W <Rd>, <Rn>, #<lsb>, #<width> 抽取Rn 中以lsb 位为最低有效位,共width 宽度的位段,并带符号扩展到Rd 中 SDIV (带符号除法) SDIV<c><Rd>,<Rn>,<Rm>Rd= Rn/RmSMLAL (带符号64位乘加)SMLAL.W <RdLo>, <RdHi>, <Rn>, <Rm> RdHi:RdLo+= Rn*Rm SMULL 带符号64位乘法SMULL.W <RdLo>, <RdHi>, <Rn>, <Rm> RdHi:RdLo= Rn*RmSSAT (带符号数饱和运算) SSAT<C><Rd>, #<imm>, <Rn>{, <shift>} 先移位Rn ,再把Rn 的低imm 位执行带符号饱和操作,并把结果带符号扩展后写到RdSBC{S}.W <Rd>, <Rn>, #<imm12>Rd= Rn- imm12-C SUB{S}.W <Rd>, <Rn>, #<imm12> Rd= Rn-imm12SUB{S}.W <Rd>, <Rn>, <Rm>{, <shift>} 先移位Rm ,Rd= Rn-新Rm SBC (减法) SUB (减法) SUBW (减法) SUBW.W <Rd>, <Rn>, #<imm12> Rd= Rn-imm12SXTB (带符号扩展) SXTH (带符号扩展)SXTB.W <Rd>, <Rm>{,ROR #<imm>}先循环移位Rm ,然后取出Rm 的低8位,带符号扩展到32位,并存储到RdSXTH.W <Rd>, <Rm>{,ROR #<imm>}先循环移位Rm ,然后取出Rm 的低16位,带符号扩展到32位,并存储到RdTEQ.W <Rn>, #<imm12>Rn 与imm12按位异或,并根据结果更新标志位TEQ (按位异或)TEQ.W <Rn>, <Rm>{, <shift>} 先移位Rm ,然后 Rn 与Rm 按位异或,并根据结果更新标志位 TST.W <Rn>, #<imm12)>Rn 与imm12按位与,并根据结果更新标志位TST (按位与)TST.W <Rn>, <Rm>{, <shift>}先移位Rm ,然后 Rn 与Rm 按位与,并根据结果更新标志位UBFX (抽取) UBFX.W <Rd>, <Rn>, #<lsb>, #<width> 抽取Rn 中以lsb 位为最低有效位,共width 宽度的位段,并无符号扩展到Rd 中UDIV (无符号除法) UDIV<c><Rd>,<Rn>,<Rm>Rd= Rn/RmUMLAL (无符号64位乘加)UMLAL.W <RdLo>, <RdHi>, <Rn>, <Rm> RdHi:RdLo+= Rn*Rm UMULL (无符号64位乘法)UMULL.W <RdLo>, <RdHi>, <Rn>, <Rm> RdHi:RdLo= Rn*RmUSAT <c><Rd>, #<imm>, <Rn>{, <shift>} 先移位Rn ,再把Rn 的低imm 位执行带符号饱和操作,将结果无符号扩展后写到Rd 中UXTB.W <Rd>, <Rm>{, <rotation>}先循环移位Rm ,然后取出Rm 的低8位,无符号扩展到32位,并存储到RdUSAT (无符号扩展) UXTB (无符号扩展) UXTH (无符号扩展)UXTH.W <Rd>, <Rm>{, <rotation>}先循环移位Rm ,然后取出Rm 的低16位,无符号扩展到32位,并存储到Rd2. 转移指令表1.3 16位转移指令CBZ <Rn>, <label> 比较结果为零时跳转CBZ (比较转移)CBNZ(比较转移)CBNZ <Rn>, <label> 比较结果不为零时分支IT<cond> 以下面一条指令为条件IT<x><cond> 以下面两条指令为条件IT(条件转移)IT<x><y><cond> 以下面三条指令为条件IT<x><y><z><cond> 以下面四条指令为条件表1.4 32位转移指令3. 存储器数据传送指令表1.5 16位存储器数据传送指令STRB <Rd>, [<Rn>, #< offset5>] *( (U8*) (Rn+offset5) ) = (U8)Rd STRB(将寄存器中的低字节存储到存储器中)STRB <Rd>, [<Rn>, <Rm>] *( (U8*) (Rn+Rm) ) = (U8)Rd LDMIA(多字加载)LDMIA <Rn>!, <register> 多个连续的存储器字加载STMIA(多字存储)STMIA <Rn>!, <registers> 将多个寄存器字保存到连续的存储单元中,首地址由Rn给出,每保存完一个Rn+4PUSH <registers> 若干寄存器压栈PUSH(压栈)PUSH <registers, LR> 若干寄存器和LR压栈POP <registers> 若干寄存器出栈POP(出栈)PUSH <registers, PC> 若干寄存器和PC出栈表1.6 32位存储器数据传送指令中LDRSH.W <Rxf>, [PC, #+/–< offset12>] 加载PC+/–offset12地址处的半字,并带符号扩展到Rxf 中LDRSB.W <Rxf>, [<Rn>, #< offset12>]加载Rn+ offset12地址处的字节,并带符号扩展到Rxf 中LDRSB.W <Rxf>. [<Rn>], #+/-< offset8>加载Rn 地址处的字节,并带符号扩展到Rxf 中,然后Rn+/-= offset8LDRSB.W <Rxf>, [<Rn>, #<+/–< offset8>]!先Rn+/-= offset8,再加载新Rn 地址处的字节,并带符号扩展到Rxf 中LDRSB.W <Rxf>, [<Rn>, <Rm>{, LSL#<shift>}]先把Rm 按要求左移0、1、2、3位,再加载Rn+新Rm 地址处的字节,并带符号扩展到Rxf 中 LDRSB (加载字节并扩展符号位)LDRSB.W <Rxf>, [PC, #+/–< offset12>]加载PC+/- offset12地址处的字节,并带符号扩展到Rxf 中LDRD.W <Rxf>, <Rxf2>, [<Rn>, #+/–<offset8>*4]{!}读取Rn 地址加上8位偏移量乘以4处的双字到Rxf(低32位), Rxf2(高32位),前索引。
C6000嵌入汇编C与汇编对照及功能说明1.求绝对值函数(1) _abs()C代码: int _abs(int src)汇编: ABS功能: 求32位数据的绝对值(2) _labs()C代码: int _labs(long src)汇编: ABS功能: 求40位数据的绝对值(3) _abs2()C代码: int _abs2(int src)汇编: ABS2功能:同时求高16位和低16位的绝对值,即return[31:16] = |src[31:16]|return[15: 0] = |src[15: 0]|2.运算指令(1) _add2()C代码: int _add2(int src1,int src2)汇编: ADD2功能: 同时进行src1,src2的高16位和src1,src2的低16位相加,忽略任何进位,即return[31:16] = src1[31:16] + src2[31:16]return[15: 0] = src1[15: 0] + src2[15: 0](2) _sadd()C代码: int _sadd(int src1,int src2)汇编: SADD功能:普通A+B的加法(3) _lsadd()C代码: long _lsadd(int src1,long src2)汇编: SADD功能: 32位数据加上40位数据,返回为40位数据(4) _add4()C代码: int _add4(int src1,int src2)汇编: ADD4功能: 同时进行src1和src2的每个对应Byte的4次加法,忽略任何进位,即 return[31:24] = src1[31:24] + src2[31:24]return[23:16] = src1[23:16] + src2[23:16]return[15: 8] = src1[15: 8] + src2[15: 8]return[ 7: 0] = src1[ 7: 0] + src2[ 7: 0]备注: src1,src2的每个8位数据当做signed数据使用(5) _sadd2()C代码: int _sadd2(int src1,int src2)汇编: SADD2功能:同时进行src1,src2的高16位和低16位相加,忽略任何进位.即return[31:16] = src1[31:16] + src2[31:16]return[15: 0] = src1[15: 0] + src2[15: 0]备注: src1,src2的每个16位数据被当做signed数据(6) _saddus2()C代码: int _saddus2(unsigned src1,int src2)汇编: SADDUS2功能: 执行和_sadd2一样的操作,但src1解释不同,见备注备注: src1的每个16位数据被当作unsigned数据,src2的每个16位数据被当作signed数据(7) _saddu4()C代码: unsigned _saddu4(unsigned src1,unsigned src2)汇编: SADDU4功能: 执行和_add4()一样的操作,但数据解释为unsigned,限值为0xff(8) _addsub()C代码: long long _addsub(int src1,int src2)汇编: ADDSUB功能:同时进行src1 + src2和src1 - src2操作,即hi32(return) = src1 + src2low32(return) = src - src2(9) _addsub2()C代码: long long _addsub2(int src1,int src2)汇编: ADDSUB2功能: 同时进行_add2()和_sub2()操作,即return[63:48] = hi16(src1) + hi16(src2)return[47:32] = low16(src1) + low16(src2)return[31:16] = hi16(src1) - hi16(src2)return[15:0] = low16(src1) - low16(src2)(10) _saddsub()C代码: long long _saddsub(unsigned src1,unsigned src2)汇编: SADDSUB功能: 同时执行add()和sub()操作,即return[63:32] = src1 + src2return[31:0] = src1 - src2(11) _saddsub2()C代码: long long _saddsub2(unsigned src1,unsigned src2)汇编: SADDSUB2功能:同时进行sadd2()和ssub2()操作,即return[63:48] = src1[31:16] + src2[31:16]return[47:32] = src1[15: 0] + src2[15: 0]return[31:16] = src1[31:16] - src2[31:16]return[15: 0] = src1[15: 0] - src2[15: 0](12) _ssub2()C代码: int _ssub2(unsigned src1,unsigned src2)汇编: SSUB2功能: 同时进行高16位和低16位的减法,即return[31:16] = src1[31:16] - src2[31:16]return[15: 0] = src1[15: 0] - src2[15: 0](13) _mpy2(),_mpy2llC代码: double(long long) _mpy2(int src1,int src2),long long _mpy2ll(intsrc1,int src2)汇编:功能:(15) _mpyhi(),_mpyhill()C代码: double _mpyhi(int src1,int src2),long long _mpyhill(int src1,int src2) 汇编: MPYHI功能: 执行16位* 32位操作,即return = src1[31:16] * src2[31: 0](15) _mpyli(),_mpylill()C代码: double _mpyli(int src1,int src2),long long _mpylill(int src1,int src2)汇编: MPYHI功能: 执行16位* 32位操作,即return = src1[15: 0] * src2[31: 0](16) _mpyhir()C代码: int _mpyhir(int src1,int src2)汇编: MPYHIR功能: 执行(16位* 32位>> 15)操作,即return = (src1[31:16] * src2[31: 0]) >> 15;备注: 结果看起来被四舍五入了,例如0x1122 * 0x55667788结果应该是0x0b6e4b17,但仿真结果为0x0b6e4b18(16) _mpylir()C代码: int _mpylir(int src1,int src2)汇编: MPYLIR功能: 执行(16位* 32位>> 15)操作,即return = (src1[15: 0] * src2[31: 0]) >> 15;备注: 结果看起来被四舍五入了,例如0x1122 * 0x55667788结果应该是0x0b6e4b17,但仿真结果为0x0b6e4b18(17) _mpy*u4(),_mpy*u4ll()C代码: double _mpysu4(int src1,int src2),long long _mpysull4(int src1,intsrc2)double _mpyu4(unsigned src1,unsigned src2),long long _mpyu4ll(unsigned src1,unsigned src2)汇编: MPYSU4MPYU4.M2X B4,A3,B5:A4功能:同时执行4个8位* 8位操作,即return[63:48] = src1[31:24] * src2[31:24];return[47:32] = src1[23:16] * src2[23:16];return[31:16] = src1[15: 8] * src2[15: 8];return[15: 0] = src1[ 7: 0] * src2[ 7: 0];(18) _smpy2(),_smpy2ll()C代码: double _smpy2(int src1,int src2),long long _smpy2ll(int src1,int src2) 汇编: SMPY2功能: 同时执行两个16位*16位操作,结果再左移1位,即return = ((src1[31:16] * src2[31:16] << 32) + (src1[15: 0] * src2[15: 0])) << 1;(19) _mpy32**()C代码: int _mpy32(int src1,int src2),long long _mpy32ll(int src1,int src2) long long _mpy32su(int src1,unsigned src2),long long_mpy32us(unsigned src1,int src2)long long _mpy32u(unsigned src1,unsigned src2)汇编: MPY32MPY32SU.M2X B4,A3,B5:A4MPY32US.M2X B4,A3,B5:A4MPY32U.M2X B4,A3,B5:A4功能: 执行32位* 32位操作(20) _mpy2ir()C代码: long long _mpy2ir(int src1,int src2)汇编: MPY2IR功能:返回如下结果return[63:32] = src1[31:16] * src2 >> 15return[31: 0] = src1[15: 0] * src2 >> 5备注: 每一部分可能被四舍五入(21) _gmpy()C代码: unsignd _gmpy(unsigned src1,unsigned src2)汇编: GMPY功能: 执行"Galois Field multiply"(22) _smpy**()C代码: int _smpy(int src1,int src2),int smpyh(int src1,int src2)int _smpyhl(int src1,int src2),int _smpylh(int src1,int src2)汇编: SMPY SMPYHSMPYHL SMPYLH功能: 执行16位*16位操作,结果再左移一位,限值结果为小于x80000000_smpy: return[31: 0] = src1[15: 0] * src2[15: 0] << 1_smpyh: return[31: 0] = src1[31:16] * src2[31:16] << 1_smpyhl:return[31: 0] = src1[31:16] * src2[15: 0] << 1_smpylh:return[31: 0] = src1[15: 0] * src2[31:16] << 1(23) _mpy**()C代码: int _mpy(int src1,int src2),int _mpyus(unsigned src1,int src2)int _mpysu(int src1,unsigned src2),unsigned _mpyu(unsigned src1,unsigned src2)汇编: MPY MPYUSMPYSU MPYU功能:返回src1[15: 0] * src2[15: 0]的结果(24) _mpyh**()C代码: int _mpyh(int src1,int src2),int _mpyhus(unsigned src1,int src2)int _mpyhsu(int src1,unsigned src2),int _mpyhu(unsigned src1,unsignedsrc2)汇编: MPYH MPYHUSMPYHSU MPYHU功能:返回src1[31:16] * src2[31:16]的结果(25) _mpyh*l*()C代码: int _mpyhl(int src1,int src2),int _mpyhuls(unsigned src1,int src2)int _mpyhslu(int src1,unsigned src2),int _mpyhlu(unsigned src1,unsigned src2)汇编: MPYHL MPYHULSMPYHSLU MPYHLU功能:返回src1[31:16] * src2[15: 0]的结果(26) _mpyl*h*()C代码: int _mpylh(int src1,int src2),int _mpyluhs(unsigned src1,int src2)int _mpylshu(int src1,unsigned src2),int _mpylhu(unsigned src1,unsigned src2)汇编: MPYLH MPYLUHSMPYLSHU MPYLHU功能:返回src1[15: 0] * src2[31: 16]的结果(27) _*ssub()C代码: int _ssub(int src1,int src2),long _lssub(int src1,int src2)汇编: SSUB.L2X B4,A3,B4功能: 执行src1 - src2操作,符号扩展为int或long(28) _subc()C代码:unsigned _subc(int src1,int src2)汇编: SUBC功能:未知!!(29) _sub2()C代码: int _sub2(int src1,int src2)汇编: SUB2功能:同时执行高16位和低16位减法,即return[31:16] = src1[31:16] - src2[31:16]return[15: 0] = src1[15: 0] - src2[15: 0](30) _sub4()C代码: int _sub4(int src1,int src2)汇编: SUB4功能:同时执行4个8位减法,即return[31:24] = src1[31:24] - src2[31:24]return[23:16] = src1[23:16] - src2[23:16]return[15: 8] = src1[15: 8] - src2[15: 8]return[ 7: 0] = src1[ 7: 0] - src2[ 7: 0](31) _subabs4()C代码: int _subabs4(int src1,int src2)汇编: SUBABS4功能:同时执行4个8位减法,再求绝对值,即 return[31:24] = |src1[31:24] - src2[31:24]|return[23:16] = |src1[23:16] - src2[23:16]|return[15: 8] = |src1[15: 8] - src2[15: 8]|return[ 7: 0] = |src1[ 7: 0] - src2[ 7: 0]|(32) _avg2()C代码: int _avg2(int src1,int src2)汇编: AVG2功能:计算两路16位平均值,四舍五入结果return[31:16] = (src1[31:16] + src2[31:16] + 1) / 2; return[15: 0] = (src1[15: 0] + src2[15: 0] + 1) / 2;(33) _avgu4()C代码: int _avgu4(int src1,int src2)汇编: AVGU4功能:计算四路8位平均值,四舍五入结果return[31:24] = (src1[31:24] + src2[31:24] + 1) / 2; return[23:16] = (src1[23:16] + src2[23:16] + 1) / 2; return[15: 8] = (src1[15: 8] + src2[15: 8] + 1) / 2; return[ 7: 0] = (src1[ 7: 0] + src2[ 7: 0] + 1) / 2;3.位操作指令(1) _clr()C代码: int _clr(unsined src,unsigned csta,unsigned cstb)汇编: CLR功能: 清除src上的位csta ~ 位cstb,即src[cstb:csta] = 0;备注: csta必须<= cstb,且保证< 32(2) _clrr()C代码: int _clrr(unsigned src,int shift)汇编: CLR功能: 清除src上的shift[ 9: 5] ~ shift[ 4: 0]位(3) _set()C代码: int _set(unsined src,unsigned csta,unsigned cstb)汇编: SET功能: 设置src上的位csta ~ 位cstb,即src[cstb:csta] = '1';备注: csta必须<= cstb,且保证< 32(4) _setr()C代码: int _setr(unsigned src,int shift)汇编: SET功能: 设置src上的shift[ 9: 5] ~ shift[ 4: 0]位为'1'(5) _sshl()C代码: int _sshl(int src,unsigned shift)汇编: SSHL功能: return[31: 0] = src << shift;备注: 有符号扩展功能(6) _rotl()C代码: int _rotl(unsigned src,unsigned shift汇编: ROTL功能: return[31: 0] = src << shift;备注:无符号扩展功能(7) __shlmb(),__shrmb()C代码: int _shlmb(int src1,int src2),int _shrmb(int src1,int src2) 汇编: SHLMB功能: shlmb-->return[31:0] = (src2 << 8) | src1[31:24]shrmb-->return[31:0] = (src2 >> 8) | (src1[7: 0] << 24)(8) __shr2(),_shru2()C代码: int _shr2(int src1,unsigned shift),int _shru2(unsigned src1,unsigned shift)汇编: SHR2功能: return[31: 16] = src1[31:16] >> shiftreturn[15: 0] = src1[15: 0] >> shift备注: 有符号数操作返回值会进行符号扩展(移出的位全部补1)(9) _sshvl(),_sshvr()C代码: int _sshvl(int src,int shift),int _sshvr(int src,int shift)汇编: SSHVL SSHVR功能: sshvl-->return[31: 0] = (src << shift) > MAX_INT?MAX_INT:(src << shift) sshvr-->return[31: 0] = (src >> shift) < MIN_INT?MIN_INT:(src >> shift)(10) _shfl()C代码: int _shfl(int src)汇编: SHFL功能:低16位嵌入到偶位,高16位嵌入到奇位,即return[31:0] = src[31]src[15]src[30]src[14]........src[16][src[0](11) _ext()C代码: int _ext(int src,unsigned lshift,unsigned rshift)汇编: EXT功能: return[31: 0] = (src << lshift) >> rshift;(12) _extr()C代码: int _extr(int src,int shift)汇编: EXT功能: return[31: 0] = (src << shift[ 9: 5]) >> shift[4: 0];(13) _extu()C代码: int _extu(int src,unsigned lshift,unsigned rshift)汇编: EXT功能: return[31: 0] = (src << lshift) >> rshift;(14) _extur()C代码: int _extur(int src,int shift)汇编: EXT功能: return[31: 0] = (src << shift[ 9: 5]) >> shift[4: 0];(15) _lmbd()C代码: unsigned _lmbd(int zero_or_one,int src)汇编: LMBD功能:从左到右查找该位是zero_or_one的位,返回该位置备注:zero_or_one必须为0或者1,为其他值无LMBD指令编译如src = 0x0fff0000,则_lmbd(0,src) == 0 /*D31为'0',所以返回0*/_lmbd(1,src) == 4 /*D27为'1',所以返回4*/(16) _*norm()C代码: unsigned _norm(int src),unsignd _lnorm(long src)汇编: NORM B4,B4功能: 未知(17) _bitc4()C代码: unsigned _bitc4(unsigned src)汇编: BITC4功能: 统计每个字节的'1'总数,4个总数合成unsigned返回备注:例如src = 0x01030507,因为4个字节分别有0x01,0x02,0x03,0x04个'1',所以返回为0x01020304(18) _bitr()C代码: unsigned _bitr(unsigned src)汇编: BITR功能: 反转所有的位,即return[31:0] = src[ 0:31]备注:例如src = '00010001000100010001000100010001',则返回值是'10001000100010001000100010001000'(19) _deal()C代码: unsigned _deal(unsigned src)汇编: DEAL功能: 所有偶位组合成一个16位数据,所有奇位组合成一个16位数据,返回该32位值,即return[31:16] = src[31,29,27, (1)return[15: 0] = src[30,28,26, 04.内存操作指令(1) _amem*()C代码: ushort& _amem2(void* ptr),const ushort _amem2_const(void* ptr) unsigned& _amem4(void* ptr),const unsigned& _amem4_const(void* ptr) long long _amem8(void* ptr),const long long& _amem8_const(void* ptr)double & _amemd8(void* ptr),const double& _amemd8_const(void* ptr)汇编: 略功能: 从对齐地址中读/写n字节数据,n = 以上的数字备注:读--->double val;char test[8] = {0,1,2,3,4,5,6,7};val = _amem2_const(&test) + _amem4_const(&test) +_amem8_const(&test);写--->_amem2(&test) = 0x0011;_amem4(&test) = 0x00112233;_amem8(&test) = 0x0011223344556677;(2) _mem*()C代码: ushort& _mem2(void* ptr),const ushort _mem2_const(void* ptr)unsigned& _mem4(void* ptr),const unsigned& _mem4_const(void* ptr)long long _mem8(void* ptr),const long long& _mem8_const(void* ptr)double & _memd8(void* ptr),const double& _memd8_const(void* ptr)汇编: 略功能: 从非对齐地址中读/写n字节数据,n = 以上的数字备注:读--->double val;char test[8] = {0,1,2,3,4,5,6,7};val = _mem2_const(&test) + _mem4_const(&test) + _mem8_const(&test); 写--->_mem2(&test) = 0x0011;_mem4(&test) = 0x00112233;_mem8(&test) = 0x0011223344556677;(3) _mvd()C代码: int _mvd(int src)汇编: MVD功能:利用4周期乘法流水线拷贝数据,return[31: 0] = src[31: 0]备注:这个需要和_mpy**()配合实现并行工作5.数据包装/转换指令(1) _hi**()C代码: unsigned _hi(double src),unsigned _hill(long long src)汇编:无功能:返回64位数据的高32位数据(2) _low**()C代码: unsigned _lo(double src),unsigned _loll(long long src)汇编:无功能:返回64位数据的低32位数据(3) _*to*()C代码: ulong _dtol(double src),unsigned _ftoi(float src)double _itod(unsigned hi32,unsigned low32),float _itof(unsigned src) long long _itoll(unsigned hi32,unsigned low32),double _ltod(long src) 汇编:无功能:各种数据类型互相转换(4) _sat()C代码: int _sat(long src2)汇编: SAT功能: 把40位long数据转成32位数据(5) _pack*2()C代码: unsigned _pack2(unsigned src1,unsigned src2),unsigned _packh2(unsigned src1,unsigned src2)汇编: PACK2 PACKH2功能: _pack2--->return[31:16] = src1[15: 0],return[15: 0] = src2[15: 0] _packh2-->return[31:16] = src1[31: 16],return[15: 0] = src2[31: 16](6) _pack*4()C代码: unsigned _packh4(unsigned src1,unsigned src2),unsigned _packl4(unsigned src1,unsigned src2)汇编: PACKH4 PACKL4功能:返回交替的4字节数据备注: 如src1 = 0x11223344,src2 = 0x55667788,则_packh4(src1,src2)返回0x11335577_packl4(src1,src2)返回0x22446688(7) _pack**2()C代码: unsigned _packhl2(unsigned src1,unsigned src2),unsigned _packlh2(unsigned src1,unsigned src2)汇编: PACKHL2 PACKLH2功能: _packhl2--->return[31:16] = src1[31: 16],return[15: 0] = src2[15: 0] _packlh2-->return[31:16] = src1[15: 0],return[15: 0] = src2[31: 16](8) _spack2()C代码: int _spack2(int src1,int src2)汇编: SPACK2功能:把两个32位数据格式化成16位数据,然后组合成32位数据备注: return[31: 16] = (int16_t)src1return[15: 0] = (int16_t)src2(9) _spacku4()C代码: unsigned _spacku4(int src1,int src2)汇编: SPACKU4功能:把4个16位数据格式化成4个8位数据,形成32位数据返回备注: return[31:24] = (unt8_t)src1[31:16]return[23:16] = (unt8_t)src1[15: 0]return[15: 8] = (unt8_t)src2[31:16]return[ 7: 0] = (unt8_t)src1[15: 0](10) _swap4()C代码: unsigned _swap(unsigned src)汇编: SWAP4功能:大小端数据转换备注: return[31:24] 和return[23:16] 交换return[15: 8] 和return[ 7: 0] 交换(11) _unpkhu4()C代码: unsigned _unpkhu4(unsigned src)汇编: UNPKHU4功能: 把两个高8位数据转成两个16位数据备注:return[31:16] = (uint16_t)src[31:24]return[15: 0] = (uint16_t)src[23:16](12) _unpklu4()C代码: unsigned _unpklu4(unsigned src)汇编: UNPKHU4功能: 把两个低8位数据转成两个16位数据备注:return[31:16] = (uint16_t)src[15: 8]return[15: 0] = (uint16_t)src[ 7: 0]6.比较/杂项指令(1) _cmpeq*() _cmpgt*()C代码: int _cmpeq2(int src1,int src2),int _cmpeq4(int src1,int src2)int _cmpgt2(int src1,int src2),int _cmpgtu4(unsigned src1,unsigned src2) 汇编: CMPEQ2 CMPEQ4CMPGT2 CMPGT4功能: 同时比较两个16位数据或者4个8位数据,比较结果在返回值的低2位或低四位中备注:_cmpeq2(0x11223344,0x11220000)返回为0x02_cmpeq4(0x11223344,0x00223344)返回为0x07_cmpgt2(0x00001111,0x0000ffff)返回为0x01_cmpgtu4(0x0000ffff,0x0000aaaa)返回0x03(2) _xpnd*()C代码: int _xpnd2(int src),int _xpnd4(int src)汇编: XPND2 XPND4功能: _xpnd2()把src的低2位逻辑值扩展为2个16位逻辑值_xpnd4()把src的低4位逻辑值扩展为4个8位逻辑值备注:_xpnd*()一般和_cmp*()配合实现逻辑扩展_xpnd2(0x01) = 0x0000ffff_xpnd2(0x03) = 0xffffffff_xpnd2(0x00) = 0x00000000_xpnd4(0x00) = 0x00000000_xpnd4(0x08) = 0xff000000_xpnd4(0x07) = 0x00ffffff_xpnd4(0x01) = 0x000000ff。
嵌入式启动流程:汇编代码解析
1.加载引导程序
嵌入式系统在加电后,第一个执行的程序通常是引导程序(Bootloader)。
它负责从存储设备中加载并执行后续的程序。
引导程序通常在启动时进行硬件设备的自检,然后从特定的存储位置(如闪存或RAM)加载后续程序。
引导程序通常使用汇编语言编写,因为它需要在硬件级别进行操作。
它负责初始化CPU、内存、硬盘等硬件设备,并确保系统环境满足后续程序的要求。
2.初始化硬件设备
在引导程序之后,接下来的任务是初始化硬件设备。
这包括初始化CPU、内存、硬盘、显示器等设备。
初始化硬件设备的过程包括设置设备的寄存器、配置设备的接口等。
在这个过程中,硬件设备被配置为适合后续程序运行的状态。
3.设置内存管理器
在硬件设备初始化完成后,接下来需要设置内存管理器。
内存管理器负责管理系统的内存资源,包括内存的分配、释放和保护。
内存管理器通常由操作系统内核提供,因此在加载操作系统内核之前,需要先初始化内存管理器。
4.加载操作系统内核
在内存管理器初始化完成后,可以加载操作系统内核。
操作系统内核是系统的核心部分,负责管理系统资源、调度应用程序的运行等。
操作系统内核通常被压缩并保存在存储设备中,因此需要先解压缩并加载到内存中。
然后,内核会进行自身的初始化,包括设置系统时钟、配置设备驱动等。
5.启动内核并初始化系统服务
在操作系统内核加载并初始化完成后,可以启动内核并初始化系统服务。
系统服务是指为应用程序提供支持的底层服务,如文件系统、网络服务等。
启动内核后,会执行一系列的系统初始化过程,包括设置系统环境变量、加载系统服务等。
这些过程完成后,系统就可以接受应用程序的请求并为其提供服务。
6.加载文件系统和应用程序
在系统服务初始化完成后,可以加载文件系统和应用程序。
文件系统是存储和管理文件数据的系统,应用程序则是为用户提供服务的程序。
文件系统通常被加载到内存中,并初始化为可用的状态。
然后,可以按需加载应用程序到内存中并执行。
在这个过程中,可能需要进行权限检查、资源分配等操作。
7.启动应用程序并进入用户界面
最后一步是启动应用程序并进入用户界面。
应用程序被加载到内存中并开始执行,用户界面则是应用程序与用户交互的界面。
用户界面可以是命令行界面或图形界面,具体取决于应用程序的需求和用户的偏好。
在用户界面中,用户可以与应用程序进行交互,如输入命令、查看输出等。