diff --git a/bsp/wch/risc-v/Libraries/Kconfig b/bsp/wch/risc-v/Libraries/Kconfig index 6482c47a1d07583596cdbea7a700b3169313f03e..3428efbab851b98ad9fa1d80f32a73c90f854882 100644 --- a/bsp/wch/risc-v/Libraries/Kconfig +++ b/bsp/wch/risc-v/Libraries/Kconfig @@ -5,4 +5,11 @@ config SOC_RISCV_SERIES_CH32V103 bool select ARCH_RISCV select SOC_RISCV_FAMILY_CH32 - \ No newline at end of file + +config SOC_FAMILY_CH56X + bool + select ARCH_RISCV + +config SOC_SERIES_CH569 + bool + select SOC_FAMILY_CH56X diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript b/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..f936f62cebfd1bcebc561d273674ec7d3d2cf817 --- /dev/null +++ b/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') diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..94c2116d98646f23984bdceb7ea98747e7e77d96 --- /dev/null +++ b/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 +#include +#include +#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(); +} diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..2b6af1a5d596df826947bcaa69b75d045daf92b3 --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.c new file mode 100644 index 0000000000000000000000000000000000000000..9f012640062c4d17e6a4f65b2b2e7eb0f254c9dd --- /dev/null +++ b/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 +#include +#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(); +} diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pfic.h new file mode 100644 index 0000000000000000000000000000000000000000..be3c6520746fa153ee76ac6109fa7d6745dbdf90 --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c new file mode 100644 index 0000000000000000000000000000000000000000..51305e4a51e48e648ebc1ad993b215a375277168 --- /dev/null +++ b/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 +#include +#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; + } +} diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.h new file mode 100644 index 0000000000000000000000000000000000000000..9b2b7b3e54d1245ca63c4ac638014d9c94738815 --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..be388386c617ccac723e3b3c09dfb95c36b0c0d1 --- /dev/null +++ b/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 +#include +#include +#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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..63a5ebef139609c51e7cef699cbd3d914e88285e --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..d0230d21fb14caa903af6bb884661621730d9a40 --- /dev/null +++ b/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 +#include +#include +#include +#ifdef RT_USING_SERIAL_V2 + #include +#else + #include +#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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..c34c6b5c21dcf0c91b921b25a9a94e0028011188 --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_wdt.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_wdt.c new file mode 100644 index 0000000000000000000000000000000000000000..200f71b0616376e2bd63eaa38eb0ffda15c2c665 --- /dev/null +++ b/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 +#include +#include +#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(); +} diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/isr_sp.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/isr_sp.h new file mode 100644 index 0000000000000000000000000000000000000000..54c33ed942ed4bdb2a1bcbe8c70416b7d6e32dc6 --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h new file mode 100644 index 0000000000000000000000000000000000000000..579996bcdd0c9f4e0402db0bd3c8e938214a3876 --- /dev/null +++ b/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 +#include +#include + +#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 diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/swi_gcc.S b/bsp/wch/risc-v/Libraries/ch56x_drivers/swi_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..3e064e7b5956cc8645ab2ac95fff6cf8b9bedf8d --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/ch569w-evt/.config b/bsp/wch/risc-v/ch569w-evt/.config new file mode 100644 index 0000000000000000000000000000000000000000..cb3bcbf285116f89a4624f260bea7e957f8af05c --- /dev/null +++ b/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 +# diff --git a/bsp/wch/risc-v/ch569w-evt/Kconfig b/bsp/wch/risc-v/ch569w-evt/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..c80a8958fdc8cdb2521a824c4755f36942434fca --- /dev/null +++ b/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" diff --git a/bsp/wch/risc-v/ch569w-evt/SConscript b/bsp/wch/risc-v/ch569w-evt/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..fab6e36f215d5c20368c4e160437c0000e1c9303 --- /dev/null +++ b/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') diff --git a/bsp/wch/risc-v/ch569w-evt/SConstruct b/bsp/wch/risc-v/ch569w-evt/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..0264ce6202773e5debe7a6527ae1dc1148a21624 --- /dev/null +++ b/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) diff --git a/bsp/wch/risc-v/ch569w-evt/applications/SConscript b/bsp/wch/risc-v/ch569w-evt/applications/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..72c14ab8db02835c0a5bf42c4059b7b0a5f227fb --- /dev/null +++ b/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') diff --git a/bsp/wch/risc-v/ch569w-evt/applications/main.c b/bsp/wch/risc-v/ch569w-evt/applications/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3c126ce04f99afa5484bbb05231782d63a431b79 --- /dev/null +++ b/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 +#include +#include +#include +#include +#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); + } +} diff --git a/bsp/wch/risc-v/ch569w-evt/board/Kconfig b/bsp/wch/risc-v/ch569w-evt/board/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..80a2613d0328ec361b8ae1459c74f46550fa1c0f --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/ch569w-evt/board/SConscript b/bsp/wch/risc-v/ch569w-evt/board/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..fee2061360e8aebc15f7a2891d2b090ec023b740 --- /dev/null +++ b/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') diff --git a/bsp/wch/risc-v/ch569w-evt/board/board.c b/bsp/wch/risc-v/ch569w-evt/board/board.c new file mode 100644 index 0000000000000000000000000000000000000000..6b4b6dbc81e41b0dd321e904386a65854fc4b2ec --- /dev/null +++ b/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 +#include +#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); +} diff --git a/bsp/wch/risc-v/ch569w-evt/board/board.h b/bsp/wch/risc-v/ch569w-evt/board/board.h new file mode 100644 index 0000000000000000000000000000000000000000..631352203ce17852e1ca6b545abf16f4c58e6862 --- /dev/null +++ b/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 +#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__ */ diff --git a/bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds b/bsp/wch/risc-v/ch569w-evt/board/linker_scripts/link.lds new file mode 100644 index 0000000000000000000000000000000000000000..41dce1bbea31f2b791fd07b744293eba729ce8b5 --- /dev/null +++ b/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 +} diff --git a/bsp/wch/risc-v/ch569w-evt/board/startup_gcc.S b/bsp/wch/risc-v/ch569w-evt/board/startup_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..71649eff1e3ae7c4e9951539b043db09fd861160 --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/ch569w-evt/figures/ch569w-evt.jpeg b/bsp/wch/risc-v/ch569w-evt/figures/ch569w-evt.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..74e645b708aa25bb55d8f0232bf37c24284c24f6 Binary files /dev/null and b/bsp/wch/risc-v/ch569w-evt/figures/ch569w-evt.jpeg differ diff --git a/bsp/wch/risc-v/ch569w-evt/rtconfig.h b/bsp/wch/risc-v/ch569w-evt/rtconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..99bad3ce80ae05e2e8cc9b6a42e1a40b3c380e2c --- /dev/null +++ b/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 diff --git a/bsp/wch/risc-v/ch569w-evt/rtconfig.py b/bsp/wch/risc-v/ch569w-evt/rtconfig.py new file mode 100644 index 0000000000000000000000000000000000000000..d6e291657a412a12e54790c4901b203adba0f176 --- /dev/null +++ b/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' diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript index ffb2e7ae177a81f7af068fc0415887542aa494d8..7e6b9947a36974099a08fd523d590fade988a83e 100644 --- a/libcpu/risc-v/SConscript +++ b/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') diff --git a/libcpu/risc-v/common/cpuport.c b/libcpu/risc-v/common/cpuport.c index 97f34d8c4c36c691b31574140fc436efd7af7910..9e9957e66cb6968ec4e6db701a438424b0f7dbec 100644 --- a/libcpu/risc-v/common/cpuport.c +++ b/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;