openwch / arduino_core_ch32

Core library for CH32duino
243 stars 42 forks source link

CH32V103 Runs at 8 MHz instead of 72 MHz #75

Open Khalinda opened 5 months ago

Khalinda commented 5 months ago

I was bench marking floating point operations on a CH32V103C8V6 based board and I noticed very poor performance. I loaded a standard Arduino Blink sketch (with 1000 ms delays), and the LED was blinking on and off every 18 seconds instead of every 2 seconds. I modified a "GPIO_Toggle" MounRiver Studio project to also blink an LED with 1000 ms delays, and it behaves as expected.

The CH32V103C8T6 board has an 8 MHz crystal oscillator. The Arduino sketch is behaving as though the RCC PLL isn't being initialized to multiply the external oscillator frequency by 9. I modified the Blink sketch and the GPIO_Toggle project to print the values of all of the RCC registers. The values don't make sense to me, but both the sketch and the project report identical values:

RCC->CTLR 0x15583
RCC->CFGR0 0x0
RCC->INTR 0x0
RCC->APB2PRSTR 0x0
RCC->APB1PRSTR 0x0
RCC->AHBPCENR 0x4
RCC->APB2PCENR 0x4004
RCC->APB1PCENR 0x0
RCC->BDCTLR 0x0
RCC->RSTSCKR 0x18000000

Does anybody know what else I can check to track down this problem?

maxint-rd commented 5 months ago

For the CH32V003 without external crystal, I had to change some configuration value in a header file, see issue #27. Someone else had that very same issue and made it into PR #66 . Perhaps your CH32V103 also needs a configuration change?

Khalinda commented 5 months ago

Thanks maxint-rd, I had already looked into "system_ch32v10x.c". In your case, you selected a different clock configuration and the code for that configuration worked correctly. In my case, the correct clock configuration appears to be selected, but the code does not work.

The CH32V103 is bit of an odd-ball chip. A number of its peripherals are unlike those of any other chip and the WCH reference manuals provide only the bare minimum of information, so it's hard to determine what could be wrong.

I compared the "system_ch32v10x.c" file from the project with the one from the Arduino core, and there was a small difference, so I copied the file from the project to the Arduino core and I rebuilt the sketch. Unfortunately, that didn't help.

Most of the files in the MounRiver Studio project are also present in the Arduino core, and there were differences in several files, so I overwrote the files in the Arduino core with the corresponding files from the project (around 100 files). Unfortunately, that didn't help either.

Perhaps the code to configure the clock isn't even being called.

maxint-rd commented 5 months ago

Too bad all your efforts were in vain. Hopefully someone else can help to solve this issue (WCH..., anyone...?) At the moment I only added the CH32V003 to my MCU collection and I'm still attempting to make it to do the regular Arduino things (eg. I2C slave is still missing). (I'll consider your experience a warning to not order this oddball chip until its Arduino core has matured.)

Khalinda commented 5 months ago

Apparently people in the know choose the CH32V203 chip instead of the CH32V103. (Nobody told me.) I've ordered a RISC-V "BluePill" board. It seems that they come with a CH32V203C8T6 chip instead of an ST32F103C8T6.

Khalinda commented 5 months ago

While comparing elf files, I noticed that "main" in GPIO_Toggle calls SystemCoreClockUpdate but main in Blink does not. I commented out the call to SystemCoreClockUpdate and that caused GPIO_Toggle to exhibit the same slow clock behavior as Blink.

Instead of SystemCoreClockUpdate, main in Blink calls pre_init. I know that DeqingSun has debugging working in the Arduino IDE, but I can't figure out what he did. Without a debugger, I haven't been able to track through the code called by pre_init to sort out what is going wrong.

So, without finding the actual problem, I came up with a work around. I copied the first two statements from main in main.c from GPIO_Toggle to main in main.cpp in the Arduino core.

int main( void )
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // added code
    SystemCoreClockUpdate();                // added code
    pre_init( );
    setup( );

    do {
        loop( );

    } while (1);

    return 0;
}

That change seems to fix the clock problem. The system clock is kind of a "configure once" device, so these statements need to appear before pre_init, (before it can cause trouble).

maxint-rd commented 5 months ago

Great. Congratulations on finding a solution!

I remember seeing that SystemCoreClockUpdate() calls when figuring out how to get the bare CH32V003 to operate at 48MHz. In that case the call was triggered by setting the proper clock speed define, which allowed me to add it to the Arduino menu.

With regards to debugging: I updated my IDE 2 environment according PR #68 and successfully tested debugging the CH32V003. It really works well, even though including the symbols and disabling optimizations takes a valuable part of the limited flash size. (I also had to use a different PC to run the latest IDE, since my regular laptop with IDE 1.8.19 doesn't support debugging).

Khalinda commented 5 months ago

Thanks maxint-rd. I'm not very Git savvy, expecially when it comes to pull requests. After I figured that out and after a couple of hours of fighting with the Arduino IDE, I was finally able to enable debugging. It took another couple of hours to get to the point of single stepping through a Blink sketch running on a CH32V003 chip. I am reminded why I don't use the V2 IDE.

I mostly can't get the IDE to even download a program to the CH32V103 chip. I'm not sure what the problem is. Maybe I'll try a different WCH-LinkE.