这篇文章分析RT1052芯片从FlexSPI上电启动到执行第一条指令的全过程
设置RT1052从FlexSPI启动
FlexSPI的初始化流程
boot ROM对FlexSPI的初始化
boot ROM是固化在芯片内部的一段启动代码,这个代码会在系统上电时被执行。boot ROM先对芯片进行必要的初始化后,会根据各个GPIO电平来选择一个启动方式,参考下面的列表选择一个boot device
fuse 没有被设置
BOOT_MODE[1:0] = 00b or 10b -> Internal Boot Mode
BOOT_CFG1[7:4] = 0000b -> Serial NOR boot via FlexSPI
BOOT_CFG1[1]=0 1->使能加密启动 0->不使能加密启动
BOOT_CFG1[3:2]->设置SPI的读前保持时间 (0–500us; 1–1ms; 2–3ms; 3–10ms)
BOOT_CFG2[2:0]->设置Flash 类型 (000b-Device supports 3B readby default,001bDevice supports 4B read by default)
BOOT_CFG2[3]->Infinite-Loop,不使能:0。(只有在调试的时候使用)
没有设置熔丝情况下,设置好这堆引脚电平为所需值,然后芯片就从SPI启动了
此时boot ROM会根据前面的BOOT_CFG1[3:2]和BOOT_CFG2[2:0]信息简单设置一下FlexSPI接口,此时默认SPI时钟为30MHz。然后读取Flash的前512字节信息。boot ROM会认为这是初始化Flash的信息,然后boot ROM根据这些预设的信息对FlexSPI接口进行初始化。初始化后就可以满速跑了。
具体流程参考下图:
这里就是前512字节数据,对FlexSPI接口的初始化。
const flexspi_nor_config_t spiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,/*标志:FCFB*/
.version = FLEXSPI_CFG_BLK_VERSION,/*版本:V1.4.0*/
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackInternally,/*内部环回*/
.csHoldTime = 3u, /*保持时间*/
.csSetupTime = 3u,/*建立时间*/
.columnAddressWidth = 0u,/*列地址宽度*/
.deviceModeCfgEnable = 1u,/*设备模式配置使能*/
.deviceModeType = 1u,/*Quad 使能命令*/
.deviceModeSeq.seqNum = 1u,/*LUT序列号*/
.deviceModeSeq.seqId = 4u, /*LUT序列索引*/
.deviceModeArg = 0x000200,/*设置 QE=1(S9)*/
.deviceType = kFlexSpiDeviceType_SerialNOR,/*设备类型为nor flash*/
.sflashPadType = kSerialFlash_4Pads,/*设备数据总线为4*/
.serialClkFreq = kFlexSpiSerialClk_133MHz,/*flash 时钟*/
.sflashA1Size = 32u * 1024u * 1024u, /*flash 大小32MBytes*/
//.dataValidTime = {16u, 16u},
.lookupTable =
{
/*快速读命令(四线)*/
[0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
[1] = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
/*读状态命令*/
[1*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),
/*写使能命令*/
[3*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0),
/*擦除扇区命令*/
[5*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20, RADDR_SDR, FLEXSPI_1PAD, 0x04),
/*页编程命令(四线)*/
[9*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 0x18),
[9*4+1] = FLEXSPI_LUT_SEQ(WRITE_SDR,FLEXSPI_4PAD , 0x04, STOP, FLEXSPI_1PAD, 0),
/*整片擦除*/
[11*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xc7, STOP, FLEXSPI_1PAD, 0),
},
},
.pageSize = 256u,/*页大小为256字节*/
.sectorSize = 4u * 1024u,/*扇区大小为4k字节*/
};
然后就是加载image了
这里分成了四部分
Image vector table—a list of pointers located at a fixed address that the ROMexamines to determine where theother components of the program image arelocated.
Boot data—a table that indicates the program image location, program image size inbytes, and the plugin flag.
Device configuration data—IC configuration data.
User code and data.
1、IVT:这段数据在flash中的偏移地址为0x1000,大小为32字节,这个字段包含了各个域的入口
2、boot data:这段数据的入口包含在IVT中,所以位置不规定。内容主要为image的入口以及flash的大小
3、DCD:这段数据的入口也包含在IVT中,所以位置不规定。主要作用是通过一系列的命令对内部寄存器进行设置,已达到初始化外设flash以及SDRAM的目的。这段数据最大为1768字。
4、前3字段都是内置的boot ROM在初始化芯片时需要被读取的数据。初始化完成后会跳转到用户代码开始执行,也即Reset_handler
内置的boot ROM能够解析这些数据那必然就对这些数据的格式有着一定的要求,具体字段的设置标准参考数据手册的第8章。这里就不搬过来了。
下一篇文章学习RT1052的cache特性