Menu

#118 Unable to erase Flash pages after page 512

0.6
Fixed
nobody
None
Medium
Defect
2021-01-23
2019-10-10
No

Hello,
I'm using stm32flash with stm32l082 with 192 K Flash and I'm unable to erase pages >= 512.

The process to induce the fault is as follows:

Start with flash containing valid code and read 2 bytes:

./stm32flash /dev/ttyUSB0 -r out.bin -S 0x0800FFFF:2

This gives two bytes into out.bin, whose are related to the neighbouring addresses:

0x0800FFFF: A9
0x08010000: FF

Then trying to erase whole flash:

./stm32flash -o /dev/ttyUSB0
 ...
Erasing flash
Mass erase failed. Try specifying the number of pages to be erased.
Failed to erase memory

OK, trying page by page errase:

./stm32flash -oe 1500 /dev/ttyUSB0
stm32flash 0.5
...
Erasing flash

Output seems to be OK, but when reading back the bytes, there is a missmatch with expected values:

./stm32flash /dev/ttyUSB0 -r out.bin -S 0x0800FFFF:2
0x0800FFFF: 00
0x08010000: FF

Just the first byte has been errased!

This has been tested with version 0.5 (last stable with modified page number limit constant) and with the latest code from the repository. Both versions lead to the same behavior.

It has been tested with two STM32L0 MCUs independently.

This problem also arises during the flash programming (this is where we discovered it): in case of missmatch between the code in Flash and the code beeing loaded, the programming fails after page 512: the code cannot be loaded: the read-back veriffication failed (or there is unreported inconsistent flash state in case, when "-v" is ommited).

Discussion

  • Anonymous

    Anonymous - 2020-02-28

    This seems to be my mistake - I had padding errors in my commands

     
  • Jan Belohoubek

    Jan Belohoubek - 2020-11-13

    Is there something I can do to help fix this?

    Best,
    Jan

     
  • Tormod Volden

    Tormod Volden - 2020-11-13

    So it is not because you had padding errors in your commands? Was that comment from you?

     
  • Tormod Volden

    Tormod Volden - 2020-11-13

    In stm32_erase_memory() there is a loop erasing 512 pages at a time. Maybe it fails on the second iteration. Can you step through it with gdb (please attach text session)?

     
  • Tormod Volden

    Tormod Volden - 2020-11-15
    • Milestone: none --> 0.6
     
  • Jan Belohoubek

    Jan Belohoubek - 2020-11-16

    That was not my comment - I thought it was yours (one of the developers).

    I'll test it today and let you know.

     
  • Jan Belohoubek

    Jan Belohoubek - 2020-11-16

    Hello Tormod,
    I make a journey through the code and the docs and I found the problem. The following change fixes the issue:

    //n = (pages <= 512) ? pages : 512;
    n = (pages <= 255) ? pages : 255;
    

    This was my first idea, as I saw the code, as the regular erase (0x43) command limits the number of pages to 1 byte. (page 22 in AN3155 Rev 13) And thus 512 cannot be represented.

    But then I traced the code and I found, that 0x44 command is actually executed, thus this should not be a problem. For illustration, I added some printfs rather than gdb output, as this is much more compact.

    Here for pages splited with 256 as maximum:

    stm32flash 0.5
    
    http://stm32flash.sourceforge.net/
    
    Interface serial_posix: 57600 8E1
    Version      : 0x31
    Option 1     : 0x00
    Option 2     : 0x00
    Device ID    : 0x0447 (STM32L07xxx/08xxx)
    
    - RAM        : Up to 20KiB  (8192b reserved by bootloader)
    - Flash      : Up to 192KiB (size first sector: 32x128)
    - Option RAM : 32b
    - System RAM : 8KiB
    Erasing flash
    CMD: 0x44 ;Page #: 0x0FE SPage: 0x0  ... ExtDone
    CMD: 0x44 ;Page #: 0x0FE SPage: 0xFF  ... ExtDone
    CMD: 0x44 ;Page #: 0x0FE SPage: 0x1FE  ... ExtDone
    CMD: 0x44 ;Page #: 0x0FE SPage: 0x2FD  ... ExtDone
    CMD: 0x44 ;Page #: 0x0FE SPage: 0x3FC  ... ExtDone
    CMD: 0x44 ;Page #: 0x0E0 SPage: 0x4FB  ... ExtDone
    

    And now bank 2 is erased!

    Here for pages splited with 512 as maximum:

    stm32flash 0.5
    
    http://stm32flash.sourceforge.net/
    
    Interface serial_posix: 57600 8E1
    Version      : 0x31
    Option 1     : 0x00
    Option 2     : 0x00
    Device ID    : 0x0447 (STM32L07xxx/08xxx)
    
    - RAM        : Up to 20KiB  (8192b reserved by bootloader)
    - Flash      : Up to 192KiB (size first sector: 32x128)
    - Option RAM : 32b
    - System RAM : 8KiB
    Erasing flash
    CMD: 0x44 ;Page #: 0x1FF SPage: 0x0  ... ExtDone
    CMD: 0x44 ;Page #: 0x1FF SPage: 0x200  ... ExtDone
    CMD: 0x44 ;Page #: 0x1DB SPage: 0x400  ... ExtDone
    

    and bank 2 is not erased! While program flow looks good for both cases!

    So I don't know where is actualy the problem (it might be in bootloader itself ?).

    On the other hand, limiting to 256 makes sense, as stm32_pages_erase() function is not checking number of pages even for regular erase - probably splitting should be done inside stm32_pages_erase() - based on actual erase command - rather than prior calling it.

    This fix looks working and it should break nothing (except increasing erase delays) but the root of the problem is escaping ...

     
  • Jan Belohoubek

    Jan Belohoubek - 2020-11-16

    Hello Tormod,
    one more interresting finding: there is some difference: you used 512, which is 2^9, I used 256, which is 2^8-1 ... when I used your 512 to erase and I dumped whole memory, I found, that only page 512 remains NOT erased - it looks, that the erase command skips page 512.

    When I used 255, memory is zeroed, but it might be an coincidence (I used random hex to fill the memory)

    here you decrement:
    pg_byte = (pages - 1) >> 8;

    Is this correct?

    This might be the problem. It looks, that changing to 255, I only skipped different pages ...

    Best,
    Jan

     
  • Jan Belohoubek

    Jan Belohoubek - 2020-11-17

    Hello Tormod,
    I'm sorry for itterative comments/test reports!

    I already found in the docs, that "pg_byte = (pages - 1) >> 8"; is correct.

    Sorry for that!

    I finally filled the MCU flash by ones (not a random program) and erased with different settings of splitting constants and my previous hypotheses seems to be wrong too.

    I used the following settings:

    //n = (pages <= 1024) ? pages : 1024; // wrong - 65536 bytes remains 0xFF
    //n = (pages <= 1023) ? pages : 1023; // wrong - 65536 bytes remains 0xFF
    //n = (pages <= 512) ? pages : 512; // wrong - 128 bytes remains 0xFF
    //n = (pages <= 511) ? pages : 511; // OK - 0 bytes
    //n = (pages <= 256) ? pages : 256; // OK - 0 bytes
    //n = (pages <= 255) ? pages : 255; // OK - 0 bytes
    
    // just to test non power-of-two related numbers
    // n = (pages <= 600) ? pages : 600;  // wrong - 22656  bytes remains 0xFF
    n = (pages <= 100) ? pages : 100; // OK - 0 bytes
    

    My test flow was (in.bin is 192K of 0xFF; hex is an alias to hexdump and it writes a byte per line)

    ./stm32flash /dev/ttyUSB0 -w in.bin -S 0x08000000:196480
    ./stm32flash -oe 1535 /dev/ttyUSB0
    ./stm32flash /dev/ttyUSB0 -r out.bin -S 0x08000000:196480
    hex out.bin | grep ff | wc -l
    

    It seems, that for 512 and above, the issue occurs: after erase and read back, some of the flash pages remain non-erased. In the case, that splitting constant is below 512, it seems to be OK.

    In the code, you mentioned: "Some device, like STM32L152, cannot erase more than 512 pages in one command." Might the relation be "<" not "<=" than 512?

    I was not successful with searching the limit of "maximum number of pages" for the MCU I have (STM32L082), nor for any other STM device.

    Best,
    Jan

     

    Last edit: Jan Belohoubek 2020-11-18
    • cJ

      cJ - 2021-01-18

      I was playing around with an STM32L082 and am thankful for Jan's "patch" above.

       
  • Tormod Volden

    Tormod Volden - 2021-01-19

    The code that splits up the erase operation was introduced in commit cdfcc5ef. The commit message suggests that the 512 limit was found by experiments and not by documentation. Does it work for you if you lower the limit to 511 on line 943 which originally is:
    n = (pages <= 512) ? pages : 512;

     
  • Jan Belohoubek

    Jan Belohoubek - 2021-01-20

    Hello Tormod,
    yes - everything below 512 is OK, anythiing above 512 (incl. 512) is NOT OK.

    It seems, that I found the STM32L082 bootloaders' limit. But in docs, I found nothing...potentially, there may arise prolems with another MCUs.

    I think, the best solution here would be to lower the default limit even more (e.g 255 - one can imaine, that uint8_t should be the smaller natural daty type to keep the page count) and add a command line argument to allow to set the limit from the command line - this is a "self-driving" solution for users with potential problems or for users looking for greater performance.

    What do you think?

     
  • Tormod Volden

    Tormod Volden - 2021-01-23

    I think if it works for you with 511 (and we haven't heard others complaints), 511 is fine. I rather think the limitation of 511 is a bug in the bootloader. We are sending the 2 bytes with the number of pages N, then 2 x N bytes with the page numbers. Maybe the buffer in the bootloader is wrongly dimensioned to 2 x N, or are only iterated to maximum 2 x N - 1 elements (reaching buffer offset 2 x N), or something like that.

    So I will limit it to 511, hopefully covering all devices and only with a slight performance drop for those who would have worked with 512.

     
  • Tormod Volden

    Tormod Volden - 2021-01-23
    • status: New --> Fixed
     

Anonymous
Anonymous

Add attachments
Cancel





MongoDB Logo MongoDB