原创 arm调试的准备内容,注意事项,以及BOOTLOADER和散列表加装的分析

2009-3-20 15:11 3687 11 11 分类: MCU/ 嵌入式
一块arm板子拿到手很多人一开始都无法下手,他不像单片机那样编译器帮你做好了一切,我在这里记录下自己的经验。

    arm内核默认的指令执行方式是从0x0执行,但是由于一般工程上代码的容量都非常大,我们都是外部扩展RAM和FLASH,把程序放在外部,那么就需要把程序的存放地址映射到0x0处,以便于pc可以在自己写的代码中跑。好在一般的arm核心都支持把norflash的0x0映射到芯片地址的0x0处(norflash要接在固定的BANK上,才能正常映射),如s3c2410,有的芯片功能更强大,支持把NANDFLASH和RAM也映射到0x0,这就需要查芯片手册确定映射方式,一般都是用OM[0,1]来选择。


   一个产品我们一般都是把代码烧录到外部的FLASH上,而调试的时候我们一般在RAM中调试。这就涉及到上面的映射选择。


   一般一个arm的开发板都配带一个简易的JTAG仿真器(2类wiggler和sdt,信号定义方法不同),我们可以使用现在广泛使用的免费仿真软件HJTAG,这个软件模拟了硬件仿真器,虽然功能一般但是省去买仿真器的钱,造福了很多初学者。十分感谢开发者。现在用的比较多的IDE开发环境是ADS1.2,网上又很多的下载,一般光盘也自带。


    有了上述的仿真工具和开发板,我们可以进行自己代码的实验了。新建一个工程,设置好ads的参数,查ads的手册。编译通过以后,就是仿真了,一般仿真有三种方法:


   1.直接下在flash里仿真,这样的话要把ads的执行入口地址设置成flash的起始地址。


   2.ram里仿真,同样要设置入口对应地址。


   3.直接在ads上设置入口地址为main


   不管什么方式都要先对CPU进行一些初始化操作,包括复位,存储区配置,进制中断,等等。这样的脚本可以自己写,也可以在hjtag的官网下载。


   下面的是s3c2410的配置脚本:


FLASH SECTION:
INTEL
28F128J3
MEMORY SECTION:
16-BIT X 1-CHIP
0x01000000
0x30000000
XTAL SECTION:
NULL
TCK SECTION:
-1
-1
SCRIPT SECTION:
SoftReset+++
Setmem+32-Bit+0x53000000+0x00000000
Setmem+32-Bit+0x4A000008+0xFFFFFFFF
Setmem+32-Bit+0x4A00001C+0x000007FF
Setmem+32-Bit+0x53000000+0x00000000
Setmem+32-Bit+0x48000000+0x22111120
Setmem+32-Bit+0x56000050+0x000055AA
Setmem+32-Bit+0x4C000014+0x00000003
Setmem+32-Bit+0x4C000000+0x00FFFFFF
Setmem+32-Bit+0x4C000004+0x00074012
Setmem+32-Bit+0x4C000008+0x00058042
Setmem+32-Bit+0x48000004+0x00002F50
Setmem+32-Bit+0x48000008+0x00000700
Setmem+32-Bit+0x4800000C+0x00000700
Setmem+32-Bit+0x48000010+0x00000700
Setmem+32-Bit+0x48000014+0x00000700
Setmem+32-Bit+0x48000018+0x0007FFFC
Setmem+32-Bit+0x4800001C+0x00018005
Setmem+32-Bit+0x48000020+0x00018005
Setmem+32-Bit+0x48000024+0x008E0459
Setmem+32-Bit+0x48000028+0x00000032
Setmem+32-Bit+0x4800002C+0x00000030
Setmem+32-Bit+0x48000030+0x00000030
PGMOPTION SECTION:


    可以直接添加到hjtag软件中。也可以用IDE环境的命令行设置,具体指令与IDE相关。


    配置好候就可以用AXD调试了。


   直接用第三中方法虽然简单,但那是由于仿真器直接跳转到C的main代码运行的,只能用来仿真不能成为最终的代码。而我们想要正常使用c的代码就必须先初始化出来c的环境,包括堆栈的设置,数据段的搬运等。这个一般都是用BOOTLOADER完成的。关于BOOTLOADER也是比较复杂的,网上有很详细的分析。大体上完成功能流程:


   1.屏蔽所有中断,禁止看门狗


   2.根据工作频率设置PLL,分出fclk,uclk等等


   3.初始化存储寄存器,这里和那个脚本完成的差不多,这里主要是为了脱离仿真器运行代码设置的。脚本是给仿真器用的。


   4.分配各种工作模式的堆栈


   5.设置缺省中断,设置中断向量表,这个我在另一篇文章里有分析。


   6.将数据段搬运到RAM中,将ZI段清0


   7.跳转到函数main


   期中第六步,对于复杂的程序工程,必须管理RAM,直接搬运并不能达到很好的分配RAm和ROM,所以常常用散列表来配置。即armlink的scatter。


一下是一个ram的脚本:


LOAD 0x30008000   ;load region
{
RAM_EXEC +0   ;PC
{
   startup.o (init, +FIRST)
   * (+RO)
    }


    L0PAGETABLE 0x30200000 UNINIT ;about 2MByte offset SDRAM
    {
        pagetable.o (+ZI)
    }


    STACKS +0x100000 UNINIT ;64KByte under L0 pagetable
    {
        stack.o (+ZI)
    }


RAM +0
{
   * (+RW,+ZI)
}


HEAP +0 UNINIT
{
   heap.o (+ZI)
}

EXCEPTION_EXEC 0 OVERLAY ;exception region
{
   exception.o (+RO)
}


}


LOAD 0x30008000 ; 是load region,整个imgae只有一个load region。0x30000000是ram的起始地址,前面预留了一部分空间。


RAM_EXEC +0   ; RAM_EXEC 描述了执行区的地址,放在第一块位置定义从起始地址开始


startup.o (init, +FIRST); 放置向量表(即Startup.o(init, +First),其中Startup.o 为Startup.s 的目标文件
                                        init是定义自己定义的。;+First表示Vector段放在最前面。


* (+RO);接着放置其它代码(即* (+RO)),* 是通配符,类似WINDOW下搜索用的通配符


后面的:“+0”表示接着上一段,“UNINIT” 表示不初始化。其他的类似。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
11
关闭 站长推荐上一条 /3 下一条