Files
kunlun/common/dbglog/iot_dbglog.c
2024-09-28 14:24:04 +08:00

495 lines
14 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os shim includes */
#include "os_types.h"
#include "os_lock.h"
#include "os_mem.h"
#include "iot_io_api.h"
/*plc include*/
#include "iot_errno.h"
#include "os_utils.h"
#include "iot_utils.h"
#include "iot_dbglog.h"
#include "iot_dbglog_api.h"
#include "iot_string.h"
#include "iot_config.h"
#include "iot_config_api.h"
#include "iot_log_api.h"
#include "iot_dbglog_def.h"
#include "iot_mtd.h"
#include "flash.h"
#include "iot_cli_type_definition.h"
#if HW_PLATFORM == HW_PLATFORM_SIMU
#define DBGLOG_DEFAULT_LEVEL DBGLOG_INFO_LVL_2
#else /* HW_PLATFORM == HW_PLATFORM_SIMU */
#define DBGLOG_DEFAULT_LEVEL DBGLOG_ERR
#endif /* HW_PLATFORM == HW_PLATFORM_SIMU */
#if !IOT_DBGLOG_DEBUG_DISABLE
static uint32_t upload_dbglog(dbglog_buf_context_t *logbuf);
static void dbglog_add_argument(dbglog_buf_context_t *dbuf,
uint32_t index, uint32_t arg);
static int32_t dbglog_buf_get_offset(dbglog_buf_context_t *logbuf,
uint32_t *write_offset, uint32_t len);
/* static void manage_dbglog_buf(dbglog_buf_context_t *logbuf); */
static void dbglog_add_string_argument(dbglog_buf_context_t *dbuf,
uint32_t index, uint8_t* arg);
#endif
static uint32_t iot_get_time_offset();
static void iot_dbglog_timer_routine(timer_id_t timerid, void* arg);
static dbglog_info_t dbglogentry;
static uint32_t timestamp_offset;
extern module_group_config config_module[];
uint32_t iot_dbglog_init()
{
uint32_t ret = 0;
BUILD_BUG_ON(DBG_LOG_MINIMUM_LEVEL <= DBGLOG_DEFAULT_LEVEL);
dbglogentry.debuglog_lock = os_create_mutex(IOT_DBGLOG_MID);
if (dbglogentry.debuglog_lock == NULL) {
ret = ERR_NOMEM;
goto out;
}
for (uint16_t i = 0; i < MODULE_GROUP_NUM; i++)
{
dbglogentry.module_info[i].module_id = i;
dbglogentry.module_info[i].level = DBGLOG_DEFAULT_LEVEL;
}
DBGLOG_SET_DBUF_INFO(dbglogentry.debuglog, NULL, DBGLOG_MAX_BUFFER_SIZE, 0);
dbglogentry.seq = 0;
dbglogentry.timestamp_start = os_boot_time32();
dbglogentry.level = DBGLOG_DEFAULT_LEVEL;
#if (HW_PLATFORM > HW_PLATFORM_SIMU && IOT_LOG_TO_FLASH_ENABLE)
dbglogentry.upload_interval = iot_log_get_save_freq()*60000;
#else
dbglogentry.upload_interval = DBGLOG_DEFAULT_UPLOAD_TIME_PERIOD;
#endif
dbglogentry.upload_timer = os_create_timer(IOT_DBGLOG_MID, false,
iot_dbglog_timer_routine, NULL);
os_start_timer(dbglogentry.upload_timer, dbglogentry.upload_interval);
dbglogentry.is_initialized = true;
return ret;
out:
if (dbglogentry.debuglog_lock)
{
os_delete_mutex(dbglogentry.debuglog_lock);
}
return ret;
}
uint32_t iot_dbglog_deinit()
{
if (dbglogentry.debuglog_lock)
{
os_delete_mutex(dbglogentry.debuglog_lock);
}
dbglogentry.is_initialized = false;
return 0;
}
uint32_t register_dbglog_callback(DBGLOG_DEBUG_LOG_EVENT_CB callback)
{
dbglogentry.dbglog_send_debug_logs_cb = callback;
return 0;
}
#if !IOT_DBGLOG_DEBUG_DISABLE
#if IOT_FLASH_SIZE > 2
int32_t iot_dbglog_input_ex(uint16_t mod_id,
uint8_t log_lvl, uint16_t msg_id, uint8_t arg_cnt, ...)
#else
int32_t iot_dbglog_input_ex(uint16_t mod_id,
uint16_t msg_id, uint8_t arg_cnt, ...)
#endif
{
if (!dbglogentry.is_initialized) {
return ERR_INVAL;
}
#if HW_PLATFORM != HW_PLATFORM_SIMU
if (mtd_get_flash_size() == FLASH_1M) {
/* disable flash log for 1M flash chip to avoid flash failure */
return ERR_INVAL;
}
#endif
uint32_t ret = 0, seq = 0;
uint32_t payload_len;
va_list arg_list;
uint32_t record_length, write_offset;
os_acquire_mutex(dbglogentry.debuglog_lock);
dbglog_buf_context_t *logbuf = &dbglogentry.debuglog;
uint32_t fw_version = 1;
uint8_t *arg = NULL;
#if IOT_FLASH_SIZE > 2
uint8_t global_level = dbglogentry.level;
uint8_t module_level = DBGLOG_DEFAULT_LEVEL;
for (int i = 0; i < MODULE_GROUP_NUM; i++)
{
if ((mod_id >= config_module[i].group_start_module_id) &&
(mod_id <= config_module[i].group_end_module_id)) {
module_level = dbglogentry.module_info[i].level;
break;
}
}
if (log_lvl < module_level)
{
ret = ERR_INVAL;
goto out;
}
if (log_lvl < global_level)
{
ret = ERR_INVAL;
goto out;
}
#endif /* IOT_FLASH_SIZE > 2 */
if ((msg_id != RAW_DATA_MSG_ID) && (arg_cnt > DBGLOG_MAX_ARGUMENT_NUM))
{
ret = ERR_INVAL;
goto out;
}
va_start(arg_list, arg_cnt);
/*Add argument in order
* timestamp offset: 4 Byte
* sequence_number(per module): 4 Byte
* module_id: 2 Byte
* Message ID: 2 Byte
* Payload Len: 2 Byte
* Resvd: 2 Byte
*/
/* total record length is (4byte fw version) +
(4byte timestamp offset)+
(4byte sequence number) +
(4byte moduleid + messageid)+
(4byte payloadlen+reserved) + (arg *4) */
record_length = 4 + 4 + 4 + 4 + 4 + arg_cnt * 4;
payload_len = arg_cnt * 4;
if (msg_id == RAW_DATA_MSG_ID)
{
#if SUPPORT_RAW_DATA_LOG
arg = va_arg(arg_list, uint8_t*);
payload_len = arg_cnt;
if (payload_len > MAX_RAW_DATA_MSG_LEN)
payload_len = MAX_RAW_DATA_MSG_LEN;
//padding payload_len as multiple of 4
if (payload_len % 4) {
payload_len += (4 - payload_len % 4);
}
record_length = 4 + 4 + 4 + 4 + 4 + payload_len;
#else
//if not SUPPORT_RAW_DATA_LOG, RAW_DATA_MSG_ID will not be accepted
goto end_write;
#endif
}
if (dbglog_buf_get_offset(logbuf, &write_offset, record_length))
{
ret = ERR_INVAL;
goto out;
}
if (write_offset == 0)
{
dbglog_add_argument(logbuf, write_offset, fw_version);
write_offset += 4;
}
else
{
//decrease the offset for fw version
logbuf->write_offset -= 4;
}
timestamp_offset = iot_get_time_offset();
dbglog_add_argument(logbuf, write_offset, timestamp_offset);
write_offset += 4;
seq = DBGLOG_UPDATE_SEQ((&dbglogentry));
dbglog_add_argument(logbuf, write_offset, seq);
write_offset += 4;
dbglog_add_argument(logbuf, write_offset,
DBGLOG_SET_MSG_ID(mod_id, msg_id));
write_offset += 4;
dbglog_add_argument(logbuf, write_offset,
DBGLOG_SET_MSG_HDR(payload_len, 0));
write_offset += 4;
#if SUPPORT_RAW_DATA_LOG
if (msg_id == RAW_DATA_MSG_ID)
{
dbglog_add_string_argument(logbuf, write_offset, arg);
goto end_write;
}
#endif
for (uint32_t i = 0; i < arg_cnt; i++) {
dbglog_add_argument(logbuf, write_offset, va_arg(arg_list, uint32_t));
write_offset += 4;
}
end_write:
va_end(arg_list);
out:
os_release_mutex(dbglogentry.debuglog_lock);
return ret;
}
#endif
void iot_crash_dbglog_input(uint16_t mod_id, uint16_t msg_id,
uint8_t* data, uint32_t datalen)
{
if (!data || datalen == 0) {
return;
}
if (!dbglogentry.dbglog_send_debug_logs_cb) {
return;
}
dbglog_buf_context_t *logbuf = &dbglogentry.debuglog;
iot_pkt_t *buffer = logbuf->buffer;
uint8_t*tail = iot_pkt_data(buffer) + logbuf->write_offset;
if (logbuf->write_offset && buffer &&
(tail <= iot_pkt_block_ptr(buffer, IOT_PKT_BLOCK_END))) {
iot_pkt_set_tail(buffer, tail);
iot_pkt_push(buffer, sizeof(cli_msg_hdr_t)+ MAX_FRAME_CODE_LEN);
dbglogentry.dbglog_send_debug_logs_cb(iot_pkt_data(buffer), 1,
logbuf->write_offset);
logbuf->write_offset = 0;
logbuf->buffer = NULL;
}
if (datalen % 4) {
datalen += (4 - datalen % 4);
}
timestamp_offset = iot_get_time_offset();
(void)msg_id;
uint32_t fw_version = 1;
uint32_t timestamp = timestamp_offset+1;
uint32_t seq = DBGLOG_UPDATE_SEQ((&dbglogentry));
uint32_t mod_msg = DBGLOG_SET_MSG_ID(mod_id, RAW_DATA_MSG_ID);
uint32_t payload_len = DBGLOG_SET_MSG_HDR(datalen, 0);
uint32_t write_offset = 0;
iot_uint32_to_bytes(fw_version,
(uint8_t*)&data[MAX_FRAME_CODE_LEN + sizeof(cli_msg_hdr_t) + write_offset],
0);
write_offset += 4;
iot_uint32_to_bytes(timestamp,
(uint8_t*)&data[MAX_FRAME_CODE_LEN + sizeof(cli_msg_hdr_t) + write_offset],
0);
write_offset += 4;
iot_uint32_to_bytes(seq,
(uint8_t*)&data[MAX_FRAME_CODE_LEN + sizeof(cli_msg_hdr_t) + write_offset],
0);
write_offset += 4;
iot_uint32_to_bytes(mod_msg,
(uint8_t*)&data[MAX_FRAME_CODE_LEN + sizeof(cli_msg_hdr_t) + write_offset],
0);
write_offset += 4;
iot_uint32_to_bytes(payload_len,
(uint8_t*)&data[MAX_FRAME_CODE_LEN + sizeof(cli_msg_hdr_t) + write_offset],
0);
write_offset += 4;
write_offset += datalen;
dbglogentry.dbglog_send_debug_logs_cb(data, 1, write_offset);
}
#if !IOT_DBGLOG_DEBUG_DISABLE
static void dbglog_add_string_argument(dbglog_buf_context_t *dbuf,
uint32_t index, uint8_t* arg)
{
uint8_t * buffer;
buffer = iot_pkt_data(dbuf->buffer);
uint32_t arglen = iot_strlen((char*)arg);
if (arglen > MAX_RAW_DATA_MSG_LEN)
arglen = MAX_RAW_DATA_MSG_LEN;
for (uint32_t i = 0; i < arglen; i++)
{
buffer[index + i] = arg[i];
}
}
static void dbglog_add_argument(dbglog_buf_context_t *dbuf,
uint32_t index, uint32_t arg)
{
uint8_t * buffer = iot_pkt_data(dbuf->buffer);
iot_uint32_to_bytes(arg, (uint8_t*)&buffer[index], 0);
}
static int32_t malloc_dbglog_buf(dbglog_buf_context_t *dbuf)
{
dbuf->buffer = iot_pkt_alloc(DBGLOG_MAX_RAW_BUFFER_SIZE, IOT_DBGLOG_MID);
if (!dbuf->buffer) {
iot_printf("%s no pkt with len %d\n", __FUNCTION__, \
DBGLOG_MAX_RAW_BUFFER_SIZE);
return -1;
}
iot_pkt_reserve(dbuf->buffer, MAX_CLI_FRAME_HEAD + sizeof(cli_msg_hdr_t));
dbuf->write_offset = 0;
return 0;
}
static int32_t dbglog_buf_get_offset(
dbglog_buf_context_t *logbuf, uint32_t *write_offset, uint32_t len)
{
dbglog_buf_context_t *dbuf = logbuf;
if (DEBUGLOG_BUFFER_IS_EMPTY(dbuf))
{
if (malloc_dbglog_buf(dbuf) != 0) {
return -1;
}
}
if (DBGLOG_BUFFER_SPACE_AVAILABLE(dbuf, len / 4))
{
*write_offset = dbuf->write_offset;
dbuf->write_offset += len;
}
else
{
upload_dbglog(dbuf);
if (malloc_dbglog_buf(dbuf) != 0) {
return -1;
}
*write_offset = dbuf->write_offset;
dbuf->write_offset += len;
}
return 0;
}
#endif
static uint32_t iot_get_time_offset()
{
uint32_t now = os_boot_time32();
uint32_t start = dbglogentry.timestamp_start;
uint32_t offset = 0;
if (now >= start)
{
offset = now - start;
} else
{
offset = ((uint32_t)(-1) - (start - now));
}
return offset;
}
void iot_dbglog_config_module_level(uint16_t module_id, uint8_t level)
{
if ((level >= DBGLOG_VERBOSE) && (level <= DBGLOG_LVL_MAX)) {
if (module_id < MODULE_GROUP_NUM) {
dbglogentry.module_info[module_id].level = level;
}
}
}
void iot_dbglog_config_level(uint8_t level)
{
if ((level >= DBGLOG_VERBOSE) && (level <= DBGLOG_LVL_MAX)) {
dbglogentry.level = level;
iot_printf("set level as:%d\n", level);
}
}
uint8_t iot_dbglog_get_level()
{
uint8_t level = dbglogentry.level;
iot_printf("get level as:%d\n", level);
return dbglogentry.level;
}
uint8_t iot_dbglog_get_module_level(uint16_t module_id)
{
uint8_t level = 0;
if (module_id < MODULE_GROUP_NUM) {
level = dbglogentry.module_info[module_id].level;
iot_printf("get module %d level as:%d\n", module_id, level);
return level;
}
return DBGLOG_DEFAULT_LEVEL;
}
void iot_dbglog_start_stop_live_capture(uint8_t enable, uint8_t* log_receiver)
{
dbglogentry.live_capture = enable;
os_mem_cpy(dbglogentry.live_log_receiver, log_receiver, IOT_MAC_ADDR_LEN);
iot_printf("start_stop live capture:%d, receiver:%s\n", enable, log_receiver);
}
uint8_t iot_dbglog_live_capture_enabled()
{
return dbglogentry.live_capture;
}
uint8_t *iot_dbglog_live_log_receiver()
{
return dbglogentry.live_log_receiver;
}
static uint32_t upload_dbglog(dbglog_buf_context_t *logbuf)
{
iot_pkt_t *buffer = logbuf->buffer;
if (dbglogentry.dbglog_send_debug_logs_cb && logbuf->write_offset)
{
if (iot_pkt_set_tail(buffer, iot_pkt_data(buffer)
+ logbuf->write_offset) == NULL) {
IOT_ASSERT(0);
return 0;
}
logbuf->write_offset = 0;
logbuf->buffer = NULL;
dbglogentry.dbglog_send_debug_logs_cb(buffer, 0, 0);
}
os_start_timer(dbglogentry.upload_timer, dbglogentry.upload_interval);
return 0;
}
dbglog_info_t *get_dbglog_instance()
{
return &dbglogentry;
}
static void iot_dbglog_timer_routine(timer_id_t timerid, void* arg)
{
(void)timerid;
(void)arg;
os_acquire_mutex(dbglogentry.debuglog_lock);
upload_dbglog(&dbglogentry.debuglog);
os_release_mutex(dbglogentry.debuglog_lock);
}