ARM必须知道的知识.docx
- 文档编号:11986464
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:17
- 大小:26.94KB
ARM必须知道的知识.docx
《ARM必须知道的知识.docx》由会员分享,可在线阅读,更多相关《ARM必须知道的知识.docx(17页珍藏版)》请在冰豆网上搜索。
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"就可以了。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ARM 必须 知道 知识