Hi everybody,
referring to:
I correctly see that, because of XIP, sln_flash.c and related have been relocated to SRAM_ITC_cm7 through linkscripts and that during erase, write, etc. operations interrupts and D-Cache are disabled:
But then I noticed that, because this project is based on RTOS, SysTick ISR is suspended during relatively long calls (sector erase may be 300 ms long according to the datasheet):
I know we're talking about 300 ms, which are not a lifetime but anyway are equivalent to 300 ticks skipped at every erase operation (and because of the filesystem we may have a lot of consecutive erase operation).
So the questions are:
- how this would affect RTOS scheduling?
- disabling ALL interrupts during such long operation is good practice?
Solved! Go to Solution.
Hi @SpoonMan ,
Sorry for the misleading previously.
I talked about your issues without an internal expert, and get the information that:
1. vector table in the flash need to copy to the internal RAM, and redirect the VTOR to the internal RAM.
2. copy the interrupt service function to the internal RAM. eg, your GPT2 interrupt Handler function to the internal RAM.
Then, you will do the flash operation.
Some blog from our expert may useful to you, but it is in Chinese, you can translate it, and try it on your side.
If you still meet issues, I will find time, to design one MCUXPresso project for it.
This post is also useful to you:
Best Regards,
Kerry
Hi @kerryzhou! Thank you very much for participating in this discussion, your contribution to this forum is very important for me.
Just make sure your API which use erase function can more than 300ms.
Can more than 300ms... what? Execute? If yes, I think this is not a problem at all, because while erasing IRQs are disabled; consequently, SysTick is disabled, which means RTOS scheduling is disabled too, so there's no risk the operation is interrupted...
disable ALL interrupt just make sure no issue happens. Otherwise, the flash operation may meet issues.
Yes, I know this very well... my question was if it's good practice to disable IRQs for so long operations (not what we intend for "atomic" I say) without taking care of consequences on scheduling times due to the disabling of SysTick IRQ.
Hi @SpoonMan ,
Thanks for your updated information.
You can check the related flash operation, whether it is the flexSPI API method, not the ROM, if yes, it needs to disable the interrupt.
In fact, that application you mentioned, also can make the application work, so you can refer to it.
For the flash operation, I think you also can try the ROM API method. ROM code will not be very sensitive like the flexSPI direct operation code.
About the interrupt disable, the freertos also have the related API which some code don't need to break by the interrupt, eg. taskENETER_CRITICAL_FROM_ISR();
Best Regards,
Kerry
For the flash operation, I think you also can try the ROM API method. ROM code will not be very sensitive like the flexSPI direct operation code.
I'm on i.MX RT1052 so I think that ROM API is not available for my platform, even if I really don't know the details about which benefits would I have if using ROM API instead of FlexSPI API.
Hi @SpoonMan ,
RT1050 is really not the complete ROM API.
But you still can refer to:
SDK_2_13_0_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\fsl_romapi
You can check it on your side.
Wish it helps you!
Best Regards,
Kerry
This sounds interesting, even if it looks like it works only on HyperFlash (some serial NOR structures and methods are missing in fsl_romapi.c/.h for 1050) while I'm oriented on QSPI Flash... am I right?
Hi @SpoonMan ,
So sorry for my later reply!
Yes, if you use the QSPI flash, you also can refer to that code, just do the FLEXSPI_NorFlash_GetConfig modification with the QSPI flash.
Maybe you don't know how to modify it, one example for you is the RT1060 flexspi polling code, that is the QSPI flash.
Wish it helps you!
Best Regards,
Kerry
Hi @kerryzhou
Don't worry about reply time... I'm also very busy on other topics, so it's not vital if I have no answer in minutes!
one example for you is the RT1060 flexspi polling code, that is the QSPI flash.
Yes, in fact when I said:
some serial NOR structures and methods are missing in fsl_romapi.c/.h for 1050
I was intending that I already tried to port 1060 example on 1050, but then I noticed that some serial NOR structures and methods was missing in fsl_romapi.c/.h for 1050. What I've done is the following:
/*! @brief The board flash size */
#define BOARD_FLASH_SIZE (0x800000U)
At this point, methods like ROM_FLEXSPI_NorFlash_GetConfig() are not present in ROM API implementation for 1050, and if I also brutally replace fsl_romapi.c/.h files from "evkbimxrt1060_fsl_romapi" example then I fall into Hard Fault runtime exception due to ROM API code incompatibility:
just do the FLEXSPI_NorFlash_GetConfig modification with the QSPI flash
Could you please better explain what do you mean I have to do when you say that?
Basically, what I notice it's wrong when replacing ROM API implementation from 1060 to 1050, are "bootloader_api_entry_t" and "flexspi_nor_driver_interface_t" definitions which are quite different and not providing get_config() method on 1050.
Hi @SpoonMan ,
Yes, RT1050, RT1060 ROM API is not the same.
As the RT1060 ROM support the get_config, but RT1050 can't support it.
You need to manually configure the get_config in the RT1050, just this API:
void FLEXSPI_NorFlash_GetConfig(flexspi_nor_config_t *config)
I mean, you need to modify the API internal related configuration, the config-> LUT, etc.
For the detail content, you can refer to the flexspi_polling in :
SDK_2_13_0_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\flexspi\nor
It's not difficult, you can try it, if you still meet issues, let me know, I may find time to help you to modify it. But for this part, it's better to create a new question post about it, as this post is a little old.
Best Regards,
Kerry
You need to manually configure the get_config in the RT1050, just this API:
void FLEXSPI_NorFlash_GetConfig(flexspi_nor_config_t *config)
I mean, you need to modify the API internal related configuration, the config-> LUT, etc.
I think it's not necessary at all, we already have the correct flexspi_nor_config_t structure defined in evkbimxrt1050_flexspi_nor_config.c! I mean this:
Let me give it a try to confirm...
Yessss! I succeeded!
FLEXSPI NOR example started!
Successfully init FLEXSPI serial NOR flash
HyperFlash Information:
Total program flash size: 8192 KB, Hex: (0x800000)
Program flash sector size: 4 KB, Hex: (0x1000)
Program flash page size: 256 B, Hex: (0x100)
Erasing serial NOR flash over FLEXSPI
Successfully erased one sector of NOR flash device 0x7ff000 -> 0x800000
Program a buffer to a page of NOR flash
Successfully programmed and verified location FLEXSPI memory 0x607ff000 -> 0x607ff100
End of FLEXSPI NOR Example!
In the following, I'll report what I modified in 1050 ROM API example project to make it working with QSPI Flash, instead of HyperFlash. In all the screenshots I'm going to post, left side is always MODIFIED code, right side is ORIGINAL EXAMPLE code.
First, I adjusted BOARD_FLASH_SIZE macro in board.h to reflect QSPI Flash total size:
Then I basically replaced evkbimxrt1050_flexspi_nor_config.h and evkbimxrt1050_flexspi_nor_config.c content with code from evkbimxrt1060_fsl_romapi example project; in evkbimxrt1050_flexspi_nor_config.h file, the only difference is the following:
while for evkbimxrt1050_flexspi_nor_config.c file basically EVERYTHING is different; in this case, let me just copy-paste modified file content:
/*
* Copyright 2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "evkbimxrt1050_flexspi_nor_config.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.xip_board"
#endif
/*******************************************************************************
* Code
******************************************************************************/
#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
#if defined(__CC_ARM) || defined(__ARMCC_VERSION) || defined(__GNUC__)
__attribute__((section(".boot_hdr.conf"), used))
#elif defined(__ICCARM__)
#pragma location = ".boot_hdr.conf"
#endif
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClksrc=kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.csHoldTime = 3u,
.csSetupTime = 3u,
.controllerMiscOption = (1u << kFlexSpiMiscOffset_SafeConfigFreqEnable),
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
.serialClkFreq = kFlexSpiSerialClk_120MHz,
.sflashA1Size = 8u * 1024u * 1024u,
.lookupTable =
{
// Read LUTs
[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),
// Read Status LUTs
[4 * 1 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),
// Write Enable LUTs
[4 * 3 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0x0),
// Erase Sector LUTs
[4 * 5 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20, RADDR_SDR, FLEXSPI_1PAD, 0x18),
// Erase Block LUTs
[4 * 8 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8, RADDR_SDR, FLEXSPI_1PAD, 0x18),
// Page Program LUTs
[4 * 9 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02, RADDR_SDR, FLEXSPI_1PAD, 0x18),
[4 * 9 + 1] = FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04, STOP, FLEXSPI_1PAD, 0x0),
// Erase Chip LUTs
[4 * 11 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60, STOP, FLEXSPI_1PAD, 0x0),
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = 1u,
.blockSize = 64u * 1024u,
.isUniformBlockSize = false,
};
#endif /* XIP_BOOT_HEADER_ENABLE */
In main source file (flexspi_romapi.c, don't ask me why NXP is not simply calling it main...) I commented out FLEXSPI_NorFlash_GetConfig() method because, as explained in my previous post, the idea is to read FLASH configuration from qspiflash_config instance already defined in evkbimxrt1050_flexspi_nor_config.c file:
[...]
I commented out everything related to local norConfig copy in main() method:
then, in each call involving norConfig pointer, I substituted it with (flexspi_nor_config_t*)&qspiflash_config. Let me post just some examples and not the entire code, you can do it by yourself easily:
Also local variables used for total FLASH size calculation etc. should take memory geometry information from qspiflash_config instead of norConfig:
and, more than this, qspiflash_config should be visible from main source file:
Last but not least, some macros related to memory geometry defined in main file (don't ask me why NXP is defining here and there macros reporting again and again always the same memory geometry information...) are no more necessary because related to FLEXSPI_NorFlash_GetConfig() method which we will not use anymore, but FLASH_PAGE_SIZE should be adapted because used by the sample code as read and write size:
That's it! Hope that my contribution will be appreciated, obviously thanks to @kerryzhou for giving some hint!
Sorry @kerryzhou but you said:
You can check the related flash operation, whether it is the flexSPI API method, not the ROM, if yes, it needs to disable the interrupt.
But if I configure and enable GPT2 to generate a periodic interrupt (in which I toggle USER_LED state, this doesn't matter) and I loop in a while (1) erase/program/read/verify code from ROM API example, I then fall into hard fault as with FLEXSPI API if I don't disable interrupts while performing FLASH operations.........
This is not what you mentioned in the quoted sentence... could you please help? I'm a little bit disappointed... Here is where I'm looping forever:
[...]
HI @SpoonMan ,
Just conform with you, with the ROM API, if you don't open the GPT interrupt, the write, erase, read are all working now, right?
But, when enable the GPT interrupt, it is failed, whether my understanding is correct or not?
Best Regards,
Kerry
Hi @kerryzhou
Yes, your understanding of my behavior is 100% correct. But please check my project, it'll help you to kickstart straight to the problem.
Hi @SpoonMan ,
Sorry for the misleading previously.
I talked about your issues without an internal expert, and get the information that:
1. vector table in the flash need to copy to the internal RAM, and redirect the VTOR to the internal RAM.
2. copy the interrupt service function to the internal RAM. eg, your GPT2 interrupt Handler function to the internal RAM.
Then, you will do the flash operation.
Some blog from our expert may useful to you, but it is in Chinese, you can translate it, and try it on your side.
If you still meet issues, I will find time, to design one MCUXPresso project for it.
This post is also useful to you:
Best Regards,
Kerry
Hi @kerryzhou
Thanks for your feedback, I have at least two questions:
Hi @SpoonMan ,
1.described method of moving vector table and ISRs to RAM is also valid for fsl_flexspi API, not only for ROM API, so what are the benefits of using ROM API instead of FlexSPI API?
=>Answer:Yes, moving vector table valid for both fsl_flexspi API which is in RAM, and the ROM API.
ROM API is just don't need to move to RAM. fsl_flexSPI need to put to the RAM, as the QSPI can't support the RWW function.
2.described method of moving vector table and ISRs to RAM looks to be not sufficient when applied in a time-division scheduling RTOS scenario, in which SysTick ISR may schedule another task while active task is still reading/writing/erasing the FLASH, consequently all tasks must be moved to RAM, and all functions called by all task must be moved to RAM.... or briefly, all the code must be moved to RAM
=>Answer:In fact, I check internally, also the same consideration like you. the RTOS tick timer.
So, you need to put the SysTick ISR to RAM. Just the interrupt hander, not all other task to the RAM.
Wish it helps you!
If you still have questions about it, please kindly let me know.
Best Regards,
Kerry
@kerryzhou So, you need to put the SysTick ISR to RAM. Just the interrupt hander, not all other task to the RAM.
Let me give you a simple example of a behavior I don't like: even if I would move SysTick ISR to RAM, what would happen is, for example during an erase operation of e.g. 300ms, my whole RTOS "freezes" for the whole erase time duration. This is really not good at all, it would turn a RTOS into a non-realtime operating system at all.
In this situation, the only option is to move the WHOLE application to RAM? Or do we have other options?
Hi @SpoonMan ,
No, you misunderstand it.
I can understand you that, if the erase happens, the timer seems can't be interrupt, as that will influence the time tick for the OS.
But, in fact, even you do the flash operation, the timer interrupt still can work, just make sure this point:
When do the flash related operation, eg, program, erase,etc. the flash will in the busy status, during the busy status, if the interrupt happens, and this interrupt ISR handler in the flash area, then it will meet the issues. So, if we just put the interrupt ISR handler to the RAM, other code still in the flash, the timer will works Ok, so no realtime influence.
The ROM API will also can put in the flash directly, don't like the fsl_flash which need to put in the internal RAM.
So, if you combine the ROM API and the interrupt ISR in the RAM, then all other code still in flash, just interrupt code in the RAM during the flash operation.
If you still have questions about it, please kindly let me know.
You can try to move the interrupt to the internal RAM, please note, not the whole app. just:
XXX_ISRHandler()
{
} , and the vector table to the internal RAM.
Any issues you meet, just kindly let me know.
Best Regards,
Kerry
Sorry @kerryzhou if I insist, but I find there are some misleading sentences in all your responses.
You said:
ROM API is just don't need to move to RAM. fsl_flexSPI need to put to the RAM, as the QSPI can't support the RWW function.
Then you said:
The ROM API will also can put in the flash directly, don't like the fsl_flash which need to put in the internal RAM.
So, if you combine the ROM API and the interrupt ISR in the RAM, then all other code still in flash, just interrupt code in the RAM during the flash operation.
What's wrong?
If ROM API supports RWW, why it's not possible to fetch instructions from QSPI Flash while writing at a different address? Vice-versa, if you say I need to relocate ROM API code and ISR to RAM, why you said before that ROM API doesn't need to move to RAM?
I think there's a lot of confusion on the topic....
Thanks in advance for the disambiguation answer.