ARM接口编程笔记
arm笔记总结
qt + c++---------------------------------------------------嵌入式:1)资源受限(cpu + 外设); (参品定位)2)系统嵌入到cpu中, 不能随意删减, 更改;二进制语言:汇编语言:高级语言:cx86-linux-gccarm-linux-gcckernel:linux设备驱动; (内核设备驱动+裸板驱动) rootfs:(根文件系统)busybox文件(可执行文件, 配置文件, ...)appqt libc++ libcapi-----------------------kerneldevice driver-----------------------board driverarm:exynos4412 (消费类电子)cortex-a9 (armv7)裸板开发:硬件基础: 看懂原理图;语言基础: 看数据手册;开发语言: c 语言; 汇编语言;. 开发板: TINY4412(友善之臂)soc : 片上系统exynos4412cortex-a9 * 4AMBA总线控制器开发板资源介绍. DATASHEET (数据手册) 原理图soft (bootloader+kernel+rootfs+tools) . minicom安装:1) yum install minicom (有yum源)配置yum源:mount -o loop rhel-server-6.5-x86_64-dvd.iso /mnt/cp server.repo /etc/yum.repos.d/yum clean allyum list2) rpm -ivh lrzsz-0.12.20-27.1.el6.x86_64.rpmrpm -ivh minicom-2.3-6.1.el6.x86_64.rpm虚拟机设置为自动检测pc <-> usb <-> com0 <-> boardls /dev/ttyUSB0 --> usb接口链接成功;minicom -s上图为配置好(需要设置谁则按哪个字母可对其修改,修改好后按ENTRE键)Save setup as dfl----------------------------------------->保存为默认设置Exit ---------------------------------------->退出进入minicom. minicom使用ctrl + A <key>Z : 帮助Q : 退出W : 开启换行模式S : 发送文件. 烧写android系统到sd卡:. 搭建开发交叉编译环境:arm-linux-gcc -vash: arm-linux-gcc: command not found (没有交叉编译器)安装交叉编译器:tar xf arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz (拷贝应用)mkdir /usr/local/arm/mv opt/FriendlyARM/toolschain/4.5.1/ /usr/local/arm/vim /root/.bash_profilePATH=/usr/local/arm/4.5.1/bin:$PATH注销当前用户, 重新登录; (ctrl + alt + backspace)arm-linux-gcc -v (命令执行正常)yum install glibc.i686 (32bit c库). 交叉编译x86下编译, arm下运行程序;x86工具更全, 速度更快, ...;. 烧写bootloader(启动加载器)u-boot (开源bootloader)grub编译u-boot:tar xf uboot_tiny4412_0929.tar.gzcd uboot_tiny4412_0929make distcleanmake tiny4412_configchmod +x mkconfigmakechmod +x tools/* -R依赖zlib库yum install zlib.i686zlib.x86_64生成u-boot u-boot.bin ...烧写工具编译:make -C sd_fuse/烧写u-boot:准备一张>4GB SD卡和读卡器; 插入pc的usb接口;如果有自动挂载, 执行:umount /dev/sdb*cd sd_fuse/tiny4412/./sd_fusing.sh /dev/sdb (需要备份sd卡中的数据, 可能会丢失)^ (根据实际情况而定)/dev/sdb1 X(记住,sdb1属于分区,不是整张卡)^/dev/mmcblock0^ (sd卡槽)/dev/mmcblockp1 X(也不允许)烧写成功;64bit : 32bit5.56.5. 使用u-boot启动:拨动启动开关为sd/mmc启动(下拨)启动开发板(3s内按下任意键)TINY4412 # <-- u-boot 命令行提示符号u-boot命令:helphelp printenvprintenvbaudrate=115200 波特率uartbootargs=console=ttySAC0,115200n8 androidboot.console=ttySAC0 lcd=S70启动kernel的参数;^ kernel输出设备console -> /dev/ttySAC0^ android输出设备^显示屏的分辨率480*800bootcmd=movi read kernel 0 40008000;movi read rootfs 0 41000000 400000;bootm 40008000 410000003s后自动启动执行的命令^kernel分区^sd/mmc^内存地址40008000^ramdisk^启动内核bootdelay=3 Ns后自动启动ethaddr=00:40:5c:26:0a:5bgatewayip=192.168.0.1ipaddr=192.168.0.20netmask=255.255.255.0serverip=192.168.0.10printenv bootdelaysetenvsetenv bootdelay 10setenv bootdelay 0 自动启动系统bootcmdsetenv abc 123 添加设置abc 变量setenv abc 删除变量abcsaveenvresetfdiskfdisk -p 0fdisk -c 0 320 806 518fatformatfatformat mmc 0:1fastboot[Partition table on MoviNAND]ptn 0 name='fwbl1' start=0x1000A len=N/A (use hard-coded info.(cmd: movi))ptn 1 name='bl2' start=N/A len=N/A (use hard-coded info. (cmd:movi))ptn 2 name='bootloader' start=N/A len=N/A (use hard-coded info.(cmd: movi))ptn 3 name='tzsw' start=N/A len=N/A (use hard-coded info. (cmd:movi))ptn 4 name='kernel' start=N/A len=N/A (use hard-coded info. (cmd:movi))ptn 5 name='ramdisk' start=N/A len=0x6800(~27262976KB) (usehard-coded info. (cmd: movi))ptn 6 name='system' start=0x1000A len=0x51888(~341975040KB) <-android系统ptn 7 name='userdata' start=0x1000A len=0xC9FAE(~847165440KB)ptn 8 name='cache' start=0x1000A len=0x81B64(~544051200KB)ptn 9 name='fat' start=0x1000A len=0x5A736E(~1775089664KB). 开始烧写android系统board:fastbootpc:烧写工具:cd tools/tar xf android_tools.tgzcd usr/local/bin/cp * /usr/local/bin/cd ../../../rm -rf usrcd ../烧写内核:cd android_0822/fastboot flash kernel zImage 烧写内核mmc start Count0 1057 12288fastboot -w 格式化userdata cachefastboot flash ramdisk ramdisk-u.img 烧写内存文件系统android 的/目录start Count13345 361fastboot flash system system.img 烧写android文件系统start???设置启动参数uboot:setenv bootargs console=ttySAC0,115200n8 androidboot.console=ttySAC0 lcd=S70saveenv重启board. android系统下执行c 代码传输工具:pc:adb push 1.c /cache 上传adb pull /cache/a.out . 下载编译和执行:pc:arm-linux-gcc -static 1.c -o 1 (android默认不支持c代码运行,使用静态编译)adb push 1 /cache board:./1。
ARM入门笔记
简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。
为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所以叫笔记而不是文章,是因为它们完全是本人个人学习经验的总结,而这些经验都来自于其他前辈的无私奉献,在这里对这些乐于发表自己经验的前辈致以由衷的感谢!现在我把这些前辈的文章经过自己的理解写出来一方面是对于他们的尊重,另一方面也希望觉得本人的笔记有参考意义的朋友把这种精神继续传下去。
再次声明,本人确实是个菜鸟,现在手头的板子是自己画的,以RT&ZQ的板子为底版,对部分电路进行了改动。
比如加入了SD卡,IIC总线键盘,触摸屏,GPS,GPRS等等。
并对LCD接口进行改造,使之完全适合手头的SHARP液晶。
把网络,串口,USB这些调试用接口都外扩了,目的是使主板尽量小(目前第一版为了调试方便,主板特意画的比较大)。
但是存储部分(RAM ROM)没有做任何变动,在这里对RT&ZQ致谢!这块板子是本人第二个板子(第一块是个接口板,30根线。
)所以走线,设计都经不起推敲,但是同样非常希望大家能够指点!板子基本元件清单说一下吧,方便其他人参考CPU:44B0RAM:HY57V641620ROM:AM29LV160NET:8019USB:D12KEY:ZLG7290LCD:SHARP LM7M632目前为止本人做的工作1板子的硬件调试是跟着软件来的2ADS AXD调试环境搭建3FLSH烧写笔记4UBOOT移植笔记5UCLINUX编译下载简单笔记6字符设备驱动开发C工程模板使用说明本模板用于使44B0运行C程序一般说来汇编用来初始化之后跳到C入口MAIN函数处一、关于工程文件1、本目录下建工程文件(.MCP)2、工程文件至少包含3个文件44binit.s44blib_a.s*.c(自己的c文件)3、44binit.s中开头部分INCLUDE两个文件MEMCFG.S Option.s用于基本设置注意这两个文件的存放目录,即让INCLUDE找到它们4、以上文件除自己的c文件之外均为三星公版,不需修改二、关于CodeWarrior设置1、DebugRel Setting里一般设置几项1)Target Setting->Linker里选ARMLinker用于设置连接2)Target Setting->Post-Linker选ARM fromELF用于生成FLASH烧录代码(只在RAM里运行而不烧录则不用)3)ARM Linker->RO BASE里添地址根据板子来,这板子上RAM接的NSCS6,地址0XC000000-0XC7FFFFF;FLASH接的NSCS0,地址0X00000-0XFFFFF地址分配原理见44B0数据手册内存管理那章的内存分配图想在RAM里调试就添0XC000000(比如0XC008000)的地址但是注意的是地址不要添过界,比如想在RAM里调试却添0X00000000程序可以进入C 代码但没法运行再有想生成用于烧写得FLASH代码RO地址就需要设置为0X0000000开始的而且LAYOUT 中也必须设置44BINIT.O为初始加载文件以上FLASH测试结论经FLASHPGM测试而且FLASHPGM不支持BIN文件只支持INTEL得HEX文件4)RW可以添可以不添一般RO解释为数据段,RW解释为数据段有时高兴了就添上0XC100000(RAM调试时)5)ARM Linker->OPTION->Image entry point选择0xc000000(RAM调试时)6)ARM Linker->Layout->Object/Symbol里可以添工程起始程序44BINIT.O注意是.O不是.S 和.0(零)也可以不添三、AXD设置1)按照BANYANGT或者ARM7正确设置调试代理BANYANGT、ARM7、H-JTAG都是代理,装哪个无所谓,一般认为BANYANGT好,但无论哪个调试之前必须运行代理2)在option->configure interface里在session file选择44b0.ini这个文件是初始化44b0寄存器的,必须运行3)Options->Configue Target里本来有两项,上面上是硬件调试,下面是软件仿真(在电脑上仿真)用ARM7就改第一项(按照ARM7说明改),用BANYANGT就按照BANYANGT说明在下面再加个BANYANGT的驱动4)在general标签页选择attach,然后确定,最后在file->save session,关闭AXD(在CodeWarrior 里一DEBUG就自动打开)四、关于JTAG1)JTAG一般有几种SDT和WIGGLER我的是WIGGLER的,两者区别主要在并口25针定义不一样(不算复位脚),与板子上JTAG相连的脚不是区分JTAG类型的标志只要和44B0对上就行2)JTAG小板上与44B0大板上JTAH跳线RAM调试时都不用接烧FLASH才用到3)网上流传的JTAG小板上也有不用RST信号的版本,无所谓,RST信号不是标准的五、另外开始的时候犯了低级错误,没设置OM123跳线导致晶体不阵~~~其他的看万龙的ARM开发板使用手册,写的还不错模板:user94/mamajinco/upload/825806664.rar这部分可能过于简单,很少有人写,但是对于不了解ARM开发过程的人真的简单吗?我是菜鸟,在这卡了3天:)一般说来有几种方法,1)板子原来的BOOTLOADER程序或者为烧写而编写的专用ADS程序比较高级而快速的方法,很多现成的开发板都用这种方法(相对来说有实力的公司),此状态下CPU是运行的,所以速度快。
ARM第一天笔记
[17]Cortex-A寄存器组织概要
(1)R0-R7每种模式都是共有
(2)R8-R12只有FIQ模式是私有的
(3)R13(sp) 和 R14(lr) 每种模式下都是独有的。
(4)R15(PC) 和 CPSR 每种模式共有
(5)SPSR 每种模式下都是独有的。 (系统模式和用户模式没有)
[1]软件和硬件的对应关系
软件 :0和1
电路 :低电平和高电平
半导体 :导通或者截止
软件和芯片的接口:寄存器
[2] 二极管特性:
(1)单向导电 --- 整流
(2)反向击穿 --- 稳压管
(3)发光特性 --- LED
(4)电容特性 --- RAM
[3]RAM分类
2--改变处理器模式进入相应的异常模式M[4:0]
3--设置中断禁止位禁止相应中断 (如果需要)
(3)保存返回地址当前PC到 LR_<mode>
(4)设置 PC 为相应的异常向量
异常返回的步骤:
(1)从 SPSR_<mode>恢复CPSR
(2)从LR_<mode>恢复PC
例子:int a;
对a的第6为置0 a &=(~(1<<6)); //a &= 0xffffffbf
对a的第6为置1 a |=(1<<6); //a |= 0x40
对a的第6为取反 a ^=(1<<6); //a ^= 0x40
练习:写出带参数的宏,对寄存器x的第y位置0,对寄存器x的第y位置1
V = ALU operation oVerflowed
ARM学习笔记
2012-2-9ARM流水线指令集写一些汇编程序.ARM的异样:与中断的区别片内外设,2410ARM9.AT:ARM926E-SAM9645.ARM是一家英国的公司,生产RISC:精简指令集的.(CISC:复杂指令集)对入嵌入式行业来说,主频高不是一切.同样主频下,CISC的执行效率要远远低于RISC,ARM的指令长度是固定的4个字节.而CISC对取来的命令还要进行指令长度的判断(主频不是一切论据1).比较流行的:51,PIC,430,AVR,MIPS,SUN,PPC,ARM的CPU.架构更换:指令集,开发环境.会浪费大量的时间与金钱.ARM后来居上的原因是:指令集完全兼容,但是外设的操作不同,但依然降低了很多公司的前期投入.ARM公司技术研讨会,5月1,10月1,一年两次.ARM约定:Byte: 8bitHALFWORD: 16bit 2ByteWORD: 32bit 4Byte大部分ARMcore提供:ARM指令集 32bitThumb指令集 16bitJazelle cores支持Java bytecode :意味着使用此类CPU之后不再需要JAVA虚拟机,就有更高的效率,(主频不是一切,论据2)7个基本工作模式:划分模式是了资源控制.最主要的资源是寄存器的资源.(牢记) 寄存器是存在与核内:CORE->寄存器->cache->存储器.寄存器的资源很少.而内核访问内存必须通过中间的寄存器 (猜测,若ADD R2,R2,R1指令,如果全写地址没有办法得到32位的指令长度)USER:应用程序90%FIQ:[快速中断]中断是有外设提出的请求,高优先级, (中断的优先级:当低优先级的中断在执行时,高优先级的中断可以打断)而在ARM中则FIQ只能有一个,不允许有一个更高优先级的打断,FIQ里面资源独立,与IRQ不重复,所以进入中断时要置位FIQ禁止.IRQ:[中断]低优先级中断,同上,IRQ也只能有一个,资源独立.Supervison:管理模式,当复位或软件中断指令执行时将会进入这种模式,CPU复位涵盖外设复位与内核复位.复位后CPU内的所有资源全部回到原始状态(管理模式,ARM状态),会引起复位的是:上电复位人为复位欠压/过压复位 CPU的工作电压. 依赖片内外设看门狗复位: 也依赖片内外设,是由看门狗的定时器来产生复位源.软件中断:系统调用是通过软件中断实现的,软件中断是拿SWI实现的,一个系统调用一个SWI,有对应的软件中断号,C库在用户空间,应用程序都在用户模式下工作的,而要陷入内核(LINUX)是切换到管理模式,因为user模式下不能访问到管理模式下的资源,所以要有SWI指令来使得能进入管理模式来做一些必须进入此模式下才能访问的资源,软件中断为用户访问受限资源提供接口.Abort:终止模式,存取异常时进入,是内核存取数据,内核需要的数据有两种,用户数据,指令数据指令数据失败:指令终止模式用户数据失败:用户数据终止模式Undef:未定义指令不等于错误的指令,如2410使用的是V4T的指令集版本,而编写指令是用V5TE的指令集来编写的,或多或少有独有的指令集,在仅支持V4T的内核上跑, System:使用和User模式相同寄存器集的特权模式,虽然共用相同的资源,但能访问在user模式下不能访问的资源异常不能被屏蔽,而中断可以.中断是异常的一种,异常的范围更广,涵盖了中断.异常产生时,必须为ARM状态,由内核自动转换.非特权模式不能由异常(异常包括中断,未定义命令等)进入,特权模式由特定异常产生时进入,1非特权,6特权(5异常,1非异常system)寄存器 R0~R15+CPSR+SPSR,其中R0~R7+R15在物理上与其他模式共享,而R8~R14为SPSR用来保存产生异常前的CPSR(当前程序的状态)SP:堆栈指针LR:链接寄存器,用来保存PC的,为了返回进入异常前状态.Thumb低位寄存器:R0~R7高位寄存器:R8~R14CPSR: USER模式下不具备往CPSR写的权限31:N = 1时,说明ALU结果是一个负数,ALU:算数逻辑单元.30:Z = 1时,说明ALU结果是0.29:C = 1时,说明ALU加法时有进位或减法时有借位,都会置1.28:V = 1时,说明ALU结果溢出时.默认情况下不影响标志位,在命令后加S来让结果影响标志位.27:Q = 1时,表示DSP扩展运算饱和状态 ARM 5TE/J架构支持.24:J = 1时,表示在Jazelle状态. ARM 5TE/J架构支持.7:IRQ = 1时,置1时,屏蔽所有IRQ中断.6:FIQ = 1时,置1时,屏蔽所有FIQ中断.5:T = 1时,ARM处理器的状态,等于0时处理器处于ARM状态,等于1时为Thumb状态,此值不由人为更改.4~0:Mode,表示了处理器处于哪种模式下,编程人员可以读,可以写,USER模式下不具备往CPSR写的权限,只能读,在特权模式下可以通过写此处的值来改变工作模式.程序指针PC:在ARM状态下,所有指令32bits宽,所以指令必须word字对齐,所以PC值由bits[31:2]决定,而bits[1:0]内的值目前无效(因为word对齐,一起跳转1个字长的长度,所以要加4,bits[1:0]里的值无效).0000 0000->0000 0100->0000 1000->0000 1100……在Thumb状态,所有指令16bits宽,所以指令必须halfword半字对齐,所以PC值由[31:1]决定,bits[0]无效在Jazelle状态,所有指令8bits宽.处理器会按字一次去4跳指令异常的处理(第三天的一个重点):以下均在ARM状态下.ARM core实现:内核自动实现,不用自己编写.并发执行,一个周期内完成.拷贝cpsr到spsr_mode设置适当的cpsr位:改变处理器状态进入ARM模式,异常模式内只能在此模式下工作,因为Thumb 没有返回原状态的指令(操作spsr)改变处理器模式进入相应的异常模式设置中断禁止位进制相应中断保存返回地址到LR_mode设置PC为相应的异常向量, 异常向量表是一个公共的入口,(有一部分高端映射没听明白,只有ARM9以上支持,以及ARM720T支持)(一般写的裸机系统从0x0开始放,而有了linux启动过之后用高端映射,到了0xffff0000开始放.)返回时:人为编写操作.也是一个周期内完成,并发执行从SPSP_mode恢复cpsr.从LR_mode恢复PC.字节序:小端:低地址存低位数据.大端:低地址存高位数据.在2006年之后使用了新的命名方法contexA:app,应用处理器.A5,A9都是双核.R:real-time实时.硬盘,M:MCU微控制单元.轻量级CPU.M0,M3,M4,核能跑50MH,而51只能1MH(F ost = 24M/12).高性能方向:TI(德州仪器)DSP出名:非对称式双核(ARM+DSP双核,DSP由ARM分配任务),SMP(对称式双核)Samsung:Freescale:moto原来的半导体部门.Marvell:Qualcomm高通:Nvidia:低功耗低成本的微控制器:M3:STM32系列意法半导体.第一个获得M3授权的公司.实时:R4所有ARM指令均为32bits,大部分为单周期指令,所有指令都可以条件执行,采用Load/Store架构(Load:数据从存储器到寄存器,store:数据从寄存器到存储器).EEPROM与FLASHROM具有通用ROM的特点,掉电不丢失数据,但是还具有可写功能.DMA直接内存访问,不用经过内核,源与目的的数据交流.但是需要DMA设备.B:PC+_32Mbyte,一跳转就不关心返回.BL:保存返回地址到LR,返回地址为当前执行指令的下一条指令的地址.对于非叶子结点的函数,LR必须压栈保存,否则只能返回一次跳转前的状态,而不能多次返回.协处理器:多达16个可定义协处理器,2410上有cp15,是有16个32位的寄存器,常用协处理器来作为ARM cache控制器,高端映射等.协处理器不在核内,属于片内外设.Thumb是16bits指令集:优化代码密度.提高窄内存操作性能.是ARM指令集的一个功能子集.缺点:条件执行不可用.源和目的寄存器相同只有地段寄存器可用常量大小受限制.内嵌的桶形移位不可用.Jazelle:是的ARM cores执行8bits的Java字节码95%的字节码执行使用硬件门电路(说明效率非常高).更高的性能增加的门电路<12KSOC概念,片上系统,是信息系统核心的芯片集成.是一个微小型的系统.BUS:总线,考点:AMBA先进的微处理器架构总线,衍生出了两个分支,AHB(类似北桥)总线,先进的高性能总线,APB(类似南桥)先进的外设总线.绝大部分是按照他们的速度来划分的,由PPT的图知道,APB类似一个AHP的外设.计算机中:北桥:离CPU较近,挂着CPU,内存南桥:键盘鼠标等,对速度要求不高.ARM处理器的内核:尾缀:T:表示支持16为的Thumb指令集.D:支持片上调试测试.M:支持长乘法(两个数相乘结果是64个位).I:支持片上仿真器ICE.J:支持Java字节码.E:支持扩展的DSP指令集.F:支持硬件的浮点指令集(核内有浮点运算器一堆门电路).S:包括以上所有.指令的流水线:PC指向正被取址的指令.预取:PC-8译码:PC-4执行:PC最佳流水线:有一个量化的标准CPI,执行指令的周期数,除以周期内指令了多少条指令,CPI = 1,为最佳.LDR:CPI = 1.5分支流水线:CPI = 1.5中断跳转返回,要把LR的值减4之后再返还给PC,这才是正确的地址.必须自己写代码实现.(因为并不像BL那样会帮你保存好当前PC-4到LR中,因为中断是随机产生的,所以在中断结束后要自动进行这一操作[其实内核做了调整,但是根据流水线的工作,调整后依然少了一条指令,所以要手动-4])存储器访问必须时钟适当的保持地址对齐,ARM7TDMIARM710T有8K的统一的cache,不具体区分指令cache和数据cache,也就是冯诺依曼结构(不分开)与哈佛结构说的是在cache里面是否分开,而不是内存中,哈佛结构分开了两个cache,增加了可用的存储宽度(指令存储器接口,数据存储器接口),并且可以实现指令与数据的同时访问(主频不是一切论据3),ARM92410是哈佛,x86是冯氏.ARM97TDMI采用哈佛结构,采用5级流水线,基本固定CPI在1.5.一般编译器会自动重排,提高效率.(比如两行不相关的代码,重新调整顺序后在流水线工作时就不会有资源锁死,减少时间的消耗,提高效率)LDMIA R13!,{R0-R3} :R13的内容给R0,R13偏移,取内容给R1……3种互锁:时间,空间,时间空间双重.支持V5TE改进ARM/Thumb交互工作新的32*16和16*16乘法指令(优化)新的前导零计数:clz,从符号位后第一位开始数,直到碰到第一个不为0,或末尾则结束,得到有多少个0.新的饱和算术指数:Q位置一,核执行差别单周期32*16乘法器EmbeddedICE逻辑RT,仿真电路的实时性提高.ARM10E系列:采用V5TE64bit存储器接口是核到cache的,CPI≈1.36级流水线为了防止流水线长,碰到了if,else不能正确预读:动态分支预测:(A8与ARM11才有)有动态分支目录.静态分支预测:没有动态分录,只有往前跳或者往后跳.Hit under miss:与cache的刷新算法有关(没注意听)每周期64位的LDM/STM操作EmbeddedICE逻辑RTII,提高仿真电路对中断的优先级有提高.双核与多发射:双核是每个核都有一条流水线,多发射是每个核有两条或多条并行的执行单元,流水线.(X86双核4线程现在是24级流水线).ARM11使用V6体系:提高了多媒体性能,扩展包括了许多新的SIMD指令(单指令流,多数据流),2倍MPEG4编码/解码,更快的音频DSP提高实时性能,更快的异常/中断处理,支持向量中断控制器(不管哪一种异常产生,均会找到对应的响应[异常函数入口地址])ARM公司提供了3种方法1.紧耦合向量中断控制器(很快),2.向量中断控制器(稍慢),3.非向量中断(最慢且视编程水平而定)[外设提出中断到CPU找到对应中断函数入口地址的时间称为中断延迟],所以V6减少了中断响应时间,新的栈和模式转变指令,减少进入和退出异常处理的开销.改进了与非ARM处理器数据共享,增强非ARM处理器的应用程序的移植性,支持混合endian系统(大小端混合使用),2012-2-10伪指令就类似C语言中#define,也不具体生成代码.AREA:定义一个段,代码段code,数据段data,自己定义的段,段名可以自己起,但是不要和原有关键字重名,code段一般readonly,data是可读写.code32/code16:指令类型32位arm,16位thumb.ENTRY:程序的入口,当有多个若干个.s文件时,要有ENTRY来告诉程序从哪开始执行,ENTRY 唯一EXPORT/INPORT:EXPORT声明一个符号可以被其他文件引用,IMPORT在当前文件引用一个其他文件声明的符号.IMPORT类似C语言中的externEQU:常量定义,相当于#definelabel:所有顶格写的为标号,标号就是地址,C语言的函数名.顶格也就是第1列.也就是说除了标号以外,都不能顶格写,并且在汇编里只有行注释,没有/**/,使用”;”进行注释. DCD:连续分配一个字内存单元DCB:分配一个字节的内存单元END:源程序借位xxx.hex→包含地址信息,xxx.bin→没有地址信息,只有指令.功能一样,但hex的文件远大于bin文件.area text, code, readonly //定义一个段,段名为text,是代码段,属性为只读entry //此处为程序入口code32 //指令类型为32位start: //label,函数名……end //源程序结尾STN:俗称的伪彩,在太阳下没办法看到,因为成像原理是电压的击穿使得液晶反转.TFT:真彩液晶.新建工程,选好芯片,target设置好板上flashram,因为片上没有,选片外.output,勾选Create HEX File,若需要生成bin文件,在user选项卡中,Run User Program After Build/Rebulid里,勾选Run #1,并填写如下命令:fromelf.exe –bin –o"*******""#L" linker,如果是纯汇编,去掉Use Memory Layout from Target Dialog,并删掉Scatter File 里的文件名.Debug,里可选仿真器.Utilities,keil不支持H-JATGS,只支持ULINK,我们用的是SST39X160XFLASH,增加数据或指令进入内核只有通过前端总线或者寄存器.条件执行:当前这条指令要不要执行,或者如何去执行,取决于上一条执行的影响标志位的结果.ARM指令可以通过添加只当的条件码前缀来达到条件执行的目的,可以提高代码密度,减少分支跳转指令数据,提高性能,默认情况下,数据处理指令不影响条件码标志位但可以选择通过添加S来影响标志位.lsl:逻辑左移MOV R2,R1,LSL #2 →0XE1A021011.什么操作,操作码 24~21→1101 MOV操作2.目的寄存器 15~12→0010 R23.源操作数什么样,寄存器移位数或寄存器数或立即数 25 = 0→是一个寄存器移位数4.源操作寄存器 3~0→0001 第二操作数寄存器R15.移位数多少位 11~7→00010 移2位6.移位类型 6~5→00 逻辑左移7.是不是影响标志位 20→0 不影响标志位8.是什么条件执行 31~28→E1 = AL 无条件执行指令的类型不同格式也不同,不能用同一个格式来分析所有命令ATPCS标准,第一个传参用R0,第二个传参用R1,第三个传参用R2,第四个传参用R3,第5个开始用栈传递. func(a,b,c,d,e…)位清楚 BIC R0,R0,#9 假设R0原来有 1111 1111, #9 = 0000 1001,记住谁为1干掉谁,结果为1111 0110比较指令 CMP R1,#10 CPSR = R1 – 10反值比较+桶形移位器:寄存器,可选择是否增加移位操作逻辑左右移位,无符号数算数右移,保留符号为,高位值填充符号位立即数:以#号开头的是立即数,判断合法立即数的方法:1.若占用连续的1个字节,是则必须为合法.(连续占用是确实的1个字节,而不是2个字节的结合)2.若占用连续的3个半个字节,即1.5个字节,则按二进制位展开,从第一个有效位1开始数,到最后一个有效位1,之间有小于等于8个有效位,并且由于这3个半字节的最低两个位为00,则是合法立即数.i.0x1F8 == 0001 1111 10 00合法ii.0x1FE == 0001 1111 11 10不合法iii.0x7F8 == 0111 1111 10 00 其实依然是不合法的,因为存在有移位只能为偶数的问题(因为老师说过移动位数除以2放到一个存储空间中,然后拿出来乘与2后再开始移位,所以实际上这里就不能把最后的10当作两位来用,因为前边的0111已经占用了半个字节,而不是如0001可以认为占了1/4个字节)iv.因为有MVN命令,所以取反有效,依然合法 0xfffffe07装载32bit常数LDR R0,=0X55555555 此时的LDR是伪指令,类是操作是在某个地方(其实是执行LDR 时,PC应在的地址,即执行地址-8,若LDR之后还有代码,会再自动向后寻址,但是最多只能离LDR这条指令4095个指令,这是LDR的缺陷)存入0x5555 5555,执行LDR时是把这个值拿出来.LDR在装载合法立即数时,会自动变为MOV指令.乘法:32位乘法:MUL{COND}{S} R0,R1,R2 R0=R1*R2MLA{COND}{S} R0,R1,R2,R3 R0=R1*R2+R364位乘法:[U|S]MULL{COND}{S} R0,R1,R2,R3 R0=R2*R3(低32位) R1=R2*R3(高32位)[U|S]MLAL{COND}{S} R0,R1,R2,R3 R0=R2*R3+R0(低32位) R1=R2*R3+R1(高32位) ARM9TDMI比7TDMI多1个周期LDRB LDRHSTRB STRHLDRSB LDRSH带符号位的装载不支持字节与半字存储指令.ARM总共有多少种寻址方式1.立即数寻址:MOV R0,#1 最快的2.寄存器寻址:MOV R0,R13.寄存器移位寻址:MOV R1,R2,LSL #24.寄存器间接寻址:a)LDR R0,[R1] 存储器到寄存器,将R1的内容作为指向存储器的地址,去读地址里的内容保存到R0.b)STR R0,[R1] 寄存器到存储器,………,存储R0内容到R15.基址变址寻址:a)前索引:LDR R0,[R1,#4] R1为基址寄存器,R1的值+4作为地址,将此地址内的值取出放到R0中. STR R0,[R1,#4]b)自动索引:LDR R0,[R1,#4]! R1为基址寄存器,R1的值+4作为新地址,并回写到R1中,将此地址内的值取出放到R0中. STR R0,[R1,#4]!c)后索引:LDR R0,[R1],#4 R1为基址寄存器,将R1的值作为地址,将此地址内的值取出放到R0中,然后将地址值+4回写到R1中STR R0,[R1],#46.多寄存器寻址:什么尾缀存储,完全相反的尾缀取出a)LDM R13!,{R0-R3}b)SRM R13!,{R0-R3}c)I:Inc增加D:Dec减A:After后B:Before先i.IA: 加,后索引,先存,后加,由R0开始ii.IB: 加,先索引,先加,后存,由R0开始iii.DA: 减,后索引,先存,后减,由R3开始iv.DB: 减,先索引,先减,后存,有R3开始7.相对寻址:相对PC,转跳范围+-32MBa) Bb)BL8.堆栈寻址:a)LDMFD:与ATPCS标准有关系, 满full空empty增add减dec,满也就是需要先索引类似B,空则说明后可以后索引,对于堆栈的操作来说,什么尾缀入栈,什么尾缀出栈i.fd:ii.fa:iii.ed:iv.ea:SWP 在寄存器和存储器之间,由一次存储器读和一次存储器写组成的原子操作(一个周期完成两个操作),完成一个字节或字的交换.此指令不能有C语言强制产生,必须使用内列内嵌或C调汇编来实现.用作信号量操作SWP R0,R1,[R2] R2内地址的内容存储R0,R1内容同时存入R2内的地址内C→系统调用→软件中断→SWI(四大步三小步)→PC指向0x08,由SWI内在我们调用它时传入的值来辨别做什么操作.LINUX内核一直运行在ARM的SVC管理模式下PSR指令:CPSR/SPSR的专用访问命令MRS{cond} Rd,<psr> 读*psr的内容到Rd中MSR{cond} <psr[_fields]>,Rm 写Rm内容到*psr中.<psr> = CPSR or SPSR[_fields] 可以为fxcv的任意组合.MSR CPSR_c, R0协处理器指令有3种1.协处理器数据处理指令(少用)2.协处理器寄存器传送指令(有16个寄存器)管理cache,页表,MMUa)MRC:从协处理器寄存器移到ARM寄存器b)MCR:从ARM寄存器移到协处理器寄存器3.写处理器存储器传送指令a)LDC:从存储器装载数据到协处理器寄存器b)STC:从协处理器寄存器存储到存储器Thumb指令集:没有条件执行源,目的寄存器必须相同仅能使用低寄存器常数大小有限制不能使用桶形移位寄存器通过BX指令在ARM与Thumb状态切换,标号位后要加1才能正确跳转到Thumb,而从Thumb跳转到ARM下要把标号位最后一位置0,使用ADR(小范围跳转指令)指令来实现V5TE体系扮酷哦全部的V4T ARM和Thumb指令集更好支持interworking 同时支持ARM/THUMB状态breakpoint指令CLZ指令,前导零计数扩展协处理器指令支持饱和处理Q位封装的带符号的板子乘法指令双字装载/存储指令ARM9TDMI v4T的StrongARM v4的XScale Microachitecture v5TE重点:立即数合法判断,指令的使用,3种基于基址变址的寻址方式,SWP指令的特点,SWI指令2012-2-13异常处理:任何一款CPU都有异常向量表,要记住基本分布,0x00→Reset,0x04→Undefined Instruction,0x08→Software Interrupt,0x0c→Prefetch Abort,0x10→DataAbort,0x14→(Reserved),0x18→IRQ,0x1c→FIQ在ARM7里只有AMR720T可以放到高端地址,ARM9/10均可以PC作为目的寄存器,指令带有S影响的不是标志位,而是回复SPSR到CPSR,同时也依然会更新PC从SWI和Undef异常返回:MOVS PC,LR从FIQ,IRQ和预取异常(Prefect Abort)返回:SUBS PC,LR,#4 [见之前笔记]从数据异常(Data Abort)返回:SUBS PC,LR,#8 [数据在E(执行)时,产生异常,会重新预读此指令,所以需要从原预读地址-8来重新预读此指令] 如果LR之前被压栈的话使用LDM"^":LDMFD SP!,{PC}^中断优先级:数越小中断优先级越高,ISR是中断处理历程的缩写.若有更高中断优先级的请求,会打断之前的中断ISR.若有而比原优先级低的话会等待高优先级的中断完成后再执行.异常优先级:异常在当前(E单元)指令执行完成后才被响应多个异常可以在同一时间产生异常指定了优先级和固定的服务顺序:这个优先级是同时产生是先去服务谁,而不是像中断优先级那样.也就是说在Data Abort异常ISR的过程中,异常可以产生SWI异常来访问一些特定的资源.ResetData AbortFIQIRQPrefetch AbortSWIUndefined instruction异常向量表的跳转指令1.B,优点是灵活,缺点是反问只能+-32MB2.MOV PC,#XXX,缺点是必须要合法立即数3.LDR PC,=32位常数,伪指令,缺点若之后有4095个指令,则不能使用异常进入时必须ARM,退出必须ARM,但是ISR可以是Thumb.异常处理中:与异常发生相关的模式改变移位着所调用的面试题:FIQ的什么特点使它可以快速响应,或者是比IRQ相应更快?1.因为在异常向量表中,FIQ在0x1C,由于FIR位于异常向量表的最末端,所以可以不用像别的那样只有4个字节保存跳转地址,而是可以直接接着写FIQ的ISR代码.2.因为他有5个私有的通用寄存器,不需要特别的保护来恢复这些寄存器. 中断处理:ARM有两级的外部中断FIQ,IRQ.(外部:片只留有两根线nIRQ,nFIQ用于外中断,)SFR:特殊功能寄存器,管理外设.处于4G之内(地址),不属于内核的东西,而是属于外设.大多数的基于ARM的系统有大于2个的中断源因此需要一个中断控制器(地址映射)来控制中断是怎样传递给ARM内核的.在许多系统中,一些中断的优先级比其他中断的优先级高,他们要抢先任何正在处理的的优先级中断.C语言中使用__irq来修饰一个函数,即作为中断程序.纯ubuntu下不支持,只用于keil的IDE环境下.要确保IRQ的堆栈指针已经被设置好在ARER最后有ALIGN=3表示这段空间是字对齐的.SPACE申请连续的字节空间__main是一套宏.宏是没有办法仿真进去的.__main的结束就自动跳转到C的main函数里面中断处理函数具有哪些特点:1.所有的中断的处理函数都不能显式调用2.中断处理函数不能传参(外设中断)3.不能返回值int *s = int * 0x80000000if(*s == 1) int_handler1();………查看属于哪个外设的中断并调用对应的处理函数中断重新使能:中断是可以嵌套的,保存IRQ状态下的LR,SPSR,也就是在使用BL之前改变模式来避免LR_irg被冲掉.通常使用system模式压栈指令必须通过通用寄存器来周转,不能直接使用状态寄存器,__irq不能写可重入中断,要自己写一些处理软中断:用户主动调用才会产生的,是内核已知的一种分支.注意,在汇编中如果SWI调用时处于SVC模式将会冲掉LR_svc.例如在SWI处理程序中的二级调用,解决方法,在SWI调用之前对LR_svc压栈保护.C中使用__swi来定义一个软中断函数.也是在MDK中才能使用的C中__swi允许最多4个参数,使用R0~R3来传递,因为SWI调用将切换到SVC模式,是自己模式的SP,而不是用户模式下的SP,并不通用存取SWI号:用于区分是OPEN,READ,WRITE等操作提取SWI指令中的常数域,要区分ARM/Thumb模式,因为指令长度不同,所以常数域不同,所以由PC-4,-2计算不同.复位处理:执行的动作取决于不同的系统,设置异常向量与调用主应用程序是必须的.ARM优化编译:在设置里面.volatile的作用:1.告诉编译器不要第变量进行优化,是对物理地址的读写,不是对cache里边copy的值,因为存储器里的内容不止内核可以改变,外设也有可能影响着里边的内容,如SFR就是这样映射在存储器中.内嵌函数inline:当调用时间大于运行时间,则推荐使用inline函数.C和C++以及汇编语言的混合编程(重点):可实现在c中无法实现的处理器功能,如swp指令.使用新的或不支持的指令产生更高效的代码ATPCS标准SL=R10SB=R9R12用于存放子程序的返回地址.BX == MOVS PC,LR汇编语言的标号就是C语言里面的函数名c与汇编混合,入口肯定在main函数,在拷贝的文件里可以看到内联汇编不能用物理寄存器void strcpy(des,src){char temp = 0;__asm{loop:ldrb temp,[R0],#1…}}标号不需顶格写,但是要加:号内嵌汇编可以使用物理寄存器,要用__asm来修饰,参考今天的代码PPT上移位的原因是为了把符号位放到对应的位置上.__package字节的对齐对齐访问:sizeof时为什么看到有些自己添加空间,为了快速访问,对齐的最好要小心指针的非对齐.参数传递时,被推荐的最大为4个,R0~R3,为了时间与空间的考虑调库是时间与空间的双重浪费内联,内嵌,C与汇编互调是今天下午的重点2012-2-14电源部分,接入12V的电源,降压到5V的电压,有电感与电容,因为有开关电源,所以用来去波纹,串模干扰.第三个串口在左下角的红外收发上.内部串口是UART口,它逻辑的0和1是TTL/CMOS电平,1≈VDD,接近硅片的供电电压(我们板子是3.3V左右),0≈VSS,接近于电源地.所以PC机要想通过串口进行通信,电平也必须匹配,PC机使用的是232电平,是一种负逻辑的关系,逻辑1 = -3v~-15v(旧主板是-25v),逻辑0 = +3v~+15v(旧主板+25v),此为负逻辑或称为232电平.所以板子上有MAX3232,起电平转换的作用,将传入的232电平与TTL/CMOS电平进行相互转换.MAX3232的工作电压比较大25V也能复合,MAX232工作电压在5V左右.AT24C02是个EEPROM(电可编程可擦除存储器,有2Kbyte,IIC),XS8900A是一个网卡芯片,有20M的晶振给它时钟源注意液晶屏接口,不要接错了,LCD附近的芯片是为了隔离,不让LCD的电压影响到CPUUSB的A口和B口最近的两个是复用的,只能用一个,所以其实只有两个USB口.UDA1341是做音频输入输出的CPU.矩阵式键盘,异常和中断体系结构.很重要.64M的SDRAM,NOR FLASH有2M,NAND FLASH有64M.1117-S33:电源行骗,输入电压3.3v,是给网卡,SDRAM,FLASH,CPU内部的外设供电的1117-S18:1.8v是给内核供电.32.768khz是给CPU内部的RTC提供时钟源的.主晶振是12M,通过CPU内部的PLL提升到200M核心板的跳线帽,烧写NOR要拔出来,应用工程师:不是很了解内核的工作,多年开发以后对外设使用好了,就更好理解内核.外设:1.看数据手册,中英文两册2.看原理图。
arm汇编指令笔记.
ARM assembler guide DUI0068是一个RISC指令结构,因为有一个加载存储结构。
只有load和store可以读取内存。
ARM的处理器模式可以全部大写或小写,不能混标志符表示一个地址常量的定义格式:1230x1C2_1001ARM编译、链接后最终生成一个ELF格式(Executable and Linking Format)的可执行文件(后缀.axf)ELF中是分section部分的,一个ELF section在汇编中定义一个section使用AREA指令。
ENTRY指令指示汇编代码第一条要执行的指令。
start是一个标识符,代表一个地址。
结束的方式是产生一个软件中断,把控制权交给调试器。
END指令指示汇编的结束使用cmd进行调试:Microsoft Windows XP [版本5.1.2600](C) 版权所有1985-2001 Microsoft Corp.C:\Documents and Settings\Administrator>cd D:\Program Files\ARM\ADSv1_2\BinC:\Documents and Settings\Administrator>D;'D' 不是内部或外部命令,也不是可运行的程序或批处理文件。
C:\Documents and Settings\Administrator>D:D:\Program Files\ARM\ADSv1_2\Bin>armsd E:\dsparm\pxa270\project\armex\__image.ax fARM Source-level Debugger, ADS1.2 [Build 805]Software supplied by: Team-EFASoftware supplied by: Team-EFAARM7TDMI, BIU, Little endian, Semihosting, Debug Comms Channel, 4GB, Mapfile, Timer, Profiler, Tube, Millisecond [20000 cycles_per_millisecond], Pagetables,IntCtrl, Tracer, RDI CodesequencesObject program file E:\dsparm\pxa270\project\armex\__image.axfarmsd: helphelp [<keyword>]Display help information on one of the following commands:Registers Fpregisters Coproc CRegisters CREGDefCWrite Step Istep Examine ListQuit Obey Go Break Unbreak Watch UNWatch Print CONtext OUtIN WHere BAcktrace Variable SYmbols LSym LEt Arguments LAnguage HelpType CAll WHIle ALias LOadLOG RELoad REAdsyms FInd PUtfile GEtfile LOCalvar COMment PAuse LOADConfig SElectconfig LISTConfig LOADAgent PROfon PROFOFf PROFClear PROFWrite CCin CCOut PROCessor SYS SETregister TRacetrigger TRACEExtent TRACEWrite TRACEStart TRACESTOp TRACEFlushHELP * gives helps on all available commands. To print the help use the LOGcommand to record the help output into a file & print the file.If the first character of a line is the '!' character the rest of the commandline is executed by a call to system(). If the first character of a line isthe '|' character the rest of the line is a treated as a comment.Note that this help is not intended to replace the printed manual whichexplains ARMSD in much greater detail.armsd: LOG** Error: No log filearmsd: stepStep completed at PC = 0x000080040x00008004: 0xe3a01003 .... : mov r1,#3armsd: Registerr0 = 0x0000000a r1 = 0x00000000 r2 = 0x00000000 r3 = 0x00000000r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008004 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00armsd: stepStep completed at PC = 0x000080080x00008008: 0xe0800001 .... : add r0,r0,r1armsd: Registerr0 = 0x0000000a r1 = 0x00000003r2 = 0x00000000 r3 = 0x00000000r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008008 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepStep completed at PC = 0x0000800c0x0000800c: 0xe3a00018 .... : mov r0,#0x18armsd: LOG** Error: No log filearmsd: Registerr0 = 0x0000000d r1 = 0x00000003 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x0000800c cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepStep completed at PC = 0x000080100x00008010: 0xe59f1000 .... : ldr r1,0x00008018 ; = #0x00020026 armsd: Registerr0 = 0x00000018 r1 = 0x00000003 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008010 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepStep completed at PC = 0x000080140x00008014: 0xef123456 V4.. : swi 0x123456armsd: Registerr0 = 0x00000018 r1 = 0x00020026 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008014 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepProgram terminated normally at PC = 0x000080140x00008014: 0xef123456 V4.. : swi 0x123456armsd: Registerr0 = 0x00000018 r1 = 0x00020026 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008014 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: quitQuittingD:\Program Files\ARM\ADSv1_2\Bin>使用armsd调试有点像微机原理上调试汇编,爽!MOV叫指令,常数范围是0-255LDR叫伪指令都是将常数放到Reg中#和FIELD指令是一样的符号在汇编程序中代表一个地址,可以用在指令中,汇编程序经过汇编器的处理之后,所有的符号都被替换成它所代表的地址值。
ARM学习笔记
10. ARM处理器运行模式
答:ARM微处理器支持7种运行模式,分别为:
? 用户模式(usr):ARM处理器正常的程序执行状态;
快速中断模式(fiq):用于高速数据传输或通道管理;?
? 外部中断模式(irq):用于通用的中断处理;
管理模式(svc):操作系统使用的保护模式;?
? ARM7没有MMU,ARM720T是MMU的;ARM9是有MMU的,ARM940T只有Memory protection unit.不是一个完整的MMU。
? ARM7TDMI提供了非常好的性能——功耗比。它包含了Thumb指令集快速乘法指令和ICE调试技术的内核。ARM9的时钟频率比ARM7更高,采用哈佛结构区分了数据总线和指令总线。
? 数据中止②:若处理器数据访问的指令的地址不存在,或该地址不允许当前指令访问,产生数据中止异常(异常向量:0x0000,0010);
? IRQ④(外部中断请求):当处理器的外部中断请求引脚有效,且CPSR中的I位为0时,产生IRQ异常。系统的外设可以该异常请求中断服务(异常向量:0x0000,0018);
7. ARM指令与Thumb指令的区别
答:在ARM体系结构中,ARM指令集中的指令是32位的指令,其执行效率很高。对于存储系统数据总线为16位的应用系统,ARM体系提供了Thumb指令集。Thumb指令集是对ARM指令集的一个子集重新编码得到的,指令长度为16位。通常在处理器执行ARM程序时,称处理器处于ARM状态;当处理器执行Thumb程序时,称处理器处于Thumb状态。Thumb指令集并没有改变ARM体系地层的程序设计模型,只是在该模型上加上了一些限制条件。Thumb指令集中的数据处理指令的操作数仍然为32位,指令寻址地址也是32位的。
ARM汇编学习笔记
这两天参加了一个编写操作系统的项目,因为要做很多底层的东西,而且这个操作系统是嵌入式的,所以开始学习ARM汇编,发现ARM汇编和一般PC平台上的汇编有很多不同,但主要还是关键字和伪码上的,其编程思想还是相同的。
现将一些学习感悟部分列出来,希望能给有问题的人一点帮助。
1、ARM汇编的格式:在ARM汇编里,有些字符是用来标记行号的,这些字符要求顶格写;有些伪码是需要成对出现的,例如ENTRY和END,就需要对齐出现,也就是说他们要么都顶格,要么都空相等的空,否则编译器将报错。
常量定义需要顶格书写,不然,编译器同样会报错。
2、字符串变量的值是一系列的字符,并且使用双引号作为分界符,如果要在字符串中使用双引号,则必须连续使用两个双引号。
3、在使用LDR时,当格式是LDR r0,=0x022248,则第二个参数表示地址,即0x022248,同样的,当src变量代表一个数组时,需要将r0寄存器指向src 则需要这样赋值:LDR r0,=src 当格式是LDR r0,[r2],则第二个参数表示寄存器,我的理解是[]符号表示取内容,r2本身表示一个寄存器地址,取内容候将其存取r0这个寄存器中。
4、在语句:CMP r0,#numBHS stop书上意思是:如果r0寄存器中的值比num大的话,程序就跳转到stop标记的行。
但是,实际测试的时候,我发现如果r0和num相等也能跳转到stop 标记的行,也就是说只要r0小于num才不会跳转。
下面就两个具体的例子谈谈ARM汇编(这是我昨天好不容易看懂的,呵呵)。
第一个是使用跳转表解决分支转移问题的例程,源代码如下(保存的时候请将文件后缀名改为s):AREA JumpTest,CODE,READONLYCODE32num EQU 4ENTRYstartMOV r0, #4MOV r1, #3MOV r2, #2MOV r3, #0CMP r0, #numBHS stopADR r4, JumpTableCMP r0, #2MOVEQ r3, #0LDREQ pc, [r4,r3,LSL #2]CMP r0, #3MOVEQ r3, #1LDREQ pc, [r4,r3,LSL #2]CMP r0, #4MOVEQ r3, #2LDREQ pc, [r4,r3,LSL #2]CMP r0, #1MOVEQ r3, #3LDREQ pc, [r4,r3,LSL #2]DEFAULTMOVEQ r0, #0SWITCHENDstopMOV r0, #0x18LDR r1, =0x20026SWI 0x123456JumpTableDCD CASE1DCD CASE2DCD CASE3DCD CASE4DCD DEFAULTCASE1ADD r0, r1, r2B SWITCHENDCASE2SUB r0, r1, r2B SWITCHENDCASE3ORR r0, r1, r2B SWITCHENDCASE4AND r0, r1, r2B SWITCHENDEND程序其实很简单,可见我有多愚笨!还是简要介绍一下这段代码吧。
ARM、单片机C语言编程问题笔记
ARM、单片机C语言编程问题笔记串口通讯—通信协议 (2)一、物理接口标准 (2)二、软件协议 (4)51单片机串口通信的发送与接收(转) (9)Printf 输出格式大全: (17)#if defined和#if !defined(c语言的宏定义) (20)C语言的条件编译#if, #elif, #else, #endif、#ifdef, #ifndef.. 22下面本人在学习ARM及单片机过程中遇到的问题在网上查找的相关资料稍作整理供各位参考学习:串口通讯—通信协议所谓通信协议是指通信双方的一种约定。
约定包括对数据格式、同步方式、传送速度、传送步骤、检纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守。
因此,也叫做通信控制规程,或称传输控制规程,它属于ISO'S OSI七层参考模型中的数据链路层。
目前,采用的通信协议有两类:异步协议和同步协议。
同步协议又有面向字符和面向比特以及面向字节计数三种。
其中,面向字节计数的同步协议主要用于DEC公司的网络体系结构中。
一、物理接口标准1.串行通信接口的基本任务(1)实现数据格式化:因为来自CPU的是普通的并行数据,所以,接口电路应具有实现不同串行通信方式下的数据格式化的任务。
在异步通信方式下,接口自动生成起止式的帧数据格式。
在面向字符的同步方式下,接口要在待传送的数据块前加上同步字符。
(2)进行串-并转换:串行传送,数据是一位一位串行传送的,而计算机处理数据是并行数据。
所以当数据由计算机送至数据发送器时,首先把串行数据转换为并行数才能送入计算机处理。
因此串并转换是串行接口电路的重要任务。
(3)控制数据传输速率:串行通信接口电路应具有对数据传输速率——波特率进行选择和控制的能力。
(4)进行错误检测:在发送时接口电路对传送的字符数据自动生成奇偶校验位或其他校验码。
在接收时,接口电路检查字符的奇偶校验或其他校验码,确定是否发生传送错误。
arm课堂笔记
arm课堂笔记寄存器:临时存放alu运算的结果的存储单元r0~r7 一组 8种模式公用一组 8r8~r12 2组 fiq私有一组,其余7种模式公用一组 5*2R13 7组 usr和system共用一组,其余每个模式都私有一组 7 R14 7组 usr和system共用一组,其余每个模式都私有一组 7 R15 1组 8种模式公用一组 1cpsr 1组 8种模式公用一组 1spsr 6组除了system和usr ,其余每个模式私有一组 6 cortex-a核心内一共有多少个寄存器:40个寄存器关于同名寄存器访问的问题:当前处在usr模式mov r0,sp(usr)切换模式到fiqmov r0,sp(fiq)切换模式到irqmov r0,sp(irq)切换模式到abortmov r0,sp (abort)切换模式到undefmov r0,sp (undef)异常处理:pc -> lr_modepc -> 异常向量cpsr -> spsr_modecpsr <- T =0; J =0 ,进入ARM状态I,F 如果需要可以禁止MODE[4:0] = mode异常处理的4大步3小步当前发生irq中断时,pc -> lr_irqpc = 0x18cpsr -> spsr_irqcpsr <- T=0,J=0;I,FMode[4:0]= 10010ARm处理器的后缀名称T: thumb指令集的支持D : debug片山调试功能的支持M : 64位的长乘法I: 嵌入式ICE 用来调试cpuS: TDMI的缩写E: 支持dsp指令J: java字节码的支持F: 硬件浮点的支持0x8000 mov0x8004 sub0x8008 add0x800c andoc与Fetch之间的关系Fetch = *pc第一个周期:pc = 0x8000F : movD :xE :x第二个周期:pc = 0x8004F : subD : movE : x第三个周期:pc = 0x8008F : add 0x8008D : subE : mov 0x8000第四个周期:pc = 0x800cF: and 0x800cD: addE: sub 0x8004LDR 流水线举例M W 是E单元的子单元分支流水线举例第一个周期:pc = 0x8008F : ORRE : bl 0x8fec第二个周期:E: L 保存pc->lr = 0x8008 pc = 0x8fecF: andD: x第三个周期:E: A lr-4 -> lr= 0x8004pc = 0x8ff0F : orrD : and第四个周期:pc = 0x8ff4F: eorD: orrE: and跳转返回:mov pc,lr (0x8004)中断流水线:第一个周期: 发生irq中断pc = 0x8008F : mov ->不变D : sub -> DIE : add -> 不变第二个周期:pc = 0x800cF: xE: EI第三个周期:E:L(异常处理4大3小)pc -> lr_irq = 0x800cpc = 0x18F: B 0xaf00D: x第四个周期:E :A lr -4 -> lr_irq = 0x8008 pc = 0x1cF: xD: B 0xaf00第五个周期:pc = 0x20F: xD: xE: b 0xaf00第六个周期:pc = 0xaf00F: STMFDD:xE: x第七个周期:pc = 0xaf04F: movD: stmfdE: x第八个周期:pc = 0xaf08D: movE : stmfd异常返回指令:subs pc,lr,#4ldr互锁的条件:当前ldr指令的目的寄存器和下一条指令的源寄存器重名时LDM互锁:ldmia需要连续计算4次内存地址,E单元需要占用4次,ATPCS规范:函数传参规则:int func(int a,int b,int c,int d,int e)第一个参数:r0第二个参数:r1第三个参数:r2第四个参数:r3如果参数大于4个,使用堆栈传参条件比较指令分析:if (a==4 || a==10) x=0;CMP r0,#4CMPNE r0,#10MOVEQ r1,#0第一种情况:r0 = 4;CMPNE r0,#10 (不成立,该指令不执行)MOVEQ r1,#0 (成立,该指令执行)第二种情况:r0=10;CMP r0,#4CMPNE r0,#10 (成立,该指令执行)MOVEQ r1,#0 (成立,该指令执行)第二种情况:r0!=10 && r0 !=4 ;CMP r0,#4CMPNE r0,#10 (成立,该指令执行)MOVEQ r1,#0 (不成立,该指令不执行)ARM指令的机器码格式:e0810102 add r0, r1, r2, lsl #2指令的格式:<操作>{}{S} Rd, Rn, Operand2RD :目的操作数Rn : 第一操作数Operand2 : 第二操作数只有比较指令影响标志位 -不指定Rd数据搬移(MOV指令)不指定Rn31-28 27-24 23-20 19-16 15-12 11- 8 7 - 4 3 - 0 e 0000 1000 0001 0000 0001 0000 00100010 0100 1010 0010 00000 1010 00101001 01000110B跳转指令b stopmov r0,#1mov r1,#2mov r2,#3mov r3,#4stop:b stop对应的反汇编为:30000: e0919122 adds r9, r1, r2, lsr #230004: eb000003 bl 3001830008: e3a00001 mov r0, #13000c: e3a01002 mov r1, #230010: e3a02003 mov r2, #330014: e3a03004 mov r3, #4B跳转指令可以翻译为: add pc,pc,+-偏移量pc = 0x300c偏移量= 3*4 = 12pc= 0x3018如何执行长跳转 ldr pc,=stop (0 ~ 4G)BIC指令的功能:mov r0,#0xffbic r0,r0,0xf0第二操作数为1的位,会对第一操作数清零r0 = 0x0f数据处理指令中的第二操作数可以有几种情况表示:寄存器寄存器移位立即数立即数的产生:一个字节的数循环右移(ROR)0到30之间的偶数位得来的一个数0x123,0x1234,0x234,0xffffffff,0xf000000f ,0x1f8,0x23456,0x800480x288立即数的判断规则:0x123第一步:把这个数展开成二进制 00 | 01 0010 0011 |第二步:从左端第一个非零的数,从左端第一个非零数的左端偶数位断开第三步:从右端第一个非零的数,从右端第一个非零数的右端偶数位断开第四步: 数断开之间的位数 <= 8 为立即数> 8 不是立即数00 | 01 1111 10 | 00多次仿真操作流程:第一步:(手动)复位开发板第二步: 重连fs_jtag或者F5第三步: 运行仿真进程第四步: 结束仿真进程装载一个32位的常数:ldr rd,=constconst 如果为是有效数(立即数) 会翻译成mov mvnconst 如果不是有效数会翻译成ldr 访问内存建议把常数装载到寄存器中时一律使用该伪指令。
ARM学习笔记
1,关于arm状态和thumb状态的理解:Arm状态就是每次取指令取4个字节(也就是一个字),而thumb状态取2个字节的指令;很显然取指令的时间都是一样的,那么显然arm状态的速度显然比thumb状态快。
(仅此而已)。
【这也就是2字节对齐和四字节对齐的原理:即cpu一次获取指令的长度】2,关于arm中的r14,r15和r16寄存器的描述:R14寄存器:即LR,是程序调准寄存器,当跳转时接收r15的地址的备份,进行跳转。
【值得明确的是当发生异常中断而发生程序跳转时,cpu会自动向BL写入当前程序的地址,当执行BL时,cpu也同样会把下一条指令的地址(即当前pc-4)自动写入LR寄存器中】R15寄存器:保存程序的地址;PC保存程序执行的当前地址。
R16寄存器:即CPSR,为当前程序状态寄存器,其包含条件码标志位和当前模式。
3,arm的时钟体系:Arm中有两个锁相环(PLL)【在此其主要作用是通过倍频因子进行倍频】;一个是MPLL (用于FCLK,,HCLK,PCLK),另一个是(UPLL)专用于USB的倍频;其倍频因子为m,p,s;很显然,只要设置PLLCON对应的寄存器就可以实现设置FCLK的时钟。
【值得注意的是:在系统复位后,在设置PLLCON之前,FCLK一直使用系统默认时钟(即外部相应的时钟,一般为12Mhz),直到设置了PLLCON。
等待一个锁定时间(一般使用默认,无需设置相应寄存器)后,FCLK才使用新的时钟。
如果,没有设置PLLCON,那么系统当然一直使用默认时钟(即外部晶振的时钟)】设置了FCLK时钟后,我们只要设置FCLK,HCLK,PCLK比例就能实现各时钟的设置。
及设置CLKDIVN寄存器即可。
Flush:刷新4,arm的存储系统:MMU中的协处理器cp15:Cp15包含16个32位寄存器。
1)访问CP15寄存器的指令:MCR:把ARM寄存器的数据转移到MMU的协处理器的寄存器;MRC:把MMU协处理器的寄存器里的数据复制到ARM寄存器中;【值得注意的是MCR和MRC只能在arm处理器的系统模式下使用】2)MMU介绍:MMU的主要功能是:(1)虚拟内存与物理内存的映射;(2)内存访问权限的控制;(3)设置虚拟内存的缓冲特性;3)实现内存映射的关键技术——分页技术:所谓页就是一块大小一定的内存,arm将内存分为许多页。
ARM学习笔记
ARM学习笔记1、ARM的MOV指令与LDR/STR指令比较CISC处理器支持“存储器-寄存器”的操作,即允许将存储器的值加到寄存器或寄存器中的值加到存储器。
但是,由于ARM处理器采用load/store体系结构,所以只能由数据处理指令来处理寄存器中的值,而面向存储器的操作只是将存储器的值复制到寄存器或者将寄存器中的值复制到存储器。
ARM的MOV指令和LDR/STR指令都能完成数据传送操作,但是在实际应用中区别还是很大的。
ARM的MOV指令属于数据处理指令,只能完成寄存器间的数据传送或将立即数加载到寄存器的操作(注意,加载立即数受指令长度的限制),例如:MOV R0,R1MOV R0,#0X3F而LDR/STR属于数据传送指令,完成的是从存储器到寄存器的数据加载或从寄存器到存储器的数据存储的操作,即可以完成存储器到寄存器间的数据转移。
例如:LDR R0,[R1]STR R0,[R1]2、MRS、MSR指令(1)状态寄存器传送至通用寄存器类指令功能:将状态寄存器的内容传送至通用寄存器。
格式:MRS{<条件码>}Rd,CPSR}SPSR其中:Rd 目标寄存器,Rd不允许R15。
R=0 将CPSR中的内容传送目的寄存器。
R=1 将SPSR中的内容传送至目的寄存器。
注释:MRS与MSR配合使用,作为更新PSR的读-修改-写序列的一部分。
例如:改变处理器或清除标志Q。
注意:当处理器在用户模式或系统模式下,一定不能试图访问SPSR这条指令不影响条件码标志。
例:MRS R0,CRSR ;将CPSR中的内容传送至R0MRS R3,SPSR ;将SPSR中的内容传送至R3(2)通用寄存器传送至状态寄存器传送指令功能:将通用寄存器的内容传送至状态寄存器。
格式:MSR{<条件码>CPSR_f|SPSR_f,<#ommed_8r>MSR{<条件码>CPSR_<field>|SPSR_<field>,Rm其中:<field>字段可以是以下之一或多种:C:控制域屏蔽字段(PSR中的第0位到第7位);X:扩展域屏蔽字段(PSR中的第8位到第15位);S:状态域屏蔽字段(PSR中的第16位到第32位);F:标志域屏蔽字段(PSR中的第24位到第31位)。
读书笔记----ARM汇编编程
读书笔记----ARM汇编编程1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59/**************************************************************** ***************** ****************************************文件头************************************ ** 《ARM体系结构与编程》读书笔记** ** 成功的步伐在您不懈的努力中加快!** **源自: METAL MAX, CUIT **起始日期:01/25/08 **当前版本:Version0.08.0125 ** **备注: 1.这是2008春节回家期间阅读《ARM体系结构与编程》这部作品的时候记载下来的。
小小的东西凝聚了我不少的心血(汗...书又不是我写的,我只是负责抄写了一遍, 有些内容给省略了...),让我体会到要真真正正做个像样的东西很不容易,但是,相信点点滴滴的积累,正所谓是:不积跬步,无以至千里;不积小流,无以成江海!2.由于刚接触ARM处理器,并不熟悉其中的一些细节问题,所有在做笔记的时候对有西理解不是很透彻,甚至会又错误。
有些地方加入了自己的一些东西(主要是一些的理解和自己做的图表)。
3.由于本人水平太菜的缘故,排版不工整,存在错别字等问题,见谅!更希望有心人忙修改和完善,众志成城!4.本文档您可以任意的修改(严禁恶搞!^_^)和传播,引用文档的部分和全部内容请本文件的文件头,如果您是有心人修改或完善了其中的部分内容,请一定保留您的改记录(修改日期、版本、修改人以及修改点等),并将其归入文件头中。
ARM学习笔记 GPIO接口
ARM学习笔记--GPIO接口GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平。
S3C2410共有117个I/O端口,共分为A~H共8组:GPA、GPB、...、GPH。
S3C2440共有130个I/O端口,分为A~J共9组:GPA、GPB、...、GPJ。
可以通过设置寄存器来确定某个引脚用于输入、输出还是其他特殊功能。
比如:可以设置GPH6作为输入、输出、或者用于串口。
1 GPIO硬件介绍1.1 通过寄存器来操作GPIO引脚GPxCON用于选择引脚功能,GPxDAT用于读/写引脚数据;另外,GPxUP用于确定是否使用内部上拉电阻。
x为B、...、H/J,没有GPAUP寄存器。
1.1.1 GPxCON寄存器从寄存器的名字可以看出,它用于配置(Configure)-选择引脚功能。
PORTA与PORTB~PORT H/J在功能选择方面有所不同,GPACON中每一位对应一根引脚(共23根引脚)。
当某位被设为0时,相应引脚为输出引脚,此时我们可以在GPADAT 中相应位写入0或是1让此引脚为低电平或高电平;当某位被设为1时,相应引脚为地址线或用于地址控制,此时GPADAT无用。
一般而言,GPACON通常被设为全1,以便访问外部存储器件。
PORT B~ PORT H/J在寄存器操作方面完全相同。
GPxCON中每两位控制一根引脚:00表示输入、01表示输出、10表示特殊功能、11保留不用。
1.1.2 GPxDAT寄存器GPxDAT用于读/写引脚;当引脚被设为输入时,读此寄存器可知相应引脚的电平状态是高还是低;当引脚被设为输出时,写此寄存器相应位可以令此引脚输出高电平或是低电平。
1.1.3 GPxUP寄存器GPxUP:某位为1时,相应引脚无内部上拉电阻;为0时,相应引脚使用内部上拉电阻。
ARM学习笔记
rSYSCFG=SYSCFG_8KB; //使用8K字节的指令缓存
for(i=_RAM_STARTADDRESS;i<(_RAM_STARTADDRESS+0x20);i+=4)
{
*((volatile unsigned *)i)=0xEA000000+0x1FFE;
}
0xEA000000+0x1FFE
就是一条跳转指令,它的条件码为1110,表示无条件跳转;L为0表示不保存返回值(因为这里修改的是异常处理入口,不用返回值);0x1FFE指定跳转目的地址。
下面我们看看signed_immed_24的计算方法:
1.将PC寄存器作为该条跳转指令的基地址;
2.用目标地址减去基地址,生成跳转偏移量(程序要保证该偏移量小于33554432);
3.将这个值的bit[25:2]填入signed_immed_24中。
因此0x1FFE的意义就是目标地址相对当前地址为 0x1FFE*4+8=0x8000
现在我们就明白了这段代码是将RAM开始的32个字节中填入了8个跳转指令,跳转的目标地址为当前指令地址+0x8000
如果你把你的程序加载到_RAM_STARTADDRESS+0x8000(在这块板子上就是0x0C008000),那么这几个异常中断都会跳转到你自己程序中的异常中断处理处,执行你自己的处理过程。
arm汇编学习笔记
arm汇编学习笔记
1.LDR和MOV的不同
ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S 指令来完成,也就是ldr/str指令。
比如想把数据从内存中某处读取到寄存器中,只能使用ldr
比如: ldr r0, 0x12345678
就是把0x12345678这个地址中的值存放到r0中。
而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。
x86中没有ldr这种指令,因为x86的mov指令可以将数据从内存中移动到寄存器中。
2.汇编的位操作技巧
ldr r0,=rGPBCON;//设置GPB5~GPB8输出端口
ldr r1,=0x55<<10;
3.B与BL的不同
B或BL指令引起处理器转移到“子程序名”处开始执行。
两者的不同之处在于BL指令在转移到子
程序执行之前,将其下一条指令的地址拷贝到R14(LR,链接寄存器)。
由于BL指令保存了下条指令的地
址,因此使用指令“MOV PC ,LR”即可实现子程序的返回。
而B 指令则无法实现子程序的返回,只能实
现单纯的跳转。
4.IMPORT
伪操作告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号,而且不论本源
文件是否实际引用该符号,该符号都将被加入到本源文件的符号表中。
即后面的标号来自外部文件。
ARM笔记
ARM处理器结构ARM处理器模式处理器模式用户user FIQ fiq IRQ irq 管理svc 终止abt 未定义und 系统sys寄存器组织ARM处理器共有37个寄存器31个通用寄存器,包括程序计数6个状态寄存器,都是32位,但寄存器R13通常用作指针堆栈,寄存器R14用作子程序链接寄存CPSR在所有处理器模式下都可以访问当前程序状态寄存器CPSR。
CPSR包含条件码标志、中断禁止位31302928765NZ C VDNM(RAZ)I F T条件码标志N 本位设置成当前指令运算结果的bit[31]的值。
当两个表示的有符号整数运算时,n=1表示运算Z z=1表示运算的结果为零;z=0表示运算的结果不为零。
对于CMP 指令,Z=1表示进行比较的两C在加法指令中(包括比较指令CMN ),当结果产生了进位,则C=1,表示无符号运算发生溢出(ov 在减法指令中(包括比较指令CMP ),当运算中发生借位,则C=0,表示无符号运算数发生进对于包含移位操作的非加减运算指令,C中包含最后一次溢出的位的数值对于其他非加减运算指令,C 位的值通常不受影响V 对于加减运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢控制位I置1则禁止IRQ中断F 置1则禁止FIQ中断模式位CPSR(当前程序状态寄存器)在任何处理器模式下被访问。
它包含了条件标志位、中断禁止位、当前处理器一个专用的物理状态寄存器,称为SPSR (备份程序状态寄存器)。
当特定的异常中断发生时,这个寄存器SPSR 来恢复CPSR 。
由于用户模式和系统模式不是异常中断模式,所以他没有SPSR 。
当用户在用户模式T T=0表示执行ARM 指令T=1表示执行Thumb 指令R10 ------ R10 ------ R10 R10_fiq sl R11 ------ R11 ------ R11 R11_fiq fp R12 ------ R12 ------ R12 R12_fiq ip R13 R13_svc R13_irq R13_fiq sp R14 R14_svc R14_irq R14_fiq lr .-------------R15/PC-------------PC R4 ------- R4 ------- R4 ------- R4 v1R5 ------- R5 ------- R5 ------- R5 v2R6 ------- R6 ------- R6 ------- R6 v3R7 ------- R7 ------- R7 ------- R7 v4R8 ------- R8 ------- R8 R8_fiq v5R9 ------- R9 ------- R9 R9_fiq v6User 模式 SVC 模式 IRQ 模式 FIQ 模式 APCS R0 ------- R0 ------- R0 ------- R0 a1R1 ------- R1 ------- R1 ------- R1 a2R2 ------- R2 ------- R2 ------- R2 a3R3 ------- R3 ------- R3 ------- R3 a432位ALU(是算术逻辑单元,是能实现多组算术运算和逻辑运算的组合逻辑电路)31个32位通用寄存器6位状态寄存器32*8位乘法器32*32位桶形移位寄存器指令译码及控制逻辑,指令流水线和数据/地址寄存器组成M[4:0]模式可访问的寄存器ob10000 user 0b10001 FIQ 0b10010 IRQ 0B10011 管理0b10111中止0b11011未定义0b11111系统Thumb状态的寄存器集Thumb状态寄存器与A系统和用户FIQ 管理中止IRQ 未定义R0R0R0R0R0R0R0R1R1R1R1R1R1R1R2R2R2R2R2R2R2R3R3R3R3R3R3R3R4R4R4R4R4R4R4R5R5R5R5R5R5R5R6R6R6R6R6R6R6R7R7R7R7R7R7R7SP SP_fiq*SP_svc*SP_abt*SP_irq*SP_und*LR LR_fiq*LR_svc*LR_abt*LR_irq*LR_und*PCPC PC PC PC PCSP LR PC CPSR SPSRARM异常异常向量表异常类型模式复位管理0x0000 00000xFFFF 0000未定义指令未定义0x0000 00040xFFFF 0004软件中断(SWI)管理0x0000 00080xFFFF 0008预取中止(取指令存储器中止)中止0x0000 000C 0xFFFF 000C 数据中止(数据访问存储器中止)中止0x0000 00100xFFFF 0010IRQ(中断)IRQ 0x0000 00180xFFFF 0018FIQ(快速中断)FIQ 0x0000 001C 0xFFFF 001C 当异常出现时,异常模式分组的R14和SPSR用于保存状态。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ARM接口编程笔记一、ARM编程模式1.ARM的含义●ARM是一家公司的名字●ARM代表的是一种RISC技术●ARM是一种CPU体系结构的名称,同x86、PPC、MIPS等并列2.ARM体系结构中对字节、半字、字、双字的定义●字节:8 bit●半字:16 bit●字:32 bit●双字:64 bit3.ARM指令集●ARM指令集,32 bit,功能最全●Thumb指令集,16 bit,是ARM指令集的子集,完成部分功能●Thumb‐2指令集,16 bit和32 bit混合●Thumb‐EE指令集,16 bit和32 bit混合●Java指令集,直接执行绝大部分的Java字节流,但需要授权4.ARM处理器的权限●非特权级:部分指令不能执行,是一种硬件的保护机制,通常用户应用程序运行在该权限级别●特权级:能执行所有指令,通常操作系统运行在该权限级别5.ARM的工作模式,处理对应模式下的特定事务,使得这些特定事务能够在硬件资源的使用上部分地独立开来,这是通过各种模式下有对应的私有硬件资源来实现的。
●User:应用程序一般运行在该模式下●Supervisor:操作系统一般运行在该模式下●IRQ:中断处理程序一般运行在该模式下●FIQ:快速中断处理程序一般运行在该模式下●Abort:发生存取异常后会进入该模式●Undef:执行未定义的指令会进入该模式●System:为解决中断不可重入而设计的一种特殊模式●Monitor:Cortex‐A特有的模式,执行监控代码●除User模式外,其他7种模式都是特权模式6.ARM寄存器寄存器最靠近CPU中的ALU,存取速度最快,没有地址,只有编号。
部分寄存器有别名,在汇编程序中本名和别名可以混用。
●R0‐R7:各模式都共用的寄存器,物理上共8个寄存器。
●R8‐R12:FIQ模式下有对应的私有寄存器,即FIQ模式下使用其私有的这组寄存器,另外7中模式都共用另外一组寄存器,物理上共有10个寄存器●R13:User和System模式共用,另外6种模式都有各自私有的寄存器,物理上共7个寄存器●R14:User和System模式共用,另外6种模式都有各自私有的寄存器,物理上共7个寄存器●R15:各模式都共用的寄存器,物理上只有1个●CPSR:各模式都共用的寄存器,物理上只有1个●SPSR:User和System模式下无此寄存器,另外6种模式都有各自私有的寄存器,物理上共6个寄存器7.ARM寄存器使用说明●虽然上表中各模式下的私有寄存器都跟有后缀,但在汇编中都使用统一的名字。
如,在FIQ模式下的汇编代码要表示R13寄存器,只能在汇编中写R13,而不能写R13_fiq●虽然总共有40个寄存器,但是处理器在某一个特定时刻,只能处于一种模式下,所以处理器在同一时间内只能见到本模式下的寄存器,最多有18个可见,最少有17个可见(User和System模式)●R13寄存器的别名为SP,是栈指针,各模式有私有的栈指针,则意味着各模式下的栈空间可以彼此独立。
通常由编译器和CPU来维护,使用前需初始化●R14寄存器的别名为LR,链接寄存器,用于自动保存返回地址。
特别需要注意的是:如果程序执行流程的改变不涉及模式的切换,则返回地址保存在当前模式下的LR寄存器中;如果程序执行流程的改变伴随着模式的切换,则返回地址保存在被切换后的模式下的LR寄存器中。
注意对LR寄存器的保护●R15的寄存器别名为PC,程序计数器,用于指示被取指令的地址,通常由CPU自动维护,也可以通过程序手动修改●CPSR寄存器,用于反映当前的程序状态,如处理器所处的模式,处理器所处的状态,中断是否被屏蔽,数据运算的结果是否发生了借位、进位,结果是否为0,结果是否为负,是否发生溢出等●SPSR寄存器,定义同CPSR寄存器。
在模式发生切换后用于保存模式切换前的模式下的CPSR寄存器,如果要切换回以前的模式,则可用切换后所在模式的SPSR去恢复切换前模式的CPSR,需要由特殊的指令来实现8.ARM指令特点●定长32 bit●大部分为单周期指令●大部分指令可条件执行,即在常规指令后跟上执行条件●采用Load/Store架构,典型的限制是不能在存储器和存储器间直接拷贝,必须通过寄存器中转9.ARM处理器核●流水线使得指令流可并行处理,提高效率●PC指向正被取指的指令,而非正在执行的指令●Cache因为存取速度高于内存,用于缓存指令和数据,提高执行速度●Write Buffer用于暂存向内存写入的数据●MMU用于程序的保护和实现虚拟内存●CP15协处理器用于控制Cache、Write Buffer和MMU等10.SoC的概念:片上系统,将CPU核同其他外围接口电路(如串口,LCD控制器等)集成在一片芯片上二、ARM指令集1.条件码CMP r3, #0 CMP r3, #0BEQ Skip ADDNE r0,r1,r2ADD r0,r1,r2Skip: Skip:合理使用条件码,可以提高代码密度,减少分支跳转指令的数目(避免清空流水线),提高了性能2.后缀S的作用:刷新CPSR寄存器中的条件码标志位,使得后续的指令可以根据带S指令的执行结果来判断本条指令是否要执行。
比较指令不用加S后缀3.分支指令B/BLBL相对于B指令,CPU会自动将返回地址保存在LR寄存器当中,从分支返回可以用LR寄存器的值恢复PC,从而完成调用的返回。
两条指令用24 bit 来存放偏移量,对于ARM指令集来说,每条指令4个字节长,则指令按照4字节对齐,那么指令地址的最低两位比特始终为0,在跳转指令中并未表示最低的两位,所以真正的偏移量是26 bit。
其中1 bit用来表示符号,所以跳转的范围为+/‐2^25 = +/‐32M。
如要实现长跳转,则可多次跳转,也可以将跳转的目的地址先保存到存储器中,然后将该地址从存储器中取出,赋给PC 4.数据处理指令Cond:指令的条件码。
Opcode:指令操作码。
S:操作是否影响cpsr,S=0不影响,S=1影响。
Rn:包含第一个操作数的寄存器编码。
Rd:目标寄存器编码。
Operand2:第2操作数、RmI:用于区别Operand2是立即数(I=1),还是寄存器移位(I=0)Shift amount:移位数Shift:移位方式关于比较指令的助记如下,但是比较指令不会保存结果,只影响标志CMP<‐>SUBSCMN<‐>ADDSTST<‐>ANDSTEQ<‐>EORS注意,MVN指令是取反传送指令,并非取负数传送指令减法指令对C标志的影响是反的,不过这由CPU自动处理移位操作LSL: x << yLSR: (unsigned)x >> yASR: (signed)x >> yRORRRX合法立即数:立即数保存在指令中,一条ARM指令是32 bit,所以不能存放一个32 bit的立即数,在一条指令中只有12 bit来表示立即数,但是并未将立即数就此限定在0~4095,而是用8 bit来表示一个数,另外4 bit来表示对这8 bit数的移位,最终的移位结果就是要表示的立即数。
显然这种方式也不能表示完32 bit 的立即数,只是相对于前一种方式,将不同的数分散在数轴上,而不是集中在一小段范围。
故而,有些立即数能被正确表示,而有的则不能被表示。
判断一个数是否是合法的立即数,或者说能否在指令中被正确表示的方法是:将数写成2进制,通过循环移位的方式,将为1的位尽量靠在一起,放在低8位,然后查看为1的比特位数跨度是否不大于8,如果是,再进一步判断移位的次数是否为偶数次,如果是则表明该数是一个合法的立即数,反之则不是。
对于非法立即数,使用LDR伪指令,编译器会自动处理。
5.单据传送指令LDR STR WordLDRB STRB ByteLDRH STRH HalfwordLDRSB 带符号的byte loadLDRSH 带符号的halfword load指令中的S表示符号扩展,如将0xFF扩展为0xFFFFFFFF6.块数据传送指令LDM STM WordIA: I ncrement A fter (先操作,后增加)IB: I ncrement B efore (先增加,后操作)DA: D ecrement A fter (先操作,后递减)DB: D ecrement B efore (先递减,后操作)寄存器传送顺序是固定的,不能被改变最小数字的寄存器总是被对应到存储器的最低地址上STM FD (Push) 块存储‐ Full Descending stack [STMDB]LDM FD (Pop) 块装载‐ Full Descending stack [LDMIA]7.信号量操作指令SWP{<cond>}{B} Rd, Rm, [Rn]一次存储器读和一次存储器写组成的原子操作,适用于信号量操作Rd和Rm可以是同一寄存器,这样可以完成寄存器和存储单元的原子数据交换不能由C编译器产生,只能由汇编语言来编写8.软中断指令SWI{<cond>} <SWI number>关键在于软中断号的获取和参数的传递常用作于系统调用的实现9.状态寄存器访问指令MRS{<cond>} Rd,<psr> ; Rd = <psr>MSR{<cond>} <psr[_fields]>,Rm ; <psr[_fields]>对状态寄存器的访问只能使用这两条指令状态寄存器被划分为4个域,分别是控制域(c),扩展域(x),状态域(s)和标志位域(f)对于MSR指令,可直接将一立即数写入状态寄存器在用户模式下对所有域可读,但只对标志位域可写,实现特权级和非特权级的关键。
这也意味着用户模式下不能修改处理器模式,不能使能或屏蔽中断10.协处理器指令MRC:从协处理器寄存器移到ARM 寄存器MCR:从 ARM 寄存器移到协处理器寄存器。