Files
ESPC3-wireless/components/system/source/k_kit/k_kit.c

4503 lines
120 KiB
C
Raw Normal View History

2024-03-28 12:19:52 +08:00
/**
* @file k_kit.c
* @author LokLiang (lokliang@163.com)
* @brief
* @version 1.1.0
*
* @date 2023-01-01 k_timer
* @date 2022-12-09
* @date 2021-01-13
*
* @copyright Copyright (c) 2022
*
*
*
* 8
* yield sleep
*
* 访线
*
* 72MHz主频下
* k_work_submit -- 3uS
* work scheduler -- 4uS
* k_fifo_put/k_fifo_take -- 2.5uS
* k_queue_alloc/k_queue_put -- 2.5uS
* k_pipe_poll_write/k_pipe_poll_read -- 1uS
*
*
* --
* --
* --
* --
* --
* -- 80..7
* -- CPU使用权
*
*
* --
* --
* --
* --
* --
* -- 80..7
*
*
* --
* --
* --
* --
* --
*
* FIFO
* --
* --
* --
* --
* -- 使
*
*
* --
* --
* --
* -- 使
*
*
* --
* -- 线
* --
* --
* -- 使
*
*
* --
* -- sizeof(size_t) * 4
* --
* -- 使
*/
#include "k_kit.h"
#include <string.h>
#include <stdio.h>
/**
* @defgroup debug
* @{
*/
#ifndef CONFIG_K_KIT_LOG_ON
#define CONFIG_K_KIT_LOG_ON 0 /* 0: k_log_sched() 无效; 1: k_log_sched() 生效 */
2024-03-28 12:19:52 +08:00
#endif
#ifndef CONFIG_K_KIT_DBG_ON
#define CONFIG_K_KIT_DBG_ON 1 /* 允许 k_kit 打印错误日志 */
#endif
#ifndef CONFIG_K_KIT_DBG_COLOR_ON
#define CONFIG_K_KIT_DBG_COLOR_ON 1 /* 在打印的日志中添加颜色控制 */
#endif
#ifndef CONFIG_K_KIT_PRINT
#define CONFIG_K_KIT_PRINT printf /* 设置打印函数 */
#endif
#define _CONS_PRINT(FMT, ARG...) \
do \
{ \
if (CONFIG_K_KIT_DBG_ON) \
{ \
CONFIG_K_KIT_PRINT(FMT, ##ARG); \
} \
} while (0)
#if (CONFIG_K_KIT_DBG_COLOR_ON == 1)
#define _COLOR_R "\033[31m" /* 红 RED */
#define _COLOR_G "\033[32m" /* 绿 GREEN */
#define _COLOR_Y "\033[33m" /* 黄 YELLOW */
#define _COLOR_B "\033[34m" /* 蓝 BLUE */
#define _COLOR_P "\033[35m" /* 紫 PURPLE */
#define _COLOR_C "\033[36m" /* 青 CYAN */
#define _COLOR_RY "\033[41;33m" /* 红底黄字 */
#define _COLOR_END "\033[0m" /* 结束 */
#else
#define _COLOR_R "" /* 红 */
#define _COLOR_G "" /* 绿 */
#define _COLOR_Y "" /* 黄 */
#define _COLOR_B "" /* 蓝 */
#define _COLOR_P "" /* 紫 */
#define _COLOR_C "" /* 青 */
#define _COLOR_RY "" /* 红底黄字 */
#define _COLOR_END "" /* 结束 */
#endif
#define _DO_SYS_LOG(FLAG, FMT, ARG...) \
do \
{ \
if (FLAG) \
{ \
_CONS_PRINT(FMT, ##ARG); \
} \
} while (0)
#define _FILENAME(FILE) (strrchr(FILE, '/') ? (strrchr(FILE, '/') + 1) : (strrchr(FILE, '\\') ? (strrchr(FILE, '\\') + 1) : FILE))
#define _GEN_DOMAIN "[KIT] "
#define _SYS_LOG_COLOR(FLAG, INFO, COLOR, FMT, ...) _DO_SYS_LOG(FLAG, INFO "%s:%d \t%s -> " COLOR FMT _COLOR_END "\r\n", \
_FILENAME(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define _DBG_WRN(FMT, ...) _SYS_LOG_COLOR(CONFIG_K_KIT_DBG_ON, "[WRN] * " _GEN_DOMAIN, _COLOR_Y, FMT, ##__VA_ARGS__)
#define _ASSERT_FALSE(EXP, FMT, ...) \
do \
{ \
if (EXP) \
{ \
_CONS_PRINT("[ASS] # " _GEN_DOMAIN "%s:%d \t%s -> %s; ## " _COLOR_RY FMT _COLOR_END "\r\n", \
_FILENAME(__FILE__), __LINE__, __FUNCTION__, #EXP, ##__VA_ARGS__); \
do \
{ \
volatile int FLAG = 0; \
do \
{ \
} while (FLAG == 0); \
} while (0); \
} \
} while (0)
/**
* @} debug
*/
#define _SIGNED_MAX(N) ((int)((1u << (sizeof(N) * 8 - 1)) - 1))
#define _WORK ((k_work_handle_t *)work_handle->hdl)
#define _WORK_Q ((k_work_q_handle_t *)_WORK->work_q_handle->hdl)
#define _K_PORT (&s_kit_init_struct)
#define _K_CONTAINER_OF(PTR, TYPE, MEMBER) ((TYPE *)&((uint8_t *)PTR)[-(int)&((TYPE *)0)->MEMBER])
#define _TRUE true
#define _FALSE false
#define _K_DIS_INT() _k_interrupt_save()
#define _K_DIS_SCHED() _k_scheduler_disable()
#define _K_EN_INT() _k_interrupt_restore()
#define _K_EN_SCHED() _k_scheduler_enable()
#define _K_FIFO_FREE 0x83459321
#define _K_QUEUE_FREE 0x32478065
#define _SLIST_SET(Value1, Value2) (Value1 = (__list_node_t)Value2)
#define _SLIST_GET(Value) ((__slist_node_t *)(Value))
#define _DLIST_SET(Value1, Value2) (Value1 = (__list_node_t)Value2)
#define _DLIST_GET(Value) ((__dlist_node_t *)(Value))
2025-02-13 17:17:07 +08:00
#define _TEST_HANDLE(HANDLE, RETURN) \
if (HANDLE == NULL) \
{ \
_DBG_WRN(#HANDLE " nul"); \
RETURN; \
} \
if (*(void **)HANDLE == NULL) \
{ \
_DBG_WRN(#HANDLE " invalid"); \
RETURN; \
}
2024-03-28 12:19:52 +08:00
typedef void *__list_node_t;
typedef struct
{
__list_node_t next;
} __slist_node_t;
typedef struct
{
__list_node_t head;
__list_node_t tail;
} __slist_t;
typedef struct
{
__list_node_t next;
__list_node_t prev;
} __dlist_node_t;
typedef struct
{
__list_node_t head;
} __dlist_t;
typedef struct
{
__slist_t mbox_valid;
__slist_t mbox_idle;
} k_work_mb_list_t;
typedef struct
{
__slist_node_t state_node;
__slist_t *state_list;
__dlist_node_t event_node;
k_tick_t timeout;
k_work_fn work_route;
void *arg;
k_work_q_t *work_q_handle;
k_work_t *work_handle;
uint8_t priority;
uint8_t exec_flag;
uint8_t exec_repeat;
uint8_t delete_flag : 1; /* 表示任务正在运行时被关闭,当运行完毕后资源被回收 */
uint8_t obj_flag_type : 1; /* 0: 表示任务类型为 work; 1: 表示任务类型为 timer */
uint8_t obj_flag_periodic : 1; /* 任务类型为 timer 时有效,表示使用自动重装 */
uint8_t obj_flag_auto_del : 1; /* 任务类型为 timer 时有效,表示执行完成后自动删除对象 */
union
{
k_work_mb_list_t *mbox_list;
k_tick_t period;
} obj_data;
#if (CONFIG_K_KIT_LOG_ON)
const char *name;
#endif
} k_work_handle_t;
typedef struct
{
__dlist_t event_list;
__slist_t ready_list[8];
__slist_t delayed_list;
size_t priority_tab;
2024-03-28 12:19:52 +08:00
k_work_t *curr_work;
k_work_handle_t *yield_work;
k_work_handle_t *sleep_work;
k_work_handle_t *sleep_work_prev;
2024-03-28 12:19:52 +08:00
k_work_q_fn work_q_resume;
void *work_q_resume_arg;
k_work_fn hook_entry;
k_tick_t timeout_early;
volatile size_t resume_flag;
2024-03-28 12:19:52 +08:00
} k_work_q_handle_t;
typedef struct
{
union
{
__slist_node_t state_node;
k_work_t *work_handle;
} ctrl;
} k_work_mb_handle_t;
typedef struct
{
__slist_t list;
k_work_t *resume_work;
k_tick_t resume_delay;
} k_fifo_q_handle_t;
typedef struct
{
union
{
__slist_node_t state_node;
size_t free_flag;
2024-03-28 12:19:52 +08:00
} ctrl;
} k_fifo_handle_t;
typedef struct
{
__slist_t list_valid;
__slist_t list_idle;
size_t item_size;
k_work_t *resume_work;
k_tick_t resume_delay;
} k_queue_handle_t;
typedef struct
{
union
{
__slist_node_t state_node;
size_t free_flag;
2024-03-28 12:19:52 +08:00
} ctrl;
k_queue_t *queue_handle;
} k_queue_data_t;
typedef volatile size_t pipe_id_t;
typedef struct
{
size_t size; // 缓存总大小
pipe_id_t wid; // 已写进的下标
pipe_id_t rid; // 已读出的下标
k_work_t *resume_work;
k_tick_t resume_delay;
} k_pipe_handle_t;
static struct
{
size_t interrupt_call;
size_t interrupt_nest;
2024-03-28 12:19:52 +08:00
k_work_t *curr_hook;
k_work_t *curr_log;
#if (CONFIG_K_KIT_LOG_ON)
k_work_t *work_log[8];
uint8_t log_index;
uint8_t log_max;
#endif
} s_cm_kit;
static k_work_q_t work_q_hdl_main;
static k_timer_q_t timer_q_hdl_main;
k_work_q_t *default_work_q_hdl = &work_q_hdl_main;
k_timer_q_t *default_timer_q_hdl = &timer_q_hdl_main;
static k_init_t s_kit_init_struct;
static const uint8_t _tab_clz_8[] = {
7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, // 0x00
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0x10
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x20
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x30
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xF0
};
static void _slist_init_list(__slist_t *list);
static void _slist_init_node(__slist_node_t *node);
static int _slist_insert_font(__slist_t *list, __slist_node_t *node);
static int _slist_insert_tail(__slist_t *list, __slist_node_t *node);
static int _slist_remove(__slist_t *list, __slist_node_t *node);
static int _slist_remove_next(__slist_t *list, __slist_node_t *prev_node, __slist_node_t *remove_node);
static int _slist_insert_next(__slist_t *list, __slist_node_t *tar_node, __slist_node_t *new_node);
static __slist_node_t *_slist_take_head(__slist_t *list);
static __slist_node_t *_slist_peek_head(__slist_t *list);
static __slist_node_t *_slist_peek_tail(__slist_t *list);
static __slist_node_t *_slist_peek_next(__slist_node_t *node);
static __slist_node_t *_slist_peek_prev(__slist_t *list, __slist_node_t *node);
static int _slist_is_pending(__slist_node_t *node);
static void _dlist_init_list(__dlist_t *list);
static void _dlist_init_node(__dlist_node_t *node);
static int _dlist_insert_tail(__dlist_t *list, __dlist_node_t *node);
static int _dlist_remove(__dlist_t *list, __dlist_node_t *node);
static __dlist_node_t *_dlist_take_head(__dlist_t *list);
static __dlist_node_t *_dlist_peek_head(__dlist_t *list);
static __dlist_node_t *_dlist_peek_tail(__dlist_t *list);
static __dlist_node_t *_dlist_peek_next(__dlist_t *list, __dlist_node_t *node);
static int _dlist_is_pending(__dlist_node_t *node);
static void _slist_init_list(__slist_t *list)
{
_SLIST_SET(list->head, 0);
_SLIST_SET(list->tail, 0);
}
static void _slist_init_node(__slist_node_t *node)
{
_SLIST_SET(node->next, 0);
}
static int _slist_insert_font(__slist_t *list, __slist_node_t *node)
{
__slist_node_t *head_node;
if (_SLIST_GET(node->next) != NULL)
{
return -1;
}
head_node = _SLIST_GET(list->head);
if (head_node)
{
_SLIST_SET(node->next, head_node);
}
else
{
_SLIST_SET(node->next, node);
_SLIST_SET(list->tail, node);
}
_SLIST_SET(list->head, node);
return 0;
}
static int _slist_insert_tail(__slist_t *list, __slist_node_t *node)
{
if (_SLIST_GET(node->next) != NULL)
{
return -1;
}
_SLIST_SET(node->next, node);
if (_SLIST_GET(list->head) == NULL)
{
_SLIST_SET(list->head, node);
}
else
{
__slist_node_t *tail_node = (__slist_node_t *)_SLIST_GET(list->tail);
_SLIST_SET(tail_node->next, node);
}
_SLIST_SET(list->tail, node);
return 0;
}
static int _slist_remove(__slist_t *list, __slist_node_t *node)
{
__slist_node_t *list_head;
__slist_node_t *node_next;
if (node == NULL || list == NULL)
{
return -1;
}
list_head = _SLIST_GET(list->head);
node_next = _SLIST_GET(node->next);
if (node_next == NULL || list_head == NULL)
{
return -1;
}
if (node == list_head) // node 是首个节点
{
if (node == _SLIST_GET(list->tail)) // node 是最后一个节点
{
_SLIST_SET(list->head, 0);
_SLIST_SET(list->tail, 0);
}
else
{
_SLIST_SET(list->head, node_next);
}
}
else // node 不是首个节点
{
__slist_node_t *prev_node = _slist_peek_prev(list, node);
if (prev_node == NULL)
{
return -1;
}
if (node == _SLIST_GET(list->tail)) // node 是最后一个节点
{
_SLIST_SET(list->tail, prev_node);
_SLIST_SET(prev_node->next, prev_node);
}
else
{
_SLIST_SET(prev_node->next, node_next);
}
}
_SLIST_SET(node->next, 0);
return 0;
}
static int _slist_remove_next(__slist_t *list, __slist_node_t *prev_node, __slist_node_t *remove_node)
{
__slist_node_t *list_head;
__slist_node_t *node_next;
if (remove_node == NULL || list == NULL)
{
return -1;
}
list_head = _SLIST_GET(list->head);
node_next = _SLIST_GET(remove_node->next);
if (node_next == NULL || list_head == NULL)
{
return -1;
}
if (remove_node == list_head) // remove_node 是首个节点
{
if (remove_node == _SLIST_GET(list->tail)) // remove_node 是最后一个节点
{
_SLIST_SET(list->head, 0);
_SLIST_SET(list->tail, 0);
}
else
{
_SLIST_SET(list->head, node_next);
}
}
else // remove_node 不是首个节点
{
if (prev_node == NULL)
{
prev_node = _slist_peek_prev(list, remove_node);
if (prev_node == NULL)
{
return -1;
}
}
if (remove_node == _SLIST_GET(list->tail)) // remove_node 是最后一个节点
{
_SLIST_SET(list->tail, prev_node);
_SLIST_SET(prev_node->next, prev_node);
}
else
{
_SLIST_SET(prev_node->next, node_next);
}
}
_SLIST_SET(remove_node->next, 0);
return 0;
}
static int _slist_insert_next(__slist_t *list, __slist_node_t *tar_node, __slist_node_t *new_node)
{
__slist_node_t *tar_node_next = _SLIST_GET(tar_node->next);
if (_SLIST_GET(list->head) == NULL || tar_node_next == NULL || _SLIST_GET(new_node->next) != NULL)
{
return -1;
}
if (tar_node == _SLIST_GET(list->tail)) // tar_node 是最后一个节点
{
_SLIST_SET(new_node->next, new_node);
_SLIST_SET(tar_node->next, new_node);
_SLIST_SET(list->tail, new_node);
}
else
{
_SLIST_SET(new_node->next, tar_node_next);
_SLIST_SET(tar_node->next, new_node);
}
return 0;
}
static __slist_node_t *_slist_take_head(__slist_t *list)
{
__slist_node_t *ret = _SLIST_GET(list->head);
_slist_remove(list, ret);
return ret;
}
static __slist_node_t *_slist_peek_head(__slist_t *list)
{
return _SLIST_GET(list->head);
}
static __slist_node_t *_slist_peek_tail(__slist_t *list)
{
return _SLIST_GET(list->tail);
}
static __slist_node_t *_slist_peek_next(__slist_node_t *node)
{
__slist_node_t *next_node = _SLIST_GET(node->next);
if (next_node == node)
{
return NULL;
}
else
{
return next_node;
}
}
static __slist_node_t *_slist_peek_prev(__slist_t *list, __slist_node_t *node)
{
__slist_node_t *prev_node = NULL;
__slist_node_t *test_node = _SLIST_GET(list->head);
while (test_node && test_node != node && prev_node != test_node)
{
prev_node = test_node;
test_node = _SLIST_GET(test_node->next);
}
if (test_node == node)
{
return prev_node;
}
return NULL;
}
static int _slist_is_pending(__slist_node_t *node)
{
return (_SLIST_GET(node->next) != NULL);
}
static void _dlist_init_list(__dlist_t *list)
{
_DLIST_SET(list->head, 0);
}
static void _dlist_init_node(__dlist_node_t *node)
{
_DLIST_SET(node->next, 0);
_DLIST_SET(node->prev, 0);
}
static int _dlist_insert_tail(__dlist_t *list, __dlist_node_t *node)
{
__dlist_node_t *first_node;
if (_DLIST_GET(node->next) != NULL || _DLIST_GET(node->prev) != NULL)
{
return -1;
}
first_node = _DLIST_GET(list->head);
if (first_node == NULL)
{
/* 直接设置链头 */
_DLIST_SET(node->next, node);
_DLIST_SET(node->prev, node);
_DLIST_SET(list->head, node);
}
else
{
__dlist_node_t *first_node_prev = _DLIST_GET(first_node->prev);
_DLIST_SET(node->next, first_node);
_DLIST_SET(node->prev, first_node_prev);
_DLIST_SET(first_node_prev->next, node);
_DLIST_SET(first_node->prev, node);
}
return 0;
}
static int _dlist_remove(__dlist_t *list, __dlist_node_t *node)
{
__dlist_node_t *first_node;
__dlist_node_t *node_next;
if (node == NULL || list == NULL)
{
return -1;
}
first_node = _DLIST_GET(list->head);
node_next = _DLIST_GET(node->next);
if (node_next == NULL || first_node == NULL)
{
return -1;
}
if (node_next == node) // 是最后一节点
{
_DLIST_SET(list->head, 0);
}
else // 不是最后一节点
{
__dlist_node_t *node_prev = _DLIST_GET(node->prev);
if (first_node == node)
{
_DLIST_SET(list->head, node_next); // 链头指向下一节点
}
_DLIST_SET(node_prev->next, node_next);
_DLIST_SET(node_next->prev, node_prev);
}
_DLIST_SET(node->next, 0);
_DLIST_SET(node->prev, 0);
return 0;
}
static __dlist_node_t *_dlist_take_head(__dlist_t *list)
{
__dlist_node_t *ret = _DLIST_GET(list->head);
_dlist_remove(list, ret);
return ret;
}
static __dlist_node_t *_dlist_peek_head(__dlist_t *list)
{
return _DLIST_GET(list->head);
}
static __dlist_node_t *_dlist_peek_tail(__dlist_t *list)
{
__dlist_node_t *list_head = _DLIST_GET(list->head);
if (list_head == NULL)
{
return NULL;
}
else
{
return _DLIST_GET(list_head->prev);
}
}
static __dlist_node_t *_dlist_peek_next(__dlist_t *list, __dlist_node_t *node)
{
__dlist_node_t *ret = _DLIST_GET(node->next);
if (_dlist_peek_head(list) == ret)
{
ret = NULL;
}
return ret;
}
static int _dlist_is_pending(__dlist_node_t *node)
{
return (_DLIST_GET(node->next) != NULL);
}
static void _k_interrupt_save(void)
{
if (s_cm_kit.interrupt_call == 0)
{
s_cm_kit.interrupt_nest = _K_PORT->interrupt_save();
}
s_cm_kit.interrupt_call++;
}
static void _k_interrupt_restore(void)
{
s_cm_kit.interrupt_call--;
_ASSERT_FALSE((int)s_cm_kit.interrupt_call < 0, "error");
if (s_cm_kit.interrupt_call == 0)
{
_K_PORT->interrupt_restore(s_cm_kit.interrupt_nest);
}
}
static void _k_scheduler_disable(void)
{
_K_PORT->scheduler_disable();
}
static void _k_scheduler_enable(void)
{
_K_PORT->scheduler_enable();
}
static void _k_nop(void)
{
}
static k_work_q_t *_k_nop_get_work_q_hdl(void)
{
return default_work_q_hdl;
}
static void _k_read_curr_handle(k_work_q_t **work_q_handle, k_work_t **work_handle)
{
*work_q_handle = _K_PORT->get_work_q_hdl();
*work_handle = ((k_work_q_handle_t *)(*work_q_handle)->hdl)->curr_work;
}
/**
* @brief
*
* @param list mbox_idle mbox_valid
*/
static void _k_work_mbox_clr_list(__slist_t *list)
{
for (;;)
{
__slist_node_t *node = _slist_take_head(list);
if (node == NULL)
{
break;
}
else
{
k_work_mb_handle_t *mbox_data = _K_CONTAINER_OF(node, k_work_mb_handle_t, ctrl.state_node);
_K_PORT->free(mbox_data);
}
}
}
/**
* @brief
*
* @param work_handle k_work_create()
*/
static void _k_work_delete(k_work_t *work_handle)
{
if (work_handle == NULL)
{
k_work_q_t *work_q_handle;
_k_read_curr_handle(&work_q_handle, &work_handle);
}
if (work_handle->hdl != NULL)
{
k_work_handle_t *work = work_handle->hdl;
if (work->obj_flag_type == 0 && work->obj_data.mbox_list != NULL)
{
k_work_mb_list_t *mbox_list = work->obj_data.mbox_list;
if (mbox_list)
{
_k_work_mbox_clr_list(&mbox_list->mbox_idle);
_k_work_mbox_clr_list(&mbox_list->mbox_valid);
_K_PORT->free(mbox_list);
work->obj_data.mbox_list = NULL;
}
}
_slist_remove(work->state_list, &work->state_node);
if (_dlist_is_pending(&work->event_node))
{
k_work_q_handle_t *work_q = work->work_q_handle->hdl;
_dlist_remove(&work_q->event_list, &work->event_node);
}
_K_PORT->free(work_handle->hdl);
#if (CONFIG_K_KIT_LOG_ON)
{
size_t max_index = sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]);
size_t index;
2024-03-28 12:19:52 +08:00
if (max_index > s_cm_kit.log_index)
{
max_index = s_cm_kit.log_index;
}
for (index = 0; index < max_index; index++)
{
if (s_cm_kit.work_log[index] == work_handle)
{
size_t i;
2024-03-28 12:19:52 +08:00
for (i = index; i + 1 < max_index; i++)
{
s_cm_kit.work_log[i] = s_cm_kit.work_log[i + 1];
}
s_cm_kit.work_log[i] = NULL;
s_cm_kit.log_index--;
s_cm_kit.log_max--;
break;
}
}
}
#endif
work_handle->hdl = NULL;
}
}
/**
* @brief (work_q->event_list)
*
* @param event_list
* @param sys_time
*/
static void _k_work_q_handler_take_event_list(__dlist_t *event_list, k_tick_t sys_time)
{
if (!_dlist_peek_head(event_list))
{
return;
}
for (;;)
{
__dlist_node_t *event_node;
_K_DIS_INT();
event_node = _dlist_take_head(event_list);
if (event_node == NULL)
{
_K_EN_INT();
break;
}
else
{
k_work_handle_t *opt_work = _K_CONTAINER_OF(event_node, k_work_handle_t, event_node);
_K_EN_INT();
/* 根据时间设置,把任务插入到延时链或直接插入到就绪链或中 */
_K_DIS_SCHED();
if (opt_work->timeout - sys_time > 0)
{
/* 按时间排序,插入到 work_q->delayed_list */
k_work_q_handle_t *work_q = opt_work->work_q_handle->hdl;
__slist_t *new_list = &work_q->delayed_list;
__slist_node_t *work_node;
__slist_node_t *test_node;
_slist_remove(opt_work->state_list, &opt_work->state_node);
opt_work->state_list = new_list;
work_node = &opt_work->state_node;
test_node = _slist_peek_head(new_list);
if (test_node == NULL)
{
work_q->timeout_early = opt_work->timeout;
_slist_insert_font(new_list, work_node);
}
else
{
__slist_node_t *end_node = _slist_peek_tail(new_list);
__slist_node_t *prev_node = NULL;
k_work_handle_t *test_work = _K_CONTAINER_OF(test_node, k_work_handle_t, state_node);
work_q->timeout_early = test_work->timeout;
do
{
if ((int)(opt_work->timeout - test_work->timeout) < 0)
{
break;
}
prev_node = test_node;
test_node = _slist_peek_next(test_node);
test_work = _K_CONTAINER_OF(test_node, k_work_handle_t, state_node);
} while (prev_node != end_node);
if (prev_node == NULL)
{
work_q->timeout_early = opt_work->timeout;
_slist_insert_font(new_list, work_node);
}
else
{
_slist_insert_next(new_list, prev_node, work_node);
}
}
}
else
{
/* 直接插入到 work_q->ready_list[] */
k_work_q_handle_t *work_q = opt_work->work_q_handle->hdl;
__slist_t *new_list = &work_q->ready_list[opt_work->priority];
if (opt_work->state_list != new_list)
{
_slist_remove(opt_work->state_list, &opt_work->state_node);
_slist_insert_tail(new_list, &opt_work->state_node);
opt_work->state_list = new_list;
work_q->priority_tab |= 1 << opt_work->priority;
}
}
_K_EN_SCHED();
}
}
}
/**
* @brief (work_q->delayed_list)
*
* @param src_list
* @return k_tick_t
*/
static k_tick_t _k_work_q_handler_take_delay_list(k_work_q_handle_t *work_q, k_tick_t sys_time)
{
int ret;
_k_work_q_handler_take_event_list(&work_q->event_list, sys_time);
if ((int)(sys_time - *(volatile int *)&work_q->timeout_early) >= 0)
{
for (;;)
{
__slist_node_t *delayed_node;
_K_DIS_SCHED();
delayed_node = _slist_peek_head(&work_q->delayed_list);
if (delayed_node != NULL)
{
k_work_handle_t *opt_work = _K_CONTAINER_OF(delayed_node, k_work_handle_t, state_node);
if (opt_work->work_q_handle->hdl == NULL)
{
_k_work_delete(opt_work->work_handle);
}
else
{
if ((int)(sys_time - opt_work->timeout) >= 0)
{
_slist_remove(opt_work->state_list, &opt_work->state_node);
opt_work->state_list = &work_q->ready_list[7 - _tab_clz_8[1 << opt_work->priority]];
_slist_insert_tail(opt_work->state_list, &opt_work->state_node);
work_q->priority_tab |= 1 << opt_work->priority;
}
else
{
work_q->timeout_early = opt_work->timeout;
_K_EN_SCHED();
break;
}
}
}
else
{
work_q->timeout_early = sys_time + _SIGNED_MAX(sys_time);
_K_EN_SCHED();
break;
}
_K_EN_SCHED();
}
}
ret = work_q->timeout_early - sys_time;
if (ret < 0)
{
ret = 0;
}
return ret;
}
/**
* @brief
*
* @param work_q_handle k_work_q_create()
* @return k_work_handle_t*
*/
static k_work_handle_t *_k_work_q_handler_take_ready_work(k_work_q_t *work_q_handle)
{
for (;;)
{
k_work_q_handle_t *work_q;
_K_DIS_SCHED();
work_q = work_q_handle->hdl;
if (work_q == NULL || work_q->priority_tab == 0)
{
_K_EN_SCHED();
return NULL;
}
else
{
int prio;
__slist_t *state_list;
__slist_node_t *state_node;
k_work_handle_t *exec_work;
prio = 7 - _tab_clz_8[work_q->priority_tab];
if (work_q->yield_work != NULL && prio < work_q->yield_work->priority)
{
_K_EN_SCHED();
return NULL;
}
state_list = &work_q->ready_list[prio];
state_node = _slist_take_head(state_list);
exec_work = NULL;
if (state_node == NULL)
{
work_q->priority_tab &= ~(1 << prio);
}
else
{
exec_work = _K_CONTAINER_OF(state_node, k_work_handle_t, state_node);
if (_slist_peek_head(state_list) == NULL)
{
work_q->priority_tab &= ~(1 << prio);
}
if (exec_work->exec_flag == 0)
{
work_q->curr_work = exec_work->work_handle;
}
exec_work->state_list = NULL;
}
_K_EN_SCHED();
if (exec_work != NULL)
{
if (exec_work->exec_flag == 0)
{
return exec_work;
}
else
{
exec_work->exec_repeat = 1;
}
}
}
}
}
/**
* @brief
*
* @param work_handle k_work_create()
*/
static void _k_work_log(void *arg)
{
#if (CONFIG_K_KIT_LOG_ON)
k_work_q_t *work_q_handle;
k_work_t *work_handle;
size_t max_index;
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
_k_read_curr_handle(&work_q_handle, &work_handle);
max_index = sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]);
if (max_index > s_cm_kit.log_index)
{
max_index = s_cm_kit.log_index;
}
while (max_index)
{
if (s_cm_kit.work_log[--max_index] == work_handle)
{
s_cm_kit.log_index = max_index + 1;
break;
}
}
if (s_cm_kit.work_log[max_index] != work_handle)
{
if (s_cm_kit.log_index < sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]))
{
s_cm_kit.work_log[s_cm_kit.log_index] = work_handle;
}
if (s_cm_kit.log_index <= sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]))
{
s_cm_kit.log_index++;
s_cm_kit.log_max = s_cm_kit.log_index;
}
}
_K_EN_SCHED();
#endif
}
/**
* @brief work_q->event_list
*
* @param work_q_handle k_work_q_create()
* @param work_handle k_work_create()
* @param timeout
* @param wait_forever
*/
static void _k_work_do_submit(k_work_q_t *work_q_handle, k_work_t *work_handle, k_tick_t timeout, bool wait_forever)
{
2025-02-13 17:17:07 +08:00
k_work_handle_t *work;
k_work_q_handle_t *work_q;
2024-03-28 12:19:52 +08:00
int resume_flag = 1;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(work_q_handle, return);
_TEST_HANDLE(work_handle, return);
work = work_handle->hdl;
work_q = work_q_handle->hdl;
2024-03-28 12:19:52 +08:00
if (wait_forever)
{
if (work->work_q_handle != work_q_handle ||
_dlist_is_pending(&work->event_node))
{
_K_DIS_INT();
if (work_handle->hdl != NULL)
{
if (_dlist_is_pending(&work->event_node))
{
k_work_q_handle_t *work_q_old = work->work_q_handle->hdl;
_dlist_remove(&work_q_old->event_list, &work->event_node);
}
work->work_q_handle = work_q_handle;
work->work_handle = work_handle;
}
_K_EN_INT();
}
}
else
{
if (work->timeout != timeout ||
work->work_q_handle != work_q_handle ||
!_dlist_is_pending(&work->event_node))
{
_K_DIS_INT();
if (work_handle->hdl != NULL)
{
work->timeout = timeout;
if (work->work_q_handle != work_q_handle)
{
if (_dlist_is_pending(&work->event_node))
{
k_work_q_handle_t *work_q_old = work->work_q_handle->hdl;
_dlist_remove(&work_q_old->event_list, &work->event_node);
}
}
work->work_q_handle = work_q_handle;
if (!_dlist_is_pending(&work->event_node))
{
_dlist_insert_tail(&work_q->event_list, &work->event_node);
work->work_handle = work_handle;
resume_flag = work_q->resume_flag;
}
}
_K_EN_INT();
}
if (resume_flag == 0)
{
work_q->resume_flag = 1;
if (work_q->work_q_resume != NULL)
{
work_q->work_q_resume(work_q->work_q_resume_arg);
}
}
}
}
/**
* @brief
*
* @param resume_work
* @param resume_delay
* 0 -
* 1 -
*/
static void _k_ipc_resume(k_work_t *resume_work, k_tick_t resume_delay)
2024-03-28 12:19:52 +08:00
{
if (resume_work != NULL)
{
k_work_handle_t *work = resume_work->hdl;
if (work != NULL && work->work_q_handle != NULL)
{
if (k_work_time_remain(resume_work) < resume_delay)
2024-03-28 12:19:52 +08:00
{
k_work_submit(work->work_q_handle, resume_work, resume_delay);
2024-03-28 12:19:52 +08:00
}
}
}
}
/**
* @brief
*
* @param work_q_handle k_work_q_create()
* @param exec_work
*/
static void _k_timer_end(k_work_q_t *work_q_handle, k_work_handle_t *exec_work)
{
if (exec_work->obj_flag_auto_del)
{
2025-02-13 17:17:07 +08:00
k_work_t work_handle = {.hdl = exec_work};
exec_work->exec_flag = 0;
2024-03-28 12:19:52 +08:00
k_work_delete(&work_handle);
2025-02-13 17:17:07 +08:00
exec_work->work_handle = NULL;
2024-03-28 12:19:52 +08:00
}
else if (exec_work->obj_flag_periodic)
{
k_tick_t timeout = exec_work->timeout +
exec_work->obj_data.period +
(_K_PORT->get_sys_ticks() - exec_work->timeout) / exec_work->obj_data.period * exec_work->obj_data.period;
_k_work_do_submit(work_q_handle, exec_work->work_handle, timeout, _FALSE);
}
}
/**
* @brief
* 1
*
* @param init_struct
*/
void k_init(const k_init_t *init_struct)
{
if (s_kit_init_struct.malloc != NULL)
{
_DBG_WRN("Duplicate initialization");
}
_ASSERT_FALSE(init_struct->malloc == NULL ||
init_struct->free == 0 ||
init_struct->interrupt_save == NULL ||
init_struct->interrupt_restore == NULL,
"Parameter error");
memcpy(&s_kit_init_struct, init_struct, sizeof(s_kit_init_struct));
if (init_struct->scheduler_disable == NULL || init_struct->scheduler_enable == NULL)
{
s_kit_init_struct.scheduler_disable = _k_nop;
s_kit_init_struct.scheduler_enable = _k_nop;
}
if (init_struct->get_work_q_hdl == NULL)
{
s_kit_init_struct.get_work_q_hdl = _k_nop_get_work_q_hdl;
}
memset(&s_cm_kit, 0, sizeof(s_cm_kit));
}
/**
* @brief
*
*/
void k_deinit(void)
{
memset(&s_kit_init_struct, 0, sizeof(s_kit_init_struct));
}
/**
* @brief
*
*
* 1.
* 2.
* 32 bytes
*
* @param work_q_handle k_work_q_create()
* @return k_tick_t
*/
k_tick_t k_work_q_handler(k_work_q_t *work_q_handle)
{
k_work_q_handle_t *work_q;
k_work_t *last_work;
k_tick_t ret;
2025-02-13 17:17:07 +08:00
if (s_kit_init_struct.malloc == NULL || work_q_handle == NULL || work_q_handle->hdl == NULL)
2024-03-28 12:19:52 +08:00
{
return -1u;
}
work_q = work_q_handle->hdl;
last_work = work_q->curr_work;
if (last_work != NULL)
{
_DBG_WRN("Not recommended executing this function in work_handler");
}
do
{
k_work_handle_t *exec_work;
if (work_q->priority_tab != 0)
{
exec_work = _k_work_q_handler_take_ready_work(work_q_handle);
if (exec_work != NULL)
{
2025-02-13 17:17:07 +08:00
uint8_t exec_flag = exec_work->exec_flag;
2024-03-28 12:19:52 +08:00
exec_work->exec_flag = 1;
if (exec_work->obj_flag_type)
{
exec_work->work_route(exec_work->arg);
_k_timer_end(work_q_handle, exec_work);
}
else
{
if (s_cm_kit.curr_hook != exec_work->work_handle)
{
k_work_fn hook_entry;
s_cm_kit.curr_hook = exec_work->work_handle;
_k_work_log(exec_work->work_handle);
hook_entry = work_q->hook_entry;
if (hook_entry)
{
hook_entry(exec_work->work_handle);
}
}
exec_work->work_route(exec_work->arg);
}
work_q->curr_work = last_work;
2025-02-13 17:17:07 +08:00
if (k_work_is_valid(exec_work->work_handle))
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
if (exec_work->delete_flag == 0)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
exec_work->exec_flag = exec_flag;
if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL)
{
_K_DIS_SCHED();
_k_work_mbox_clr_list(&exec_work->obj_data.mbox_list->mbox_idle);
_K_EN_SCHED();
}
2024-03-28 12:19:52 +08:00
}
}
2025-02-13 17:17:07 +08:00
else
{
exec_work->exec_flag = 0;
k_work_delete(exec_work->work_handle);
}
2024-03-28 12:19:52 +08:00
}
}
}
else
{
exec_work = NULL;
}
ret = _k_work_q_handler_take_delay_list(work_q, _K_PORT->get_sys_ticks());
if (exec_work != NULL)
{
break;
}
} while (*(volatile uint8_t *)&work_q->priority_tab != 0);
if (work_q->priority_tab != 0)
{
ret = 0;
}
if (last_work != NULL)
{
if (((k_work_handle_t *)last_work->hdl)->exec_repeat != 0)
{
((k_work_handle_t *)last_work->hdl)->exec_repeat = 0;
k_work_submit(((k_work_handle_t *)last_work->hdl)->work_q_handle,
((k_work_handle_t *)last_work->hdl)->work_handle,
0);
}
}
if (work_q->resume_flag)
{
work_q->resume_flag = 0;
ret = 0;
}
if (work_q->curr_work)
{
if (s_cm_kit.curr_hook != work_q->curr_work)
{
k_work_fn hook_entry;
s_cm_kit.curr_hook = work_q->curr_work;
_k_work_log(work_q->curr_work);
hook_entry = work_q->hook_entry;
if (hook_entry)
{
hook_entry(work_q->curr_work);
}
}
}
return ret;
}
/**
* @brief
*
* : 112 bytes
*
* @param work_q_handle[out]
* @return k_err_t 0 -- , -1 --
*/
k_err_t k_work_q_create(k_work_q_t *work_q_handle)
{
k_work_q_handle_t *work_q;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
_K_DIS_SCHED();
work_q = _K_PORT->malloc(sizeof(k_work_q_handle_t));
if (work_q != NULL)
{
size_t i;
2024-03-28 12:19:52 +08:00
memset(work_q, 0, sizeof(*work_q));
work_q_handle->hdl = work_q;
work_q->work_q_resume = NULL;
work_q->work_q_resume_arg = NULL;
for (i = 0; i < sizeof(work_q->ready_list) / sizeof(work_q->ready_list[0]); i++)
{
_slist_init_list(&work_q->ready_list[i]);
}
_slist_init_list(&work_q->delayed_list);
_dlist_init_list(&work_q->event_list);
}
_K_EN_SCHED();
if (work_q == NULL)
{
_DBG_WRN("Insufficient memory");
return -1;
}
else
{
return 0;
}
}
/**
* @brief
* 1.
* 2.
* 3.
* 4.
*
* @param work_q_handle k_work_q_create()
*/
void k_work_q_delete(k_work_q_t *work_q_handle)
{
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
_K_DIS_SCHED();
2025-02-13 17:17:07 +08:00
if (work_q_handle != NULL && work_q_handle->hdl != NULL)
2024-03-28 12:19:52 +08:00
{
k_work_q_handle_t *work_q = work_q_handle->hdl;
while (*(volatile uint8_t *)&work_q->priority_tab != 0)
{
__slist_node_t *state_node = _slist_take_head(&work_q->ready_list[7 - _tab_clz_8[work_q->priority_tab]]);
if (state_node == NULL)
{
break;
}
else
{
k_work_handle_t *work = _K_CONTAINER_OF(state_node, k_work_handle_t, state_node);
_k_work_delete(work->work_handle);
}
}
for (;;)
{
__dlist_node_t *node = _dlist_take_head(&work_q->event_list);
if (node == NULL)
{
break;
}
else
{
k_work_handle_t *work = _K_CONTAINER_OF(node, k_work_handle_t, event_node);
_k_work_delete(work->work_handle);
}
}
for (;;)
{
__slist_node_t *state_node = _slist_take_head(&work_q->delayed_list);
if (state_node == NULL)
{
break;
}
else
{
k_work_handle_t *work = _K_CONTAINER_OF(state_node, k_work_handle_t, state_node);
_k_work_delete(work->work_handle);
}
}
if (work_q->curr_work != NULL)
{
_k_work_delete(work_q->curr_work);
}
_K_PORT->free(work_q_handle->hdl);
work_q_handle->hdl = NULL;
}
_K_EN_SCHED();
}
/**
* @brief
*
* @param work_q_handle k_work_q_create()
* @param work_q_resume
* @param arg
*/
void k_work_q_resume_regist(k_work_q_t *work_q_handle, k_work_q_fn work_q_resume, void *arg)
{
if (k_work_q_is_valid(work_q_handle))
{
k_work_q_handle_t *work_q = work_q_handle->hdl;
work_q->work_q_resume_arg = arg;
work_q->work_q_resume = work_q_resume;
}
}
/**
* @brief
*
* @param work_q_handle k_work_q_create()
* @retval true
* @retval false
*/
bool k_work_q_is_valid(k_work_q_t *work_q_handle)
{
if (s_kit_init_struct.malloc == NULL || work_q_handle == NULL || work_q_handle->hdl == NULL)
{
return _FALSE;
}
else
{
return _TRUE;
}
}
/**
* @brief 退
*
* @param work_q_handle k_work_q_create()
* @param entry NULL
*/
void k_work_hook(k_work_q_t *work_q_handle, k_work_fn hook)
{
2025-02-13 17:17:07 +08:00
k_work_q_handle_t *work_q;
_TEST_HANDLE(work_q_handle, return);
work_q = work_q_handle->hdl;
2024-03-28 12:19:52 +08:00
work_q->hook_entry = hook;
}
/**
* @brief
*
* @retval true
* @retval false
*/
bool k_work_q_delayed_state(k_work_q_t *work_q_handle)
{
2025-02-13 17:17:07 +08:00
k_work_q_handle_t *work_q;
_TEST_HANDLE(work_q_handle, return _FALSE);
work_q = work_q_handle->hdl;
2024-03-28 12:19:52 +08:00
if (_dlist_peek_head(&work_q->event_list) != NULL)
{
return _TRUE;
}
if (_slist_peek_head(&work_q->delayed_list) != NULL)
{
return _TRUE;
}
return _FALSE;
}
/**
* @brief
*
* @param work_q_handle k_work_q_create()
* @retval true
* @retval false
*/
bool k_work_q_ready_state(k_work_q_t *work_q_handle)
{
k_work_q_handle_t *work_q = work_q_handle->hdl;
if (work_q == NULL || work_q->priority_tab == 0)
{
return _FALSE;
}
else
{
return _FALSE;
}
}
k_err_t k_work_create_default(k_work_t *work_handle,
const char *name,
k_work_fn work_route,
void *arg,
uint8_t priority,
k_tick_t delay_ticks)
{
if (!k_work_is_valid(work_handle))
{
k_err_t ret = k_work_create(work_handle, name, work_route, arg, priority);
if (ret == 0)
{
k_work_submit(default_work_q_hdl, work_handle, delay_ticks);
}
return ret;
}
else
{
return 0;
}
}
2024-03-28 12:19:52 +08:00
/**
* @brief
*
*
* k_work_q_handler()
* : 48 bytes
*
* @param work_handle[out]
* @param name
* @param work_route
* @param arg
* @param priority 0 .. 70
* @return k_err_t 0 -- -1 --
*/
k_err_t k_work_create(k_work_t *work_handle,
const char *name,
k_work_fn work_route,
void *arg,
uint8_t priority)
{
k_work_handle_t *work;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
if (work_route == NULL)
{
_DBG_WRN("work_route invalid");
return -1;
}
if (priority >= (8 - _tab_clz_8[sizeof(_tab_clz_8) - 1]))
{
_DBG_WRN("Param over range: priority = %d, New value is %d",
priority,
priority % (8 - _tab_clz_8[sizeof(_tab_clz_8) - 1]) %
(sizeof(((k_work_q_handle_t *)0)->ready_list) / sizeof(((k_work_q_handle_t *)0)->ready_list[0])));
}
_K_DIS_SCHED();
work = _K_PORT->malloc(sizeof(k_work_handle_t));
_K_EN_SCHED();
if (work)
{
memset(work, 0, sizeof(*work));
work->work_handle = work_handle;
work->work_route = work_route;
work->arg = arg;
work->priority = priority % (8 - _tab_clz_8[sizeof(_tab_clz_8) - 1]) %
(sizeof(((k_work_q_handle_t *)0)->ready_list) / sizeof(((k_work_q_handle_t *)0)->ready_list[0]));
_slist_init_node(&work->state_node);
_dlist_init_node(&work->event_node);
#if (CONFIG_K_KIT_LOG_ON)
work->name = name;
#endif
work_handle->hdl = work;
return 0;
}
else
{
_DBG_WRN("Insufficient memory");
return -1;
}
}
/**
* @brief
*
*
*
* @param work_handle k_work_create()
*/
void k_work_delete(k_work_t *work_handle)
{
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
if (work_handle == NULL)
{
k_work_q_t *work_q_handle;
_k_read_curr_handle(&work_q_handle, &work_handle);
}
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(work_handle, return);
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
k_work_handle_t *work = work_handle->hdl;
if (work->exec_flag == 0)
{
_k_work_delete(work_handle);
}
else
{
work->delete_flag = 1;
}
_K_EN_SCHED();
}
/**
* @brief
*
* @param work_handle k_work_create()
* @retval true
* @retval false
*/
bool k_work_is_valid(k_work_t *work_handle)
{
if (work_handle == NULL || work_handle->hdl == NULL)
{
return _FALSE;
}
else
{
return _TRUE;
}
}
/**
* @brief
*
* @param work_handle k_work_create()
* @retval true
* @retval false
*/
bool k_work_is_pending(k_work_t *work_handle)
{
k_work_handle_t *work = work_handle->hdl;
if (work != NULL)
{
if (work->exec_flag != 0)
{
return _TRUE;
}
if (_dlist_is_pending(&work->event_node))
{
return _TRUE;
}
if (_slist_is_pending(&work->state_node))
{
return _TRUE;
}
}
return _FALSE;
}
/**
* @brief
*
* @param work_handle
* @return k_tick_t
*/
k_tick_t k_work_time_remain(k_work_t *work_handle)
{
_TEST_HANDLE(work_handle, return -1);
2024-03-28 12:19:52 +08:00
k_work_handle_t *work = work_handle->hdl;
k_tick_t ret = 0;
if (!_dlist_is_pending(&work->event_node) &&
!_slist_is_pending(&work->state_node))
{
return -1;
}
ret = work->timeout - _K_PORT->get_sys_ticks();
if (ret < 0)
{
ret = 0;
}
return ret;
}
/**
* @brief work_q->event_list
*
* @param work_q_handle k_work_q_create()
* @param work_handle k_work_create()
* @param delay_ticks 0-1
*/
void k_work_submit(k_work_q_t *work_q_handle, k_work_t *work_handle, k_tick_t delay_ticks)
{
if (delay_ticks == -1)
{
_k_work_do_submit(work_q_handle, work_handle, 0, _TRUE);
}
else
{
if ((size_t)delay_ticks > _SIGNED_MAX(delay_ticks))
2024-03-28 12:19:52 +08:00
{
delay_ticks = _SIGNED_MAX(delay_ticks);
}
_k_work_do_submit(work_q_handle, work_handle, _K_PORT->get_sys_ticks() + delay_ticks, _FALSE);
}
}
/**
* @brief 使 k_work_submit work_q_handle
*
* @param work_handle k_work_create()
* @param delay_ticks CPU的时间
*/
void k_work_resume(k_work_t *work_handle, k_tick_t delay_ticks)
{
_TEST_HANDLE(work_handle, return);
2024-03-28 12:19:52 +08:00
k_work_handle_t *work = work_handle->hdl;
if ((size_t)delay_ticks > _SIGNED_MAX(delay_ticks))
2024-03-28 12:19:52 +08:00
{
delay_ticks = _SIGNED_MAX(delay_ticks);
2024-03-28 12:19:52 +08:00
}
k_work_submit(work->work_q_handle, work_handle, delay_ticks);
2024-03-28 12:19:52 +08:00
}
/**
* @brief
*
* @param delay_ticks 0
*/
void k_work_later(k_tick_t delay_ticks)
{
k_work_q_t *work_q_handle;
k_work_t *work_handle;
_k_read_curr_handle(&work_q_handle, &work_handle);
if ((size_t)delay_ticks > _SIGNED_MAX(delay_ticks))
2024-03-28 12:19:52 +08:00
{
delay_ticks = _SIGNED_MAX(delay_ticks);
}
k_work_submit(work_q_handle, work_handle, delay_ticks);
}
/**
* @brief
*
* @param work_handle k_work_create()
*/
void k_work_suspend(k_work_t *work_handle)
{
k_work_handle_t *work;
_K_DIS_INT();
work = work_handle->hdl;
if (work != NULL)
{
if (_dlist_is_pending(&work->event_node))
{
k_work_q_handle_t *work_q = work->work_q_handle->hdl;
_dlist_remove(&work_q->event_list, &work->event_node);
}
}
_K_EN_INT();
_K_DIS_SCHED();
work = work_handle->hdl;
if (work != NULL)
{
_slist_remove(work->state_list, &work->state_node);
work->state_list = NULL;
work->exec_flag = 0;
work->obj_flag_periodic = 0;
}
_K_EN_SCHED();
}
/**
* @brief
*
* @param delay_ticks 0
*/
void k_work_later_until(k_tick_t delay_ticks)
{
k_work_q_t *work_q_handle;
k_work_t *work_handle;
k_work_handle_t *work;
k_tick_t timeout;
_k_read_curr_handle(&work_q_handle, &work_handle);
work = work_handle->hdl;
if ((size_t)delay_ticks > _SIGNED_MAX(delay_ticks))
2024-03-28 12:19:52 +08:00
{
delay_ticks = _SIGNED_MAX(delay_ticks);
}
timeout = work->timeout + delay_ticks + (_K_PORT->get_sys_ticks() - work->timeout) / delay_ticks * delay_ticks;
_k_work_do_submit(work_q_handle, work_handle, timeout, _FALSE);
}
/**
* @brief CPU的使用权
*
*
*
*
*
* @param delay_ticks CPU的时间
*/
void k_work_yield(k_tick_t delay_ticks)
{
k_work_q_t *work_q_handle;
k_work_t *work_handle;
k_work_handle_t *yield_work;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
_k_read_curr_handle(&work_q_handle, &work_handle);
yield_work = _WORK_Q->yield_work;
_WORK_Q->yield_work = _WORK;
k_work_sleep(delay_ticks);
_WORK_Q->yield_work = yield_work;
}
/**
* @brief CPU的使用权
*
*
*
* 24 bytes
*
* @param delay_ticks CPU的时间
*/
void k_work_sleep(k_tick_t delay_ticks)
{
k_work_q_t *work_q_handle;
k_work_t *work_handle;
k_work_handle_t *sleep_work;
2024-03-28 12:19:52 +08:00
k_tick_t sys_time;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
if ((size_t)delay_ticks > _SIGNED_MAX(delay_ticks))
2024-03-28 12:19:52 +08:00
{
delay_ticks = _SIGNED_MAX(delay_ticks);
}
_k_read_curr_handle(&work_q_handle, &work_handle);
sys_time = _K_PORT->get_sys_ticks();
_WORK->timeout = sys_time + delay_ticks;
sleep_work = _WORK_Q->sleep_work;
_WORK_Q->sleep_work = _WORK;
if (sleep_work != NULL)
{
if ((int)(_WORK->timeout - sleep_work->timeout) > 0 &&
_WORK_Q->sleep_work_prev != sleep_work)
{
_WORK_Q->sleep_work_prev = sleep_work;
// 当前任务的超时时间晚于前个任务的超时时间,上个任务将被阻塞
#if (CONFIG_K_KIT_LOG_ON)
_DBG_WRN("Work timeout conflict: previous task will be blocked %d ticks, "
"current work '%s', previous work '%s'",
(int)(_WORK->timeout - sleep_work->timeout),
_WORK->work_handle->name,
sleep_work->work_handle->name);
#else
_DBG_WRN("Work timeout conflict: previous task will be blocked %d ticks, "
"current work 0x%08x, previous work 0x%08x",
(int)(_WORK->timeout - sleep_work->timeout),
(size_t)_WORK->work_route,
(size_t)sleep_work->work_route);
#endif
}
}
2024-03-28 12:19:52 +08:00
_k_work_q_handler_take_event_list(&_WORK_Q->event_list, sys_time);
do
{
if (default_timer_q_hdl->hdl != NULL && /* 已创建软定时器队列对象 */
s_kit_init_struct.scheduler_disable == _k_nop && /* 非多线程 */
k_timer_q_handler(default_timer_q_hdl) == 0) /* 有就绪的定时任务 */
{
sys_time = _K_PORT->get_sys_ticks();
continue;
}
if (_WORK_Q->priority_tab != 0)
{
k_work_handle_t *exec_work = _k_work_q_handler_take_ready_work(_WORK->work_q_handle);
if (exec_work != NULL)
{
2025-02-13 17:17:07 +08:00
uint8_t exec_flag = exec_work->exec_flag;
2024-03-28 12:19:52 +08:00
exec_work->exec_flag = 1;
if (exec_work->obj_flag_type)
{
exec_work->work_route(exec_work->arg);
_k_timer_end(work_q_handle, exec_work);
}
else
{
if (s_cm_kit.curr_hook != exec_work->work_handle)
{
k_work_fn hook_entry;
s_cm_kit.curr_hook = exec_work->work_handle;
_k_work_log(exec_work->work_handle);
hook_entry = _WORK_Q->hook_entry;
if (hook_entry)
{
hook_entry(exec_work->work_handle);
}
}
exec_work->work_route(exec_work->arg);
}
_WORK_Q->curr_work = work_handle;
2025-02-13 17:17:07 +08:00
if (k_work_is_valid(exec_work->work_handle))
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
if (exec_work->delete_flag == 0)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
exec_work->exec_flag = exec_flag;
if (exec_work->obj_flag_type == 0 && exec_work->obj_data.mbox_list != NULL)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
if (_slist_peek_head(&exec_work->obj_data.mbox_list->mbox_idle) != NULL)
{
_K_DIS_SCHED();
_k_work_mbox_clr_list(&exec_work->obj_data.mbox_list->mbox_idle);
_K_EN_SCHED();
}
2024-03-28 12:19:52 +08:00
}
}
2025-02-13 17:17:07 +08:00
else
{
exec_work->exec_flag = 0;
k_work_delete(exec_work->work_handle);
}
2024-03-28 12:19:52 +08:00
}
}
}
if (work_handle->hdl == NULL)
{
break;
}
sys_time = _K_PORT->get_sys_ticks();
if (_k_work_q_handler_take_delay_list(_WORK_Q, sys_time) > 0 &&
_K_PORT->thread_sleep &&
*(volatile int *)&_WORK->timeout - sys_time > 0)
{
_K_PORT->thread_sleep(1);
sys_time = _K_PORT->get_sys_ticks();
_k_work_q_handler_take_delay_list(_WORK_Q, sys_time);
}
} while (*(volatile int *)&_WORK->timeout - sys_time > 0);
if (_WORK->exec_repeat != 0)
{
_WORK->exec_repeat = 0;
k_work_submit(_WORK->work_q_handle, _WORK->work_handle, 0);
}
if (_WORK_Q->curr_work)
{
if (s_cm_kit.curr_hook != _WORK_Q->curr_work)
{
k_work_fn hook_entry;
s_cm_kit.curr_hook = _WORK_Q->curr_work;
_k_work_log(_WORK_Q->curr_work);
hook_entry = _WORK_Q->hook_entry;
if (hook_entry)
{
hook_entry(_WORK_Q->curr_work);
}
}
}
_WORK_Q->sleep_work = sleep_work;
2024-03-28 12:19:52 +08:00
}
/**
* @brief
*
* @param work_q_handle k_work_q_create()
* @return k_work_t*
*/
k_work_t *k_get_curr_work_handle(k_work_q_t *work_q_handle)
{
2025-02-13 17:17:07 +08:00
k_work_q_handle_t *work_q;
_TEST_HANDLE(work_q_handle, return NULL);
work_q = work_q_handle->hdl;
2024-03-28 12:19:52 +08:00
return work_q->curr_work;
}
/**
* @brief
* : 20 bytes
*
* k_mbox k_fifo
* 1.
* 2.
* 3. 使 k_work_mbox_cancel()
*
* @param work_handle k_work_create()
* @return k_err_t 0 -- -1 --
*/
k_err_t k_work_mbox_create(k_work_t *work_handle)
{
k_work_handle_t *work;
k_work_mb_list_t *mbox_list;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(work_handle, return -1);
2024-03-28 12:19:52 +08:00
work = work_handle->hdl;
2025-02-13 17:17:07 +08:00
if (work->obj_flag_type != 0)
2024-03-28 12:19:52 +08:00
{
_DBG_WRN("work_handle invalid");
return -1;
}
if (work->obj_data.mbox_list != NULL)
{
_DBG_WRN("work mbox was be created");
return -1;
}
if (work->work_q_handle == NULL)
{
_DBG_WRN("work_handle = %p was not submit to any work_q_handle handle", work);
}
_K_DIS_SCHED();
mbox_list = _K_PORT->malloc(sizeof(*mbox_list));
if (mbox_list != NULL)
{
_slist_init_list(&mbox_list->mbox_idle);
_slist_init_list(&mbox_list->mbox_valid);
work->obj_data.mbox_list = mbox_list;
}
_K_EN_SCHED();
if (mbox_list == NULL)
{
_DBG_WRN("Insufficient memory");
return -1;
}
else
{
return 0;
}
}
/**
* @brief
*
* @param work_handle k_work_create()
*/
void k_work_mbox_delete(k_work_t *work_handle)
{
k_work_handle_t *work;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(work_handle, return);
2024-03-28 12:19:52 +08:00
work = work_handle->hdl;
if (work->obj_flag_type != 0)
{
_DBG_WRN("work_handle invalid");
return;
}
if (work->obj_data.mbox_list == NULL)
{
_DBG_WRN("work mbox never be created");
return;
}
_K_DIS_SCHED();
if (work->obj_data.mbox_list != NULL)
{
k_work_mb_list_t *mbox_list = work->obj_data.mbox_list;
_k_work_mbox_clr_list(&mbox_list->mbox_idle);
_k_work_mbox_clr_list(&mbox_list->mbox_valid);
_K_PORT->free(mbox_list);
work->obj_data.mbox_list = NULL;
}
_K_EN_SCHED();
}
/**
* @brief
*
*
* 8 bytes
*
* @param work_handle k_work_create()
* @param size
* @return void*
*/
void *k_work_mbox_alloc(k_work_t *work_handle, size_t size)
{
k_work_handle_t *work;
k_work_mb_handle_t *mbox_data;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(work_handle, return NULL);
2024-03-28 12:19:52 +08:00
work = work_handle->hdl;
if (work->work_q_handle == NULL)
{
_DBG_WRN("work was not pending or to be canceled");
return NULL;
}
if (work->obj_flag_type != 0)
{
_DBG_WRN("work_handle invalid");
return NULL;
}
if (work->obj_data.mbox_list == NULL)
{
_DBG_WRN("never create mbox with function 'k_work_mbox_create()'");
return NULL;
}
_K_DIS_SCHED();
mbox_data = _K_PORT->malloc(sizeof(*mbox_data) + size);
if (mbox_data != NULL)
{
mbox_data->ctrl.work_handle = work_handle;
}
_K_EN_SCHED();
if (mbox_data == NULL)
{
_DBG_WRN("Insufficient memory");
return NULL;
}
else
{
return (void *)&mbox_data[1];
}
}
/**
* @brief
*
* @param mbox k_work_mbox_alloc()
* @return k_err_t 0 -- -1 --
*/
k_err_t k_work_mbox_cancel(void *mbox)
{
k_work_mb_handle_t *mbox_data = &((k_work_mb_handle_t *)mbox)[-1];
k_err_t ret = 0;
2025-02-13 17:17:07 +08:00
if (mbox == NULL)
{
_DBG_WRN("mbox invalid");
return -1;
}
2024-03-28 12:19:52 +08:00
k_work_handle_t *work = mbox_data->ctrl.work_handle->hdl;
if (work == NULL)
{
_DBG_WRN("work_handle invalid");
ret = -1;
}
if (work->work_q_handle == NULL)
{
_DBG_WRN("work was not pending or to be canceled");
ret = -1;
}
if (work->obj_data.mbox_list == NULL)
{
_DBG_WRN("never create mbox with function 'k_work_mbox_create()'");
ret = -1;
}
if (ret == 0)
{
_K_DIS_SCHED();
_K_PORT->free(mbox_data);
_K_EN_SCHED();
}
return ret;
}
/**
* @brief
*
*
* @param mbox k_work_mbox_alloc()
* @return k_err_t 0 -- -1 --
*/
k_err_t k_work_mbox_submit(void *mbox)
{
k_work_mb_handle_t *mbox_data = &((k_work_mb_handle_t *)mbox)[-1];
k_work_handle_t *work = mbox_data->ctrl.work_handle->hdl;
k_err_t ret = 0;
2025-02-13 17:17:07 +08:00
if (mbox == NULL)
{
_DBG_WRN("mbox invalid");
return -1;
}
2024-03-28 12:19:52 +08:00
if (work == NULL)
{
_DBG_WRN("work_handle invalid");
ret = -1;
}
else if (work->work_q_handle == NULL)
{
_DBG_WRN("work was not pending or to be canceled");
ret = -1;
}
else if (work->obj_flag_type != 0)
{
_DBG_WRN("work_handle invalid");
ret = -1;
}
else if (work->obj_data.mbox_list == NULL)
{
_DBG_WRN("never create mbox with function 'k_work_mbox_create()'");
ret = -1;
}
if (ret != 0)
{
_K_DIS_SCHED();
_K_PORT->free(mbox_data);
_K_EN_SCHED();
return ret;
}
_slist_init_node(&mbox_data->ctrl.state_node);
_K_DIS_SCHED();
_slist_insert_tail(&work->obj_data.mbox_list->mbox_valid, &mbox_data->ctrl.state_node);
_K_EN_SCHED();
k_work_submit(work->work_q_handle, work->work_handle, 0);
return ret;
}
/**
* @brief
*
*
* @return void* NULL --
*/
void *k_work_mbox_take(void)
{
k_work_q_t *work_q_handle;
k_work_t *work_handle;
k_work_handle_t *work;
__slist_node_t *node;
_k_read_curr_handle(&work_q_handle, &work_handle);
work = work_handle->hdl;
if (work == NULL)
{
_DBG_WRN("work_handle invalid");
return NULL;
}
if (work->obj_flag_type != 0)
{
_DBG_WRN("work_handle invalid");
return NULL;
}
if (work->obj_data.mbox_list == NULL)
{
_DBG_WRN("never create mbox with function 'k_work_mbox_create()'");
return NULL;
}
_K_DIS_SCHED();
node = _slist_take_head(&work->obj_data.mbox_list->mbox_valid);
if (node == NULL)
{
_K_EN_SCHED();
return NULL;
}
else
{
k_work_mb_handle_t *mbox_data = _K_CONTAINER_OF(node, k_work_mb_handle_t, ctrl.state_node);
_slist_insert_tail(&work->obj_data.mbox_list->mbox_idle, &mbox_data->ctrl.state_node);
_K_EN_SCHED();
return &mbox_data[1];
}
}
/**
* @brief
*
* @return void* NULL --
*/
void *k_work_mbox_peek(void)
{
k_work_q_t *work_q_handle;
k_work_t *work_handle;
k_work_handle_t *work;
__slist_node_t *node;
_k_read_curr_handle(&work_q_handle, &work_handle);
work = work_handle->hdl;
if (work == NULL)
{
_DBG_WRN("work_handle invalid");
return NULL;
}
if (work->obj_flag_type != 0)
{
_DBG_WRN("work_handle invalid");
return NULL;
}
if (work->obj_data.mbox_list == NULL)
{
_DBG_WRN("never create mbox with function 'k_work_mbox_create()'");
return NULL;
}
node = _slist_peek_head(&work->obj_data.mbox_list->mbox_valid);
if (node == NULL)
{
return NULL;
}
else
{
k_work_mb_handle_t *mbox_data = _K_CONTAINER_OF(node, k_work_mb_handle_t, ctrl.state_node);
return (void *)&mbox_data[1];
}
}
/**
* @brief
*/
void k_work_mbox_clr(void)
{
k_work_q_t *work_q_handle;
k_work_t *work_handle;
k_work_handle_t *work;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
_k_read_curr_handle(&work_q_handle, &work_handle);
work = work_handle->hdl;
if (work == NULL)
{
_DBG_WRN("work_handle invalid");
return;
}
if (work->obj_flag_type != 0)
{
_DBG_WRN("work_handle invalid");
return;
}
if (work->obj_data.mbox_list == NULL)
{
_DBG_WRN("work mbox never be created");
return;
}
_K_DIS_SCHED();
if (work->obj_data.mbox_list != NULL)
{
_k_work_mbox_clr_list(&work->obj_data.mbox_list->mbox_idle);
_k_work_mbox_clr_list(&work->obj_data.mbox_list->mbox_valid);
}
_K_EN_SCHED();
}
/**
* @brief
*
*
* 1.
* 2.
* 32 bytes
*
* @param timer_q_handle k_timer_q_create()
* @return k_tick_t
*/
k_tick_t k_timer_q_handler(k_timer_q_t *timer_q_handle)
{
return k_work_q_handler((k_work_q_t *)timer_q_handle);
}
/**
* @brief
*
* : 104 bytes
*
* @param timer_q_handle[out]
* @return k_err_t 0 -- , -1 --
*/
k_err_t k_timer_q_create(k_timer_q_t *timer_q_handle)
{
return k_work_q_create((k_work_q_t *)timer_q_handle);
}
/**
* @brief
* 1.
* 2.
* 3.
* 4.
*
* @param timer_q_handle k_timer_q_create()
*/
void k_timer_q_delete(k_timer_q_t *timer_q_handle)
{
k_work_q_delete((k_work_q_t *)timer_q_handle);
}
/**
* @brief
*
* @param timer_q_handle k_timer_q_create()
* @param timer_q_resume
* @param arg
*/
void k_timer_q_resume_regist(k_timer_q_t *timer_q_handle, k_timer_q_fn timer_q_resume, void *arg)
{
k_work_q_resume_regist((k_work_q_t *)timer_q_handle, (k_work_q_fn)timer_q_resume, arg);
}
/**
* @brief
*
* @param timer_q_handle k_timer_q_create()
* @retval true
* @retval false
*/
bool k_timer_q_is_valid(k_timer_q_t *timer_q_handle)
{
return k_work_q_is_valid((k_work_q_t *)timer_q_handle);
}
/**
* @brief
*
* @retval true
* @retval false
*/
bool k_timer_q_delayed_state(k_timer_q_t *timer_q_handle)
{
return k_work_q_delayed_state((k_work_q_t *)timer_q_handle);
}
/**
* @brief
*
* @param timer_q_handle k_timer_q_create()
* @retval true
* @retval false
*/
bool k_timer_q_ready_state(k_timer_q_t *timer_q_handle)
{
return k_work_q_ready_state((k_work_q_t *)timer_q_handle);
}
/**
* @brief
*
*
* k_timer_q_handler()
* : 48 bytes
*
* @param timer_handle[out]
* @param timer_q_handle k_timer_q_create()
* @param timer_route
* @param arg
* @param priority 0 .. 70
* @return k_err_t 0 -- -1 --
*/
k_err_t k_timer_create(k_timer_t *timer_handle,
k_timer_q_t *timer_q_handle,
k_timer_fn timer_route,
void *arg,
uint8_t priority)
{
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(timer_q_handle, return -1);
2024-03-28 12:19:52 +08:00
if (k_work_create((k_work_t *)timer_handle, "", (k_work_fn)timer_route, arg, priority) == 0)
{
k_work_handle_t *work = timer_handle->hdl;
work->work_q_handle = (k_work_q_t *)timer_q_handle;
work->obj_flag_type = 1;
work->obj_data.period = _SIGNED_MAX(work->obj_data.period);
return 0;
}
else
{
return -1;
}
}
/**
* @brief
*
*
*
* @param timer_handle k_timer_create()
*/
void k_timer_delete(k_timer_t *timer_handle)
{
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(timer_handle, return);
2024-03-28 12:19:52 +08:00
if (timer_handle == NULL)
{
k_work_q_t *work_q_handle;
_k_read_curr_handle(&work_q_handle, (k_work_t **)&timer_handle);
}
_K_DIS_SCHED();
k_work_handle_t *work = timer_handle->hdl;
if (work->exec_flag == 0)
{
_k_work_delete((k_work_t *)timer_handle);
}
else
{
work->delete_flag = 1;
}
_K_EN_SCHED();
}
/**
* @brief
*
* @param timer_handle k_timer_create()
* @param periodic
* @param period
*/
void k_timer_set_period(k_timer_t *timer_handle, bool periodic, k_tick_t period)
{
k_work_handle_t *work = timer_handle->hdl;
if (work)
{
if ((size_t)period > _SIGNED_MAX(period))
2024-03-28 12:19:52 +08:00
{
period = _SIGNED_MAX(period);
}
_K_DIS_SCHED();
work->obj_flag_periodic = periodic;
work->obj_data.period = period;
_K_EN_SCHED();
}
else
{
_DBG_WRN("you must using k_timer_create() to create one timer_handle first");
}
}
/**
* @brief
*
* @param timer_handle k_timer_create()
* @param periodic
* @param period
* @param delay_ticks
*/
void k_timer_start(k_timer_t *timer_handle, k_tick_t delay_ticks)
{
2025-02-13 17:17:07 +08:00
k_work_handle_t *work;
_TEST_HANDLE(timer_handle, return);
work = timer_handle->hdl;
_k_work_do_submit(work->work_q_handle, (k_work_t *)timer_handle, _K_PORT->get_sys_ticks() + delay_ticks, _FALSE);
2024-03-28 12:19:52 +08:00
}
/**
* @brief
*
* @param timer_handle k_timer_create()
*/
void k_timer_stop(k_timer_t *timer_handle)
{
k_work_suspend((k_work_t *)timer_handle);
}
/**
* @brief
*
* @param timer_q_handle k_timer_q_create()
* @param timer_route
* @param arg
* @param delay_ticks
* @return k_err_t
*/
k_err_t k_timer_newsubmit(k_timer_q_t *timer_q_handle, k_timer_fn timer_route, void *arg, k_tick_t delay_ticks)
{
k_timer_t timer_handle;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(timer_q_handle, return -1);
2024-03-28 12:19:52 +08:00
memset(&timer_handle, 0, sizeof(timer_handle));
if (k_timer_create(
&timer_handle,
timer_q_handle,
timer_route,
arg,
0) == 0)
{
k_work_handle_t *work = timer_handle.hdl;
work->obj_flag_auto_del = 1;
k_timer_set_period(&timer_handle, _FALSE, delay_ticks);
k_timer_start(&timer_handle, delay_ticks);
return 0;
}
else
{
return -1;
}
}
/**
* @brief
*
* @param timer_q_handle k_timer_q_create()
* @param timer_route
* @param arg
* @param delay_ticks
* @return k_err_t
*/
k_err_t k_timer_resubmit(k_timer_q_t *timer_q_handle, k_timer_fn timer_route, void *arg, k_tick_t delay_ticks)
{
k_timer_cancel(timer_q_handle, timer_route);
return k_timer_newsubmit(timer_q_handle, timer_route, arg, delay_ticks);
}
/**
* @brief
*
* @param timer_q_handle k_timer_q_create()
* @param timer_route
*/
void k_timer_cancel(k_timer_q_t *timer_q_handle, k_timer_fn timer_route)
{
k_work_q_handle_t *work_q;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(timer_q_handle, return);
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
work_q = timer_q_handle->hdl;
if (work_q != NULL)
{
do
{
__dlist_t *test_list = &work_q->event_list;
__dlist_node_t *test_node = _dlist_peek_head(test_list);
__dlist_node_t *end_node = _dlist_peek_tail(test_list);
__dlist_node_t *prev_node = NULL;
do
{
k_work_handle_t *test_work;
if (test_node == NULL)
{
break;
}
test_work = _K_CONTAINER_OF(test_node, k_work_handle_t, event_node);
if ((void *)test_work->work_route == (void *)timer_route)
{
_dlist_remove(test_list, test_node);
if (prev_node == NULL)
{
test_node = _dlist_peek_head(test_list);
}
else
{
test_node = _dlist_peek_next(test_list, prev_node);
}
_K_PORT->free(test_work);
}
else
{
prev_node = test_node;
test_node = _dlist_peek_next(test_list, prev_node);
}
} while (prev_node != end_node);
} while (0);
do
{
__slist_t *test_list = &work_q->delayed_list;
__slist_node_t *test_node = _slist_peek_head(test_list);
__slist_node_t *end_node = _slist_peek_tail(test_list);
__slist_node_t *prev_node = NULL;
do
{
k_work_handle_t *test_work;
if (test_node == NULL)
{
break;
}
test_work = _K_CONTAINER_OF(test_node, k_work_handle_t, state_node);
if ((void *)test_work->work_route == (void *)timer_route)
{
_slist_remove_next(test_list, prev_node, test_node);
if (prev_node == NULL)
{
test_node = _slist_peek_head(test_list);
}
else
{
test_node = _slist_peek_next(prev_node);
}
_K_PORT->free(test_work);
}
else
{
prev_node = test_node;
test_node = _slist_peek_next(prev_node);
}
} while (prev_node != end_node);
} while (0);
do
{
size_t i;
2024-03-28 12:19:52 +08:00
for (i = 0; i < sizeof(work_q->ready_list) / sizeof(work_q->ready_list[0]); i++)
{
__slist_t *test_list = &work_q->ready_list[i];
__slist_node_t *test_node = _slist_peek_head(test_list);
__slist_node_t *end_node = _slist_peek_tail(test_list);
__slist_node_t *prev_node = NULL;
do
{
k_work_handle_t *test_work;
if (test_node == NULL)
{
break;
}
test_work = _K_CONTAINER_OF(test_node, k_work_handle_t, state_node);
if ((void *)test_work->work_route == (void *)timer_route)
{
_slist_remove_next(test_list, prev_node, test_node);
if (prev_node == NULL)
{
test_node = _slist_peek_head(test_list);
}
else
{
test_node = _slist_peek_next(prev_node);
}
_K_PORT->free(test_work);
}
else
{
prev_node = test_node;
test_node = _slist_peek_next(prev_node);
}
} while (prev_node != end_node);
}
} while (0);
}
_K_EN_SCHED();
}
/**
* @brief
*
* @param timer_handle k_timer_create()
* @retval true
* @retval false
*/
bool k_timer_is_valid(k_timer_t *timer_handle)
{
return k_work_is_valid((k_work_t *)timer_handle);
}
/**
* @brief
*
* @param timer_handle k_timer_create()
* @retval true
* @retval false
*/
bool k_timer_is_pending(k_timer_t *timer_handle)
{
return k_work_is_pending((k_work_t *)timer_handle);
}
/**
* @brief
*
* @param timer_handle k_timer_create()
* @retval true
* @retval false
*/
bool k_timer_is_periodic(k_timer_t *timer_handle)
{
k_work_handle_t *work = timer_handle->hdl;
return (bool)!!work->obj_flag_periodic;
}
/**
* @brief
*
* @param timer_handle
* @return k_tick_t
*/
k_tick_t k_timer_get_period(k_timer_t *timer_handle)
{
2025-02-13 17:17:07 +08:00
k_work_handle_t *work;
_TEST_HANDLE(timer_handle, return -1u);
work = timer_handle->hdl;
2024-03-28 12:19:52 +08:00
return work->obj_data.period;
}
/**
* @brief
*
* @param timer_handle
* @return k_tick_t
*/
k_tick_t k_timer_time_remain(k_timer_t *timer_handle)
{
return k_work_time_remain((k_work_t *)timer_handle);
}
/**
* @brief FIFO对象
*
* : 20 bytes
*
* @param fifo_handle[out] FIFO对象指针
* @return k_err_t 0 -- , -1 --
*/
k_err_t k_fifo_q_create(k_fifo_t *fifo_handle)
{
k_fifo_q_handle_t *fifo_q;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
_K_DIS_SCHED();
fifo_q = _K_PORT->malloc(sizeof(k_fifo_q_handle_t));
if (fifo_q != NULL)
{
fifo_handle->hdl = fifo_q;
fifo_q->resume_work = NULL;
fifo_q->resume_delay = 0;
_slist_init_list(&fifo_q->list);
}
_K_EN_SCHED();
if (fifo_q == NULL)
{
_DBG_WRN("Insufficient memory");
return -1;
}
else
{
return 0;
}
}
/**
* @brief FIFO的对象
* 1.
* 2. FIFO对象被删除
* 3. FIFO对象及数据的堆内存被自动回收
*
* @param fifo_handle k_fifo_q_create()
*/
void k_fifo_q_delete(k_fifo_t *fifo_handle)
{
k_fifo_q_handle_t *fifo_q;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(fifo_handle, return);
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
2025-02-13 17:17:07 +08:00
2024-03-28 12:19:52 +08:00
fifo_q = fifo_handle->hdl;
2025-02-13 17:17:07 +08:00
for (;;)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
__slist_node_t *node = _slist_take_head(&fifo_q->list);
if (node == NULL)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
break;
}
else
{
k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node);
_K_PORT->free(fifo_data);
2024-03-28 12:19:52 +08:00
}
}
2025-02-13 17:17:07 +08:00
_K_PORT->free(fifo_q);
fifo_handle->hdl = NULL;
2024-03-28 12:19:52 +08:00
_K_EN_SCHED();
}
/**
* @brief FIFO内的所有数据
*
* @param fifo_handle k_fifo_q_create()
*/
void k_fifo_q_clr(k_fifo_t *fifo_handle)
{
k_fifo_q_handle_t *fifo_q;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(fifo_handle, return);
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
2025-02-13 17:17:07 +08:00
2024-03-28 12:19:52 +08:00
fifo_q = fifo_handle->hdl;
2025-02-13 17:17:07 +08:00
for (;;)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
__slist_node_t *node = _slist_take_head(&fifo_q->list);
if (node == NULL)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
break;
}
else
{
k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node);
_K_PORT->free(fifo_data);
2024-03-28 12:19:52 +08:00
}
}
2025-02-13 17:17:07 +08:00
2024-03-28 12:19:52 +08:00
_K_EN_SCHED();
}
/**
* @brief FIFO
*
* @param fifo_handle k_fifo_q_create()
* @retval true
* @retval false
*/
bool k_fifo_q_is_valid(k_fifo_t *fifo_handle)
{
if (s_kit_init_struct.malloc == NULL || fifo_handle == NULL || fifo_handle->hdl == NULL)
{
return _FALSE;
}
else
{
return _TRUE;
}
}
/**
* @brief
*
*
* @param fifo_handle k_fifo_q_create()
* @param work_handle k_work_create()
* @param delay_ticks
*/
void k_fifo_q_regist(k_fifo_t *fifo_handle, k_work_t *work_handle, k_tick_t delay_ticks)
{
2025-02-13 17:17:07 +08:00
k_fifo_q_handle_t *fifo_q;
_TEST_HANDLE(fifo_handle, return);
fifo_q = fifo_handle->hdl;
fifo_q->resume_work = work_handle;
fifo_q->resume_delay = delay_ticks;
2024-03-28 12:19:52 +08:00
}
/**
* @brief
*
* @param fifo_handle k_fifo_q_create()
*/
void k_fifo_q_unregist(k_fifo_t *fifo_handle)
{
2025-02-13 17:17:07 +08:00
k_fifo_q_handle_t *fifo_q;
_TEST_HANDLE(fifo_handle, return);
fifo_q = fifo_handle->hdl;
2024-03-28 12:19:52 +08:00
fifo_q->resume_work = NULL;
}
/**
* @brief FIFO的数据结构
* 8 bytes
*
* @param size
* @return void* NULL
*/
void *k_fifo_alloc(size_t size)
{
k_fifo_handle_t *fifo_data;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
_K_DIS_SCHED();
fifo_data = _K_PORT->malloc(sizeof(*fifo_data) + size);
_K_EN_SCHED();
if (fifo_data == NULL)
{
_DBG_WRN("Insufficient memory");
return NULL;
}
else
{
fifo_data->ctrl.free_flag = _K_FIFO_FREE;
return (void *)&fifo_data[1];
}
}
/**
* @brief k_fifo_alloc()
* FIFO中时被释放
*
* @param data
* @return k_err_t 0 -- -1 -- FIFO中提取或数据无效
*/
k_err_t k_fifo_free(void *data)
{
k_fifo_handle_t *fifo_data;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
if (data == NULL)
{
_DBG_WRN("data invalid");
return -1;
}
2024-03-28 12:19:52 +08:00
fifo_data = &((k_fifo_handle_t *)data)[-1];
_K_DIS_SCHED();
if (fifo_data->ctrl.free_flag == _K_FIFO_FREE)
{
fifo_data->ctrl.free_flag = 0;
_K_PORT->free(fifo_data);
fifo_data = NULL;
}
_K_EN_SCHED();
if (fifo_data != NULL)
{
_DBG_WRN("%p was not in fifo queue, can not to free", data);
return -1;
}
else
{
return 0;
}
}
/**
* @brief FIFO中
*
* @param fifo_handle k_fifo_q_create()
* @param data
* @return k_err_t 0 -- -1 -- FIFO对象无效或数据结不是由 k_fifo_alloc()
*/
k_err_t k_fifo_put(k_fifo_t *fifo_handle, void *data)
{
2025-02-13 17:17:07 +08:00
k_fifo_q_handle_t *fifo_q;
k_fifo_handle_t *fifo_data;
bool resume_flag = _FALSE;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(fifo_handle, return -1);
if (data == NULL)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
_DBG_WRN("data invalid");
2024-03-28 12:19:52 +08:00
return -1;
}
2025-02-13 17:17:07 +08:00
fifo_q = fifo_handle->hdl;
fifo_data = &((k_fifo_handle_t *)data)[-1];
if (fifo_data->ctrl.free_flag != _K_FIFO_FREE)
2024-03-28 12:19:52 +08:00
{
_DBG_WRN("fifo_data invalid");
return -1;
}
_slist_init_node(&fifo_data->ctrl.state_node);
_K_DIS_INT();
if (_slist_peek_head(&fifo_q->list) == NULL)
{
2025-02-13 17:17:07 +08:00
resume_flag = _TRUE;
2024-03-28 12:19:52 +08:00
}
_slist_insert_tail(&fifo_q->list, &fifo_data->ctrl.state_node);
_K_EN_INT();
if (resume_flag)
{
_k_ipc_resume(fifo_q->resume_work, fifo_q->resume_delay);
2024-03-28 12:19:52 +08:00
}
return 0;
}
/**
* @brief FIFO中弹出最先压入的数据
*
* @param fifo_handle k_fifo_q_create()
* @return void* NULL -- FIFO队列为空
*/
void *k_fifo_take(k_fifo_t *fifo_handle)
{
2025-02-13 17:17:07 +08:00
k_fifo_q_handle_t *fifo_q;
2024-03-28 12:19:52 +08:00
__slist_node_t *node;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(fifo_handle, return NULL);
fifo_q = fifo_handle->hdl;
2024-03-28 12:19:52 +08:00
_K_DIS_INT();
node = _slist_take_head(&fifo_q->list);
_K_EN_INT();
if (node == NULL)
{
return NULL;
}
else
{
k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node);
fifo_data->ctrl.free_flag = _K_FIFO_FREE;
return (void *)&fifo_data[1];
}
}
/**
* @brief FIFO中头部的数据地址
*
* @param fifo_handle k_fifo_q_create()
* @return void* NULL -- FIFO队列为空
*/
void *k_fifo_peek_head(k_fifo_t *fifo_handle)
{
k_fifo_q_handle_t *fifo_q;
__slist_node_t *node;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(fifo_handle, return NULL);
2024-03-28 12:19:52 +08:00
fifo_q = fifo_handle->hdl;
node = _slist_peek_head(&fifo_q->list);
if (node == NULL)
{
return NULL;
}
else
{
k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node);
return (void *)&fifo_data[1];
}
}
/**
* @brief FIFO中尾部的数据地址
*
* @param fifo_handle k_fifo_q_create()
* @return void* NULL -- FIFO队列为空
*/
void *k_fifo_peek_tail(k_fifo_t *fifo_handle)
{
k_fifo_q_handle_t *fifo_q;
__slist_node_t *node;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(fifo_handle, return NULL);
2024-03-28 12:19:52 +08:00
fifo_q = fifo_handle->hdl;
node = _slist_peek_tail(&fifo_q->list);
if (node == NULL)
{
return NULL;
}
else
{
k_fifo_handle_t *fifo_data = _K_CONTAINER_OF(node, k_fifo_handle_t, ctrl.state_node);
return (void *)&fifo_data[1];
}
}
/**
* @brief QUEUE对象
*
* : 32 bytes
*
* @param queue_handle[out] QUEUE对象指针
* @param queue_length
* @param item_size
* @return k_err_t 0 -- , -1 --
*/
k_err_t k_queue_create(k_queue_t *queue_handle, size_t queue_length, size_t item_size)
{
size_t real_item_size;
k_queue_handle_t *queue;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
real_item_size = (size_t) & ((k_queue_data_t *)0)[1] + (item_size + sizeof(size_t) - 1) / sizeof(size_t) * sizeof(size_t);
_K_DIS_SCHED();
queue = _K_PORT->malloc(sizeof(k_queue_handle_t) + real_item_size * queue_length);
if (queue != NULL)
{
size_t i;
queue_handle->hdl = queue;
queue->item_size = item_size;
queue->resume_work = NULL;
queue->resume_delay = 0;
_slist_init_list(&queue->list_valid);
_slist_init_list(&queue->list_idle);
for (i = 0; i < queue_length; i++)
{
k_queue_data_t *queue_data = (k_queue_data_t *)&((uint8_t *)&queue[1])[real_item_size * i];
queue_data->queue_handle = queue_handle;
_slist_init_node(&queue_data->ctrl.state_node);
_slist_insert_tail(&queue->list_idle, &queue_data->ctrl.state_node);
}
}
_K_EN_SCHED();
if (queue == NULL)
{
_DBG_WRN("Insufficient memory");
return -1;
}
else
{
return 0;
}
}
/**
* @brief QUEUE的对象
* 1.
* 2. QUEUE对象被删除
* 3. QUEUE对象及数据的堆内存被自动回收
*
* @param queue_handle k_queue_create()
*/
void k_queue_delete(k_queue_t *queue_handle)
{
k_queue_handle_t *queue;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(queue_handle, return);
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
queue = queue_handle->hdl;
if (queue != NULL)
{
_K_PORT->free(queue);
queue_handle->hdl = NULL;
}
_K_EN_SCHED();
}
/**
* @brief QUEUE内的所有数据
*
* @param queue_handle k_queue_create()
*/
void k_queue_clr(k_queue_t *queue_handle)
{
k_queue_handle_t *queue;
__slist_node_t *node;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(queue_handle, return);
2024-03-28 12:19:52 +08:00
queue = queue_handle->hdl;
if (queue != NULL)
{
for (;;)
{
_K_DIS_INT();
node = _slist_take_head(&queue->list_valid);
if (node == NULL)
{
_K_EN_INT();
break;
}
else
{
_slist_insert_font(&queue->list_idle, node);
_K_EN_INT();
}
}
}
}
/**
* @brief QUEUE
*
* @param queue_handle k_queue_create()
* @retval true
* @retval false
*/
bool k_queue_is_valid(k_queue_t *queue_handle)
{
if (s_kit_init_struct.malloc == NULL || queue_handle == NULL || queue_handle->hdl == NULL)
{
return _FALSE;
}
else
{
return _TRUE;
}
}
/**
* @brief
*
*
* @param queue_handle k_queue_create()
* @param work_handle k_work_create()
* @param delay_ticks
*/
void k_queue_regist(k_queue_t *queue_handle, k_work_t *work_handle, k_tick_t delay_ticks)
{
2025-02-13 17:17:07 +08:00
k_queue_handle_t *queue;
_TEST_HANDLE(queue_handle, return);
queue = queue_handle->hdl;
queue->resume_work = work_handle;
queue->resume_delay = delay_ticks;
2024-03-28 12:19:52 +08:00
}
/**
* @brief
*
* @param queue_handle k_queue_create()
*/
void k_queue_unregist(k_queue_t *queue_handle)
{
2025-02-13 17:17:07 +08:00
k_queue_handle_t *queue;
_TEST_HANDLE(queue_handle, return);
queue = queue_handle->hdl;
2024-03-28 12:19:52 +08:00
queue->resume_work = NULL;
}
/**
* @brief
* k_queue_take() + memcpy() + k_queue_free()
*
* @param queue_handle k_queue_create()
* @param dst
* @return k_err_t 0 -1
*/
k_err_t k_queue_recv(k_queue_t *queue_handle, void *dst)
{
k_queue_handle_t *queue;
void *data = k_queue_take(queue_handle);
if (data == NULL)
{
return -1;
}
queue = queue_handle->hdl;
memcpy(dst, data, queue->item_size);
k_queue_free(data);
return 0;
}
/**
* @brief
* k_queue_alloc() + memcpy() + k_queue_put()
*
* @param queue_handle k_queue_create()
* @param src
* @return k_err_t 0 -1
*/
k_err_t k_queue_send(k_queue_t *queue_handle, const void *src)
{
k_queue_handle_t *queue;
void *data = k_queue_alloc(queue_handle);
if (data == NULL)
{
return -1;
}
queue = queue_handle->hdl;
memcpy(data, src, queue->item_size);
k_queue_put(data);
return 0;
}
/**
* @brief QUEUE的数据结构
* 4 bytes
*
* @param queue_handle k_queue_create()
* @return void* 0
*/
void *k_queue_alloc(k_queue_t *queue_handle)
{
2025-02-13 17:17:07 +08:00
k_queue_handle_t *queue;
2024-03-28 12:19:52 +08:00
__slist_node_t *node;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(queue_handle, return NULL);
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
queue = queue_handle->hdl;
2024-03-28 12:19:52 +08:00
_K_DIS_INT();
node = _slist_take_head(&queue->list_idle);
_K_EN_INT();
if (node == NULL)
{
return NULL;
}
else
{
k_queue_data_t *queue_data = _K_CONTAINER_OF(node, k_queue_data_t, ctrl.state_node);
queue_data->ctrl.free_flag = _K_QUEUE_FREE;
return (void *)&queue_data[1];
}
}
/**
* @brief k_queue_alloc()
* QUEUE中时被释放
*
* @param data k_queue_alloc() k_queue_take()
* @return k_err_t 0 -- -1 -- QUEUE中弹出或数据无效
*/
k_err_t k_queue_free(void *data)
{
k_queue_data_t *queue_data;
k_queue_handle_t *queue;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
if (data == NULL)
{
_DBG_WRN("data invalid");
return -1;
}
queue_data = &((k_queue_data_t *)data)[-1];
2025-02-13 17:17:07 +08:00
if (queue_data->queue_handle == NULL || queue_data->queue_handle->hdl == NULL)
2024-03-28 12:19:52 +08:00
{
_DBG_WRN("queue_handle invalid");
return -1;
}
2025-02-13 17:17:07 +08:00
2024-03-28 12:19:52 +08:00
if (queue_data->ctrl.free_flag != _K_QUEUE_FREE)
{
_DBG_WRN("%p was freed", data);
return -1;
}
2025-02-13 17:17:07 +08:00
queue = (k_queue_handle_t *)queue_data->queue_handle->hdl;
2024-03-28 12:19:52 +08:00
_slist_init_node(&queue_data->ctrl.state_node);
_K_DIS_INT();
_slist_insert_font(&queue->list_idle, &queue_data->ctrl.state_node);
_K_EN_INT();
return 0;
}
/**
* @brief QUEUE中
*
* @param data k_queue_alloc() k_queue_take()
* @return k_err_t 0 -- -1 -- QUEUE对象无效或数据结不是由 k_queue_alloc()
*/
k_err_t k_queue_put(void *data)
{
k_queue_data_t *queue_data;
k_queue_handle_t *queue;
2025-02-13 17:17:07 +08:00
bool resume_flag = _FALSE;
2024-03-28 12:19:52 +08:00
if (data == NULL)
{
_DBG_WRN("data invalid");
return -1;
}
queue_data = &((k_queue_data_t *)data)[-1];
2025-02-13 17:17:07 +08:00
if (queue_data->queue_handle == NULL || queue_data->queue_handle->hdl == NULL)
2024-03-28 12:19:52 +08:00
{
_DBG_WRN("queue_handle invalid");
return -1;
}
if (queue_data->ctrl.free_flag != _K_QUEUE_FREE)
{
_DBG_WRN("%p was freed", data);
return -1;
}
2025-02-13 17:17:07 +08:00
queue = (k_queue_handle_t *)queue_data->queue_handle->hdl;
2024-03-28 12:19:52 +08:00
_slist_init_node(&queue_data->ctrl.state_node);
_K_DIS_INT();
if (_slist_peek_head(&queue->list_valid) == NULL)
{
2025-02-13 17:17:07 +08:00
resume_flag = _TRUE;
2024-03-28 12:19:52 +08:00
}
_slist_insert_tail(&queue->list_valid, &queue_data->ctrl.state_node);
_K_EN_INT();
if (resume_flag)
{
_k_ipc_resume(queue->resume_work, queue->resume_delay);
2024-03-28 12:19:52 +08:00
}
return 0;
}
/**
* @brief QUEUE中弹出最先压入的数据
*
* @param queue_handle k_queue_create()
* @return void* NULL -- QUEUE队列为空
*/
void *k_queue_take(k_queue_t *queue_handle)
{
2025-02-13 17:17:07 +08:00
k_queue_handle_t *queue;
2024-03-28 12:19:52 +08:00
__slist_node_t *node;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(queue_handle, return NULL);
queue = queue_handle->hdl;
2024-03-28 12:19:52 +08:00
_K_DIS_INT();
node = _slist_take_head(&queue->list_valid);
_K_EN_INT();
if (node == NULL)
{
return NULL;
}
else
{
k_queue_data_t *queue_data = _K_CONTAINER_OF(node, k_queue_data_t, ctrl.state_node);
queue_data->ctrl.free_flag = _K_QUEUE_FREE;
return (void *)&queue_data[1];
}
}
/**
* @brief QUEUE中头部的数据地址
*
* @param queue_handle k_queue_create()
* @return void* NULL -- QUEUE队列为空
*/
void *k_queue_peek_head(k_queue_t *queue_handle)
{
k_queue_handle_t *queue;
__slist_node_t *node;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(queue_handle, return NULL);
2024-03-28 12:19:52 +08:00
queue = queue_handle->hdl;
node = _slist_peek_head(&queue->list_valid);
if (node == NULL)
{
return NULL;
}
else
{
k_queue_data_t *queue_data = _K_CONTAINER_OF(node, k_queue_data_t, ctrl.state_node);
return (void *)&queue_data[1];
}
}
/**
* @brief QUEUE中尾部的数据地址
*
* @param queue_handle k_queue_create()
* @return void* NULL -- QUEUE队列为空
*/
void *k_queue_peek_tail(k_queue_t *queue_handle)
{
k_queue_handle_t *queue;
__slist_node_t *node;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(queue_handle, return NULL);
2024-03-28 12:19:52 +08:00
queue = queue_handle->hdl;
node = _slist_peek_tail(&queue->list_valid);
if (node == NULL)
{
return NULL;
}
else
{
k_queue_data_t *queue_data = _K_CONTAINER_OF(node, k_queue_data_t, ctrl.state_node);
return (void *)&queue_data[1];
}
}
/**
* @brief
*
* @param data
* @return k_queue_t
*/
k_queue_t *k_queue_read_handle(void *data)
{
k_queue_data_t *queue_data;
if (data == NULL)
{
_DBG_WRN("data invalid");
return NULL;
}
queue_data = &((k_queue_data_t *)data)[-1];
return queue_data->queue_handle;
}
/**
* @brief k_queue_create() item_size
*
* @param queue_handle k_queue_create()
* @return size_t k_queue_create() item_size
*/
size_t k_queue_get_item_size(k_queue_t *queue_handle)
{
k_queue_handle_t *queue;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(queue_handle, return 0);
2024-03-28 12:19:52 +08:00
queue = queue_handle->hdl;
return queue->item_size;
}
/**
* @brief
* : 24 bytes
*
* @param pipe_handle[out]
* @param pipe_size
* @return k_err_t 0 -- , -1 --
*/
k_err_t k_pipe_create(k_pipe_t *pipe_handle, size_t pipe_size)
{
k_pipe_handle_t *pipe;
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
pipe_size++;
_K_DIS_SCHED();
pipe = _K_PORT->malloc(sizeof(k_pipe_handle_t) + pipe_size);
if (pipe != NULL)
{
pipe_handle->hdl = pipe;
pipe->size = pipe_size;
pipe->resume_work = NULL;
pipe->resume_delay = 0;
}
_K_EN_SCHED();
if (pipe == NULL)
{
_DBG_WRN("Insufficient memory");
return -1;
}
else
{
k_pipe_clr(pipe_handle);
return 0;
}
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
*/
void k_pipe_delete(k_pipe_t *pipe_handle)
{
_ASSERT_FALSE(s_kit_init_struct.malloc == NULL, "Never use 'k_init()' to initialize");
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(pipe_handle, return);
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
2025-02-13 17:17:07 +08:00
_K_PORT->free(pipe_handle->hdl);
pipe_handle->hdl = NULL;
2024-03-28 12:19:52 +08:00
_K_EN_SCHED();
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
*/
void k_pipe_clr(k_pipe_t *pipe_handle)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(pipe_handle, return);
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
2024-03-28 12:19:52 +08:00
_K_DIS_SCHED();
pipe->wid = 0;
pipe->rid = 0;
_K_EN_SCHED();
}
/**
* @brief PIPE
*
* @param pipe_handle k_pipe_create()
* @retval true
* @retval false
*/
bool k_pipe_is_valid(k_pipe_t *pipe_handle)
{
if (s_kit_init_struct.malloc == NULL || pipe_handle == NULL || pipe_handle->hdl == NULL)
{
return _FALSE;
}
else
{
return _TRUE;
}
}
/**
* @brief
*
*
* @param pipe_handle k_pipe_create()
* @param work_handle k_work_create()
* @param delay_ticks
*/
void k_pipe_regist(k_pipe_t *pipe_handle, k_work_t *work_handle, k_tick_t delay_ticks)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
_TEST_HANDLE(pipe_handle, return);
pipe = pipe_handle->hdl;
pipe->resume_work = work_handle;
pipe->resume_delay = delay_ticks;
2024-03-28 12:19:52 +08:00
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
*/
void k_pipe_unregist(k_pipe_t *pipe_handle)
{
k_pipe_handle_t *pipe = pipe_handle->hdl;
pipe->resume_work = NULL;
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
* @param data
* @return size_t
*/
size_t k_pipe_poll_write(k_pipe_t *pipe_handle, uint8_t data)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
pipe_id_t wid;
2024-03-28 12:19:52 +08:00
bool resume_flag;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(pipe_handle, return 0);
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
wid = pipe->wid;
if (++wid >= pipe->size)
{
wid = 0;
}
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
if (wid != pipe->rid)
{
((uint8_t *)&pipe[1])[pipe->wid] = data;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
_K_DIS_INT();
resume_flag = (pipe->wid == pipe->rid);
pipe->wid = wid;
_K_EN_INT();
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
if (resume_flag)
{
_k_ipc_resume(pipe->resume_work, pipe->resume_delay);
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
return 1;
2024-03-28 12:19:52 +08:00
}
return 0;
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
* @param data NULL
* @param size
* @return size_t
*/
size_t k_pipe_fifo_fill(k_pipe_t *pipe_handle, const void *data, size_t size)
{
size_t ret = 0;
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
pipe_id_t wid;
2024-03-28 12:19:52 +08:00
bool resume_flag;
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(pipe_handle, return 0);
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
wid = pipe->wid;
resume_flag = (wid == pipe->rid);
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
while (size)
{
pipe_id_t rid = *(volatile pipe_id_t *)&pipe->rid;
pipe_id_t min;
pipe_id_t remain;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
if (wid >= rid)
{
remain = pipe->size - wid - (rid == 0);
}
else
{
remain = rid - wid - 1;
}
if (remain == 0)
{
break;
}
min = size < remain ? size : remain;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
if (data)
{
memcpy(&((uint8_t *)&pipe[1])[wid], &((uint8_t *)data)[ret], min);
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
if ((wid += min) >= pipe->size)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
wid = 0;
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
size -= min;
ret += min;
}
_K_DIS_INT();
resume_flag = (pipe->wid == pipe->rid);
pipe->wid = wid;
_K_EN_INT();
if (resume_flag && ret)
{
_k_ipc_resume(pipe->resume_work, pipe->resume_delay);
2024-03-28 12:19:52 +08:00
}
return ret;
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
* @param data
* @return size_t 0
*/
size_t k_pipe_poll_read(k_pipe_t *pipe_handle, uint8_t *data)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
pipe_id_t rid;
_TEST_HANDLE(pipe_handle, return 0);
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
rid = pipe->rid;
if (rid != pipe->wid)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
data[0] = ((uint8_t *)&pipe[1])[rid++];
if (rid < pipe->size)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
pipe->rid = rid;
}
else
{
pipe->rid = 0;
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
return 1;
2024-03-28 12:19:52 +08:00
}
return 0;
}
/**
* @brief data NULL
*
* @param pipe_handle k_pipe_create()
* @param data NULL
* @param size
* @return size_t
*/
size_t k_pipe_fifo_read(k_pipe_t *pipe_handle, void *data, size_t size)
{
size_t ret = 0;
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
pipe_id_t rid;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
_TEST_HANDLE(pipe_handle, return 0);
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
rid = pipe->rid;
while (size)
{
pipe_id_t wid = *(volatile pipe_id_t *)&pipe->wid;
pipe_id_t min;
pipe_id_t remain;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
if (rid > wid)
{
remain = pipe->size - rid;
}
else
{
remain = wid - rid;
}
if (remain == 0)
{
break;
}
min = size < remain ? size : remain;
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
if (data)
{
memcpy(&((uint8_t *)data)[ret], &((uint8_t *)&pipe[1])[rid], min);
}
2024-03-28 12:19:52 +08:00
2025-02-13 17:17:07 +08:00
if ((rid += min) >= pipe->size)
{
rid = 0;
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
size -= min;
ret += min;
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
pipe->rid = rid;
2024-03-28 12:19:52 +08:00
return ret;
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
* @retval true
* @retval false
*/
bool k_pipe_is_ne(k_pipe_t *pipe_handle)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
_TEST_HANDLE(pipe_handle, return _FALSE);
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
if (pipe->rid == pipe->wid)
2024-03-28 12:19:52 +08:00
{
return _FALSE;
}
else
{
2025-02-13 17:17:07 +08:00
return _TRUE;
2024-03-28 12:19:52 +08:00
}
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
* @return size_t
*/
size_t k_pipe_get_valid_size(k_pipe_t *pipe_handle)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
_TEST_HANDLE(pipe_handle, return 0);
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
if (pipe->wid < pipe->rid)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
return pipe->size + pipe->wid - pipe->rid;
2024-03-28 12:19:52 +08:00
}
else
{
2025-02-13 17:17:07 +08:00
return pipe->wid - pipe->rid;
2024-03-28 12:19:52 +08:00
}
}
/**
* @brief
*
* @param pipe_handle k_pipe_create()
* @return size_t
*/
size_t k_pipe_get_empty_size(k_pipe_t *pipe_handle)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
_TEST_HANDLE(pipe_handle, return 0);
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
return pipe->size - (k_pipe_get_valid_size(pipe_handle) + 1);
2024-03-28 12:19:52 +08:00
}
/**
* @brief
* pipe dst_size
* 访
* 使 k_pipe_fifo_read(pipe_handle, NULL, size)
*
* @param pipe_handle k_pipe_create()
* @param dst_base[out]
* @param dst_size[out]
*/
void k_pipe_peek_valid(k_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
_TEST_HANDLE(pipe_handle, return);
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
if (dst_base)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
*dst_base = (&((uint8_t *)&pipe[1])[pipe->rid]);
}
if (dst_size)
{
pipe_id_t rid = pipe->rid;
pipe_id_t wid = pipe->wid;
if (rid > wid)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
*dst_size = pipe->size - rid;
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
else
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
*dst_size = wid - rid;
2024-03-28 12:19:52 +08:00
}
}
}
/**
* @brief
* pipe dst_size
* 访
* 使 k_pipe_fifo_fill(pipe_handle, NULL, size)
*
* @param pipe_handle k_pipe_create()
* @param dst_base[out]
* @param dst_size[out]
*/
void k_pipe_peek_empty(k_pipe_t *pipe_handle, void **dst_base, size_t *dst_size)
{
2025-02-13 17:17:07 +08:00
k_pipe_handle_t *pipe;
_TEST_HANDLE(pipe_handle, return);
pipe = (k_pipe_handle_t *)pipe_handle->hdl;
if (dst_base)
{
*dst_base = (&((uint8_t *)&pipe[1])[pipe->wid]);
}
if (dst_size)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
pipe_id_t rid = pipe->rid;
pipe_id_t wid = pipe->wid;
if (wid >= rid)
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
*dst_size = pipe->size - wid - (rid == 0);
2024-03-28 12:19:52 +08:00
}
2025-02-13 17:17:07 +08:00
else
2024-03-28 12:19:52 +08:00
{
2025-02-13 17:17:07 +08:00
*dst_size = rid - wid - 1;
2024-03-28 12:19:52 +08:00
}
}
}
/**
* @brief
*
* @return k_tick_t
*/
k_tick_t k_get_sys_ticks(void)
{
return _K_PORT->get_sys_ticks();
}
/**
* @brief
*
*/
void k_disable_interrupt(void)
{
_K_DIS_INT();
}
/**
* @brief
*
*/
void k_enable_interrupt(void)
{
_K_EN_INT();
}
/**
* @brief
*
*
* CONFIG_K_KIT_LOG_ON 0
*
*/
void k_log_sched(void)
{
#if (CONFIG_K_KIT_LOG_ON)
#define _WORK_NAME(WORK) ((k_work_handle_t *)WORK->hdl)->name
k_work_t *work = s_cm_kit.curr_hook;
size_t flag;
2024-03-28 12:19:52 +08:00
if (s_cm_kit.curr_log == work)
{
return;
}
else
{
s_cm_kit.curr_log = work;
}
_K_DIS_SCHED();
CONFIG_K_KIT_PRINT("\r\n");
do
{
size_t index;
2024-03-28 12:19:52 +08:00
const char *arg;
size_t max_index;
2024-03-28 12:19:52 +08:00
flag = 0;
max_index = sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]);
if (max_index > s_cm_kit.log_index)
{
max_index = s_cm_kit.log_index;
}
CONFIG_K_KIT_PRINT("[work_q]");
for (index = 0; index < max_index; index++)
{
if (s_cm_kit.work_log[index] == work)
{
index++;
break;
}
arg = _WORK_NAME(s_cm_kit.work_log[index]);
if (arg == NULL)
arg = "Unknow";
CONFIG_K_KIT_PRINT(" ==> '" _COLOR_C "%s" _COLOR_END "'", arg);
}
arg = _WORK_NAME(work);
if (arg == NULL)
arg = "Unknow";
if (index < s_cm_kit.log_max)
{
if (s_cm_kit.log_index > sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]))
{
CONFIG_K_KIT_PRINT(" ==> ... ==> '" _COLOR_C "%s" _COLOR_END "' >>>\r\n", arg);
}
else
{
size_t i;
2024-03-28 12:19:52 +08:00
CONFIG_K_KIT_PRINT(" ==> '" _COLOR_C "%s" _COLOR_END "'", arg);
max_index = sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]);
if (max_index > s_cm_kit.log_max)
{
max_index = s_cm_kit.log_max;
}
for (i = index; i < max_index; i++)
{
arg = _WORK_NAME(s_cm_kit.work_log[i]);
if (arg == NULL)
arg = "Unknow";
CONFIG_K_KIT_PRINT(" <<< '" _COLOR_C "%s" _COLOR_END "'", arg);
s_cm_kit.work_log[i] = NULL;
}
if (s_cm_kit.log_max > sizeof(s_cm_kit.work_log) / sizeof(s_cm_kit.work_log[0]))
{
CONFIG_K_KIT_PRINT(" <<< ...");
}
CONFIG_K_KIT_PRINT("\r\n");
s_cm_kit.log_max = index;
flag = 1;
}
}
else
{
CONFIG_K_KIT_PRINT(" ==> '" _COLOR_C "%s" _COLOR_END "' >>>\r\n", arg);
}
} while (flag);
_K_EN_SCHED();
#undef _WORK_NAME
#endif
}