打印
[ZLG-ARM]

写LPC2220的BOOT时遇到了应用程序中断不发生的情况

[复制链接]
1971|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
freny|  楼主 | 2008-8-18 16:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在用LPC2220写BOOTLOAD时,处理中断上碰到了麻烦,我本意是在BOOT的IRQ中断地址(外
部FLASH0x80000018)让他跳转到外部的RAM(0x81000018,应用程序拷贝到0X81000000后
部),然后由应用程序的中断再做处理。
中断表映射设置的都是由外部,即外部FLASH,先到外部FLASH的BOOT,然后靠代码跳转到
应用程序的中断表。
BOOT程序:
   。。。。
   ;中断向量表
Reset
。。。 
LDR     PC, IRQ_Addr
        LDR     PC, FIQ_Addr
        。。。
        IRQ_Addr            DCD     0x81000018//这样就跳转到外部RAM的中断表中了
        FIQ_Addr            DCD     0x8100001c

APP程序:

    LDR     PC, IRQ_Addr
    ...
    IRQ_Addr            DCD     IRQ_Handler
FIQ_Addr            DCD     FIQ_Handler
......
;IRQ中断
IRQ_Handler
        STMFD   SP!, {R0-R3, LR}
        mov r0,#0x020
        ldr pc,[r0,#-0x0ff0]//这样就进入了VIC向量中断处理了
        LDMFD   SP!, {R0-R3, LR}
        SUBS    PC,  LR,  #4
 //以上想法应该 什么问题,但始终应用程序无法发生中断,请问是什么原因造成的?是
不是LDR跳转不了这么大的范围?  
 
 另一个问题,我在BOOT中没做中断跳转,而是还是指向向量中断,这样不管BOOT还是应用
程序都可用向量中断了:
    LDR     PC, [pc,#-0xff0] 
 但现在问题出来了,应用程序中我试了下直接在ADS中设置运行地址还是用分散加载的方
法,两种方法都发现,一定不能使得STARTUP.O的vectors放程序的最前面,就是在分散加
载文件中(Startup.o (vectors, +First)这句),不能用这句,如果加了该句应用程序进
不了中断处理,ADS设置中设置ARM Linker中的Layout项中的object/symbol 和section也
起到同样作用,同样不能设置,已设置了就进不了中断。
 
 请各位牛人能指点一二。谢谢!

相关帖子

沙发
yangvu| | 2008-8-19 08:35 | 只看该作者

回复主题:写LPC2220的BOOT时遇到了应用程序中断不发生的情况

一我的理解,你是想然程序在外部flash运行,同时要使异常向量表处能正常运行,我觉得可以用scatter文件将代码的运行地址设置为外部地址,然后将存储器映射设置为映射到外部存储器就可以了。

使用特权

评论回复
板凳
freny|  楼主 | 2008-8-19 09:50 | 只看该作者

回复主题:写LPC2220的BOOT时遇到了应用程序中断不发生的情况

多谢指教,我是想把BOOT程序存储在外部FLASH,然后利用scatter文件将STARTUP.O外的其他文件加载到内部RAM中运行,而应用程序存储在BOOT程序之后,BOOT在外部RAM运行后拷贝应用程序到外部RAM,然后跳转到外部RAM这样就可以启动应用程序了。BOOT的存储器映射设置是映射到外部FLASH的,应用程序映射到外部RAM(应用程序我的运行地址设置的是外部RAM,存在FLASH),而我外部FLASH的开头就是BOOT的中断跳转处理,这样中断以来就自然后找到外部FLASH的中断跳转处理,由BOOT的中断跳转处理就可以跳转到外部RAM相应的中断向量表了。
但现在不知何原因,很明显BOOT的中断是可以发生的,但如何都跳转不到外部的RAM中断向量表,而且一旦应用程序的中断向量表放置在程序最前部(即外部RAM的开头)处,无论如何中断都不发生,只有不强制放到最前部,而且BOOT不跳转到外部RAM而是直接跳转到向量中断表才能发生中断。
非常奇怪的问题,多谢。
BOOT的文件
ROM_LOAD 0x80000000
{
    ROM_EXEC 0x80000000
    {
        Startup.o (vectors, +First) 
        * (+RO)              
    }
    ROM_EXEC1 0x40000000
    {
        Test.o(+RO)
        flash.o(+RO)
        comm.o(+RO)                  
    }
    IRAM 0x40002000
    {
        Startup.o (MyStacks)
    }

    STACKS_BOTTOM +0 UNINIT
    {
        Startup.o (StackBottom)
    }

    STACKS 0x40004000 UNINIT
    {
        Startup.o (Stacks)
    }

    ERAM 0x40002800
    {
        * (+RW,+ZI)
    }

    HEAP +0 UNINIT
    {
        Startup.o (Heap)
    }

    HEAP_BOTTOM 0x40003000 UNINIT
    {
        Startup.o (HeapTop)
    }
}
应用程序的加载文件
ROM_LOAD 0x81000000
{
    ROM_EXEC 0x81000000
    {    
       Startup.o (vectors, +First)//这一句一旦加上中断就不会发生     
        * (+RO)
    }

    IRAM 0x40000000
    {
        Startup.o (MyStacks)
    }

    STACKS_BOTTOM +0 UNINIT
    {
        Startup.o (StackBottom)
    }

    STACKS 0x40004000 UNINIT
    {
        Startup.o (Stacks)
    }

    ERAM 0x81060000
    {
        * (+RW,+ZI)
    }

    HEAP +0 UNINIT
    {
        Startup.o (Heap)
    }

    HEAP_BOTTOM 0x81080000 UNINIT
    {
        Startup.o (HeapTop)
    }
}


使用特权

评论回复
地板
yangvu| | 2008-8-19 11:54 | 只看该作者

补充两点

1.外部存储器只能从0x8000 0000开始执行,lpc的异常向量重映射是映射到0x8000 0000的,不会到0x8100 0000,所以你的scatter文件那个地方不太对
2.你所说的boot具体是指那些,是从加电到异常向量表,还是从异常向量表到main函数

使用特权

评论回复
5
freny|  楼主 | 2008-8-19 14:32 | 只看该作者

详细情况

你好,很感谢你的指点。
我现在写一个BOOTLOAD,存储在外部FLASH的前32K(0X80000000开始),运行时依靠scatter文件的
ROM_EXEC 0x80000000
    {
        Startup.o (vectors, +First) 
        * (+RO)              
    }
    ROM_EXEC1 0x40000000
    {
        Test.o(+RO)
        flash.o(+RO)
        comm.o(+RO)                  
    }
这句使得ADS编译器自动将其Test.o、flash.o、comm.o拷贝到内部RAM(0X4000000)运行,这样就能读写外部FLASH。

这个BOOTLOAD的作用为接收PC传来的应用程序的BIN文件而将其写入外部FLASH32K以后的地方。或则将外部FLASH32K以后的100K(即应用程序代码)拷贝到外部RAM中(0X81000000),然后通过跳转到0X81000000开始运行应用程序,所以应用程序的scatter文件写成0X81000000应该没什么问题的?

中断异常向量始终是映射到0X80000000的,只是在0X80000000上的中断向量表是BOOTLOAD的,需要提供二次跳转,所以我就把BOOTLOAD的中断向量表都指向了应用程序的,而应用程序是在外部RAM中运行,所以应该指向0X81000004、0X81000008等。

所以我的BOOT是上电装载应用程序到外部RAM,其中他的中断异常向量只是做二次跳转而找到外部RAM内的应用程序的中断向量表,从而实现由应用程序来处理中断。

我IRQ中断BOOT是跳转到0X81000018,FIQ跳转到0X8100001C,然后由应用程序的按正常的来处理。

现在的问题是BOOT部分不能跳转到0X81000018,只能直接跳转到向量中断表去处理(LDR PC,[PC,#-0XFF0]),而且应用程序不能把中断异常向量表放到结果文件的前32个字节,不放前部的话IRQ中断可以执行,就是scatter文件的Startup.o (vectors, +First)这句, 这个我分析是因为BOOT部分直接跳到了向量中断表去处理了,应用程序的中断异常向量没有起到作用,只是应用程序提供了向量中断表中中断处理函数的地址,这就会造成其他中断是不会发生的。但我为什么只是把中断异常向量放到文件的前部中断就不发生了?BOOT只是跳向个固定的地址(向量中断表),然后来执行中断,应用程序只需设置中断并提供服务程序地址就可以了呀?
以下是应用程序部分:
    PINSEL1 = 3<<8;    // 设置管脚连接,P0.20设置为EINT3
                                        // 3<<8 等价于 0x00000180
    IO2DIR = LEDCON;// 配置LED                                
    //IO0DIR = BEEPCON;    // 设置B1控制口为输出,其它I/O为输入
    //IO0CLR = BEEPCON;
   EXTMODE = 1<<3;    // 设置EINT3中断为边沿触发模式
                                    // 1<<3 等价于 0x08
    EXTPOLAR = 0x00;    // 设置EINT3中断为下降沿触发
                
    /* 打开EINT3中断(设置向量控制器,即使用向量IRQ) */
    VICIntSelect = 0x00000000;    // 设置所有中断分配为IRQ中断
    VICVectCntl0 = 0x20|17;            // 分配EINT3中断到向量中断0
    // 0x20表示向量IRQ使能,1<<17表示EINT3在VIC通道17号
    VICVectAddr0 = (int)IRQ_Eint3;     // 设置中断服务程序地址
    EXTINT = 1<<3;        // 清除EINT3中断标志    
    VICIntEnable = 1<<17;  // 使能EINT3中断,EINT3在VIC通道17号
这样设置了向量中断0的服务程序地址,照理至少IRQ向量中断应该能发生呀,他不发生除非服务程序地址没对而跑飞了,但我发现应用程序
并没有跑飞,只是中断无反应而已。
    
再次感谢你的指点,祝工作顺利!谢谢!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

37

帖子

0

粉丝