使用串口打印调试信息,通常设置为115200bps, N81,这种设置每秒打印10K+字节的调试信息。
比如打印信息:[I:ERROR][T:19/09/04 16:15:19:649][F:ca.c][C:ca_update_sys_mode][L:1979] Get CA status failed
,有100+字节,打印这条信息耗时约为10ms。
目前应用,只打印关键信息,每次操作有120+条打印信息,这样打印调试信息就耗时1.2S。
在项目实施过程中增加了网络打印调试手段。
网络打印简单说就是将打印信息通过网口经过网络将调试信息传送到打印接收端。具体实施时考虑资源消耗,使用UDP协议。具体实施如下:
1.初始化网络设备
static u32 debug_init(phandle param)
{
static bool b_is_inited = false;
u32 error_code = SUCCESS;
os_thread_create_t create_t;
bool ret = false;
static u32 thread_handle=0;
os_sem_create_t sem_create;
if (b_is_inited)
{
return SUCCESS;
}
/*平台网络初始化*/
......
/*创建信号量、线程*/
sem_create.pshared=0;
sem_create.sem_count=1;
ret=os_create_sem(sem_create,&g_debug_sem);
if(ret)
{
DEBUG_PRINTF_MONTAGE("os_create_sem failed,[p-err]=0x%x\n", ret);
return PUBLIC_MODULE_PUBLIC_DEBUG;
}
memset(&create_t,0,sizeof(create_t));
create_t.attr_set=OS_CREATE_ATTR_SET;
create_t.call_back = debug_net_send_thread;
create_t.parm = NULL;
create_t.schedpolicy=THREAD_SCHED_OTHER;
create_t.set_priority=THREAD_SET_PRIORITY_OFFSET;
create_t.priority=OS_THREAD_PRIORITY_MID;
create_t.detachstate=THREAD_CREATE_DETACHED;
create_t.stack_size = 0x10000;
create_t.thread_name="debug_send_network";
if (os_create_thread(create_t,&thread_handle))
{
DEBUG_PRINTF_MONTAGE("os_create_thread failed,[p-err]=0x%x\n", ret);
os_destroy_sem(g_debug_sem);
return PUBLIC_MODULE_PUBLIC_DEBUG;
}
return SUCCESS;
}
2.打印信息直接拷贝到内存buffer
static s32 debug_printf(const u32 level, const s8 *format, ...)
{
static s8 buffer[1024];
u32 buffer_len = 0;
va_list list;
va_start(list, format);
vsnprintf(buffer,sizeof(buffer), format, list);
va_end(list);
os_acquire_sem(g_debug_sem, OS_WAIT_TIMEOUT_MAX);
buffer_len = strlen(buffer);
if(b_is_client_inited)
{
if( (g_net_log_pos + buffer_len) < DEBUG_DATABUF_LEN )
{
memcpy(g_net_log_buf+g_net_log_pos, buffer, buffer_len);
g_net_log_pos += buffer_len;
}
else
{
DEBUG_PRINTF_MONTAGE("buffer_len:%d remain %d\n", buffer_len, DEBUG_DATABUF_LEN-g_net_log_pos);
}
}
os_release_sem(g_debug_sem);
return 0;
}
3.发送线程间隔一段时间发送一次打印buffer信息到接收端
static void *debug_net_send_thread(void * pvoid_parm)
{
s32 sock = 0;
s32 send_buf_len_total = 0;
s32 send_len = 0;
s32 actual_send_len = 0;
s32 actual_send_len_total = 0;
sock = lwip_socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
DEBUG_PRINTF_MONTAGE("create socket failed[%d]\n",sock);
return NULL;
}
while(1)
{
if ( b_is_client_inited && (g_net_log_pos > 0) )
{
os_acquire_sem(g_debug_sem,OS_WAIT_TIMEOUT_MAX);
memcpy(g_send_buf, g_net_log_buf, g_net_log_pos);
send_buf_len_total = g_net_log_pos;
g_net_log_pos = 0;
os_release_sem(g_debug_sem);
actual_send_len_total = 0;
while(send_buf_len_total > 0)
{
send_len = MIN(send_buf_len_total, DEBUG_SEND_PERTIME_MAX);
actual_send_len = lwip_sendto(sock, (const void *)g_send_buf+actual_send_len_total, send_len, 0,(const struct sockaddr *)&g_client_addr, sizeof(g_client_addr));
if (actual_send_len < send_len)
{
DEBUG_PRINTF_MONTAGE("actual_send_len:%d < send_len:%d\n", actual_send_len, send_len);
os_msleep(10);
}
if (actual_send_len > 0)
{
actual_send_len_total += actual_send_len;
send_buf_len_total -= actual_send_len;
}
}
}
os_msleep(50);
}
lwip_close(sock);
return NULL;
}
4.信息接收端运行在PC机上,使用python开发,核心代码如下:
def main():
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
port_num = 23456
udp_socket.bind(('', port_num))
time_str = time.strftime('%Y%m%
d_%H%M%S', time.localtime())
file_name = "MT2211_log_" + time_str + ".log"
f = open(file_name, 'w+')
print("ip: " + get_host_ip() + " port: " + "".join("%d" % port_num) + " log save file: " + file_name)
while True:
receive_data = udp_socket.recvfrom(65507)
data_to_bytes = ''.join("%s" % receive_data[0].decode())
print("%s" % receive_data[0].decode(), end="")
f.write(data_to_bytes)
file_size = os.path.getsize(file_name)
if file_size >= (10 * 1024 * 1024):
f.close()
time_str = time.strftime('%Y%m%d_%H%M%S', time.localtime())
file_name = "MT2211_log_" + time_str + ".log"
f = open(file_name, 'w+')
print("store log to new file: " + file_name)
f.close()
5.运行情况,信息接收端net_print打印以及每10M日志信息存储到一个新文件