feat(bsp): New bsp for ch32 has been added.

1.Add the general part bsp of ch32 (including system clock, software interrupts, interrupt controllers, etc.). Supports V00X/V10X/V20X/V30X (Although the V00X series is supported, the sram of the chip is too small and it is not recommended for use).
This commit is contained in:
MacRsh
2025-07-10 01:08:03 +08:00
parent 2d234791cc
commit 8b077d287c
14 changed files with 423 additions and 71 deletions

View File

@@ -0,0 +1,14 @@
/**
* @copyright (c) 2025, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2025-06-11 MacRsh First version
*/
#include <board/mr_board.h>
void mr_board_init(void) {
/* Init systick */
mr_board_systick_init();
}

118
bsp/wch/common/board/irq.c Normal file
View File

@@ -0,0 +1,118 @@
/**
* @copyright (c) 2025, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2025-06-11 MacRsh First version
*/
#include <board/mr_board.h>
#include <mr_x.h>
#if defined(MR_USE_IRQ)
static void irq_priority_set(mr_uint32_t irq, mr_uint8_t priority, void *param);
static void irq_type_set(mr_uint32_t irq, mr_uint8_t type, void *param);
static void irq_enable(mr_uint32_t irq, void *param);
static void irq_unmask(mr_uint32_t irq, void *param);
static void irq_disable(mr_uint32_t irq, void *param);
static void irq_mask(mr_uint32_t irq, void *param);
static mr_irq_ops_t __ops = {.priority_set = irq_priority_set,
.type_set = irq_type_set,
.enable = irq_enable,
.unmask = irq_unmask,
.disable = irq_disable,
.mask = irq_mask};
static mr_irq_t __irq;
#if defined(MR_USE_IRQ_DEFER_HOOK)
static void irq_defer_hook_suspend(void *param);
static void irq_defer_hook_wakeup(void *param);
static mr_irq_defer_hook_t __hook
= {.suspend = irq_defer_hook_suspend, .wakeup = irq_defer_hook_wakeup};
#endif /* defined(MR_USE_IRQ_DEFER_HOOK) */
#if defined(MR_USE_IRQ)
static void irq_priority_set(mr_uint32_t irq, mr_uint8_t priority,
void *param) {
MR_UNUSED(param);
/* Set irq priority */
NVIC_SetPriority((IRQn_Type)irq, priority);
}
static void irq_type_set(mr_uint32_t irq, mr_uint8_t type, void *param) {
MR_UNUSED(irq);
MR_UNUSED(type);
MR_UNUSED(param);
}
static void irq_enable(mr_uint32_t irq, void *param) {
MR_UNUSED(param);
/* Enable irq */
NVIC_EnableIRQ((IRQn_Type)irq);
}
static void irq_unmask(mr_uint32_t irq, void *param) {
MR_UNUSED(irq);
MR_UNUSED(param);
}
static void irq_disable(mr_uint32_t irq, void *param) {
MR_UNUSED(param);
/* Disable irq */
NVIC_DisableIRQ((IRQn_Type)irq);
}
static void irq_mask(mr_uint32_t irq, void *param) {
MR_UNUSED(irq);
MR_UNUSED(param);
}
#endif /* defined(MR_USE_IRQ) */
#if defined(MR_USE_IRQ_DEFER_HOOK)
static void irq_defer_hook_suspend(void *param) {
MR_UNUSED(param);
/* Clear soft irq */
SysTick->CTLR &= ~(1 << 31);
}
static void irq_defer_hook_wakeup(void *param) {
MR_UNUSED(param);
/* Trigger soft irq */
SysTick->CTLR |= (1 << 31);
}
void SW_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void SW_Handler(void) {
mr_irq_defer_execute();
}
#endif /* defined(MR_USE_IRQ_DEFER_HOOK) */
void mr_board_irq_init(void) {
mr_err_t ret;
#if (MR_CFG_WCH_IRQ_END == MR_CFG_IRQ_TABLE_SIZE)
#error "IRQ size exceed IRQ table, adjust 'MR_CFG_WCH_IRQ_END'"
#endif /* (MR_CFG_WCH_IRQ_END == MR_CFG_IRQ_TABLE_SIZE) */
/* Init irq */
ret = mr_irq_init(&__irq, MR_CFG_WCH_IRQ_BEGIN, MR_CFG_WCH_IRQ_END, &__ops,
MR_NULL);
if (ret != 0) {
MR_ASSERT(ret == 0);
return;
}
#if defined(MR_USE_IRQ_DEFER_HOOK)
/* Init irq defer hook */
mr_irq_defer_hook_set(&__hook);
/* Init NVIC */
NVIC_SetPriority(Software_IRQn, MR_CFG_WCH_IRQ_DEFER_PRIORITY);
NVIC_EnableIRQ(Software_IRQn);
#endif /* defined(MR_USE_IRQ_DEFER_HOOK) */
}
MR_INIT_EXPORT(mr_board_irq_init, MR_INIT_LEVEL_IRQ);
#endif /* defined(MR_USE_IRQ) */

View File

@@ -0,0 +1,44 @@
/**
* @copyright (c) 2025, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2025-06-11 MacRsh First version
*/
#include <board/mr_board.h>
#include <mr_x.h>
static volatile int __irq_nest = 0;
void mr_port_assert(const char *file, int line, const char *expr) {
MR_UNUSED(file);
MR_UNUSED(line);
MR_UNUSED(expr);
}
int mr_port_output(const char *buf, mr_size_t size) {
MR_UNUSED(buf);
MR_UNUSED(size);
return 0;
}
int mr_port_irq_save(void) {
/* Disable interrupt */
__disable_irq();
/* Increment irq nest */
return (++__irq_nest);
}
void mr_port_irq_restore(int mask) {
MR_UNUSED(mask);
/* Decrement irq nest */
if ((--__irq_nest) > 0) {
return;
}
/* Enable interrupt */
__enable_irq();
}

View File

@@ -0,0 +1,39 @@
/**
* @copyright (c) 2025, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2025-06-11 MacRsh First version
*/
#include <board/mr_board.h>
#include <mr_x.h>
extern uint32_t SystemCoreClock;
void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void SysTick_Handler(void) {
/* Clear the interrupt */
SysTick->SR &= ~(1 << 0);
/* Increase clock */
mr_clock_increase(1);
}
static void systick_init(mr_uint32_t tick) {
/* Init systick */
SysTick->CTLR = 0;
SysTick->SR = 0;
SysTick->CNT = 0;
SysTick->CMP = (SystemCoreClock / tick) - 1;
SysTick->CTLR = 0xf;
/* Init NVIC */
NVIC_SetPriority(SysTicK_IRQn, MR_CFG_WCH_SYSTICK_IRQ_PRIORITY);
NVIC_EnableIRQ(SysTicK_IRQn);
}
void mr_board_systick_init(void) {
/* Init systick */
systick_init(MR_CFG_TICK_PER_SECOND);
}

View File

@@ -0,0 +1,68 @@
menu "Board options"
# ==================================
# BOARD
# ==================================
config MR_USE_BOARD
def_bool y
# ==================================
# SERIES
# ==================================
choice
prompt "Series"
default MR_USE_SERIES_V30X
config MR_USE_SERIES_V00X
bool "V00X"
config MR_USE_SERIES_V10X
bool "V10X"
config MR_USE_SERIES_V20X
bool "V20X"
config MR_USE_SERIES_V30X
bool "V30X"
endchoice
# ==================================
# SYSTICK
# ==================================
config MR_CFG_WCH_SYSTICK_IRQ_PRIORITY
int "Systick irq priority"
default 1
range 0 15
# ==================================
# NVIC
# ==================================
config MR_CFG_WCH_IRQ_DEFER_PRIORITY
int "Defer irq priority"
default 2
range MR_CFG_WCH_SYSTICK_IRQ_PRIORITY 15
config MR_CFG_WCH_IRQ_BEGIN
int "IRQ begin"
default 16
range 2 MR_CFG_IRQ_TABLE_SIZE
config MR_CFG_WCH_IRQ_END
int "IRQ end"
default 38 if MR_USE_SERIES_V00X
default 59 if MR_USE_SERIES_V10X
default 69 if MR_USE_SERIES_V20X
default 103 if MR_USE_SERIES_V30X
range MR_CFG_WCH_IRQ_BEGIN MR_CFG_IRQ_TABLE_SIZE
if MR_CFG_WCH_IRQ_END=MR_CFG_IRQ_TABLE_SIZE
comment "IRQ size exceed IRQ table, adjust 'Irq table size'"
endif
if MR_CFG_WCH_IRQ_END<MR_CFG_IRQ_TABLE_SIZE
config MR_USE_WCH_IRQ_DEFER_HOOK
select MR_USE_IRQ_DEFER_HOOK
def_bool y
endif
endmenu

View File

@@ -0,0 +1,46 @@
/**
* @copyright (c) 2024, MacRsh
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2024-06-12 MacRsh First version
*/
#ifndef __MR_BOARD_H__
#define __MR_BOARD_H__
#include <mr_config.h>
#if defined(MR_USE_SERIES_V00X)
#include "ch32v00x.h"
#elif defined(MR_USE_SERIES_V10X)
#include "ch32v10x.h"
#elif defined(MR_USE_SERIES_V20X)
#include "ch32v20x.h"
#elif defined(MR_USE_SERIES_V30X)
#include "ch32v30x.h"
#else
#error "Series not supported"
#endif /* defined(MR_USE_SERIES_V00X) */
#include "core_riscv.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @addtogroup Board
* @{
*/
/**
* @brief This function initializes the board systick.
*/
void mr_board_systick_init(void);
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MR_BOARD_H__ */

View File

@@ -14,6 +14,26 @@ choice
bool "64B"
endchoice
# ==================================
# ASSERT
# ==================================
choice
prompt "Assertion"
default MR_USE_ASSERT
config MR_USE_ASSERT_LIBC
bool "STD"
config MR_USE_ASSERT_3PARTY
bool "3RD"
config MR_USE_ASSERT
bool "INT"
config MR_USE_ASSERT_NONE
bool "NONE"
endchoice
# ==================================
# MALLOC
# ==================================
@@ -37,23 +57,6 @@ config MR_CFG_HEAP_SIZE
default 4096
range 24 2147483647
# ==================================
# ASSERT
# ==================================
choice
prompt "Assertion"
default MR_USE_ASSERT
config MR_USE_ASSERT_LIBC
bool "STD"
config MR_USE_ASSERT_3PARTY
bool "3RD"
config MR_USE_ASSERT
bool "INT"
endchoice
# ==================================
# SPRINTF
# ==================================
@@ -108,7 +111,24 @@ endchoice
config MR_USE_STRING_SAFE
depends on MR_USE_STRING
bool "Use string null-ptr safety"
default y
default n
# ==================================
# ATOMIC
# ==================================
choice
prompt "Atomic"
default MR_USE_ATOMIC
config MR_USE_ATOMIC_LIBC
bool "STD"
config MR_USE_ATOMIC_3PARTY
bool "3RD"
config MR_USE_ATOMIC
bool "INT"
endchoice
# ==================================
# TYPES

View File

@@ -10,15 +10,15 @@
#define __MR_LIBC_ATOMIC_H__
#include <mr_config.h>
#if defined(MR_USE_3PARTY_ATOMIC)
#if defined(MR_USE_ATOMIC_LIBC)
#include <stdatomic.h>
#elif defined(MR_USE_3PARTY_ATOMIC)
#include <3party/libc/mr_atomic.h>
#else
#include <port/mr_port_irq.h>
#endif /* defined(MR_USE_3PARTY_ATOMIC) */
#include <libc/mr_compiler.h>
#include <libc/mr_types.h>
#if !defined(__ATOMIC_SEQ_CST)
#include <port/mr_port_irq.h>
#endif /* !defined(__ATOMIC_SEQ_CST) */
#endif /* defined(MR_USE_3PARTY_ATOMIC) */
#ifdef __cplusplus
extern "C" {
@@ -30,7 +30,28 @@ extern "C" {
*/
/* Atomic definition */
#if defined(MR_USE_3PARTY_ATOMIC)
#if defined(MR_USE_ATOMIC_LIBC)
typedef atomic_int mr_atomic_t;
#define MR_ATOMIC_INIT(_val) ATOMIC_VAR_INIT(_val)
#define mr_atomic_init(_a, _val) atomic_init(_a, _val)
#define mr_atomic_load(_a) \
atomic_load_explicit(_a, memory_order_seq_cst)
#define mr_atomic_store(_a, _val) \
atomic_store_explicit(_a, _val, memory_order_seq_cst)
#define mr_atomic_exchange(_a, _val) \
atomic_exchange_explicit(_a, _val, memory_order_seq_cst)
#define mr_atomic_compare_exchange(_a, _val, _desired) \
atomic_compare_exchange_strong_explicit( \
_a, _val, _desired, memory_order_seq_cst, memory_order_seq_cst)
#define mr_atomic_fetch_add(_a, _val) \
atomic_fetch_add_explicit(_a, _val, memory_order_seq_cst)
#define mr_atomic_fetch_sub(_a, _val) \
atomic_fetch_sub_explicit(_a, _val, memory_order_seq_cst)
#define mr_atomic_fetch_and(_a, _val) \
atomic_fetch_and_explicit(_a, _val, memory_order_seq_cst)
#define mr_atomic_fetch_or(_a, _val) \
atomic_fetch_or_explicit(_a, _val, memory_order_seq_cst)
#elif defined(MR_USE_3PARTY_ATOMIC)
/* In '3party/libc/mr_atomic.h' */
#else
/* Atomic type */
@@ -64,10 +85,6 @@ MR_INLINE mr_atomic_t mr_atomic_load(volatile mr_atomic_t *atomic) {
mr_atomic_t tmp;
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
tmp = __atomic_load_n(atomic, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -76,7 +93,6 @@ MR_INLINE mr_atomic_t mr_atomic_load(volatile mr_atomic_t *atomic) {
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
return tmp;
}
@@ -89,10 +105,6 @@ MR_INLINE mr_atomic_t mr_atomic_load(volatile mr_atomic_t *atomic) {
MR_INLINE void mr_atomic_store(volatile mr_atomic_t *atomic, mr_atomic_t val) {
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
__atomic_store_n(atomic, val, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -101,7 +113,6 @@ MR_INLINE void mr_atomic_store(volatile mr_atomic_t *atomic, mr_atomic_t val) {
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
}
/**
@@ -116,10 +127,6 @@ MR_INLINE mr_atomic_t mr_atomic_exchange(volatile mr_atomic_t *atomic,
mr_atomic_t tmp;
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
tmp = __atomic_exchange_n(atomic, val, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -129,7 +136,6 @@ MR_INLINE mr_atomic_t mr_atomic_exchange(volatile mr_atomic_t *atomic,
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
return tmp;
}
@@ -147,11 +153,6 @@ MR_INLINE mr_bool_t mr_atomic_compare_exchange(volatile mr_atomic_t *atomic,
mr_bool_t tmp;
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
tmp = __atomic_compare_exchange_n(atomic, val, desired, MR_FALSE,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -166,7 +167,6 @@ MR_INLINE mr_bool_t mr_atomic_compare_exchange(volatile mr_atomic_t *atomic,
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
return tmp;
}
@@ -182,10 +182,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_add(volatile mr_atomic_t *atomic,
mr_atomic_t tmp;
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
tmp = __atomic_fetch_add(atomic, val, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -195,7 +191,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_add(volatile mr_atomic_t *atomic,
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
return tmp;
}
@@ -211,10 +206,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_sub(volatile mr_atomic_t *atomic,
mr_atomic_t tmp;
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
tmp = __atomic_fetch_sub(atomic, val, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -224,7 +215,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_sub(volatile mr_atomic_t *atomic,
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
return tmp;
}
@@ -240,10 +230,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_and(volatile mr_atomic_t *atomic,
mr_atomic_t tmp;
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
tmp = __atomic_fetch_and(atomic, val, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -253,7 +239,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_and(volatile mr_atomic_t *atomic,
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
return tmp;
}
@@ -269,10 +254,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_or(volatile mr_atomic_t *atomic,
mr_atomic_t tmp;
int mask;
#if defined(__ATOMIC_SEQ_CST)
MR_UNUSED(mask);
tmp = __atomic_fetch_or(atomic, val, __ATOMIC_SEQ_CST);
#else
/* Disable interrupt */
mask = mr_port_irq_save();
@@ -282,7 +263,6 @@ MR_INLINE mr_atomic_t mr_atomic_fetch_or(volatile mr_atomic_t *atomic,
/* Enable interrupt */
mr_port_irq_restore(mask);
#endif /* defined(__ATOMIC_SEQ_CST) */
return tmp;
}
#endif /* defined(MR_USE_3PARTY_ATOMIC) */

View File

@@ -15,12 +15,17 @@ config MR_CFG_CLOCK_HOOK_SIZE
default 2
range 2 128
config MR_CFG_TICK_PER_SECOND
int "Tick per-second"
default 1000
range 1 2147483647
# ==================================
# PRINTF
# ==================================
config MR_USE_PRINTF
bool "Use printf"
default y
default n
config MR_CFG_PRINTF_BUF_SIZE
depends on MR_USE_PRINTF

View File

@@ -139,13 +139,13 @@ mr_async_t *mr_async_create(mr_async_entry_t *entry, void *param);
mr_err_t mr_async_del(mr_async_t *async);
/**
* @brief This macro function runs an async.
* @brief This macro function binds an async to a workqueue.
*
* @param _async The async.
* @param _queue The workqueue.
*/
#define mr_async_run(_async, _queue) \
mr_workqueue_work(_queue, &(_async)->work)
#define mr_async_bind(_async, _queue) \
mr_workqueue_bind(_queue, &(_async)->work)
/**
* @brief This macro function checks if an async is waiting.
@@ -169,11 +169,22 @@ mr_err_t mr_async_cancel(mr_async_t *async);
*
* @param _async The async.
* @param _wait_async The async to wait.
*
* @note It can generate asynchronous behaviors.
*/
#define mr_async_wait_async(_async, _wait_async) \
mr_await_wait(&(_wait_async)->await, _async)
#if defined(MR_USE_ASYNC_SYNC)
/**
* @brief This macro function runs an async.
*
* @param _async The async.
* @param _queue The workqueue.
*/
#define mr_async_run(_async, _queue) \
mr_workqueue_work(_queue, &(_async)->work)
/**
* @brief This macro function begins an async.
*

View File

@@ -21,6 +21,11 @@ extern "C" {
* @{
*/
/* Clock tick per-second definition */
#if !defined(MR_CFG_TICK_PER_SECOND)
#define MR_CFG_TICK_PER_SECOND (1000)
#endif /* !defined(MR_CFG_TICK_PER_SECOND) */
/* Clock type */
typedef mr_uint32_t mr_tick_t;
#define MR_TICK_MAX MR_UINT32_MAX

View File

@@ -21,6 +21,7 @@ extern "C" {
*/
/* Initcall level definition */
#define MR_INIT_LEVEL_IRQ "1.0"
#define MR_INIT_LEVEL_USER(_level) "2."_level
/* Initcall entry type */

View File

@@ -280,7 +280,8 @@ mr_err_t mr_async_cancel(mr_async_t *async) {
MR_ASSERT((async != MR_NULL) && MR_OBJECT_IS_INITED(async));
MR_ASSERT(MR_OBJECT_CLASS_IS_OR(async, &__async_class1, &__async_class2));
/* Remove async */
/* Cancel async */
mr_work_cancel(&async->work);
async_remove(async);
return 0;
}

View File

@@ -372,7 +372,7 @@ mr_err_t mr_workqueue_hook_set(mr_workqueue_t *queue,
mr_workqueue_hook_t *hook) {
/* Check parameter */
MR_ASSERT((queue != MR_NULL) && MR_OBJECT_IS_INITED(queue));
MR_ASSERT(MR_OBJECT_CLASS_IS_OR(queue, &__class1, &__class2));
MR_ASSERT(MR_OBJECT_CLASS_IS_OR(queue, &__queue_class1, &__queue_class2));
MR_ASSERT(hook != MR_NULL);
/* Set workqueue hook */