DM642复位后,芯片先从CE1空间读取1K字节的数据到内部SRAM,然后从地址0开始运行。因为一般的程序都远远大于1K字节,所以一般都是有一个二级bootloader,用它来加载主程序。Bootloader运行完后调用c_int00()来进行C运行时刻初始化,如堆栈,静态变量等,之后会调用BIOS_init,最后开始运行main函数,main函数结束后DSP/BIOS的任务管理器开始运行。 具体实现起来时要稍复杂一些,因为有一些实际问题需要考虑。 1.外部存储器一般是NOR Flash,容量较大时,因为DM642的CE1只有1MB空间,需要使用GPIO配合的分页模式。因为GPIO的缺省值是输入,内有上拉电阻,所以bootloader需要写在最高页。DM642复位后采用最慢的读写时序。 2.Bootloader需要在有限的1K字节内完成SDRAM初始化,并将主程序搬运到内存中然后开始运行。TI的例子是用汇编写的,因为此时c的运行环境还没有初始化。其中最关键的是栈指针没有初始化,我们给它赋值后其他部分就可以用c来写,但要注意仍不能使用c库函数。
汇编部分进行栈指针初始化:
_boot_sp: mvk .S2 0x0600, B15 mvkl .S2 _boot_loader, B0 mvkh .S2 _boot_loader, B0 b .S2 B0 nop 5
boot.c进行EMIF初始化,并分段将主程序从Flash读入SDRAM
#pragma CO DE_SECTION(boot_loader, ".boot_load");
void boot_loader(){ Uint32 program_addr,size; Uint8* src,*dest;
program_addr=0x90000404;//First Entry //Init the EMIF interface EMIFA_GCTL = 0x00052060; EMIFA_CE0 = 0x00000040; EMIFA_CE1 = 0x21E28E01; //0x11518a01 EMIFA_CE2 = 0xffffffd3; EMIFA_CE3 = 0xffffffd3; EMIFA_SDRAMCTL = 0x6b228000; EMIFA_SDRAMTIM = 0x000003A9; EMIFA_SDRAMEXT = 0x000505cd; EMIFA_CE0SECCTL= 0x00000071; EMIFA_CE1SECCTL= 0x00000002; EMIFA_CE2SECCTL= 0x00000002; EMIFA_CE3SECCTL= 0x00000002; //Load Second Bootloader to SDRAM size=*(Uint32*)program_addr; while(size){ program_addr+=4; dest=(Uint8*)(*(Uint32*)program_addr); program_addr+=4; src=(Uint8*)program_addr; program_addr+=size; |