ch32v003fun icon indicating copy to clipboard operation
ch32v003fun copied to clipboard

minichlink resetting option bytes on flash operations

Open ddrown opened this issue 2 years ago • 4 comments

I'm using the ch32v307, and it has a register to determine the ram/flash split. I'm guessing it's doing a shadow copy of the flash contents into ram. This is the option byte at 0x1ffff802, which is copied to the register OBR in the flash controller at startup.

I can set the option byte to use a 192KB flash/128KB sram split just fine with:

    FLASH_Unlock();
    FLASH_ProgramOptionByteData(0x1FFFF802, (FLASH_GetUserOptionByte() & 0b00111111));
    FLASH_Lock();

The board picks up my change through a reset, by pushing the reset button or using minichlink -a -b or NVIC_SystemReset();

Reading back the option bytes:

volatile uint8_t *optionBytes = (uint8_t *)0x1FFFF800;
printf("USER=%x %x %x %x\r\n", optionBytes[0], optionBytes[1], optionBytes[2], optionBytes[3]);

I get the expected value:

USER=a5 5a 3f c0

And the flash OBR register has the split I want:

OBR = 0x3fffcfc (192K+128K RSVR1 RSVR2 RSVR3 STANDBY_RST STOP_RST IWDG_SW)

But when I flash a new image with minichlink -a -w build/example.bin 0x08000000 -b, something is resetting my user option bytes back to 0xff:

USER=a5 5a ff 0

Which resets back to the 288K/32K memory split:

OBR = 0x3fffffc (288K+32K RSVR1 RSVR2 RSVR3 STANDBY_RST STOP_RST IWDG_SW)

I experimented with commenting out OBKEYR unlocking in InternalUnlockFlash, but that didn't change this behavior.

Any ideas on what to try next?

ddrown avatar Aug 23 '23 03:08 ddrown

The InternalUnlockFlash is not used for V307 because for WCH-LinkE it uses a custom implementation of WriteBinaryBlob.

We aim to make a low-level implementation of the protocol, so the registers can be set directly. I will try to fix this issue when I am working on that again.

Have you tried out if similar alternatives like the Rust-based wlink mess with the option bytes as well?

AlexanderMandera avatar Aug 23 '23 16:08 AlexanderMandera

wlink doesn't work properly with my WCH-LinkE:

$ wlink flash --address 0x08000000 build/example.bin
17:01:44 [INFO] WCH-Link v2.9 (WCH-LinkE-CH32V305)
17:01:44 [INFO] Attached chip: CH32V30x(0x30700528)
17:01:44 [INFO] Read build/example.bin as Binary format
17:01:44 [INFO] Flashing 9792 bytes to 0x08000000
17:01:44 [INFO] Flash done
17:01:45 [INFO] Now reset...
17:01:45 [INFO] Resume executing...
Error: DMI Status Failed

After that error, the microcontroller isn't printing to serial and wlink just prints error messages for any command:

$ wlink regs
17:12:04 [INFO] WCH-Link v2.9 (WCH-LinkE-CH32V305)
17:12:04 [INFO] Attached chip: CH32V30x(0x30700528)
Error: DM Abstract comand error: Parity

But if I power cycle the board, the debugger comes back and it looks like wlink isn't resetting the option bytes.

ddrown avatar Aug 23 '23 17:08 ddrown

Ok, looking at the official programmer, it sets the user option bytes along with readout protection with:

$ grep 81:06:08:02 *.txt
128k.txt:81:06:08:02:3f:ff:ff:ff:ff:ff:ff
32k.txt:81:06:08:02:ff:ff:ff:ff:ff:ff:ff
64k.txt:81:06:08:02:bf:ff:ff:ff:ff:ff:ff
96k.txt:81:06:08:02:7f:ff:ff:ff:ff:ff:ff

The surrounding context is:

> 81:06:01:01
< 82:06:01:02
> 81:06:08:02:bf:ff:ff:ff:ff:ff:ff
< 82:06:01:02
> 81:02:01:01
< 82:02:01:01
> 81:0d:01:02
< 82:0d:05:06:30:70:05:28
> 81:06:01:01
< 82:06:01:02

So since this is in between two 81:06:01:01's, I tried modifying pgm-wch-linke.c with:

        wch_link_command( (libusb_device_handle *)dev, "\x81\x06\x01\x01", 4, 0, 0, 0 );
+       wch_link_command( (libusb_device_handle *)dev, "\x81\x06\x08\x02\xbf\xff\xff\xff\xff\xff\xff", 11, 0, 0, 0 );
        wch_link_command( (libusb_device_handle *)dev, "\x81\x06\x01\x01", 4, 0, 0, 0 ); // Not sure why but it seems to work better when we request twice.

that gives me 64K ram, but it isn't especially elegant. Any ideas on how to handle this better?

ddrown avatar Aug 28 '23 02:08 ddrown

Here's an attempt (attached) to utilize the above bit patterns , to partition the CH307 Ram on flashing. New option -K <RamKB> ie. -K 64 - Valid 32 / 64 / 96 / 128 minichlink-ram-partitioning.zip

Btw: I'm a git novice , don't send a pull request. I have included a git-diff

I "cheated" , and used two Global variables .. Dunno' if minichlink Author will kill me ....

Bingo600 avatar Nov 30 '23 14:11 Bingo600