2025-12-17 15:55:25 +08:00

171 lines
4.5 KiB
C

#ifdef USE_LOGGER
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "base.h"
#include "kdrv_log.h"
#include "kmdw_memory.h"
#include "kl520_include.h"
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member), \
n = list_next_entry(pos, member); \
&pos->member != (head); \
pos = n, n = list_next_entry(n, member))
struct node {
struct node *next, *prev;
};
struct poollist
{
struct node list_hook;
int8_t cn_list;
};
struct pool_item
{
struct node list_hook;
void *item;
};
struct pool_info {
struct node list_hook;
int8_t len;
char buf[LOG_BUF_SIZE];
};
typedef struct log_pool_t {
struct poollist list;
uint8_t w_idx;
struct pool_info *p;
} log_pool_t;
static log_pool_t log_pool;
static osThreadId_t tid_log = NULL;
static kdrv_uart_handle_t uart_handle;
static bool en_logbuffer = FALSE;
/*******************************************************************************************************/
/* Private APIs */
/*******************************************************************************************************/
static inline void list_add(struct node *new_node, struct node *head)
{
struct node *prev = head;
struct node *next = head->next;
next->prev = new_node;
new_node->next = next;
new_node->prev = prev;
prev->next = new_node;
}
static inline void list_del_init(struct node *entry)
{
struct node *prev = entry->prev;
struct node *next = entry->next;
next->prev = prev;
prev->next = next;
entry->next = entry;
entry->prev = entry;
}
static void poollist_item_push(struct poollist* p, struct pool_item* pitem)
{
list_add(&pitem->list_hook, &p->list_hook);
++(p->cn_list);
}
static struct pool_item* poollist_item_pop(struct poollist* p)
{
struct pool_item* pitem = NULL, * pnext;
if (p->cn_list > 0)
{
list_for_each_entry_safe(pitem, pnext, &p->list_hook, list_hook)
{
--(p->cn_list);
list_del_init(&pitem->list_hook);
break;
}
}
return pitem;
}
static bool kdrv_init_log_pool(void)
{
if((log_pool.p = (struct pool_info *)kmdw_ddr_reserve(sizeof(struct pool_info)*LOG_BUF_SIZE)) != 0) {
log_pool.w_idx = 0;
return true;
}
return false;
}
static void kdrv_log_thread_running(void *argument)
{
struct pool_info *p_info;
for (;;) {
osThreadFlagsWait(FLAGS_KDRV_PRINT_LOG_EVENTS, osFlagsWaitAny, osWaitForever);
while((p_info = (struct pool_info *)poollist_item_pop(&log_pool.list)) != NULL)
{
kdrv_uart_write(uart_handle, (uint8_t *)&p_info->buf[0], p_info->len);
}
continue;
}
}
/*******************************************************************************************************/
/* Public APIs */
/*******************************************************************************************************/
void kdrv_log_push(char *str)
{
int8_t str_len = strlen(str);
if(en_logbuffer == TRUE) {
memcpy((void *)&log_pool.p[log_pool.w_idx].buf[0], (void *)str, str_len);
log_pool.p[log_pool.w_idx].len = str_len;
log_pool.p[log_pool.w_idx].buf[str_len] = '\0';
poollist_item_push(&log_pool.list, (struct pool_item*)&log_pool.p[log_pool.w_idx]);
if(log_pool.w_idx++ == LOG_BUF_NUM)
log_pool.w_idx = 0;
set_thread_event(tid_log, FLAGS_KDRV_PRINT_LOG_EVENTS);
}
else {
kdrv_uart_write(uart_handle, (uint8_t *)str, str_len);
}
}
kdrv_status_t kdrv_logger_thread_create(kdrv_uart_handle_t handle)
{
if (tid_log != NULL)
return KDRV_STATUS_ERROR;
if(kdrv_init_log_pool() == false)
return KDRV_STATUS_ERROR;
if((tid_log = osThreadNew(kdrv_log_thread_running, NULL, NULL)) != NULL) {
osThreadSetPriority (tid_log, osPriorityNormal);
uart_handle = handle;
en_logbuffer = TRUE;
return KDRV_STATUS_OK;
}
return KDRV_STATUS_ERROR;
}
#endif