浏览代码

WCH CH569W-R0-1v0 evt board bsp port, first version (#6167)

WCH CH569W-R0-1v0 evt board bsp port, first version

dev/test under Ubuntu 20.04
toolchain from MounRiver_Studio_Community_Linux_x64_V120

tested drivers : SysTick, gpio, gpio interrupt, uart1 (RX interrupt, TX polling)

libcpu/risc-v/SConscript :
group includes rtconfig.CPU only if folder exists

libcpu/risc-v/common/cpuport.c/rt_hw_context_switch_interrupt() :
make it RT_WEAK for customization
emuzit 2 年之前
父节点
当前提交
c802fcdcf8
共有 33 个文件被更改,包括 5085 次插入3 次删除
  1. 8 1
      bsp/wch/risc-v/Libraries/Kconfig
  2. 28 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript
  3. 399 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c
  4. 216 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.h
  5. 119 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.c
  6. 258 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.h
  7. 249 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c
  8. 395 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.h
  9. 262 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.c
  10. 138 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.h
  11. 343 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c
  12. 254 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h
  13. 241 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_wdt.c
  14. 31 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/isr_sp.h
  15. 152 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h
  16. 190 0
      bsp/wch/risc-v/Libraries/ch56x_drivers/swi_gcc.S
  17. 664 0
      bsp/wch/risc-v/ch569w-evt/.config
  18. 21 0
      bsp/wch/risc-v/ch569w-evt/Kconfig
  19. 13 0
      bsp/wch/risc-v/ch569w-evt/SConscript
  20. 38 0
      bsp/wch/risc-v/ch569w-evt/SConstruct
  21. 13 0
      bsp/wch/risc-v/ch569w-evt/applications/SConscript
  22. 231 0
      bsp/wch/risc-v/ch569w-evt/applications/main.c
  23. 64 0
      bsp/wch/risc-v/ch569w-evt/board/Kconfig
  24. 13 0
      bsp/wch/risc-v/ch569w-evt/board/SConscript
  25. 80 0
      bsp/wch/risc-v/ch569w-evt/board/board.c
  26. 36 0
      bsp/wch/risc-v/ch569w-evt/board/board.h
  27. 199 0
      bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds
  28. 174 0
      bsp/wch/risc-v/ch569w-evt/board/startup_gcc.S
  29. 二进制
      bsp/wch/risc-v/ch569w-evt/figures/ch569w-evt.jpeg
  30. 192 0
      bsp/wch/risc-v/ch569w-evt/rtconfig.h
  31. 62 0
      bsp/wch/risc-v/ch569w-evt/rtconfig.py
  32. 1 1
      libcpu/risc-v/SConscript
  33. 1 1
      libcpu/risc-v/common/cpuport.c

+ 8 - 1
bsp/wch/risc-v/Libraries/Kconfig

@@ -5,4 +5,11 @@ config SOC_RISCV_SERIES_CH32V103
     bool
     select ARCH_RISCV
     select SOC_RISCV_FAMILY_CH32
-    
+
+config SOC_FAMILY_CH56X
+    bool
+    select ARCH_RISCV
+
+config SOC_SERIES_CH569
+    bool
+    select SOC_FAMILY_CH56X

+ 28 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript

@@ -0,0 +1,28 @@
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split("""
+ch56x_sys.c
+swi_gcc.S
+""")
+
+if GetDepend('SOC_SERIES_CH569'):
+    src += ['ch56x_pfic.c']
+    if GetDepend('RT_USING_WDT'):
+        src += ['ch56x_wdt.c']
+
+if GetDepend('RT_USING_HWTIMER'):
+    src += ['ch56x_timer.c']
+
+if GetDepend('RT_USING_PIN'):
+    src += ['ch56x_gpio.c']
+
+if GetDepend(['RT_USING_SERIAL', 'BSP_USING_UART']):
+    src += ['ch56x_uart.c']
+
+path = [cwd]
+
+group = DefineGroup('Drivers', src, depend=[''], CPPPATH=path)
+
+Return('group')

+ 399 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c

@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#include <rthw.h>
+#include <rtdebug.h>
+#include <drivers/pin.h>
+#include "ch56x_gpio.h"
+#include "isr_sp.h"
+
+struct port_info
+{
+    uint32_t pin_mark;
+    struct gpio_px_regs *regbase;
+};
+
+static const struct port_info pin_ports[GPIO_PORTS] =
+{
+    {GPIO_PA_PIN_MARK, (struct gpio_px_regs *)GPIO_REG_BASE_PA},
+    {GPIO_PB_PIN_MARK, (struct gpio_px_regs *)GPIO_REG_BASE_PB},
+};
+
+static struct rt_pin_irq_hdr pin_irq_hdr_table[8] =
+{
+    {-1, 0, RT_NULL, RT_NULL},
+    {-1, 0, RT_NULL, RT_NULL},
+    {-1, 0, RT_NULL, RT_NULL},
+    {-1, 0, RT_NULL, RT_NULL},
+    {-1, 0, RT_NULL, RT_NULL},
+    {-1, 0, RT_NULL, RT_NULL},
+    {-1, 0, RT_NULL, RT_NULL},
+    {-1, 0, RT_NULL, RT_NULL},
+};
+
+
+#if defined(SOC_SERIES_CH569)
+static int _gpio_pin_to_ibit(rt_base_t pin)
+{
+    /* gpio ext interrupt 7-0 : {PB15,PB12,PB11,PB4,PB3,PA4,PA3,PA2}
+     * not time critical, use linear search
+    */
+    switch (pin)
+    {
+    case GET_PIN(A,  2): return 0;
+    case GET_PIN(A,  3): return 1;
+    case GET_PIN(A,  4): return 2;
+    case GET_PIN(B,  3): return 3;
+    case GET_PIN(B,  4): return 4;
+    case GET_PIN(B, 11): return 5;
+    case GET_PIN(B, 12): return 6;
+    case GET_PIN(B, 15): return 7;
+    }
+    return -1;
+}
+
+#else
+
+static int _gpio_pin_to_ibit(rt_base_t pin)
+{
+    /* gpio ext interrupt 7-0 : {PB10,PB4,PA12,PA11,PA10,PA6,PA4,PA3}
+     * not time critical, use linear search
+    */
+    switch (pin)
+    {
+    case GET_PIN(A,  3): return 0;
+    case GET_PIN(A,  4): return 1;
+    case GET_PIN(A,  6): return 2;
+    case GET_PIN(A, 10): return 3;
+    case GET_PIN(A, 11): return 4;
+    case GET_PIN(A, 12): return 5;
+    case GET_PIN(B,  4): return 6;
+    case GET_PIN(B, 10): return 7;
+    }
+    return -1;
+}
+#endif
+
+static struct gpio_px_regs *_gpio_px_regbase(rt_base_t pin)
+{
+    /* fixed linear mapping : 32 pins per port, for ports A,B,C,D...
+    */
+    uint32_t port = (uint32_t)pin >> 5;
+    uint32_t bitpos = 1 << (pin & 0x1f);
+
+    if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
+        return pin_ports[port].regbase;
+    else
+        return RT_NULL;
+}
+
+static void gpio_pin_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode)
+{
+    volatile struct gpio_px_regs *px;
+
+    uint32_t port = (uint32_t)pin >> 5;
+    uint32_t bitpos = 1 << (pin & 0x1f);
+
+    if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
+        px = pin_ports[port].regbase;
+    else
+        return;
+
+    switch (mode)
+    {
+    case PIN_MODE_OUTPUT:
+        BITS_CLR(px->PD,  bitpos);
+        BITS_SET(px->DIR, bitpos);
+        break;
+    case PIN_MODE_INPUT:
+        BITS_CLR(px->PU,  bitpos);
+        BITS_CLR(px->PD,  bitpos);
+        BITS_CLR(px->DIR, bitpos);
+        break;
+    case PIN_MODE_INPUT_PULLUP:
+        BITS_SET(px->PU,  bitpos);
+        BITS_CLR(px->PD,  bitpos);
+        BITS_CLR(px->DIR, bitpos);
+        break;
+    case PIN_MODE_INPUT_PULLDOWN:
+        BITS_CLR(px->PU,  bitpos);
+        BITS_SET(px->PD,  bitpos);
+        BITS_CLR(px->DIR, bitpos);
+        break;
+    case PIN_MODE_OUTPUT_OD:
+        BITS_SET(px->PD,  bitpos);
+        BITS_SET(px->OUT, bitpos);
+    }
+}
+
+static void gpio_pin_write(struct rt_device *device, rt_base_t pin, rt_base_t value)
+{
+    volatile struct gpio_px_regs *px;
+
+    uint32_t port = (uint32_t)pin >> 5;
+    uint32_t bitpos = 1 << (pin & 0x1f);
+
+    if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
+        px = pin_ports[port].regbase;
+    else
+        return;
+
+    if (value == 0)
+        BITS_CLR(px->OUT, bitpos);
+    else
+        BITS_SET(px->OUT, bitpos);
+}
+
+static int gpio_pin_read(struct rt_device *device, rt_base_t pin)
+{
+    volatile struct gpio_px_regs *px;
+
+    uint32_t port = (uint32_t)pin >> 5;
+    uint32_t bitpos = 1 << (pin & 0x1f);
+
+    if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
+        px = pin_ports[port].regbase;
+    else
+        return PIN_LOW;
+
+    return (px->PIN & bitpos) ? PIN_HIGH : PIN_LOW;
+}
+
+static rt_base_t gpio_pin_get(const char *name)
+{
+    int port, pin, sz, n;
+
+    /* pin name is in the form "PX.nn" (X: A,B,C,D...;  nn: 0~31)
+     * fixed linear mapping : 32 pins per port, for ports A,B,C,D...
+    */
+    sz = rt_strlen(name);
+    if ((sz == 4 || sz == 5) && name[0] == 'P' && name[2] == '.')
+    {
+        port = name[1] - 'A';
+        pin  = name[3] - '0';
+        if (0 <= port && port < GPIO_PORTS && 0 <= pin && pin <= 9)
+        {
+            if (sz == 5)
+            {
+                n = name[4] - '0';
+                pin = (0 <= n && n <= 9) ? (pin * 10 + n) : 32;
+            }
+            if (pin < 32 && (pin_ports[port].pin_mark & (1 << pin)))
+            {
+                return port * 32 + pin;
+            }
+        }
+    }
+
+    return -1;
+}
+
+static rt_err_t gpio_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
+                rt_uint32_t mode, void (*hdr)(void *args), void *args)
+{
+    rt_base_t level;
+
+    int ibit;
+
+    switch (mode)
+    {
+    case PIN_IRQ_MODE_RISING:
+    case PIN_IRQ_MODE_FALLING:
+    case PIN_IRQ_MODE_HIGH_LEVEL:
+    case PIN_IRQ_MODE_LOW_LEVEL:
+        break;
+    case PIN_IRQ_MODE_RISING_FALLING:
+        /* hardware not supported */
+    default:
+        return -RT_EINVAL;
+    }
+
+    ibit = _gpio_pin_to_ibit(pin);
+    if (ibit < 0)
+        return -RT_EINVAL;
+
+    level = rt_hw_interrupt_disable();
+    if (pin_irq_hdr_table[ibit].pin  == pin &&
+        pin_irq_hdr_table[ibit].mode == mode &&
+        pin_irq_hdr_table[ibit].hdr  == hdr &&
+        pin_irq_hdr_table[ibit].args == args)
+    {
+        rt_hw_interrupt_enable(level);
+        return RT_EOK;
+    }
+
+    if (pin_irq_hdr_table[ibit].pin >= 0)
+    {
+        rt_hw_interrupt_enable(level);
+        return -RT_EFULL;
+    }
+
+    pin_irq_hdr_table[ibit].pin  = pin;
+    pin_irq_hdr_table[ibit].mode = mode;
+    pin_irq_hdr_table[ibit].hdr  = hdr;
+    pin_irq_hdr_table[ibit].args = args;
+
+    rt_hw_interrupt_enable(level);
+    return RT_EOK;
+}
+
+static rt_err_t gpio_pin_detach_irq(struct rt_device *device, rt_int32_t pin)
+{
+    rt_base_t level;
+
+    int ibit;
+
+    ibit = _gpio_pin_to_ibit(pin);
+    if (ibit < 0)
+        return -RT_EINVAL;
+
+    level = rt_hw_interrupt_disable();
+    if (pin_irq_hdr_table[ibit].pin < 0)
+    {
+        rt_hw_interrupt_enable(level);
+        return RT_EOK;
+    }
+    pin_irq_hdr_table[ibit].pin  = -1;
+    pin_irq_hdr_table[ibit].mode =  0;
+    pin_irq_hdr_table[ibit].hdr  = RT_NULL;
+    pin_irq_hdr_table[ibit].args = RT_NULL;
+    rt_hw_interrupt_enable(level);
+    return RT_EOK;
+}
+
+static rt_err_t gpio_pin_irq_enable(struct rt_device *device, rt_base_t pin,
+                                    rt_uint32_t enabled)
+{
+    volatile struct gpio_registers *gpio;
+
+    rt_base_t level, int_enable;
+
+    int ibit, bitpos;
+
+    ibit = _gpio_pin_to_ibit(pin);
+    if (ibit < 0)
+        return -RT_EINVAL;
+    bitpos = (1 << ibit);
+
+    gpio = (struct gpio_registers *)GPIO_REG_BASE;
+
+    if (enabled == PIN_IRQ_ENABLE)
+    {
+        level = rt_hw_interrupt_disable();
+        if (pin_irq_hdr_table[ibit].pin != pin)
+        {
+            rt_hw_interrupt_enable(level);
+            return -RT_EINVAL;
+        }
+
+        switch (pin_irq_hdr_table[ibit].mode)
+        {
+        case PIN_IRQ_MODE_RISING:
+            BITS_SET(gpio->INT_MODE.reg,  bitpos);
+            BITS_SET(gpio->INT_POLAR.reg, bitpos);
+            break;
+        case PIN_IRQ_MODE_FALLING:
+            BITS_SET(gpio->INT_MODE.reg,  bitpos);
+            BITS_CLR(gpio->INT_POLAR.reg, bitpos);
+            break;
+        case PIN_IRQ_MODE_HIGH_LEVEL:
+            BITS_CLR(gpio->INT_MODE.reg,  bitpos);
+            BITS_SET(gpio->INT_POLAR.reg, bitpos);
+            break;
+        case PIN_IRQ_MODE_LOW_LEVEL:
+            BITS_CLR(gpio->INT_MODE.reg,  bitpos);
+            BITS_CLR(gpio->INT_POLAR.reg, bitpos);
+            break;
+        case PIN_IRQ_MODE_RISING_FALLING:
+        default:
+            rt_hw_interrupt_enable(level);
+            return -RT_EINVAL;
+        }
+
+        /* clear possible pending intr, then enable pin intr */
+        int_enable = gpio->INT_ENABLE.reg;
+        gpio->INT_FLAG.reg = bitpos;
+        gpio->INT_ENABLE.reg = int_enable | bitpos;
+        /* enable GPIO_IRQn if this is the first enabled EXTIx */
+        if (int_enable == 0)
+        {
+            rt_hw_interrupt_umask(GPIO_IRQn);
+        }
+        rt_hw_interrupt_enable(level);
+    }
+    else if (enabled == PIN_IRQ_DISABLE)
+    {
+        level = rt_hw_interrupt_disable();
+        int_enable = gpio->INT_ENABLE.reg;
+        BITS_CLR(int_enable, bitpos);
+        gpio->INT_ENABLE.reg = int_enable;
+        /* disable GPIO_IRQn if no EXTIx enabled */
+        if (int_enable == 0)
+        {
+            rt_hw_interrupt_mask(GPIO_IRQn);
+        }
+        rt_hw_interrupt_enable(level);
+    }
+    else
+    {
+        return -RT_EINVAL;
+    }
+
+    return RT_EOK;
+}
+
+static const struct rt_pin_ops pin_ops =
+{
+    .pin_mode = gpio_pin_mode,
+    .pin_write = gpio_pin_write,
+    .pin_read = gpio_pin_read,
+    .pin_attach_irq = gpio_pin_attach_irq,
+    .pin_detach_irq = gpio_pin_detach_irq,
+    .pin_irq_enable = gpio_pin_irq_enable,
+    .pin_get = gpio_pin_get,
+};
+
+static int rt_hw_pin_init(void)
+{
+    return rt_device_pin_register("pin", &pin_ops, RT_NULL);
+}
+INIT_BOARD_EXPORT(rt_hw_pin_init);
+
+void gpio_irq_handler(void) __attribute__((interrupt()));
+void gpio_irq_handler(void)
+{
+    volatile struct gpio_registers *gpio;
+
+    uint8_t iflags;
+
+    int ibit, bitpos;
+
+    isr_sp_enter();
+    rt_interrupt_enter();
+
+    gpio = (struct gpio_registers *)GPIO_REG_BASE;
+    iflags = gpio->INT_FLAG.reg;
+    /* prioritized as pb15 -> pa2 (CH569), or pb10 -> pa3 */
+    for (ibit = 7; ibit >= 0; ibit--)
+    {
+        bitpos = (1 << ibit);
+        if (iflags & bitpos)
+        {
+            if (pin_irq_hdr_table[ibit].hdr)
+            {
+                pin_irq_hdr_table[ibit].hdr(pin_irq_hdr_table[ibit].args);
+            }
+            /* clear interrupt */
+            gpio->INT_FLAG.reg = bitpos;
+        }
+    }
+
+    rt_interrupt_leave();
+    isr_sp_leave();
+}

+ 216 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.h

@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#ifndef __CH56X_GPIO_H__
+#define __CH56X_GPIO_H__
+
+#include "soc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Fixed linear mapping : 32 pins per port, for ports A,B,C,D...
+*/
+#define GET_PIN(port,pin)       (GPIO_P##port##_PIN_START + pin)
+
+#ifdef SOC_SERIES_CH569
+#define GPIO_INT_PINS { \
+        GET_PIN(A,2), GET_PIN(A,3),  GET_PIN(A,4),  GET_PIN(B,3), \
+        GET_PIN(B,4), GET_PIN(B,11), GET_PIN(B,12), GET_PIN(B,15) \
+        }
+#else
+#define GPIO_INT_PINS { \
+        GET_PIN(A,3),  GET_PIN(A,4),  GET_PIN(A,6), GET_PIN(A,10), \
+        GET_PIN(A,11), GET_PIN(A,12), GET_PIN(B,4), GET_PIN(B,10), \
+        }
+#endif
+
+/*
+ * R8_GPIO_INT_FLAG / R8_GPIO_INT_STATUS (CH567,CH568):
+ *    write 1 to specific bit to clear int flag
+ *
+ * R8_GPIO_INT_ENABLE:
+ *    To use EXTIx function, pin should be set as input.
+ *    For wakeup function, also set RB_SLP_GPIO_WAKE.
+ *
+ * R8_GPIO_INT_MODE:
+ * R8_GPIO_INT_POLAR:
+ */
+#if defined(SOC_SERIES_CH569)
+union _gpio_interrupt
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t pa2  : 1;
+        uint8_t pa3  : 1;
+        uint8_t pa4  : 1;
+        uint8_t pb3  : 1;
+        uint8_t pb4  : 1;
+        uint8_t pb11 : 1;
+        uint8_t pb12 : 1;
+        uint8_t pb15 : 1;
+    };
+};
+
+#else
+
+union _gpio_interrupt
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t pa3  : 1;
+        uint8_t pa4  : 1;
+        uint8_t pa6  : 1;
+        uint8_t pa10 : 1;
+        uint8_t pa11 : 1;
+        uint8_t pa12 : 1;
+        uint8_t pb4  : 1;
+        uint8_t pb10 : 1;
+    };
+};
+#endif
+
+#define GPIO_IE_DISABLE         0
+#define GPIO_IE_ENABLE          1
+
+#define GPIO_IM_LEVEL           0
+#define GPIO_IM_EDGE            1
+
+#define GPIO_IP_LOW_FALLING     0
+#define GPIO_IP_HIGH_RISING     1
+
+/*
+ * R8_PIN_ALTERNATE (CH569)  : reset value is 0x01
+ * R8_PORT_PIN (CH567/CH568) : reset value is 0x00
+ */
+union _gpio_pin_alternate
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t pin_mii   : 1;  // RW, ETH uses RMII/RGMII (CH565W/CH569W)
+        uint8_t pin_tmr1  : 1;  // RW, TMR1/PWM5/CAP1 remapping
+        uint8_t pin_tmr2  : 1;  // RW, TMR2/PWM6/CAP2 remapping
+        uint8_t resv_3    : 1;
+        uint8_t pin_uart0 : 1;  // RW, RXD0/TXD0 remapping
+        uint8_t pin_uart1 : 1;  // RW, CH567 only
+        uint8_t resv_6    : 2;
+    };
+};
+#define RB_PIN_MII              0x01
+#define RB_PIN_TMR1             0x02
+#define RB_PIN_TMR2             0x04
+#define RB_PIN_UART0            0x10
+#define RB_PIN_UART1            0x20
+
+#ifdef SOC_SERIES_CH569
+#define GPIO_ALT_RMII           0
+#define GPIO_ALT_RGMII          1
+#define GPIO_ALT_TMR1_PB15      0
+#define GPIO_ALT_TMR1_PB0       1
+#define GPIO_ALT_TMR2_PA4       0
+#define GPIO_ALT_TMR2_PB3       1
+#define GPIO_ALT_UART0_PB5_6    0
+#define GPIO_ALT_UART0_PA5_6    1
+#else
+#define GPIO_ALT_TMR1_PA10      0
+#define GPIO_ALT_TMR1_PB2       1
+#define GPIO_ALT_TMR2_PA11      0
+#define GPIO_ALT_TMR2_PB11      1
+#define GPIO_ALT_UART0_PB4_7    0
+#define GPIO_ALT_UART0_PA15_14  1
+#define GPIO_ALT_UART1_PA8_9    0
+#define GPIO_ALT_UART1_PB8_9    1
+#endif
+
+struct gpio_px_regs
+{
+    uint32_t  DIR;  // reset value for pins is 0, input pins
+    uint32_t  PIN;  // RO
+    uint32_t  OUT;  // reset value is 0
+    uint32_t  CLR;  // reset value is 0
+    uint32_t  PU;   // reset value is 0
+    uint32_t  PD;   // reset value is 0
+    uint32_t  DRV;  // reset value for pins is 0, 8mA
+    uint32_t  SMT;  // reset value for pins is 1, enable schmitt trigger
+} __packed;
+
+CHECK_STRUCT_SIZE(struct gpio_px_regs, 0x20);
+
+#define GPIO_PX_DIR_IN          0
+#define GPIO_PX_DIR_OUT         1
+
+#define GPIO_PX_PU_DISABLE      0
+#define GPIO_PX_PU_ENABLE       1
+#define GPIO_PX_PD_DISABLE      0  // for DIR_IN
+#define GPIO_PX_PD_ENABLE       1  // for DIR_IN
+#define GPIO_PX_PD_PUSH_PULL    0  // for DIR_OUT
+#define GPIO_PX_PD_OPEN_DRAIN   1  // for DIR_OUT
+
+#define GPIO_PX_DRV_8mA         0
+#define GPIO_PX_DRV_16mA        1
+
+#define GPIO_PX_SMT_DISABLE     0
+#define GPIO_PX_SMT_SLOW        1  // for DIR_OUT
+#define GPIO_PX_SMT_ENABLE      1  // for DIR_IN
+
+/*
+ * 0x12  R8_PIN_ALTERNATE:   GPIO multi-use remapping register
+ * 0x1c  R8_GPIO_INT_FLAG:   GPIO interrupt flag register
+ * 0x1d  R8_GPIO_INT_ENABLE: GPIO interrupt enable register
+ * 0x1e  R8_GPIO_INT_MODE:   GPIO interrupt mode register
+ * 0x1f  R8_GPIO_INT_POLAR:  GPIO interrupt polarity register
+ *
+ * 0x40  R32_PA_DIR:  PA pin direction control
+ * 0x44  R32_PA_PIN:  PA pin input status
+ * 0x48  R32_PA_OUT:  PA pin output register
+ * 0x4c  R32_PA_CLR:  PA pin output clear
+ * 0x50  R32_PA_PU:   PA pin pull-up resistor enable register
+ * 0x54  R32_PA_PD:   PA pin open drain output / input pull-down control
+ * 0x58  R32_PA_DRV:  PA pin output driving capability register
+ * 0x5c  R32_PA_SMT:  PA pin slow output / schmitt trigger input control
+ *
+ * 0x60  R32_PB_DIR:
+ * 0x64  R32_PB_PIN:
+ * 0x68  R32_PB_OUT:
+ * 0x6c  R32_PB_CLR:
+ * 0x70  R32_PB_PU:
+ * 0x74  R32_PB_PD:
+ * 0x78  R32_PB_DRV:
+ * 0x7c  R32_PB_SMT:
+ *
+ * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
+ * Be careful for those with side effect for read.
+ */
+struct gpio_registers
+{
+    uint32_t                    resv_00[4];
+    uint8_t                     resv_10[2];
+    union _gpio_pin_alternate   PIN_ALTERNATE;
+    uint8_t                     resv_13;
+    uint32_t                    resv_14[2];
+    union _gpio_interrupt       INT_FLAG;
+    union _gpio_interrupt       INT_ENABLE;
+    union _gpio_interrupt       INT_MODE;
+    union _gpio_interrupt       INT_POLAR;
+    uint32_t                    resv_20[8];
+    struct gpio_px_regs         PA;
+    struct gpio_px_regs         PB;
+} __packed;
+
+CHECK_STRUCT_SIZE(struct gpio_registers, 0x80);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 119 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.c

@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#include <rthw.h>
+#include <rtdebug.h>
+#include "ch56x_pfic.h"
+#include "ch56x_sys.h"
+#include "isr_sp.h"
+
+void rt_hw_interrupt_mask(int vector)
+{
+    pfic_interrupt_mask(vector);
+}
+
+void rt_hw_interrupt_umask(int vector)
+{
+    pfic_interrupt_umask(vector);
+}
+
+/**
+ * @brief   Trigger software interrupt.
+ */
+void pfic_swi_pendset(void)
+{
+    volatile struct pfic_registers *pfic = (void *)PFIC_REG_BASE;
+    _pfic_ireg_bit_set(pfic, IPSR, SWI_IRQn);
+}
+
+/**
+ * @brief   Clear software interrupt.
+ */
+void pfic_swi_pendreset(void)
+{
+    volatile struct pfic_registers *pfic = (void *)PFIC_REG_BASE;
+    _pfic_ireg_bit_set(pfic, IPRR, SWI_IRQn);
+}
+
+/**
+ * @brief   Write PFIC interrupt configuration register.
+ *
+ * @param   key_bit is (PFIC_CFGR_KEYx + bit_position), one of the following :
+ *          PFIC_CFGR_NMISET / PFIC_CFGR_NMIRESET
+ *          PFIC_CFGR_EXCSET / PFIC_CFGR_EXCRESET
+ *          PFIC_CFGR_PFICRESET
+ *          PFIC_CFGR_SYSRESET
+ *          All others are treated as NEST/HWSTK (B.1/B.0) write.
+ */
+void pfic_cfgr_set(uint32_t key_bit)
+{
+    volatile struct pfic_registers *pfic = (void *)PFIC_REG_BASE;
+    uint32_t u32v;
+
+    switch (key_bit)
+    {
+    case PFIC_CFGR_NMISET:
+    case PFIC_CFGR_NMIRESET:
+    case PFIC_CFGR_EXCSET:
+    case PFIC_CFGR_EXCRESET:
+    case PFIC_CFGR_PFICRESET:
+    case PFIC_CFGR_SYSRESET:
+        pfic->CFGR = key_bit;
+    default:
+        /* B.1/B.0 hold NEST/HWSTK, key ignored */
+        u32v = key_bit & (CFGR_NESTCTRL_MASK | CFGR_HWSTKCTRL_MASK);
+        pfic->CFGR = cfgr_nest_hwstk(u32v);
+    }
+}
+
+/**
+ * @brief   Make SysTick ready, systick/swi irq are enabled.
+ *
+ * @param   count is (HCLK/8) clocks count to generate systick irq.
+ *          if 0 => calculate with current HCLK and RT_TICK_PER_SECOND
+ */
+void systick_init(uint32_t count)
+{
+    volatile struct systick_registers *systick = (void *)SysTick_REG_BASE;
+    volatile struct pfic_registers *pfic = (void *)PFIC_REG_BASE;
+
+    if (count == 0)
+        count = sys_hclk_get() / 8 / RT_TICK_PER_SECOND;
+
+    _pfic_irqn_disable(pfic, SysTick_IRQn);
+    pfic->IPRIOR[SysTick_IRQn] = 0xe0;
+    pfic->IPRIOR[SWI_IRQn] = 0xf0;
+    systick->CTLR.reg = 0;
+    systick->CNTL  = 0;
+    systick->CNTH  = 0;
+    systick->CMPLR = count - 1;
+    systick->CMPHR = 0;
+    systick->CNTFG.cntif = 0;
+    /* enable & reload SysTick, with HCLK/8 */
+    systick->CTLR.reg = RB_STKCTL_STRELOAD | RB_STKCTL_STIE | RB_STKCTL_STE;
+    _pfic_irqn_enable(pfic, SysTick_IRQn);
+    _pfic_irqn_enable(pfic, SWI_IRQn);
+}
+
+void systick_handler(void) __attribute__((interrupt()));
+void systick_handler(void)
+{
+    volatile struct systick_registers *systick;
+
+    isr_sp_enter();
+    rt_interrupt_enter();
+
+    rt_tick_increase();
+    systick = (struct systick_registers *)SysTick_REG_BASE;
+    /* clear count-to-zero flag */
+    systick->CNTFG.cntif = 0;
+
+    rt_interrupt_leave();
+    isr_sp_leave();
+}

+ 258 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.h

@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#ifndef __CH56X_PFIC_H__
+#define __CH56X_PFIC_H__
+
+#include "soc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* IREG: IENR/IRER/IRSR/IPRR, make sure irqn be 12~59
+*/
+#define PFIC_IREG1_MASK     0xfffff000
+#define PFIC_IREG2_MASK     0x0fffffff
+#define PFIC_MAX_IREG_BITS  60
+
+#define _pfic_ireg_bit_get(pfic, IREG, irqn) \
+        ((pfic->IREG[(irqn) >> 5] >> ((irqn) & 0x1f)) & 1)
+
+#define _pfic_ireg_bit_set(pfic, IREG, irqn) \
+        do pfic->IREG[(irqn) >> 5] = 1 << ((irqn) & 0x1f); while(0)
+
+#define _pfic_irqn_enable(pfic, irqn)  _pfic_ireg_bit_set(pfic, IENR, irqn)
+#define _pfic_irqn_disable(pfic, irqn) _pfic_ireg_bit_set(pfic, IRER, irqn)
+
+/* Note: `union _pfic_cfgr` is not used directly in the reg structure */
+union _pfic_cfgr
+{
+    uint32_t reg;
+    struct
+    {
+        uint32_t hwstkctrl  : 1;    // RW, hw stack push/pop control (0:enable)
+        uint32_t nestctrl   : 1;    // RW, nested intr enable control (0:enable)
+        uint32_t nmiset     : 1;    // WO, write 1 to set NMI pending
+        uint32_t nmireset   : 1;    // WO, write 1 to reset NMI pending
+        uint32_t excset     : 1;    // WO, write 1 to set exception pending
+        uint32_t excreset   : 1;    // WO, write 1 to reset exception pending
+        uint32_t pficreset  : 1;    // WO, write 1 to reset PFIC module, auto clear
+        uint32_t sysreset   : 1;    // WO, write 1 for a system reset, auto clear
+        uint32_t resv_8     : 8;
+        uint32_t keycode    : 16;   // WO, write protection keycode
+    };
+};
+#define PFIC_CFGR_KEY1      0xfa05  // for hwstkctrl & nestctrl
+#define PFIC_CFGR_KEY2      0xbcaf  // for nmi & exc set/reset
+#define PFIC_CFGR_KEY3      0xbeef  // for sysreset
+
+#define PFIC_CFGR_NMISET            (PFIC_CFGR_KEY2 << 16 | 1 << 2)
+#define PFIC_CFGR_NMIRESET          (PFIC_CFGR_KEY2 << 16 | 1 << 3)
+#define PFIC_CFGR_EXCSET            (PFIC_CFGR_KEY2 << 16 | 1 << 4)
+#define PFIC_CFGR_EXCRESET          (PFIC_CFGR_KEY2 << 16 | 1 << 5)
+#define PFIC_CFGR_PFICRESET         (1 << 6)
+#define PFIC_CFGR_SYSRESET          (PFIC_CFGR_KEY3 << 16 | 1 << 7)
+
+#define CFGR_HWSTKCTRL_ENABLE       (0 << 0)
+#define CFGR_HWSTKCTRL_DISABLE      (1 << 0)
+#define CFGR_HWSTKCTRL_MASK         (1 << 0)
+#define CFGR_NESTCTRL_ENABLE        (0 << 1)
+#define CFGR_NESTCTRL_DISABLE       (1 << 1)
+#define CFGR_NESTCTRL_MASK          (1 << 1)
+#define cfgr_nest_hwstk(v)          (PFIC_CFGR_KEY1 << 16 | (v))
+
+union _pfic_gisr
+{
+    uint32_t reg;
+    struct
+    {
+        uint32_t neststa    : 8;    // RO, nested interrupt state (0/1/2)
+        uint32_t gactsta    : 1;    // RO, global interrupt active status
+        uint32_t gpendsta   : 1;    // RO, global interrupt pending status
+        uint32_t resv_10    : 22;
+    };
+};
+#define PFIC_NESTSTA_NONE   0
+#define PFIC_NESTSTA_L1     1
+#define PFIC_NESTSTA_L2     2
+
+union _pfic_fiofaddrr
+{
+    uint32_t reg;
+    struct
+    {
+        uint32_t offaddr    : 24;   // RW
+        uint32_t irqid      : 8;    // RW
+    };
+};
+
+union _pfic_sctlr
+{
+    uint32_t reg;
+    struct
+    {
+        uint32_t resv_0         : 1;
+        uint32_t sleeponexit    : 1;  // enter (deep) sleep mode on isr exiting
+        uint32_t sleepdeep      : 1;  // RW, 0/1 for sleep/deep-sleep mode
+        uint32_t wfitowfe       : 1;  // RW, treat WFI as WFE
+        uint32_t sevonpend      : 1;  // RW
+        uint32_t setevent       : 1;  // WO, set event for WFE
+        uint32_t resv_6         : 26;
+    };
+};
+
+/*
+ * 0x000  R32_PFIC_ISR1:        PFIC interrupt enable status (# 12-31)
+ * 0x004  R32_PFIC_ISR2:        PFIC interrupt enable status (# 32-59)
+ * 0x020  R32_PFIC_IPR1:        PFIC interrupt pending status (# 12-31)
+ * 0x024  R32_PFIC_IPR2:        PFIC interrupt pending status (# 32-59)
+ * 0x040  R32_PFIC_ITHRESDR:    PFIC interrupt priority threshold (B.7-4)
+ * 0x044  R32_PFIC_FIBADDRR:    PFIC fast intr base address (B.31-28)
+ * 0x048  R32_PFIC_CFGR:        PFIC interrupt configuration register
+ * 0x04c  R32_PFIC_GISR:        PFIC global interrupt status register
+ * 0x060  R32_PFIC_FIOFADDRR0:  PFIC fast intr 0 offset address (B.23-0)
+ * 0x064  R32_PFIC_FIOFADDRR1:  PFIC fast intr 1 offset address (B.23-0)
+ * 0x068  R32_PFIC_FIOFADDRR2:  PFIC fast intr 2 offset address (B.23-0)
+ * 0x06c  R32_PFIC_FIOFADDRR3:  PFIC fast intr 3 offset address (B.23-0)
+ * 0x100  R32_PFIC_IENR1:       PFIC interrupt enable register (# 12-31)
+ * 0x104  R32_PFIC_IENR2:       PFIC interrupt enable register (# 32-59)
+ * 0x180  R32_PFIC_IRER1:       PFIC interrupt reset register (# 12-31)
+ * 0x184  R32_PFIC_IRER2:       PFIC interrupt reset register (# 32-59)
+ * 0x200  R32_PFIC_IPSR1:       PFIC interrupt pending set register (# 12-31)
+ * 0x204  R32_PFIC_IPSR2:       PFIC interrupt pending set register (# 32-59)
+ * 0x280  R32_PFIC_IPRR1:       PFIC interrupt pending reset register (# 12-31)
+ * 0x284  R32_PFIC_IPRR2:       PFIC interrupt pending reset register (# 32-59)
+ * 0x300  R32_PFIC_IACTR1:      PFIC interrupt active status register (# 12-31)
+ * 0x304  R32_PFIC_IACTR2:      PFIC interrupt active status register (# 32-59)
+ * 0x400  R32_PFIC_IPRIORx:     PFIC interrupt priority registers
+ * 0xd10  R32_PFIC_SCTLR:       PFIC system control register
+ *
+ * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
+ * Be careful for those with side effect for read.
+ */
+struct pfic_registers
+{
+    uint32_t              ISR[2];
+    uint32_t              resv_08[6];
+    uint32_t              IPR[2];
+    uint32_t              resv_28[6];
+    uint32_t              ITHRESDR;
+    uint32_t              FIBADDRR;
+    uint32_t              CFGR;
+    union _pfic_gisr      GISR;
+    uint32_t              resv_50[4];
+    union _pfic_fiofaddrr FIOFADDRR[4];
+    uint32_t              resv_70[36];
+    uint32_t              IENR[2];
+    uint32_t              resv_108[30];
+    uint32_t              IRER[2];
+    uint32_t              resv_188[30];
+    uint32_t              IPSR[2];
+    uint32_t              resv_208[30];
+    uint32_t              IPRR[2];
+    uint32_t              resv_288[30];
+    uint32_t              IACTR[2];
+    uint32_t              resv_308[62];
+    uint8_t               IPRIOR[256];
+    uint32_t              resv_500[516];
+    union _pfic_sctlr     SCTLR;
+} __packed;
+
+CHECK_STRUCT_SIZE(struct pfic_registers, 0xd14);
+
+union _systick_ctlr
+{
+    uint32_t reg;
+    struct
+    {
+        uint32_t ste        : 1;  // RW, systick enable
+        uint32_t stie       : 1;  // RW, systick interrupt enable
+        uint32_t stclk      : 1;  // RW, systick clock source select
+        uint32_t resv_3     : 5;
+        uint32_t streload   : 1;  // W1, write 1 to reload systick
+        uint32_t resv_9     : 23;
+    };
+};
+#define RB_STKCTL_STE       0x001
+#define RB_STKCTL_STIE      0x002
+#define RB_STKCTL_STCLK     0x004
+#define RB_STKCTL_STRELOAD  0x100
+
+#define SYSTICK_SRC_HCLK_8  0
+#define SYSTICK_SRC_HCLK    1
+
+union _systick_cntfg
+{
+    uint32_t reg;
+    struct
+    {
+        uint32_t swie       : 1;  // RW, software interrupt enable
+        uint32_t cntif      : 1;  // RW0, counter dec to 0 (write 0 to clear)
+        uint32_t resv_2     : 30;
+    };
+};
+#define RB_CNTFG_SWIE       0X01
+#define RB_CNTFG_CNTIF      0X02
+
+/*
+ * 0x00  R32_STK_CTLR:   SysTick control register
+ * 0x04  R32_STK_CNTL:   SysTick counter, Lo.32
+ * 0x08  R32_STK_CNTH:   SysTick counter, Hi.32
+ * 0x0c  R32_STK_CMPLR:  SysTick compare-reload register, Lo.32
+ * 0x10  R32_STK_CMPHR:  SysTick compare-reload register, Hi.32
+ * 0x14  R32_STK_CNTFG:  SysTick counter flags
+ *
+ * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
+ * Be careful for those with side effect for read.
+ */
+struct systick_registers
+{
+    union _systick_ctlr   CTLR;
+    uint32_t              CNTL;
+    uint32_t              CNTH;
+    uint32_t              CMPLR;
+    uint32_t              CMPHR;
+    union _systick_cntfg  CNTFG;
+} __packed;
+
+CHECK_STRUCT_SIZE(struct systick_registers, 0x18);
+
+rt_inline void pfic_interrupt_umask(uint8_t irqn)
+{
+    volatile struct pfic_registers *pfic;
+
+    if (irqn < PFIC_MAX_IREG_BITS)
+    {
+        pfic = (void *)PFIC_REG_BASE;
+        _pfic_ireg_bit_set(pfic, IENR, irqn);
+    }
+}
+
+rt_inline void pfic_interrupt_mask(uint8_t irqn)
+{
+    volatile struct pfic_registers *pfic;
+
+    if (irqn < PFIC_MAX_IREG_BITS)
+    {
+        pfic = (void *)PFIC_REG_BASE;
+        _pfic_ireg_bit_set(pfic, IRER, irqn);
+    }
+}
+
+void pfic_swi_pendset(void);
+void pfic_swi_pendreset(void);
+void pfic_cfgr_set(uint32_t key_bit);
+void systick_init(uint32_t count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 249 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c

@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#include <rthw.h>
+#include <rtdebug.h>
+#include "ch56x_sys.h"
+
+rt_inline uint8_t _slp_clk_off0_irqn_bit(uint8_t irqn)
+{
+    uint8_t bitpos;
+
+    switch (irqn)
+    {
+    case TMR0_IRQn:   bitpos = RB_SLP_CLK_TMR0;  break;
+    case TMR1_IRQn:   bitpos = RB_SLP_CLK_TMR1;  break;
+    case TMR2_IRQn:   bitpos = RB_SLP_CLK_TMR2;  break;
+    /* special case to control PWMX clock in irqn way */
+    case PWMX_OFFn:   bitpos = RB_SLP_CLK_PWMX;  break;
+    case UART0_IRQn:  bitpos = RB_SLP_CLK_UART0; break;
+    case UART1_IRQn:  bitpos = RB_SLP_CLK_UART1; break;
+    case UART2_IRQn:  bitpos = RB_SLP_CLK_UART2; break;
+    case UART3_IRQn:  bitpos = RB_SLP_CLK_UART3; break;
+    default:
+        bitpos = 0;
+    }
+
+    return bitpos;
+}
+
+rt_inline uint8_t _slp_clk_off1_irqn_bit(uint8_t irqn)
+{
+    uint8_t bitpos;
+
+    switch (irqn)
+    {
+    case SPI0_IRQn:   bitpos = RB_SLP_CLK_SPI0;  break;
+    case SPI1_IRQn:   bitpos = RB_SLP_CLK_SPI1;  break;
+#if defined(SOC_CH567)
+    case SDC_IRQn:    bitpos = RB_SLP_CLK_SDC;   break;
+    case LED_IRQn:    bitpos = RB_SLP_CLK_LED;   break;
+    case USB0_IRQn:   bitpos = RB_SLP_CLK_USB0;  break;
+    case USB1_IRQn:   bitpos = RB_SLP_CLK_USB1;  break;
+    case ECDC_IRQn:   bitpos = RB_SLP_CLK_ECDC;  break;
+#elif defined(SOC_CH568)
+    case SDC_IRQn:    bitpos = RB_SLP_CLK_SDC;   break;
+    case LED_IRQn:    bitpos = RB_SLP_CLK_LED;   break;
+    case USB1_IRQn:   bitpos = RB_SLP_CLK_USB1;  break;
+    case USB0_IRQn:   bitpos = RB_SLP_CLK_SATA;  break;
+    case ECDC_IRQn:   bitpos = RB_SLP_CLK_ECDC;  break;
+#else
+    case EMMC_IRQn:   bitpos = RB_SLP_CLK_EMMC;  break;
+    case HSPI_IRQn:   bitpos = RB_SLP_CLK_HSPI;  break;
+    case USBHS_IRQn:  bitpos = RB_SLP_CLK_USBHS; break;
+    case USBSS_IRQn:  bitpos = RB_SLP_CLK_USBSS; break;
+    case SerDes_IRQn: bitpos = RB_SLP_CLK_SERD;  break;
+    case DVP_IRQn:    bitpos = RB_SLP_CLK_DVP;   break;
+#endif
+    default:
+        bitpos = 0;
+    }
+
+    return bitpos;
+}
+
+#if defined(SOC_SERIES_CH569)
+rt_inline uint8_t _wake_clk_off_irqn_bit(uint8_t irqn)
+{
+    uint8_t bitpos;
+
+    switch (irqn)
+    {
+    case ETH_IRQn:    bitpos = RB_SLP_CLK_ETH;   break;
+    case ECDC_IRQn:   bitpos = RB_SLP_CLK_ECDC;  break;
+    default:
+        bitpos = 0;
+    }
+
+    return bitpos;
+}
+#endif
+
+/**
+ * @brief   Turn on/off device clock for group clk_off0.
+ *
+ * @param   bits is a bit mask to select corresponding devices.
+ *
+ * @param   off is to turn off the clock (1) or trun on (0).
+ */
+void sys_slp_clk_off0(uint8_t bits, int off)
+{
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+    rt_base_t level;
+    uint8_t u8v;
+
+    u8v = sys->SLP_CLK_OFF0.reg;
+    u8v = off ? (u8v | bits) : (u8v & ~bits);
+    level = rt_hw_interrupt_disable();
+    sys_safe_access_enter(sys);
+    sys->SLP_CLK_OFF0.reg = u8v;
+    sys_safe_access_leave(sys);
+    rt_hw_interrupt_enable(level);
+}
+
+/**
+ * @brief   Turn on/off device clock for group clk_off1.
+ *
+ * @param   bits is a bit mask to select corresponding devices.
+ *
+ * @param   off is to turn off the clock (1) or trun on (0).
+ */
+void sys_slp_clk_off1(uint8_t bits, int off)
+{
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+    rt_base_t level;
+    uint8_t u8v;
+
+    u8v = sys->SLP_CLK_OFF1.reg;
+    u8v = off ? (u8v | bits) : (u8v & ~bits);
+    level = rt_hw_interrupt_disable();
+    sys_safe_access_enter(sys);
+    sys->SLP_CLK_OFF1.reg = u8v;
+    sys_safe_access_leave(sys);
+    rt_hw_interrupt_enable(level);
+}
+
+/**
+ * @brief   Turn on/off device clock, specified by its irq number.
+ *
+ * @param   irqn is the irq number of the target device.
+ *          PWMX does not have irqn, use special PWMX_OFFn number.
+ *
+ * @param   off is to turn off the clock (1) or trun on (0).
+ *
+ * @return  Returns if irqn-device has corresponding clk off bit :
+ *          0 if device not found; otherwise bit position of off0/off1.
+ */
+int sys_clk_off_by_irqn(uint8_t irqn, int off)
+{
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+    uint8_t u8v;
+    size_t offset;
+
+    uint8_t bitpos = 0;
+
+    if (irqn < END_OF_IRQn)
+    {
+        if ((bitpos = _slp_clk_off0_irqn_bit(irqn)) != 0)
+        {
+            offset = offsetof(struct sys_registers, SLP_CLK_OFF0);
+        }
+        else if ((bitpos = _slp_clk_off1_irqn_bit(irqn)) != 0)
+        {
+            offset = offsetof(struct sys_registers, SLP_CLK_OFF1);
+        }
+#if defined(SOC_SERIES_CH569)
+        else if ((bitpos = _wake_clk_off_irqn_bit(irqn)) != 0)
+        {
+            offset = offsetof(struct sys_registers, SLP_WAKE_CTRL);
+        }
+#endif
+        if (bitpos)
+        {
+            volatile uint8_t *cxreg = (void *)sys;
+            rt_base_t level;
+            u8v = cxreg[offset];
+            u8v = off ? (u8v | bitpos) : (u8v & ~bitpos);
+            level = rt_hw_interrupt_disable();
+            sys_safe_access_enter(sys);
+            cxreg[offset] = u8v;
+            sys_safe_access_leave(sys);
+            rt_hw_interrupt_enable(level);
+        }
+    }
+
+    return bitpos;
+}
+
+/**
+ * @brief   Setup HCLK frequency.
+ *
+ * @param   freq is the desired hclk frequency.
+ *          supported : 120/96/80/60/48/40/32/30/15/10/6/3/2 MHz
+ *
+ * @return  Returns 0 if hclk is successfully set.
+ */
+int sys_hclk_set(uint32_t freq)
+{
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+
+    uint8_t plldiv;
+
+    int clksel = -1;
+
+    if (freq >= 30000000)
+    {
+        if (freq <= 120000000)
+        {
+            /* supported : 120/96/80/60/48/40/32/30 MHz */
+            plldiv = 480000000 / freq;  // 30M => 16 & 0xf => 0
+            clksel = RB_CLK_SEL_PLL;
+        }
+    }
+    else if (freq >= 2000000)
+    {
+        /* supported : 15/10/6/3/2 MHz */
+        plldiv = 30000000 / freq;
+        clksel = 0;
+    }
+
+    if (clksel >= 0)
+    {
+        rt_base_t level = rt_hw_interrupt_disable();
+        sys_safe_access_enter(sys);
+        sys->CLK_PLL_DIV.reg = clk_pll_div_wdat(plldiv);
+        sys->CLK_CFG_CTRL.reg = clk_cfg_ctrl_wdat(clksel);
+        sys_safe_access_leave(sys);
+        rt_hw_interrupt_enable(level);
+        clksel = 0;
+    }
+
+    return clksel;
+}
+
+/**
+ * @brief   Get current HCLK frequency.
+ *
+ * @return  Returns current HCLK frequency (Hz).
+ */
+uint32_t sys_hclk_get(void)
+{
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+
+    uint8_t plldiv = sys->CLK_PLL_DIV.pll_div;
+
+    if (sys->CLK_CFG_CTRL.sel_pll == CLK_SEL_PLL_USB_480M)
+    {
+        return plldiv ? 480000000 / plldiv : 30000000;
+    }
+    else
+    {
+        return plldiv ?  30000000 / plldiv : 2000000;
+    }
+}

+ 395 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.h

@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#ifndef __CH56X_SYS_H__
+#define __CH56X_SYS_H__
+
+#include "soc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define sys_safe_access_enter(sys) \
+        do { \
+            sys->SAFE_ACCESS_SIG.reg = SAFE_ACCESS_SIG_1; \
+            sys->SAFE_ACCESS_SIG.reg = SAFE_ACCESS_SIG_2; \
+        } while(0)
+
+#define sys_safe_access_leave(sys) \
+        do sys->SAFE_ACCESS_SIG.reg = 0; while(0)
+
+union _sys_safe_access_sig
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t safe_acc_mode   : 2;  // RO, current safe access, 11b => RWA ok
+        uint8_t resv_2          : 2;
+        uint8_t safe_acc_timer  : 3;  // RO, current safe access time count
+        uint8_t resv_7          : 1;
+    };
+};
+#define RB_SAFE_ACC_MODE        0x03
+#define RB_SAFE_ACC_TIMER       0x70
+
+#define SAFE_ACCESS_SIG_1       0x57
+#define SAFE_ACCESS_SIG_2       0xa8
+
+union _sys_glob_rom_cfg
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t rom_ext_re      : 1;  // RO, allow programmer to read FlashROM
+        uint8_t code_ram_we     : 1;  // RWA, code SRAM writaboe
+        uint8_t rom_data_we     : 1;  // RWA, FlashROM data erasable/writable
+        uint8_t rom_code_we     : 1;  // RWA, FlashROM code erasable/writable
+        uint8_t rom_code_ofs    : 1;  // RWA, FlashROM offset for user code
+        uint8_t resv_5          : 3;
+    };
+};
+#define RB_ROM_EXT_RE           0x01
+#define RB_CODE_RAM_WE          0x02
+#define RB_ROM_DATA_WE          0x04
+#define RB_ROM_CODE_WE          0x08
+#define RB_ROM_CODE_OFS         0x10
+
+#define ROM_CODE_OFS_0x00000    0
+#define ROM_CODE_OFS_0x04000    1
+
+union _sys_rst_boot_stat
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t reset_flag      : 2;  // RO, last reset cause
+        uint8_t cfg_reset_en    : 1;  // RO, external reset pin (#RST) status
+        uint8_t cfg_boot_en     : 1;  // RO, reset as 1
+        uint8_t cfg_debug_en    : 1;  // RO
+        uint8_t boot_loader     : 1;  // RO
+        uint8_t resv_6          : 2;
+    };
+};
+#define RB_RESET_FLAG           0x03
+#define RB_CFG_RESET_EN         0x04
+#define RB_CFG_BOOT_EN          0x08
+#define RB_CFG_DEBUG_EN         0x10
+#define RB_BOOT_LOADER          0x20
+
+#define RESET_FLAG_IS_SOFT      0
+#define RESET_FLAG_IS_POR       1
+#define RESET_FLAG_IS_WDOG      2
+#define RESET_FLAG_IS_RSTPIN    3
+
+union _sys_rst_wdog_ctrl
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t software_reset  : 1;  // WA/WZ, system software reset, auto clear
+#if defined(SOC_SERIES_CH569)
+        uint8_t wdog_rst_en     : 1;  // RWA, enable watchdog overflow to reset
+        uint8_t wdog_int_en     : 1;  // RWA, enable watchdog overflow interrupt
+        uint8_t wdog_int_flag   : 1;  // RW1, watchdog counter overflow
+#else
+        uint8_t resv_2          : 3;
+#endif
+        uint8_t resv_4          : 4;  // RO, B.7-6 must write 01b
+    };
+};
+#define RB_SOFTWARE_RESET       0x01
+#ifdef SOC_SERIES_CH569
+#define RB_WDOG_RST_EN          0x02
+#define RB_WDOG_INT_EN          0x04
+#define RB_WDOG_INT_FLAG        0x08
+#endif
+#define wdog_ctrl_wdat(v)       (0x40 | (v))
+
+union _sys_clk_pll_div
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t pll_div         : 4;  // RWA, min 2
+        uint8_t resv_4          : 4;  // RWA, B.7-6 must write 01b
+    };
+};
+#define clk_pll_div_wdat(div)   (0x40 | (div))
+
+union _sys_clk_cfg_ctrl
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t pll_sleep       : 1;  // RWA, PLL sleep control
+        uint8_t sel_pll         : 1;  // RWA, clock source select
+        uint8_t resv_6          : 6;  // RWA, must write 10b
+    };
+};
+#define RB_CLK_PLL_SLEEP        0x01
+#define RB_CLK_SEL_PLL          0x02
+
+#define CLK_PLL_SLEEP_DISABLE   0
+#define CLK_PLL_SLEEP_ENABLE    1
+#define CLK_SEL_PLL_HSE_30M     0
+#define CLK_SEL_PLL_USB_480M    1
+#define clk_cfg_ctrl_wdat(v)    (0x80 | (v))
+
+union _sys_clk_mod_aux
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t int_125m_en     : 1;  // RWA, USB PHY 125MHz to ETH
+        uint8_t ext_125m_en     : 1;  // RWA, external 125MHz to ETH
+        uint8_t mco_sel_msk     : 2;  // RWA, MCO output select
+        uint8_t mco_en          : 1;  // RWA, MCO output enable
+        uint8_t resv_5          : 3;
+    };
+};
+#define RB_INT_125M_EN          0x01
+#define RB_EXT_125M_EN          0x02
+#define RB_MCO_SEL_MSK          0x0c
+#define RB_MCO_EN               0x10
+
+#define MCO_SEL_MSK_125M        0
+#define MCO_SEL_MSK_25M         1
+#define MCO_SEL_MSK_2_5M        2
+
+/* All bits are RWA (need safe_access_sig), 0/1 : clock on/off
+*/
+union _sys_slp_clk_off0
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t tmr0    : 1;
+        uint8_t tmr1    : 1;
+        uint8_t tmr2    : 1;
+        uint8_t pwmx    : 1;
+        uint8_t uart0   : 1;
+        uint8_t uart1   : 1;
+        uint8_t uart2   : 1;
+        uint8_t uart3   : 1;
+    };
+};
+#define RB_SLP_CLK_TMR0         0x01
+#define RB_SLP_CLK_TMR1         0x02
+#define RB_SLP_CLK_TMR2         0x04
+#define RB_SLP_CLK_PWMX         0x08
+#define RB_SLP_CLK_UART0        0x10
+#define RB_SLP_CLK_UART1        0x20
+#define RB_SLP_CLK_UART2        0x40
+#define RB_SLP_CLK_UART3        0x80
+
+#define SYS_SLP_CLK_ON          0
+#define SYS_SLP_CLK_OFF         1
+
+/* All writable bits are RWA (need safe_access_sig), 0/1 : clock on/off
+*/
+union _sys_slp_clk_off1
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t spi0    : 1;
+        uint8_t spi1    : 1;
+#if defined(SOC_CH567)
+        uint8_t sdc     : 1;
+        uint8_t led     : 1;
+        uint8_t usb0    : 1;
+        uint8_t usb1    : 1;
+        uint8_t resv_6  : 1;
+#elif defined(SOC_CH568)
+        uint8_t sdc     : 1;
+        uint8_t led     : 1;
+        uint8_t resv_4  : 1;
+        uint8_t usb1    : 1;
+        uint8_t sata    : 1;
+        uint8_t ecdc    : 1;
+#else
+        uint8_t emmc    : 1;
+        uint8_t hspi    : 1;
+        uint8_t usbhs   : 1;
+        uint8_t usbss   : 1;
+        uint8_t serd    : 1;
+        uint8_t dvp     : 1;
+#endif
+    };
+};
+#define RB_SLP_CLK_SPI0         0x01
+#define RB_SLP_CLK_SPI1         0x02
+#if defined(SOC_WCH_CH567)
+#define RB_SLP_CLK_SDC          0x04
+#define RB_SLP_CLK_LED          0x08
+#define RB_SLP_CLK_USB0         0x10
+#define RB_SLP_CLK_USB1         0x20
+#define RB_SLP_CLK_ECDC         0x80
+#elif defined(SOC_WCH_CH568)
+#define RB_SLP_CLK_SDC          0x04
+#define RB_SLP_CLK_LED          0x08
+#define RB_SLP_CLK_USB1         0x20
+#define RB_SLP_CLK_SATA         0x40
+#define RB_SLP_CLK_ECDC         0x80
+#else
+#define RB_SLP_CLK_EMMC         0x04
+#define RB_SLP_CLK_HSPI         0x08
+#define RB_SLP_CLK_USBHS        0x10
+#define RB_SLP_CLK_USBSS        0x20
+#define RB_SLP_CLK_SERD         0x40
+#define RB_SLP_CLK_DVP          0x80
+#endif
+
+/* All writable bits are RWA (need safe_access_sig)
+*/
+union _sys_slp_wake_ctrl
+{
+    uint8_t reg;
+    struct
+    {
+#if defined(SOC_WCH_CH567)
+        uint8_t usb0_wake       : 1;
+        uint8_t usb1_wake       : 1;
+        uint8_t resv_2          : 2;
+        uint8_t gpio_wake       : 1;
+        uint8_t resv_5          : 3;
+#elif defined(SOC_WCH_CH568)
+        uint8_t resv_0          : 1;
+        uint8_t usb1_wake       : 1;
+        uint8_t sata_wake       : 1;
+        uint8_t resv_3          : 1;
+        uint8_t gpio_wake       : 1;
+        uint8_t resv_5          : 3;
+#else
+        uint8_t usbhs_wake      : 1;
+        uint8_t usbss_wake      : 1;
+        uint8_t clk_eth         : 1;
+        uint8_t clk_ecdc        : 1;
+        uint8_t gpio_wake       : 1;
+        uint8_t eth_wake        : 1;
+        uint8_t resv_6          : 2;
+#endif
+    };
+};
+#if defined(SOC_WCH_CH567)
+#define RB_SLP_USB0_WAKE        0x01
+#define RB_SLP_USB1_WAKE        0x02
+#define RB_SLP_GPIO_WAKE        0x10
+#elif defined(SOC_WCH_CH568)
+#define RB_SLP_USB1_WAKE        0x02
+#define RB_SLP_SATA_WAKE        0x04
+#define RB_SLP_GPIO_WAKE        0x10
+#else
+#define RB_SLP_USBHS_WAKE       0x01
+#define RB_SLP_USBSS_WAKE       0x02
+#define RB_SLP_CLK_ETH          0x04
+#define RB_SLP_CLK_ECDC         0x08
+#define RB_SLP_GPIO_WAKE        0x10
+#define RB_SLP_ETH_WAKE         0x20
+#endif
+
+union _sys_slp_power_ctrl
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t usbhs_pwrdn     : 1;  // RWA, USBHS power down (0:PWRUP)
+        uint8_t resv_2          : 7;
+    };
+};
+#define RB_SLP_USBHS_PWRDN      0x01
+
+union _sys_serd_ana_cfg1
+{
+    uint16_t reg;
+    struct
+    {
+        uint8_t serd_pll_cfg;         // RWA, reset as 0x5a
+        uint8_t serd_30m_sel    : 1;  // RWA
+        uint8_t serd_dn_tst     : 1;  // RWA
+        uint8_t resv_10         : 6;
+    };
+};
+#define RB_SERD_PLL_CFG         0x0ff
+#define RB_SERD_30M_SEL         0x100
+#define RB_SERD_DN_TST          0x200
+
+union _sys_serd_ana_cfg2
+{
+    uint32_t reg;
+    struct
+    {
+        uint32_t serd_trx_cfg   : 25;  // RWA, reset as 423015h
+        uint32_t resv_25        : 7;
+    };
+};
+#define RB_SERD_TRX_CFG         0x1000000
+
+/*
+ * 0x00  R8_SAFE_ACCESS_SIG: safe access signature register
+ * 0x01  R8_CHIP_ID:         RF, chip ID register
+ * 0x02  R8_SAFE_ACCESS_ID:  RF, read as 02h
+ * 0x03  R8_WDOG_COUNT       RW, watchdog counter
+ * 0x04  R8_GLOB_ROM_CFG:    ROM config register
+ * 0x05  R8_RST_BOOT_STAT:   RO, boot state register
+ * 0x06  R8_RST_WDOG_CTRL:   software reset & watchdog control register
+ * 0x07  R8_GLOB_RESET_KEEP: RW, only power-on-reset can clear this register
+ * 0x08  R8_CLK_PLL_DIV:     RWA, PLL output divisor register
+ * 0x0a  R8_CLK_CFG_CTRL:    RWA, clock config register
+ * 0x0b  R8_CLK_MOD_AUX:     RWA, clock auxiliary register
+ * 0x0c  R8_SLP_CLK_OFF0:    RWA, sleep control register 0
+ * 0x0d  R8_SLP_CLK_OFF1:    RWA, sleep control register 1
+ * 0x0e  R8_SLP_WAKE_CTRL:   RWA, wakeup control register
+ * 0x0f  R8_SLP_POWER_CTRL:  RWA, low power management register
+ * 0x20  R16_SERD_ANA_CFG1:  RWA, SerDes PHY analog param config register 1
+ * 0x24  R32_SERD_ANA_CFG2:  RWA, SerDes PHY analog param config register 2
+ *
+ * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
+ * Be careful for those with side effect for read.
+ */
+struct sys_registers
+{
+    union _sys_safe_access_sig  SAFE_ACCESS_SIG;
+    uint8_t                     CHIP_ID;
+    uint8_t                     SAFE_ACCESS_ID;
+    uint8_t                     WDOG_COUNT;
+    union _sys_glob_rom_cfg     GLOB_ROM_CFG;
+    union _sys_rst_boot_stat    RST_BOOT_STAT;
+    union _sys_rst_wdog_ctrl    RST_WDOG_CTRL;
+    uint8_t                     GLOB_RESET_KEEP;
+    union _sys_clk_pll_div      CLK_PLL_DIV;
+    uint8_t                     resv_9;
+    union _sys_clk_cfg_ctrl     CLK_CFG_CTRL;
+    union _sys_clk_mod_aux      CLK_MOD_AUX;
+    union _sys_slp_clk_off0     SLP_CLK_OFF0;
+    union _sys_slp_clk_off1     SLP_CLK_OFF1;
+    union _sys_slp_wake_ctrl    SLP_WAKE_CTRL;
+    union _sys_slp_power_ctrl   SLP_POWER_CTRL;
+#if defined(SOC_SERIES_CH569)
+    uint32_t                    resv_10[4];
+    union _sys_serd_ana_cfg1    SERD_ANA_CFG1;
+    uint16_t                    resv_22;
+    union _sys_serd_ana_cfg2    SERD_ANA_CFG2;
+#endif
+} __packed;
+
+CHECK_STRUCT_SIZE(struct sys_registers, 0x28);
+
+uint32_t sys_hclk_get(void);
+int  sys_hclk_set(uint32_t freq);
+int  sys_clk_off_by_irqn(uint8_t irqn, int off);
+void sys_slp_clk_off0(uint8_t bits, int off);
+void sys_slp_clk_off1(uint8_t bits, int off);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 262 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.c

@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#include <rthw.h>
+#include <rtdebug.h>
+#include <drivers/hwtimer.h>
+#include "ch56x_sys.h"
+#include "ch56x_timer.h"
+#include "isr_sp.h"
+
+struct hwtimer_device
+{
+    struct rt_hwtimer_device parent;
+    struct rt_hwtimer_info hwtimer_info;
+    volatile struct timer_registers *reg_base;
+    rt_hwtimer_mode_t tmode;
+    irq_number_t irqn;
+    char *name;
+};
+
+#ifdef BSP_USING_TMR0
+static struct hwtimer_device hwtimer_device_0 =
+{
+    .hwtimer_info =
+    {
+        .maxfreq = 80000000,
+        .minfreq = 80000000,
+        .maxcnt  = 0x3ffffff,
+        .cntmode = HWTIMER_CNTMODE_UP,
+    },
+    .reg_base = (struct timer_registers *)TMR0_REG_BASE,
+    .tmode = HWTIMER_MODE_PERIOD,
+    .irqn = TMR0_IRQn,
+    .name = "timer0",
+};
+#endif
+
+#ifdef BSP_USING_TMR1
+static struct hwtimer_device hwtimer_device_1 =
+{
+    .hwtimer_info =
+    {
+        .maxfreq = 80000000,
+        .minfreq = 80000000,
+        .maxcnt  = 0x3ffffff,
+        .cntmode = HWTIMER_CNTMODE_UP,
+    },
+    .reg_base = (struct timer_registers *)TMR1_REG_BASE,
+    .tmode = HWTIMER_MODE_PERIOD,
+    .irqn = TMR1_IRQn,
+    .name = "timer1",
+};
+#endif
+
+#ifdef BSP_USING_TMR2
+static struct hwtimer_device hwtimer_device_2 =
+{
+    .hwtimer_info =
+    {
+        .maxfreq = 80000000,
+        .minfreq = 80000000,
+        .maxcnt  = 0x3ffffff,
+        .cntmode = HWTIMER_CNTMODE_UP,
+    },
+    .reg_base = (struct timer_registers *)TMR2_REG_BASE,
+    .tmode = HWTIMER_MODE_PERIOD,
+    .irqn = TMR2_IRQn,
+    .name = "timer2",
+};
+#endif
+
+static void hwtimer_stop(struct rt_hwtimer_device *timer);
+
+static void hwtimer_init(struct rt_hwtimer_device *timer, uint32_t state)
+{
+    struct hwtimer_device *hwtimer_device = (void *)timer;
+
+    RT_ASSERT(hwtimer_device != RT_NULL);
+
+    /* no resource processing, `state` ignored */
+    hwtimer_stop(timer);
+
+    if (hwtimer_device->irqn != TMR0_IRQn)
+    {
+        hwtimer_device->reg_base->CTRL_DMA.reg = 0;
+    }
+}
+
+static rt_err_t hwtimer_start(struct rt_hwtimer_device *timer, uint32_t cnt, rt_hwtimer_mode_t mode)
+{
+    struct hwtimer_device *hwtimer_device = (void *)timer;
+    volatile struct timer_registers *txreg;
+
+    RT_ASSERT(hwtimer_device != RT_NULL);
+
+    /* hwtimer_device->tmode may be different from timer->mode.
+     * For multi-cycle ONESHOT, tmode is set to PERIOD at hwtimer_start.
+    */
+    hwtimer_device->tmode = mode;
+
+    sys_clk_off_by_irqn(hwtimer_device->irqn, SYS_SLP_CLK_ON);
+    txreg = hwtimer_device->reg_base;
+    txreg->CNT_END = cnt;
+    txreg->CTRL_MOD.reg = RB_TMR_ALL_CLEAR;
+    txreg->CTRL_MOD.reg = RB_TMR_COUNT_EN;
+    txreg->INTER_EN.cyc_end = 1;
+    rt_hw_interrupt_umask(hwtimer_device->irqn);
+
+    return RT_EOK;
+}
+
+static void hwtimer_stop(struct rt_hwtimer_device *timer)
+{
+    struct hwtimer_device *hwtimer_device = (void *)timer;
+    volatile struct timer_registers *txreg;
+
+    RT_ASSERT(hwtimer_device != RT_NULL);
+
+    rt_hw_interrupt_mask(hwtimer_device->irqn);
+    /* note: RB_TMR_COUNT_EN cleared */
+    txreg = hwtimer_device->reg_base;
+    txreg->CTRL_MOD.reg = RB_TMR_ALL_CLEAR;
+    txreg->INTER_EN.reg = 0;
+    sys_clk_off_by_irqn(hwtimer_device->irqn, SYS_SLP_CLK_OFF);
+}
+
+static uint32_t hwtimer_count_get(struct rt_hwtimer_device *timer)
+{
+    struct hwtimer_device *hwtimer_device = (void *)timer;
+
+    RT_ASSERT(hwtimer_device != RT_NULL);
+
+    return hwtimer_device->reg_base->COUNT;
+}
+
+static rt_err_t hwtimer_control(
+    struct rt_hwtimer_device *timer, uint32_t cmd, void *args)
+{
+    struct hwtimer_device *hwtimer_device = (void *)timer;
+    rt_err_t result = RT_EOK;
+
+    RT_ASSERT(hwtimer_device != RT_NULL);
+
+    switch (cmd)
+    {
+    case HWTIMER_CTRL_FREQ_SET:
+        /*  clocking for ch56x timers are fixed to Fsys */
+        if (args == RT_NULL || *(uint32_t *)args != timer->info->minfreq)
+        {
+            result = -RT_EINVAL;
+        }
+        break;
+
+    case HWTIMER_CTRL_STOP:
+    case HWTIMER_CTRL_INFO_GET:
+    case HWTIMER_CTRL_MODE_SET:
+    default:
+        result = -RT_ENOSYS;
+    }
+
+    return result;
+}
+
+static const struct rt_hwtimer_ops hwtimer_ops =
+{
+    .init = hwtimer_init,
+    .start = hwtimer_start,
+    .stop = hwtimer_stop,
+    .count_get = hwtimer_count_get,
+    .control = hwtimer_control,
+};
+
+static int rt_hw_hwtimer_init(void)
+{
+    struct hwtimer_device *devices[3];
+
+    uint32_t Fsys = sys_hclk_get();
+
+    int n = 0;
+
+#ifdef BSP_USING_TMR2
+    devices[n++] = &hwtimer_device_2;
+#endif
+#ifdef BSP_USING_TMR1
+    devices[n++] = &hwtimer_device_1;
+#endif
+#ifdef BSP_USING_TMR0
+    devices[n++] = &hwtimer_device_0;
+#endif
+
+    while (--n >= 0)
+    {
+        struct hwtimer_device *hwtimer_device = devices[n];
+        /* counting frequency is fixed to Fsys */
+        hwtimer_device->hwtimer_info.maxfreq = Fsys;
+        hwtimer_device->hwtimer_info.minfreq = Fsys;
+        hwtimer_device->parent.info = &hwtimer_device->hwtimer_info;
+        hwtimer_device->parent.ops = &hwtimer_ops;
+        rt_device_hwtimer_register(
+            &hwtimer_device->parent, hwtimer_device->name, RT_NULL);
+    }
+    return RT_EOK;
+}
+INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
+
+static void _hwtimer_isr_common(struct hwtimer_device *hwtimer_device)
+{
+    volatile struct timer_registers *txreg = hwtimer_device->reg_base;
+
+    if (txreg->INT_FLAG.cyc_end)
+    {
+        if (hwtimer_device->tmode == HWTIMER_MODE_ONESHOT)
+        {
+            /* disable timer to emulate oneshot */
+            txreg->CTRL_MOD.reg = 0;
+        }
+        rt_device_hwtimer_isr(&hwtimer_device->parent);
+        txreg->INT_FLAG.cyc_end = 1;
+    }
+}
+
+#ifdef BSP_USING_TMR0
+void tmr0_irq_handler(void) __attribute__((interrupt()));
+void tmr0_irq_handler(void)
+{
+    isr_sp_enter();
+    rt_interrupt_enter();
+    _hwtimer_isr_common(&hwtimer_device_0);
+    rt_interrupt_leave();
+    isr_sp_leave();
+}
+#endif
+
+#ifdef BSP_USING_TMR1
+void tmr1_irq_handler(void) __attribute__((interrupt()));
+void tmr1_irq_handler(void)
+{
+    isr_sp_enter();
+    rt_interrupt_enter();
+    _hwtimer_isr_common(&hwtimer_device_1);
+    rt_interrupt_leave();
+    isr_sp_leave();
+}
+#endif
+
+#ifdef BSP_USING_TMR2
+void tmr2_irq_handler(void) __attribute__((interrupt()));
+void tmr2_irq_handler(void)
+{
+    isr_sp_enter();
+    rt_interrupt_enter();
+    _hwtimer_isr_common(&hwtimer_device_2);
+    rt_interrupt_leave();
+    isr_sp_leave();
+}
+#endif

+ 138 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.h

@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#ifndef __CH56X_TIMER_H__
+#define __CH56X_TIMER_H__
+
+#include "soc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+union _timer_ctrl_mod
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t mode_in     : 1;  // B.0 : RW, timer mode setting
+        uint8_t all_clear   : 1;  // B.1 : RW, clear FIFO/count/int-flag
+        uint8_t count_en    : 1;  // B.2 : RW, enable timer module
+        uint8_t out_en      : 1;  // B.3 : RW, timer output enable
+        uint8_t out_polar   : 1;  // B.4 : RW, output polarity for PWM mode
+        uint8_t resv_5      : 1;
+        uint8_t pwm_repeat  : 2;  // B.7-6 : RW, PWM repeat count, 1/4/8/16
+    };
+    struct
+    {
+        uint8_t stuff_0     : 6;
+        uint8_t cap_edge    : 2;  // B.7-6 : RW, capture edge mode
+    };
+};
+#define RB_TMR_MODE_IN      0x01
+#define RB_TMR_ALL_CLEAR    0x02
+#define RB_TMR_COUNT_EN     0x04
+#define RB_TMR_OUT_EN       0x08
+#define RB_TMR_OUT_POLAR    0x10
+#define RB_TMR_CAP_COUNT    0x10
+#define RB_TMR_PWM_REPEAT   0xc0
+#define RB_TMR_CAP_EDGE     0xc0
+
+#define TMR_MODE_TIMER_PWM  0
+#define TMR_MODE_CAP_COUNT  1
+#define TMR_PWM_REPEAT_1    0
+#define TMR_PWM_REPEAT_4    1
+#define TMR_PWM_REPEAT_8    2
+#define TMR_PWM_REPEAT_16   3
+#define TMR_CAP_EDGE_NONE   0
+#define TMR_CAP_EDGE_BOTH   1
+#define TMR_CAP_EDGE_F2F    2
+#define TMR_CAP_EDGE_R2R    3
+
+union _timer_ctrl_dma
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t dma_enable  : 1;  // B.0 : RW, enable DMA
+        uint8_t resv_1      : 1;
+        uint8_t dma_loop    : 1;  // B.2 : RW, enable DMA address looping
+        uint8_t resv_3      : 5;
+    };
+};
+#define RB_TMR_DMA_ENABLE   0x01
+#define RB_TMR_DMA_LOOP     0x04
+
+union _timer_interrupt
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t cyc_end     : 1;  // B.0
+        uint8_t data_act    : 1;  // B.1
+        uint8_t fifo_hf     : 1;  // B.2
+        uint8_t dma_end     : 1;  // B.3
+        uint8_t fifo_ov     : 1;  // B.4
+        uint8_t resv_5      : 3;
+    };
+};
+#define RB_TMR_IX_MASK      0x1f
+#define RB_TMR_IE_CYC_END   0x01  // RW, enable interrupt for timer capture count timeout or PWM cycle end
+#define RB_TMR_IE_DATA_ACT  0x02  // RW, enable interrupt for timer capture input action or PWM trigger
+#define RB_TMR_IE_FIFO_HF   0x04  // RW, enable interrupt for timer FIFO half (capture fifo >=4 or PWM fifo <=3)
+#define RB_TMR_IE_DMA_END   0x08  // RW, enable interrupt for timer1/2 DMA completion
+#define RB_TMR_IE_FIFO_OV   0x10  // RW, enable interrupt for timer FIFO overflow
+
+#define RB_TMR_IF_CYC_END   0x01  // RW1, interrupt flag for timer capture count timeout or PWM cycle end
+#define RB_TMR_IF_DATA_ACT  0x02  // RW1, interrupt flag for timer capture input action or PWM trigger
+#define RB_TMR_IF_FIFO_HF   0x04  // RW1, interrupt flag for timer FIFO half (capture fifo >=4 or PWM fifo <=3)
+#define RB_TMR_IF_DMA_END   0x08  // RW1, interrupt flag for timer1/2 DMA completion
+#define RB_TMR_IF_FIFO_OV   0x10  // RW1, interrupt flag for timer FIFO overflow
+
+/*
+ * 0x00  R8_TMRx_CTRL_MOD:   mode setting register
+ * 0x01  R8_TMRx_CTRL_DMA:   DMA control register
+ * 0x02  R8_TMRx_INTER_EN:   interrupt enable register
+ * 0x06  R8_TMRx_INT_FLAG:   interrupt flag register
+ * 0x07  R8_TMRx_FIFO_COUNT: RO, FIFO count register
+ * 0x08  R32_TMRx_COUNT:     RO, timer current count register
+ * 0x0c  R32_TMRx_CNT_END:   RW, timer count end register
+ * 0x10  R32_TMRx_FIFO:      RO/WO, FIFO data register, LSB 26 bits
+ * 0x14  R32_TMRx_DMA_NOW:   RW, DMA buffer current address, LSB 18 bits
+ * 0x18  R32_TMRx_DMA_BEG:   RW, DMA buffer begin address, LSB 18 bits
+ * 0x1c  R32_TMRx_DMA_END:   RW, DMA buffer end address (exclusive), LSB 18 bits
+ *
+ * Note: DMA related registers (0x10,0x14,0x18,0x1c) are TMR1/2 only
+ *
+ * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
+ * Be careful for those with side effect for read.
+ */
+struct timer_registers
+{
+    union _timer_ctrl_mod   CTRL_MOD;
+    union _timer_ctrl_dma   CTRL_DMA;
+    union _timer_interrupt  INTER_EN;
+    uint8_t                 resv_3[3];
+    union _timer_interrupt  INT_FLAG;
+    uint8_t                 FIFO_COUNT;
+    uint32_t                COUNT;
+    uint32_t                CNT_END;
+    uint32_t                FIFO;
+    uint32_t                DMA_NOW;
+    uint32_t                DMA_BEG;
+    uint32_t                DMA_END;
+} __packed;
+
+CHECK_STRUCT_SIZE(struct timer_registers, 0x20);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 343 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c

@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#include <rthw.h>
+#include <rtdebug.h>
+#include <ipc/completion.h>
+#include <ipc/dataqueue.h>
+#ifdef RT_USING_SERIAL_V2
+    #include <drivers/serial_v2.h>
+#else
+    #include <drivers/serial.h>
+#endif
+#include "ch56x_sys.h"
+#include "ch56x_uart.h"
+#include "isr_sp.h"
+
+#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && \
+    !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3)
+    #error "Please define at least one UARTx"
+#endif
+
+struct serial_device
+{
+    struct rt_serial_device parent;
+    volatile struct uart_registers *reg_base;
+    irq_number_t irqn;
+    char *name;
+};
+
+#ifdef BSP_USING_UART0
+static struct serial_device serial_device_0 =
+{
+    .reg_base = (struct uart_registers *)UART0_REG_BASE,
+    .irqn = UART0_IRQn,
+    .name = "uart0",
+};
+#endif
+
+#ifdef BSP_USING_UART1
+static struct serial_device serial_device_1 =
+{
+    .reg_base = (struct uart_registers *)UART1_REG_BASE,
+    .irqn = UART1_IRQn,
+    .name = "uart1",
+};
+#endif
+
+#ifdef BSP_USING_UART2
+static struct serial_device serial_device_2 =
+{
+    .reg_base = (struct uart_registers *)UART2_REG_BASE,
+    .irqn = UART2_IRQn,
+    .name = "uart2",
+};
+#endif
+
+#ifdef BSP_USING_UART3
+static struct serial_device serial_device_3 =
+{
+    .reg_base = (struct uart_registers *)UART3_REG_BASE,
+    .irqn = UART3_IRQn,
+    .name = "uart3",
+};
+#endif
+
+static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    struct serial_device *serial_device = (struct serial_device *)serial;
+    volatile struct uart_registers *uxreg = serial_device->reg_base;
+
+    union _uart_fcr fcr;
+    union _uart_lcr lcr;
+    uint32_t x;
+
+    x = 10 * sys_hclk_get() / 8 / cfg->baud_rate;
+    x = (x + 5) / 10;
+    uxreg->DL = x;
+    uxreg->DIV = 1;
+
+    lcr.reg = 0;
+    switch (cfg->data_bits)
+    {
+    case DATA_BITS_5:
+        lcr.word_sz = LCR_DATA_BITS_5;
+        break;
+    case DATA_BITS_6:
+        lcr.word_sz = LCR_DATA_BITS_6;
+        break;
+    case DATA_BITS_7:
+        lcr.word_sz = LCR_DATA_BITS_7;
+        break;
+    case DATA_BITS_8:
+    default:
+        lcr.word_sz = LCR_DATA_BITS_8;
+        break;
+    }
+
+    switch (cfg->stop_bits)
+    {
+    case STOP_BITS_2:
+        lcr.stop_bit = LCR_STOP_BITS_2;
+        break;
+    case STOP_BITS_1:
+    default:
+        lcr.stop_bit = LCR_STOP_BITS_1;
+        break;
+    }
+
+    switch (cfg->parity)
+    {
+    case PARITY_ODD:
+        lcr.par_mod = LCR_PARITY_ODD;
+        lcr.par_en = 1;
+        break;
+    case PARITY_EVEN:
+        lcr.par_mod = LCR_PARITY_EVEN;
+        lcr.par_en = 1;
+        break;
+    case PARITY_NONE:
+    default:
+        lcr.par_en = 0;
+        break;
+    }
+    uxreg->LCR.reg = lcr.reg;
+
+    fcr.reg = RB_FCR_FIFO_EN | RB_FCR_RX_FIFO_CLR | RB_FCR_TX_FIFO_CLR;
+    fcr.fifo_trig = UART_1BYTE_TRIG;
+    uxreg->FCR.reg = fcr.reg;
+
+    /* TXD pin output enable */
+    uxreg->IER.txd_en = 1;
+
+    return RT_EOK;
+}
+
+static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *args)
+{
+    struct serial_device *serial_device = (struct serial_device *)serial;
+    volatile struct uart_registers *uxreg = serial_device->reg_base;
+
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_CLR_INT:
+        uxreg->IER.recv_rdy = 0;
+        uxreg->IER.line_stat = 0;
+        uxreg->IER.thr_empty = 0;
+        rt_hw_interrupt_mask(serial_device->irqn);
+        break;
+    case RT_DEVICE_CTRL_SET_INT:
+        uxreg->FCR.fifo_trig = UART_1BYTE_TRIG;
+        uxreg->MCR.int_oe = 1;
+        uxreg->IER.recv_rdy = 1;
+        uxreg->IER.line_stat = 1;
+        if (serial->parent.open_flag & RT_DEVICE_FLAG_INT_TX)
+        {
+            uxreg->IER.thr_empty = 1;
+        }
+        rt_hw_interrupt_umask(serial_device->irqn);
+        break;
+    default:
+        break;
+    }
+
+    return RT_EOK;
+}
+
+static int uart_putc(struct rt_serial_device *serial, char ch)
+{
+    struct serial_device *serial_device = (struct serial_device *)serial;
+    volatile struct uart_registers *uxreg = serial_device->reg_base;
+
+    if (serial->parent.open_flag & RT_DEVICE_FLAG_INT_TX)
+    {
+        if (uxreg->TFC >= UART_FIFO_SIZE)
+            return -1;
+    }
+    else
+    {
+        while (uxreg->TFC >= UART_FIFO_SIZE)
+        {
+            if (rt_thread_self() && rt_interrupt_get_nest() == 0)
+                rt_thread_yield();
+        }
+    }
+    uxreg->THR = ch;
+
+    return 1;
+}
+
+static int uart_getc(struct rt_serial_device *serial)
+{
+    struct serial_device *serial_device = (struct serial_device *)serial;
+    volatile struct uart_registers *uxreg = serial_device->reg_base;
+
+    /* UART_II_RECV_RDY is cleared by reading RBR */
+    return (uxreg->RFC > 0) ? uxreg->RBR : -1;
+}
+
+static const struct rt_uart_ops uart_ops =
+{
+    .configure = uart_configure,
+    .control = uart_control,
+    .putc = uart_putc,
+    .getc = uart_getc,
+    .dma_transmit = RT_NULL,
+};
+
+int rt_hw_uart_init(void)
+{
+    struct serial_device *devices[4];
+
+    /* Note: HCLK should be at least 8MHz for default 115200 baud to work */
+    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+    int n = 0;
+
+#ifdef BSP_USING_UART3
+    devices[n++] = &serial_device_3;
+#endif
+#ifdef BSP_USING_UART2
+    devices[n++] = &serial_device_2;
+#endif
+#ifdef BSP_USING_UART1
+    devices[n++] = &serial_device_1;
+#endif
+#ifdef BSP_USING_UART0
+    devices[n++] = &serial_device_0;
+#endif
+
+    /* IMPORTANT: pin mode should be set properly @ board init */
+
+    while (--n >= 0)
+    {
+        uint32_t flag;
+        struct serial_device *serial = devices[n];
+        serial->parent.ops = &uart_ops;
+        serial->parent.config = config;
+
+        sys_clk_off_by_irqn(serial->irqn, SYS_SLP_CLK_ON);
+
+        flag = RT_DEVICE_FLAG_RDWR   |
+               RT_DEVICE_FLAG_STREAM |  // for converting '\n'
+               RT_DEVICE_FLAG_INT_TX |
+               RT_DEVICE_FLAG_INT_RX ;
+        rt_hw_serial_register(&serial->parent, serial->name, flag, RT_NULL);
+
+        /* rt_serial_open => uart_control with RT_DEVICE_CTRL_SET_INT */
+    }
+
+    return 0;
+}
+
+static void _uart_isr_common(struct serial_device *serial_device)
+{
+    struct rt_serial_device *serial = &serial_device->parent;
+    volatile struct uart_registers *uxreg = serial_device->reg_base;
+
+    switch (uxreg->IIR.int_mask)
+    {
+    case UART_II_RECV_TOUT:
+        /* FIXME: It's a bad idea to read RBR to clear UART_II_RECV_TOUT.
+         * Race condition may happen that actual rx data is dropped.
+        */
+        if (uxreg->RFC == 0)
+        {
+            uxreg->RBR;
+            //rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_TIMEOUT);
+            break;
+        }
+        /* pass through as if UART_II_RECV_RDY */
+    case UART_II_RECV_RDY:
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+        break;
+    case UART_II_THR_EMPTY:
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
+        break;
+    case UART_II_LINE_STAT:
+        uxreg->LSR;
+        break;
+    case UART_II_MODEM_CHG:
+        uxreg->MSR;
+        break;
+    case UART_II_SLV_ADDR:
+        uxreg->IIR;
+        break;
+    default:
+        break;
+    }
+}
+
+#ifdef BSP_USING_UART0
+void uart0_irq_handler(void) __attribute__((interrupt()));
+void uart0_irq_handler(void)
+{
+    isr_sp_enter();
+    rt_interrupt_enter();
+    _uart_isr_common(&serial_device_0);
+    rt_interrupt_leave();
+    isr_sp_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART1
+void uart1_irq_handler(void) __attribute__((interrupt()));
+void uart1_irq_handler(void)
+{
+    isr_sp_enter();
+    rt_interrupt_enter();
+    _uart_isr_common(&serial_device_1);
+    rt_interrupt_leave();
+    isr_sp_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART2
+void uart2_irq_handler(void) __attribute__((interrupt()));
+void uart2_irq_handler(void)
+{
+    isr_sp_enter();
+    rt_interrupt_enter();
+    _uart_isr_common(&serial_device_2);
+    rt_interrupt_leave();
+    isr_sp_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART3
+void uart3_irq_handler(void) __attribute__((interrupt()));
+void uart3_irq_handler(void)
+{
+    isr_sp_enter();
+    rt_interrupt_enter();
+    _uart_isr_common(&serial_device_3);
+    rt_interrupt_leave();
+    isr_sp_leave();
+}
+#endif

+ 254 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h

@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#ifndef __CH56X_UART_H__
+#define __CH56X_UART_H__
+
+#include "soc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef UART_FIFO_SIZE
+#define UART_FIFO_SIZE      8
+#endif
+
+#ifndef UART_RECV_RDY_SZ
+#define UART_RECV_RDY_SZ    7    // FIFO trigger level for rx data available
+#endif
+
+union _uart_mcr
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t dtr         : 1;  // B.0 : RW, DTR output (UART0 only)
+        uint8_t rts         : 1;  // B.1 : RW, RTS output (UART0 only)
+        uint8_t out1        : 1;  // B.2 : RW, user defined modem control (UART0 only)
+        uint8_t int_oe      : 1;  // B.3 : RW, interrupt output enable / OUT2
+        uint8_t loop        : 1;  // B.4 : RW, enable internal loop test (UART0 only)
+        uint8_t au_flow_en  : 1;  // B.5 : RW, enable CTS/RTS autoflow control
+        uint8_t tnow        : 1;  // B.6 : RW, enable DTR TNOW output (UART0 only)
+        uint8_t half        : 1;  // B.7 : RW, enable half-duplex mode (UART0 only)
+    };
+};
+#define RB_MCR_DTR          0x01
+#define RB_MCR_RTS          0x02
+#define RB_MCR_OUT1         0x04
+#define RB_MCR_OUT2         0x08
+#define RB_MCR_INT_OE       0x08
+#define RB_MCR_LOOP         0x10
+#define RB_MCR_AU_FLOW_EN   0x20
+#define RB_MCR_TNOW         0x40
+#define RB_MCR_HALF         0x80
+
+union _uart_ier
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t recv_rdy    : 1;  // B.0 : RW, enable rx data ready intr
+        uint8_t thr_empty   : 1;  // B.1 : RW, enable THR empty intr
+        uint8_t line_stat   : 1;  // B.2 : RW, enable rx line status intr
+        uint8_t modem_chg   : 1;  // B.3 : RW, enable modem status change intr (UART0 only)
+        uint8_t dtr_en      : 1;  // B.4 : RW, DTR/TNOW output pin enable (UART0 only)
+        uint8_t rts_en      : 1;  // B.5 : RW, RTS output pin enable (UART0 only)
+        uint8_t txd_en      : 1;  // B.6 : RW, TXD pin enable
+        uint8_t reset       : 1;  // B.7 : WZ, software reset control, active high, auto clear
+    };
+};
+#define RB_IER_RECV_RDY     0x01
+#define RB_IER_THR_EMPTY    0x02
+#define RB_IER_LINE_STAT    0x04
+#define RB_IER_MODEM_CHG    0x08
+#define RB_IER_DTR_EN       0x10
+#define RB_IER_RTS_EN       0x20
+#define RB_IER_TXD_EN       0x40
+#define RB_IER_RESET        0x80
+
+union _uart_fcr
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t fifo_en     : 1;  // B.0   : RW, FIFO enable
+        uint8_t rx_fifo_clr : 1;  // B.1   : WZ, write 1 to clear rx FIFO, auto clear
+        uint8_t tx_fifo_clr : 1;  // B.2   : WZ, write 1 to clear tx FIFO, auto clear
+        uint8_t resv_3      : 3;
+        uint8_t fifo_trig   : 2;  // B.7-6 : RW, rx FIFO trigger level, 1/2/4/7 bytes
+    };
+};
+#define RB_FCR_FIFO_EN      0x01
+#define RB_FCR_RX_FIFO_CLR  0x02
+#define RB_FCR_TX_FIFO_CLR  0x04
+#define RB_FCR_FIFO_TRIG    0xc0
+
+#define UART_1BYTE_TRIG     0
+#define UART_2BYTE_TRIG     1
+#define UART_4BYTE_TRIG     2
+#define UART_7BYTE_TRIG     3
+
+union _uart_lcr
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t word_sz     : 2;  // B.1-0 : RW, word bit length, 5/6/7/8 bits
+        uint8_t stop_bit    : 1;  // B.2   : RW, stop bit length, 1/2 bits
+        uint8_t par_en      : 1;  // B.3   : RW, parity enable
+        uint8_t par_mod     : 2;  // B.5-4 : RW, parity mode, odd/even/mark/space
+        uint8_t break_en    : 1;  // B.6   : RW, force BREAK line condition
+        uint8_t dlab        : 1;  // B.7   : RW, user defined general purpose bit
+    };
+};
+#define RB_LCR_WORD_SZ      0x03
+#define RB_LCR_STOP_BIT     0x04
+#define RB_LCR_PAR_EN       0x08
+#define RB_LCR_PAR_MOD      0x30
+#define RB_LCR_BREAK_EN     0x40
+#define RB_LCR_DLAB         0x80
+#define RB_LCR_GP_BIT       0x80
+
+#define LCR_DATA_BITS_5     0
+#define LCR_DATA_BITS_6     1
+#define LCR_DATA_BITS_7     2
+#define LCR_DATA_BITS_8     3
+
+#define LCR_STOP_BITS_1     0
+#define LCR_STOP_BITS_2     1
+
+#define LCR_PARITY_ODD      0
+#define LCR_PARITY_EVEN     1
+#define LCR_PARITY_MARK     2
+#define LCR_PARITY_SPACE    3
+
+union _uart_iir
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t int_mask    : 4;  // B.3-0 : RO, interrupt mask (intr if B.0 is 0)
+        uint8_t resv_4      : 2;
+        uint8_t fifo_id     : 2;  // B.7-6 : RO, FIFO enabled flag
+    };
+};
+#define RB_IIR_NO_INT       0x01
+#define RB_IIR_INT_MASK     0x0f
+#define RB_IIR_FIFO_ID      0xc0
+
+/* RB_IIR_INT_MASK (IIR bits 3:0) definition
+*/
+#define UART_II_SLV_ADDR    0x0e  // UART0 slave address match interrupt
+#define UART_II_LINE_STAT   0x06  // rx line status interrupt
+#define UART_II_RECV_RDY    0x04  // rx data available interrupt
+#define UART_II_RECV_TOUT   0x0c  // rx fifo timeout interrupt
+#define UART_II_THR_EMPTY   0x02  // THR empty interrupt
+#define UART_II_MODEM_CHG   0x00  // UART0 modem status change interrupt
+#define UART_II_NO_INTER    0x01  // no interrupt pending
+
+union _uart_lsr
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t data_rdy    : 1;  // B.0 : RO, rx FIFO data ready
+        uint8_t over_err    : 1;  // B.1 : RZ, rx FIFO data overrun
+        uint8_t par_err     : 1;  // B.2 : RZ, rx parity error
+        uint8_t frame_err   : 1;  // B.3 : RZ, rx frame error
+        uint8_t break_err   : 1;  // B.4 : RZ, rx BREAK detected
+        uint8_t tx_fifo_emp : 1;  // B.5 : RO, tx FIFO empty
+        uint8_t tx_all_emp  : 1;  // B.6 : RO, THR/TSR all empty
+        uint8_t err_rx_fifo : 1;  // B.7 : RO, PAR/FRAME/BREAK ERR in rx FIFO
+    };
+};
+#define RB_LSR_DATA_RDY     0x01
+#define RB_LSR_OVER_ERR     0x02
+#define RB_LSR_PAR_ERR      0x04
+#define RB_LSR_FRAME_ERR    0x08
+#define RB_LSR_BREAK_ERR    0x10
+#define RB_LSR_TX_FIFO_EMP  0x20
+#define RB_LSR_TX_ALL_EMP   0x40
+#define RB_LSR_ERR_RX_FIFO  0x80
+
+union _uart_msr
+{
+    uint8_t reg;
+    struct
+    {
+        uint8_t cts_chg     : 1;  // B.0 : RZ, CTS input changed
+        uint8_t dsr_chg     : 1;  // B.1 : RZ, DSR input changed
+        uint8_t ri_chg      : 1;  // B.2 : RZ, RI  input changed
+        uint8_t dcd_chg     : 1;  // B.3 : RZ, DCD input changed
+        uint8_t cts         : 1;  // B.4 : RO, CTS action status
+        uint8_t dsr         : 1;  // B.5 : RO, DSR action status
+        uint8_t ri          : 1;  // B.6 : RO, RI  action status
+        uint8_t dcd         : 1;  // B.7 : RO, DCD action status
+    };
+};
+#define RB_MSR_CTS_CHG      0x01
+#define RB_MSR_DSR_CHG      0x02
+#define RB_MSR_RI_CHG       0x04
+#define RB_MSR_DCD_CHG      0x08
+#define RB_MSR_CTS          0x10
+#define RB_MSR_DSR          0x20
+#define RB_MSR_RI           0x40
+#define RB_MSR_DCD          0x80
+
+/*
+ * 0x00  R8_UARTx_MCR:  Modem Control Register
+ * 0x01  R8_UARTx_IER:  Interrupt Enable Register
+ * 0x02  R8_UARTx_FCR:  FIFO Control Register
+ * 0x03  R8_UARTx_LCR:  Line Control Register
+ * 0x04  R8_UARTx_IIR:  Interrupt Identification Register
+ * 0x05  R8_UARTx_LSR:  Line Status Register
+ * 0x06  R8_UARTx_MSR:  Modem Status Register (UART0 only)
+ * 0x08  R8_UARTx_RBR:  Rx Buffer Register
+ * 0x08  R8_UARTx_THR:  Tx Hold Register
+ * 0x0a  R8_UARTx_RFC:  Rx FIFO count register
+ * 0x0b  R8_UARTx_TFC:  Tx FIFO count register
+ * 0x0c  R16_UARTx_DL:  Divisor Latch
+ * 0x0e  R8_UARTx_DIV:  frequency pre divider
+ * 0x0f  R8_UARTx_ADR:  Address Register (UART0 only)
+ *
+ * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
+ * Be careful for those with side effect for read (e.g. RBR, IIR).
+ */
+struct uart_registers
+{
+    union _uart_mcr MCR;
+    union _uart_ier IER;
+    union _uart_fcr FCR;
+    union _uart_lcr LCR;
+    union _uart_iir IIR;
+    union _uart_lsr LSR;
+    union _uart_lsr MSR;
+    uint8_t         resv_7;
+    union
+    {
+        uint8_t     RBR;
+        uint8_t     THR;
+    };
+    uint8_t         resv_9;
+    uint8_t         RFC;
+    uint8_t         TFC;
+    uint16_t        DL;
+    uint8_t         DIV;
+    uint8_t         ADR;
+} __packed;
+
+CHECK_STRUCT_SIZE(struct uart_registers, 0x10);
+
+int rt_hw_uart_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 241 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_wdt.c

@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-20     Emuzit            first version
+ */
+#include <rthw.h>
+#include <rtdebug.h>
+#include <drivers/watchdog.h>
+#include "ch56x_sys.h"
+
+#define WDOG_HICOUNT_MAX    0xfff  // enough to hold (4095 * 120M/524288) >> 8
+
+struct watchdog_device
+{
+    rt_watchdog_t parent;
+    volatile uint32_t hicount;
+    uint32_t timeout;
+    uint32_t reload;
+    uint8_t is_start;
+};
+
+static struct watchdog_device watchdog_device;
+
+static void wdt_reload_counter(rt_watchdog_t *wdt, int cmd)
+{
+    struct watchdog_device *wdt_dev = (void *)wdt;
+
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+
+    rt_base_t level;
+
+    level = rt_hw_interrupt_disable();
+    /* reload WDOG_COUNT also clears RB_WDOG_INT_FLAG*/
+    sys->WDOG_COUNT = (uint8_t)wdt_dev->reload;
+    wdt_dev->hicount = wdt_dev->reload >> 8;
+    if (cmd != RT_DEVICE_CTRL_WDT_KEEPALIVE && wdt_dev->is_start)
+    {
+        sys_safe_access_enter(sys);
+        if ((wdt_dev->reload >> 8) == WDOG_HICOUNT_MAX)
+        {
+            /* WDOG_COUNT can work on its own, no wdog_irq needed */
+            sys->RST_WDOG_CTRL.reg = wdog_ctrl_wdat(RB_WDOG_RST_EN);
+            rt_hw_interrupt_mask(WDOG_IRQn);
+        }
+        else
+        {
+            /* Extend wdt with wdt_dev->hicount through wdog_irq.
+             * CAVEAT: wdt not effective if global interrupt disabled !!
+            */
+            sys->RST_WDOG_CTRL.reg = wdog_ctrl_wdat(RB_WDOG_INT_EN);
+            rt_hw_interrupt_umask(WDOG_IRQn);
+        }
+        sys_safe_access_leave(sys);
+    }
+    rt_hw_interrupt_enable(level);
+}
+
+static uint32_t wdt_get_timeleft(rt_watchdog_t *wdt)
+{
+    struct watchdog_device *wdt_dev = (void *)wdt;
+
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+
+    uint32_t countleft;
+    uint64_t count64;
+
+    if ((wdt_dev->reload >> 8) == WDOG_HICOUNT_MAX)
+    {
+        /* WDOG_COUNT can work on its own, without hicount */
+        countleft = 0xff - sys->WDOG_COUNT;
+    }
+    else
+    {
+        uint32_t c1 = sys->WDOG_COUNT;
+        uint32_t hc = wdt_dev->hicount;
+        uint32_t c2 = sys->WDOG_COUNT;
+        /* check if WDOG_COUNT overflows between c1/c2 reads */
+        if (c2 < c1)
+        {
+            rt_base_t level = rt_hw_interrupt_disable();
+            hc = wdt_dev->hicount;
+            if (sys->RST_WDOG_CTRL.wdog_int_flag && sys->RST_WDOG_CTRL.wdog_int_en)
+            {
+                hc++;
+            }
+            rt_hw_interrupt_enable(level);
+        }
+        countleft = ((WDOG_HICOUNT_MAX << 8) + 0xff) - ((hc << 8) + c2);
+    }
+
+    /* convert wdt count to seconds : count / (Fsys/524288) */
+    count64 = countleft;
+    return (uint32_t)((count64 << 19) / sys_hclk_get());
+}
+
+static uint32_t _convert_timeout_to_reload(uint32_t seconds)
+{
+    uint32_t N, R, Fsys, reload = -1;
+
+    /* timeout is limited to 4095, not to overflow 32-bit (T * 2^19) */
+    if (seconds < 4096)
+    {
+        /* watchdog timer is clocked at Fsys/524288, arround 3~228Hz */
+        Fsys = sys_hclk_get();
+        /* T * (Fsys/2^19) => (T * N) + T * (R/2^19) */
+        N = Fsys >> 19;
+        R = Fsys & 0x7ffff;
+        reload = (WDOG_HICOUNT_MAX << 8) + 0xff;
+        reload -= seconds * N + ((seconds * R) >> 19) + 1;
+    }
+
+    return reload;
+}
+
+static void _stop_wdog_operation()
+{
+    volatile struct sys_registers *sys = (void *)SYS_REG_BASE;
+
+    rt_base_t level = rt_hw_interrupt_disable();
+    sys_safe_access_enter(sys);
+    sys->RST_WDOG_CTRL.reg = wdog_ctrl_wdat(RB_WDOG_INT_FLAG);
+    sys_safe_access_leave(sys);
+    rt_hw_interrupt_enable(level);
+
+    rt_hw_interrupt_mask(WDOG_IRQn);
+}
+
+static rt_err_t wdt_init(rt_watchdog_t *wdt)
+{
+    struct watchdog_device *wdt_dev = (void *)wdt;
+
+    _stop_wdog_operation();
+    wdt_dev->is_start = 0;
+    wdt_dev->timeout = -1;
+    wdt_dev->reload = -1;
+
+    return RT_EOK;
+}
+
+static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
+{
+    struct watchdog_device *wdt_dev = (void *)wdt;
+
+    uint32_t reload, timeout;
+
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_WDT_KEEPALIVE:
+        wdt_reload_counter(wdt, cmd);
+        break;
+    case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
+        *((uint32_t *)arg) = wdt_get_timeleft(wdt);
+        break;
+    case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
+        *((uint32_t *)arg) = wdt_dev->timeout;
+        break;
+    case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
+        /* CAVEAT: Setting timeout larger than an 8-bit WDOG_COUNT can
+         * hold turns the wdog into interrupt mode, which makes wdog
+         * usless if cause of death is lost global interrupt enable.
+        */
+        timeout = *((uint32_t *)arg);
+        reload = _convert_timeout_to_reload(timeout);
+        if ((reload >> 8) > WDOG_HICOUNT_MAX)
+        {
+            return -RT_EINVAL;
+        }
+        wdt_dev->timeout = timeout;
+        wdt_dev->reload = reload;
+        /* FIXME: code example implies wdt started by SET_TIMEOUT ? */
+    case RT_DEVICE_CTRL_WDT_START:
+        if ((wdt_dev->reload >> 8) > WDOG_HICOUNT_MAX)
+        {
+            return -RT_EINVAL;
+        }
+        wdt_dev->is_start = 1;
+        wdt_reload_counter(wdt, cmd);
+        break;
+    case RT_DEVICE_CTRL_WDT_STOP:
+        _stop_wdog_operation();
+        wdt_dev->is_start = 0;
+        break;
+    default:
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+static struct rt_watchdog_ops watchdog_ops =
+{
+    .init = wdt_init,
+    .control = wdt_control,
+};
+
+int rt_hw_wdt_init(void)
+{
+    rt_uint32_t flag;
+
+    watchdog_device.parent.ops = &watchdog_ops;
+
+    flag = RT_DEVICE_FLAG_DEACTIVATE;
+    return rt_hw_watchdog_register(&watchdog_device.parent, "wdt", flag, RT_NULL);
+}
+INIT_BOARD_EXPORT(rt_hw_wdt_init);
+
+void wdog_irq_handler(void) __attribute__((interrupt()));
+void wdog_irq_handler(void)
+{
+    volatile struct pfic_registers *pfic;
+    volatile struct sys_registers *sys;
+
+    rt_interrupt_enter();
+
+    sys = (struct sys_registers *)SYS_REG_BASE;
+    /* FIXME: RB_WDOG_INT_FLAG seems completely not functioning at all !!
+     * It's not set at WDOG_COUNT overflow, writing 1 to it does not clear
+     * wdt interrupt. Bit 16 of pfic->IPR[0] is not effective thereof.
+    */
+    if (watchdog_device.hicount < WDOG_HICOUNT_MAX)
+    {
+        watchdog_device.hicount++;
+        /* clear interrupt flag */
+        //sys->RST_WDOG_CTRL.reg |= RB_WDOG_INT_FLAG;
+        sys->WDOG_COUNT = sys->WDOG_COUNT;
+    }
+    else
+    {
+        /* reset system if watchdog timeout */
+        uint8_t u8v = RB_SOFTWARE_RESET | RB_WDOG_INT_FLAG;
+        sys_safe_access_enter(sys);
+        sys->RST_WDOG_CTRL.reg = wdog_ctrl_wdat(u8v);
+        sys_safe_access_leave(sys);
+    }
+
+    rt_interrupt_leave();
+}

+ 31 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/isr_sp.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-27     Emuzit            first version
+ */
+#ifndef __ISR_SP_H__
+#define __ISR_SP_H__
+
+/* usrstack is no more in use right after rt_system_scheduler_start().
+ * It is also the time global interrupt is enabled.
+*/
+#define isr_sp_enter() \
+        asm("la   t0, rt_interrupt_nest"); \
+        asm("bnez t0, 1f"); \
+        asm("la   t0, _eusrstack"); \
+        asm("sw   sp, -4(t0)"); \
+        asm("addi sp, t0, -4"); \
+        asm("1:")
+
+#define isr_sp_leave() \
+        asm("la   t0, rt_interrupt_nest"); \
+        asm("bnez t0, 1f"); \
+        asm("la   t0, _eusrstack"); \
+        asm("lw   sp, -4(t0)"); \
+        asm("1:")
+
+#endif

+ 152 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h

@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#ifndef __SOC_H__
+#define __SOC_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+
+#if !defined(SOC_CH567) && \
+    !defined(SOC_CH568) && \
+    !defined(SOC_SERIES_CH569)
+#define SOC_SERIES_CH569
+#endif
+
+#define CHECK_STRUCT_SIZE(s, size) \
+        static_assert(sizeof(s) == size, #s " has wrong size")
+
+#define BITS_SET(x, bits)   do x |=  bits; while(0)
+#define BITS_CLR(x, bits)   do x &= ~bits; while(0)
+
+#define FLASH_BASE_ADDRESS  0x00000000
+#define RAMS_BASE_ADDRESS   0x20000000
+#define RAMX_BASE_ADDRESS   0x20020000
+#define BUS8_BASE_ADDRESS   0x80000000
+
+#ifdef SOC_SERIES_CH569
+#define RAMS_SIZE           16
+#else
+#define RAMS_SIZE           32
+#endif
+#define RAMS_END            (RAMS_BASE_ADDRESS + RAMS_SIZE * 1024)
+
+#define SYS_REG_BASE        0x40001000
+#define GPIO_REG_BASE       0x40001000
+#define GPIO_REG_BASE_PA    0x40001040
+#define GPIO_REG_BASE_PB    0x40001060
+
+#define GPIO_PORTS          2           // 2 ports : PA & PB
+#define GPIO_PA_PIN_START   0           // PA : pin number 0~31
+#define GPIO_PB_PIN_START   32          // PB : pin number 32~63
+
+#ifdef SOC_SERIES_CH569
+#define GPIO_PA_PIN_MARK    0x00ffffff  // PA : bits 0~23
+#define GPIO_PB_PIN_MARK    0x01ffffff  // PB : bits 0~24
+#else
+#define GPIO_PA_PIN_MARK    0x0000ffff  // PA : bits 0~15
+#define GPIO_PB_PIN_MARK    0x00003fff  // PB : bits 0~13
+#endif
+
+#define TMR0_REG_BASE       0x40002000
+#define TMR1_REG_BASE       0x40002400
+#define TMR2_REG_BASE       0x40002800
+
+#define UART0_REG_BASE      0x40003000
+#define UART1_REG_BASE      0x40003400
+#define UART2_REG_BASE      0x40003800
+#define UART3_REG_BASE      0x40003c00
+
+#define SPI0_REG_BASE       0x40004000
+#define SPI1_REG_BASE       0x40004400
+
+#define PWMX_REG_BASE       0x40005000
+
+#define PFIC_REG_BASE       0xe000e000
+#define SysTick_REG_BASE    0xe000f000
+
+#ifdef SOC_SERIES_CH569
+#define HSPI_REG_BASE       0x40006000  // CH569W
+#define ECDC_REG_BASE       0x40007000
+#define USBSS_REG_BASE      0x40008000
+#define USBHS_REG_BASE      0x40009000
+#define EMMC_REG_BASE       0x4000a000
+#define SERDES_REG_BASE     0x4000b000
+#define ETH_REG_BASE        0x4000c000  // CH565W/CH569W
+#define DVP_REG_BASE        0x4000e000  // CH565W/CH565M
+#else
+#define LED_REG_BASE        0x40006000
+#define USB0_REG_BASE       0x40008000  // CH567
+#define USB1_REG_BASE       0x40009000  // CH567
+#define USB_REG_BASE        0x40009000  // CH568
+#define SDC_REG_BASE        0x4000a000
+#define SATA_REG_BASE       0x4000b000  // CH568
+#define ECDC_REG_BASE       0x4000c400
+#endif
+
+#if defined(SOC_SERIES_CH569)
+typedef enum
+{
+    PWMX_OFFn    = 0,
+    NMI_IRQn     = 2,
+    EXC_IRQn     = 3,
+    SysTick_IRQn = 12,
+    SWI_IRQn     = 14,
+    WDOG_IRQn    = 16,
+    TMR0_IRQn    = 17,
+    GPIO_IRQn    = 18,
+    SPI0_IRQn    = 19,
+    USBSS_IRQn   = 20,
+    LINK_IRQn    = 21,
+    TMR1_IRQn    = 22,
+    TMR2_IRQn    = 23,
+    UART0_IRQn   = 24,
+    USBHS_IRQn   = 25,
+    EMMC_IRQn    = 26,
+    DVP_IRQn     = 27,
+    HSPI_IRQn    = 28,
+    SPI1_IRQn    = 29,
+    UART1_IRQn   = 30,
+    UART2_IRQn   = 31,
+    UART3_IRQn   = 32,
+    SerDes_IRQn  = 33,
+    ETH_IRQn     = 34,
+    PMT_IRQn     = 35,
+    ECDC_IRQn    = 36,
+    END_OF_IRQn
+} irq_number_t;
+
+#else
+
+typedef enum
+{
+    PWMX_OFFn    = 0,
+    SOFT_IRQn    = 0,
+    TMR0_IRQn    = 1,
+    GPIO_IRQn    = 2,
+    SPI0_IRQn    = 3,
+    USB0_IRQn    = 4,   // CH567
+    SATA_IRQn    = 4,   // CH568
+    TMR1_IRQn    = 5,
+    TMR2_IRQn    = 6,
+    UART0_IRQn   = 7,
+    USB1_IRQn    = 8,
+    SDC_IRQn     = 9,
+    ECDC_IRQn    = 10,
+    LED_IRQn     = 11,
+    SPI1_IRQn    = 12,
+    UART1_IRQn   = 13,
+    UART2_IRQn   = 14,
+    UART3_IRQn   = 15,
+    END_OF_IRQn
+} irq_number_t;
+#endif
+
+#endif

+ 190 - 0
bsp/wch/risc-v/Libraries/ch56x_drivers/swi_gcc.S

@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-09-09     WCH          the first version
+ * 2022-07-15     Emuzit       adapt to ch569w-evt
+ */
+ 
+#include "cpuport.h"
+
+    .global swi_handler
+    .align  2
+swi_handler:
+    /* save all from thread context */
+#ifdef ARCH_RISCV_FPU
+    addi    sp, sp, -32 * FREGBYTES
+    FSTORE  f0, 0 * FREGBYTES(sp)
+    FSTORE  f1, 1 * FREGBYTES(sp)
+    FSTORE  f2, 2 * FREGBYTES(sp)
+    FSTORE  f3, 3 * FREGBYTES(sp)
+    FSTORE  f4, 4 * FREGBYTES(sp)
+    FSTORE  f5, 5 * FREGBYTES(sp)
+    FSTORE  f6, 6 * FREGBYTES(sp)
+    FSTORE  f7, 7 * FREGBYTES(sp)
+    FSTORE  f8, 8 * FREGBYTES(sp)
+    FSTORE  f9, 9 * FREGBYTES(sp)
+    FSTORE  f10, 10 * FREGBYTES(sp)
+    FSTORE  f11, 11 * FREGBYTES(sp)
+    FSTORE  f12, 12 * FREGBYTES(sp)
+    FSTORE  f13, 13 * FREGBYTES(sp)
+    FSTORE  f14, 14 * FREGBYTES(sp)
+    FSTORE  f15, 15 * FREGBYTES(sp)
+    FSTORE  f16, 16 * FREGBYTES(sp)
+    FSTORE  f17, 17 * FREGBYTES(sp)
+    FSTORE  f18, 18 * FREGBYTES(sp)
+    FSTORE  f19, 19 * FREGBYTES(sp)
+    FSTORE  f20, 20 * FREGBYTES(sp)
+    FSTORE  f21, 21 * FREGBYTES(sp)
+    FSTORE  f22, 22 * FREGBYTES(sp)
+    FSTORE  f23, 23 * FREGBYTES(sp)
+    FSTORE  f24, 24 * FREGBYTES(sp)
+    FSTORE  f25, 25 * FREGBYTES(sp)
+    FSTORE  f26, 26 * FREGBYTES(sp)
+    FSTORE  f27, 27 * FREGBYTES(sp)
+    FSTORE  f28, 28 * FREGBYTES(sp)
+    FSTORE  f29, 29 * FREGBYTES(sp)
+    FSTORE  f30, 30 * FREGBYTES(sp)
+    FSTORE  f31, 31 * FREGBYTES(sp)
+#endif
+
+    addi  sp, sp, -32 * REGBYTES
+
+    STORE x1,   1 * REGBYTES(sp)
+
+    /* saved MPIE */
+ 	li    x1,   0x80
+    STORE x1,   2 * REGBYTES(sp)
+
+    STORE x4,   4 * REGBYTES(sp)
+    STORE x5,   5 * REGBYTES(sp)
+    STORE x6,   6 * REGBYTES(sp)
+    STORE x7,   7 * REGBYTES(sp)
+    STORE x8,   8 * REGBYTES(sp)
+    STORE x9,   9 * REGBYTES(sp)
+    STORE x10, 10 * REGBYTES(sp)
+    STORE x11, 11 * REGBYTES(sp)
+    STORE x12, 12 * REGBYTES(sp)
+    STORE x13, 13 * REGBYTES(sp)
+    STORE x14, 14 * REGBYTES(sp)
+    STORE x15, 15 * REGBYTES(sp)
+    STORE x16, 16 * REGBYTES(sp)
+    STORE x17, 17 * REGBYTES(sp)
+    STORE x18, 18 * REGBYTES(sp)
+    STORE x19, 19 * REGBYTES(sp)
+    STORE x20, 20 * REGBYTES(sp)
+    STORE x21, 21 * REGBYTES(sp)
+    STORE x22, 22 * REGBYTES(sp)
+    STORE x23, 23 * REGBYTES(sp)
+    STORE x24, 24 * REGBYTES(sp)
+    STORE x25, 25 * REGBYTES(sp)
+    STORE x26, 26 * REGBYTES(sp)
+    STORE x27, 27 * REGBYTES(sp)
+    STORE x28, 28 * REGBYTES(sp)
+    STORE x29, 29 * REGBYTES(sp)
+    STORE x30, 30 * REGBYTES(sp)
+    STORE x31, 31 * REGBYTES(sp)
+
+    /* rt_thread_switch_interrupt_flag not 0 => clear & switch thread */
+    la    t0, rt_thread_switch_interrupt_flag
+    lw    t1, 0(t0)
+    beqz  t1, .L_restore
+    sw    zero, 0(t0)
+
+    /* prepare to switch to rt_interrupt_to_thread */
+    csrr  t1, mepc
+    STORE t1, 0 * REGBYTES(sp)
+
+    la    t0, rt_interrupt_from_thread
+    LOAD  t1, 0(t0)
+    STORE sp, 0(t1)
+
+    la    t0, rt_interrupt_to_thread
+    LOAD  t1, 0(t0)
+    LOAD  sp, 0(t1)
+
+    LOAD  t1, 0 * REGBYTES(sp)
+    csrw  mepc, t1
+
+.L_restore:
+
+    /* clear software interrupt */
+    jal   pfic_swi_pendreset
+
+    LOAD  x1,   1 * REGBYTES(sp)
+
+	li    t0, 0x1800
+	csrs  mstatus, t0
+	LOAD  t0, 2 * REGBYTES(sp)
+	csrs  mstatus, t0
+
+    LOAD  x4,   4 * REGBYTES(sp)
+    LOAD  x5,   5 * REGBYTES(sp)
+    LOAD  x6,   6 * REGBYTES(sp)
+    LOAD  x7,   7 * REGBYTES(sp)
+    LOAD  x8,   8 * REGBYTES(sp)
+    LOAD  x9,   9 * REGBYTES(sp)
+    LOAD  x10, 10 * REGBYTES(sp)
+    LOAD  x11, 11 * REGBYTES(sp)
+    LOAD  x12, 12 * REGBYTES(sp)
+    LOAD  x13, 13 * REGBYTES(sp)
+    LOAD  x14, 14 * REGBYTES(sp)
+    LOAD  x15, 15 * REGBYTES(sp)
+    LOAD  x16, 16 * REGBYTES(sp)
+    LOAD  x17, 17 * REGBYTES(sp)
+    LOAD  x18, 18 * REGBYTES(sp)
+    LOAD  x19, 19 * REGBYTES(sp)
+    LOAD  x20, 20 * REGBYTES(sp)
+    LOAD  x21, 21 * REGBYTES(sp)
+    LOAD  x22, 22 * REGBYTES(sp)
+    LOAD  x23, 23 * REGBYTES(sp)
+    LOAD  x24, 24 * REGBYTES(sp)
+    LOAD  x25, 25 * REGBYTES(sp)
+    LOAD  x26, 26 * REGBYTES(sp)
+    LOAD  x27, 27 * REGBYTES(sp)
+    LOAD  x28, 28 * REGBYTES(sp)
+    LOAD  x29, 29 * REGBYTES(sp)
+    LOAD  x30, 30 * REGBYTES(sp)
+    LOAD  x31, 31 * REGBYTES(sp)
+    addi  sp, sp, 32 * REGBYTES
+
+    /* load float reg */
+#ifdef ARCH_RISCV_FPU
+    FLOAD   f0, 0 * FREGBYTES(sp)
+    FLOAD   f1, 1 * FREGBYTES(sp)
+    FLOAD   f2, 2 * FREGBYTES(sp)
+    FLOAD   f3, 3 * FREGBYTES(sp)
+    FLOAD   f4, 4 * FREGBYTES(sp)
+    FLOAD   f5, 5 * FREGBYTES(sp)
+    FLOAD   f6, 6 * FREGBYTES(sp)
+    FLOAD   f7, 7 * FREGBYTES(sp)
+    FLOAD   f8, 8 * FREGBYTES(sp)
+    FLOAD   f9, 9 * FREGBYTES(sp)
+    FLOAD   f10, 10 * FREGBYTES(sp)
+    FLOAD   f11, 11 * FREGBYTES(sp)
+    FLOAD   f12, 12 * FREGBYTES(sp)
+    FLOAD   f13, 13 * FREGBYTES(sp)
+    FLOAD   f14, 14 * FREGBYTES(sp)
+    FLOAD   f15, 15 * FREGBYTES(sp)
+    FLOAD   f16, 16 * FREGBYTES(sp)
+    FLOAD   f17, 17 * FREGBYTES(sp)
+    FLOAD   f18, 18 * FREGBYTES(sp)
+    FLOAD   f19, 19 * FREGBYTES(sp)
+    FLOAD   f20, 20 * FREGBYTES(sp)
+    FLOAD   f21, 21 * FREGBYTES(sp)
+    FLOAD   f22, 22 * FREGBYTES(sp)
+    FLOAD   f23, 23 * FREGBYTES(sp)
+    FLOAD   f24, 24 * FREGBYTES(sp)
+    FLOAD   f25, 25 * FREGBYTES(sp)
+    FLOAD   f26, 26 * FREGBYTES(sp)
+    FLOAD   f27, 27 * FREGBYTES(sp)
+    FLOAD   f28, 28 * FREGBYTES(sp)
+    FLOAD   f29, 29 * FREGBYTES(sp)
+    FLOAD   f30, 30 * FREGBYTES(sp)
+    FLOAD   f31, 31 * FREGBYTES(sp)
+    addi    sp, sp, 32 * FREGBYTES
+#endif
+    mret

+ 664 - 0
bsp/wch/risc-v/ch569w-evt/.config

@@ -0,0 +1,664 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# RT-Thread Configuration
+#
+
+#
+# RT-Thread Kernel
+#
+CONFIG_RT_NAME_MAX=8
+# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
+# CONFIG_RT_USING_SMP is not set
+CONFIG_RT_ALIGN_SIZE=4
+# CONFIG_RT_THREAD_PRIORITY_8 is not set
+CONFIG_RT_THREAD_PRIORITY_32=y
+# CONFIG_RT_THREAD_PRIORITY_256 is not set
+CONFIG_RT_THREAD_PRIORITY_MAX=32
+CONFIG_RT_TICK_PER_SECOND=200
+# CONFIG_RT_USING_OVERFLOW_CHECK is not set
+CONFIG_RT_USING_HOOK=y
+CONFIG_RT_HOOK_USING_FUNC_PTR=y
+CONFIG_RT_USING_IDLE_HOOK=y
+CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
+CONFIG_IDLE_THREAD_STACK_SIZE=384
+# CONFIG_RT_USING_TIMER_SOFT is not set
+
+#
+# kservice optimization
+#
+CONFIG_RT_KSERVICE_USING_STDLIB=y
+# CONFIG_RT_KSERVICE_USING_STDLIB_MEMORY is not set
+# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
+# CONFIG_RT_USING_TINY_FFS is not set
+# CONFIG_RT_KPRINTF_USING_LONGLONG is not set
+# CONFIG_RT_DEBUG is not set
+
+#
+# Inter-Thread communication
+#
+CONFIG_RT_USING_SEMAPHORE=y
+CONFIG_RT_USING_MUTEX=y
+# CONFIG_RT_USING_EVENT is not set
+CONFIG_RT_USING_MAILBOX=y
+# CONFIG_RT_USING_MESSAGEQUEUE is not set
+# CONFIG_RT_USING_SIGNALS is not set
+
+#
+# Memory Management
+#
+CONFIG_RT_USING_MEMPOOL=y
+CONFIG_RT_USING_SMALL_MEM=y
+# CONFIG_RT_USING_SLAB is not set
+# CONFIG_RT_USING_MEMHEAP is not set
+CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y
+# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
+# CONFIG_RT_USING_SLAB_AS_HEAP is not set
+# CONFIG_RT_USING_USERHEAP is not set
+# CONFIG_RT_USING_NOHEAP is not set
+# CONFIG_RT_USING_MEMTRACE is not set
+# CONFIG_RT_USING_HEAP_ISR is not set
+CONFIG_RT_USING_HEAP=y
+
+#
+# Kernel Device Object
+#
+CONFIG_RT_USING_DEVICE=y
+# CONFIG_RT_USING_DEVICE_OPS is not set
+CONFIG_RT_USING_INTERRUPT_INFO=y
+CONFIG_RT_USING_CONSOLE=y
+CONFIG_RT_CONSOLEBUF_SIZE=128
+CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
+CONFIG_RT_VER_NUM=0x40101
+# CONFIG_RT_USING_CPU_FFS is not set
+CONFIG_ARCH_RISCV=y
+# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
+
+#
+# RT-Thread Components
+#
+CONFIG_RT_USING_COMPONENTS_INIT=y
+CONFIG_RT_USING_USER_MAIN=y
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048
+CONFIG_RT_MAIN_THREAD_PRIORITY=10
+# CONFIG_RT_USING_LEGACY is not set
+CONFIG_RT_USING_MSH=y
+CONFIG_RT_USING_FINSH=y
+CONFIG_FINSH_USING_MSH=y
+CONFIG_FINSH_THREAD_NAME="tshell"
+CONFIG_FINSH_THREAD_PRIORITY=20
+CONFIG_FINSH_THREAD_STACK_SIZE=4096
+CONFIG_FINSH_USING_HISTORY=y
+CONFIG_FINSH_HISTORY_LINES=5
+CONFIG_FINSH_USING_SYMTAB=y
+CONFIG_FINSH_CMD_SIZE=80
+CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
+CONFIG_FINSH_USING_DESCRIPTION=y
+# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
+# CONFIG_FINSH_USING_AUTH is not set
+CONFIG_FINSH_ARG_MAX=10
+# CONFIG_RT_USING_DFS is not set
+# CONFIG_RT_USING_FAL is not set
+
+#
+# Device Drivers
+#
+CONFIG_RT_USING_DEVICE_IPC=y
+# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
+CONFIG_RT_USING_SERIAL=y
+CONFIG_RT_USING_SERIAL_V1=y
+# CONFIG_RT_USING_SERIAL_V2 is not set
+# CONFIG_RT_SERIAL_USING_DMA is not set
+CONFIG_RT_SERIAL_RB_BUFSZ=64
+# CONFIG_RT_USING_CAN is not set
+CONFIG_RT_USING_HWTIMER=y
+# CONFIG_RT_USING_CPUTIME is not set
+# CONFIG_RT_USING_I2C is not set
+# CONFIG_RT_USING_PHY is not set
+CONFIG_RT_USING_PIN=y
+# CONFIG_RT_USING_ADC is not set
+# CONFIG_RT_USING_DAC is not set
+# CONFIG_RT_USING_PWM is not set
+# CONFIG_RT_USING_MTD_NOR is not set
+# CONFIG_RT_USING_MTD_NAND is not set
+# CONFIG_RT_USING_PM is not set
+# CONFIG_RT_USING_RTC is not set
+# CONFIG_RT_USING_SDIO is not set
+# CONFIG_RT_USING_SPI is not set
+CONFIG_RT_USING_WDT=y
+# CONFIG_RT_USING_AUDIO is not set
+# CONFIG_RT_USING_SENSOR is not set
+# CONFIG_RT_USING_TOUCH is not set
+# CONFIG_RT_USING_HWCRYPTO is not set
+# CONFIG_RT_USING_PULSE_ENCODER is not set
+# CONFIG_RT_USING_INPUT_CAPTURE is not set
+# CONFIG_RT_USING_WIFI is not set
+
+#
+# Using USB
+#
+# CONFIG_RT_USING_USB is not set
+# CONFIG_RT_USING_USB_HOST is not set
+# CONFIG_RT_USING_USB_DEVICE is not set
+
+#
+# C/C++ and POSIX layer
+#
+CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
+
+#
+# POSIX (Portable Operating System Interface) layer
+#
+# CONFIG_RT_USING_POSIX_FS is not set
+# CONFIG_RT_USING_POSIX_DELAY is not set
+# CONFIG_RT_USING_POSIX_CLOCK is not set
+# CONFIG_RT_USING_POSIX_TIMER is not set
+# CONFIG_RT_USING_PTHREADS is not set
+# CONFIG_RT_USING_MODULE is not set
+
+#
+# Interprocess Communication (IPC)
+#
+# CONFIG_RT_USING_POSIX_PIPE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
+
+#
+# Socket is in the 'Network' category
+#
+# CONFIG_RT_USING_CPLUSPLUS is not set
+
+#
+# Network
+#
+# CONFIG_RT_USING_SAL is not set
+# CONFIG_RT_USING_NETDEV is not set
+# CONFIG_RT_USING_LWIP is not set
+# CONFIG_RT_USING_AT is not set
+
+#
+# Utilities
+#
+# CONFIG_RT_USING_RYM is not set
+# CONFIG_RT_USING_ULOG is not set
+# CONFIG_RT_USING_UTEST is not set
+# CONFIG_RT_USING_VAR_EXPORT is not set
+# CONFIG_RT_USING_RT_LINK is not set
+# CONFIG_RT_USING_VBUS is not set
+
+#
+# RT-Thread Utestcases
+#
+# CONFIG_RT_USING_UTESTCASES is not set
+
+#
+# RT-Thread online packages
+#
+
+#
+# IoT - internet of things
+#
+# CONFIG_PKG_USING_LWIP is not set
+# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
+# CONFIG_PKG_USING_PAHOMQTT is not set
+# CONFIG_PKG_USING_UMQTT is not set
+# CONFIG_PKG_USING_WEBCLIENT is not set
+# CONFIG_PKG_USING_WEBNET is not set
+# CONFIG_PKG_USING_MONGOOSE is not set
+# CONFIG_PKG_USING_MYMQTT is not set
+# CONFIG_PKG_USING_KAWAII_MQTT is not set
+# CONFIG_PKG_USING_BC28_MQTT is not set
+# CONFIG_PKG_USING_WEBTERMINAL is not set
+# CONFIG_PKG_USING_LIBMODBUS is not set
+# CONFIG_PKG_USING_FREEMODBUS is not set
+# CONFIG_PKG_USING_NANOPB is not set
+
+#
+# Wi-Fi
+#
+
+#
+# Marvell WiFi
+#
+# CONFIG_PKG_USING_WLANMARVELL is not set
+
+#
+# Wiced WiFi
+#
+# CONFIG_PKG_USING_WLAN_WICED is not set
+# CONFIG_PKG_USING_RW007 is not set
+# CONFIG_PKG_USING_COAP is not set
+# CONFIG_PKG_USING_NOPOLL is not set
+# CONFIG_PKG_USING_NETUTILS is not set
+# CONFIG_PKG_USING_CMUX is not set
+# CONFIG_PKG_USING_PPP_DEVICE is not set
+# CONFIG_PKG_USING_AT_DEVICE is not set
+# CONFIG_PKG_USING_ATSRV_SOCKET is not set
+# CONFIG_PKG_USING_WIZNET is not set
+# CONFIG_PKG_USING_ZB_COORDINATOR is not set
+
+#
+# IoT Cloud
+#
+# CONFIG_PKG_USING_ONENET is not set
+# CONFIG_PKG_USING_GAGENT_CLOUD is not set
+# CONFIG_PKG_USING_ALI_IOTKIT is not set
+# CONFIG_PKG_USING_AZURE is not set
+# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
+# CONFIG_PKG_USING_JIOT-C-SDK is not set
+# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
+# CONFIG_PKG_USING_JOYLINK is not set
+# CONFIG_PKG_USING_EZ_IOT_OS is not set
+# CONFIG_PKG_USING_IOTSHARP_SDK is not set
+# CONFIG_PKG_USING_NIMBLE is not set
+# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
+# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
+# CONFIG_PKG_USING_IPMSG is not set
+# CONFIG_PKG_USING_LSSDP is not set
+# CONFIG_PKG_USING_AIRKISS_OPEN is not set
+# CONFIG_PKG_USING_LIBRWS is not set
+# CONFIG_PKG_USING_TCPSERVER is not set
+# CONFIG_PKG_USING_PROTOBUF_C is not set
+# CONFIG_PKG_USING_DLT645 is not set
+# CONFIG_PKG_USING_QXWZ is not set
+# CONFIG_PKG_USING_SMTP_CLIENT is not set
+# CONFIG_PKG_USING_ABUP_FOTA is not set
+# CONFIG_PKG_USING_LIBCURL2RTT is not set
+# CONFIG_PKG_USING_CAPNP is not set
+# CONFIG_PKG_USING_AGILE_TELNET is not set
+# CONFIG_PKG_USING_NMEALIB is not set
+# CONFIG_PKG_USING_PDULIB is not set
+# CONFIG_PKG_USING_BTSTACK is not set
+# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
+# CONFIG_PKG_USING_WAYZ_IOTKIT is not set
+# CONFIG_PKG_USING_MAVLINK is not set
+# CONFIG_PKG_USING_BSAL is not set
+# CONFIG_PKG_USING_AGILE_MODBUS is not set
+# CONFIG_PKG_USING_AGILE_FTP is not set
+# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
+# CONFIG_PKG_USING_RT_LINK_HW is not set
+# CONFIG_PKG_USING_LORA_PKT_FWD is not set
+# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set
+# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set
+# CONFIG_PKG_USING_HM is not set
+# CONFIG_PKG_USING_SMALL_MODBUS is not set
+# CONFIG_PKG_USING_NET_SERVER is not set
+# CONFIG_PKG_USING_ZFTP is not set
+
+#
+# security packages
+#
+# CONFIG_PKG_USING_MBEDTLS is not set
+# CONFIG_PKG_USING_LIBSODIUM is not set
+# CONFIG_PKG_USING_LIBHYDROGEN is not set
+# CONFIG_PKG_USING_TINYCRYPT is not set
+# CONFIG_PKG_USING_TFM is not set
+# CONFIG_PKG_USING_YD_CRYPTO is not set
+
+#
+# language packages
+#
+
+#
+# JSON: JavaScript Object Notation, a lightweight data-interchange format
+#
+# CONFIG_PKG_USING_CJSON is not set
+# CONFIG_PKG_USING_LJSON is not set
+# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
+# CONFIG_PKG_USING_RAPIDJSON is not set
+# CONFIG_PKG_USING_JSMN is not set
+# CONFIG_PKG_USING_AGILE_JSMN is not set
+
+#
+# XML: Extensible Markup Language
+#
+# CONFIG_PKG_USING_SIMPLE_XML is not set
+# CONFIG_PKG_USING_EZXML is not set
+# CONFIG_PKG_USING_LUATOS_SOC is not set
+# CONFIG_PKG_USING_LUA is not set
+# CONFIG_PKG_USING_JERRYSCRIPT is not set
+# CONFIG_PKG_USING_MICROPYTHON is not set
+# CONFIG_PKG_USING_PIKASCRIPT is not set
+# CONFIG_PKG_USING_RTT_RUST is not set
+
+#
+# multimedia packages
+#
+
+#
+# LVGL: powerful and easy-to-use embedded GUI library
+#
+# CONFIG_PKG_USING_LVGL is not set
+# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
+# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set
+# CONFIG_PKG_USING_GUI_GUIDER_DEMO is not set
+
+#
+# u8g2: a monochrome graphic library
+#
+# CONFIG_PKG_USING_U8G2_OFFICIAL is not set
+# CONFIG_PKG_USING_U8G2 is not set
+# CONFIG_PKG_USING_OPENMV is not set
+# CONFIG_PKG_USING_MUPDF is not set
+# CONFIG_PKG_USING_STEMWIN is not set
+# CONFIG_PKG_USING_WAVPLAYER is not set
+# CONFIG_PKG_USING_TJPGD is not set
+# CONFIG_PKG_USING_PDFGEN is not set
+# CONFIG_PKG_USING_HELIX is not set
+# CONFIG_PKG_USING_AZUREGUIX is not set
+# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
+# CONFIG_PKG_USING_NUEMWIN is not set
+# CONFIG_PKG_USING_MP3PLAYER is not set
+# CONFIG_PKG_USING_TINYJPEG is not set
+# CONFIG_PKG_USING_UGUI is not set
+
+#
+# PainterEngine: A cross-platform graphics application framework written in C language
+#
+# CONFIG_PKG_USING_PAINTERENGINE is not set
+# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set
+# CONFIG_PKG_USING_MCURSES is not set
+# CONFIG_PKG_USING_TERMBOX is not set
+# CONFIG_PKG_USING_VT100 is not set
+# CONFIG_PKG_USING_QRCODE is not set
+# CONFIG_PKG_USING_GUIENGINE is not set
+
+#
+# tools packages
+#
+# CONFIG_PKG_USING_CMBACKTRACE is not set
+# CONFIG_PKG_USING_EASYFLASH is not set
+# CONFIG_PKG_USING_EASYLOGGER is not set
+# CONFIG_PKG_USING_SYSTEMVIEW is not set
+# CONFIG_PKG_USING_SEGGER_RTT is not set
+# CONFIG_PKG_USING_RDB is not set
+# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
+# CONFIG_PKG_USING_ULOG_FILE is not set
+# CONFIG_PKG_USING_LOGMGR is not set
+# CONFIG_PKG_USING_ADBD is not set
+# CONFIG_PKG_USING_COREMARK is not set
+# CONFIG_PKG_USING_DHRYSTONE is not set
+# CONFIG_PKG_USING_MEMORYPERF is not set
+# CONFIG_PKG_USING_NR_MICRO_SHELL is not set
+# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
+# CONFIG_PKG_USING_LUNAR_CALENDAR is not set
+# CONFIG_PKG_USING_BS8116A is not set
+# CONFIG_PKG_USING_GPS_RMC is not set
+# CONFIG_PKG_USING_URLENCODE is not set
+# CONFIG_PKG_USING_UMCN is not set
+# CONFIG_PKG_USING_LWRB2RTT is not set
+# CONFIG_PKG_USING_CPU_USAGE is not set
+# CONFIG_PKG_USING_GBK2UTF8 is not set
+# CONFIG_PKG_USING_VCONSOLE is not set
+# CONFIG_PKG_USING_KDB is not set
+# CONFIG_PKG_USING_WAMR is not set
+# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set
+# CONFIG_PKG_USING_LWLOG is not set
+# CONFIG_PKG_USING_ANV_TRACE is not set
+# CONFIG_PKG_USING_ANV_MEMLEAK is not set
+# CONFIG_PKG_USING_ANV_TESTSUIT is not set
+# CONFIG_PKG_USING_ANV_BENCH is not set
+# CONFIG_PKG_USING_DEVMEM is not set
+# CONFIG_PKG_USING_REGEX is not set
+# CONFIG_PKG_USING_MEM_SANDBOX is not set
+# CONFIG_PKG_USING_SOLAR_TERMS is not set
+# CONFIG_PKG_USING_GAN_ZHI is not set
+# CONFIG_PKG_USING_FDT is not set
+# CONFIG_PKG_USING_CBOX is not set
+# CONFIG_PKG_USING_SNOWFLAKE is not set
+# CONFIG_PKG_USING_HASH_MATCH is not set
+# CONFIG_PKG_USING_FIRE_PID_CURVE is not set
+# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set
+
+#
+# system packages
+#
+
+#
+# enhanced kernel services
+#
+# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
+# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
+# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set
+
+#
+# acceleration: Assembly language or algorithmic acceleration packages
+#
+# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
+# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
+# CONFIG_PKG_USING_QFPLIB_M3 is not set
+
+#
+# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard
+#
+# CONFIG_PKG_USING_CMSIS_5 is not set
+# CONFIG_PKG_USING_CMSIS_RTOS1 is not set
+# CONFIG_PKG_USING_CMSIS_RTOS2 is not set
+
+#
+# Micrium: Micrium software products porting for RT-Thread
+#
+# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set
+# CONFIG_PKG_USING_UCOSII_WRAPPER is not set
+# CONFIG_PKG_USING_UC_CRC is not set
+# CONFIG_PKG_USING_UC_CLK is not set
+# CONFIG_PKG_USING_UC_COMMON is not set
+# CONFIG_PKG_USING_UC_MODBUS is not set
+# CONFIG_PKG_USING_RTDUINO is not set
+# CONFIG_PKG_USING_CAIRO is not set
+# CONFIG_PKG_USING_PIXMAN is not set
+# CONFIG_PKG_USING_PARTITION is not set
+# CONFIG_PKG_USING_PERF_COUNTER is not set
+# CONFIG_PKG_USING_FLASHDB is not set
+# CONFIG_PKG_USING_SQLITE is not set
+# CONFIG_PKG_USING_RTI is not set
+# CONFIG_PKG_USING_DFS_YAFFS is not set
+# CONFIG_PKG_USING_LITTLEFS is not set
+# CONFIG_PKG_USING_DFS_JFFS2 is not set
+# CONFIG_PKG_USING_DFS_UFFS is not set
+# CONFIG_PKG_USING_LWEXT4 is not set
+# CONFIG_PKG_USING_THREAD_POOL is not set
+# CONFIG_PKG_USING_ROBOTS is not set
+# CONFIG_PKG_USING_EV is not set
+# CONFIG_PKG_USING_SYSWATCH is not set
+# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
+# CONFIG_PKG_USING_PLCCORE is not set
+# CONFIG_PKG_USING_RAMDISK is not set
+# CONFIG_PKG_USING_MININI is not set
+# CONFIG_PKG_USING_QBOOT is not set
+# CONFIG_PKG_USING_PPOOL is not set
+# CONFIG_PKG_USING_OPENAMP is not set
+# CONFIG_PKG_USING_LPM is not set
+# CONFIG_PKG_USING_TLSF is not set
+# CONFIG_PKG_USING_EVENT_RECORDER is not set
+# CONFIG_PKG_USING_ARM_2D is not set
+# CONFIG_PKG_USING_MCUBOOT is not set
+# CONFIG_PKG_USING_TINYUSB is not set
+# CONFIG_PKG_USING_CHERRYUSB is not set
+# CONFIG_PKG_USING_KMULTI_RTIMER is not set
+# CONFIG_PKG_USING_TFDB is not set
+# CONFIG_PKG_USING_QPC is not set
+
+#
+# peripheral libraries and drivers
+#
+# CONFIG_PKG_USING_SENSORS_DRIVERS is not set
+# CONFIG_PKG_USING_REALTEK_AMEBA is not set
+# CONFIG_PKG_USING_SHT2X is not set
+# CONFIG_PKG_USING_SHT3X is not set
+# CONFIG_PKG_USING_AS7341 is not set
+# CONFIG_PKG_USING_STM32_SDIO is not set
+# CONFIG_PKG_USING_ICM20608 is not set
+# CONFIG_PKG_USING_BUTTON is not set
+# CONFIG_PKG_USING_PCF8574 is not set
+# CONFIG_PKG_USING_SX12XX is not set
+# CONFIG_PKG_USING_SIGNAL_LED is not set
+# CONFIG_PKG_USING_LEDBLINK is not set
+# CONFIG_PKG_USING_LITTLED is not set
+# CONFIG_PKG_USING_LKDGUI is not set
+# CONFIG_PKG_USING_NRF5X_SDK is not set
+# CONFIG_PKG_USING_NRFX is not set
+# CONFIG_PKG_USING_WM_LIBRARIES is not set
+# CONFIG_PKG_USING_KENDRYTE_SDK is not set
+# CONFIG_PKG_USING_INFRARED is not set
+# CONFIG_PKG_USING_MULTI_INFRARED is not set
+# CONFIG_PKG_USING_AGILE_BUTTON is not set
+# CONFIG_PKG_USING_AGILE_LED is not set
+# CONFIG_PKG_USING_AT24CXX is not set
+# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
+# CONFIG_PKG_USING_AD7746 is not set
+# CONFIG_PKG_USING_PCA9685 is not set
+# CONFIG_PKG_USING_I2C_TOOLS is not set
+# CONFIG_PKG_USING_NRF24L01 is not set
+# CONFIG_PKG_USING_TOUCH_DRIVERS is not set
+# CONFIG_PKG_USING_MAX17048 is not set
+# CONFIG_PKG_USING_RPLIDAR is not set
+# CONFIG_PKG_USING_AS608 is not set
+# CONFIG_PKG_USING_RC522 is not set
+# CONFIG_PKG_USING_WS2812B is not set
+# CONFIG_PKG_USING_EMBARC_BSP is not set
+# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
+# CONFIG_PKG_USING_MULTI_RTIMER is not set
+# CONFIG_PKG_USING_MAX7219 is not set
+# CONFIG_PKG_USING_BEEP is not set
+# CONFIG_PKG_USING_EASYBLINK is not set
+# CONFIG_PKG_USING_PMS_SERIES is not set
+# CONFIG_PKG_USING_NUCLEI_SDK is not set
+# CONFIG_PKG_USING_CAN_YMODEM is not set
+# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set
+# CONFIG_PKG_USING_QLED is not set
+# CONFIG_PKG_USING_PAJ7620 is not set
+# CONFIG_PKG_USING_AGILE_CONSOLE is not set
+# CONFIG_PKG_USING_LD3320 is not set
+# CONFIG_PKG_USING_WK2124 is not set
+# CONFIG_PKG_USING_LY68L6400 is not set
+# CONFIG_PKG_USING_DM9051 is not set
+# CONFIG_PKG_USING_SSD1306 is not set
+# CONFIG_PKG_USING_QKEY is not set
+# CONFIG_PKG_USING_RS485 is not set
+# CONFIG_PKG_USING_RS232 is not set
+# CONFIG_PKG_USING_NES is not set
+# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set
+# CONFIG_PKG_USING_VDEVICE is not set
+# CONFIG_PKG_USING_SGM706 is not set
+# CONFIG_PKG_USING_STM32WB55_SDK is not set
+# CONFIG_PKG_USING_RDA58XX is not set
+# CONFIG_PKG_USING_LIBNFC is not set
+# CONFIG_PKG_USING_MFOC is not set
+# CONFIG_PKG_USING_TMC51XX is not set
+# CONFIG_PKG_USING_TCA9534 is not set
+# CONFIG_PKG_USING_KOBUKI is not set
+# CONFIG_PKG_USING_ROSSERIAL is not set
+# CONFIG_PKG_USING_MICRO_ROS is not set
+# CONFIG_PKG_USING_MCP23008 is not set
+# CONFIG_PKG_USING_BLUETRUM_SDK is not set
+# CONFIG_PKG_USING_MISAKA_AT24CXX is not set
+# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set
+# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set
+# CONFIG_PKG_USING_BL_MCU_SDK is not set
+# CONFIG_PKG_USING_SOFT_SERIAL is not set
+# CONFIG_PKG_USING_MB85RS16 is not set
+# CONFIG_PKG_USING_CW2015 is not set
+# CONFIG_PKG_USING_RFM300 is not set
+
+#
+# AI packages
+#
+# CONFIG_PKG_USING_LIBANN is not set
+# CONFIG_PKG_USING_NNOM is not set
+# CONFIG_PKG_USING_ONNX_BACKEND is not set
+# CONFIG_PKG_USING_ONNX_PARSER is not set
+# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
+# CONFIG_PKG_USING_ELAPACK is not set
+# CONFIG_PKG_USING_ULAPACK is not set
+# CONFIG_PKG_USING_QUEST is not set
+# CONFIG_PKG_USING_NAXOS is not set
+
+#
+# miscellaneous packages
+#
+
+#
+# project laboratory
+#
+
+#
+# samples: kernel and components samples
+#
+# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
+# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
+# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
+# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
+
+#
+# entertainment: terminal games and other interesting software packages
+#
+# CONFIG_PKG_USING_CMATRIX is not set
+# CONFIG_PKG_USING_SL is not set
+# CONFIG_PKG_USING_CAL is not set
+# CONFIG_PKG_USING_ACLOCK is not set
+# CONFIG_PKG_USING_THREES is not set
+# CONFIG_PKG_USING_2048 is not set
+# CONFIG_PKG_USING_SNAKE is not set
+# CONFIG_PKG_USING_TETRIS is not set
+# CONFIG_PKG_USING_DONUT is not set
+# CONFIG_PKG_USING_COWSAY is not set
+# CONFIG_PKG_USING_LIBCSV is not set
+# CONFIG_PKG_USING_OPTPARSE is not set
+# CONFIG_PKG_USING_FASTLZ is not set
+# CONFIG_PKG_USING_MINILZO is not set
+# CONFIG_PKG_USING_QUICKLZ is not set
+# CONFIG_PKG_USING_LZMA is not set
+# CONFIG_PKG_USING_MULTIBUTTON is not set
+# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
+# CONFIG_PKG_USING_CANFESTIVAL is not set
+# CONFIG_PKG_USING_ZLIB is not set
+# CONFIG_PKG_USING_MINIZIP is not set
+# CONFIG_PKG_USING_HEATSHRINK is not set
+# CONFIG_PKG_USING_DSTR is not set
+# CONFIG_PKG_USING_TINYFRAME is not set
+# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
+# CONFIG_PKG_USING_DIGITALCTRL is not set
+# CONFIG_PKG_USING_UPACKER is not set
+# CONFIG_PKG_USING_UPARAM is not set
+# CONFIG_PKG_USING_HELLO is not set
+# CONFIG_PKG_USING_VI is not set
+# CONFIG_PKG_USING_KI is not set
+# CONFIG_PKG_USING_ARMv7M_DWT is not set
+# CONFIG_PKG_USING_UKAL is not set
+# CONFIG_PKG_USING_CRCLIB is not set
+# CONFIG_PKG_USING_LWGPS is not set
+# CONFIG_PKG_USING_STATE_MACHINE is not set
+# CONFIG_PKG_USING_DESIGN_PATTERN is not set
+# CONFIG_PKG_USING_CONTROLLER is not set
+# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
+# CONFIG_PKG_USING_MFBD is not set
+# CONFIG_PKG_USING_SLCAN2RTT is not set
+# CONFIG_PKG_USING_SOEM is not set
+CONFIG_SOC_FAMILY_CH56X=y
+CONFIG_SOC_SERIES_CH569=y
+
+#
+# Hardware Drivers Config
+#
+CONFIG_SOC_CH569W=y
+
+#
+# On-chip Peripheral Drivers
+#
+CONFIG_BSP_USING_UART=y
+# CONFIG_BSP_USING_UART0 is not set
+CONFIG_BSP_USING_UART1=y
+# CONFIG_BSP_USING_UART2 is not set
+# CONFIG_BSP_USING_UART3 is not set
+CONFIG_BSP_USING_TIMER=y
+CONFIG_BSP_USING_TMR0=y
+CONFIG_BSP_USING_TMR1=y
+# CONFIG_BSP_USING_TMR2 is not set
+
+#
+# Onboard Peripheral Drivers
+#
+
+#
+# Board extended module Drivers
+#

+ 21 - 0
bsp/wch/risc-v/ch569w-evt/Kconfig

@@ -0,0 +1,21 @@
+mainmenu "RT-Thread Configuration"
+
+config BSP_DIR
+    string
+    option env="BSP_ROOT"
+    default "."
+
+config RTT_DIR
+    string
+    option env="RTT_ROOT"
+    default "../../../.."
+
+config PKGS_DIR
+    string
+    option env="PKGS_ROOT"
+    default "packages"
+
+source "$RTT_DIR/Kconfig"
+source "$PKGS_DIR/Kconfig"
+source "../Libraries/Kconfig"
+source "board/Kconfig"

+ 13 - 0
bsp/wch/risc-v/ch569w-evt/SConscript

@@ -0,0 +1,13 @@
+import os
+from building import *
+
+objs = []
+
+cwd = GetCurrentDir()
+list = os.listdir(cwd)
+
+for d in list:
+    if os.path.isfile(os.path.join(cwd, d, 'SConscript')):
+        objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+Return('objs')

+ 38 - 0
bsp/wch/risc-v/ch569w-evt/SConstruct

@@ -0,0 +1,38 @@
+import os
+import sys
+import rtconfig
+
+if os.getenv('RTT_ROOT'):
+    RTT_ROOT = os.getenv('RTT_ROOT')
+else:
+    RTT_ROOT = os.path.normpath(os.getcwd() + '/../../../..')
+
+sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
+try:
+    from building import *
+except:
+    print('Cannot find RT-Thread root directory, please check RTT_ROOT')
+    print('RTT_ROOT: ' + RTT_ROOT)
+    exit(-1)
+
+TARGET = 'rtthread.' + rtconfig.TARGET_EXT
+
+DefaultEnvironment(tools=[])
+env = Environment(tools = ['mingw'],
+    AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+    CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
+    AR = rtconfig.AR, ARFLAGS = '-rc',
+    LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
+env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
+
+Export('RTT_ROOT')
+Export('rtconfig')
+
+# prepare building environment
+objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
+
+objs.extend(SConscript('../Libraries/ch56x_drivers/SConscript',
+    variant_dir='build/libraries/ch56x_drivers', duplicate=0))
+
+# make a building
+DoBuilding(TARGET, objs)

+ 13 - 0
bsp/wch/risc-v/ch569w-evt/applications/SConscript

@@ -0,0 +1,13 @@
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split("""
+main.c
+""")
+
+path = [cwd, str(Dir('#'))]
+
+group = DefineGroup('Applications', src, depend=[''], CPPPATH=path)
+
+Return('group')

+ 231 - 0
bsp/wch/risc-v/ch569w-evt/applications/main.c

@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ * 2022-07-20     Emuzit            add watchdog test
+ * 2022-07-26     Emuzit            add hwtimer test
+ */
+#include <rtthread.h>
+#include <rtdebug.h>
+#include <drivers/pin.h>
+#include <drivers/watchdog.h>
+#include <drivers/hwtimer.h>
+#include "board.h"
+
+static const rt_base_t gpio_int_pins[8] = GPIO_INT_PINS;
+
+/* note : PIN_IRQ_MODE_RISING_FALLING not supported */
+static const uint32_t gpint_mode[] =
+{
+    PIN_IRQ_MODE_RISING,
+    PIN_IRQ_MODE_RISING,
+    PIN_IRQ_MODE_RISING,
+    PIN_IRQ_MODE_RISING,
+    PIN_IRQ_MODE_FALLING,
+    PIN_IRQ_MODE_FALLING,
+    PIN_IRQ_MODE_FALLING,
+    PIN_IRQ_MODE_FALLING,
+};
+
+static struct rt_mailbox *gpint_mb = RT_NULL;
+static struct rt_thread  *gpint_thread = RT_NULL;
+
+static rt_base_t led0, led1;
+
+static rt_device_t wdg_dev;
+
+static struct rt_device *tmr_dev_0;
+static struct rt_device *tmr_dev_1;
+
+static void gpio_int_callback(void *pin)
+{
+    led1 = (led1 == PIN_LOW) ? PIN_HIGH : PIN_LOW;
+    rt_pin_write(LED1_PIN, led1);
+
+    if (gpint_mb != RT_NULL)
+    {
+        /* non-block, silently ignore RT_EFULL */
+        rt_mb_send(gpint_mb, (uint32_t)pin);
+    }
+}
+
+static void gpio_int_thread(void *param)
+{
+    while (1)
+    {
+        rt_err_t res;
+        uint32_t pin;
+
+        res = rt_mb_recv(gpint_mb, &pin, RT_WAITING_FOREVER);
+        if (res == RT_EOK)
+        {
+            rt_kprintf("gpio_int #%d (%d)\n", pin, rt_pin_read(pin));
+        }
+        rt_thread_mdelay(100);
+
+#ifdef RT_USING_WDT
+        rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL);
+#endif
+    }
+}
+
+#ifdef RT_USING_HWTIMER
+static rt_err_t tmr_timeout_cb(rt_device_t dev, rt_size_t size)
+{
+    rt_tick_t tick = rt_tick_get();
+
+    int tmr = (dev == tmr_dev_1) ? 1 : 0;
+
+    rt_kprintf("hwtimer %d timeout callback fucntion @tick %d\n", tmr, tick);
+
+    return RT_EOK;
+}
+#endif
+
+void main(void)
+{
+    rt_hwtimerval_t timerval;
+    rt_hwtimer_mode_t mode;
+    rt_size_t tsize;
+
+    uint32_t seconds;
+    rt_err_t res;
+
+    int i;
+
+    rt_kprintf("\nCH569W-R0-1v0, HCLK: %dMHz\n\n", sys_hclk_get() / 1000000);
+
+    /* Enable all gpio interrupt with various modes.
+     * LED0 or GND touching can be used to trigger pin interrupt.
+    */
+    gpint_mb = rt_mb_create("pximb", 8, RT_IPC_FLAG_FIFO);
+    if (gpint_mb == RT_NULL)
+    {
+        rt_kprintf("gpint mailbox create failed !\n");
+    }
+    else
+    {
+        gpint_thread = rt_thread_create("pxith", gpio_int_thread, RT_NULL,
+                                        512, RT_MAIN_THREAD_PRIORITY, 50);
+        if (gpint_thread == RT_NULL)
+        {
+            rt_kprintf("gpint thread create failed !\n");
+        }
+        else
+        {
+            rt_thread_startup(gpint_thread);
+
+            for (i = 0; i < 8; i++)
+            {
+                rt_base_t pin = gpio_int_pins[i];
+                rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP);
+                res = rt_pin_attach_irq(
+                      pin, gpint_mode[i], gpio_int_callback, (void *)pin);
+                if (res != RT_EOK)
+                {
+                    rt_kprintf("rt_pin_attach_irq failed (%d:%d)\n", i, res);
+                }
+                else
+                {
+                    rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
+                }
+            }
+        }
+    }
+
+#ifdef RT_USING_WDT
+    /* Test watchdog with 30s timeout, keepalive with gpio interrupt.
+     *
+     * CAVEAT: With only 8-bit WDOG_COUNT and fixed clocking at Fsys/524288,
+     * watchdog of ch56x may be quite limited with very short timeout.
+    */
+    seconds = 30;
+    wdg_dev = rt_device_find("wdt");
+    if (!wdg_dev)
+    {
+        rt_kprintf("watchdog device not found !\n");
+    }
+    else if (rt_device_init(wdg_dev) != RT_EOK ||
+             rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &seconds) != RT_EOK)
+    {
+        rt_kprintf("watchdog setup failed !\n");
+    }
+    else
+    {
+        rt_kprintf("WDT_TIMEOUT in %d seconds, trigger gpio interrupt to keep alive.\n\n", seconds);
+    }
+#endif
+
+#ifdef RT_USING_HWTIMER
+    /* setup two timers, ONESHOT & PERIOD each
+    */
+    tmr_dev_0 = rt_device_find("timer0");
+    tmr_dev_1 = rt_device_find("timer1");
+    if (tmr_dev_0 == RT_NULL || tmr_dev_1 == RT_NULL)
+    {
+        rt_kprintf("hwtimer device(s) not found !\n");
+    }
+    else if (rt_device_open(tmr_dev_0, RT_DEVICE_OFLAG_RDWR) != RT_EOK ||
+             rt_device_open(tmr_dev_1, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
+    {
+        rt_kprintf("hwtimer device(s) open failed !\n");
+    }
+    else
+    {
+        rt_device_set_rx_indicate(tmr_dev_0, tmr_timeout_cb);
+        rt_device_set_rx_indicate(tmr_dev_1, tmr_timeout_cb);
+
+        timerval.sec = 3;
+        timerval.usec = 500000;
+        tsize = sizeof(timerval);
+        mode = HWTIMER_MODE_ONESHOT;
+        if (rt_device_control(tmr_dev_0, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK)
+        {
+            rt_kprintf("timer0 set mode failed !\n");
+        }
+        else if (rt_device_write(tmr_dev_0, 0, &timerval, tsize) != tsize)
+        {
+            rt_kprintf("timer0 start failed !\n");
+        }
+        else
+        {
+            rt_kprintf("timer0 started !\n");
+        }
+
+        timerval.sec = 5;
+        timerval.usec = 0;
+        tsize = sizeof(timerval);
+        mode = HWTIMER_MODE_PERIOD;
+        if (rt_device_control(tmr_dev_1, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK)
+        {
+            rt_kprintf("timer1 set mode failed !\n");
+        }
+        else if (rt_device_write(tmr_dev_1, 0, &timerval, tsize) != tsize)
+        {
+            rt_kprintf("timer1 start failed !\n");
+        }
+        else
+        {
+            rt_kprintf("timer1 started !\n");
+        }
+    }
+#endif
+
+    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
+    rt_pin_write(LED1_PIN, led1 = PIN_HIGH);
+
+    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
+    rt_pin_write(LED0_PIN, led0 = PIN_LOW);
+
+    while (1)
+    {
+        /* flashing LED0 every 1 second */
+        rt_thread_mdelay(500);
+        led0 = (led0 == PIN_LOW) ? PIN_HIGH : PIN_LOW;
+        rt_pin_write(LED0_PIN, led0);
+    }
+}

+ 64 - 0
bsp/wch/risc-v/ch569w-evt/board/Kconfig

@@ -0,0 +1,64 @@
+menu "Hardware Drivers Config"
+
+config SOC_CH569W
+    bool
+    select SOC_FAMILY_CH56X
+    select SOC_SERIES_CH569
+    select RT_USING_COMPONENTS_INIT
+    select RT_USING_USER_MAIN
+    default y
+
+menu "On-chip Peripheral Drivers"
+
+config BSP_USING_UART
+    bool "using on-chip uart"
+    select RT_USING_SERIAL
+    default y
+
+    if BSP_USING_UART
+        config BSP_USING_UART0
+        bool "using UART0"
+        default n
+
+        config BSP_USING_UART1
+        bool "using UART1"
+        default y
+
+        config BSP_USING_UART2
+        bool "using UART2"
+        default n
+
+        config BSP_USING_UART3
+        bool "using UART3"
+        default n
+    endif
+
+config BSP_USING_TIMER
+    bool "using on-chip timer"
+    select RT_USING_HWTIMER
+    default n
+
+    if BSP_USING_TIMER
+        config BSP_USING_TMR0
+        bool "using TMR0"
+        default y
+
+        config BSP_USING_TMR1
+        bool "using TMR1"
+        default n
+
+        config BSP_USING_TMR2
+        bool "using TMR2"
+        default n
+    endif
+endmenu
+
+menu "Onboard Peripheral Drivers"
+
+endmenu
+
+menu "Board extended module Drivers"
+
+endmenu
+
+endmenu

+ 13 - 0
bsp/wch/risc-v/ch569w-evt/board/SConscript

@@ -0,0 +1,13 @@
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+board.c
+startup_gcc.S
+''')
+
+path = [cwd]
+
+group = DefineGroup('Drivers', src, depend=[''], CPPPATH=path)
+Return('group')

+ 80 - 0
bsp/wch/risc-v/ch569w-evt/board/board.c

@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#include <rthw.h>
+#include <drivers/pin.h>
+#include "board.h"
+#include "ch56x_pfic.h"
+#include "ch56x_uart.h"
+
+extern rt_uint32_t rt_thread_switch_interrupt_flag;
+
+/* FIXME: Use rt_interrupt_leave_hook to trigger SWI for context switch.
+ * Hopefully there's a standard riscv way instead of this clumsy patch.
+*/
+static void irq_leave_hook(void)
+{
+    if (rt_thread_switch_interrupt_flag)
+    {
+        pfic_swi_pendset();
+    }
+}
+
+/*
+ * _start -> handle_reset
+ * src/components.c/entry() -> rtthread_startup()
+ * libcpu/risc-v/common/context_gcc.S/rt_hw_interrupt_disable
+ */
+void rt_hw_board_init()
+{
+    volatile struct pfic_registers *pfic = (void *)PFIC_REG_BASE;
+
+    /* disable all pfic interrupts */
+    pfic->IRER[0] = PFIC_IREG1_MASK;
+    pfic->IRER[1] = PFIC_IREG2_MASK;
+
+    /* disable hwstack push/pop & nested interrupt */
+    pfic->CFGR = cfgr_nest_hwstk(CFGR_NESTCTRL_DISABLE | CFGR_HWSTKCTRL_DISABLE);
+
+    /* disable clock input for all peripheral devices */
+    sys_slp_clk_off0(0xff, SYS_SLP_CLK_OFF);
+    sys_slp_clk_off1(0xff, SYS_SLP_CLK_OFF);
+    sys_clk_off_by_irqn(ETH_IRQn, SYS_SLP_CLK_OFF);
+    sys_clk_off_by_irqn(ECDC_IRQn, SYS_SLP_CLK_OFF);
+
+    /* setup HCLK for systick & peripheral devices */
+    sys_hclk_set(SYS_HCLK_FREQ);
+
+    /* set SysTick to RT_TICK_PER_SECOND with current HCLK */
+    systick_init(0);
+
+    /* Note: keep MSTATUS_MIE disabled to prevent SysTick from processing
+     * thread scheduling, which may not be ready upon 1st systick irq.
+     * MSTATUS_MIE will be set when rt_system_scheduler_start() starts
+     * the first thread and copies mstatus from stack_frame.
+     */
+
+#ifdef RT_USING_HEAP
+    rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
+#endif
+
+#ifdef RT_USING_COMPONENTS_INIT
+    rt_components_board_init();
+#endif
+
+#ifdef RT_USING_CONSOLE
+    /* console is uart1, TXD1/RXD1 : PA8/PA7 */
+    rt_pin_mode(GET_PIN(A, 8), PIN_MODE_OUTPUT);
+    rt_pin_mode(GET_PIN(A, 7), PIN_MODE_INPUT_PULLUP);
+    rt_hw_uart_init();
+    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif
+
+    rt_interrupt_leave_sethook(irq_leave_hook);
+}

+ 36 - 0
bsp/wch/risc-v/ch569w-evt/board/board.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2022-07-15     Emuzit            first version
+ */
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+#include <stdint.h>
+#include "ch56x_sys.h"
+#include "ch56x_gpio.h"
+
+#define LED0_PIN            GET_PIN(B, 24)
+#define LED1_PIN            GET_PIN(B, 22)
+#define LED2_PIN            GET_PIN(B, 23)
+
+#define SYS_HCLK_FREQ       80000000  // 80 MHz
+
+#define RAMX_SIZE           32  // USER_MEM 00/01/1x : 32/64/96 KB
+#define RAMX_END            (RAMX_BASE_ADDRESS + RAMX_SIZE * 1024)
+
+extern uint32_t _ebss, _heap_end;
+extern uint32_t _susrstack, _eusrstack;
+
+#define HEAP_BEGIN          ((void *)&_ebss)
+#define HEAP_END            ((void *)&_heap_end)
+#define SUSRSTACK           ((void *)&_susrstack)
+#define EUSRSTACK           ((void *)&_eusrstack)
+
+void rt_hw_board_init(void);
+
+#endif /* __BOARD_H__ */

+ 199 - 0
bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds

@@ -0,0 +1,199 @@
+ENTRY( _start )
+
+__stack_size = 2048;
+
+PROVIDE( _stack_size = __stack_size );
+
+MEMORY
+{
+	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 96K
+	RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
+	RAMX (xrw) : ORIGIN = 0x20020000, LENGTH = 32K
+}
+
+SECTIONS
+{
+
+	.init :
+	{
+		_sinit = .;
+		. = ALIGN(4);
+		KEEP(*(SORT_NONE(.init)))
+		. = ALIGN(4);
+		_einit = .;
+	} >FLASH AT>FLASH
+
+    .vector :
+    {
+        *(.vector);
+  	    . = ALIGN(64);
+    } >FLASH AT>FLASH
+
+	.text :
+	{
+		. = ALIGN(4);
+		*(.text)
+		*(.text.*)
+		*(.rodata)
+		*(.rodata*)
+		*(.glue_7)
+		*(.glue_7t)
+		*(.gnu.linkonce.t.*)
+
+		/* section information for finsh shell */
+    	. = ALIGN(4);
+    	__fsymtab_start = .;
+    	KEEP(*(FSymTab))
+    	__fsymtab_end = .;
+    	. = ALIGN(4);
+    	__vsymtab_start = .;
+    	KEEP(*(VSymTab))
+    	__vsymtab_end = .;
+    	. = ALIGN(4);
+
+    	/* section information for initial. */
+    	. = ALIGN(4);
+    	__rt_init_start = .;
+    	KEEP(*(SORT(.rti_fn*)))
+    	__rt_init_end = .;
+    	. = ALIGN(4);
+
+    	/* section information for modules */
+    	. = ALIGN(4);
+    	__rtmsymtab_start = .;
+    	KEEP(*(RTMSymTab))
+    	__rtmsymtab_end = .;
+		. = 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 :
+	{
+    	*(.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 = . );
+	
+	.dmadata :
+    {
+        . = ALIGN(16);
+        PROVIDE( _dmadata_start = .);
+        *(.dmadata*)
+        *(.dmadata.*)
+        . = ALIGN(16);
+        PROVIDE( _dmadata_end = .);
+    } >RAMX AT>FLASH /**/
+
+    .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
+    {
+        PROVIDE( _heap_end = . );
+        . = ALIGN(4);
+        PROVIDE(_susrstack = . );
+        . = . + __stack_size;
+        PROVIDE( _eusrstack = .);
+    } >RAM 
+}

+ 174 - 0
bsp/wch/risc-v/ch569w-evt/board/startup_gcc.S

@@ -0,0 +1,174 @@
+/********************************** (C) COPYRIGHT *******************************
+* File Name          : startup_gcc.s
+* Author             : WCH
+* Version            : V1.0
+* Date               : 2020/07/31
+* Description        : CH56x vector table for eclipse toolchain.
+*******************************************************************************/
+
+	.section	.init,"ax",@progbits
+	.global	_start
+	.align	1
+_start:
+	j	handle_reset
+
+    .section    .vector,"ax",@progbits
+    .align  1
+_vector_base:
+    .option norvc;
+    .word   0
+    .word   0
+        j   nmi_handler
+        j   hardfault_handler
+    .word   0
+    .word   0
+    .word   0
+    .word   0
+    .word   0
+    .word   0
+    .word   0
+    .word   0
+        j   systick_handler
+    .word   0
+        j   swi_handler
+    .word   0
+    /* External Interrupts */
+        j   wdog_irq_handler
+        j   tmr0_irq_handler
+        j   gpio_irq_handler
+        j   spi0_irq_handler
+        j   usbss_irq_handler
+        j   link_irq_handler
+        j   tmr1_irq_handler
+        j   tmr2_irq_handler
+        j   uart0_irq_handler
+        j   usbhs_irq_handler
+        j   emmc_irq_handler
+        j   dvp_irq_handler
+        j   hspi_irq_handler
+        j   spi1_irq_handler
+        j   uart1_irq_handler
+        j   uart2_irq_handler
+        j   uart3_irq_handler
+        j   serdes_irq_handler
+        j   eth_irq_handler
+        j   pmt_irq_handler
+        j   ecdc_irq_handler
+
+    .option rvc;
+
+    .section    .text.vector_handler,"ax", @prsocogbits
+
+    .weak   nmi_handler
+    .weak   hardfault_handler
+    .weak   systick_handler
+    .weak   swi_handler
+    .weak   wdog_irq_handler
+    .weak   tmr0_irq_handler
+    .weak   gpio_irq_handler
+    .weak   spi0_irq_handler
+    .weak   usbss_irq_handler
+    .weak   link_irq_handler
+    .weak   tmr1_irq_handler
+    .weak   tmr2_irq_handler
+    .weak   uart0_irq_handler
+    .weak   usbhs_irq_handler
+    .weak   emmc_irq_handler
+    .weak   dvp_irq_handler
+    .weak   hspi_irq_handler
+    .weak   spi1_irq_handler
+    .weak   uart1_irq_handler
+    .weak   uart2_irq_handler
+    .weak   uart3_irq_handler
+    .weak   serdes_irq_handler
+    .weak   eth_irq_handler
+    .weak   pmt_irq_handler
+    .weak   ecdc_irq_handler
+
+nmi_handler:        j .L_rip
+hardfault_handler:  j .L_rip
+systick_handler:    j .L_rip
+swi_handler:        j .L_rip
+wdog_irq_handler:   j .L_rip
+tmr0_irq_handler:   j .L_rip
+gpio_irq_handler:   j .L_rip
+spi0_irq_handler:   j .L_rip
+usbss_irq_handler:  j .L_rip
+link_irq_handler:   j .L_rip
+tmr1_irq_handler:   j .L_rip
+tmr2_irq_handler:   j .L_rip
+uart0_irq_handler:  j .L_rip
+usbhs_irq_handler:  j .L_rip
+emmc_irq_handler:   j .L_rip
+dvp_irq_handler:    j .L_rip
+hspi_irq_handler:   j .L_rip
+spi1_irq_handler:   j .L_rip
+uart1_irq_handler:  j .L_rip
+uart2_irq_handler:  j .L_rip
+uart3_irq_handler:  j .L_rip
+serdes_irq_handler: j .L_rip
+eth_irq_handler:    j .L_rip
+pmt_irq_handler:    j .L_rip
+ecdc_irq_handler:   j .L_rip
+
+.L_rip:
+    csrr t0, mepc
+    csrr t1, mstatus
+    csrr t2, mcause
+    csrr t3, mtval
+    csrr t4, mscratch
+1:  j 1b
+
+	.section	.text.handle_reset,"ax",@progbits
+	.weak	handle_reset
+	.align	1
+handle_reset:
+    .option push 
+    .option	norelax 
+	la gp, __global_pointer$
+    .option	pop 
+1:
+	la sp, _eusrstack 
+
+/* Load data section from flash to RAM */
+2:	
+	la a0, _data_lma
+	la a1, _data_vma
+	la a2, _edata
+	bgeu a1, a2, 2f
+1:
+	lw t0, (a0)
+	sw t0, (a1)
+	addi a0, a0, 4
+	addi a1, a1, 4
+	bltu a1, a2, 1b
+/* clear bss section */
+2:
+	la a0, _sbss
+	la a1, _ebss
+	bgeu a0, a1, 2f
+1:
+	sw zero, (a0)
+	addi a0, a0, 4
+	bltu a0, a1, 1b
+
+/* clear dmadata section */
+2:
+    la a0, _dmadata_start
+    la a1, _dmadata_end
+    bgeu a0, a1, 2f
+1:
+    sw zero, (a0)
+    addi a0, a0, 4
+    bltu a0, a1, 1b
+
+2:
+	/* leave all interrupt disabled */
+    li t0, 0x1800
+    csrs mstatus, t0
+	la t0, _vector_base
+    ori t0, t0, 1
+	csrw mtvec, t0
+	la t0, entry
+	csrw mepc, t0
+	mret

二进制
bsp/wch/risc-v/ch569w-evt/figures/ch569w-evt.jpeg


+ 192 - 0
bsp/wch/risc-v/ch569w-evt/rtconfig.h

@@ -0,0 +1,192 @@
+#ifndef RT_CONFIG_H__
+#define RT_CONFIG_H__
+
+/* Automatically generated file; DO NOT EDIT. */
+/* RT-Thread Configuration */
+
+/* RT-Thread Kernel */
+
+#define RT_NAME_MAX 8
+#define RT_ALIGN_SIZE 4
+#define RT_THREAD_PRIORITY_32
+#define RT_THREAD_PRIORITY_MAX 32
+#define RT_TICK_PER_SECOND 200
+#define RT_USING_HOOK
+#define RT_HOOK_USING_FUNC_PTR
+#define RT_USING_IDLE_HOOK
+#define RT_IDLE_HOOK_LIST_SIZE 4
+#define IDLE_THREAD_STACK_SIZE 384
+
+/* kservice optimization */
+
+#define RT_KSERVICE_USING_STDLIB
+
+/* Inter-Thread communication */
+
+#define RT_USING_SEMAPHORE
+#define RT_USING_MUTEX
+#define RT_USING_MAILBOX
+
+/* Memory Management */
+
+#define RT_USING_MEMPOOL
+#define RT_USING_SMALL_MEM
+#define RT_USING_SMALL_MEM_AS_HEAP
+#define RT_USING_HEAP
+
+/* Kernel Device Object */
+
+#define RT_USING_DEVICE
+#define RT_USING_INTERRUPT_INFO
+#define RT_USING_CONSOLE
+#define RT_CONSOLEBUF_SIZE 128
+#define RT_CONSOLE_DEVICE_NAME "uart1"
+#define RT_VER_NUM 0x40101
+#define ARCH_RISCV
+
+/* RT-Thread Components */
+
+#define RT_USING_COMPONENTS_INIT
+#define RT_USING_USER_MAIN
+#define RT_MAIN_THREAD_STACK_SIZE 2048
+#define RT_MAIN_THREAD_PRIORITY 10
+#define RT_USING_MSH
+#define RT_USING_FINSH
+#define FINSH_USING_MSH
+#define FINSH_THREAD_NAME "tshell"
+#define FINSH_THREAD_PRIORITY 20
+#define FINSH_THREAD_STACK_SIZE 4096
+#define FINSH_USING_HISTORY
+#define FINSH_HISTORY_LINES 5
+#define FINSH_USING_SYMTAB
+#define FINSH_CMD_SIZE 80
+#define MSH_USING_BUILT_IN_COMMANDS
+#define FINSH_USING_DESCRIPTION
+#define FINSH_ARG_MAX 10
+
+/* Device Drivers */
+
+#define RT_USING_DEVICE_IPC
+#define RT_USING_SERIAL
+#define RT_USING_SERIAL_V1
+#define RT_SERIAL_RB_BUFSZ 64
+#define RT_USING_HWTIMER
+#define RT_USING_PIN
+#define RT_USING_WDT
+
+/* Using USB */
+
+
+/* C/C++ and POSIX layer */
+
+#define RT_LIBC_DEFAULT_TIMEZONE 8
+
+/* POSIX (Portable Operating System Interface) layer */
+
+
+/* Interprocess Communication (IPC) */
+
+
+/* Socket is in the 'Network' category */
+
+
+/* Network */
+
+
+/* Utilities */
+
+
+/* RT-Thread Utestcases */
+
+
+/* RT-Thread online packages */
+
+/* IoT - internet of things */
+
+
+/* Wi-Fi */
+
+/* Marvell WiFi */
+
+
+/* Wiced WiFi */
+
+
+/* IoT Cloud */
+
+
+/* security packages */
+
+
+/* language packages */
+
+/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
+
+
+/* XML: Extensible Markup Language */
+
+
+/* multimedia packages */
+
+/* LVGL: powerful and easy-to-use embedded GUI library */
+
+
+/* u8g2: a monochrome graphic library */
+
+
+/* PainterEngine: A cross-platform graphics application framework written in C language */
+
+
+/* tools packages */
+
+
+/* system packages */
+
+/* enhanced kernel services */
+
+
+/* acceleration: Assembly language or algorithmic acceleration packages */
+
+
+/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
+
+
+/* Micrium: Micrium software products porting for RT-Thread */
+
+
+/* peripheral libraries and drivers */
+
+
+/* AI packages */
+
+
+/* miscellaneous packages */
+
+/* project laboratory */
+
+/* samples: kernel and components samples */
+
+
+/* entertainment: terminal games and other interesting software packages */
+
+#define SOC_FAMILY_CH56X
+#define SOC_SERIES_CH569
+
+/* Hardware Drivers Config */
+
+#define SOC_CH569W
+
+/* On-chip Peripheral Drivers */
+
+#define BSP_USING_UART
+#define BSP_USING_UART1
+#define BSP_USING_TIMER
+#define BSP_USING_TMR0
+#define BSP_USING_TMR1
+
+/* Onboard Peripheral Drivers */
+
+/* Board extended module Drivers */
+
+
+#endif

+ 62 - 0
bsp/wch/risc-v/ch569w-evt/rtconfig.py

@@ -0,0 +1,62 @@
+import os
+ARCH     = 'risc-v'
+CPU      = 'ch56x'
+# toolchains options
+CROSS_TOOL  = 'gcc'
+
+#------- toolchains path -------------------------------------------------------
+if os.getenv('RTT_CC'):
+    CROSS_TOOL = os.getenv('RTT_CC')
+
+if  CROSS_TOOL == 'gcc':
+    PLATFORM    = 'gcc'
+    EXEC_PATH   = r'/opt/mrs-riscv-none-embed/bin'
+else:
+    print('Please make sure your toolchains is GNU GCC!')
+    exit(0)
+
+if os.getenv('RTT_EXEC_PATH'):
+    EXEC_PATH = os.getenv('RTT_EXEC_PATH')
+
+#BUILD = 'debug'
+BUILD = 'release'
+
+CORE = 'risc-v'
+MAP_FILE = 'rtthread.map'
+LINK_FILE = './board/linker_scripts/link.lds'
+TARGET_NAME = 'rtthread.bin'
+
+#------- GCC settings ----------------------------------------------------------
+if PLATFORM == 'gcc':
+    # toolchains
+    PREFIX = 'riscv-none-embed-'
+    CC = PREFIX + 'gcc'
+    CXX= PREFIX + 'g++'
+    AS = PREFIX + 'gcc'
+    AR = PREFIX + 'ar'
+    LINK = PREFIX + 'gcc'
+    TARGET_EXT = 'elf'
+    SIZE = PREFIX + 'size'
+    OBJDUMP = PREFIX + 'objdump'
+    OBJCPY = PREFIX + 'objcopy'
+
+    DEVICE = ' -march=rv32imac -mabi=ilp32 -DUSE_PLIC -DUSE_M_TIME -DNO_INIT -mcmodel=medany -msmall-data-limit=8 -L.  -nostartfiles  -lc '
+    CFLAGS = DEVICE
+    CFLAGS += ' -save-temps=obj'
+    AFLAGS = '-c'+ DEVICE + ' -x assembler-with-cpp'
+    LFLAGS = DEVICE
+    LFLAGS += ' -Wl,--gc-sections,-cref,-Map=' + MAP_FILE
+    LFLAGS += ' -T ' + LINK_FILE
+    LFLAGS += ' -Wl,-wrap=memset'
+
+    CPATH = ''
+    LPATH = ''
+
+    if BUILD == 'debug':
+        CFLAGS += ' -O0 -g3'
+        AFLAGS += ' -g3'
+    else:
+        CFLAGS += ' -O2'
+
+    POST_ACTION = OBJCPY + ' -O binary $TARGET ' + TARGET_NAME + '\n'
+    POST_ACTION += SIZE + ' $TARGET\n'

+ 1 - 1
libcpu/risc-v/SConscript

@@ -24,7 +24,7 @@ else :
 # cpu porting code files
 if  rtconfig.CPU == "e9xx" :
     group = group + SConscript(os.path.join(rtconfig.VENDOR, rtconfig.CPU, 'SConscript'))
-else :
+elif rtconfig.CPU in list:
     group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript'))
 
 Return('group')

+ 1 - 1
libcpu/risc-v/common/cpuport.c

@@ -138,7 +138,7 @@ rt_uint8_t *rt_hw_stack_init(void       *tentry,
  * #endif
  */
 #ifndef RT_USING_SMP
-void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
+RT_WEAK void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
 {
     if (rt_thread_switch_interrupt_flag == 0)
         rt_interrupt_from_thread = from;