【朝花夕拾】如何在RT4位FDCB中使能QE功能
作者:火山
一, 文档简介
RT1XXX芯片需要接外部memory作为程序存储媒介,如果外部使用QSPI flash,通常会使用quad功能去读写代码,SDK代码也是基于quad去读取代码并启动。外部使用的QSPI flash,需要查看SFDP 是否满足包含JESD216B+以上版本,因为这种版本通常RT ROM会自动使能QE功能,但是对于JESD216B以下版本,需要命令方式去使能QE位,从而使能quad功能,否则FDCB的LUT定义的是quad读,但是新的芯片QE位没有使能,会导致程序启动失败。所以,对于新的芯片,需要使用命令方式先使能QE位,然后才可以使用quad功能去读写flash。然而,对于量产芯片,通常会直接下载好代码到QSPI flash,然后再从RT芯片启动,这个时候,额外使能QE位会导致工作量的增加,那么如何能够实现一次性烧录app代码到QSPI flash,并且能够直接使能QE并在RT4位芯片中boot呢?
下面就QSPI flash在JESD216B+以下版本的情况,在MIMXRT1170-EVK板子上讲解,如何使用FDCB添加QE使能的命令,来实现,即使QE位没有使能,也能利用FDCB使能QE并启动。
二,FDCB 添加QE使能
MIMXRT1170-EVK板子上的QSPI flash是IS25WP128,改芯片的QE位是状态寄存器的第6位,具体情况可以从QSPI芯片数据手册查看:
下面给出FDCB使能QE位的相关代码。
2.1 使用kDeviceConfigCmdType_QuadEnable
相关FDCB代码如下:
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
…
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_QuadEnable,
.deviceModeSeq = {.seqNum = 1u, .seqId = 4},
.deviceModeArg = 0x40,
…
.lookupTable =
{
…
//Write QE bit
[4 * 4 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, WRITE_SDR, FLEXSPI_1PAD, 0x1),
…
},
},
};
deviceModeCfgEnable 用于使能Device Mode 配置
deviceModeType定义deive mode类型为QE使能
deviceModeSeq定义device mode 配置的序列参数
deviceModeArg定义device mode的数据,0x40代表状态寄存器的第6位
lookupTable中定义写寄存器的LUT序列,主要是写状态寄存器。
2.2 使用kDeviceConfigCmdType_Generic
相关FDCB代码如下:
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
…
.deviceModeCfgEnable = 1u,
.deviceModeType = kDeviceConfigCmdType_Generic,
.deviceModeSeq = {.seqNum = 1u, .seqId = 4},
.deviceModeArg = 0x40,
…
.lookupTable =
{
…
//Write QE bit
[4 * 4 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, WRITE_SDR, FLEXSPI_1PAD, 0x1),
…
},
},
};
deviceModeCfgEnable 用于使能Device Mode 配置
deviceModeType定义deive mode类型为常规配置
deviceModeSeq定义device mode 配置的序列参数
deviceModeArg定义device mode的数据,0x40代表状态寄存器的第6位
lookupTable中定义写寄存器的LUT序列,主要是写状态寄存器。
这里注意到,其实两种方法,唯一的区别就是deviceModeType,那么这里有个问题就是kDeviceConfigCmdType_Generic和kDeviceConfigCmdType_QuadEnable有什么区别?从代码的注释可以看到:
kDeviceConfigCmdType_Generic, //!< Generic command, for example: configure dummy cycles, drive strength, etc
kDeviceConfigCmdType_QuadEnable, //!< Quad Enable command
从操作方法完全一致,在和内部相关部门确认之后,确实kDeviceConfigCmdType_Generic也能使能QE功能,但是这个常规方式通常还支持一般的配置,比如dummy cycle, 引脚的驱动能力等。而kDeviceConfigCmdType_QuadEnable一般专门用于QE位的时候,所以推荐使用还是kDeviceConfigCmdType_QuadEnable。
三,测试FDCB QE使能结果
对于默认的MIMXRT1170-EVK的QSPI flash是使能了QE位功能,所以我们需要首先关闭QE功能并去测试FDCB使能QE后是否工作。
3.1 QE使能关闭测试
这里测试代码使用的是:SDK_2_13_10_MIMXRT1170-EVK\boards\evkmimxrt1170\driver_examples\flexspi\nor\polling_transfer
添加写状态寄存器第6位为0,并读回确认,相关API添加如下:
status_t flexspi_nor_disable_quad_mode(FLEXSPI_Type *base)
{
flexspi_transfer_t flashXfer;
status_t status;
uint32_t writeValue = 0;//
#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
flexspi_cache_status_t cacheStatus;
flexspi_nor_disable_cache(&cacheStatus);
#endif
/* Write enable */
status = flexspi_nor_write_enable(base, 0);
if (status != kStatus_Success)
{
return status;
}
/* Enable quad mode. */
flashXfer.deviceAddress = 0;
flashXfer.port = FLASH_PORT;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG;
flashXfer.data = &writeValue;
flashXfer.dataSize = 1;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success)
{
return status;
}
status = flexspi_nor_wait_bus_busy(base);
/* Do software reset. */
FLEXSPI_SoftwareReset(base);
#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
flexspi_nor_enable_cache(cacheStatus);
#endif
return status;
}
status_t flexspi_nor_QE_register(FLEXSPI_Type *base, uint32_t *QEvalue)
{
/* Wait status ready. */
bool isBusy;
uint32_t readValue;
status_t status;
flexspi_transfer_t flashXfer;
flashXfer.deviceAddress = 0;
flashXfer.port = FLASH_PORT;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READSTATUSREG;
flashXfer.data = &readValue;
flashXfer.dataSize = 1;
do
{
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success)
{
return status;
}
if (FLASH_BUSY_STATUS_POL)
{
if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET))
{
isBusy = true;
}
else
{
isBusy = false;
}
}
else
{
if (readValue & (1U << FLASH_BUSY_STATUS_OFFSET))
{
isBusy = false;
}
else
{
isBusy = true;
}
}
*QEvalue = readValue;
} while (isBusy);
return status;
}
在main中,测试流程为:
1)上电初始化后,读取状态寄存器值
2)使能QE位,读取状态寄存器值
3)关于QE位,读取状态寄存器值
代码如下:
PRINTF("Get the QE bit value before QE enable!\r\n");
uint32_t QEvalue=0;
status = flexspi_nor_QE_register(EXAMPLE_FLEXSPI, &QEvalue);
if (status != kStatus_Success)
{
return status;
}
PRINTF("QE=%X!\r\n",(uint8_t)QEvalue);
/* Enter quad mode. */
status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI);
if (status != kStatus_Success)
{
return status;
}
PRINTF("Get the QE bit value after QE enable!\r\n");
status = flexspi_nor_QE_register(EXAMPLE_FLEXSPI, &QEvalue);
if (status != kStatus_Success)
{
return status;
}
PRINTF("QE=%X!\r\n",(uint8_t)QEvalue);
status = flexspi_nor_disable_quad_mode(EXAMPLE_FLEXSPI);
if (status != kStatus_Success)
{
return status;
}
PRINTF("Get the QE bit value after QE disable!\r\n");
status = flexspi_nor_QE_register(EXAMPLE_FLEXSPI, &QEvalue);
if (status != kStatus_Success)
{
return status;
}
PRINTF("QE=%X!\r\n",(uint8_t)QEvalue);
测试结果如下:
3.2 下载app FDCB 使能QE并测试
准备app FDCB使能QE的代码,这里使用SDK中的led_blinky代码,FDCB修改为上述使能QE的情况,并予以下载测试。
准备的app有两种:分别为2.1, 2.2两种方法,生产的app为:
evkmimxrt1170_iled_blinky_cm7_FCB_QE.bin
evkmimxrt1170_iled_blinky_cm7_FCB_QEGEN.bin
为了保证下载的flashloader不使能QE从而影响测试结果,这里使用MCUBootUtility, FDCB使用单线方式下载代码,配置如下:
下载evkmimxrt1170_iled_blinky_cm7_FCB_QE.bin或者evkmimxrt1170_iled_blinky_cm7_FCB_QEGEN.bin
到QSPI flash中:
四,附件
- 附件A
附上blhost的批量.bat文件内容
blhost -t 5242000 -u 0x1FC9,0x013D -j -- get-property 1 0
sleep 10
blhost -t 5242000 -u 0x1FC9,0x013D -j -- load-image ivt_flashloader_user.bin
sleep 100
blhost -t 50000 -u 0x15A2,0x0073 -j -- get-property 1 0
sleep 10
blhost -t 5242000 -u 0x15A2,0x0073 -j -- fill-memory 0x20202000 4 0xcf900001 word
sleep 100
blhost -t 50000 -u 0x15A2,0x0073 -j -- configure-memory 9 0x20202000
sleep 100
blhost -t 5242000 -u 0x15A2,0x0073 -j -- write-memory 0x20202000 cfg_fdcb_RTxxx_1bit_sdr_flashA.bin
sleep 200
blhost -t 50000 -u 0x15A2,0x0073 -j -- configure-memory 9 0x20202000
sleep 100
blhost -t 5242000 -u 0x15A2,0x0073 -j -- read-memory 0x30000000 0x1000 flexspiNorCfg.dat 9
sleep 200
blhost -t 2048000 -u 0x15A2,0x0073 -j -- flash-erase-region 0x30000000 0x9000 9
sleep 200
blhost -t 5242000 -u 0x15A2,0x0073 -j -- read-memory 0x30000000 0x1000 flexspiNorCfg.dat 9
sleep 200
blhost -t 5242000 -u 0x15A2,0x0073 -j -- write-memory 0x30000000 evkmimxrt1170_iled_blinky_cm7_FCB_QE.bin 9
sleep 200
blhost -t 5242000 -u 0x15A2,0x0073 -j -- read-memory 0x30000000 0x9000 flexspiNorCfg.dat 9
sleep 200
pause
- 附件B
.bat文件烧录log
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x1FC9,0x013D -j -- get-property 1 0
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 10
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x1FC9,0x013D -j -- load-image ivt_flashloader_user.bin
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 100
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 50000 -u 0x15A2,0x0073 -j -- get-property 1 0
{
"command" : "get-property",
"response" : [ 1258424064 ],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 10
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x15A2,0x0073 -j -- fill-memory 0x20202000 4 0xcf900001 word
{
"command" : "fill-memory",
"response" : [],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 100
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 50000 -u 0x15A2,0x0073 -j -- configure-memory 9 0x20202000
{
"command" : "configure-memory",
"response" : [],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 100
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x15A2,0x0073 -j -- write-memory 0x20202000 cfg_fdcb_RTxxx_1bit_sdr_flashA.bin
{
"command" : "write-memory",
"response" : [],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 200
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 50000 -u 0x15A2,0x0073 -j -- configure-memory 9 0x20202000
{
"command" : "configure-memory",
"response" : [],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 100
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x15A2,0x0073 -j -- read-memory 0x30000000 0x1000 flexspiNorCfg.dat 9
{
"command" : "read-memory",
"response" : [ 4096 ],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\KerryPC\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 200
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 2048000 -u 0x15A2,0x0073 -j -- flash-erase-region 0x30000000 0x9000 9
{
"command" : "flash-erase-region",
"response" : [],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 200
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x15A2,0x0073 -j -- read-memory 0x30000000 0x1000 flexspiNorCfg.dat 9
{
"command" : "read-memory",
"response" : [ 4096 ],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 200
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x15A2,0x0073 -j -- write-memory 0x30000000 evkmimxrt1170_iled_blinky_cm7_FCB_QE.bin 9
{
"command" : "write-memory",
"response" : [],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 200
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>blhost -t 5242000 -u 0x15A2,0x0073 -j -- read-memory 0x30000000 0x9000 flexspiNorCfg.dat 9
{
"command" : "read-memory",
"response" : [ 36864 ],
"status" : {
"description" : "0 (0x0) Success.",
"value" : 0
}
}
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>sleep 200
C:\--\IMXRTCode\Question\RT1170\flash\QSPI flash\FCB QE\kerry\app\cmd>pause