495 lines
14 KiB
C
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);
|
|
}
|