Mboot SPI Flash Question

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
marc4444
Posts: 14
Joined: Sat Aug 03, 2019 12:16 pm

Mboot SPI Flash Question

Post by marc4444 » Tue Mar 31, 2020 5:04 pm

Hi all,

I've built a custom board with the STM32F12CE (that's working fine with micropython after a new board definition) and I'm trying use MBOOT to load firmware from an SPI memory chip (32M-BIT Winbond W25Q32JV). I've previously got MBOOT working with the pyboard lite and a similar SPI memory chip (64M-BIT Winbond W25Q64FW).

On my custom board I don't have USB access which is making things more tricky - I have UART1 with a REPL to speak to the board and also all the pins for ST-Link so I can flash FW onto the device.

I've downloaded the .dfu.gz file ok onto the device and I can see the file is correct (length/checksums match). When I call the below bootload function I lose the REPL connection, the two LEDs both light up (LED 1 and LED 2 on my board), but nothing else happens, even after > 1 minute it just sits there with both LEDs on. When I cycle the power the old FW boots up fine.

import fwupdate
fwupdate.update_mpy('fw2.dfu.gz',0x80000000,0x400000)

In my board .mk file I have:

MCU_SERIES = f4
CMSIS_MCU = STM32F412Cx
AF_FILE = boards/stm32f412_af.csv
LD_FILES = boards/BA_V3/mem_map.ld boards/BA_V3/mem.ld
TEXT0_ADDR = 0x0800C000

The memory files are copied from the pyboard lite ones and adjusted for MBOOT:
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */
FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 16K */
FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 16K /* sectors 1 is 16K */
FLASH_TEXT (rx) : ORIGIN = 0x0800C000, LENGTH = 464K /* sector 3 is 16K, 4 is 64K, 5,6,7 are 128K */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
}

Then I've declared what I think are the correct variables in mpconfigboard.h:
#define MBOOT_FSLOAD (1)
#define MBOOT_SPIFLASH_ADDR (0x80000000)
#define MBOOT_SPIFLASH_BYTE_SIZE (4 * 1024 * 1024)
#define MBOOT_SPIFLASH_LAYOUT "/0x80000000/16*04Kg"
#define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (16 / 4)
#define MBOOT_SPIFLASH_SPIFLASH (&spi_bdev.spiflash)
#define MBOOT_SPIFLASH_CONFIG (&spiflash_config)

I've been through all the docs and can't see what I'm doing wrong.. Any help is really appreciated?

Thanks,
Marc

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Mboot SPI Flash Question

Post by dhylands » Tue Mar 31, 2020 6:36 pm

Doesn't mboot start at 0x08000000? It looks like your DFU image is also starting at the same address, which means that mboot would be wiping itself out?

marc4444
Posts: 14
Joined: Sat Aug 03, 2019 12:16 pm

Re: Mboot SPI Flash Question

Post by marc4444 » Tue Mar 31, 2020 9:05 pm

Hi David,

Thanks for the quick reply - My understanding is yes mboot is at 0x08000000 but I don't see how the DFU image starts at the same address? I thought the 'TEXT0_ADDR = 0x0800C000' shifts the ISR after the filesystem, leaving 0x08000000 free for MBOOT.

I've pasted both memory files that are included in the .mk file below. They are both based on the pyboard example. Am I missing something?

Thanks very much!

My version below of the boards/stm32f405.ld is very similar except i've reduced the FLASH_FS down to give more room for a larger program file in FLASH_TEXT:

Code: Select all

/*
    GNU linker script for STM32F412
*/

/* Specify the memory areas */
MEMORY
{
    FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */
    FLASH_ISR (rx)  : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 16K */
    FLASH_FS (rx)   : ORIGIN = 0x08004000, LENGTH = 16K /* sectors 1 is 16K */
    FLASH_TEXT (rx) : ORIGIN = 0x0800C000, LENGTH = 464K /* sector 3 is 16K, 4 is 64K, 5,6,7 are 128K */
    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 256K
}

/* produce a link error if there is not this amount of RAM for these sections */
_minimum_stack_size = 2K;
_minimum_heap_size = 16K;

/* Define the stack.  The stack is full descending so begins just above last byte
   of RAM.  Note that EABI requires the stack to be 8-byte aligned for a call. */
_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
_sstack = _estack - 16K; /* tunable */

/* RAM extents for the garbage collector */
_ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = _ebss; /* heap starts just after statically allocated memory */
_heap_end = _sstack;


And the copy of common_blifs.ld is unchanged (I think):

Code: Select all

/* Memory layout for internal flash storage configuration:

    FLASH_ISR   .isr_vector

    FLASH_TEXT  .text
    FLASH_TEXT  .data

    RAM         .data
    RAM         .bss
    RAM         .heap
    RAM         .stack
*/

ENTRY(Reset_Handler)

/* define output sections */
SECTIONS
{
    /* The startup code goes first into FLASH */
    .isr_vector :
    {
        . = ALIGN(4);
        KEEP(*(.isr_vector)) /* Startup code */

        . = ALIGN(4);
    } >FLASH_TEXT

    /* The program code and other data goes into FLASH */
    .text :
    {
        . = ALIGN(4);
        *(.text*)          /* .text* sections (code) */
        *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    /*  *(.glue_7)   */    /* glue arm to thumb code */
    /*  *(.glue_7t)  */    /* glue thumb to arm code */

        . = ALIGN(4);
        _etext = .;        /* define a global symbol at end of code */
    } >FLASH_TEXT

    /* used by the startup to initialize data */
    _sidata = LOADADDR(.data);

    /* This is the initialized data section
    The program executes knowing that the data is in the RAM
    but the loader puts the initial values in the FLASH (inidata).
    It is one task of the startup to copy the initial values from FLASH to RAM. */
    .data :
    {
        . = ALIGN(4);
        _sdata = .;        /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */
        *(.data*)          /* .data* sections */

        . = ALIGN(4);
        _edata = .;        /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */
    } >RAM AT> FLASH_TEXT

    /* Uninitialized data section */
    .bss :
    {
        . = ALIGN(4);
        _sbss = .;         /* define a global symbol at bss start; used by startup code */
        *(.bss*)
        *(COMMON)

        . = ALIGN(4);
        _ebss = .;         /* define a global symbol at bss end; used by startup code and GC */
    } >RAM

    /* this is to define the start of the heap, and make sure we have a minimum size */
    .heap :
    {
        . = ALIGN(4);
        . = . + _minimum_heap_size;
        . = ALIGN(4);
    } >RAM

    /* this just checks there is enough RAM for the stack */
    .stack :
    {
        . = ALIGN(4);
        . = . + _minimum_stack_size;
        . = ALIGN(4);
    } >RAM

    .ARM.attributes 0 : { *(.ARM.attributes) }
}


User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Mboot SPI Flash Question

Post by dhylands » Tue Mar 31, 2020 9:13 pm

The 0x08000000 I noticed was this:

Code: Select all

import fwupdate
fwupdate.update_mpy('fw2.dfu.gz',0x80000000,0x400000)

marc4444
Posts: 14
Joined: Sat Aug 03, 2019 12:16 pm

Re: Mboot SPI Flash Question

Post by marc4444 » Tue Mar 31, 2020 9:18 pm

Ah ok understood - i think they are slightly different (below) and the call to update_mpy() references the location/length of the SPI flash.

Code: Select all

0x08000000<< Mboot start
0x80000000<< SPI Flash start
Any other ideas on what could be causing it just to hang without deleting anything? I wasn't sure if it needed any special changes for the STMF412?

I also wasn't entirely sure on the settings for 'MBOOT_SPIFLASH_LAYOUT ' and 'MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE ' for the memory chip i'm using...

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Mboot SPI Flash Question

Post by jimmo » Tue Mar 31, 2020 11:36 pm

OK, so if I understand correctly:

You have a custom board definition that is very similar to PYBV11 but with mboot in sector 0, filesystem in sectors 1, sector 2 unused (?), and code (inc ISR) at sector 3 onwards.
Have you modified flashbdev.c to set FLASH_MEM_SEG1_NUM_BLOCKS to match your 16kiB FS?

I assume you also set USE_MBOOT=1 in mpconfigboard.mk?

What are:
boards/BA_V3/mem_map.ld boards/BA_V3/mem.ld

I'd expect to see this using (your custom) stm32f412.ld and (standard) boards/common_blifs.ld

How is the external flash filesystem mounted in regular operation? It almost sounds like maybe mboot can't mount the filesystem on the external flash.

Is there any way you can share your board configs and any additional scripts on github?
marc4444 wrote:
Tue Mar 31, 2020 9:18 pm
I also wasn't entirely sure on the settings for 'MBOOT_SPIFLASH_LAYOUT ' and 'MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE ' for the memory chip i'm using...
Yes these definitely need to be correct.

marc4444
Posts: 14
Joined: Sat Aug 03, 2019 12:16 pm

Re: Mboot SPI Flash Question

Post by marc4444 » Wed Apr 01, 2020 4:13 pm

Thanks for the detailed reply Jimmo - going through each of your points:
jimmo wrote:
Tue Mar 31, 2020 11:36 pm
You have a custom board definition that is very similar to PYBV11 but with mboot in sector 0, filesystem in sectors 1, sector 2 unused (?), and code (inc ISR) at sector 3 onwards.
Yes this is correct. And good spot I had missed sector 2! I updated the mem_map.ld file so it looks like the below.

Code: Select all

/*
    GNU linker script for STM32F412
*/

/* Specify the memory areas */
MEMORY
{
    FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */
    FLASH_ISR (rx)  : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0,1 are 16K each */
    FLASH_FS (rx)   : ORIGIN = 0x08008000, LENGTH = 16K /* sectors 2 is 16K */
    FLASH_TEXT (rx) : ORIGIN = 0x0800C000, LENGTH = 464K /* sector 3 is 16K, 4 is 64K, 5,6,7 are 128K */
    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 256K
}

/* produce a link error if there is not this amount of RAM for these sections */
_minimum_stack_size = 2K;
_minimum_heap_size = 16K;

/* Define the stack.  The stack is full descending so begins just above last byte
   of RAM.  Note that EABI requires the stack to be 8-byte aligned for a call. */
_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
_sstack = _estack - 16K; /* tunable */

/* RAM extents for the garbage collector */
_ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = _ebss; /* heap starts just after statically allocated memory */
_heap_end = _sstack;

jimmo wrote:
Tue Mar 31, 2020 11:36 pm
Have you modified flashbdev.c to set FLASH_MEM_SEG1_NUM_BLOCKS to match your 16kiB FS?
I hadn't - I've corrected this now by creating the definition below in flashbdev.c, I fixed the start_addr and num_blocks (I think):

Code: Select all

#elif defined(STM32F412Cx)

STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k
#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
#define FLASH_SECTOR_SIZE_MAX (0x4000) // 16k max due to size of cache buffer
#define FLASH_MEM_SEG1_START_ADDR (0x08008000) // sector 2
#define FLASH_MEM_SEG1_NUM_BLOCKS (32) // sector 2: 16k
jimmo wrote:
Tue Mar 31, 2020 11:36 pm
I assume you also set USE_MBOOT=1 in mpconfigboard.mk?
I had been declaring it on every use but have moved it into mpconfigboard.mk:
jimmo wrote:
Tue Mar 31, 2020 11:36 pm
What are:
boards/BA_V3/mem_map.ld boards/BA_V3/mem.ld
I'd expect to see this using (your custom) stm32f412.ld and (standard) boards/common_blifs.ld
Correct - mem_map.ld is effectively stm32f412.ld and mem.ld is a copy of common_blifs.ld
jimmo wrote:
Tue Mar 31, 2020 11:36 pm
How is the external flash filesystem mounted in regular operation? It almost sounds like maybe mboot can't mount the filesystem on the external flash.
I had previously added code into mpconfigboard.h as guided in other parts of the forum - my understanding is that this will mount the SPI flash. I had the same settings to mount the SPI flash with the pyboard version that I got working so hopefully these are correct.
jimmo wrote:
Tue Mar 31, 2020 11:36 pm
Yes these definitely need to be correct.
Could you just confirm how the 'MBOOT_SPIFLASH_LAYOUT ' and 'MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE ' should be set for a specific SPI flash chip? The datasheet for the one I'm using https://www.winbond.com/resource-files/ ... 242017.pdf says "Up to 256 bytes can be programmed at a time. Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or the entire chip (chip erase)". So my understanding is this would equate to the below settings? But let me know if I've misunderstood?

Code: Select all

#define MBOOT_SPIFLASH_LAYOUT "/0x80000000/16*04Kg"
#define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (16 / 4)
Just to confirm - I've compiled with the settings above (make BOARD=V3 USE_MBOOT=1 clean all) for both the mboot and main firmware, and flashed it onto a chip but the same behaviour happens (it just hangs with both LEDs on) when calling 'fwupdate.update_mpy('fw2.dfu.gz',0x80000000,0x400000)'.

Thanks again for the great reply and if you have any thoughts it would be great to hear?

marc4444
Posts: 14
Joined: Sat Aug 03, 2019 12:16 pm

Re: Mboot SPI Flash Question

Post by marc4444 » Mon Apr 06, 2020 6:41 am

In case anyone else has this issue - it turns out that the problem was that I was using the internal crystal rather than an external crystal on my custom board. Micropython supports this but MBOOT did not, I spoke with Damien and he's adding a fix in main.c in mboot for this so shouldn't be an issue in the future! Thanks for the help.

Post Reply