- 积分
- 0
贡献0
飞刀0 FD
注册时间2016-5-6
在线时间0 小时
扫一扫,手机访问本帖
|
一直都在在uboot环境在调试裸机程序,以前为了实现中断调试,改了u-boot的源码,把0x00映射到物理地址上去,并且是在程序的中断向量表上,但是最近有进一步研究了一下中断发现其实可以不用修改u-boot源码来实现中断调试。关键点在内部的sram部分,就是在上电启动的时候内部的8Ksram被映射到了0x00地址上,而其真是物理地址是0x0c000000,这在数据手册上可以查到。其实在启动完成后在0x00地址上也可以访问到该内存。所以现在有一种不用修改u-boot源码的方法实现。代码如下:
首先准备init.s文件,这是在主函数执行先的准备。
IMPORT Main
IMPORT Uc_IRQHandler
EXPORT __ENTRY
AREA Init, CODE, READONLY
__ENTRY
b ResetHandler
b . ; handlerUndef
b . ; SWI interrupt handler
b . ; handlerPAbort
b . ; handlerDAbort
b . ; handlerReserved
ldr pc, =Uc_IRQHandler ; handlerIRQ
b . ; handlerFIQ
ResetHandler
nop
nop
nop
b Main
nop
nop
nop
nop
END
其中Uc_IRQHandle为中断发生后调用的函数可以用C写也可以用汇编写。如果想用6410的vic中断功能就推荐用汇编,很简单的几句话,给个参考
UC_IRQHandler
stmfd sp!,{r0-r3,r12,lr}
ldr lr, =int_return
ldr r0,=0x71200f00
ldr r0,[r0]
mov pc,r0
int_return :
ldmfd sp!,{r0-r3,r12,lr}
subs pc,lr,#4
这个地方有个小bug,就是ldr r0,=0x71200f00只是读取前32个中断地址,所以如果不是前面32个中断源发生中断的话这个地址上为0,你的程序会重启,注意下,别到时候找不到原因,呵呵。可以修改一下,先判断读进来的是不是0,如果是就是后面的32个中断源中一个发生了,这里又涉及到中断优先级,呵呵就是如果两个中断控制器都发生了中断,先读哪个就表示那个中断优先级高。
当然这段程序是不会自己跑到0x00的地方去的,也就是中断发生后这些代码是在你指定的编译地址上的,比如你指定RO为0x50008000,那么这段程序只会在这个地方呆着,所以为了调用它有要在主函数中加点东西,呵呵
extern char __ENTRY[];
void Remap(void)
{
unsigned long *s_addr,*d_addr;
unsigned long len=1024;
int i;
s_addr = (unsigned long *)__ENTRY;
d_addr = (unsigned long *)0x0;
for (i=0;i<len;i++)
{
d_addr[i] = s_addr[i];
}
}
好了在主函数中最开始的地方调用一下Remap函数就可以了,以后中断发生了就可以调用你的中断函数了。
(注:关于VIC中断控制器部分,可以参考lpc系列处理器,这个跟它用的一样的,而和以往三星cpu的中断处理方法都不一样,这点要注意,6410的VIC控制器很好,简化了我们写程序的复杂度,步骤:(1)写好中断函数,在rvds下不要想以前写的那样加上__irq,就和普通函数一样;(2)查cpu手册看你要写的中断是vic对应的第几个中断源;(3)在中断控制器中选择你要设置的中断是irq中断还是fiq中断,这里的例子都是irq,fiq的差不多;(4)把中断函数的地址赋值给对应的中断地址寄存器,每个中断源对应一个,具体看cpu数据手册;(5)设置中断源的优先级,这一步如果没有特殊要求可以不用;(6)在vic控制器中打开对应的中断使能;(7)打开你要操作的外设的中断使能(如果有的话);(8)完了,真的完了,然后该干嘛干嘛去吧,中断不用你管了,中断发生后就自动条用你写的中断函数,比2440的简单写吧,注意一点的就是在你的中断函数最后必须执行一次写中断地址寄存器,0通道的寄存器地址是0x71200f00,1通道的没记住自己查,比如0通道的所有中断函数最后必须加上一句(*(volatile unsigned long *)(0x71200f00))=0,否则下面的中断就不能处理了。) |
|