Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not able to erase section of memory on STM32F103 #73

Open
GeorgeIoak opened this issue Jan 16, 2024 · 10 comments
Open

Not able to erase section of memory on STM32F103 #73

GeorgeIoak opened this issue Jan 16, 2024 · 10 comments

Comments

@GeorgeIoak
Copy link

GeorgeIoak commented Jan 16, 2024

I'm working on a project where I have an application loaded at 0x08005000 and I have reserved 22 pages. I was running some tests on how to erase that section of memory and I can't seem to get it to work without getting an error when it tries to create the bytearray of pages to erase:

C:\Users\george>py -m stm32loader -p COM20 -f F1 -V -e -a 0x08005000 -l 0x5800
Open port COM20, baud 115200
Activating bootloader (select UART)
*** Command: Get
    Bootloader version: 0x22
    Available commands: 0x0, 0x1, 0x2, 0x11, 0x21, 0x31, 0x43, 0x63, 0x73, 0x82, 0x92
Bootloader version: 0x22
*** Command: Get ID
Chip id: 0x410 (STM32F10x Medium-density)
*** Command: Read memory
*** Command: Read memory
Device UID: FF35-066B-30474630-43152645
Flash size: 128 KiB
*** Command: Erase memory
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Python312\Lib\site-packages\stm32loader\__main__.py", line 41, in <module>
    main()
  File "C:\Python312\Lib\site-packages\stm32loader\__main__.py", line 37, in main
    stm32loader_main(*sys.argv[1:])
  File "C:\Python312\Lib\site-packages\stm32loader\main.py", line 248, in main
    loader.perform_commands()
  File "C:\Python312\Lib\site-packages\stm32loader\main.py", line 148, in perform_commands
    self.stm32.erase_memory(pages)
  File "C:\Python312\Lib\site-packages\stm32loader\bootloader.py", line 624, in erase_memory
    page_numbers = bytearray(pages)
                   ^^^^^^^^^^^^^^^^
ValueError: byte must be in range(0, 256)

C:\Users\george>py -m stm32loader --version
0.7.1
@GeorgeIoak
Copy link
Author

I'm a little confused by the explanation in the AN3155 app note but I think we should be sending the page number of each page after we've sent the number of pages to erase:

Erase Memory command specifications:
1. The bootloader receives a byte that contains N, the number of pages to be erased – 1. 
N = 255 is reserved for global erase requests. For 0 ≤ N ≤ 254, N + 1 pages are erased.
2. The bootloader receives (N + 1) bytes, each byte containing a page number.

So if I pass in the starting address of 0x08005000 the pages_from_range should return a list starting with page 20 going to page 42

@GeorgeIoak
Copy link
Author

So either I've stumbled on a bug or the example on the main page is wrong:

stm32loader --erase --address 0x08000000 --length 0x2000 --port /dev/cu.usbserial-A5XK3RJT

Because if I pass the offset from 0x08000000 the erase command will work:

C:\Users\george>py -m stm32loader -p COM20 -f F1 -V -e -a 0x5000 -l 0x5800
Open port COM20, baud 115200
Activating bootloader (select UART)
*** Command: Get
    Bootloader version: 0x22
    Available commands: 0x0, 0x1, 0x2, 0x11, 0x21, 0x31, 0x43, 0x63, 0x73, 0x82, 0x92
Bootloader version: 0x22
*** Command: Get ID
Chip id: 0x410 (STM32F10x Medium-density)
*** Command: Read memory
*** Command: Read memory
Device UID: FF35-066B-30474630-43152645
Flash size: 128 KiB
*** Command: Erase memory
    Erase memory done
    ```

@dbeinder
Copy link

dbeinder commented Jan 16, 2024

This is a bug, or at least an inconsistency in the --address argument. In selective erase mode, the address starts at 0 for the start of the flash, otherwise the pages are calculated incorrectly:

# Erase from address to address + length.
start_address = self.configuration.address
end_address = self.configuration.address + self.configuration.length
pages = self.stm32.pages_from_range(start_address, end_address)
self.stm32.erase_memory(pages)
# Assemble the list of pages to erase.
first_page = start // self.flash_page_size
last_page = end // self.flash_page_size
pages = list(range(first_page, last_page))

@florisla florisla added the bug label Jan 16, 2024
@florisla
Copy link
Owner

Thanks for reporting this. Not sure if I should change the behavior or the docs...

I think changing the behavior would make the --address argument more consistent with other uses.

@dbeinder
Copy link

I'd prefer the intuitive way, to have --address always refer to a memory mapped location. Of course, that would require stm32loader to know the flash base addresses for all chips to do selective erase. It would be a nice feature in itself - for many families the fixed fallback value of the --address argument is probably a bad idea anyway.

The easiest would be to add a separate, mandatory argument like --erase-start which can then start at 0 for start-of-flash.

@GeorgeIoak
Copy link
Author

If I had a vote I too would prefer that --address refers to the actual location as I think that's easier on the user and eliminates any confusion.

@florisla
Copy link
Owner

@GeorgeIoak Thanks, the more input the better! But can you clarify if by 'the actual location' you mean the offset relative to start of flash ('implemented behavior') or the absolute address ('documented behavior'). Bot addressing modes are equally 'real' in my mind ;-)

@GeorgeIoak
Copy link
Author

Sorry for the confusion, I mean the actual location, 0x08005000 because that's what you enter in the linker script.

@GeorgeIoak
Copy link
Author

GeorgeIoak commented Jan 18, 2024

I was hoping that maybe I could ask for some clarification on the actual erase command and what the bootloader expects. When I issue this, py -m stm32loader -p COM20 -f F1 -V -e -a 0x5000 -l 0x5800 what is the actual data sent and returned?

I know after 0x43, 0xBC the STM32 should send an ACK and then AN3155 says to send

  • the number of pages to be erased – 1
  • The bootloader receives (N + 1) bytes, each byte containing a page number
  • checksum, XOR (N, N+1 bytes))

In my example I calculate the First Page = 20 and the last page = 42 so 23 total pages so if I'm thinking correctly we should be sending:

  • 22
  • 20, 21, 22, ...42
  • 23

I believe that I've calculated the checksum correctly but maybe not. After sending this we should expect to receive an ACK back from the STM32

But I see that we're sending

  • 21
  • 20, 21, 22, ...41
  • 20

So shouldn't we be erasing page 42 and with the current code it looks like we're only going to erase up to page 41.

@florisla
Copy link
Owner

florisla commented Jan 18, 2024

Hi, I thought you were on to a bug... but on second thought I think your calculation is off.

Length 0x5800 is decimal 22528, which is 22 KiB (22 * 1024). So the page count is 22. Sending page_count_minus_one == 21 and then page indices 20 to 41 is what you asked stm32loader to do.

To also erase page 42 you would supply -l 0x5c00.

In your calculation, the first page is 20. Start address plus length results in page 42. But that is not the page index of the last page to be erased. 42 is the page index of the first page which is no longer included. The 'last' page which gets erased is 41. This is due to zero-based counting; 20 ends with a zero but it is first page to be erased.

@florisla florisla added this to the Next-version milestone Feb 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants