分类: LINUX
2010-03-10 08:34:37
当ARM处理器上电或者Reset之后,处理器从0x0取指。因此,必须保证系统上电时,0x0处有指令可以执行。所以,上电的时候,0x0地址处必定是ROM或者Flash(NOR)。
Remap
1.什么是Remap?
在ROM从0x0用几句指令引导系统之后,把RAM映射到0x0就是Remap。比如AT91RM9200,系统资源:片内128K的rom,片内16K的SRAM。复位后片内的ROM可以通过0x0和0x0010_0000来访问,片内SRAM通过0x0020_0000来访问。系统启动后,通过Remap命令可以把片内SRAM映射到0x0处,即remap后,只能通过0x0010_0000访问片内rom,通过地址0x0和0x0020_0000访问片内SRAM。
Remap前后,不同之处就是片内RAM的位置变了。
2.Remap的作用,为何要进行remap呢?有什么好处?
为了加快启动的速度,也方便可以更改异常向量表,加快中断响应速度,往往把异常向量表映射到更快、更宽的RAM中。但是异常向量表的开始地址是由ARM架构决定的,必须位于0x0处,因此,必须把RAM映射到0x0处。
所以9200如果要执行带中断的程序,必须Remap。
3.Remap的实现
Remap的实现和ARM处理器的实现相关。
1)如果处理器有专门的寄存器可以完成Remap。那么Remap是通过Remap寄存器的相应bit置1完成的。如Atmel AT91RM9200的MC_RCR寄存器中RCB位,注意该命令位是切换的,如果已经remap了,执行后将取消remap。
2)如果处理器没有专门的寄存器,但是memory的bank控制寄存器可以用来配置bank的起始地址,那么只要把RAM的起始地址编程为0x0,也可以完成remap。如samsung s3c4510
3)如果上面两种机制都没有,那么Remap就不要做了。因为处理器实现决定了SDRAM对应的bank地址是不能改变的。如Samsung S3c2410.
4)如果象2410那样不能Remap的话怎么办?2410不是不能Remap吗?为了加快启动速度,可以这样做:
A.使用它的NAND boot模式。为什么NAND boot会比较快,那是因为2410里面有块小石头——“SteppingStone”,一块4KB SRAM,它是映射在0x0的。启动程序会自动被copy到这个石头里面。自然异常向量的入口放到这个地方,一样可以达到比NOR boot快的启动、异常响应速度。
B.如果你对NOR Boot情有独衷,那么你只好把你的异常向量的入口copy到SDRAM里面,实现所谓的High Vector.
Initboot.c
一般在LowlevelInit()部分设置向量表:
|
程序主体部分:main.c
|
Asm_isr.s部分:
这部分汇编代码主要是为了能够实现中断嵌套做得一些现场保护,如果整个处理器只有一个中断源使能了,这部分代码可以只保留跳到C的那部分。
|
为了理解AIC的工作过程,最好跟踪一下寄存器的值是如何变化的。所以把AIC配置在保护模式下。
0xfffff09C SVR[AT91C_ID_US1]
0xfffff100 IVR
0xfffff108 ISR
0xfffff10c IPR
0xfffff110 IMR
0xfffff114 CISR
图1 目标板启动后跳到mian函数
图2 串口和中断配置完成
观察到中断配置好后,中断服务程序的地址已经写到SVR[US1]中,=0x00200458,观察反汇编代码0x00200458处存放的就是AT91F_IRQ0_ASM_HANDLER。IMR中US1置位,表示US1中断使能。
图3全速运行,在串口助手中发了个数据,且预先在0x18处设了个断点
注意红色部分,观察到,程序在0x18处停下来,说明中断产生后,程序要跳转到0x18处,且处理器进入IRQ模式,IVR把中断源对应的SVR读进去,CISR寄存器对应的nIRQ置位,说明给arm核的nIRQ中断信号线出现,即将进入中断。IPR对应的中断源位置位,表明US1产生的中断挂起了。下一步就是执行该中断源对应的中断处理函数。下一步跳转到IVR内容指定的地址处。
图4a SMR电平域设置为电平敏感
图4b SMR电平域设置为边沿触发
为了能够观察ISR寄存器的内容,必须在保护模式下对IVR执行一个写操作,且在IVR的读与写之间不要设置断点,否则会破坏AIC的状态,观察不到正确的数据(手册上写的)。所以我们在写IVR操作执行后设了一个断点。然后可以看到ISR的内容变成07(这个正是US1的ID,表示US1的中断服务程序正在执行)。IVR又回到了默认值。CISR中nIRQ信号清除。
注意电平敏感模式和边沿触发模式,有一个差别,就是在边沿触发模式下,IPR中断源自动清除,而电平敏感模式下,并没有自动清除,手册上说如果是电平敏感模式,要在中断处理程序中清除中断源,可是我的中断处理程序中并没有写ICCR寄存器,为何在进入C handler后执行了一条指令后,就自己清除了IPR,跟手册似乎不一样。这一点现在还是有点不明白。
图5 切换处理器模式 进入SYS模式
图6a单步进入c处理函数(电平敏感模式)
图6b 电平敏感模式下的 程序中并没有写ICCR寄存器,进入C handler后执行了一条指令后,自动清除IPR
图7 写EOICR中断结束命名后,ISR清除,表示此次中断完成
调试AIC过程中遇到的问题:
1, 刚开始的时候不知道调试AIC需要在保护模式下,看9200手册的时候对这一块也没有认真的去看。
2, 如果没有配置AIC在保护模式下,当打开AXD的memory观察AIC的各个寄存器内容时,这样会破坏AIC的状态,导致中断服务程序不能正常进行。刚开始不知道这个问题,同样的操作,我的程序一会儿能进中断,一会不能进中断,问师兄,师兄他们也不知道。去找老板,老板还没有等我把话说完,就让我自己先去检查程序,让我好好的把中断过程理解一下。我仔细检查了一下程序,也没有发现什么问题,就是最简单的配置串口和aic,能有什么问题。唉,搞了几天也搞不明为什么程序一会能行,一会又不行了。按说复位arm板子应该就可以了,砸电脑的心都有了。后来在网上无意中看到21ic的阿南版主的一个调试笔记,才发现了问题所在——因为开了memory观察窗口。太感谢阿南版主了,也挺佩服阿南版主的,为什么我就没有注意到这个问题呢?反思……
3, 该程序还有个小问题,就是当在pc调试助手中一次发送很多数据时,比如发200个数据时,就会产生数据丢失的问题。通过问题的排查,终于找到了问题所在,因为我的串口数据是以固定速率发过来的,但是我通过中断接收,然后在中断中发送,因为有while(!(AT91C_BASE_US1->US_CSR&AT91C_US_TXRDY));这样一个等待过程,导致某个RHR的内容还没有取走,下一个数据已经发过来了,覆盖了没有取走的数据,这样就产生数据丢失了。
因为我在中断处理程序中,把发送部分删掉,加上语句receive[i++]=temp;这样把每次中断接收的数据存在一个数组中,通过观察数组的内容,发现跟我发送的内容一致,没有数据丢失,由此判断是因为while的等待造成了数据丢失。