分类:
2009-03-31 10:59:57
从最简单的开始
kiss~~~
这次我要实现初始化sdram,并在sdram里运行led程序
PROGRAM start
SECTION START:CODE:ROOT(2)
CODE32
PUBLIC __iar_program_start
IMPORT main
__iar_program_start:
bl disable_watchdog
bl memsetup
bl copy2sdram ;把stepping_stone复制到0x30000000开始的地址
ldr sp,=0x32000000
ldr pc,=main ;这一句绝对跳转,跳到0x30000000以后的地址执行
halt:
b halt
disable_watchdog:
mov r1,#0x53000000
mov r2,#0x0
str r2,[r1]
mov pc,lr
memsetup:
ldr r1,=0x48000000
ldr r2,=0x22111110
str r2,[r1],#4 //BWSCON
ldr r2,=0x00007FFC
str r2,[r1],#4 //BANKCON0
ldr r2,=0x00007FFC
str r2,[r1],#4 //BANKCON1
ldr r2,=0x00000700
str r2,[r1],#4 //BANKCON2
ldr r2,=0x00000700
str r2,[r1],#4 //BANKCON3
ldr r2,=0x00002E50
str r2,[r1],#4 //BANKCON4
ldr r2,=0x00002E50
str r2,[r1],#4 //BANKCON5
ldr r2,=0x00018005
str r2,[r1],#4 //BANKCON6
ldr r2,=0x00018005
str r2,[r1],#4 //BANKCON7
ldr r2,=0x008c04e9
str r2,[r1],#4 //REFRESH
ldr r2,=0x00000032
str r2,[r1],#4 //BANKSIZE
ldr r2,=0x00000030
str r2,[r1],#4 //MRSRB6
ldr r2,=0x00000030
str r2,[r1],#4 //MRSRB7
mov pc,lr
copy2sdram:
mov r1,#0
ldr r2,=0x30000000
mov r3,#4*1024
copy_loop:
ldr r4,[r1],#4
str r4,[r2],#4
cmp r1,r3
bne copy_loop
mov pc,lr
END
c文件和上次一样,链接文件如下,全放在0x30000000以后
define memory MEM with size = 4G;
define region STEPPING_STONE = MEM:[from 0x0 to 0xfff];
define region SDRAM = MEM:[from 0x30000000 to 0x33ffffff];
place in SDRAM{section START};
place in SDRAM{section .text};
如果在线仿真调试的话,还需要一个宏文件,IAR中后缀名是.mac,在jtag下载程序之前做一些初始化,
它实现了关看门狗,禁止终端,设置cpu频率,初始化sdram的寄存器,如果不是在线仿真调试
这些需要我们自己在程序中实现
setup()
{
__writeMemory32(0x00000000, 0x53000000, "Memory"); /* watchdog timer disable */
__writeMemory32(0xffffffff, 0x4a000008, "Memory"); /* disable all interrupts */
__writeMemory32(0x000007ff, 0x4a00001c, "Memory"); /* disable all sub-interrupts */
__writeMemory32(0xffffffff, 0x4a000000, "Memory"); /* clear all source pending bits */
__writeMemory32(0x000007ff, 0x4a000018, "Memory"); /* clear all sub-source pending bits */
__writeMemory32(0xffffffff, 0x4a000010, "Memory"); /* clear interrupt pending bit */
__writeMemory32(0x00ffffff, 0x4c000000, "Memory"); /* PLL locktime counter */
__writeMemory32(0x000a1031, 0x4c000004, "Memory"); /* Fin=12MHz, Fout=202.8MHz */
__writeMemory32(0x00000003, 0x4c000014, "Memory"); /* FCLK:HCLK:PCLK = 1:2:4 */
__writeMemory32(0x22111110, 0x48000000, "Memory"); /* BWSCON */
__writeMemory32(0x00007FFC, 0x48000004, "Memory"); /* BANKCON0 */
__writeMemory32(0x00007FFC, 0x48000008, "Memory"); /* BANKCON1 */
__writeMemory32(0x00000700, 0x4800000c, "Memory"); /* BANKCON2 */
__writeMemory32(0x00000700, 0x48000010, "Memory"); /* BANKCON3 */
__writeMemory32(0x00002E50, 0x48000014, "Memory"); /* BANKCON4 */
__writeMemory32(0x00002E50, 0x48000018, "Memory"); /* BANKCON5 */
__writeMemory32(0x00018005, 0x4800001c, "Memory"); /* BANKCON6 */
__writeMemory32(0x00018005, 0x48000020, "Memory"); /* BANKCON7 */
__writeMemory32(0x008c04e9, 0x48000024, "Memory"); /* REFRESH */
__writeMemory32(0x00000032, 0x48000028, "Memory"); /* BANKSIZE */
__writeMemory32(0x00000030, 0x4800002c, "Memory"); /* MRSRB6 */
__writeMemory32(0x00000030, 0x48000030, "Memory"); /* MRSRB7 */
}
execUserPreload()
{
__message "Initializing SDRAM ...\n";
setup();
__message "Initializing SDRAM ... Completed\n";
}
在线调试时,程序是从0x30000000开始运行的,0x30000000是程序的执行起始地址
关于程序的地址,有一个执行地址和物理地址
一般这两个地址是相等的
链接脚本里指定的是执行地址,jtag调试也是根据程序的执行地址,下载到相应的物理地址去的,我们在链接脚本指定了两个段都是从0x30000000开始
所以jtag调试时,下载程序到0x30000000开始地址,并从0x30000000开始执行
但0x30000000开始地址是sdram,需要初始化,
所以,在下载之前就需要初始化,这就是宏文件所作的事。
这个程序全都是从0x30000000开始链接的,cpu复位是从0地址开始执行的
那我们怎么让它自己能启动执行呢,
我们可以把0x30000000链接生成的程序放在0地址,前面的bl指令是相对跳转
是基于当前pc值向前或向后的偏移值计算,与位置无关,把它放在0地址也能执行
然后我们把0地址开始的一段复制到0x300000000开始的地方,
这样,它的物理地址和执行地址就相同了,再用
一个绝对跳转,ldr pc,=main
就跳到0x30000000以后的地址继续执行。
在IAR EWARM里的project-->option-->output converter选中generate additional output
把output format选为binary,就可以得到后缀名.bin的二进制文件,它比.out文件小多了,
去掉了很多调试信息
把它用H-Jtag烧进nand flash,最新版的H-Jtag(3月2号发布)已经支持nand flash烧写了
就可以看到灯在闪。
比调试时慢很多,比在stepping stone里也慢很多
原因是,调试时,设置了cpu频率为200M
外部sdram比stepping stone性能差很多,很多。