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

minichlink resetting option bytes on flash operations #232

Open
ddrown opened this issue Aug 23, 2023 · 4 comments
Open

minichlink resetting option bytes on flash operations #232

ddrown opened this issue Aug 23, 2023 · 4 comments

Comments

@ddrown
Copy link

ddrown commented Aug 23, 2023

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?

@AlexanderMandera
Copy link
Contributor

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?

@ddrown
Copy link
Author

ddrown commented Aug 23, 2023

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
Copy link
Author

ddrown commented Aug 28, 2023

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?

@Bingo600
Copy link

Bingo600 commented Nov 30, 2023

Here's an attempt (attached) to utilize the above bit patterns , to partition the CH307 Ram on flashing.
New option -K 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 ....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants