I recently tried to develop a custom app flasher (based on the stm32loader Python module) for STM32L073xx microcontrollers, but I got stuck at one point.

This lib tries to obtain the flash size from thr micro because for the same chip UID (0x447 - STM32L07x/L08x/L010) we can have different flash sizes. The lib sends a command to read the memory (cmd 0x11 0xEE) and here my problem starts:

  • flash size is stored at address 0x1FF8007C (RM0367, section 34.1.1)
  • the internal bootloader allows reading memory in the range of the system memory: 0x1FF00000 - 0x1FF01FFF (AN2606 Rev35, ch.56 "Device-dependent bootloader parameters", STM32 series L0, PID 0x447)

When I try to read the flash size from this address, I receive the response 0x1F (NACK), and I cannot continue the process.

Of course I could copy the flash size byte somewhere in RAM before jumping to the system bootloader or assume some flash size, but then the application won't be robust for all chips.

How should it be handled the proper way? Is there another address where flash size is stored?

Now I'm able to read the whole flash content, but there is a new challenge. I've tried to perform a mass erase to prepare the flash for writing new content and surprise surprise ... the bootloader returns NACK for any type of mass erase!

My communication looks like this:

  • enter bootloader
  • send 0x7F, get 0x79 (ACK)
  • send 0x44 0xBB, get 0x79 (ACK) - Extended Erase Memory command

Now I tried the following:

  • send 0xFF 0xFF 0x00, get 0x1F (NACK) - Mass Erase
  • send 0xFF 0xFE 0x01, get 0x1F (NACK) - Bank 1 Erase
  • send 0xFF 0xFD 0x02, get 0x1F (NACK) - Bank 2 Erase

None of them work ... any suggestions?

  • \$\begingroup\$ Show the actual operations you attempt to use with complete detail. Are any other operations (like flashing) a success? \$\endgroup\$ Commented Jan 21, 2019 at 14:04
  • \$\begingroup\$ Would you like do see terminal/logic analyzer log? It's quite simple. During startup I jump to bootloader when some magic number is set in RAM (I check it before initializing RAM with data). Then from PC app i run python script which sends 0x7F to activate bootlader usart channel, i've got 0x79 (ACK), then I send 0x11 0xEE, get 0x79, send 0x1F 0xF8 0x00 0x7C and CRC, then I get from bootloader 0x1F (NACK). If address is within defined range, everything is ok. If i hardcode flash size and skip asking for it, i'm able for example to read whole flash through bootloader read command. \$\endgroup\$
    – voldi
    Commented Jan 21, 2019 at 18:47
  • 1
    \$\begingroup\$ @voldi Your follow-up question should be posted as a new question, instead of an edit. \$\endgroup\$
    – Lundin
    Commented Jan 22, 2019 at 12:26
  • \$\begingroup\$ I made it like that but somebody edited it. I wanted to just continue solving my issues. \$\endgroup\$
    – voldi
    Commented Jan 22, 2019 at 14:37
  • \$\begingroup\$ This is not a discussion forum, questions can't be extended with new issues. Your original problem was solved, now you need a new question on a new page. \$\endgroup\$ Commented Jan 22, 2019 at 15:23

1 Answer 1


It's unclear why reading address 0x1FF8007C does not work, I get the same failure.

However, experimenting with a Nucleo-L073RZ shows that it will permit one to read 128 bytes starting at address 0x1FF80000, which will have the flash size value which you seek as its penultimate 16-bit word.

Thinking it might be an offset issue I tried reads at 0x1FF80000 + [0x70, 0x60, 0x40] none of which worked. Conversely, reading at 0x800007c does work, so offsets are allowed in general. And as the read size is sent after the point where the address is NAK'd, it's not an issue with a 32- or 16-bit read being required.

Anyway, reading out a 128 byte block should solve your problem.

Another idea would be to start at an address near the top of the largest flash size and read down until you stop getting a failure. Or you could load a little stub into RAM and execute it. But it seems like reading out 128 bytes will be your simplest solution.

As an aside, using https://github.com/florisla/stm32loader (which seems to be what is on pypi, you didn't say what you were using) I found that I had to reset the chip each time I invoked the program, so apparently it is not leaving the bootloader in the right state. Still, that is an improvement over another tool I'd tried a few months back, which refused to talk to the L07x bootloader at all, though it was fine with the L05x one...

If one really wanted to spend an afternoon descending a rabbit hole, it would probably be possible to set a breakpoint before sending the address CRC byte and trace the bootloader operation to the logic which generates the ACK or NAK, but as it's in ROM all you would probably learn is precisely what is or (apparently erroneously) is not allowed.

  • \$\begingroup\$ your workaround works and I already implemented it into lib (yes, I'm using stm32loader from pypi). It's strange that bootloader which isn't some beta version has that kind of limitation... Anyway I'm able now to read whole flash content, but there is new challenge. See edit above. \$\endgroup\$
    – voldi
    Commented Jan 22, 2019 at 9:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.