diff --git a/bsp/wch/common/board/irq.c b/bsp/wch/common/board/irq.c index 11801bc..f1b1032 100644 --- a/bsp/wch/common/board/irq.c +++ b/bsp/wch/common/board/irq.c @@ -76,14 +76,14 @@ static void irq_defer_hook_suspend(void *priv) { MR_UNUSED(priv); /* Clear soft irq */ - SysTick->CTLR &= ~(1 << 31); + SysTick->CTLR &= ~(1U << 31); } static void irq_defer_hook_wakeup(void *priv) { MR_UNUSED(priv); /* Trigger soft irq */ - SysTick->CTLR |= (1 << 31); + SysTick->CTLR |= (1U << 31); } void SW_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); diff --git a/include/port/mr_port_irq.h b/include/port/mr_port_irq.h index 17e1050..1e6f014 100644 --- a/include/port/mr_port_irq.h +++ b/include/port/mr_port_irq.h @@ -14,7 +14,7 @@ extern "C" { #endif /* __cplusplus */ /** - * @addtogroup Port-IRQ + * @addtogroup Port-irq * @{ */ diff --git a/kernel/fifo.c b/kernel/fifo.c index 89d41b3..6e91ad1 100644 --- a/kernel/fifo.c +++ b/kernel/fifo.c @@ -26,11 +26,11 @@ mr_uint32_t mr_fifo_init(mr_fifo_t *fifo, void *buf, mr_uint32_t size, size = FIFO_ALIGN_POW2_DOWN(size / elemsz); /* Init fifo */ - fifo->buf = buf; - fifo->mask = size - 1; mr_atomic_init(&fifo->ridx, 0); mr_atomic_init(&fifo->widx, 0); fifo->elemsz = elemsz; + fifo->mask = size - 1; + fifo->buf = buf; return size; } diff --git a/kernel/irq.c b/kernel/irq.c index bb26409..a13b349 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -254,6 +254,7 @@ static mr_irq_action_t *irq_action_alloc(mr_uint32_t irq, mr_irq_entry_t *entry, action->defer_entry = defer_entry; #else MR_UNUSED(defer_entry); + MR_UNUSED(ret); #endif /* MR_USE_IRQ_DEFER */ /* Init irq action */ diff --git a/test/kernel/irq.c b/test/kernel/irq.c index 6ecd8fe..eff1f57 100644 --- a/test/kernel/irq.c +++ b/test/kernel/irq.c @@ -43,7 +43,6 @@ static void irq_unmask(mr_uint32_t irq, void *priv) { static void irq_disable(mr_uint32_t irq, void *priv) { MR_UNUSED(priv); - last_irq = (mr_int32_t)irq; } @@ -65,7 +64,6 @@ static mr_irq_ops_t mock_irq_ops = { static mr_irq_return_t test_irq_handler(mr_uint32_t irq, void *owner) { MR_UNUSED(irq); MR_UNUSED(owner); - handle_count++; return MR_IRQ_HANDLED; } diff --git a/test/kernel/wait.c b/test/kernel/wait.c index b206bb5..d34ba86 100644 --- a/test/kernel/wait.c +++ b/test/kernel/wait.c @@ -19,7 +19,6 @@ static void test_waiter_cb(mr_waiter_t *waiter, void *param, mr_uint32_t event) { MR_UNUSED(waiter); MR_UNUSED(param); - trig_status++; last_event = event; last_param = param; @@ -225,7 +224,6 @@ static mr_uint32_t test_check_race(mr_waitable_t *w, void *p) { static mr_uint32_t gen = 0; MR_UNUSED(p); - if ((gen++) == 0) { mr_waitable_complete(w); diff --git a/test/kernel/workqueue.c b/test/kernel/workqueue.c new file mode 100644 index 0000000..282d06a --- /dev/null +++ b/test/kernel/workqueue.c @@ -0,0 +1,324 @@ +/** + * @copyright (c) 2024-2025, MacRsh + * + * @license SPDX-License-Identifier: Apache-2.0 + * + * @date 2024-09-06 MacRsh First version + */ + +#include +#if defined(MR_USE_TEST) +#if defined(MR_USE_WORKQUEUE) +#include + +static void *last_param = MR_NULL; +static int work_run_count = 0; + +static void test_work_entry(struct mr_work *work, void *param) { + MR_UNUSED(work); + work_run_count++; + last_param = param; +} + +/* -------------------------------------------------------------------------- */ +/* Test: Workqueue init / del */ +static void test_workqueue_init_del(void) { + mr_workqueue_t queue; + mr_err_t ret; + + ret = mr_workqueue_init(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&queue), MR_TRUE); + + ret = mr_workqueue_del(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&queue), MR_FALSE); +} +MR_TEST_EXPORT(workqueue, init_del, test_workqueue_init_del); + +/* -------------------------------------------------------------------------- */ +/* Test: Workqueue create / del */ +static void test_workqueue_create_del(void) { + mr_workqueue_t *queue; + mr_err_t ret; + + queue = mr_workqueue_create(); + MR_TEST_ASSERT_NE_PTR(queue, MR_NULL); + MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(queue), MR_TRUE); + + ret = mr_workqueue_del(queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); +} +MR_TEST_EXPORT(workqueue, create_del, test_workqueue_create_del); + +/* -------------------------------------------------------------------------- */ +/* Test: Work init / del */ +static void test_work_init_del(void) { + mr_work_t work; + mr_err_t ret; + + ret = mr_work_init(&work, test_work_entry, (void *)0x1234); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&work), MR_TRUE); + + ret = mr_work_del(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&work), MR_FALSE); +} +MR_TEST_EXPORT(workqueue, work_init_del, test_work_init_del); + +/* -------------------------------------------------------------------------- */ +/* Test: Work create / del */ +static void test_work_create_del(void) { + mr_work_t *work; + mr_err_t ret; + + work = mr_work_create(test_work_entry, (void *)0x5678); + MR_TEST_ASSERT_NE_PTR(work, MR_NULL); + MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(work), MR_TRUE); + + ret = mr_work_del(work); + MR_TEST_ASSERT_EQ_INT(ret, 0); +} +MR_TEST_EXPORT(workqueue, work_create_del, test_work_create_del); + +/* -------------------------------------------------------------------------- */ +/* Test: Work bind / schedule / execute */ +static void test_work_schedule_execute(void) { + mr_workqueue_t queue; + mr_work_t work; + mr_err_t ret; + + ret = mr_workqueue_init(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_init(&work, test_work_entry, (void *)0xABCD); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_schedule(&work); + MR_TEST_ASSERT_EQ_INT(ret, -MR_ENOENT); + + ret = mr_work_bind(&work, &queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_schedule(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + work_run_count = 0; + ret = mr_workqueue_execute(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(work_run_count, 1); + MR_TEST_ASSERT_EQ_PTR(last_param, (void *)0xABCD); + + ret = mr_work_del(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_workqueue_del(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); +} +MR_TEST_EXPORT(workqueue, schedule_execute, test_work_schedule_execute); + +/* -------------------------------------------------------------------------- */ +/* Test: Work delayed schedule */ +static void test_work_delayed_schedule(void) { + mr_work_t work, work1; + mr_workqueue_t queue; + mr_err_t ret; + + ret = mr_workqueue_init(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_init(&work, test_work_entry, (void *)0xDEAD); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_delayed_schedule(&work, 10); + MR_TEST_ASSERT_EQ_INT(ret, -MR_ENOENT); + + ret = mr_work_bind(&work, &queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_init(&work1, test_work_entry, (void *)0xDEAD); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_bind(&work1, &queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_delayed_schedule(&work, 10); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_delayed_schedule(&work, 10); + MR_TEST_ASSERT_EQ_INT(ret, -MR_EBUSY); + + ret = mr_work_delayed_schedule(&work1, 20); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + mr_clock_increase(10); + + work_run_count = 0; + ret = mr_workqueue_execute(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(work_run_count, 1); + MR_TEST_ASSERT_EQ_PTR(last_param, (void *)0xDEAD); + + ret = mr_work_delayed_schedule(&work, 0); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + mr_clock_increase(10); + + mr_work_cancel(&work1); + ret = mr_work_delayed_schedule(&work1, 10); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_workqueue_del(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_del(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_del(&work1); + MR_TEST_ASSERT_EQ_INT(ret, 0); +} +MR_TEST_EXPORT(workqueue, delayed_schedule, test_work_delayed_schedule); + +/* -------------------------------------------------------------------------- */ +/* Test: Work cancel */ +static void test_work_cancel(void) { + mr_workqueue_t queue; + mr_work_t work; + mr_err_t ret; + + ret = mr_workqueue_init(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_init(&work, test_work_entry, MR_NULL); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_bind(&work, &queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_schedule(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_cancel(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + work_run_count = 0; + ret = mr_workqueue_execute(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(work_run_count, 0); + + ret = mr_work_del(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_workqueue_del(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); +} +MR_TEST_EXPORT(workqueue, work_cancel, test_work_cancel); + +/* -------------------------------------------------------------------------- */ +/* Test: Work is running */ +static void test_work_is_running(void) { + mr_workqueue_t queue; + mr_work_t work; + mr_err_t ret; + + ret = mr_workqueue_init(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_init(&work, test_work_entry, MR_NULL); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_bind(&work, &queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + MR_TEST_ASSERT_EQ_INT(MR_WORK_IS_RUNNING(&work), MR_FALSE); + + ret = mr_work_schedule(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + MR_TEST_ASSERT_EQ_INT(MR_WORK_IS_RUNNING(&work), MR_TRUE); + + ret = mr_work_schedule(&work); + MR_TEST_ASSERT_NE_INT(ret, 0); + + ret = mr_work_cancel(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + MR_TEST_ASSERT_EQ_INT(MR_WORK_IS_RUNNING(&work), MR_FALSE); + + ret = mr_work_del(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_workqueue_del(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); +} +MR_TEST_EXPORT(workqueue, work_is_running, test_work_is_running); + +#if defined(MR_USE_WORKQUEUE_HOOK) +static int hook_suspend_called = 0; +static int hook_wakeup_called = 0; + +static void test_hook_suspend(struct mr_workqueue *queue, void *param) { + MR_UNUSED(queue); + MR_UNUSED(param); + hook_suspend_called = 1; +} + +static void test_hook_wakeup(struct mr_workqueue *queue, void *param) { + MR_UNUSED(queue); + MR_UNUSED(param); + hook_wakeup_called = 1; +} + +static void test_workqueue_hook(void) { + mr_workqueue_hook_t hook = {.suspend = test_hook_suspend, + .wakeup = test_hook_wakeup, + .param = MR_NULL}; + mr_work_t work, work1; + mr_workqueue_t queue; + mr_err_t ret; + + ret = mr_workqueue_init(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + mr_workqueue_hook_set(&queue, &hook); + + ret = mr_work_init(&work, test_work_entry, MR_NULL); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_bind(&work, &queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_init(&work1, test_work_entry, MR_NULL); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_bind(&work1, &queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + hook_wakeup_called = 0; + ret = mr_work_schedule(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(hook_wakeup_called, 1); + + ret = mr_work_schedule(&work1); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(hook_wakeup_called, 1); + + hook_suspend_called = 0; + ret = mr_workqueue_execute(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); + MR_TEST_ASSERT_EQ_INT(hook_suspend_called, 1); + + ret = mr_work_del(&work); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_work_del(&work1); + MR_TEST_ASSERT_EQ_INT(ret, 0); + + ret = mr_workqueue_del(&queue); + MR_TEST_ASSERT_EQ_INT(ret, 0); +} +MR_TEST_EXPORT(workqueue, hook, test_workqueue_hook); +#endif /* defined(MR_USE_WORKQUEUE_HOOK) */ +#endif /* defined(MR_USE_WORKQUEUE) */ +#endif /* defined(MR_USE_TEST) */ diff --git a/test/libc/malloc.c b/test/libc/malloc.c index 1558038..43ae6d8 100644 --- a/test/libc/malloc.c +++ b/test/libc/malloc.c @@ -55,7 +55,7 @@ static void test_malloc_free_basic(void) { usable = mr_malloc_usable_size(MR_NULL); MR_TEST_ASSERT_EQ_UINT(usable, 0); - usable = mr_malloc_usable_size(p + 32); + usable = mr_malloc_usable_size((mr_uint8_t *)p + 32); MR_TEST_ASSERT_EQ_UINT(usable, 0); #else usable = 128;