gicking / stm8gal

PC tool for uplading hexfiles to the STM8 microcontroller via UART or SPI , using the built-in ROM bootloader. Works under Windows and Posix operating systems
Apache License 2.0
80 stars 21 forks source link

allow to program the option bytes #6

Closed tenbaht closed 5 years ago

tenbaht commented 5 years ago

It would be useful to be able to access and modify the option bytes using stm8gal. Especially the ROP (read out protection) bit for unlocking a locked MCU is important.

gicking commented 5 years ago

hi Michale,

using option "-x" stm8gal already deactivates the bootloader via option byte (and it's complementary). Via bootloader this is identical to writing other flash memory. So adding this is VERY simple, the question is mainly the "user interface"

What would you prefer?

Regards, Georg

gicking commented 5 years ago

I just compared the datasheets of STM8AF52xx and STM8L101xx, and unfortunately the option bytes don't match. In addition the STM8L does not require the complementary value, probably to save a few bytes... :-(

tenbaht commented 5 years ago

stm8flash treats the option bytes simply as a generic memory area that can be read and written. It is the users responsibility to format the content accordingly. Maybe something similar for stm8gal? Using stm8flash looks like this:

stm8flash -c stlinkv2 -p "stm8s103?3" -s opt -r opt.bin

How about an option "-s "? It could default to flash memory if not given. This allows for easy extensions in the future e.g. for EEPROM access.

If you decide to add a device type specifier anyway (because of the uart mode issue) It would be possible to integrate the knowledge about the exact memory layout into stm8gal and allow a more user-friendly interface similar to the fuse definitions with avrdude: avrdude -U efuse:w:0xaa:m. Maybe something like this:

stm8gal -p s103 -s opt1 -w 0x02 -s opt2 -w 0x00

But I am not sure if this is really better than a generic interface similar to stm8flash.

gicking commented 5 years ago

I prefer option 1 because it matches the procedure in stm8flash, and also because I don't plan to add a device specifier for the uart mode issue . Besides the many different supported options would just blow up stm8gal.

Do I understand correctly that file opt.bin contains plain binary data, and that -s opt only sets the target address to the start of the option bytes?

Alternatively how about writing option bytes from a hexfile with proper address and value...? Such a hexfile could be easily created from an ASCII-table using hexfile_merger. And as a positive side-effect I wouldn't need to change stm8gal ;-)

tenbaht commented 5 years ago

I am not sure if only setting the target address is enough. I think the access needs to unlocked first by a magic sequence and two special bits need to be set in the flash control registers. (rm0016, sec. 4.4.6, page 43). But sec. 4.6.5 (page 49) gives hope: "Option byte programming is very similar to data EEPROM byte programming".

I guess there is a reason why the guys at stm8flash add a special option for this memory area (but I don't know for sure). Reading the option byte area of an unlocked STM8S103F3P6 without any option bits set (on Mint 19) looks like this:

$ stm8flash -c stlinkv2 "-pstm8s103?3" -s opt -r opt.hex
Determine OPT area
Due to its file extension (or lack thereof), "opt.hex" is considered as INTEL HEX format!
Reading 64 bytes at 0x4800... OK
Bytes received: 64
$ cat opt.hex 
:204800000000FF00FF00FF00FF00FF0000000000000000000000000000000000000000009D
:20482000000000000000000000000000000000000000000000000000000000000000000078
:00000001FF

Or in binary mode:

$ stm8flash -c stlinkv2 "-pstm8s103?3" -s opt -r opt.bin
Determine OPT area
Due to its file extension (or lack thereof), "opt.bin" is considered as RAW BINARY format!
Reading 64 bytes at 0x4800... OK
Bytes received: 64
$ hd opt.bin
00000000  00 00 ff 00 ff 00 ff 00  ff 00 ff 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000040
gicking commented 5 years ago

you are correct about unlocking option byte range. However, this is apparently taken care of by the bootloader or the RAM routines already. Because if you look at main.c line 773 you see that activating the bootloader is done via

bsl_memWrite(ptrPort, physInterface, uartMode, 0x487E, 2, (char*)"\x55\xAA", -1);

and bsl_memWrite() makes no distinction between P-flash or option bytes. So no magic there... :-)

As said, the main question is the "UI", not the actual writing of the option bytes. But let me check again

gicking commented 5 years ago

my current idea is to write option bytes just like a "normal" hexfile. Already tested it and it works :-)

Procedure:

  1. create plain option byte table like in this example
  2. use hexfile_merger tool to convert to hexfile via hexfile_merger -i table.txt -o option.s19
  3. dump option bytes via stm8gal -p /dev/ttyUSB0 -r 0x4800 0x487F pre.txt
  4. upload result to STM8 via stm8gal -p /dev/ttyUSB0 -w option.s19
  5. dump option bytes again via stm8gal -p /dev/ttyUSB0 -r 0x4800 0x487F post.txt
  6. comparison via diff pre.txt post.tx confirms the intended change in OPT2/NOPT2
    4,5c4,5
    < 0x4803    0x00
    < 0x4804    0xff
    ---
    > 0x4803    0x80
    > 0x4804    0x7f

I understand that calling an extra tool is inconvenient, but that can be overcome rather easily by adding an import filter for plain tables (like this). Then changing option bytes becomes as easy as RTFM... ;-) I actually prefer this method over cryptic commandline parameters, because it is more transparent. But what do you think?

IMHO the only disadvantage is that stm8gal can currently only upload one file at a time --> to upload a software AND change the option bytes it must be called twice. Changing that could be done by adding support for multiple file import (like hexfile_merger).

But first things first: is changing option bytes via plain ASCII tables the way to go? Please let me know what you think. Thanks in advance!

PS: By the way, as the memory dumps from steps 3+5 have the same format as the import file in step 1, they are convenient starting points for option byte setups :-)

tenbaht commented 5 years ago

Sound like a good start. I will try it next week.

Would it be possible to support using the txt files as input files directly? It would be a custom hex file format.

Instead of hexfile_merger the standard objcopy (or sdobjcopy from the sdcc package) can do the job of converting binary data into a valid s19 file:

$ echo -n "abcd" > test.bin # just 4 bytes of nonsense data
$ sdobjcopy --change-addresses 0x4800 -I binary -O srec test.bin test.s19
$ cat test.s19
S0080000612E7331398B
S10748006162636426
S9034800B4

How about supporting raw binary data as input? That would save the conversion step to s19. The address transformation can be handled by either specifing a memory type (like -s option) or an address parameter (like -a 0x4800).

gicking commented 5 years ago

yes, I plan to support both ASCII tables and binary data as input format. Then changing option bytes becomes very easy. My current idea is like this:

ASCII Table: file format is currently detected by file extension. I will simply add a new filter for "*.txt" for tables like this:

# OPT2 alternate function
0x4803  0x80
0x4804 0x7F

Binary File: add a new option -wb addr file (="write binary"), like you proposed. Then the above conversion step to s19 would no longer be required.

Let me know what you think :-)

PS: one more question: I remember that Cosmic allows to specify static data with address. That is how I used to set option bytes from within a project without having to change them only. Unfortunately I don't recall how this is done, but does SDCC allow this as well? If yes, that is yet another option, i.e. encapsulated in the resulting build output. At least I should point out this option in the Readme.md.

gicking commented 5 years ago

ASCII table seems to work now, see branch "addTableAndBinary". Please try and let me know. Thanks in advance!

Syntax is same as before (stm8gal -p /dev/ttyUSB0 -w OPT2.txt). Simple example tables can be found in folder "option_bytes".

gicking commented 5 years ago

just uploaded branch "addTableAndBinary" which now allows multiple uploads (and downloads) in one run. In addition it is now possible to change a value in flash or RAM directly (option -s), or via an ASCII table (*.txt). That way option bytes (or any other memory) can be changed easily.

Note however, that inconsistent option bytes (NOPT != OPT^0xFF) result in an endless reset cycle, i.e. bootloader is effectively disabled --> recover requires SWIM and stm8flash. Therefore always change option bytes pairs if applicable (is device dependent)

Please let me know what you think of this. Also please let me know if the previos UART mode detection is working for your boards...? Thanks a lot in advance!

gicking commented 5 years ago

Writing option bytes works in v1.3.0 via hexfiles, binary files or files with plain text, e.g.

# OPT2 alternate function
0x4803  0x80
0x4804 0x7F

Warning: use option bytes with cary! If OPT and NOPT (=inverse) bytes don't match. the STM8 stays in an endless reset cycle. This condition can only be fixed via SWIM interface.