IMXRT Fota update the firmware in the flash

290 views
Skip to first unread message

Embedded Systems

unread,
Aug 7, 2019, 9:14:22 AM8/7/19
to NuttX
Hello,

I need to make firmware over the air (FOTA) update for our device which is based on IMXRT. So let me give you little bit more information about my idea. We are using IMXRT with external 16Mbyte NOR FLash and the IMXRT execute the firmware directly from it. I need to find a way to update that firmware. I am aware that i need to make QSPI driver but i am trying to figure out what else do i need. So I plan to have 3 different sections in the flash. 

1. config section - this section is must for IMXRT , because the CPU reads the flash settings and the firmware start address from this section every time when it boots.

THe other 2 sections are identical and they both are for firmware, the idea is if you execute from firmware section 1 at the moment then the update will go in firmware section 2 and on the next boot the execution will be from section 2. and the opposite if the firmware is executed from firmware section 2 at the moment , the update will go in section 1 and on the next boot it will execute from section 1. 

So in order to do that i have to be able erase and write in specific blocks and sectors of the flash memory from the application. My question how to erase or write in specific block or sector of Nor flash memory from the application layer in Nuttx.

Thank you in advance!

Best regards,
Ivan Ucherdzhiev

Gregory Nutt

unread,
Aug 7, 2019, 10:05:43 AM8/7/19
to nu...@googlegroups.com

> So in order to do that i have to be able erase and write in specific
> blocks and sectors of the flash memory from the application. My
> question how to erase or write in specific block or sector of Nor
> flash memory from the application layer in Nuttx.

Normally you would write a FLASH MTD driver with three partitions.  The
low-levels details for erasing and writing should be in the user manual.

The upper half is at drivers/mtd/mtd_progmem.c.  The lower half
interface is at include/nuttx/progmem.c.  You see an example
implementation in arch/arm/src/stm32/stm32_flash.c

Partitiions are managed by drivers/mtd/mtd_partitioni.c.


Embedded Systems

unread,
Aug 7, 2019, 10:14:23 AM8/7/19
to NuttX
Thank you Mr. Gregory! 

If i understand correctly i will need qspi driver (for communication with the memory), memory specific driver for the used memory low level read, write , erase and a FLASH MTD driver for the connection between the application and the  specific driver , am I understanding correctly?

Best regards,
Ivan Ucherdzhiev

--
You received this message because you are subscribed to the Google Groups "NuttX" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nuttx+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nuttx/6d06f2f1-78a0-4aa0-f902-4cba7f96049a%40gmail.com.


--
Kind regards,
Ivan Ucherdzhiev

Team Lead @ Barin Sports
Bulgaria
skype: ipy_44

Gregory Nutt

unread,
Aug 7, 2019, 10:16:14 AM8/7/19
to nu...@googlegroups.com

> If i understand correctly i will need qspi driver (for communication
> with the memory), memory specific driver for the used memory low level
> read, write , erase ...
This is the progmem driver similar to stm32_flash.c
> and a FLASH MTD driver for the connection between the application and
> the specific driver , am I understanding correctly?

This one you should not have to write.  This is the one at
drivers/mtd/mtd_progmem.c



Gregory Nutt

unread,
Aug 7, 2019, 10:24:15 AM8/7/19
to nu...@googlegroups.com
Hmmm.. I am confused.  All of the above "progmem" logic is used for
accessing on-chip FLASH memory.  Forget everything I said. For external
memory, there are fewer things you need to write: Only the QSPI MTD
driver.  You can skip the progmem stuff since you are using external memory.

In that case, there is only the QSPI MTD driver.  There are examples of
QSPI MTD drivers in drivers/mtd:    mx25rxx.c, n25qxxx.c, s25fl1.c,
sst26.c.  Things would be connected like:

1. User layer:  Flash file system (SmartFS, NXFFS, SPIFFS, LittleFS)
--OR-- a raw character/block driver interface (drivers/mtd/ftl.c)
2. QSPI MTD driver
3. Hardware

That is a little simpler conceptually.



Embedded Systems

unread,
Aug 7, 2019, 10:38:58 AM8/7/19
to NuttX
Thank you Mr. Gregory , I got what i need to do .

Best regards,
Ivan Ucherdzhiev

--
You received this message because you are subscribed to the Google Groups "NuttX" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nuttx+un...@googlegroups.com.

Embedded Systems

unread,
Mar 27, 2020, 6:19:12 AM3/27/20
to NuttX
Hello Mr. Gregory,

I would like to ask for advice. I am facing a problem of understanding for exactly to update the firmware of a XIP flash memory. My idea so far is to. define 2 regions in the flash memory with equal size. Active region from which the code is currently executed and "update" region in which the new firmware will be uploaded and after it is uploaded the CPU will be reconfigured to start executing the firmware for the updated region. The problem is i dont understand how to write/erase sectors in flash memory which is used as a XIP memory. The only possible solution which i see so far is to define all write/erase function to be placed and executed from the RAM memory. Can you please give me advice am i on the right direction or give me some advice how to deal with that issue? 

thank you in advance!

Best regards,
Ivan Ucherdzhiev

Virus-free. www.avast.com

Gregory Nutt

unread,
Mar 27, 2020, 12:01:23 PM3/27/20
to nu...@googlegroups.com

I would like to ask for advice. I am facing a problem of understanding for exactly to update the firmware of a XIP flash memory. My idea so far is to. define 2 regions in the flash memory with equal size. Active region from which the code is currently executed and "update" region in which the new firmware will be uploaded and after it is uploaded the CPU will be reconfigured to start executing the firmware for the updated region.

That is a pretty standard strategies.  It protects against a bad download bricking the device.

There has to be a small, third region that just contains some housekeeping information like which flash region has the bootable image and to execute that image.  A partition could (1) have not valid image, (2) have an unverified image, or (3) have a verified image.

I there is an unverified image, the boot-up logic should mark that as "not valid" then execute it.  When it runs, it should change its state to verified.  Subsequently, the boot-up logiv should revert to the verified image.

The problem is i dont understand how to write/erase sectors in flash memory which is used as a XIP memory. The only possible solution which i see so far is to define all write/erase function to be placed and executed from the RAM memory. Can you please give me advice am i on the right direction or give me some advice how to deal with that issue?

I don't think I fully understand your concerned.  If  flash image A is running in partition 1, it does not need to execute out of RAM to write flash image B in partition 2.

Is the concern because you cannot execute from this flash memory while modifying it?  If the hardware behaves that way, then yes, you would have to execute from RAM.

If you have plenty of external RAM, the perhaps the proper solution is to always execute entirely from RAM.  Otherwise, you can use ramfuncs to move some of the functions into RAM at bootup.  Look in imxrt_start.c:

335   /* Copy any necessary code sections from FLASH to RAM.  The correct
336    * destination in OCRAM is given by _sramfuncs and _eramfuncs.  The
337    * temporary location is in flash after the data initialization code
338    * at _framfuncs.  This should be done before imxrt_clockconfig() is
339    * called (in case it has some dependency on initialized C variables).
340    */
341
342 #ifdef CONFIG_ARCH_RAMFUNCS
343   for (src = &_framfuncs, dest = &_sramfuncs; dest < &_eramfuncs; )
344     {
345       *dest++ = *src++;
346     }
347 #endif

And at, for example, imxrt1060-evk/scripts/flash-ocram.ld:

169     .ramfunc ALIGN(4):
170     {
171         _sramfuncs = ABSOLUTE(.);
172         *(.ramfunc  .ramfunc.*)
173         _eramfuncs = ABSOLUTE(.);
174     } > sram AT > flash
175
176     _framfuncs = LOADADDR(.ramfunc);

That is all you need to use to execute functions from RAM.

Greg



Gregory Nutt

unread,
Mar 27, 2020, 12:09:44 PM3/27/20
to nu...@googlegroups.com

...you can use ramfuncs to move some of the functions into RAM at bootup.  Look in imxrt_start.c:

335   /* Copy any necessary code sections from FLASH to RAM.  The correct
336    * destination in OCRAM is given by _sramfuncs and _eramfuncs.  The
337    * temporary location is in flash after the data initialization code
338    * at _framfuncs.  This should be done before imxrt_clockconfig() is
339    * called (in case it has some dependency on initialized C variables).
340    */
341
342 #ifdef CONFIG_ARCH_RAMFUNCS
343   for (src = &_framfuncs, dest = &_sramfuncs; dest < &_eramfuncs; )
344     {
345       *dest++ = *src++;
346     }
347 #endif

And at, for example, imxrt1060-evk/scripts/flash-ocram.ld:

169     .ramfunc ALIGN(4):
170     {
171         _sramfuncs = ABSOLUTE(.);
172         *(.ramfunc  .ramfunc.*)
173         _eramfuncs = ABSOLUTE(.);
174     } > sram AT > flash
175
176     _framfuncs = LOADADDR(.ramfunc);

That is all you need to use to execute functions from RAM.

I don't see any usage of ramfuncs in the i.MXRT code, but there are examples for other architectures.  They all work the same.  It looks like other MCUs have issues about running from FLASH and modifying FLASH concurrently too:

src/efm32/efm32_flash.c:#ifndef CONFIG_ARCH_RAMFUNCS
src/efm32/efm32_flash.c:int __ramfunc__ msc_load_verify_address(uint32_t *address)
src/efm32/efm32_flash.c:int __ramfunc__ msc_load_write_data(uint32_t *data, uint32_t num_words,
src/efm32/efm32_flash.c:ssize_t __ramfunc__ up_progmem_eraseblock(size_t block)
src/efm32/efm32_flash.c:ssize_t __ramfunc__ up_progmem_write(size_t addr, const void *buf, size_t size)

./src/samv7/sam_eefc.c:#if defined(CONFIG_ARCH_HAVE_RAMFUNCS) && defined(CONFIG_ARCH_RAMFUNCS)
./src/samv7/sam_eefc.c:__ramfunc__ void sam_eefc_writefmr(uint32_t regval)
./src/samv7/sam_eefc.c:__ramfunc__ int sam_eefc_command(uint32_t cmd, uint32_t arg)
./src/samv7/sam_eefc.c:__ramfunc__ int sam_eefc_readsequence(uint32_t start_cmd, uint32_t stop_cmd,
./src/samv7/sam_eefc.c:#endif /* defined(CONFIG_ARCH_HAVE_RAMFUNCS) && defined(CONFIG_ARCH_RAMFUNCS) */

There are some platforms that have to use RAM functions to perform flash clock configuration too.

For ARM, __ramfunc__ is defined in:

src/common/up_internal.h:#  define __ramfunc__ __attribute__ ((section(".ramfunc"),long_call,noinline))

Greg


Embedded Systems

unread,
Mar 30, 2020, 9:23:58 AM3/30/20
to NuttX
Hello Mr. Gregory,

thank you very much. Yes my concerns is because i cannot modify the flash memory while using it as XIP.

My plan is the following. Put all the FleXSPI functions in the RAM memory, so that will let me update the flash (i already test that and it is working if the transfer functions are blocking ).

The other thing which is not clear for me is how to make the flexspi exactly for the nuttx standard. The flex spi interface in IMXRT is not like the common QSPI interface and it is working with LUT table which have to be uploaded at the initialization phase. When the flash memory is used as XiP there is a small partition at the beginning of the flash memory which contains the LuT and the flash memory information. The bootloader in the IMXRT is reading that partition, setting up the flexspi interface and then starting to execute the firmware from the flash (that means that if the flash is used as XiP it does not need to be initialized again from the firmware because the bootloader already did it). 

If the flash is nto used as XiP, then it has to be initialized from the firmware and the LuT table have to be configured. my question is where is the proper plase for that LuT table. The LuT table is different for the different flash but the format of the LuT table is specific for IMXRT that is why i believe the right place is the board.h file. What are your thoughts about that is this the right place?

I am planing to have a working polling mode of flexspi during the end of this week if everything is working correctly

Thank you in advance!
Best regards,
Ivan Ucherdzhiev

--
You received this message because you are subscribed to the Google Groups "NuttX" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nuttx+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages