Arduino Core for WCH CH32

repository·main·Indexed 18 days ago

https://github.com/openwch/arduino_core_ch32

Core library and support for WCH CH32 series MCU evaluation boards, enabling programming and debugging via the Arduino IDE. Supports various families including CH32V00x, CH32V20x, CH32X035, CH32V10x, and CH32V30x. Includes implementations for EEPROM emulation (specifically for CH32V003), Wire (I2C), SPI, and base classes for network/serial communication such as Client and Server.

Tokens
6.1K
Snippets
22
Records
27
Agent score
14%

What's inside arduino_core_ch32

  1. Save EEPROM data to permanent storage

    main

    The EEPROM library uses a RAM buffer to allow speedy access to data. Changes made via write(), put(), or the subscript operator [] only affect the RAM buffer. To persist these changes to the chip's flash memory, you must call EEPROM.commit().

    EEPROM.commit() returns a bool indicating whether the write operation was successful.

    EEPROM.write(0, 123);
    if (EEPROM.commit()) {
      // Data successfully saved to flash
    }
  2. EEPROM implementation details for CH32V003

    main

    On the CH32V003, the library emulates EEPROM using the Option bytes area in flash memory.

    • Capacity: 26 bytes total. This includes 2 bytes from data0 and data1 (Option bytes) and 24 bytes from the user select word storage area.
    • Memory Layout: The internal _data[26] array is laid out as { ob[4], ob[6], ob[16...62] }.
    • Limitations: This implementation is currently specific to the CH32V003. Attempting to address more than 26 bytes may cause incorrect behavior.
    • Special Method: EEPROM.ReadOptionBytes() returns a uint32_t containing the data0 and data1 bytes and their inverse values, useful for inspecting the underlying hardware storage.
  3. Install the CH32 Arduino Core via Boards Manager

    main

    To use CH32 MCU support in the Arduino IDE, add the official WCH boards manager URL to your IDE settings and install the package through the Boards Manager.

    1. Open the Arduino IDE.
    2. Navigate to the Additional Boards Managers URLs field in the preferences.
    3. Add the following URL: https://github.com/openwch/board_manager_files/raw/main/package_ch32v_index.json
    4. Open the Boards Manager, search for "wch", and install the package.
    https://github.com/openwch/board_manager_files/raw/main/package_ch32v_index.json
  4. Configure Linux environment for CH32 uploading

    main

    On Linux, after the first installation of the support package, you must run a configuration script to set up necessary libraries and rules (such as udev rules) to ensure the upload function works correctly.

    Navigate to the package installation path within your Arduino IDE directory and execute start.sh. The path typically follows this pattern:

    cd ~/.arduino15/packages/WCH/tools/beforeinstall/1.0.0
    ./start.sh

    Upon successful execution, you should see output indicating that libraries were copied/registered and rules were reloaded.

    cd ~/.arduino15/packages/WCH/tools/beforeinstall/1.0.0
    ./start.sh
  5. Initialize the EEPROM library

    main

    To use the EEPROM library, you must include the header file and call EEPROM.begin() during your setup phase. This method initializes the EEPROM object by reading the current data from permanent storage into a RAM memory buffer, allowing for fast access.

    Note: This library follows the initialization convention used by Serial and Wire classes, which differs from some older Arduino EEPROM implementations.

    #include <EEPROM.h>
    
    void setup(){
      EEPROM.begin();
    }
    
    void loop(){
    }
  6. Enable I2C scanning on CH32 using Wire

    main

    To use the I2C Scanner example on CH32 boards, you must manually modify the libraries/Wire/src/utility/twi.c file to support scanning via Wire.endTransmission() without data transmission.

    Required changes in twi.c:

    1. Ensure a timeout on addresses releases the bus.
    2. Allow sending only the address (without actual data).
    3. Reduce the timeout value: set I2C_TIMEOUT_TICK to 25 (previously 100ms).

    Note: The standard Wire.setWireTimeout(timeout, reset_on_timeout) function is currently not supported in this core.

  7. Use the EEPROM library for non-volatile storage

    main

    The EEPROM library emulates EEPROM by using the Option bytes area in Flash. On the CH32V003, this provides 26 bytes of storage (2 bytes of option data + 24 bytes of available space).

    Important Workflow:

    1. Call begin() to initialize the library and load existing data into RAM.
    2. Use read(), write(), put(), or get() to manipulate data in the RAM buffer.
    3. Crucial: You must call commit() to write the modified RAM buffer back to Flash. Changes are not persistent until commit() is called.
    4. Use erase() to clear the buffer (requires commit() to persist).
    #include <EEPROM.h>
    
    void setup() {
      EEPROM.begin();
    
      // Writing a value
      EEPROM.write(0, 42);
      
      // Writing a complex type using put()
      float myValue = 3.14;
      EEPROM.put(1, myValue);
    
      // Persist changes to Flash
      if (EEPROM.commit()) {
        // Success
      }
    }
    
    void loop() {
      // Reading a value
      uint8_t val = EEPROM.read(0);
    
      // Reading a complex type using get()
      float retrievedValue;
      EEPROM.get(1, retrievedValue);
    }
  8. Troubleshoot CH32 Uploading issues

    main

    Windows

    If you encounter errors during the upload process, ensure that your WCH-LINKE firmware is up to date and consistent with the latest version provided under MRS (MounRiver Studio).

    macOS

    If you encounter libusb related errors after installing the library via Homebrew, contact the MRS team at support@mounriver.com.

    Linux

    Ensure you have run the ./start.sh script in the ~/.arduino15/packages/WCH/tools/beforeinstall/... directory to configure environment rules.

  9. Read and write complex data types

    main

    For types larger than a single byte (e.g., int, float, or custom structs), use get() and put().

    • EEPROM.get(address, variable): Retrieves data of any type from the EEPROM into the provided variable.
    • EEPROM.put(address, variable): Writes data of any type from the variable to the EEPROM RAM buffer. Requires EEPROM.commit() to save.
    float myValue = 3.14;
    int myInt = 100;
    
    // Writing complex types
    EEPROM.put(0, myValue);
    EEPROM.put(sizeof(float), myInt);
    EEPROM.commit();
    
    // Reading complex types
    float readValue;
    int readInt;
    EEPROM.get(0, readValue);
    EEPROM.get(sizeof(float), readInt);
  10. Read and write single bytes

    main

    You can interact with individual bytes using read() and write(), or by using the object as an array via the subscript operator.

    • EEPROM.read(address): Returns the uint8_t value at the specified int address.
    • EEPROM.write(address, value): Writes a uint8_t value to the specified int address in RAM. Requires EEPROM.commit() to save.
    • EEPROM[address]: Subscript operator that allows reading and writing directly to the RAM buffer. Requires EEPROM.commit() to save.
    // Using read/write
    uint8_t val = EEPROM.read(0);
    EEPROM.write(0, val + 1);
    EEPROM.commit();
    
    // Using subscript operator
    uint8_t val2 = EEPROM[0];
    EEPROM[0] = val2 + 1;
    EEPROM.commit();