openwch / arduino_core_ch32

Core library for CH32duino
261 stars 45 forks source link

Clock selection using Arduino IDE menu #27

Closed maxint-rd closed 4 months ago

maxint-rd commented 1 year ago

While testing this Arduino core on my CH32V003, I found that using a bare CH32V003 TSSOP20 chip without external crystal requires a change of clock selection in system_ch32v00x.c. Not having the correct clock selected resulted in incorrect timing of millis() and micros(). In my test using the timestamp feature of the IDE, I saw that 500ms actually took a second, which illustrated that the default fallback clock is the 24MHz internal oscillator. Having the internal clock as automatic fallback is a nice feature, but having an IDE user changing core code should be avoided.

To make clock selection easier I modified the files boards.txt, platform.txt and system_ch32v00x.c. I now can select the clock using the menu of the Arduino IDE. I don't have other type of chips for testing, but perhaps you may want to make a similar change.


Changes made:

/packages/WCH/hardware/ch32/1.0.3/system/CH32V00x/USER/system_ch32v00x.c : => all clock related defines commented out

/packages/WCH/hardware/ch32/1.0.3/boards.txt :

# added Clock selection to menu
menu.clock=Clock

# added flags for Clock selection
CH32V00x_EVT.menu.clock.48MHzE=48 MHz External
CH32V00x_EVT.menu.clock.48MHzE.build.flags.clock=-DSYSCLK_FREQ_48MHz_HSE=48000000
CH32V00x_EVT.menu.clock.24MHzE=24 MHz External
CH32V00x_EVT.menu.clock.24MHzE.build.flags.clock=-DSYSCLK_FREQ_24MHz_HSE=HSE_VALUE
CH32V00x_EVT.menu.clock.8MHzE=8 MHz External
CH32V00x_EVT.menu.clock.8MHzE.build.flags.clock=-DSYSCLK_FREQ_8MHz_HSE=8000000
CH32V00x_EVT.menu.clock.48MHz=48 MHz Internal
CH32V00x_EVT.menu.clock.48MHz.build.flags.clock=-DSYSCLK_FREQ_48MHZ_HSI=48000000
CH32V00x_EVT.menu.clock.24MHz=24 MHz Internal
CH32V00x_EVT.menu.clock.24MHz.build.flags.clock=-DSYSCLK_FREQ_24MHZ_HSI=HSI_VALUE
CH32V00x_EVT.menu.clock.8MHz=8 MHz Internal
CH32V00x_EVT.menu.clock.8MHz.build.flags.clock=-DSYSCLK_FREQ_8MHz_HSI=8000000

/packages/WCH/hardware/ch32/1.0.3/platform.txt "

# added Clock flag to various compiler flags
compiler.S.flags={build.flags.clock} {compiler.extra_flags} -x assembler-with-cpp "-I{build.system.path}/{build.series}/SRC/Startup/" "-I{build.core.path}/ch32/"

compiler.c.flags={build.flags.clock} {compiler.extra_flags} -c {build.flags.optimize} {build.flags.debug} {compiler.warning_flags} -std=gnu99 -MMD {compiler.ch.extra_include}

compiler.cpp.flags={build.flags.clock} {compiler.extra_flags} -c {build.flags.optimize} {build.flags.debug} {compiler.warning_flags} -std={compiler.cpp.std}  -fno-threadsafe-statics  -fno-rtti -fno-exceptions -fno-use-cxa-atexit -MMD {compiler.ch.extra_include} -fpermissive
0x0fe commented 10 months ago

yes that is very much needed if working with HSI. @TianpeiLee

TianpeiLee commented 4 months ago

While testing this Arduino core on my CH32V003, I found that using a bare CH32V003 TSSOP20 chip without external crystal requires a change of clock selection in system_ch32v00x.c. Not having the correct clock selected resulted in incorrect timing of millis() and micros(). In my test using the timestamp feature of the IDE, I saw that 500ms actually took a second, which illustrated that the default fallback clock is the 24MHz internal oscillator. Having the internal clock as automatic fallback is a nice feature, but having an IDE user changing core code should be avoided.

To make clock selection easier I modified the files boards.txt, platform.txt and system_ch32v00x.c. I now can select the clock using the menu of the Arduino IDE. I don't have other type of chips for testing, but perhaps you may want to make a similar change.

Changes made:

/packages/WCH/hardware/ch32/1.0.3/system/CH32V00x/USER/system_ch32v00x.c : => all clock related defines commented out

/packages/WCH/hardware/ch32/1.0.3/boards.txt :

# added Clock selection to menu
menu.clock=Clock

# added flags for Clock selection
CH32V00x_EVT.menu.clock.48MHzE=48 MHz External
CH32V00x_EVT.menu.clock.48MHzE.build.flags.clock=-DSYSCLK_FREQ_48MHz_HSE=48000000
CH32V00x_EVT.menu.clock.24MHzE=24 MHz External
CH32V00x_EVT.menu.clock.24MHzE.build.flags.clock=-DSYSCLK_FREQ_24MHz_HSE=HSE_VALUE
CH32V00x_EVT.menu.clock.8MHzE=8 MHz External
CH32V00x_EVT.menu.clock.8MHzE.build.flags.clock=-DSYSCLK_FREQ_8MHz_HSE=8000000
CH32V00x_EVT.menu.clock.48MHz=48 MHz Internal
CH32V00x_EVT.menu.clock.48MHz.build.flags.clock=-DSYSCLK_FREQ_48MHZ_HSI=48000000
CH32V00x_EVT.menu.clock.24MHz=24 MHz Internal
CH32V00x_EVT.menu.clock.24MHz.build.flags.clock=-DSYSCLK_FREQ_24MHZ_HSI=HSI_VALUE
CH32V00x_EVT.menu.clock.8MHz=8 MHz Internal
CH32V00x_EVT.menu.clock.8MHz.build.flags.clock=-DSYSCLK_FREQ_8MHz_HSI=8000000

/packages/WCH/hardware/ch32/1.0.3/platform.txt "

# added Clock flag to various compiler flags
compiler.S.flags={build.flags.clock} {compiler.extra_flags} -x assembler-with-cpp "-I{build.system.path}/{build.series}/SRC/Startup/" "-I{build.core.path}/ch32/"

compiler.c.flags={build.flags.clock} {compiler.extra_flags} -c {build.flags.optimize} {build.flags.debug} {compiler.warning_flags} -std=gnu99 -MMD {compiler.ch.extra_include}

compiler.cpp.flags={build.flags.clock} {compiler.extra_flags} -c {build.flags.optimize} {build.flags.debug} {compiler.warning_flags} -std={compiler.cpp.std}  -fno-threadsafe-statics  -fno-rtti -fno-exceptions -fno-use-cxa-atexit -MMD {compiler.ch.extra_include} -fpermissive

@maxint-rd Thank you for your contribution. I am trying to verify your solution and would like to port it to another chip. I am not sure what problem has occurred here. After modifying board.txt and platform.txt, regardless of which clock is selected in the IDE, the result of running is using internal HSI. However, from the compiled log, it does appear that build.flags.clock has already taken effect when generating core. a. So, I would like to know if there is indeed no problem on your end? image image

maxint-rd commented 4 months ago

@TianpeiLee : Thank you for addressing this issue. There is also PR #66 by another user that addresses the same issue.

To answer your question: as mentioned in my initial post, the system file that defines the clock setting also needed to be changed. For CH32V003 this is: /packages/WCH/hardware/ch32/1.0.3/system/CH32V00x/USER/system_ch32v00x.c

In my local version I commented out all clock related defines. As a global solution it may be better to use some #ifdef 's. For my CH32V003 this worked just fine. Unfortunately I don't have any other member of the CH32 family to check this out. While debugging the V003 behavior I did notice the code to follow to interesting steps. Perhaps these are different for other CH32 MCU's.

Finally: I read in another post that your contributions are all done in your spare time. I really appreciate your commitment to maintain this core. Thank you! I also regret that WCH is not dedicating a budget to support this Arduino core. Maybe WCH doesn't see the commercial gain of helping thousands of developers use this very nice CH32 family of chips. For me having such an affordable processor allowed me to do experiments on using it in project that I normally would not dare to do.

TianpeiLee commented 4 months ago

@maxint-rd Thank you for your reply,before testing, I had already commented out the relevant definitions in system_ch32v00x.c, but I still cannot implement clock switching function

maxint-rd commented 4 months ago

Hmmm... does it work for you on the CH32V003, but not for the others? If it also doesn't work for the V003 I suggest you to test PR #66 Unfortunately I don't have any other CH32 family members to test.

P.S. Thank you so much for maintaining this core. I really like using the CH32V003 and perhaps will also try some other family members. If you're interested I can also submit PR's for some other core improvements that I only tested for the V003. In my fork of this core you can find branches to implement I2C slave support, an EEPROM emulation library and some other things.

TianpeiLee commented 4 months ago

I tested it on 003 and found that it is only effective for 24M and 8M. Observing the registers, I found that the values of the registers were not set correctly when selecting 48M. I think it should be a hidden small issue , although I haven't found it yet.

I am very happy for you to submit a PR's for this repository to improve it, that's really great!

I am planning to add the CH32V006 series, which is more like an enhanced 003 and supports hardware multiplication(RV32EC_Zmmul_xw extension). _https://www.wch-ic.com/downloads/CH32V006DS0_PDF.html_ image I think many people will be interested in it. Currently, the toolchain on the official website does not support it. I am currently adding some basic peripheral library files and compiling it in the 003 compilation environment.

maxint-rd commented 4 months ago

Okay, I looked again at your screenshot. Maybe your problem is something small indeed. The person that submitted PR #66 noticed inconsistencies in capitalization and he corrected that too. Note the inconsistent use of capital Z versus lower case z in the MHz/MHZ definition of DSYSCLK_FREQ_48MHZ_HSI and DSYSCLK_FREQ_8MHz_HSI. Since 24MHz is the default clock I suspect your 48MHz selection isn't propagated properly. Can you look at that?

BTW. That V006 is certainly ingeresting. In my latest projects the main limitation of the V003 was use of flash memory. The 16MB got full quickly, often requiring me to disable features, or not be able to debug. I also noted that the LTO had issues, making flash more limiting (see my comment in issue #51 ):

Latest hold-up was that somehow my I2C configuration application doesn't start when using -Os with LTO (Link Time Optimization), which is weird. It did work in Arduino IDE 1.8.19 with an older core, but in IDE v2.3.2 with core 1.4 it only works without LTO. Still need to test more variations and another sketch to see if my changes caused this.

Edit: even the simple basic Blink example doesn't run with LTO, not for smallest (-Os) nor fastest (-O3). Without LTO these same options run fine. Weird!

Does anyone else have issues with LTO?

TianpeiLee commented 4 months ago

Oh, thank you very much. Yes, I noticed the issue with the capitalization of that letter, and now everything is normal. I am updating it to another chip.

The "LTO" option in gcc seems to overly optimize the code under risc-v, causing program exceptions. Currently, this issue has not been resolved. If the Arduino IDE can generate a list file, it may be easier to find problems from assembly code.

TianpeiLee commented 4 months ago

It will be enabled in the next update