diff --git a/boards.txt b/boards.txt index 32fbe00a..2b1fe88f 100644 --- a/boards.txt +++ b/boards.txt @@ -2,6 +2,15 @@ menu.pnum=Board Select menu.clock=Clock Select + +#menu.peripherals=peripherals +menu.periADC=ADC Module +menu.periUART=UART Module +menu.periSPI=SPI Module +menu.periI2C=I2C Module +menu.periI2Cslave=I2C Slave Option +menu.periTimer=Hardware Timer + menu.xserial=U(S)ART support menu.usb=USB support (if available) menu.xusb=USB speed (if available) @@ -14,8 +23,8 @@ menu.upload_method=Upload method -############################################################################## -##CH32V00x_EVT Board +############################################################################# +##CH32V00x EVT Board CH32V00x_EVT.name=CH32V00x CH32V00x_EVT.build.core=arduino @@ -38,7 +47,7 @@ CH32V00x_EVT.menu.pnum.CH32V003F4.build.variant=CH32V00x/CH32V003F4 CH32V00x_EVT.menu.pnum.CH32V003F4.build.chip=CH32V003F4 CH32V00x_EVT.menu.pnum.CH32V003F4.build.march=rv32ecxw CH32V00x_EVT.menu.pnum.CH32V003F4.build.mabi=ilp32e -CH32V00x_EVT.menu.pnum.CH32V003F4.build.math_lib_gcc=-lm +CH32V00x_EVT.menu.pnum.CH32V003F4.build.math_lib_gcc=-lm CH32V00x_EVT.menu.pnum.CH32V003F4.build.IQ_math_RV32= CH32V00x_EVT.menu.pnum.CH32V003F4.build.ch_extra_lib=-lprintf @@ -53,6 +62,31 @@ CH32V00x_EVT.menu.upload_method.ispMethod.upload.protocol= CH32V00x_EVT.menu.upload_method.ispMethod.upload.options= CH32V00x_EVT.menu.upload_method.ispMethod.upload.tool=wchisp +# Peripherals Options +CH32V00x_EVT.menu.periADC.disable=disabled (default) +CH32V00x_EVT.menu.periADC.disable.build.periADC= +CH32V00x_EVT.menu.periADC.enable=enabled +CH32V00x_EVT.menu.periADC.enable.build.periADC=-DADC_MODULE_ENABLED +CH32V00x_EVT.menu.periUART.disable=disabled (default) +CH32V00x_EVT.menu.periUART.disable.build.periUART= +CH32V00x_EVT.menu.periUART.enable=enabled +CH32V00x_EVT.menu.periUART.enable.build.periUART=-DUART_MODULE_ENABLED +CH32V00x_EVT.menu.periSPI.disable=disabled (default) +CH32V00x_EVT.menu.periSPI.disable.build.periSPI= +CH32V00x_EVT.menu.periSPI.enable=enabled +CH32V00x_EVT.menu.periSPI.enable.build.periSPI=-DSPI_MODULE_ENABLED +CH32V00x_EVT.menu.periI2C.disable=disabled (default) +CH32V00x_EVT.menu.periI2C.disable.build.periI2C= +CH32V00x_EVT.menu.periI2C.enable=enabled +CH32V00x_EVT.menu.periI2C.enable.build.periI2C=-DI2C_MODULE_ENABLED +CH32V00x_EVT.menu.periI2Cslave.disable=disabled (default) +CH32V00x_EVT.menu.periI2Cslave.disable.build.periI2Cslave=-DOPT_I2C_SLAVE=0 +CH32V00x_EVT.menu.periI2Cslave.enable=enabled +CH32V00x_EVT.menu.periI2Cslave.enable.build.periI2Cslave=-DOPT_I2C_SLAVE=1 +CH32V00x_EVT.menu.periTimer.disable=disabled (default) +CH32V00x_EVT.menu.periTimer.disable.build.periTimer= +CH32V00x_EVT.menu.periTimer.enable=enabled +CH32V00x_EVT.menu.periTimer.enable.build.periTimer=-DTIM_MODULE_ENABLED # Clock Select CH32V00x_EVT.menu.clock.48MHz_HSI=48MHz Internal @@ -130,6 +164,23 @@ CH32VM00X_EVT.build.variant_h=variant_{build.board}.h CH32VM00X_EVT.debug.tool=gdb-WCH_LinkE +#CH32V002F4 EVT Board +CH32VM00X_EVT.menu.pnum.CH32V002F4=CH32V002F4 EVT +CH32VM00X_EVT.menu.pnum.CH32V002F4.node=NODE_V002F4 +CH32VM00X_EVT.menu.pnum.CH32V002F4.upload.maximum_size=16384 +CH32VM00X_EVT.menu.pnum.CH32V002F4.upload.maximum_data_size=4096 +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.mcu=QingKe-V2C +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.board=CH32V002F4 +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.series=CH32VM00X +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.variant=CH32VM00X/CH32V002F4 +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.chip=CH32V002F4 +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.march=rv32ecxw +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.mabi=ilp32e +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.math_lib_gcc=-lm +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.IQ_math_RV32= +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.ch_extra_lib=-lprintf +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.ldscript=LinkV002.ld + #CH32V006K8 EVT Board CH32VM00X_EVT.menu.pnum.CH32V006K8=CH32V006K8 EVT CH32VM00X_EVT.menu.pnum.CH32V006K8.node=NODE_V006K8 @@ -145,7 +196,24 @@ CH32VM00X_EVT.menu.pnum.CH32V006K8.build.mabi=ilp32e CH32VM00X_EVT.menu.pnum.CH32V006K8.build.math_lib_gcc=-lm CH32VM00X_EVT.menu.pnum.CH32V006K8.build.IQ_math_RV32= CH32VM00X_EVT.menu.pnum.CH32V006K8.build.ch_extra_lib=-lprintf - +CH32VM00X_EVT.menu.pnum.CH32V006K8.build.ldscript=Link.ld + +#CH32V006F8 EVT Board +CH32VM00X_EVT.menu.pnum.CH32V006F8=CH32V006F8 EVT +CH32VM00X_EVT.menu.pnum.CH32V006F8.node=NODE_V006F8 +CH32VM00X_EVT.menu.pnum.CH32V006F8.upload.maximum_size=63488 +CH32VM00X_EVT.menu.pnum.CH32V006F8.upload.maximum_data_size=8192 +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.mcu=QingKe-V2C +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.board=CH32V006F8 +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.series=CH32VM00X +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.variant=CH32VM00X/CH32V006F8 +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.chip=CH32V006F8 +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.march=rv32ecxw +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.mabi=ilp32e +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.math_lib_gcc=-lm +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.IQ_math_RV32= +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.ch_extra_lib=-lprintf +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.ldscript=Link.ld # Upload menu CH32VM00X_EVT.menu.upload_method.swdMethod=WCH-SWD @@ -158,6 +226,34 @@ CH32VM00X_EVT.menu.upload_method.ispMethod.upload.options= CH32VM00X_EVT.menu.upload_method.ispMethod.upload.tool=wchisp +# Peripherals Options +CH32VM00X_EVT.menu.periADC.disable=disabled (default) +CH32VM00X_EVT.menu.periADC.disable.build.periADC= +CH32VM00X_EVT.menu.periADC.enable=enabled +CH32VM00X_EVT.menu.periADC.enable.build.periADC=-DADC_MODULE_ENABLED +CH32VM00X_EVT.menu.periUART.disable=disabled (default) +CH32VM00X_EVT.menu.periUART.disable.build.periUART= +CH32VM00X_EVT.menu.periUART.enable=enabled +CH32VM00X_EVT.menu.periUART.enable.build.periUART=-DUART_MODULE_ENABLED +CH32VM00X_EVT.menu.periSPI.disable=disabled (default) +CH32VM00X_EVT.menu.periSPI.disable.build.periSPI= +CH32VM00X_EVT.menu.periSPI.enable=enabled +CH32VM00X_EVT.menu.periSPI.enable.build.periSPI=-DSPI_MODULE_ENABLED +CH32VM00X_EVT.menu.periI2C.disable=disabled (default) +CH32VM00X_EVT.menu.periI2C.disable.build.periI2C= +CH32VM00X_EVT.menu.periI2C.enable=enabled +CH32VM00X_EVT.menu.periI2C.enable.build.periI2C=-DI2C_MODULE_ENABLED +CH32VM00X_EVT.menu.periI2Cslave.disable=disabled (default) +CH32VM00X_EVT.menu.periI2Cslave.disable.build.periI2Cslave=-DOPT_I2C_SLAVE=0 +CH32VM00X_EVT.menu.periI2Cslave.enable=enabled +CH32VM00X_EVT.menu.periI2Cslave.enable.build.periI2Cslave=-DOPT_I2C_SLAVE=1 +CH32VM00X_EVT.menu.periTimer.disable=disabled (default) +CH32VM00X_EVT.menu.periTimer.disable.build.periTimer= +CH32VM00X_EVT.menu.periTimer.enable=enabled +CH32VM00X_EVT.menu.periTimer.enable.build.periTimer=-DTIM_MODULE_ENABLED + + + # Clock Select CH32VM00X_EVT.menu.clock.48MHz_HSI=48MHz Internal CH32VM00X_EVT.menu.clock.48MHz_HSI.build.flags.clock=-DSYSCLK_FREQ_48MHz_HSI=48000000 -DF_CPU=48000000 @@ -250,6 +346,22 @@ CH32X035_EVT.menu.pnum.CH32X035G8U.build.math_lib_gcc=-lm CH32X035_EVT.menu.pnum.CH32X035G8U.build.IQ_math_RV32= CH32X035_EVT.menu.pnum.CH32X035G8U.build.ch_extra_lib=-lprintf +#CH32X033F8P EVT Board +CH32X035_EVT.menu.pnum.CH32X033F8P=CH32X033F8P EVT +CH32X035_EVT.menu.pnum.CH32X033F8P.node=NODE_X033F8P +CH32X035_EVT.menu.pnum.CH32X033F8P.upload.maximum_size=63488 +CH32X035_EVT.menu.pnum.CH32X033F8P.upload.maximum_data_size=20480 +CH32X035_EVT.menu.pnum.CH32X033F8P.build.mcu=QingKe-V4C +CH32X035_EVT.menu.pnum.CH32X033F8P.build.board=CH32X033F8P +CH32X035_EVT.menu.pnum.CH32X033F8P.build.series=CH32X035 +CH32X035_EVT.menu.pnum.CH32X033F8P.build.variant=CH32X035/CH32X033F8P +CH32X035_EVT.menu.pnum.CH32X033F8P.build.chip=CH32X033F8P +CH32X035_EVT.menu.pnum.CH32X033F8P.build.march=rv32imacxw +CH32X035_EVT.menu.pnum.CH32X033F8P.build.mabi=ilp32 +CH32X035_EVT.menu.pnum.CH32X033F8P.build.math_lib_gcc=-lm +CH32X035_EVT.menu.pnum.CH32X033F8P.build.IQ_math_RV32= +CH32X035_EVT.menu.pnum.CH32X033F8P.build.ch_extra_lib=-lprintf + # Upload menu CH32X035_EVT.menu.upload_method.swdMethod=WCH-SWD @@ -261,6 +373,32 @@ CH32X035_EVT.menu.upload_method.ispMethod.upload.protocol= CH32X035_EVT.menu.upload_method.ispMethod.upload.options= CH32X035_EVT.menu.upload_method.ispMethod.upload.tool=wchisp +# Peripherals Options +CH32X035_EVT.menu.periADC.disable=disabled (default) +CH32X035_EVT.menu.periADC.disable.build.periADC= +CH32X035_EVT.menu.periADC.enable=enabled +CH32X035_EVT.menu.periADC.enable.build.periADC=-DADC_MODULE_ENABLED +CH32X035_EVT.menu.periUART.disable=disabled (default) +CH32X035_EVT.menu.periUART.disable.build.periUART= +CH32X035_EVT.menu.periUART.enable=enabled +CH32X035_EVT.menu.periUART.enable.build.periUART=-DUART_MODULE_ENABLED +CH32X035_EVT.menu.periSPI.disable=disabled (default) +CH32X035_EVT.menu.periSPI.disable.build.periSPI= +CH32X035_EVT.menu.periSPI.enable=enabled +CH32X035_EVT.menu.periSPI.enable.build.periSPI=-DSPI_MODULE_ENABLED +CH32X035_EVT.menu.periI2C.disable=disabled (default) +CH32X035_EVT.menu.periI2C.disable.build.periI2C= +CH32X035_EVT.menu.periI2C.enable=enabled +CH32X035_EVT.menu.periI2C.enable.build.periI2C=-DI2C_MODULE_ENABLED +CH32X035_EVT.menu.periI2Cslave.disable=disabled (default) +CH32X035_EVT.menu.periI2Cslave.disable.build.periI2Cslave=-DOPT_I2C_SLAVE=0 +CH32X035_EVT.menu.periI2Cslave.enable=enabled +CH32X035_EVT.menu.periI2Cslave.enable.build.periI2Cslave=-DOPT_I2C_SLAVE=1 +CH32X035_EVT.menu.periTimer.disable=disabled (default) +CH32X035_EVT.menu.periTimer.disable.build.periTimer= +CH32X035_EVT.menu.periTimer.enable=enabled +CH32X035_EVT.menu.periTimer.enable.build.periTimer=-DTIM_MODULE_ENABLED + # Clock Select CH32X035_EVT.menu.clock.48MHz_HSI=48MHz Internal diff --git a/cores/arduino/ch32/clock.c b/cores/arduino/ch32/clock.c index 61e4452d..6b3829b2 100644 --- a/cores/arduino/ch32/clock.c +++ b/cores/arduino/ch32/clock.c @@ -53,7 +53,25 @@ uint32_t getCurrentMillis(void) uint32_t getCurrentMicros(void) { - +#if defined(CH32VM00X) || defined(CH32V00x) + // MMOLE 250708: a uint64_t division causes need for __udivdi3, which is quite large (more than 1KB) + // SysTick->CMP and CNT are 32-bit values, let's try to avoid 64 bit divisions to minimize Flash usage + // (This might cause smaller roll-over, but who cares...) + // NOTE: 64 bit divisions are also used by delayMicroseconds() in wiring_time.h + uint32_t m0 = GetTick(); + __IO uint32_t u0 = SysTick->CNT; + uint32_t m1 = GetTick(); + __IO uint32_t u1 = SysTick->CNT; //may be a interruption + uint32_t tms = SysTick->CMP + 1; + + if (m1 != m0) { + //return (m1 * 1000 + ((tms - u1) * 1000) / tms); + return m1 * 1000 + u1 * 1000 / tms; // fix issue #65 + } else { + //return (m0 * 1000 + ((tms - u0) * 1000) / tms); + return m0 * 1000 + u0 * 1000 / tms; // fix issue #65 + } +#else uint64_t m0 = GetTick(); __IO uint64_t u0 = SysTick->CNT; uint64_t m1 = GetTick(); @@ -61,10 +79,13 @@ uint32_t getCurrentMicros(void) uint64_t tms = SysTick->CMP + 1; if (m1 != m0) { - return (m1 * 1000 + ((tms - u1) * 1000) / tms); + //return (m1 * 1000 + ((tms - u1) * 1000) / tms); + return m1 * 1000 + u1 * 1000 / tms; // fix issue #65 } else { - return (m0 * 1000 + ((tms - u0) * 1000) / tms); + //return (m0 * 1000 + ((tms - u0) * 1000) / tms); + return m0 * 1000 + u0 * 1000 / tms; // fix issue #65 } +#endif } @@ -112,9 +133,11 @@ uint32_t getCurrentMicros(void) tms = (tms << 32) + *((__IO uint32_t *)SYSTICK_CMPL) + 1; if (m1 != m0) { - return (m1 * 1000 + ((tms - u1) * 1000) / tms); + //return (m1 * 1000 + ((tms - u1) * 1000) / tms); + return m1 * 1000 + u1 * 1000 / tms; // fix issue #65 } else { - return (m0 * 1000 + ((tms - u0) * 1000) / tms); + //return (m0 * 1000 + ((tms - u0) * 1000) / tms); + return m0 * 1000 + u0 * 1000 / tms; // fix issue #65 } } diff --git a/cores/arduino/wiring_time.h b/cores/arduino/wiring_time.h index a7487679..142169c1 100644 --- a/cores/arduino/wiring_time.h +++ b/cores/arduino/wiring_time.h @@ -65,6 +65,31 @@ extern void delay(uint32_t ms) ; static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused)); static inline void delayMicroseconds(uint32_t us) { +#if defined(CH32VM00X) || defined(CH32V00x) + // MMOLE 250708: a uint64_t division causes need for __udivdi3, which is quite large (more than 1KB) + // SysTick->CMP and CNT are 32-bit values, let's try to avoid 64 bit divisions to minimize Flash usage + // (This might cause smaller roll-over, but who cares...) + // NOTE: 64 bit divisions are also used by micros() in clock.c + __IO uint32_t currentTicks = SysTick->CNT; + /* Number of ticks per millisecond */ + uint32_t tickPerMs = SysTick->CMP + 1; + /* Number of ticks to count */ + uint32_t nbTicks = ((us - ((us > 0) ? 1 : 0)) * tickPerMs) / 1000; + /* Number of elapsed ticks */ + uint32_t elapsedTicks = 0; + __IO uint32_t oldTicks = currentTicks; + do { + currentTicks = SysTick->CNT; + // elapsedTicks += (oldTicks < currentTicks) ? tickPerMs + oldTicks - currentTicks : + // oldTicks - currentTicks; + + //increment + elapsedTicks += (oldTicks <= currentTicks) ? currentTicks - oldTicks : + tickPerMs - oldTicks + currentTicks; + + oldTicks = currentTicks; + } while (nbTicks > elapsedTicks); +#else __IO uint64_t currentTicks = SysTick->CNT; /* Number of ticks per millisecond */ uint64_t tickPerMs = SysTick->CMP + 1; @@ -83,7 +108,8 @@ static inline void delayMicroseconds(uint32_t us) tickPerMs - oldTicks + currentTicks; oldTicks = currentTicks; - } while (nbTicks > elapsedTicks); + } while (nbTicks > elapsedTicks); +#endif } #else #define SYSTICK_CNTL (0xE000F004) diff --git a/libraries/EEPROM/README.md b/libraries/EEPROM/README.md index f09aabbe..ef4999cd 100644 --- a/libraries/EEPROM/README.md +++ b/libraries/EEPROM/README.md @@ -6,12 +6,13 @@ The EEPROM library provides an easy to use interface to interact with the intern This CH32 version of the library provides a familiar API to emulated EEPROM using the Option bytes area in flash memory. Ported to CH32 by Maxint R&D, based on multiple sources: -- Code from the Option Data example of CH32V003fun by @CNLOHR. +- Code from the Option Data example of CH32V003fun by @CNLOHR and various WCH EVT Flash examples. - Arduino original copyright (c) 2006 David A. Mellis. All right reserved. New version by Christopher Andrews 2015. - ESP8266 version copyright (c) 2014 Ivan Grokhotkov. All rights reserved. ## Table of contents - [CH32V003 emulated EEPROM](#ch32v003-emulated-eeprom) +- [CH32 boards with larger emulated EEPROM](#ch32-boards-with-larger-emulated-eeprom) - [How to use this library](#how-to-use-this-library) - [Library functions](#library-functions) - [Features & limitations](#features--limitations) @@ -41,6 +42,17 @@ Layout for uint8_t _data[26]: { ob[4], ob[6], ob[16...62] ]. The first release of this library was made for the CH32V003 and only uses the user select word storage area. It was tested using Arduino IDE 2.3.2 and OpenWCH core 1.0.4. + +### CH32 boards with larger emulated EEPROM +Depending on the board, the size of the user-defined information storage area can be different, allowing for a larger emulated EEPROM. +For all CH32 chips the starting address is 0x1FFFF800. The first 16 bytes is for configuration, including 4 bytes for data0/data1. +The remainder can be used for EEPROM values and their inverse. The method to write these bytes can be different per chip. + - 64B => 2+(64-16)/2=2+24=26B: CH32V003 + - 128B => 2+(128-16)/2=2+56=58B: CH32V103, CH32V20x, CH32V30x/31x + - 256B => 2+(256-16)/2=2+120=122B: CH32V002/V004/V006/V007, CH32X033/X035 + +Currently tested to work: CH32V003/CH32V002/CH32V006/CH32X033. +(CH32VM00X required updated ch32v00x_flash.c from latest EVT code) Future releases of this library may support other CH32 processors and allow for larger memory sizes. ### **How to use this library** @@ -150,8 +162,9 @@ The method returns a `uint32_t` value, containing the data0 and data1 bytes and --- ## Features & limitations -- The first release of this library was made only for the CH32V003 and has been tested on that MCU only. Other members of the CH32 may behave incorrectly or not work at all. -- This EEPROM implementation for the CH32V003 has only 26 bytes available. When addressing more, things are likely to go wrong. A future release may allow using more pages from the flash memory. +- The first release of this library was made for the CH32V003, offering 26 bytes of emulated EEPROM. It was tested on CH32V003 and CH32X033. +. The next release offered 122 bytes of emulated EEPROM on CH32X035/X033 and CH32VM00X (V002/V004/V006/V008). It passed tests on V002, V006 and X033. +- Other members of the CH32 may behave incorrectly or not work at all. A test on V103 showed issues writing more than the first two bytes. - Most CH32 EEPROM methods are the same as their equivalent on regular Arduino's. BEWARE: The begin() and end() methods are like their counterparts for ESP8266/ESP32, but are very different from the begin() and end() methods of EEPROM v2.0 by Christopher Andrews, who introduced them to support C++ iterators. This library follows the begin() convention introduced by the Serial and Wire classes, i.e. to initialize the object. ## Disclaimer diff --git a/libraries/EEPROM/library.properties b/libraries/EEPROM/library.properties index 661bbb84..c49c30ad 100644 --- a/libraries/EEPROM/library.properties +++ b/libraries/EEPROM/library.properties @@ -1,5 +1,5 @@ name=EEPROM -version=1.0.0 +version=1.0.2507 author=Maxint maintainer=https://github.com/maxint-rd sentence=Enables reading and writing to non-volatile storage in the processor. diff --git a/libraries/EEPROM/src/EEPROM.cpp b/libraries/EEPROM/src/EEPROM.cpp index 53f6c9b9..37ff678b 100644 --- a/libraries/EEPROM/src/EEPROM.cpp +++ b/libraries/EEPROM/src/EEPROM.cpp @@ -18,10 +18,44 @@ These 8 bytes use 16 bytes of flash. The total storage area page is 64 bytes, leaving 48 bytes available, (including required inverse values). This is 24 bytes that can be used plus the two data0 and data1 bytes. Layout for uint8_t _data[26]: { ob[4], ob[6], ob[16...62] ]. + + + From the CH32X035 Data Sheet: + "Built-in 3328 bytes system storage area (System FLASH), i.e. BOOT area, for system boot program storage, builtin + bootstrap loading program. 256-byte system non-volatile configuration information storage area, used for vendor configuration word storage, + factory-cured, user cannot be modified. 256-byte user-defined information storage area for user-selected word storage." + So next to 62kB of Code FLASH, the chip features 3kB Flash for boot, configuration and storage. That 256-byte + user-selected word storage area is the area we can use to emulate on chip EEPROM memory. + + The size of the user-defined information storage area can be different, allowing for a larger emulated EEPROM. + For all CH32 chips the starting address is 0x1FFFF800. The first 16 bytes is for configuration + 4-bytes for data0/data1. + The remainder can be used for EEPROM values and their inverse. The method to write these bytes can be different per chip. + 64B => 2+(64-16)/2=2+24=26B: CH32V003 + 128B => 2+(128-16)/2=2+56=58B: CH32V103, CH32V20x, CH32V30x/31x + 256B => 2+(256-16)/2=2+120=122B: CH32V002/V004/V006/V007, CH32X033/X035 + Currently tested to work: CH32V003/CH32V002/CH32V006/CH32X033 + (CH32VM00X required updated ch32v00x_flash.c from latest EVT code) + + TODO: Allow larger EEPROM for CH32V10x/V20x/V30x/V31x. Note: User option bytes storage area is 128B + + Note: for some board the current Arduino core may have incorrect latency set + V00X RM page 242 suggests this: + FLASH_ACTLR [1:0] LATENCY[1:0] RW, reset value is 0 => 0 wait state + FLASH wait status number. + 00: 0 wait (Recommended 0<=SYSCLK<=15MHz); + 01: 1 wait (Recommended 15 -#define OB_AVAIL_DATA_START 8 // valid for CH32V003; how about others? +#define OB_AVAIL_DATA_START 8 // valid for CH32V003; how about others? (same for X03x, V20x, V30x, V31x) EEPROMClass::EEPROMClass(void) { } @@ -44,7 +78,11 @@ uint32_t EEPROMClass::ReadOptionBytes() void EEPROMClass::begin(void) { +#if defined(CH32VM00X) || defined(CH32X035) + _size = 122; // Option bytes available on CH32V002/V006, CH32X035/X033: 256- 16 = 240; 240/2=120, 2+120=122 +#else _size = 26; // Option bytes available on CH32V003: 64 - 16 = 48; 48/2=24, 2+24=26 +#endif // Allocate data buffer and copy the current content from storage if(!_data) @@ -141,6 +179,21 @@ bool EEPROMClass::commit() // Note that when a byte is written as a word, it automatically gets its inverse value as second byte if(_data && _size) { +#if defined(CH32VM00X) || defined(CH32X035) + // To write to the larger 256B option byte area of V00X, we use fast page programming as shown by EVT EXAM code + // (see FLASH_OptionBytePR() in /EVT/EXAM/SRC/Peripheral/src/ch32v00X_flash.c) + // Tested OK for V002/V006. X035 seems similar, but first needs testing + FLASH_Unlock_Fast(); + FLASH_BufReset(); + for (int i=2;i<_size; i++) { + uint32_t val; + val=_data[i+1]<<16 | _data[i]; + FLASH_BufLoad((OB_BASE + (OB_AVAIL_DATA_START + (i-2))*2), val); + i++; + } + FLASH_ProgramPage_Fast(OB_BASE); + FLASH_Lock_Fast(); +#else uint16_t *ob16p=(uint16_t *)OB_BASE; for (int i=2;i<_size; i++) { if(_data[i]!=0xFF) { @@ -148,8 +201,9 @@ bool EEPROMClass::commit() while (FLASH->STATR & FLASH_BUSY); // Wait for flash operation to be done } } +#endif } - + FLASH->CTLR &= CR_OPTPG_Reset; // Disable programming mode FLASH->CTLR|=CR_LOCK_Set; // Lock flash memories again return(true); diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index a0b554a7..b3c46bb8 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -239,7 +239,7 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb) // Enable SPI clock if (handle->Instance == SPI1) { - #if defined(CH32L10x) + #if defined(CH32L10x) || defined(CH32VM00X) RCC_PB2PeriphResetCmd(RCC_PB2Periph_SPI1, ENABLE); RCC_PB2PeriphResetCmd(RCC_PB2Periph_SPI1, DISABLE); RCC_PB2PeriphClockCmd(RCC_PB2Periph_SPI1, ENABLE ); @@ -254,7 +254,7 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb) #if defined SPI2_BASE if (handle->Instance == SPI2) { - #if defined(CH32L10x) + #if defined(CH32L10x) || defined(CH32VM00X) RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI2, ENABLE); RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI2, DISABLE); RCC_PB1PeriphClockCmd(RCC_PB1Periph_SPI2, ENABLE ); @@ -269,7 +269,7 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb) #if defined SPI3_BASE if (handle->Instance == SPI3) { - #if defined(CH32L10x) + #if defined(CH32L10x) || defined(CH32VM00X) RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI3, ENABLE); RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI3, DISABLE); RCC_PB1PeriphClockCmd(RCC_PB1Periph_SPI3, ENABLE ); @@ -306,7 +306,7 @@ void spi_deinit(spi_t *obj) // Reset SPI and disable clock if (handle->Instance == SPI1) { - #if defined(CH32L10x) + #if defined(CH32L10x) || defined(CH32VM00X) RCC_PB2PeriphResetCmd(RCC_PB2Periph_SPI1, ENABLE); RCC_PB2PeriphResetCmd(RCC_PB2Periph_SPI1, DISABLE); RCC_PB2PeriphClockCmd(RCC_PB2Periph_SPI1, DISABLE); @@ -320,7 +320,7 @@ void spi_deinit(spi_t *obj) #if defined SPI2_BASE if (handle->Instance == SPI2) { - #if defined(CH32L10x) + #if defined(CH32L10x) || defined(CH32VM00X) RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI2, ENABLE); RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI2, DISABLE); RCC_PB1PeriphClockCmd(RCC_PB1Periph_SPI2, DISABLE); @@ -335,7 +335,7 @@ void spi_deinit(spi_t *obj) #if defined SPI3_BASE if (handle->Instance == SPI3) { - #if defined(CH32L10x) + #if defined(CH32L10x) || defined(CH32VM00X) RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI3, ENABLE); RCC_PB1PeriphResetCmd(RCC_PB1Periph_SPI3, DISABLE); RCC_PB1PeriphClockCmd(RCC_PB1Periph_SPI3, DISABLE); diff --git a/libraries/Wire/src/utility/twi.c b/libraries/Wire/src/utility/twi.c index 7b65983f..2948fc4c 100644 --- a/libraries/Wire/src/utility/twi.c +++ b/libraries/Wire/src/utility/twi.c @@ -141,9 +141,15 @@ void i2c_custom_init(i2c_t *obj, uint32_t timing, uint32_t addressingMode, uint3 // Enable I2C1 clock if not done if (obj->i2c == I2C1) { + #if defined(CH32L10x) || defined(CH32VM00X) + RCC_PB1PeriphResetCmd(RCC_PB1Periph_I2C1, ENABLE); + RCC_PB1PeriphResetCmd(RCC_PB1Periph_I2C1, DISABLE); + RCC_PB1PeriphClockCmd(RCC_PB1Periph_I2C1, ENABLE ); + #else RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE ); + #endif obj->irq = I2C1_EV_IRQn; obj->irqER = I2C1_ER_IRQn; @@ -154,9 +160,15 @@ void i2c_custom_init(i2c_t *obj, uint32_t timing, uint32_t addressingMode, uint3 // Enable I2C2 clock if not done if (obj->i2c == I2C2) { + #if defined(CH32L10x) || defined(CH32VM00X) + RCC_PB1PeriphResetCmd(RCC_PB1Periph_I2C2, ENABLE); + RCC_PB1PeriphResetCmd(RCC_PB1Periph_I2C2, DISABLE); + RCC_PB1PeriphClockCmd(RCC_PB1Periph_I2C2, ENABLE ); + #else RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE ); + #endif obj->irq = I2C2_EV_IRQn; obj->irqER = I2C2_ER_IRQn; diff --git a/platform.txt b/platform.txt index 7f32cc3e..5bf5b3cf 100644 --- a/platform.txt +++ b/platform.txt @@ -36,11 +36,14 @@ compiler.libraries.ldflags= compiler.extra_flags=-march={build.march} -mabi={build.mabi} -msmall-data-limit=8 -msave-restore -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common +# peripherial option flags +compiler.peripheral_flags=-DIDE_MENU_PERIPHERALS {build.periADC} {build.periUART} {build.periSPI} {build.periI2C} {build.periI2Cslave} {build.periTimer} + compiler.S.flags={compiler.extra_flags} -x assembler-with-cpp {build.flags.clock} "-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.c.flags={build.flags.clock} {compiler.extra_flags} {compiler.peripheral_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 +compiler.cpp.flags={build.flags.clock} {compiler.extra_flags} {compiler.peripheral_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 compiler.ar.flags=rcs @@ -132,6 +135,7 @@ recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} {build.i recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects +# {build.flags.optimize} recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.extra_flags} -T "{build.system.path}/{build.series}/SRC/Ld/{build.ldscript}" -nostartfiles -Xlinker --gc-sections "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} {build.flags.ldflags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--start-group {object_files} {build.ch_extra_lib} -Wl,--whole-archive "{archive_file_path}" -Wl,--no-whole-archive -lc -Wl,--end-group ## Create output (.bin file) @@ -162,7 +166,7 @@ recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* # Uploader tool ## WCH-LinkE -tools.WCH_linkE.path={runtime.tools.openocd-1.0.0.path}/bin/ +tools.WCH_linkE.path={runtime.tools.openocd-2.3.0.path}/bin/ tools.WCH_linkE.cmd=openocd tools.WCH_linkE.upload.params.verbose= tools.WCH_linkE.upload.params.quiet= @@ -190,6 +194,6 @@ debug.toolchain.prefix=riscv-none-embed debug.toolchain.path={compiler.path} debug.server=openocd -debug.server.openocd.path={runtime.tools.openocd-1.0.0.path}/bin/openocd +debug.server.openocd.path={runtime.tools.openocd-2.3.0.path}/bin/openocd debug.server.openocd.scripts_dir={debug.toolchain.path}/scripts debug.server.openocd.script={runtime.tools.openocd.path}/bin/wch-riscv.cfg diff --git a/system/CH32VM00X/SRC/Ld/LinkV002.ld b/system/CH32VM00X/SRC/Ld/LinkV002.ld new file mode 100644 index 00000000..16111b73 --- /dev/null +++ b/system/CH32VM00X/SRC/Ld/LinkV002.ld @@ -0,0 +1,175 @@ +ENTRY( _start ) + +__stack_size = 512; + +PROVIDE( _stack_size = __stack_size ); + +MEMORY +{ +/* CH32V002 */ +/**/ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K +/**/ + +/* CH32V004_CH32V005 */ +/* + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 32K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 6K +*/ + +/* CH32V006_CH32V007_CH32M007 */ +/* + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 62K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K +*/ + +} + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + . = ALIGN(4); + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.sdata2*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = ALIGN(4); + PROVIDE(_susrstack = . ); + . = . + __stack_size; + PROVIDE( _eusrstack = .); + } >RAM + +} + + + diff --git a/system/CH32VM00X/SRC/Peripheral/inc/ch32v00X.h b/system/CH32VM00X/SRC/Peripheral/inc/ch32v00X.h index 65d279bb..0ac2fc72 100644 --- a/system/CH32VM00X/SRC/Peripheral/inc/ch32v00X.h +++ b/system/CH32VM00X/SRC/Peripheral/inc/ch32v00X.h @@ -16,7 +16,11 @@ extern "C" { #endif -#if !defined(CH32V002) && !defined(CH32V005) && !defined(CH32V006)&& !defined(CH32V007_M007) +#if defined(CH32V002F4) + #define CH32V002 // MMOLE 250710: added to not use V006 defaults +#endif + +#if !defined(CH32V002) && !defined(CH32V004) && !defined(CH32V005) && !defined(CH32V006)&& !defined(CH32V007_M007) // MMOLE 250710: added V004 //#define CH32V002 /* CH32V002*/ //#define CH32V004 /* CH32V004 */ //#define CH32V005 /* CH32V005 */ @@ -406,14 +410,19 @@ typedef struct #define TIM3_BASE (PB1PERIPH_BASE + 0x0800) #define WWDG_BASE (PB1PERIPH_BASE + 0x2C00) #define IWDG_BASE (PB1PERIPH_BASE + 0x3000) -#define USART2_BASE (PB1PERIPH_BASE + 0x4400) +#if !defined(CH32V002) && !defined(CH32V004) // MMOLE 250625: V002 has no USART2 (same for V004), not having GPIOB_BASE makes flash size a bit smaller. + // TODO? CH32V006F4U6 16KB/4K/QFN20 also has no USART2 + #define USART2_BASE (PB1PERIPH_BASE + 0x4400) +#endif #define I2C1_BASE (PB1PERIPH_BASE + 0x5400) #define PWR_BASE (PB1PERIPH_BASE + 0x7000) #define AFIO_BASE (PB2PERIPH_BASE + 0x0000) #define EXTI_BASE (PB2PERIPH_BASE + 0x0400) #define GPIOA_BASE (PB2PERIPH_BASE + 0x0800) -#define GPIOB_BASE (PB2PERIPH_BASE + 0x0C00) +#if !defined(CH32V002) && !defined(CH32V004) // MMOLE 250625: V002 has no port B (same for V004), not having GPIOB_BASE makes flash size a bit smaller. + #define GPIOB_BASE (PB2PERIPH_BASE + 0x0C00) +#endif #define GPIOC_BASE (PB2PERIPH_BASE + 0x1000) #define GPIOD_BASE (PB2PERIPH_BASE + 0x1400) #define ADC1_BASE (PB2PERIPH_BASE + 0x2400) @@ -445,7 +454,9 @@ typedef struct #define AFIO ((AFIO_TypeDef *)AFIO_BASE) #define EXTI ((EXTI_TypeDef *)EXTI_BASE) #define GPIOA ((GPIO_TypeDef *)GPIOA_BASE) -#define GPIOB ((GPIO_TypeDef *)GPIOB_BASE) +#if defined(GPIOB_BASE) // MMOLE 250625: V002 and V004 have no port B + #define GPIOB ((GPIO_TypeDef *)GPIOB_BASE) +#endif #define GPIOC ((GPIO_TypeDef *)GPIOC_BASE) #define GPIOD ((GPIO_TypeDef *)GPIOD_BASE) #define ADC1 ((ADC_TypeDef *)ADC1_BASE) @@ -465,7 +476,9 @@ typedef struct #define OB ((OB_TypeDef *)OB_BASE) #define EXTEN ((EXTEN_TypeDef *)EXTEN_BASE) -#define USART2 ((USART_TypeDef *)USART2_BASE) +#if defined(USART2_BASE) // MMOLE 250710: V002 and V004 have no USART2 + #define USART2 ((USART_TypeDef *)USART2_BASE) +#endif #define OPA ((OPA_TypeDef *)OPA_BASE) #define TIM3 ((TIM_TypeDef *)TIM3_BASE) #define TKey1 ((ADC_TypeDef *)ADC1_BASE) diff --git a/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_flash.c b/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_flash.c index 4b30a505..d592ba97 100644 --- a/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_flash.c +++ b/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_flash.c @@ -680,7 +680,8 @@ void FLASH_BufReset(void) */ void FLASH_BufLoad(uint32_t Address, uint32_t Data0) { - if(((Address >= ValidAddrStart) && (Address < ValidAddrEnd)) || (Address == OB_BASE)) + if(((Address >= ValidAddrStart) && (Address < ValidAddrEnd)) || ((Address >= OB_BASE) && (Address < OB_BASE+0x100))) // MMOLE 250721: copied from latest EVT (v1.2), needed by EEPROM + //if(((Address >= ValidAddrStart) && (Address < ValidAddrEnd)) || (Address == OB_BASE)) { FLASH->CTLR &= (CR_OPTER_Reset & CR_PAGE_ER_Reset); diff --git a/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_gpio.c b/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_gpio.c index 3b719666..807ff06d 100644 --- a/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_gpio.c +++ b/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_gpio.c @@ -37,11 +37,13 @@ void GPIO_DeInit(GPIO_TypeDef *GPIOx) RCC_PB2PeriphResetCmd(RCC_PB2Periph_GPIOA, ENABLE); RCC_PB2PeriphResetCmd(RCC_PB2Periph_GPIOA, DISABLE); } +#if defined(GPIOB_BASE) // MMOLE 250625: V002 and V004 have no port B else if(GPIOx == GPIOB) { RCC_PB2PeriphResetCmd(RCC_PB2Periph_GPIOB, ENABLE); RCC_PB2PeriphResetCmd(RCC_PB2Periph_GPIOB, DISABLE); } +#endif else if(GPIOx == GPIOC) { RCC_PB2PeriphResetCmd(RCC_PB2Periph_GPIOC, ENABLE); @@ -464,12 +466,35 @@ void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) * @param none * * @return none + * + * MMOLE 250625 - by not using chip specific defines, GPIO_IPD_Unused takes up 750 bytes on the V002F4, resulting in 3792 bytes for the simple Blink sketch + * Using the define brings this back to 64 bytes, resulting in 3096 bytes. + * By not defining GPIOB_BASE and using #if defined(GPIOB_BASE) this is lowered to 3056 bytes. + + * */ void GPIO_IPD_Unused(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; - uint32_t chip = 0; RCC_PB2PeriphClockCmd(RCC_PB2Periph_GPIOA |RCC_PB2Periph_GPIOB | RCC_PB2Periph_GPIOC | RCC_PB2Periph_GPIOD, ENABLE); +#if defined(CH32V002F4) + // MMOLE 250625: note that original code is identical for CH32V002F4U6 and CH32V002F4P6. Both 20 pin packages have full set of ports GPIOC and GPIOD + // CH32V002J4M6, CH32V002D4U6, CH32V002A4M6 have less pins and thus need additional and inits for GPIOC and GPIOD, but are identical for GPIOA and GPIOB + // Note that according to Reference Manual p1 fig.1-1, the V002 has no port GPIOB, so perhaps that init can be omitted along with everything GPIOB_BASE? + // (location of GPIOB_BASE (PB2PERIPH_BASE+0x0C00) is marked RESERVED in the RM p9. for V002 and V004 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_3|GPIO_Pin_4\ + |GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; + GPIO_Init(GPIOA, &GPIO_InitStructure); +#if defined(GPIOB_BASE) // MMOLE 250625: V002 and V004 have no port B + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2\ + |GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5\ + |GPIO_Pin_6; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; + GPIO_Init(GPIOB, &GPIO_InitStructure); +#endif +#else + uint32_t chip = 0; chip = *( uint32_t * )0x1FFFF704 & (~0x000000F0); switch(chip) { @@ -735,6 +760,6 @@ void GPIO_IPD_Unused(void) } } - +#endif // #if defined(CH32V002F4) } diff --git a/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_usart.c b/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_usart.c index 38e56028..0e9ef098 100644 --- a/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_usart.c +++ b/system/CH32VM00X/SRC/Peripheral/src/ch32v00X_usart.c @@ -59,11 +59,13 @@ void USART_DeInit(USART_TypeDef *USARTx) RCC_PB2PeriphResetCmd(RCC_PB2Periph_USART1, ENABLE); RCC_PB2PeriphResetCmd(RCC_PB2Periph_USART1, DISABLE); } +#if defined(USART2) // MMOLE 250710: V002 and V004 have no USART2 if(USARTx == USART2) { RCC_PB2PeriphResetCmd(RCC_PB2Periph_USART2, ENABLE); RCC_PB2PeriphResetCmd(RCC_PB2Periph_USART2, DISABLE); } +#endif } /********************************************************************* diff --git a/system/CH32VM00X/USER/system_ch32v00X.c b/system/CH32VM00X/USER/system_ch32v00X.c index 6169b774..10b00a88 100644 --- a/system/CH32VM00X/USER/system_ch32v00X.c +++ b/system/CH32VM00X/USER/system_ch32v00X.c @@ -158,10 +158,10 @@ GPIOD->BSHR =0x2; GPIO_IPD_Unused(); #ifdef SYSCLK_FREQ_8MHz_HSI SetSysClockTo_8MHz_HSI(); -#elif defined SYSCLK_FREQ_24MHZ_HSI - SetSysClockTo_24MHZ_HSI(); -#elif defined SYSCLK_FREQ_48MHZ_HSI - SetSysClockTo_48MHZ_HSI(); +#elif defined SYSCLK_FREQ_24MHz_HSI // MMOLE 250602: fix MHz - SYSCLK_FREQ_24MHZ_HSI + SetSysClockTo_24MHz_HSI(); // SetSysClockTo_24MHZ_HSI(); +#elif defined SYSCLK_FREQ_48MHz_HSI // MMOLE 250602: fix MHz - SYSCLK_FREQ_48MHZ_HSI + SetSysClockTo_48MHz_HSI(); // SetSysClockTo_48MHZ_HSI(); #elif defined SYSCLK_FREQ_8MHz_HSE SetSysClockTo_8MHz_HSE(); #elif defined SYSCLK_FREQ_24MHz_HSE diff --git a/variants/CH32V00x/CH32V003F4/variant_CH32V003F4.h b/variants/CH32V00x/CH32V003F4/variant_CH32V003F4.h index 9bf293a1..c611b233 100644 --- a/variants/CH32V00x/CH32V003F4/variant_CH32V003F4.h +++ b/variants/CH32V00x/CH32V003F4/variant_CH32V003F4.h @@ -13,11 +13,13 @@ #pragma once /* ENABLE Peripherals */ +#ifndef IDE_MENU_PERIPHERALS // MMOLE: defined when peripherals are enabled/disabled via the IDE menu #define ADC_MODULE_ENABLED #define UART_MODULE_ENABLED #define SPI_MODULE_ENABLED #define I2C_MODULE_ENABLED #define TIM_MODULE_ENABLED +#endif /* CH32V003F4 Pins */ #define PA1 PIN_A1 diff --git a/variants/CH32VM00X/CH32V002F4/CMakeLists.txt b/variants/CH32VM00X/CH32V002F4/CMakeLists.txt new file mode 100644 index 00000000..32cffb5f --- /dev/null +++ b/variants/CH32VM00X/CH32V002F4/CMakeLists.txt @@ -0,0 +1,30 @@ +# v3.21 implemented semantic changes regarding $ +# See https://cmake.org/cmake/help/v3.21/command/target_link_libraries.html#linking-object-libraries-via-target-objects +cmake_minimum_required(VERSION 3.21) + +add_library(variant INTERFACE) +add_library(variant_usage INTERFACE) + +target_include_directories(variant_usage INTERFACE + . +) + + +target_link_libraries(variant_usage INTERFACE + base_config +) + +target_link_libraries(variant INTERFACE variant_usage) + + + +add_library(variant_bin STATIC EXCLUDE_FROM_ALL + PeripheralPins.c + variant_CH32V002F4.cpp +) +target_link_libraries(variant_bin PUBLIC variant_usage) + +target_link_libraries(variant INTERFACE + variant_bin +) + diff --git a/variants/CH32VM00X/CH32V002F4/PeripheralPins.c b/variants/CH32VM00X/CH32V002F4/PeripheralPins.c new file mode 100644 index 00000000..caf4a150 --- /dev/null +++ b/variants/CH32VM00X/CH32V002F4/PeripheralPins.c @@ -0,0 +1,147 @@ +/** + ******************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * All rights reserved. + * + * This software component is licensed by WCH under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +#include "Arduino.h" +#include "PeripheralPins.h" + +/* ===== + * Notes: + * - The pins mentioned Px_y_ALTz are alternative possibilities which use other + * HW peripheral instances. You can use them the same way as any other "normal" + * pin (i.e. analogWrite(PA7_ALT1, 128);). + * + * - Commented lines are alternative possibilities which are not used per default. + * If you change them, you will have to know what you do + * ===== + */ + +//*** ADC *** +#ifdef ADC_MODULE_ENABLED +WEAK const PinMap PinMap_ADC[] = { + {PA_2, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 0)}, // ADC1_IN0 + {PA_1, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 1)}, // ADC1_IN1 + {PC_4, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 2)}, // ADC1_IN2 + {PD_2, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 3)}, // ADC1_IN3 + {PD_3, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 4)}, // ADC1_IN4 + {PD_5, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 5)}, // ADC1_IN5 + {PD_6, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 6)}, // ADC1_IN6 + {PD_4, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 7)}, // ADC1_IN7 + {NC, NP, 0} +}; +#endif + +//*** No DAC *** + + + +//*** I2C *** +#ifdef I2C_MODULE_ENABLED +WEAK const PinMap PinMap_I2C_SDA[] = { + {PC_1, I2C1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFOD, NOPULL, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef I2C_MODULE_ENABLED +WEAK const PinMap PinMap_I2C_SCL[] = { + {PC_2, I2C1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFOD, NOPULL, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +//*** TIM *** +#ifdef TIM_MODULE_ENABLED +WEAK const PinMap PinMap_TIM[] = { + {PD_4, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 1)}, // TIM2_CH1 + {PD_3, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 2)}, // TIM2_CH2 + {PC_0, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 3)}, // TIM2_CH3 + {PD_7, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 4)}, // TIM2_CH4 + + {PD_2, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 1)}, // TIM1_CH1 + {PA_1, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 2)}, // TIM1_CH2 + {PC_3, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 3)}, // TIM1_CH3 + {PC_4, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 4)}, // TIM1_CH4 + {PD_0, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 1)}, // TIM1_CH1N + {PA_2, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 2)}, // TIM1_CH2N + {PD_1, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 3)}, // TIM1_CH3N + {NC, NP, 0} +}; +#endif + +//*** UART *** +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_TX[] = { + {PD_5, USART1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_RX[] = { + {PD_6, USART1, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_RTS[] = { + {PC_2, USART1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_CTS[] = { + {PD_3, USART1, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + + +//*** SPI *** +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_MOSI[] = { + {PC_6, SPI1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_MISO[] = { + {PC_7, SPI1, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_FLOAT, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_SCLK[] = { + {PC_5, SPI1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_SSEL[] = { + {PC_1, SPI1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + + + + + + + + + diff --git a/variants/CH32VM00X/CH32V002F4/PinNamesVar.h b/variants/CH32VM00X/CH32V002F4/PinNamesVar.h new file mode 100644 index 00000000..e7ee4ec5 --- /dev/null +++ b/variants/CH32VM00X/CH32V002F4/PinNamesVar.h @@ -0,0 +1,27 @@ +/* SYS_WKUP */ +#ifdef PWR_WAKEUP_PIN1 + SYS_WKUP1 = PA_0, +#endif +#ifdef PWR_WAKEUP_PIN2 + SYS_WKUP2 = NC, +#endif +#ifdef PWR_WAKEUP_PIN3 + SYS_WKUP3 = NC, +#endif +#ifdef PWR_WAKEUP_PIN4 + SYS_WKUP4 = NC, +#endif +#ifdef PWR_WAKEUP_PIN5 + SYS_WKUP5 = NC, +#endif +#ifdef PWR_WAKEUP_PIN6 + SYS_WKUP6 = NC, +#endif +#ifdef PWR_WAKEUP_PIN7 + SYS_WKUP7 = NC, +#endif +#ifdef PWR_WAKEUP_PIN8 + SYS_WKUP8 = NC, +#endif + + diff --git a/variants/CH32VM00X/CH32V002F4/boards_entry.txt b/variants/CH32VM00X/CH32V002F4/boards_entry.txt new file mode 100644 index 00000000..1741c479 --- /dev/null +++ b/variants/CH32VM00X/CH32V002F4/boards_entry.txt @@ -0,0 +1,12 @@ +# This file help to add generic board entry. + + + +# CH32V002F4 +CH32VM00X_EVT.menu.pnum.CH32V002F4=CH32V002F4 EVT +CH32VM00X_EVT.menu.pnum.CH32V002F4.upload.maximum_size=16384 +CH32VM00X_EVT.menu.pnum.CH32V002F4.upload.maximum_data_size=4096 +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.board=CH32V002F4 +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.product_line=CH32VM00X +CH32VM00X_EVT.menu.pnum.CH32V002F4.build.variant=CH32VM00X/CH32V002F4 + diff --git a/variants/CH32VM00X/CH32V002F4/variant_CH32V002F4.cpp b/variants/CH32VM00X/CH32V002F4/variant_CH32V002F4.cpp new file mode 100644 index 00000000..3c35cf60 --- /dev/null +++ b/variants/CH32VM00X/CH32V002F4/variant_CH32V002F4.cpp @@ -0,0 +1,130 @@ +/** + ******************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * All rights reserved. + * + * This software component is licensed by WCH under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +#include "pins_arduino.h" + +/* + +CH32V002 comes in same packages as CH32V003, with addition of QFN12: + CH32V002F4P6 - TSSOP20 - PC0-PC7, PD0-PD7, PA1/PA2, A0-A7 - PD1=SWIO, PD7=RST, PD6=RX, PD5=TX + CH32V002F4U6 - QFN20 - PC0-PC7, PD0-PD7, PA1/PA2, A0-A7 - PD1=SWIO, PD7=RST, PD6=RX, PD5=TX + CH32V002A4M6 - SOP16 - PC0-PC7, PD1/4-7, PA1/2, A0-2/5-7 - PD1=SWIO, PD7=RST, PD6=RX, PD5=TX + CH32V002D4U6 - QFN12 - PC0/3/4/6/7, PD0/1/4/7, PA1/2, A0-2/7 - PD1=SWIO, PD7=RST + CH32V002J4M6 - SOP8 - PC1/2/4, PD1, PA1/2, A0-2/5/6 - PD1=SWIO=PD4=PD5=TX, PA1=PD6=A1=A6=RX +The largest package has 20 pins. For compatibility of Arduino pin numbers the TSSOP20 pinout is used. + +V003/V002/V006 TSSOP20 PINOUT + +-----v-----+ + 14/A7 1 -+PD4 PD3+- 20 13/A4 + TX/A5 2 -+PD5 PD2+- 19 12/A3 + RX/A6 3 -+PD6 PD1+- 18 SWIO + RST 4 -+PD7 PC7+- 17 9 + 0/A1 5 -+PA1 PC6+- 16 8 + 1/A0 6 -+PA2 PC5+- 15 7 + GND 7 -+VSS PC4+- 14 6/A2 + 10 8 -+PD0 PC3+- 13 5 + VCC 9 -+VDD PC2+- 12 4/SCL + 2 10 -+PC0 PC1+- 11 3/SDA + +-----------+ + +CH32V002 vs CH32V003 + +V002: RV32EmC, 16K Flash, 4KB SRAM, 3328B bootloader, 256B user mem, 12-bit ADC, System Clock Monitor, 2-5V, QFN12 +V003: RV32EC, 16K Flash, 2KB SRAM, 1920B bootloasder, 64B user mmm, 10-bit ADC, OPA, 3v#-5V +V004: RV32EmC, 32K Flash, 6KB SRAM, 3328B bootloader, 256B user mem, 12-bit ADC, System Clock Monitor, 2-5V +V005: RV32EmC, 32K Flash, 6KB SRAM, 3328B bootloader, 256B user mem, 12-bit ADC, System Clock Monitor, 2-5V, QFN12, QSOP24, UART2 +V006: RV32EmC, 62K Flash, 8KB SRAM, 3328B bootloader, 256B user mem, 12-bit ADC, 8-ch touch. System Clock Monitor, 2-5V, OPA, UART2, 16-bit simple timer, QFN32 + +Model Flash Ram Gpio SPI +V003 15K 2K +CH32V002F4P6 16K 4K 18 1 1 2 8+3 1 1 1 TSSOP20 +F4U6 QFN20 +A4M6 14 6+3 SOP16 +D4U6 11 4+3 - QFN12 +J4M6 6 6+3 - SOP8 +V004 32K 6K +V005 32K 6K +V006K8 64K 8K + +*/ +// Digital PinName array. On smaller packages some GPIOs are bound to the same pin. +// Leading pinout is TSSOP20 (18x gpio), same as V003 TSSOP20 +const PinName digitalPin[] = { + PA_1, // D0/A1 + PA_2, // D1/A0 + PC_0, // D2 + PC_1, // D3 + PC_2, // D4 + PC_3, // D5 + PC_4, // D6/A2 + PC_5, // D7 + PC_6, // D8 + PC_7, // D9 + PD_0, // D10 + PD_1, // D11/SWIO + PD_2, // D12/A3 + PD_3, // D13/A4 + PD_4, // D14/A7 + PD_5, // D15/A5/TX + PD_6, // D16/A6/RX + PD_7 // D17/RST + +/* WCH V006K8 pins + PA_0, //D0 + PA_1, //D1/A1 + PA_2, //D2/A0 + PA_3, //D3 + PA_4, //D4 + PA_5, //D5 + PA_6, //D6 + PA_7, //D7 + PB_0, //D8 + PB_1, //D9 + PB_2, //D10 + PB_3, //D11 + PB_4, //D12 + PB_5, //D13 + PB_6, //D14 + PC_0, //D15 + PC_1, //D16 + PC_2, //D17 + PC_3, //D18 + PC_4, //D19/A2 + PC_5, //D20 + PC_6, //D21 + PC_7, //D22 + PD_0, //D23 + PD_1, //D24 + PD_2, //D25/A3 + PD_3, //D26/A4 + PD_4, //D27/A7 + PD_5, //D28/A5 + PD_6, //D29/A6 + PD_7 //D30 +*/ +}; + +// Analog (Ax) pin number array +const uint32_t analogInputPin[] = { + 1, // A0/PA2 + 0, // A1/PA1 + 6, // A2/PC4 + 12, // A3/PD2 + 13, // A4/PD3 + 15, // A5/PD5 + 16, // A6/PD6 + 14 // A7/PD4 +}; + + + diff --git a/variants/CH32VM00X/CH32V002F4/variant_CH32V002F4.h b/variants/CH32VM00X/CH32V002F4/variant_CH32V002F4.h new file mode 100644 index 00000000..6038eea0 --- /dev/null +++ b/variants/CH32VM00X/CH32V002F4/variant_CH32V002F4.h @@ -0,0 +1,178 @@ +/* + ******************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * All rights reserved. + * + * This software component is licensed by WCH under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ +#pragma once + +/* ENABLE Peripherals */ +#ifndef IDE_MENU_PERIPHERALS // defined when peripherals are enabled/disabled via the IDE menu +#define ADC_MODULE_ENABLED +#define UART_MODULE_ENABLED +#define SPI_MODULE_ENABLED +#define I2C_MODULE_ENABLED +#define TIM_MODULE_ENABLED +#endif + +/* CH32V002F4 Pins - same as CH32V003F4 TSSOP20 (18x GPIO, 8+3 ADC, 1xSER, no OPA */ +#define PA1 PIN_A1 +#define PA2 PIN_A0 +#define PC0 2 +#define PC1 3 +#define PC2 4 +#define PC3 5 +#define PC4 PIN_A2 +#define PC5 7 +#define PC6 8 +#define PC7 9 +#define PD0 10 +#define PD1 11 +#define PD2 PIN_A3 +#define PD3 PIN_A4 +#define PD4 PIN_A7 +#define PD5 PIN_A5 +#define PD6 PIN_A6 +#define PD7 17 + +/* +#define PA0 0 // N/A +#define PA1 PIN_A1 +#define PA2 PIN_A0 +#define PA3 3 // N/A +#define PA4 4 // N/A +#define PA5 5 // N/A +#define PA6 6 // N/A +#define PA7 7 // N/A +#define PB0 8 // N/A +#define PB1 9 // N/A +#define PB2 10 // N/A +#define PB3 11 // N/A +#define PB4 12 // N/A +#define PB5 13 // N/A +#define PB6 14 // N/A +#define PC0 15 +#define PC1 16 +#define PC2 17 +#define PC3 18 +#define PC4 PIN_A2 +#define PC5 20 +#define PC6 21 +#define PC7 22 +#define PD0 23 +#define PD1 24 +#define PD2 PIN_A3 +#define PD3 PIN_A4 +#define PD4 PIN_A7 +#define PD5 PIN_A5 +#define PD6 PIN_A6 +#define PD7 30 +*/ + +// Alternate pins number +#define PD5_ALT1 (PD5 | ALT1) +#define PD6_ALT1 (PD6 | ALT1) + + +#define NUM_DIGITAL_PINS 18 +#define NUM_ANALOG_INPUTS 8 + +// #define ADC_CTLR_ADCAL +#define ADC_RESOLUTION 12 + + + +// On-board LED pin number +#ifndef LED_BUILTIN + #define LED_BUILTIN PNUM_NOT_DEFINED +#endif + + + +// On-board user button +#ifndef USER_BTN + #define USER_BTN PNUM_NOT_DEFINED +#endif + + + + +// UART Definitions +#ifndef SERIAL_UART_INSTANCE + #define SERIAL_UART_INSTANCE 1 +#endif +// Default pin used for generic 'Serial' instance +// Mandatory for Firmata +#ifndef PIN_SERIAL_RX + #define PIN_SERIAL_RX PD6 +#endif +#ifndef PIN_SERIAL_TX + #define PIN_SERIAL_TX PD5 +#endif + + +// SPI definitions +#ifndef PIN_SPI_SS + #define PIN_SPI_SS PC4 +#endif +#ifndef PIN_SPI_MOSI + #define PIN_SPI_MOSI PC6 +#endif +#ifndef PIN_SPI_MISO + #define PIN_SPI_MISO PC7 +#endif +#ifndef PIN_SPI_SCK + #define PIN_SPI_SCK PC5 +#endif + +// I2C definitions +#ifndef PIN_WIRE_SDA + #define PIN_WIRE_SDA PC1 +#endif +#ifndef PIN_WIRE_SCL + #define PIN_WIRE_SCL PC2 +#endif + +// Timer Definitions +#ifndef TIMER_TONE + #define TIMER_TONE TIM2 +#endif +#ifndef TIMER_SERVO + #define TIMER_SERVO TIM1 +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#ifdef __cplusplus + // These serial port names are intended to allow libraries and architecture-neutral + // sketches to automatically default to the correct port name for a particular type + // of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, + // the first hardware serial port whose RX/TX pins are not dedicated to another use. + // + // SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor + // + // SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial + // + // SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library + // + // SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. + // + // SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX + // pins are NOT connected to anything by default. + #ifndef SERIAL_PORT_MONITOR + #define SERIAL_PORT_MONITOR Serial + #endif + #ifndef SERIAL_PORT_HARDWARE + #define SERIAL_PORT_HARDWARE Serial + #endif +#endif + + diff --git a/variants/CH32VM00X/CH32V006F8/CMakeLists.txt b/variants/CH32VM00X/CH32V006F8/CMakeLists.txt new file mode 100644 index 00000000..813148f5 --- /dev/null +++ b/variants/CH32VM00X/CH32V006F8/CMakeLists.txt @@ -0,0 +1,30 @@ +# v3.21 implemented semantic changes regarding $ +# See https://cmake.org/cmake/help/v3.21/command/target_link_libraries.html#linking-object-libraries-via-target-objects +cmake_minimum_required(VERSION 3.21) + +add_library(variant INTERFACE) +add_library(variant_usage INTERFACE) + +target_include_directories(variant_usage INTERFACE + . +) + + +target_link_libraries(variant_usage INTERFACE + base_config +) + +target_link_libraries(variant INTERFACE variant_usage) + + + +add_library(variant_bin STATIC EXCLUDE_FROM_ALL + PeripheralPins.c + variant_CH32V006K8.cpp +) +target_link_libraries(variant_bin PUBLIC variant_usage) + +target_link_libraries(variant INTERFACE + variant_bin +) + diff --git a/variants/CH32VM00X/CH32V006F8/PeripheralPins.c b/variants/CH32VM00X/CH32V006F8/PeripheralPins.c new file mode 100644 index 00000000..dc215b0f --- /dev/null +++ b/variants/CH32VM00X/CH32V006F8/PeripheralPins.c @@ -0,0 +1,155 @@ +/** + ******************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * All rights reserved. + * + * This software component is licensed by WCH under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +#include "Arduino.h" +#include "PeripheralPins.h" + +/* ===== + * Notes: + * - The pins mentioned Px_y_ALTz are alternative possibilities which use other + * HW peripheral instances. You can use them the same way as any other "normal" + * pin (i.e. analogWrite(PA7_ALT1, 128);). + * + * - Commented lines are alternative possibilities which are not used per default. + * If you change them, you will have to know what you do + * ===== + */ + +//*** ADC *** +#ifdef ADC_MODULE_ENABLED +WEAK const PinMap PinMap_ADC[] = { + {PA_2, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 0)}, // ADC1_IN0 + {PA_1, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 1)}, // ADC1_IN1 + {PC_4, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 2)}, // ADC1_IN2 + {PD_2, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 3)}, // ADC1_IN3 + {PD_3, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 4)}, // ADC1_IN4 + {PD_5, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 5)}, // ADC1_IN5 + {PD_6, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 6)}, // ADC1_IN6 + {PD_4, ADC1, CH_PIN_DATA_EXT(CH_MODE_INPUT, CH_CNF_INPUT_ANALOG, 0, AFIO_NONE, 7)}, // ADC1_IN7 + {NC, NP, 0} +}; +#endif + +//*** No DAC *** + + + +//*** I2C *** +#ifdef I2C_MODULE_ENABLED +WEAK const PinMap PinMap_I2C_SDA[] = { + {PC_1, I2C1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFOD, NOPULL, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef I2C_MODULE_ENABLED +WEAK const PinMap PinMap_I2C_SCL[] = { + {PC_2, I2C1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFOD, NOPULL, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +//*** TIM *** +#ifdef TIM_MODULE_ENABLED +WEAK const PinMap PinMap_TIM[] = { + {PD_4, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 1)}, // TIM2_CH1 + {PD_3, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 2)}, // TIM2_CH2 + {PC_0, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 3)}, // TIM2_CH3 + {PD_7, TIM2, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM2_DISABLE, 4)}, // TIM2_CH4 + + {PD_2, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 1)}, // TIM1_CH1 + {PA_1, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 2)}, // TIM1_CH2 + {PC_3, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 3)}, // TIM1_CH3 + {PC_4, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 4)}, // TIM1_CH4 + {PD_0, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 1)}, // TIM1_CH1N + {PA_2, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 2)}, // TIM1_CH2N + {PD_1, TIM1, CH_PIN_DATA_EXT(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, NOPULL, AFIO_Remap_TIM1_DISABLE, 3)}, // TIM1_CH3N + {NC, NP, 0} +}; +#endif + +//*** UART *** +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_TX[] = { + {PD_5, USART1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {PD_2, USART2, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_PartialRemap3_USART2_ENABLE)}, // V006 - USART2 was not defined + //{PA_2, USART2, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, // X033 was PA_2 + {NC, NP, 0} +}; +#endif + +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_RX[] = { + {PD_6, USART1, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_NONE)}, + {PD_3, USART2, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_PartialRemap3_USART2_ENABLE)}, // V006 - USART2 was not defined + //{PA_3, USART2, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_NONE)}, // X033 was PA_3 + {NC, NP, 0} +}; +#endif + +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_RTS[] = { + {PC_2, USART1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {PA_1, USART2, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_PartialRemap3_USART2_ENABLE)}, // V006 - USART2 RTS on F8 is PA_1: alt USART_2_RTS_2/3/4/5 + //{PA_1, USART2, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, // X033 was PA_1 + {NC, NP, 0} +}; +#endif + +#ifdef UART_MODULE_ENABLED +WEAK const PinMap PinMap_UART_CTS[] = { + {PD_3, USART1, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_NONE)}, + {PA_4, USART2, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_NONE)}, // V006 - USART2 CTS on F8 is PA_4: USART2_CTS, alt USART_2_CTS_2/USART2_CTS_5 + //{PA_0, USART2, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_PUPD, PULLUP, AFIO_NONE)}, // X033 was PA_0 + {NC, NP, 0} +}; +#endif + + +//*** SPI *** +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_MOSI[] = { + {PC_6, SPI1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_MISO[] = { + {PC_7, SPI1, CH_PIN_DATA(CH_MODE_INPUT, CH_CNF_INPUT_FLOAT, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_SCLK[] = { + {PC_5, SPI1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + +#ifdef SPI_MODULE_ENABLED +WEAK const PinMap PinMap_SPI_SSEL[] = { + {PC_1, SPI1, CH_PIN_DATA(CH_MODE_OUTPUT_50MHz, CH_CNF_OUTPUT_AFPP, 0, AFIO_NONE)}, + {NC, NP, 0} +}; +#endif + + + + + + + + + diff --git a/variants/CH32VM00X/CH32V006F8/PinNamesVar.h b/variants/CH32VM00X/CH32V006F8/PinNamesVar.h new file mode 100644 index 00000000..e7ee4ec5 --- /dev/null +++ b/variants/CH32VM00X/CH32V006F8/PinNamesVar.h @@ -0,0 +1,27 @@ +/* SYS_WKUP */ +#ifdef PWR_WAKEUP_PIN1 + SYS_WKUP1 = PA_0, +#endif +#ifdef PWR_WAKEUP_PIN2 + SYS_WKUP2 = NC, +#endif +#ifdef PWR_WAKEUP_PIN3 + SYS_WKUP3 = NC, +#endif +#ifdef PWR_WAKEUP_PIN4 + SYS_WKUP4 = NC, +#endif +#ifdef PWR_WAKEUP_PIN5 + SYS_WKUP5 = NC, +#endif +#ifdef PWR_WAKEUP_PIN6 + SYS_WKUP6 = NC, +#endif +#ifdef PWR_WAKEUP_PIN7 + SYS_WKUP7 = NC, +#endif +#ifdef PWR_WAKEUP_PIN8 + SYS_WKUP8 = NC, +#endif + + diff --git a/variants/CH32VM00X/CH32V006F8/boards_entry.txt b/variants/CH32VM00X/CH32V006F8/boards_entry.txt new file mode 100644 index 00000000..02390c66 --- /dev/null +++ b/variants/CH32VM00X/CH32V006F8/boards_entry.txt @@ -0,0 +1,12 @@ +# This file help to add generic board entry. + + + +# CH32V006F8 +CH32VM00X_EVT.menu.pnum.CH32V006F8=CH32V006F8 EVT +CH32VM00X_EVT.menu.pnum.CH32V006F8.upload.maximum_size=63488 +CH32VM00X_EVT.menu.pnum.CH32V006F8.upload.maximum_data_size=8192 +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.board=CH32V006F8 +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.product_line=CH32VM00X +CH32VM00X_EVT.menu.pnum.CH32V006F8.build.variant=CH32VM00X/CH32V006F8 + diff --git a/variants/CH32VM00X/CH32V006F8/variant_CH32V006F8.cpp b/variants/CH32VM00X/CH32V006F8/variant_CH32V006F8.cpp new file mode 100644 index 00000000..c8264263 --- /dev/null +++ b/variants/CH32VM00X/CH32V006F8/variant_CH32V006F8.cpp @@ -0,0 +1,116 @@ +/** + ******************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * All rights reserved. + * + * This software component is licensed by WCH under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +#include "pins_arduino.h" + + +/* +These CH32V006F packages have 20 pins: + CH32V006F8P6 - TSSOP20 - PC0-PC7, PD0-PD7, PA1/PA2, A0-A7 - PD1=SWIO, PD7=RST, PD6=RX, PD5=TX + CH32V006F8U6 - QFN20 - PC0-PC7, PD0-PD7, PA1/PA2, A0-A7 - PD1=SWIO, PD7=RST, PD6=RX, PD5=TX + CH32V006F4U6 - QFN20 - PC0-PC7, PD0-PD7, PA1/PA2, A0-A7 - PD1=SWIO, PD7=RST, PD6=RX, PD5=TX, 16K Flash, 4K RAM, no OPA + +V003/V002/V006 TSSOP20 PINOUT + +-----v-----+ + 14/A7 1 -+PD4 PD3+- 20 13/A4 + TX/A5 2 -+PD5 PD2+- 19 12/A3 + RX/A6 3 -+PD6 PD1+- 18 SWIO + RST 4 -+PD7 PC7+- 17 9 + 0/A1 5 -+PA1 PC6+- 16 8 + 1/A0 6 -+PA2 PC5+- 15 7 + GND 7 -+VSS PC4+- 14 6/A2 + 10 8 -+PD0 PC3+- 13 5 + VCC 9 -+VDD PC2+- 12 4/SCL + 2 10 -+PC0 PC1+- 11 3/SDA + +-----------+ +*/ + +// Digital PinName array,Some GPIOs are bound to the same pin. +const PinName digitalPin[] = { + PA_1, // D0/A1 + PA_2, // D1/A0 + PC_0, // D2 + PC_1, // D3 + PC_2, // D4 + PC_3, // D5 + PC_4, // D6/A2 + PC_5, // D7 + PC_6, // D8 + PC_7, // D9 + PD_0, // D10 + PD_1, // D11/SWIO + PD_2, // D12/A3 + PD_3, // D13/A4 + PD_4, // D14/A7 + PD_5, // D15/A5/TX + PD_6, // D16/A6/RX + PD_7 // D17/RST +/* + PA_0, //D0 + PA_1, //D1/A1 + PA_2, //D2/A0 + PA_3, //D3 + PA_4, //D4 + PA_5, //D5 + PA_6, //D6 + PA_7, //D7 + PB_0, //D8 + PB_1, //D9 + PB_2, //D10 + PB_3, //D11 + PB_4, //D12 + PB_5, //D13 + PB_6, //D14 + PC_0, //D15 + PC_1, //D16 + PC_2, //D17 + PC_3, //D18 + PC_4, //D19/A2 + PC_5, //D20 + PC_6, //D21 + PC_7, //D22 + PD_0, //D23 + PD_1, //D24 + PD_2, //D25/A3 + PD_3, //D26/A4 + PD_4, //D27/A7 + PD_5, //D28/A5 + PD_6, //D29/A6 + PD_7 //D30 +*/ +}; + +// Analog (Ax) pin number array +const uint32_t analogInputPin[] = { + 1, // A0/PA2 + 0, // A1/PA1 + 6, // A2/PC4 + 12, // A3/PD2 + 13, // A4/PD3 + 15, // A5/PD5 + 16, // A6/PD6 + 14 // A7/PD4 +/* + 2, // A0/PA2 + 1, // A1/PA1 + 19, // A2/PC4 + 25, // A3/PD2 + 26, // A4/PD3 + 28, // A5/PD5 + 29, // A6/PD6 + 27 // A7/PD4 +*/ +}; + + + diff --git a/variants/CH32VM00X/CH32V006F8/variant_CH32V006F8.h b/variants/CH32VM00X/CH32V006F8/variant_CH32V006F8.h new file mode 100644 index 00000000..29155a7c --- /dev/null +++ b/variants/CH32VM00X/CH32V006F8/variant_CH32V006F8.h @@ -0,0 +1,230 @@ +/* + ******************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * All rights reserved. + * + * This software component is licensed by WCH under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ +#pragma once + +/* ENABLE Peripherals */ +#ifndef IDE_MENU_PERIPHERALS // defined when peripherals are enabled/disabled via the IDE menu +#define ADC_MODULE_ENABLED +#define UART_MODULE_ENABLED +#define SPI_MODULE_ENABLED +#define I2C_MODULE_ENABLED +#define TIM_MODULE_ENABLED +#endif + +/* CH32V006F Pins */ +#define PA1 PIN_A1 +#define PA2 PIN_A0 +#define PC0 2 +#define PC1 3 +#define PC2 4 +#define PC3 5 +#define PC4 PIN_A2 +#define PC5 7 +#define PC6 8 +#define PC7 9 +#define PD0 10 +#define PD1 11 +#define PD2 PIN_A3 +#define PD3 PIN_A4 +#define PD4 PIN_A7 +#define PD5 PIN_A5 +#define PD6 PIN_A6 +#define PD7 17 + +/* +#define PA0 0 +#define PA1 PIN_A1 +#define PA2 PIN_A0 +#define PA3 3 +#define PA4 4 +#define PA5 5 +#define PA6 6 +#define PA7 7 +#define PB0 8 +#define PB1 9 +#define PB2 10 +#define PB3 11 +#define PB4 12 +#define PB5 13 +#define PB6 14 +#define PC0 15 +#define PC1 16 +#define PC2 17 +#define PC3 18 +#define PC4 PIN_A2 +#define PC5 20 +#define PC6 21 +#define PC7 22 +#define PD0 23 +#define PD1 24 +#define PD2 PIN_A3 +#define PD3 PIN_A4 +#define PD4 PIN_A7 +#define PD5 PIN_A5 +#define PD6 PIN_A6 +#define PD7 30 +*/ + +// Alternate pins number +#define PD5_ALT1 (PD5 | ALT1) +#define PD6_ALT1 (PD6 | ALT1) + + +#define NUM_DIGITAL_PINS 18 +#define NUM_ANALOG_INPUTS 8 + +// #define ADC_CTLR_ADCAL +#define ADC_RESOLUTION 12 + + + +// On-board LED pin number +#ifndef LED_BUILTIN + #define LED_BUILTIN PNUM_NOT_DEFINED +#endif + + + +// On-board user button +#ifndef USER_BTN + #define USER_BTN PNUM_NOT_DEFINED +#endif + + + + +// UART Definitions +#ifndef SERIAL_UART_INSTANCES + // Define the number of UART instances that can be used. + // For CH32V006F8 SSOP20 the supported maximum is currently two. + // These are UART1 and UART2 on pins PD5=TX1, PD6=RX1 and on PD2=TX2, PD3=RX2 + #define SERIAL_UART_INSTANCES 2 // select 1 or 2 instances +#endif + +// TSSOP20 UART2 has RX/TX as alternative functions U2RX_/U2TX_ on pins 20/19 (PD3/PD2) +#if (SERIAL_UART_INSTANCES==1) + // If using only one UART inactance, select which to use: UART1 or UART2 + #ifndef SERIAL_UART_INSTANCE + #define SERIAL_UART_INSTANCE 1 + #endif +#else + // multiple instances, max 2 for CH32X033F8P SSOP20 + // NOTE: do not define SERIAL_UART_INSTANCE when using multiple instances! + #undef SERIAL_UART_INSTANCE + #define ENABLE_HWSERIAL1 1 + #define ENABLE_HWSERIAL2 1 +#endif + + +// Default pin used for generic 'Serial' instance +// Mandatory for Firmata +// For CH32V006F8 serial pins RX1=PD6/TX1=PD5 or alternative U2RX_/U2TX_ on pins 20/19 (PD3/PD2) + +// Pins used for Serial2 instance (used by HardwareSerial constructor) +#if (SERIAL_UART_INSTANCES==1) + // one single UART instance, specify which pins to be used + #if (SERIAL_UART_INSTANCE==1) + #ifndef PIN_SERIAL_RX + #define PIN_SERIAL_RX PD6 + #endif + #ifndef PIN_SERIAL_TX + #define PIN_SERIAL_TX PD5 + #endif + #elif (SERIAL_UART_INSTANCE==2) + // Use UART2 RX2/TX2 (PD3/PD2) + #ifndef PIN_SERIAL_RX + #define PIN_SERIAL_RX PD3 + #endif + #ifndef PIN_SERIAL_TX + #define PIN_SERIAL_TX PD2 + #endif + #endif // #if (SERIAL_UART_INSTANCE==1) +#else + // multiple instances. Define each pin for each UART (Serial=Serial1) + #define Serial Serial1 // specify which UART to use as 'Serial' + #ifndef PIN_SERIAL_RX + #define PIN_SERIAL_RX PD6 // supported: PD6=RX1 (not supported alternatives PD5/PD1/PC6/PC1) + #endif + #ifndef PIN_SERIAL_TX + #define PIN_SERIAL_TX PD5 // supported: PD5=TX1 (not supported alternatives PD6/PC5/PC0/PD0) + #endif + #ifndef PIN_SERIAL_RX2 + #define PIN_SERIAL_RX2 PD3 // supported: PD3=RX2_ + #endif + #ifndef PIN_SERIAL_TX2 + #define PIN_SERIAL_TX2 PD2 // supported: PD2=TX2_/USART2_TX_3 (not supported alternative PA2=USART2_TX_2/PC4=USART2_TX_5/PD7=PA4=USART2_TX_1) + // Datasheet Note 4: For CH32V006F8U6, CH32V006F8P6, CH32V005F6U6, CH32V005F6P6 and CH32V005D6U6 chips, + // the PA4 and PD7 pins are short-jointed and sealed inside the chip, and it is forbidden that both of the two IMAGO + // are configured as output functions. Note 5: PD7 is the reset pin. + #endif +#endif // #if (SERIAL_UART_INSTANCES==1) + + +// SPI definitions +#ifndef PIN_SPI_SS + #define PIN_SPI_SS PC4 +#endif +#ifndef PIN_SPI_MOSI + #define PIN_SPI_MOSI PC6 +#endif +#ifndef PIN_SPI_MISO + #define PIN_SPI_MISO PC7 +#endif +#ifndef PIN_SPI_SCK + #define PIN_SPI_SCK PC5 +#endif + +// I2C definitions +#ifndef PIN_WIRE_SDA + #define PIN_WIRE_SDA PC1 +#endif +#ifndef PIN_WIRE_SCL + #define PIN_WIRE_SCL PC2 +#endif + +#ifndef TIMER_TONE + #define TIMER_TONE TIM2 +#endif +#ifndef TIMER_SERVO + #define TIMER_SERVO TIM1 +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#ifdef __cplusplus + // These serial port names are intended to allow libraries and architecture-neutral + // sketches to automatically default to the correct port name for a particular type + // of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, + // the first hardware serial port whose RX/TX pins are not dedicated to another use. + // + // SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor + // + // SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial + // + // SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library + // + // SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. + // + // SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX + // pins are NOT connected to anything by default. + #ifndef SERIAL_PORT_MONITOR + #define SERIAL_PORT_MONITOR Serial + #endif + #ifndef SERIAL_PORT_HARDWARE + #define SERIAL_PORT_HARDWARE Serial + #endif +#endif + + diff --git a/variants/CH32VM00X/PinAF_CH32V00X.h b/variants/CH32VM00X/PinAF_CH32V00X.h index 5b4fbffd..d64630b8 100644 --- a/variants/CH32VM00X/PinAF_CH32V00X.h +++ b/variants/CH32VM00X/PinAF_CH32V00X.h @@ -119,10 +119,17 @@ static inline void pinV32_DisconnectDebug(PinName pin) // Disconnect JTAG-DP + SW-DP signals. // Warning: Need to reconnect under reset +#if defined(GPIOB_BASE) // MMOLE 250625: V002 and V004 have no port B if ((pin == PD_1) || (pin == PB_3)) { GPIO_PinRemapConfig(GPIO_Remap_SDI_Disable, ENABLE); // JTAG-DP Disabled and SW-DP Disabled } +#else + if ((pin == PD_1)) + { + GPIO_PinRemapConfig(GPIO_Remap_SDI_Disable, ENABLE); // JTAG-DP Disabled and SW-DP Disabled + } +#endif // #if defined(GPIOB_BASE) #else (void)(pin); #endif diff --git a/variants/CH32VM00X/README.md b/variants/CH32VM00X/README.md new file mode 100644 index 00000000..e67c38f6 --- /dev/null +++ b/variants/CH32VM00X/README.md @@ -0,0 +1,103 @@ +## CH32VM00X Boards: CH32V002, CH32V006, etc. ## + +Currently supported board variants (listed in **bold**): +| | QFN32 |QSOP24|QFN20|[TSSOP20](#tssop20-pinout) |SSOP16|QFN12|SOP8 | | +|--------|--------|------|-----|--------|------|-----|-----|---| +|CH32V002|_n/a_ |_n/a_ | |**F4P6**| | | | | +|CH32V004|_n/a_ |_n/a_ | | |_n/a_ |_n/a_|_n/a_| | +|CH32V005|_n/a_ | | | |_n/a_ | |_n/a_| | +|CH32V006|**K8U6**| | |**F6P6**|_n/a_ |_n/a_|_n/a_| | +|CH32V007| | |_n/a_| _n/a_ |_n/a_ |_n/a_|_n/a_| | +|CH32M007|_n/a_ | |_n/a_| _n/a_ |_n/a_ |_n/a_|_n/a_| * | + + - See [notes below](#known-issues--limitations) for known issues and installation instructions. + - CH32M007 also available in QFN26/QSOP28 (no specfic support yet). + +------------------ + +### TSSOP20 PINOUT ### +Arduino pin numbers D0-D17, A0-A7. +Shared pinout for CH32V003F4P6 /CH32V002F4P6/CH32V006F8P6 + +``` + +-----v-----+ + A7 D14~ 1-+PD4 PD3+-20 D13~ A4 + TX/A5 D15~ 2-+PD5 PD2+-19 D12~ A3 + RX/A6 D16~ 3-+PD6 PD1+-18 D11 SWIO + RST D17 4-+PD7 PC7+-17 D9 MISO + A1 D0~ 5-+PA1 PC6+-16 D8 MOSI + A0 D1~ 6-+PA2 PC5+-15 D7 SCK + GND 7-+VSS PC4+-14 D6~ A2 + D10 8-+PD0 PC3+-13 D5 + VCC 9-+VDD PC2+-12 D4 SCL + D2 10-+PC0 PC1+-11 D3 SDA + +-----------+ +``` + +### Feature comparison with V003 (TSSOP20) ### + +| Feature | V003 | V002 | V004 | V005 | V006 | +| ------- | ------ | ------ | ------ | ------ | ------ | +| Flash | 16KB | 16KB | 32KB | 32KB | 62KB | +| RAM | 2KB | 4KB | 6KB | 6KB | 8KB | +| UserMem | 64B | 256B | 256B | 256B | 256B | +| ADC | 10-bit | 12-bit | 12-bit | 12-bit | 12-bit | +| OPA | 1-ch | | | 1-ch | 3-ch | +| Touch | | | | | 8x | +| Serial | 1x | 1x | 1x | 1x | 2x | +| Timers | 2+2 WD | 2+2 WD | 2+2 WD | 2+2 WD | 3+2 WD | +| VCC | 2v7~5v5| 2~5V | 2~5V | 2~5V | 2~5V | +| ISA | RV32EC | RV32EmC| RV32EmC| RV32EmC| RV32EmC| + +### Documentation / Links ### +- Datasheets: [CH32V002](https://www.wch-ic.com/downloads/CH32V002DS0_PDF.html), [CH32V004](https://www.wch-ic.com/downloads/CH32V004DS0_PDF.html), [CH32V005/CH32V006](https://www.wch-ic.com/downloads/CH32V006DS0_PDF.html), [CH32V007/CH32M007](https://www.wch-ic.com/downloads/CH32V007DS0_PDF.html), +- Reference manual: [CH32V00X](https://www.wch-ic.com/downloads/CH32V00XRM_PDF.html) + +### Known Issues & Limitations ### +- The boards file in this PR has provisions for selecting peripherals from the menu. This feature is not (yet) implemented for all boards (currenly only for V003/V002/V006/X035). To support other boards the menu options need to be copied and `#ifndef IDE_MENU_PERIPHERALS` should be added to the variant specific file variant_CH32XnnnYYZZ.h +- To fix the clock capitalization bug (see #66), minimal changes were made. Not all changes from the latest SDK were incorporated. +- This PR requires CH32 Arduino core with latest updates from the master branch (see [installation notes](#fresh-installation-with-support-for-ch32vm00x-v002v006etc)). +- To see the updated boards menu after installation of core v1.0.4, you may need to [clear the IDE 2.x application cache](#clearing-arduino-2x-ide-application-cache). +- Uploading and debugging the new boards using the Arduino IDE 2.x, requires an [updated version of OpenOCD](#updating-openocd). + +------------------ + +### Fresh installation with support for CH32VM00X (V002/V006/etc) ### + +1. Install [latest WCH Link Utility](https://www.wch.cn/downloads/WCH-LinkUtility_ZIP.html), update LinkE device when prompted. Test connection to Link Utility and CH32 chip using Query Chip Info. (This step installs drivers and support for CH32V006 and other newer chips). +2. Install latest Arduino IDE (v2.3.6). +3. Run Arduino IDE as administrator, Add [board json](https://github.com/openwch/board_manager_files/raw/main/package_ch32v_index.json) to preferences. Install WCH CH32 core v1.0.4. Exit IDE. +4. Download [zip of latest master branch](https://github.com/openwch/arduino_core_ch32/archive/refs/heads/main.zip). Unzip and copy/overwrite all contents to this location: + - `C:\Users\\AppData\Local\Arduino15\packages\WCH\hardware\ch32v\1.0.4` +5. Optional: review [unmerged PRs](https://github.com/openwch/arduino_core_ch32/pulls) for possibly required fixes and manually copy changed files. +6. Optional: for uploading to new chip: [update OpenOCD](#updating-openocd) obtained from MounRiver Studio. +7. Restart IDE. If new boards are not visible: [clear IDE application cache](#clearing-arduino-2x-ide-application-cache). +8. Select CH32 board. Test uploading simple serial example. Test debugging. + +### Clearing Arduino 2.x IDE application cache ### +When newly added menu items are not visible in the Arduino IDE v2.x, the cause can be an application cache that is not automatically refreshed. +Assuming you are using the Arduino IDE v2.x under Windows, the menu can be cached in such a way that restarting the IDE is insufficient. For instance when I added my definition for the X033 board (and later again for the the V002), it would not show the board to be selected. I had to exit the IDE, then remove this folder prior to restarting the IDE: + - `C:\Users\\AppData\Roaming\arduino-ide` + +I read that this is a [known IDE 2.x issue](https://github.com/arduino/arduino-ide/issues/1030) and that it's okay to [delete the entire folder](https://github.com/arduino/arduino-ide/issues/1030#issuecomment-1152005617). This [Arduino post](https://support.arduino.cc/hc/en-us/articles/4415103213714-Find-sketches-libraries-board-cores-and-other-files-on-your-computer) gives an overview of all folders used by the IDE. Apparently that `arduino-ide` folder contains some state information. After deleting it and restarting the IDE, you need to select the board again and then the new menu should be shown. +(Issue [#110](https://github.com/openwch/arduino_core_ch32/issues/110) shares some frustration, followed by [this solution](https://github.com/openwch/arduino_core_ch32/issues/110#issuecomment-2768025106) ). + +### Updating OpenOCD ### +To support the new CH32VM00X boards (CH32V002, CH32V006, etc), the installation done when installing CH32 Arduino core v 1.0.4 needs to be updated. +This can be done by copying it from a recent installation of MounRiver Studio. + +These are the steps I took: + +After installation of MounRiver Studio (in Windows 11 x64 under VMware Workstation Player) following all defaults, WCH OpenOCD v2.3 was found here: +`C:\MounRiver\MounRiver_Studio2\resources\app\resources\win32\components\WCH\OpenOCD` + +I copied the contents of that folder to a new 2.3.0 folder (next to the 1.0.0 folder) in +- `C:\Users\\AppData\Local\Arduino15\packages\WCH\tools\openocd` + +Then I changed this file: +- `C:\Users\\AppData\Local\Arduino15\packages\WCH\hardware\ch32v\1.0.4\platform.txt` +Use search and replace to change "openocd-1.0.0" into "openocd-2.3.0" in the sections `# Uploader tool` and `# Debugger configuration`. + +After restarting the Arduino IDE (v2.3.6) I could successfully upload my sketch and use the interactive debugger. Yippie! +Thanks @tako0910 for pointing out this OpenOCD update. +