BOOT是什么?BOOT就是启动。
做嵌入式设计的朋友们知道,在应用设计时需要考虑到BOOT的设计,既要方便程序下载,调试同时也要兼顾到系统正常运行。那么做DSP的设计是否也有这样的考虑呢? 在DSP的调试之前,所有的可执行代码都是在PC机上,只有下载到DSP里面,DSP才能开始执行。当软件开发完成后,必须要脱离PC机,需要DSP完全独立工作。这个时候就必须要根据不同的需求,选择不同的BOOT模式,也就是选择不同的方式将可执行代码加载到DSP的高速存储器里面全速运行。可执行代码一般可选择放在FLASH中,或其他的主机上,然后通过主机接口或者以太网接口下载到DSP 。
对于单核DSP的BOOT,相对简单些。
一般将可执行代码存放在ROM或者FLASH里面。 比如ROMBOOT模式,EDMA自动从CE1对应的存储器空间拷贝1KB的代码到DSP内部SRAM地址0x00000000,在EDMA工作期间,CPU停止工作,拷贝完成后,CPU开始运行。 大家会问,如果代码大于1KB怎么办?其实这个问题非常简单。前面我们提到的,EDMA拷贝1KB的代码,那么大家是否想过,同样是利用这个拷贝1KB的代码的过程,是否可以完成大于1KB的代码的自启动呢?答案当然是肯定的。其实在其他的MCU嵌入式中早就使用了。就是利用这1KB的代码,将其设计为把FLASH中的代码全部拷贝到内部高速存储器,然后跳转到C语言环境初始化程序的入口处“_c_int00”,这样启动就完成了。那么我们把这1KB的代码叫做第二级启动加载程序。
对于多核的C6678的DSP来说,就没这么简单了。(使用的平台是广州创龙-TL6678-EasyEVM开发板) 下面我来一一介绍。 大家知道,在C6678的内部,固化了一段程序,也就是RBL程序。 当DSP在上电复位后,RBL负责根据其配置将应用程序从慢速的外部存储器比如FLASH等或者是外接的主机或者网络等等地方搬到内部的高速存储器中运行。 下图就是从C6678的数据手册(SPRS691E)中截取出来的,表示RBL在DSP的ROM中的位置,其起始地址是0x20B00000。 DSP的BOOT过程,分为主机BOOT和存储器BOOT两种形式。顾名思义,主机BOOT,就是把DSP配置为从模式,DSP等待外部主机传送代码到其内部高速存储器执行。存储器BOOT模式呢,以DSP为主,DSP自动将外部存储器中存放的代码搬到其内部高速存储器并且运行。
那么我们就看看,C6678的RBL为我们准备了多少种BOOT模式以及不同的BOOT模式所支持的外设情况。
BOOT模式以及不同的BOOT模式所支持的外设情况 | | 我们的用户代码存放在16BIT宽的外接存储器中,而且是异步加载。 | | 这是前面说的主机BOOT模式。也就是说外面的主机通过串行高速接口加载用户的程序,这时候有两种选择。一是使用MESSAGING模式,二是使用Direct IO 接口模式。 | | 这也是主机BOOT模式。外部主机通过以太网接口加载用户程序。这里有个问题需要注意:以太网通信是以数据包的形式进行,数据包加速器由核心参考时钟或者SerDes参考时钟驱动 。 | | 这依然是主机BOOT模式。外部主机通过PCI 接口加载程序到内部高速存储器运行。 | | 这是属于存储器BOOT模式。而且DSP的I2C是主,外部I2C的存储器是从。用户程序存放在外部从I2C的EEPROM中,DSP以BOOT表格式中数据块的形式加载。 | | 这是属于主机BOOT模式。DSP的I2C是从,外部I2C主机发送用户程序到DSP的存储器。同上,数据格式需要满足DSP的BOOT表的格式。这种BOOT模式在哪里会用到?在单片的I2CEEPROM对应于多片DSP的场合下,用这种BOOT模式,可以大大节省BOOT时间。在通信或者图像处理中常常用到。 | | 这是属于存储器BOOT模式。DSP通过SPI外接的FLASH读入用户程序,同样数据格式也必须满足DSP的BOOT表的格式。 | | 这是被动的主机BOOT模式。主机负责配置存储器同时加载用户程序并且直接BOOT DSP。 |
BOOT过程取决于两个因素:一个就是通过DSP的硬件引脚的高低电平配置决定,另外一个就是触发BOOT过程的复位机制。
接下来讲讲C6678从上电复位后的BOOTLOADER的工作情况。
C6678的BOOT过程由COREPAC0执行。从C6678的DATASHEET可以看出,POR和RESETFULL 两个管脚可以触发上电复位,从而引起RBL初始化。POR引脚由上电时序产生,RESETFULL则由主机来复位系统。只有在POR实现上电复位之后,RESETFULL才能实现全局复位,也就是说RESETFULL复位时热复位。 在上电复位的过程中,13个BOOTLOADER引脚状态分别被采样且被锁存在BOOT的配置寄存器中,RBL就凭着这些设备状态寄存器的值去进行决策,往后如何BOOT—使用设备状态寄存器中的启动配置,BOOT过程就是执行初始化代码,也就是RBL初始化代码: (1)ROM里面的代码激活所有支持该功能的外设的复位隔离,也就是说,这些外设的状态不会被改变。支持这个功能的外设有:
SmartReflex,DDR3,Embedded Trace,Ehternet SGMII,Ethernet Switch,SRIO,AIF2。 (2)ROM代码必须在所有启动需要使用的外设供电和时钟都是有效的情况下才能正常 。 (3)ROM代码配置系统的PLL,根据DEVSTAT寄存器中PLL选择的3个BIT,配置C6678 的工作速度。 (4)对于NO-BOOT,SPI以及I2CBOOT模式,主PLL保留在BYPASS模式下。其他的BOOT模式BOOTLOADER初始化过程则把主PLL配置成PLL MODE。 (5)ROM代码在所有的COREPACS中保留最后0xD23F 字节。这个东西有什么用呢?这个保留的RAM区域其实就是用来存储启动过程中的初始化配置,也就是我们常听说的启动参数表。下面有一个表,放在局部L2里面的COREPAC0的启动参数表:
注意哟,对于EMIF16 BOOT模式,RBL不保留MEMORY。这时候MEMORY的使用完全依赖存储在NOR FLASH的镜像。
(6)在启动过程中,BOOTLAODER会在SECONDARY COREPACS(即COREPAC1-7) 执行IDLE命令,且等待中断,只有在应用程序加载到SENCONDARYCOREPACS之后,每个COREPACS中的BOOT_MAGIC_ADDRESS被启用,这时候COREPAC0中的应用程序就可以触发一个 IPC唤醒其他的核,完成启动。此时从核执行程序指向BOOT_MAGIC_ADDRESS指定的地址。 如上表中的BOOTMAGIC地址就是ROM搬移到RAM信息的最后一个字,这里面存放的就是各CORE初始化之后需要跳转的C程序入口地址:_c_int00()。C6678 的内存规划设计的时候,不同CORE的BOOT_MAGIC_ADDRESS存放在该核的L2 RAM的最后一个字里面。所以用一个公式的形式表示每个核的BOOT_MAGIC_ADDRESS就是0x1n87ffc,其中n表示第n个核)。 (7)所有的L1D和L1P被BOOT代码配置成CACHE,而L2存储器则配置成可寻址的内存空间。 (8)这时候除了主机中断,其他的中断都是无效的。主机中断在PCIe,SRIO及HyperlinkBoot模式下是需要使用的。 (9)BOOTLAODER里面有个DDR配置表。缺省配置初始化为0 。在启动时,每块BOOT表加载完后,表格中的所有参数都会进行测试。发现其中ENABLE BITMAP域非零,DDR3就会被配置。此时允许BOOT表配置DDR表,然后初始化并加载数据到DDR。
以下分别是对上述的各种BOOT的配置参数:有兴趣的朋友可加技术交流群,平时交流一下心得:79635273、332643352
|