/****************************************************************************** 版权所有: 文件名称: rt_printf.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2020-06-18 功能说明: 打印输出功能。 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include #include #include #include "head.h" #include #include "rt_printf.h" #include /*------------------------------- 宏定义 -------------------------------------- */ #define PRINTF_BUF_SIZE (16 * 1024) /*------------------------------ 类型结构 ------------------------------------- */ typedef struct { unsigned short year; unsigned char month; unsigned char day; unsigned char hour; unsigned char minute; unsigned char second; unsigned char week; unsigned int us; // 微锟斤拷 } CO_TIME; static pthread_t printf_tid = 0; static int exit_flag = 0; static uint8_t p_buf[PRINTF_BUF_SIZE]; // 输出 static uint8_t p_buf_s[PRINTF_BUF_SIZE]; // 源 static char printf_buf[PRINTF_BUF_SIZE]; static uint32_t w_p = 0; // 写指针 static uint32_t r_p = 0; // 读指针 static pthread_mutex_t printf_mutex; extern int main_mod_is_exit(void); void sys_gettime_tm(CO_TIME *tm_t) { struct tm *p; struct timeval tv; gettimeofday(&tv, NULL); // p=gmtime(&tv.tv_sec); p = localtime(&tv.tv_sec); tm_t->year = 1900 + p->tm_year; // tm_year锟斤拷锟斤拷1900为锟斤拷愕斤拷锟斤拷诘锟斤拷锟斤拷锟斤拷锟? // printf("year=%d",tm_t->year); tm_t->month = p->tm_mon + 1; // tm_mon锟斤拷值锟斤拷围0-11锟斤拷 // printf("month=%d",tm_t->month); tm_t->day = p->tm_mday; // printf("day=%d",tm_t->day); tm_t->hour = p->tm_hour; // printf("hour=%d",tm_t->hour); tm_t->minute = p->tm_min; // printf("minute=%d",tm_t->minute); tm_t->second = p->tm_sec; // printf("second=%d",tm_t->second); tm_t->week = p->tm_wday; // printf("week=%d",tm_t->week); tm_t->us = tv.tv_usec; // printf("us=%d\n",tm_t->us); } void sys_gettime_CP56(CP56_TIME2A *tm_t) { CO_TIME co_tm_t; sys_gettime_tm(&co_tm_t); tm_t->time_t.year = (unsigned char)(co_tm_t.year - 2000); tm_t->time_t.month = co_tm_t.month; tm_t->time_t.day = co_tm_t.day; tm_t->time_t.week = co_tm_t.week; tm_t->time_t.hour = co_tm_t.hour; tm_t->time_t.min = co_tm_t.minute; tm_t->time_t.ms = co_tm_t.second * 1000 + co_tm_t.us / 1000; } // 把印时间,具体在那个文件和行号 void co_printf(const char *fp, const int line) { char sDebug[1024]; char *ptr = NULL; struct timespec ts; struct rtc_time_t pt; // CP56_TIME2A Clock_u; memset(sDebug, '\0', sizeof(sDebug)); // sys_gettime_CP56(&Clock_u); gps_get_time(&ts); timespec_to_rtc(ts, &pt, 1); sprintf(sDebug, "%04d-%02d-%02d %02d:%02d:%02d:%03d ", pt.year + 2000, pt.month, pt.day, pt.hour, pt.min, pt.ms / 1000, pt.ms % 1000); ptr = strrchr(fp, '/'); if (ptr) { sprintf(sDebug + strlen(sDebug), "%s[%d]:", ptr + 1, line); } else { sprintf(sDebug + strlen(sDebug), "%s[%d]:", fp, line); } rt_printf(sDebug); } // 可变参形式进行实现myprintf int myprintf(const char *fmt, ...) { char buf[1024]; va_list args; int printed; va_start(args, fmt); printed = vsprintf(buf, fmt, args); va_end(args); rt_printf(buf); return printed; } void rt_printf_time2(struct timespec ts) { struct rtc_time_t tm; timespec_to_rtc(ts, &tm, 0); rt_printf("%04d-%02d-%02d %02d:%02d:%02d:%09d!\r\n", tm.year + 2000, tm.month, tm.day, tm.hour, tm.min, tm.ms / 1000, ts.tv_nsec); return; } /****************************************************************************** 函数名称: print_mem 函数版本: 01.01 创建作者: sunxi 创建日期: 2020-06-18 函数说明: 以十六进制的方式显示内存的内容 参数说明: addr: 输出内容的起始地址 len: 输出内容的长度 返回值: 无 修改记录: */ void print_mem(char *name, void *addr, unsigned int len) { int once; int i, name_len; if (name) { rt_printf(name); name_len = strlen(name); } else { rt_printf("addr=0x%08x,len=%d\r\n", (unsigned int)addr, len); name_len = 10; } while (1) { once = len < 16 ? len : 16; if (!name) { rt_printf("%08x:", (unsigned int)addr); } for (i = 0; i < once; i++) { if (i == 8) rt_printf(" "); // 使用2个空格,不使用"-",因为规约解析工具不支持"-". rt_printf(" %02x", *(unsigned char *)addr++); } rt_printf("\r\n"); len -= once; if (len == 0) { break; } // 打印对齐空格 for (i = 0; i < name_len; i++) { rt_printf(" "); } } return; } void print_mem_time(char *name, void *addr, unsigned int len) { struct rtc_time_t tm; struct timespec ts; char buf[64]; clk_time_get(&ts); timespec_to_rtc(ts, &tm, 0); if (name) { sprintf(buf, "%s(%04d-%02d-%02d %02d:%02d:%02d:%06ld)", name, tm.year + 2000, tm.month, tm.day, tm.hour, tm.min, tm.ms / 1000, ts.tv_nsec / 1000); } else { sprintf(buf, "mem(%04d-%02d-%02d %02d:%02d:%05d)", tm.year + 2000, tm.month, tm.day, tm.hour, tm.min, tm.ms); } print_mem(buf, addr, len); } // int g_print_time = 0; void print_msg(char *name, void *addr, unsigned int len) { if (g_print_time) { print_mem_time(name, addr, len); } else { print_mem(name, addr, len); } } int rt_printf(const char *fmt, ...) { #if 0 char pbuf[1024]; va_list args; int printed; va_start(args, fmt); printed = vsprintf(pbuf, fmt, args); va_end(args); //直接打印 printf(pbuf); #else // 放入显示缓冲区 va_list args; int length, byte; va_start(args, fmt); vsnprintf(printf_buf, PRINTF_BUF_SIZE, (char *)fmt, args); va_end(args); length = strlen(printf_buf); pthread_mutex_lock(&printf_mutex); if ((w_p + length) < PRINTF_BUF_SIZE) { memcpy((uint8_t *)&p_buf_s[w_p], (uint8_t *)printf_buf, length); w_p += length; } else { byte = PRINTF_BUF_SIZE - w_p; memcpy((uint8_t *)&p_buf_s[w_p], (uint8_t *)printf_buf, byte); w_p = length - byte; memcpy((uint8_t *)p_buf_s, (uint8_t *)&printf_buf[byte], w_p); } // printf("-----test printf----wp=%d---%s",w_p, printf_buf); pthread_mutex_unlock(&printf_mutex); #endif return 0; } /****************************************************************************** 函数名称: rt_printf_func 函数版本: 01.01 创建作者: sunxi 创建日期: 2022-5-31 函数说明: 打印工作函数. 参数说明: 返回值: 返回0 修改记录: */ static int rt_printf_func(void *arg) { int len = 0; int len_1 = 0; memset(p_buf, 0, sizeof(p_buf)); memset(p_buf_s, 0, sizeof(p_buf_s)); w_p = 0; r_p = 0; pthread_mutex_init(&printf_mutex, NULL); #if 0 strcpy(&p_buf[w_p],test_1); w_p += strlen(test_1); strcpy(&p_buf[w_p],test_2); w_p += strlen(test_2); strcpy(&p_buf[w_p],test_3); w_p += strlen(test_3); rt_printf(p_buf); #endif uint32_t wdt_id; int rc = watchdog_add_item("rt_printf_func", &wdt_id, 120); if (rc != 0) { printf("can not add rt_printf_func task to wdt\r\n"); return 0; } prctl(PR_SET_NAME, "rt_printf_func"); while (!exit_flag) { msleep(10); watchdog_feed(wdt_id); if (main_mod_is_exit()) { break; } // rt_printf("w_p = %d, r_p = %d\r\n",w_p,r_p); pthread_mutex_lock(&printf_mutex); len = 0; len_1 = 0; if (w_p != r_p) { memset(p_buf, 0, sizeof(p_buf)); // 获取打印信息 if (w_p > r_p) { len = w_p - r_p; memcpy(p_buf, &p_buf_s[r_p], len); r_p += len; } else { // w_p指针翻滚,过0 // 分两段读取,再合并 len = PRINTF_BUF_SIZE - r_p; memcpy(p_buf, &p_buf_s[r_p], len); r_p += len; len_1 = w_p; memcpy(&p_buf[len], p_buf_s, len_1); r_p = len_1; } if (r_p >= PRINTF_BUF_SIZE) r_p = 0; p_buf[sizeof(p_buf) - 1] = 0; // 保证结束 } pthread_mutex_unlock(&printf_mutex); if ((len > 0) || (len_1 > 0)) { // noted by sunxi: 20221122 重定向6000端口打印 if (g_print_to_net) { net_debug_send(p_buf, sizeof(p_buf)); // return 0; } else { printf(p_buf); // printf("\r\n"); } } } watchdog_remove_item(wdt_id); return 0; } /****************************************************************************** 函数名称: rt_printf_init 函数版本: 01.01 创建作者: sunxi 创建日期: 2022-5-31 函数说明: 初始化. 参数说明: 无 返回值: 成功返回0, 失败返回-1 修改记录: */ int rt_printf_init(void) { int ret; ret = pthread_create(&printf_tid, NULL, (void *)rt_printf_func, NULL); if (ret) { printf("ret = %d, err = %s\r\n", ret, strerror(ret)); printf_tid = 0; return ret; } return 0; } /****************************************************************************** 函数名称: rt_printf_exit 函数版本: 01.01 创建作者: sunxi 创建日期: 2022-5-31 函数说明: 反初始化. 参数说明: 无 返回值: 总是返回0. 修改记录: */ int rt_printf_exit(void) { exit_flag = 1; pthread_join(printf_tid, NULL); return 0; } /*------------------------------ 测试函数 ------------------------------------- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数). */ /*------------------------------ 文件结束 ------------------------------------- */