新闻  |   论坛  |   博客  |   在线研讨会
LPC学习
sdjntl | 2010-05-30 15:08:47    阅读:5102   发布文章

寄存器和工作模式:

7种工作模式:
fiq/irq/abt/und/sys/usr/svc。通过"MSR cpsr_c,#0xdx"切换。上电时进入svc模式。
svc和usr的区别是:svc可以通过"MSR cpsr_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是一个最特殊的寄存器,结构如下:

31 30 29 28 27~8 7 6 5 4 3 2 1 0
N Z C V 保留 I F T M4 M3 M2 M1 M0

其中,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。

Prefetch Abort和Data Abort模式:
Prefetch Abort通常会发生在自修改指令之后。而Data Abort发生于向无效内存中取操作数时,通常是数据指针越过边界了。如果在scatter文件中不指定边界,若编译时内存分配超过了实际物理内存,一定会有Data Abort或Prefetch Abort发生。

对特殊功能寄存器的操作:
通常都有两个寄存器操作同一个特殊功能。一个是负责置位,另一个是负责清除。如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控制引脚功能。

Boot Block
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、首先,硬复位后所有的Special Function Registor都有默认值。不必考虑设置的顺序问题。可以先设置好中断,再开通模块功能。
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、修改C Compiler的优化级别为最低。重新编译。
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中可能没有传说中的优先级机制。

关于Spurious Interrupts:
其中Solution1、2、3皆可行。当然,最好的办法是不要老是关中断。
在18App的主循环中不断关闭/开启UART的中断以读取其缓冲区的长度及数据,出现以下现象:程序经常走进VICDefaultAddress!
解释:当UART中断产生时,Core latches the IRQ status,此时,UART的中断被关闭。然后,Core loads IRQ Address from VIC. the VIC will not be able to clearly identify the interrupt that generated the interrupt request, and as a result the VIC will return the default interrupt VICDefVectAddr.


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

关于周立功EasyJTAG设置:
计算机并口要设为SPP模式。
弹出Fatal Axd Error时,点击Connect mode...选择ATTACH...然后Restart即可。


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

编译和调试:

Project->Remove Object Code...删除当前运行代码,然后可以重新编译。
Axd Debugger运行时会产生C:\documents and settings\username\default-1-2-0-0.sec.如果在打开Axd Debugger时不能自动调入Image, 可以删除此文件,重新打开Axd Debugger, 然后调入Image即可。

单步执行时对特殊功能寄存器的监视:
要监视Timer0寄存器组,从0xE000,4000开始。打开"Processor View"->"Memory"定位在0xE0004000。刚开始运行时监测结果正常,几个循环后,0xE0004000(T0PR)开始不断变化,而这个寄存器除了初始化时,不应该变化的。本应该变化的寄存器如0xE0004008(T0TC)反而不变了。于是打开"Processor Views"->"Watch",在里面加入 *((unsigned long*)0xE0004000)至 *((unsigned long*)0xE000403C)进行观察。发现Watch窗口的内容与Memory中的不同,似乎是Memory中的内容与其对应的地址产生了4个字节的错位。因为Memory中0xE000400C的内容总是与Watch中0xE0004008的内容相近,两者的差别大概是JTAG两次读RAM的时间差。另外,RAM的0xE000401C与Watch中0xE0004018内容相同。所以,Watch窗口的内容是正确的。

Debug:
Axd的Disassembly窗口:有单三角箭头的两个按钮,用于在小范围内(页内)滚动汇编程序。也有双三角箭头的两个按钮,用于在整个汇编程序的范围内移动。

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
在路上
最近文章
ARM的开发步骤
2010-05-30 17:13:59
LPC2XXX系列问答(二)
2010-05-30 17:08:12
LPC2XXX系列问答(一)
2010-05-30 17:07:28
推荐文章
最近访客