ARM必须知道的知识.docx

上传人:b****4 文档编号:11986464 上传时间:2023-04-16 格式:DOCX 页数:17 大小:26.94KB
下载 相关 举报
ARM必须知道的知识.docx_第1页
第1页 / 共17页
ARM必须知道的知识.docx_第2页
第2页 / 共17页
ARM必须知道的知识.docx_第3页
第3页 / 共17页
ARM必须知道的知识.docx_第4页
第4页 / 共17页
ARM必须知道的知识.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

ARM必须知道的知识.docx

《ARM必须知道的知识.docx》由会员分享,可在线阅读,更多相关《ARM必须知道的知识.docx(17页珍藏版)》请在冰豆网上搜索。

ARM必须知道的知识.docx

ARM必须知道的知识

寄存器和工作模式:

7种工作模式:

fiq/irq/abt/und/sys/usr/svc。

通过"MSRcpsr_c,#0xdx"切换。

上电时进入svc模式。

svc和usr的区别是:

svc可以通过"MSRcpsr_c,#0xdx"自由切换到其它任何模式,但是usr不可以。

各模式下有自己的堆栈。

要在程序启动后依次进入各个模式分别设置自己的堆栈,最后进入usr模式。

好多个寄存器:

r0-r7(a1-a4/v1-v4),r15(pc)在所有模式下都可见。

r8(v5),r9(sb,v6),r10(sl,v7),r11(fp,v8),r12(ip)fiq模式下有一组独立的映射。

r13(sp)/R14(lr)在usr和sys模式下用同一组映射,其它模式下各有自己的映射。

cpsr在所有模式下可见。

spsr在usr和sys模式下没有映射。

cpsr是一个最特殊的寄存器,结构如下:

3130292827~876543210

NZCV保留IFTM4M3M2M1M0

其中,N/Z/C/V分别为负/零/进位/溢出的标志位。

在所有模式下都可以进行读操作。

I/F为中断/快中断禁止位,M4~M0是工作模式控制位,它们在USR模式下都不可操作。

T为Thum/ARM模式位,在所有模式下不可直接操作,否则会天下大乱,预取址错误中断可以捕获这种乱局。

只能用BX指令进行Thum/ARM的状态切换。

总之,USR模式很不方便。

在该模式下只可以通过软中断控制I/F位。

cpsr只能够用MSR/MRS指令来操作。

各工作模式下的spsr:

在由突发事件引起的模式切换发生时,新模式的spsr自动保存cpsr的值,以备该模式退出时还原cpsr。

在程序的控制下进入某模式时,cpsr不会自动保存到相应的spsr。

PrefetchAbort和DataAbort模式:

PrefetchAbort通常会发生在自修改指令之后。

而DataAbort发生于向无效内存中取操作数时,通常是数据指针越过边界了。

如果在scatter文件中不指定边界,若编译时内存分配超过了实际物理内存,一定会有DataAbort或PrefetchAbort发生。

对特殊功能寄存器的操作:

通常都有两个寄存器操作同一个特殊功能。

一个是负责置位,另一个是负责清除。

如VICIntEnable和VICIntEnClr,IOxSET和IOxCLR等。

这样就使得单独操作某一位或某几位变得非常容易,如:

IO0SET=0x00001100;IO0CLR=0x00000011等,只变动特定的位,而不影响其他位。

当然也可以用IO0PIN=0x00001100直接设置所有的位。

--------------------------------------------------------------------------------

存储器映射:

0-1G(0x0000,0000-0x3fff,ffff):

片内Flash.

1-2G(0x4000,0000-0x7fff,ffff):

片内RAM.

2-3.5G(0x8000,0000-0xbfff,ffff-0xdfff,ffff):

片外存储器。

3.5G-3.75G(0xe000,0000-0xefff,ffff):

VPB外设。

3.75G-4G(0xf000,0000-0xffff,ffff):

AHB外设。

虽然ARM7的寻址空间为4G,但是LPC2200系列只提供A0~A23总共16M的地址。

片选信号CS0-CS3是A24和A25的译码输出,将片外存储区0x8000,0000-0x83ff,ffff划分为bank0-bank3,共16M*4=64M.这4个bank可以被分别配置为8/16/32位总线宽度。

复位时,bank0的总线宽度由Boot1:

0引脚决定,bank1为32位,bank2为16位,bank3为8位。

字节定位信号(BLS0-BLS3)协调总线宽度和外存芯片数据线宽度。

当Memory由“字节宽度器件”(如62256)或者“未按照字节区分的多字节器件”组成时,应将RBLE设置为"0"。

此时,读访问时EMC将BLS0~BLS3拉高。

当Memory由“含有字节选择输入的16位或32位器件”组成时,应将RBLE设置为"1"。

此时,读访问时EMC将BLS0~BLS3拉低。

所以,当Memory由62256组成时,由于不需要“片内字节选择输入”,故令RBLE='0',则BLS0~BLS3只会与nWR同步,可以代替nWR使用。

但是,当Memory由IS61LV25616AL组成时,由于该芯片有"nLB"和"nUB"控制低/高8位的输入,故令RBLE='1',则BLS0~BLS3与nRD和nWR都会同步,此时,不可以使用BLS0~BLS3代替nWR信号。

地址数据总线:

D0-D31,A0-A23,OE,WE,CS0-CS3,BLS0-BLS3

启动后由P2.7/P2.6控制引导方式,然后由程序设置MEMMAP决定中断向量的映射。

BCFG0-BCFG3控制读写延时和总线宽度。

注意复位后的默认值。

PINSEL2控制引脚功能。

BootBlock

LPC2114/2214的BootBlock被固化在最高的Flash块中,运行时被映射到0x7FFF,E000-0x7FFFF,FFFF的区域。

而LPC2210没有片内Flash,但它有8K片内ROM存储了BootBlock,也被映射到0x7FFF,E000处。

--------------------------------------------------------------------------------

VPB只是ARM内部使用的总线,它通过桥与AHB总线连接,对用户透明。

所以,不必考虑它的存在,只要知道0xe000-0xffff,ffff是外设控制器的地址就可以了。

--------------------------------------------------------------------------------

VIC:

ARM有19个中断源,为其分配了0-18号VIC通道。

向量控制寄存器VICVectCntl0-15记录了各个通道号及其使能位。

当中断发生时,VICVectAddr0-15中的一个值会被copy到VICVectAddr.

如果是非向量中断则VICdefaultAddr被copy到VICVectAddr.

程序跳转到VICVectorAddr指向的地址。

中断返回时,写0x00到VICVectAddr.

非向量中断是指那些虽然已经打开(允许),但是没有在相应的VICVectorCntl0~15和VICVectorAddr0~15中设置的中断。

关于中断设置:

1、首先,硬复位后所有的SpecialFunctionRegistor都有默认值。

不必考虑设置的顺序问题。

可以先设置好中断,再开通模块功能。

2、软中断(SWI)与非向量中断不同,它的入口是0x0000,0008。

进入软中断后,系统变为管理模式。

而非向量中断入口是0x0000,0018。

它引导系统进入fiq/irq模式。

3、VIC设置实例:

  VICIntSelect=0x00000000;  //所有中断都是IRQ

  VICVectCntl0=0x20|15;  //EINT1为向量中断,使用Slot0

  VICVectAddr0=(uint32)EINT1_Exception;  //EINT1中断地址

  VICDefVectAddr=(uint32)Default_Entry;  //非向量中断地址

  VICIntEnable=0x00018000;  //使能EINT1和EINT2

  由于在管理向量中断的VICVectCntl0~15和VICVectAddr0~15中只设置了EINT1,故EINT2中断发生时,要进入非向量中断处理程序Default_Entry。

关于优先级:

在调试C语言的多中断程序时,在中断中设断点,调了几个循环就全乱了。

开始时怀疑编译器有问题,后来发现是Debugger不够好。

测试如下:

1、修改CCompiler的优化级别为最低。

重新编译。

2、令Timer0定时0.25秒中断,在中断中将Test++。

  令EINT3(外部RTC)1秒中断,在中断中用LCD显示Test的值并将一个LED取反。

然后再用软件延时,占据CPU0.9秒或0.5秒后才退出中断。

3、令Timer0的优先级小于EINT3。

LED为1秒断续,LCD显示的Test值一秒加一。

4、令Timer0的优先级大于EINT3。

LED为1秒断续,LCD显示的Test值一秒加一或加二或加四。

结论:

Timer0中Test加一/加二/加四是在EINT3退出后的间隙中完成的。

所以,IRQ中可能没有传说中的优先级机制。

关于SpuriousInterrupts:

在18App的主循环中不断关闭/开启UART的中断以读取其缓冲区的长度及数据,出现以下现象:

程序经常走进VICDefaultAddress!

解释:

当UART中断产生时,CorelatchestheIRQstatus,此时,UART的中断被关闭。

然后,CoreloadsIRQAddressfromVIC.theVICwillnotbeabletoclearlyidentifytheinterruptthatgeneratedtheinterruptrequest,andasaresulttheVICwillreturnthedefaultinterruptVICDefVectAddr.

--------------------------------------------------------------------------------

关于周立功EasyJTAG设置:

计算机并口要设为SPP模式。

弹出FatalAxdError时,点击Connectmode...选择ATTACH...然后Restart即可。

--------------------------------------------------------------------------------

编译和调试:

Project->RemoveObjectCode...删除当前运行代码,然后可以重新编译。

AxdDebugger运行时会产生C:

\documentsandsettings\username\default-1-2-0-0.sec.如果在打开AxdDebugger时不能自动调入Image,可以删除此文件,重新打开AxdDebugger,然后调入Image即可。

单步执行时对特殊功能寄存器的监视:

要监视Timer0寄存器组,从0xE000,4000开始。

打开"ProcessorView"->"Memory"定位在0xE0004000。

刚开始运行时监测结果正常,几个循环后,0xE0004000(T0PR)开始不断变化,而这个寄存器除了初始化时,不应该变化的。

本应该变化的寄存器如0xE0004008(T0TC)反而不变了。

于是打开"ProcessorViews"->"Watch",在里面加入*((unsignedlong*)0xE0004000)至*((unsignedlong*)0xE000403C)进行观察。

发现Watch窗口的内容与Memory中的不同,似乎是Memory中的内容与其对应的地址产生了4个字节的错位。

因为Memory中0xE000400C的内容总是与Watch中0xE0004008的内容相近,两者的差别大概是JTAG两次读RAM的时间差。

另外,RAM的0xE000401C与Watch中0xE0004018内容相同。

所以,Watch窗口的内容是正确的。

Debug:

Axd的Disassembly窗口:

有单三角箭头的两个按钮,用于在小范围内(页内)滚动汇编程序。

也有双三角箭头的两个按钮,用于在整个汇编程序的范围内移动。

Axd的"Lowlevelsymbles"窗口可用于观察各变量的地址,此窗口在辅助阅读Disassembly时有用。

--------------------------------------------------------------------------------

分散加载描述文件.scf的设置

MetrowerksCodeWarriorV1.2的"Edit->DebugInExRAMSettings",然后在"Linker->ARMLinker"的Output页中,选中Scatter选项。

在Scatter的编辑框中选择写好的.scf文件。

(Scatter-Loadingdescriptionfile).

简单应用时可以不写.scf文件。

而在"Output"页中选择"Simple".然后填写"ROBase"和"RWBase"的起始地址。

在"LayOut"页中,填写Object/Symble:

Startup.o,Section:

Start.编写启动文件:

Startup.s.

在"Option"页里的"ImageEntryPoint"填入起始地址。

--------------------------------------------------------------------------------

Scatter-LoadDescriptionFile的结构:

".scf"文件中的"+RW"对应".s"源文件中的"READWRITE".

".scf"文件中的"+ZI"对应".s"源文件中的"NOINIT".

".scf"文件中的"+RO"对应".s"源文件中的"READONLY".

在".s"源文件中有:

AREAarea_nameCODE/DATA,READONLY/NOINIT/READWRITE

END

".scf"的例子:

内容 注解

ROM_LOAD0x80000000

{ NameofLoadRegion,StartAddressforLoadRegionandMaximumsizeofLoadRegion(省略了)

 ROM_EXEC0x800000000x20000

{片外存储区,从0x80000000开始,最多0x20000字节。

 Startup.o(Vector,+First)Startup模块的Vector段放在最前面。

注1

 *(+RO)其他所有模块中的所有代码和只读的数据放在这里。

 } 

 IRAM0x400000000x00004000

{片内RAM区,从0x40000000开始,最多0x4000字节

 Startup.o(MyStacks,+first)指定Startup.o中MyStacks放在最前面。

 Startup.o(+RW,+ZI)Startup.o中的其他+RW/+ZI段。

注1

 os_cpu_a.o(+RW,+ZI) 

 } 

 STACKS0x40004000UNINIT

{片内16KRAM的顶端,存放不需要被"Clibrary"初始化的段。

 Stack.o(+ZI)注2

 } 

 ERAM0x80040000

{ 

 *(+RW,+ZI) 

 } 

 HEAP+0UNINIT

{"+0"表示接着上一段"ERAM"的结尾,继续安排存储区。

 Heap.o(+ZI)注3

 } 

}  

下面是在scf文件中引用过的源文件示意:

"Startup.s"

  code32

  areaVectors,CODE,READONLY

  entry

  ...

  end注1:

在"Startup.o"里面会生成名为"Vectors"的段,段的属性为"READONLY"

"Stack.s"

  areaStacks,DATA,NOINIT

  exportStackUsr

StackUsr  SPACE1

  end注2:

在"Stack.o"里面会生成名为"Stacks"的段,段的属性为"NOINIT",该属性对应scf文件中的"+ZI".该段不需要初始化或者可以被初始化为"0".

"Heap.s"

  areaHeap,DATA,NOINIT

  exportbottom_of_heap

bottom_of_heap  SPACE1

  end注3:

"Heap.o"里面名为"Heap"的段。

在Scatter文件中最好每一个Region都加一个Maximum参数,这样当编译时如果实际使用的空间大于MaximumSize,会有Error:

16220E:

Excutionregionxxxsize(xxxbytes)exceedslimit(xxbytes)。

如果地址有重复,会有Error:

16221E:

Excutionregionxxxoverlapswithexcutionregionxxx。

前一个Region的首地址+Maximum>后一个Region的首地址时不一定有Error。

只有当一分配的内存出现覆盖时才会有Error。

Region的"UNINIT"之类的参数要放在"Maximumsize"参数之前。

在一个Region中,RAM的分配不是按照罗列的顺序来的。

要想让汇编中使用的变量有固定的位置,可以把所有汇编文件产生的".o"放在同一个Region中。

如:

IRAM10x40000000

{

  startup.o(+RW,+ZI)

  ASMSourceCode1.o(+RW,+ZI)

  ASMSourceCode2.o(+RW,+ZI)

}

IRAM2+0

{

  CSourceCode1.o(+RW,+ZI)

  CSourceCode2.o(+RW,+ZI)

}

这样,所有汇编中定义的变量地址就相对集中了。

如果只有一个汇编文件如startup.s,也可以这样:

IRAM0x400020000x1000

{

  startup.o(Mystack,+first)

  *(+RW,+ZI)

}

用一个"+first"强行将startup.s中的Mystack放在0x40002000位置。

在"Edit->DebugRelSettings...->ARMLinker"中选中"Imagemap"。

编译后在Error&Warnings窗口会显示出详细的内存分配情况。

如果在"Listfilename"中指定一个输出文件名,该祥单会直接存在制定文件中以供多次研究。

--------------------------------------------------------------------------------

关于JTAG接口:

P1.20/TRACESYNC应该加上拉电阻以禁止TRACE功能。

PINSEL2一定要在程序开始时初始化一下。

LPC2210

JTAG

 1,2/VDD3.3V 

P1.31/nTRST,input3/nTRST,outputEasyJTAG中有上拉电阻。

P1.28/TDI,input5/TDI,outputEasyJTAG中有上拉电阻。

P1.30/TMS,input7/TMS,outputEasyJTAG中有上拉电阻。

P1.29/TCK,input/output9/TCK,input/outputEasyJTAG中有上拉电阻。

P1.26/RTCK,input11/RTCK,outputP1.26外接下拉电阻。

P1.26有内部上拉电阻,故测量时该引脚会呈现高电平。

但是在复位时,它的上拉电阻不起作用,只有外部的下拉电阻起作用,P1.26=0V,所以上电后PINSEL2的D3~D0会是0x04(B0100),JTAG有效。

若将P1.26接到3.3V再复位,此时PINSEL2的D3~D0将会是0x00,JTAG无效。

P1.27/TDO,output13/TDO,inputEasyJTAG中有上拉电阻。

nRESET,input15/nRST,outputEasyJTAG中有上拉电阻。

 4,6,8,10,12,14,16,18,20/GND 

 17,19/NC 

G18控制板采用LPC2114,每次运行Axd都不会正确调入程序。

原因如下:

有一次是因为已经有一个Axd在运行了,打开第二个Axd,当然不会正确调入程序。

还有一次是重新编译了一下,就好了。

以上两次都不奇怪,奇怪的是下面几次:

在"ConfigTarget->Config->EasyJTagSetup"随便点两下"HaltMode"中的选项,然后一路点击"OK",会出现"ReloadthelastImage?

",点击"Yes"。

有时会有正确的程序被调入,但有时候不成功。

要检验是不是已经成功调入了,只要按下"Ctrl-D"显示Disassembly窗口,即可看到芯片中的程序是否正确。

在"Option->ConfigInterface->SessionFile->SessionfileOptions"中选择"ReloadImages",之后每次启动Axd都会提示"TheprocessorARM_1alreadyhasimage(s)loaded.Continuetheoperationwillreplacethecurrentlyloadedimages(s)....Doyouwishtocontinue?

"选择"Yes",有时候也可以成功调入程序。

当然,在"EasyJTagSetup->AuxOption"中要选中"EraseFlashwhenneed".

固化的程序中有禁止JTag调试端口的语句(操作PINSEL2的语句),连不上时用LPC2000FlashUtility擦除了Flash。

偶尔可行。

注意使用LPC2000FlashUtility时要先将电路复位,再点"OK".

当然最根本的解决办法是将计算机并口设置为"EPP"模式。

其他地方都按照"Default"就可以了。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 文化宗教

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1