feat(async): async supports thread, eventqueue, and real-time mode.

This commit is contained in:
MacRsh
2025-07-11 01:16:36 +08:00
parent 8b077d287c
commit ed8941bb9a
8 changed files with 139 additions and 74 deletions

View File

@@ -29,14 +29,16 @@ 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) */
static mr_uint8_t __irqn[] = {
WWDG_IRQn,
};
#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);
NVIC_SetPriority((IRQn_Type)__irqn[irq], priority);
}
static void irq_type_set(mr_uint32_t irq, mr_uint8_t type, void *param) {
@@ -49,7 +51,7 @@ static void irq_enable(mr_uint32_t irq, void *param) {
MR_UNUSED(param);
/* Enable irq */
NVIC_EnableIRQ((IRQn_Type)irq);
NVIC_EnableIRQ((IRQn_Type)__irqn[irq]);
}
static void irq_unmask(mr_uint32_t irq, void *param) {
@@ -61,14 +63,13 @@ static void irq_disable(mr_uint32_t irq, void *param) {
MR_UNUSED(param);
/* Disable irq */
NVIC_DisableIRQ((IRQn_Type)irq);
NVIC_DisableIRQ((IRQn_Type)__irqn[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) {
@@ -94,12 +95,10 @@ void SW_Handler(void) {
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);
ret = mr_irq_init(&__irq, 0,
MR_MIN(MR_ARRAY_SIZE(__irqn), MR_CFG_IRQ_TABLE_SIZE - 1),
&__ops, MR_NULL);
if (ret != 0) {
MR_ASSERT(ret == 0);
return;

View File

@@ -42,27 +42,8 @@ config MR_CFG_WCH_IRQ_DEFER_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

@@ -34,23 +34,15 @@ extern "C" {
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_load(_a) atomic_load(_a)
#define mr_atomic_store(_a, _val) atomic_store(_a, _val)
#define mr_atomic_exchange(_a, _val) atomic_exchange(_a, _val)
#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)
atomic_compare_exchange_strong(_a, _val, _desired)
#define mr_atomic_fetch_add(_a, _val) atomic_fetch_add(_a, _val)
#define mr_atomic_fetch_sub(_a, _val) atomic_fetch_sub(_a, _val)
#define mr_atomic_fetch_and(_a, _val) atomic_fetch_and(_a, _val)
#define mr_atomic_fetch_or(_a, _val) atomic_fetch_or(_a, _val)
#elif defined(MR_USE_3PARTY_ATOMIC)
/* In '3party/libc/mr_atomic.h' */
#else

View File

@@ -13,9 +13,9 @@
#if defined(MR_USE_STRING_LIBC)
#include <string.h>
#else
#include <libc/mr_types.h>
#endif /* defined(MR_USE_STRING_LIBC) */
#include <libc/mr_compiler.h>
#include <libc/mr_types.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -68,8 +68,8 @@ config MR_USE_IRQ
config MR_CFG_IRQ_TABLE_SIZE
depends on MR_USE_IRQ
int "Irq table size"
default 32
range 4 1024
default 16
range 2 1024
config MR_USE_IRQ_DEFER
depends on MR_USE_IRQ
@@ -91,9 +91,9 @@ config MR_USE_ASYNC
bool "Use async"
default y
config MR_USE_ASYNC_SYNC
config MR_USE_ASYNC_THREAD
depends on MR_USE_ASYNC
bool "Use async sync"
bool "Use async thread"
default n
endmenu

View File

@@ -34,10 +34,21 @@ typedef struct mr_await {
mr_list_t list;
} mr_await_t;
/* Async mode type */
typedef enum mr_async_mode {
#if defined(MR_USE_ASYNC_THREAD)
MR_ASYNC_THREAD,
#endif /* defined(MR_USE_ASYNC_THREAD) */
MR_ASYNC_QUEUE,
MR_ASYNC_RTM,
} mr_async_mode_t;
/* Async type */
typedef struct mr_async {
mr_object_t parent;
#if defined(MR_USE_ASYNC_THREAD)
mr_await_t await;
#endif /* defined(MR_USE_ASYNC_THREAD) */
mr_int32_t label;
mr_list_t list;
mr_work_t work;
@@ -139,13 +150,16 @@ 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 binds an async to a workqueue.
* @brief This function runs an async.
*
* @param _async The async.
* @param _queue The workqueue.
* @param async The async.
* @param mode The async mode.
* @param queue The async workqueue(use on 'MR_ASYNC_QUEUE' or
* 'MR_ASYNC_THREAD').
* @return 0 on success, a negative error code on failure.
*/
#define mr_async_bind(_async, _queue) \
mr_workqueue_bind(_queue, &(_async)->work)
mr_err_t mr_async_run(mr_async_t *async, mr_async_mode_t mode,
mr_workqueue_t *queue);
/**
* @brief This macro function checks if an async is waiting.
@@ -160,10 +174,12 @@ mr_err_t mr_async_del(mr_async_t *async);
* @param async The async.
* @return 0 on success, a negative error code on failure.
*
* @note All async-io may generate asynchronous behaviors, which can be cancelled by this function.
* @note All async-io may generate asynchronous behaviors, which can be
* cancelled by this function.
*/
mr_err_t mr_async_cancel(mr_async_t *async);
#if defined(MR_USE_ASYNC_THREAD)
/**
* @brief This macro function waits for an async.
*
@@ -174,21 +190,15 @@ mr_err_t mr_async_cancel(mr_async_t *async);
*/
#define mr_async_wait_async(_async, _wait_async) \
mr_await_wait(&(_wait_async)->await, _async)
#endif /* defined(MR_USE_ASYNC_THREAD) */
#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)
#if defined(MR_USE_ASYNC_THREAD)
/**
* @brief This macro function begins an async.
*
* @param _async The async.
*
* @note It can only be used async thread mode.
*/
#define mr_async_begin(_async) \
switch ((_async)->label) { \
@@ -199,6 +209,8 @@ mr_err_t mr_async_cancel(mr_async_t *async);
* @brief This macro function ends an async.
*
* @param _async The async.
*
* @note It can only be used async thread mode.
*/
#define mr_async_end(_async) \
(_async)->label = -1; \
@@ -278,7 +290,7 @@ mr_err_t mr_async_cancel(mr_async_t *async);
mr_async_cancel(_async); \
} \
} while (0)
#endif /* defined(MR_USE_ASYNC_SYNC) */
#endif /* defined(MR_USE_ASYNC_THREAD) */
/**
* @brief This function gets an async.

View File

@@ -78,11 +78,11 @@ static void await_remove(mr_await_t *await) {
while (!mr_list_is_empty(&await->list)) {
async = MR_CONTAINER_OF(await->list.next, mr_async_t, list);
/* Resume async */
mr_work_schedule(&async->work);
/* Remove async from waiting list */
mr_list_del(&async->list);
/* Resume async */
mr_work_schedule(&async->work);
}
/* Unlock */
@@ -131,7 +131,10 @@ mr_err_t mr_await_wait(mr_await_t *await, mr_async_t *async) {
}
mr_err_t mr_await_complete(mr_await_t *await) {
mr_async_entry_t *entry;
mr_async_t *async;
mr_list_t rtmlist;
void *param;
int mask;
/* Check parameter */
@@ -143,6 +146,9 @@ mr_err_t mr_await_complete(mr_await_t *await) {
return 0;
}
/* Init real-time list */
mr_list_init(&rtmlist);
/* Lock */
mask = mr_spinlock_lock_irqsave(&__lock);
@@ -153,9 +159,31 @@ mr_err_t mr_await_complete(mr_await_t *await) {
/* Remove async from waiting list */
mr_list_del(&async->list);
/* Force resume async(it might be running a timer) */
mr_work_cancel(&async->work);
mr_work_schedule(&async->work);
/* Check if async is in thread or queue mode */
if (async->work.queue) {
/* Force resume async(it might be running a timer) */
mr_work_cancel(&async->work);
mr_work_schedule(&async->work);
continue;
}
/* Move async to real-time list */
mr_list_move(&async->list, &rtmlist);
}
/* Check real-time list */
while (!mr_list_is_empty(&rtmlist)) {
async = MR_LIST_ENTRY(rtmlist.next, mr_async_t, list);
/* Remove async from real-time list */
mr_list_del(&async->list);
/* Save async entry and param */
entry = (mr_async_entry_t *)async->entry;
param = (void *)async->work.param;
/* Call async entry */
entry(async, param);
}
/* Unlock */
@@ -207,7 +235,9 @@ static mr_err_t async_init(mr_async_t *async, const mr_class_t *class,
mr_ptr_t entry, mr_ptr_t param) {
/* Init async */
mr_work_init(&async->work, async_work_entry, param);
#if defined(MR_USE_ASYNC_THREAD)
mr_await_init(&async->await, 1);
#endif /* defined(MR_USE_ASYNC_THREAD) */
mr_list_init(&async->list);
async->entry = entry;
async->label = 0;
@@ -275,6 +305,55 @@ mr_err_t mr_async_del(mr_async_t *async) {
return 0;
}
mr_err_t mr_async_run(mr_async_t *async, mr_async_mode_t mode,
mr_workqueue_t *queue) {
mr_err_t ret;
/* Check parameter */
MR_ASSERT((async != MR_NULL) && MR_OBJECT_IS_INITED(async));
MR_ASSERT((mode < MR_ASYNC_RTM) && (queue != MR_NULL));
MR_ASSERT(mode <= MR_ASYNC_RTM);
/* Check if mode is workqueue mode */
if (mode == MR_ASYNC_QUEUE
#if defined(MR_USE_ASYNC_THREAD)
|| mode == MR_ASYNC_THREAD
#endif /* defined(MR_USE_ASYNC_THREAD) */
) {
/* Get workqueue */
queue = mr_workqueue_get(queue);
if (!queue) {
return -MR_ENOMEM;
}
}
switch (mode) {
#if defined(MR_USE_ASYNC_THREAD)
case MR_ASYNC_THREAD: {
ret = mr_workqueue_work(queue, &async->work);
break;
}
#endif /* defined(MR_USE_ASYNC_THREAD) */
case MR_ASYNC_QUEUE: {
ret = mr_work_bind(&async->work, queue);
break;
}
case MR_ASYNC_RTM: {
/* Real-time mode */
mr_work_cancel(&async->work);
async->work.queue = MR_NULL;
return 0;
}
default: {
return -MR_EINVAL;
}
}
/* Put workqueue */
mr_workqueue_put(queue);
return ret;
}
mr_err_t mr_async_cancel(mr_async_t *async) {
/* Check parameter */
MR_ASSERT((async != MR_NULL) && MR_OBJECT_IS_INITED(async));
@@ -292,8 +371,10 @@ static mr_async_t *async_obj_release(mr_object_t *obj) {
/* Get async */
async = MR_CONTAINER_OF(obj, mr_async_t, parent);
#if defined(MR_USE_ASYNC_THREAD)
/* Complete await */
mr_await_complete(&async->await);
#endif /* defined(MR_USE_ASYNC_THREAD) */
/* Delete async */
mr_work_del(&async->work);

View File

@@ -215,7 +215,7 @@ static mr_tick_t timer_timeout_check(void) {
void *param;
int mask;
/* Init operation list and tick */
/* Init operation list */
mr_list_init(&oplist);
/* Lock */