|
经常有朋友询问TI的6727芯片的flash启动程序怎么做,其实TI提供了一个二次启动的例子,具体做法可以参照http://focus.ti.com/lit/an/spraa69c/spraa69c.pdf 。
这篇文档很详细,如果你有耐心将其读完,采用TI的新方式做启动是再好不过了。不过如果你和我一样懒,不愿意做安装Perl,把程序做成AIS Stream,编译那个Secondary bootloader工程等等,这一系列麻烦的工作的话,那么请继续往下看。
我采用和6713时代一样的办法:在0x90000000 - 0x90000400 中放置不到 1k bytes的boot loader,载入指定位置的boot table(用hex6x将out文件转换为boot table)。
6727 有个麻烦,它的EMIF对flash空间的存取有限,需要采用其它的引脚对高位地址进行扩充,这样启动程序会复杂一些,可能导致程序大小超出1k byte,这也许是TI选择二次启动的原因之一吧。
为了节省空间,很自然想到的是采用汇编编写,不过6727的汇编实在是太麻烦了,因此我尝试用C语言编写这个boot loader。不过由于boot loader运行时尚未初始化C语言运行环境,也就是说没有堆栈可用,因此所有变量都必须采用寄存器。另外C语言编译之后的大小很可能超出1k byte,所以需要对编译器进行优化配置,我选择Size Most Critical(-ms3)对下面的程序进行编译,最终编译之后的大小约为650bytes,看来还有余地添加一些其它的功能呢。
/* bootloader for C6727 根据HD12引脚的状态载入不同的程序 HD12 pin = High, load from page 0 HD12 pin = Low , load from page 8 硬件设计上通过HD0 - HD3控制flash地址的高位 control flash page address by HD0 - HD3 */
#include
/*定义SDRAM配置寄存器*/ #define SDTIMR *(Uint32 *)0xf0000020 #define SDSRETR *(Uint32 *)0xf000003c #define SDRCR *(Uint32 *)0xf000000c #define SDCR *(Uint32 *)0xf0000008
/* 控制flash地址的高位,根据硬件的配置不同应做适当的修改 */ #define FLASH_SET_PAGE(X) *(Uint32 *)(0x43000014) = \ (*(Uint32 *)(0x43000014) & 0xfffffff0) | (X)
/* 将boot函数放在.boot_prog section */ #pragma CODE_SECTION(bss_boot,".boot_prog")
void boot() { /* 由于boot函数运行时尚未初始化C语言运行环境的Stack, 因此所有变量都采用register */
register Uint32 * boot_dst; register Uint32 * boot_src; register Uint32 boot_page; register Uint32 boot_ep; register Int32 boot_cnt;
/* set EMIF-A1CR-ASIZE to 16bit、flash内存的存储类型为16bit */ /* 根据flash的类型,可能还需要进行其它的配置 */ *(Uint32 *)(0xf0000010) = (*(Uint32 *)(0xf0000010) & 0xfffffffc) | 0x01;
/*为了能将程序复制到SDRAM中,进行EMIF的SDRAM相关的配置*/ /*应根据SDRAM芯片的类型做适当的修改*/ SDTIMR = 0x29114510; SDSRETR = 0x00000006; SDRCR = 0x00000d06; SDCR = 0x00004520; SDRCR = 0x000005ff;
/* set UHPI-GPIOEN */ /* 使能控制 flash 地质高位的 GPIO */ *(Uint32 *)(0x4300000c) = 0x00000180;
/* set UHPI-GPIODIR1 */ /* 设置控制 flash 地址高位的GPIO的方向 */ *(Uint32 *)(0x43000010) = 0x0000000f;
/* 根据HD12的状态、配置需载入的程序所在的Page */ if( *(Uint32 *)(0x43000014) & 0x00001000 ) boot_page = 8; else boot_page = 0; FLASH_SET_PAGE(boot_page); /* 被载入的程序的boot table所在的地址 */ boot_src = (Uint32 *)(0x90000400); boot_ep = *boot_src++; /* 取得 Entry point */ while(1){ boot_cnt =(Int32) *boot_src++; if((Uint32)boot_src == 0x90008000){ boot_src = (Uint32 *)(0x90000000); boot_page ++; FLASH_SET_PAGE(boot_page); } boot_dst = (Uint32 *)(*boot_src++); if((Uint32)boot_src == 0x90008000){ boot_src = (Uint32 *)(0x90000000); boot_page ++; FLASH_SET_PAGE(boot_page); } if(boot_cnt == 0){ (*(void (*)())boot_ep)(); /* 跳转到Entry point */ } while(boot_cnt>0){ *boot_dst++ = *boot_src++; if((Uint32)boot_src == 0x90008000){ boot_src = (Uint32 *)(0x90000000); boot_page ++; FLASH_SET_PAGE(boot_page); } boot_cnt -= 4; } } }
|