打印

谢谢d1d2前辈提供的线索

[复制链接]
1422|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
biehoff|  楼主 | 2008-11-25 23:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
AD, ni, ROM, RAM, AI
谢谢d1d2前辈提供的线索
看了《ARM体系结构与编程》中的连接器部分 和ADS的ARM LINKER文档
对分散加载有点点了解了  试着写了个分散加载的小文件

load    0x00000000
{
    exec1    0x00000000
    {
        44binit.o(init,+first)
        *(+ro)
    }
    exec2    0x0c000000
    {
        *(+rw,+zi)
    }
}
烧录后可以运行  
稍微修改下 
load1    0x00000000
{
    exec1    0x00000000       //0x00000000是ROM的起始地址
    {
        44binit.o(init,+first)
        *(+ro)
    }
    exec2    0x0c000000       //0x0c000000是RAM的起始地址
    {
        *(+rw,+zi)
    }
}

load2    0x00005000
{
    exec3    0x00005000
    {
        main.o(+ro)
    }
}
也能运行 但是发现 所有被加载的 *.o文件的 RO输入段 只能再ROM里面
不能放到 RAM的地址去运行
如果改成 
load2    0x00005000
{
    exec3    0x0c100000     
    {                       
        main.o(+ro)
    }
}
程序就跑飞了

暂时结论 所有的RO输入段只能再ROM里跑  不过相关的RW ZI可以复制到RAM里
请前辈指教 是这样吗?

相关帖子

沙发
dld2| | 2008-11-26 08:54 | 只看该作者

例子

这是把44b0片内sram的一部分用来跑程序。

LOAD_SDRAM 0x0c008000  
{
    SDRAM1 0x0c008000 0x100000
    {
        44BINIT.O (INIT +FIRST)
        * (+RO)
    }

    SDRAM2 0x0c500000 0x80000
    {
        * (+RW,+ZI)
    }
    
    SRAM 0x10001000 0x1000
    {
        COMMONCALC.O (+RO)
    }

}

这样COMMONCALC.O的RO部分在链接时定位在SRAM中。
但是这部分代码还需要程序拷贝到SRAM才能执行。下面是main中的部分代码:

extern char Load$$SRAM$$Base[];
extern char Image$$SRAM$$Base[];
extern unsigned int Image$$SRAM$$Length;
extern char Image$$SRAM$$Limit[];
//以上符号是连接器自动生成的。可以当普通变量使用。

void Main(void)
{    
    。。。
         Uart_Printf(" * SRAM load start addr %x",(unsigned int)Load$$SRAM$$Base);
    Uart_Printf(" * SRAM exec start addr %x",(unsigned int)Image$$SRAM$$Base);
    Uart_Printf(" * SRAM exec end   addr %x",(unsigned int)Image$$SRAM$$Limit);
    Uart_Printf(" * SRAM exec image length %x",(unsigned int)Image$$SRAM$$Length);
    
         //将SRAM段从加载地址拷贝到执行地址
    memcpy(Image$$SRAM$$Base, Load$$SRAM$$Base, Image$$SRAM$$Limit - Image$$SRAM$$Base);
}

总的来说:如果加载地址与执行地址不同,需要人工干预。
和RW段需要在初始化代码中拷贝是一个道理。




使用特权

评论回复
板凳
biehoff|  楼主 | 2008-11-26 10:54 | 只看该作者

谢谢前辈指点

我也曾想过是否要自己写一小段程序  把程序拷贝到RAM去  书上完全没提过这方面的操作  刚开始还天真的以为 写个scattered文件 编译器就自己去搞定

前辈给的例子中
    SRAM 0x10001000 0x1000
    {
        COMMONCALC.O (+RO)
    }
是需要自己拷贝 COMMONCALC 过去的

那么
    SDRAM2 0x0c500000 0x80000
    {
        * (+RW,+ZI)
    }
也需要自己拷贝所有的 RW ZI吧  貌似不拷贝程序也能跑
这个要拷贝就好复杂了···  

使用simple模式的时候 初始化程序里有定义
   IMPORT    |Image$$RO$$Limit| 
   IMPORT    |Image$$RW$$Base|  
   IMPORT    |Image$$ZI$$Base|  
   IMPORT    |Image$$ZI$$Limit|  
这些符号在后面有段汇编程序用来拷贝 RW ZI段到RAM里的

使用scattered模式时  上面的那些符号都没意义的 与之相关的 拷贝程序
也没用了 (然后就被我删了)
那么要自己使用
Load$$SRAM2$$Base
Image$$SRAM2$$Base
Image$$SRAM2$$Length;
Image$$SRAM2$$Limit
这些符号 自己写程序来完成拷贝吧

感谢前辈指点  我理解到这里了···

使用特权

评论回复
地板
biehoff|  楼主 | 2008-11-26 11:34 | 只看该作者

又发现一点

刚才又发现一点有趣的事
load1    0x00000000
{
    exec1    0x00000000       //0x00000000是ROM的起始地址
    {
        44binit.o(init,+first)
        *(+ro)
    }
    exec2    0x0c000000       //0x0c000000是RAM的起始地址
    {
        *(+rw,+zi)
    }
}

load2    0x00005000
{
    exec3    0x00005000
    {
        main.o(+ro)
    }
}
上述分散加载程序是可以跑起来的

我还没按前辈的指点写拷贝程序  只是验证下某些疑问

在AXD环境下看编译后的代码
main{}果然被放在0x00005000那里了 调用main{} 就是直接跳转到 0x00005000

如果改成
load2    0x00005000
{
    exec3    0x00009000
    {
        main.o(+ro)
    }
}
程序跑飞了  那是当然的····
再到AXD下看代码 
调用main{} 就是跳转到 0x00009000去执行 那里是乱码  就跑飞了
在回头看看 0x00005000 好像也是乱码  仔细对照了一下此处 编译后的机器码 和 main{}函数的机器码是一样的  原来 main{}还再原地没动 0x00005000

很有趣····  好像有点理解分散加载的功能了  而且要自己写些程序和分散加载功能配合 

使用特权

评论回复
5
dld2| | 2008-11-26 11:45 | 只看该作者

俺是同学,不要太客气

3楼说得对。

我改了启动代码:
;scatter des file test
;    IMPORT    |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data)
    IMPORT    |Image$$SDRAM1$$Limit|  ; End of ROM code (=start of ROM data)
;    IMPORT    |Image$$RW$$Base|   ; Base of RAM to initialise
    IMPORT    |Image$$SDRAM2$$Base|   ; Base of RAM to initialise
;    IMPORT    |Image$$ZI$$Base|   ; Base and limit of area
    IMPORT    |Image$$SDRAM2$$ZI$$Base|   ; Base and limit of area
;    IMPORT    |Image$$ZI$$Limit|  ; to zero initialise;
    IMPORT    |Image$$SDRAM2$$ZI$$Limit|  ; to zero initialise;


;scatter des file test
    LDR        r0, =|Image$$SDRAM1$$Limit|    ; Get pointer to ROM data
    LDR        r1, =|Image$$SDRAM2$$Base|    ; and RAM copy
    LDR        r3, =|Image$$SDRAM2$$ZI$$Base|    
    ;Zero init base => top of initialised data
            
    CMP        r0, r1        ; Check that they are different
    BEQ        %F1
0        
    CMP        r1, r3        ; Copy init data
    LDRCC   r2, [r0], #4    ;--> LDRCC r2, [r0] + ADD r0, r0, #4         
    STRCC   r2, [r1], #4    ;--> STRCC r2, [r1] + ADD r1, r1, #4
    BCC        %B0
1        
    LDR        r1, =|Image$$SDRAM2$$ZI$$Limit| ; Top of zero init segment
    MOV        r2, #0
2        
    CMP        r3, r1        ; Zero init
    STRCC   r2, [r3], #4
    BCC        %B2


-----------------------------------
还是很麻烦的,呵呵。

使用特权

评论回复
6
biehoff|  楼主 | 2008-11-26 11:50 | 只看该作者

RE

哦   原来确实是要自己改代码的···
早知道 没那么便宜的事  照着书上讲的写个TXT文件就搞定了  那算是YY了
   很感谢  困扰我好几天的问题了···

使用特权

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

本版积分规则

21

主题

138

帖子

0

粉丝