说到BootROM对FDCB的处理,大家有必要先回顾下痞子衡写过的一篇旧文 《深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程》,文章虽然是针对i.MXRT1050写的,但基本流程也差不多适用i.MXRT1170,在文中的 2.6 小节第二次初始化里,我们在上面FDCB里的关于Flash寄存器的额外配置操作才会被处理,代码大致如下:
status_t flexspi_init(uint32_t instance, flexspi_mem_config_t *config) { status_t status = kStatus_InvalidArgument; // 决定是否用30MHz SDR的安全时钟来做FlexSPI初始化 bool need_safe_freq = (config->deviceModeCfgEnable || config->configCmdEnable) && ((config->controllerMiscOption & (1 << kFlexSpiMiscOffset_SafeConfigFreqEnable))); if (need_safe_freq) { flexspi_clock_config(instance, kFlexSpiSerialClk_SafeFreq, kFlexSpiClk_SDR); } else { flexspi_clock_config(instance, config->serialClkFreq, flexspi_is_ddr_mode_enable(config)); } // 省略代码片段,包含FlexSPI引脚、模块本身等各种初始化 // 实现Flash配置寄存器写入操作 if (config->configCmdEnable) { // PortA1/A2/B1/B2如使能则全写一遍 flexspi_device_cmd_config_all_chips(instance, config); } if (need_safe_freq) { // 重新配回指定的FlexSPI时钟 flexspi_clock_config(instance, config->serialClkFreq, flexspi_is_ddr_mode_enable(config)); } return status; } void flexspi_device_cmd_config_all_chips(uint32_t instance, flexspi_mem_config_t *config) { uint32_t baseAddr = 0; uint32_t *flashSizeStart = &config->sflashA1Size; for (uint32_t index = 0; index < 4; index++) { uint32_t currentFlashSize = *flashSizeStart++; if (currentFlashSize > 0) { flexspi_device_cmd_config(instance, config, baseAddr); baseAddr += currentFlashSize; } } } void flexspi_device_cmd_config(uint32_t instance, flexspi_mem_config_t *config, uint32_t baseAddr) { FLEXSPI_Type *base = flexspi_get_module_base(instance); flexspi_xfer_t flashXfer; flashXfer.operation = kFlexSpiOperation_Config; flashXfer.baseAddress = baseAddr; flashXfer.isParallelModeEnable = false; flashXfer.txSize = 4; for (uint32_t index = 0; index < 3; index++) { if (config->configCmdSeqs[index].seqId > 0) { // If device is working under DPI/QPI/OPI mode, ignore SPI2XPI command uint32_t read_cmd_pads = (base->LUT[0] >> 8) & 0x03; if ((read_cmd_pads > FLEXSPI_1PAD) && (config->configModeType[index] == kDeviceConfigCmdType_Spi2Xpi)) { continue; } flashXfer.seqId = config->configCmdSeqs[index].seqId; flashXfer.seqNum = config->configCmdSeqs[index].seqNum; flashXfer.txBuffer = &config->configCmdArgs[index]; // 这里需要调用WRITE ENABLE指令 flexspi_device_write_enable(instance, config, false, baseAddr); flexspi_update_lut(instance, 1, &config->lookupTable[4 * flashXfer.seqId], flashXfer.seqNum); flashXfer.seqId = 1; flexspi_command_xfer(instance, &flashXfer); if ((!config->waitTimeCfgCommands) && (config->configModeType[index] != (uint8_t)kDeviceConfigCmdType_Spi2Xpi) && (config->configModeType[index] != (uint8_t)kDeviceConfigCmdType_Xpi2Spi)) { // 这里需要调用READ STATUS指令 flexspi_device_wait_busy(instance, config, false, baseAddr); } else { flexspi_sw_delay_us(config->waitTimeCfgCommands * 100UL); } } } }至此,Flash工作频率与Dummy Cycle的联系痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。