285 lines
6.8 KiB
C
285 lines
6.8 KiB
C
// 主要是增加debug流,可以保存log到内存,然后发向流,可以作为定时保存log使用
|
|
// 这个流就不作保护,所以最好单线程去使用(如果多线程,可以增加锁),可以使用一个
|
|
// 全局去保存对应的句柄,但是这里就不全局保存也不使用全局(可以创建多个流,每个
|
|
// 独立的线程可以独立调试)
|
|
#include "debug_log_msi.h"
|
|
|
|
#define DEBUG_LOG_STREAM_MALLOC av_psram_malloc
|
|
#define DEBUG_LOG_STREAM_FREE av_psram_free
|
|
|
|
// 结构体申请空间函数
|
|
#define STREAM_LIBC_MALLOC av_malloc
|
|
#define STREAM_LIBC_FREE av_free
|
|
#define STREAM_LIBC_ZALLOC av_zalloc
|
|
|
|
#define DEBUG_LOG_MAX_NUM 10
|
|
#define DEBUG_LOG_CACHE_SIZE (1024 * 4) // 4K
|
|
|
|
#define DBG_LOG_FAIL_TIMES (3)
|
|
|
|
static int32_t debug_log_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
|
{
|
|
int32_t ret = RET_OK;
|
|
struct dbg_log_s *log_s = (struct dbg_log_s *) msi->priv;
|
|
switch (cmd_id)
|
|
{
|
|
case MSI_CMD_POST_DESTROY:
|
|
{
|
|
fbpool_destroy(&log_s->tx_pool);
|
|
if (log_s)
|
|
{
|
|
STREAM_LIBC_FREE(log_s);
|
|
msi->priv = NULL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSI_CMD_PRE_DESTROY:
|
|
{
|
|
if (log_s)
|
|
{
|
|
os_work_cancle2(&log_s->work, 1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSI_CMD_FREE_FB:
|
|
{
|
|
struct framebuff *fb = (struct framebuff *) param1;
|
|
if (fb->data)
|
|
{
|
|
DEBUG_LOG_STREAM_FREE(fb->data);
|
|
fb->data = NULL;
|
|
}
|
|
fb->rev = 0;
|
|
fbpool_put(&log_s->tx_pool, fb);
|
|
// 不需要内核去释放fb
|
|
ret = RET_OK + 1;
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t sync_debug_buf(struct dbg_log_s *log_s)
|
|
{
|
|
uint32_t flags;
|
|
int ret = 0;
|
|
|
|
struct framebuff *fb = NULL;
|
|
|
|
flags = disable_irq();
|
|
if (log_s->fb && log_s->offset)
|
|
{
|
|
fb = log_s->fb;
|
|
fb->len = log_s->offset;
|
|
log_s->fb = NULL;
|
|
log_s->offset = 0;
|
|
}
|
|
enable_irq(flags);
|
|
|
|
if (fb)
|
|
{
|
|
ret = fb->len;
|
|
msi_output_fb(log_s->s, fb);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int32 debug_log_sync_work(struct os_work *work)
|
|
{
|
|
struct dbg_log_s *log_s = (struct dbg_log_s *) work;
|
|
sync_debug_buf(log_s);
|
|
os_run_work_delay(work, 1000);
|
|
return 0;
|
|
}
|
|
|
|
void *dbg_log_msi(const char *host_name)
|
|
{
|
|
struct msi *s = NULL;
|
|
uint8_t isnew;
|
|
struct dbg_log_s *log_s;
|
|
s = msi_new(host_name, 0, &isnew);
|
|
|
|
if (isnew)
|
|
{
|
|
log_s = (struct dbg_log_s *) STREAM_LIBC_ZALLOC(sizeof(struct dbg_log_s));
|
|
ASSERT(log_s);
|
|
s->priv = (void *) log_s;
|
|
s->action = (msi_action) debug_log_action;
|
|
fbpool_init(&log_s->tx_pool, DEBUG_LOG_MAX_NUM);
|
|
log_s->s = s;
|
|
log_s->fb = NULL;
|
|
log_s->offset = 0;
|
|
OS_WORK_INIT(&log_s->work, debug_log_sync_work, 0);
|
|
os_run_work_delay(&log_s->work, 1000);
|
|
msi_add_output(s, NULL, R_DEBUG_STREAM);
|
|
s->enable = 1;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
uint8_t *get_debug_buf(struct dbg_log_s *log_s, uint32_t *write_len, uint32_t len)
|
|
{
|
|
uint8_t *malloc_buf;
|
|
uint8_t *buf;
|
|
uint32_t remain_size;
|
|
uint32_t flags;
|
|
uint8_t disable_irq_en = 0;
|
|
uint32_t times = 0;
|
|
|
|
struct framebuff *fb = NULL;
|
|
|
|
again:
|
|
flags = disable_irq();
|
|
if (log_s->fb && (DEBUG_LOG_CACHE_SIZE == log_s->offset))
|
|
{
|
|
fb = log_s->fb;
|
|
fb->len = log_s->offset;
|
|
log_s->fb = NULL;
|
|
log_s->offset = 0;
|
|
}
|
|
enable_irq(flags);
|
|
|
|
if (fb)
|
|
{
|
|
msi_output_fb(log_s->s, fb);
|
|
}
|
|
|
|
if (!log_s->fb)
|
|
{
|
|
malloc_buf = (uint8_t *) DEBUG_LOG_STREAM_MALLOC(DEBUG_LOG_CACHE_SIZE);
|
|
if (malloc_buf)
|
|
{
|
|
flags = disable_irq();
|
|
disable_irq_en = 1;
|
|
if (!log_s->fb)
|
|
{
|
|
log_s->fb = fbpool_get(&log_s->tx_pool, 0, log_s->s);
|
|
if (log_s->fb)
|
|
{
|
|
log_s->fb->data = malloc_buf;
|
|
log_s->offset = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG_STREAM_FREE(malloc_buf);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 如果没有关闭中断,就关闭中断去操?因为log_s->fb有可能需要同步,会被释放
|
|
if (!disable_irq_en)
|
|
{
|
|
flags = disable_irq();
|
|
disable_irq_en = 1;
|
|
}
|
|
if (log_s->fb)
|
|
{
|
|
buf = log_s->fb->data + log_s->offset;
|
|
remain_size = DEBUG_LOG_CACHE_SIZE - log_s->offset;
|
|
if (remain_size > len)
|
|
{
|
|
*write_len = len;
|
|
}
|
|
else
|
|
{
|
|
*write_len = remain_size;
|
|
}
|
|
|
|
log_s->offset += (*write_len);
|
|
}
|
|
else
|
|
{
|
|
*write_len = 0;
|
|
buf = NULL;
|
|
}
|
|
if (disable_irq_en)
|
|
{
|
|
enable_irq(flags);
|
|
}
|
|
times++;
|
|
// 如果保存失败,重新去尝试吧
|
|
if (!buf && (times < DBG_LOG_FAIL_TIMES))
|
|
{
|
|
os_sleep_ms(1);
|
|
goto again;
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
uint8_t *get_debug_buf_interrupt(struct dbg_log_s *log_s, uint32_t *write_len, uint32_t len)
|
|
{
|
|
uint8_t *buf;
|
|
uint32_t remain_size;
|
|
//uint32_t flags;
|
|
if (log_s->fb)
|
|
{
|
|
buf = log_s->fb->data + log_s->offset;
|
|
remain_size = DEBUG_LOG_CACHE_SIZE - log_s->offset;
|
|
if (remain_size >= len)
|
|
{
|
|
*write_len = len;
|
|
}
|
|
else
|
|
{
|
|
*write_len = remain_size;
|
|
log_s->fb->rev = 1; // 标记有数据漏了,log那里可以记录一下
|
|
}
|
|
if (!remain_size)
|
|
{
|
|
*write_len = 0;
|
|
buf = NULL;
|
|
}
|
|
log_s->offset += (*write_len);
|
|
}
|
|
else
|
|
{
|
|
*write_len = 0;
|
|
buf = NULL;
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
void hgprntf_debug_log_msi(void *priv, char *str, int32 len)
|
|
{
|
|
uint32_t in_disable_irq(void);
|
|
uint8_t *buf;
|
|
struct dbg_log_s *log_s = (struct dbg_log_s *) priv;
|
|
if (__in_interrupt() || in_disable_irq())
|
|
{
|
|
uint32_t cp_len;
|
|
if (len == 0)
|
|
{
|
|
len = os_strlen(str);
|
|
}
|
|
buf = get_debug_buf_interrupt(log_s, &cp_len, len);
|
|
if (buf)
|
|
{
|
|
os_memcpy(buf, str, cp_len);
|
|
len -= cp_len;
|
|
str += cp_len;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (len == 0)
|
|
{
|
|
len = os_strlen(str);
|
|
}
|
|
do
|
|
{
|
|
uint32_t cp_len;
|
|
buf = get_debug_buf(log_s, &cp_len, len);
|
|
if (buf)
|
|
{
|
|
os_memcpy(buf, str, cp_len);
|
|
len -= cp_len;
|
|
str += cp_len;
|
|
}
|
|
} while (len && buf);
|
|
} |