OpenHarmony海思WS63星闪平台:EasyLogger 移植到海思 WS63 平台完整指南
文章目录前言1. WS63 平台与典型软件栈2. EasyLogger 简介2.1 项目背景与许可2.2 架构分层理解移植要改哪里3. 本仓库目录与编译单元4. WS63 移植层实现要点elog_port.c4.1 为何使用 CMSIS-RTOS24.2 printf 与 UART4.3 时间戳与内核 Tick5. 配置说明elog_cfg.h5.1 输出总开关与静态级别5.2 缓冲区5.3 缓冲模式elog_buf5.4 颜色与格式5.5 不要在本平台打开的宏6. 编译系统集成6.1 CMake本仓库已集成示例6.2 GNOpenHarmony 风格7. 初始化与运行期 API7.1 推荐启动顺序7.2 常用输出方式7.3 过滤与格式运行期8. RAM、线程与实时性建议9. 可选插件Flash / 文件后端10. 常见问题排查11. 参考与延伸总结前言在海思 WS63一类Wi-Fi / 星闪 SoC上跑应用时调试与现场排障高度依赖串口日志既要能在多线程环境下安全打印又希望尽量少占 RAM、不把 UART 写操作拖慢业务线程。EasyLogger是嵌入式领域常用的轻量级日志库通过可裁剪的配置与异步输出能较好平衡这些需求。本文面向在本仓库xiaohong WS63 SDK或同类OpenHarmony / LiteOS CMSIS-RTOS2工程中的集成者说明EasyLogger是什么、适合什么场景如何在本工程形态下完成移植与编译集成elog_cfg.h与elog_port.c在 WS63 上的注意点初始化顺序、常用 API、RAM/线程/UART 与常见问题。文中路径以本仓库为准src/easylogger/。若你使用其他目录请自行替换。1. WS63 平台与典型软件栈WS63为海思面向 IoT 连接场景的芯片平台常见配套包括实时内核LiteOS-M / 兼容层RTOS API多通过CMSIS-RTOS2cmsis_os2.h封装信号量、线程等日志出口调试阶段多为UART printf重定向或 SDK 提供的打印接口。本仓库的BUILD.gn通过ws63_sdk.gni引入 SDK 头文件与驱动板级示例为xiaohong_ws63_v1宏BOARD_XH_WS63_V1。EasyLogger 的移植层必须与当前工程实际使用的 RTOS API 一致——本工程采用的是CMSIS-RTOS2而不是 POSIXpthread。2. EasyLogger 简介2.1 项目背景与许可EasyLogger简称elog由Armink维护源码采用MIT许可仓库与文档可在 GitHub / Gitee 检索EasyLogger获取原版说明。其核心目标是在资源受限 MCU上提供分级日志Assert / Error / Warn / Info / Debug / Verbose按标签tag、关键字、级别过滤可选颜色ANSI 转义序列终端支持时便于区分级别可选异步输出业务线程只写缓冲专用线程或回调做 UART 输出可选缓冲输出合并多次写入减少碎片输出。本仓库内置版本在elog.h中标记为ELOG_SW_VERSION 2.2.99与上游版本号可能随合并略有差异以头文件为准。github地址https://github.com/armink/EasyLogger2.2 架构分层理解移植要改哪里层次作用WS63 上谁实现核心elog.c格式化、过滤、调用输出链路一般不改工具elog_utils.c字符串与内存辅助一般不改异步elog_async.c环形缓冲、异步策略一般不改通过宏选 pthread 或自定义 notice缓冲elog_buf.c缓冲刷新策略一般不改移植层elog_port.c锁、输出、时间、线程名、异步线程必须按平台实现所有与板级相关的行为都集中在elog_port.c以及可选插件的*_port.c。3. 本仓库目录与编译单元建议保持如下布局与当前工程一致src/easylogger/ ├── inc/ │ ├── elog.h # 对外 API 与 log_x 宏 │ └── elog_cfg.h # 功能开关与缓冲区尺寸移植时最常改 ├── port/ │ └── elog_port.c # WS63 / CMSIS-RTOS2 移植实现 ├── src/ │ ├── elog.c │ ├── elog_utils.c │ ├── elog_async.c │ └── elog_buf.c └── plugins/ # 可选Flash / 文件后端默认未编入本工程 CMake ├── flash/ └── file/建议编入的 C 文件与CMakeLists.txt中一致elog_port.celog.celog_utils.celog_buf.celog_async.c头文件搜索路径需包含src/easylogger/inc。说明当前仓库的BUILD.gn静态库xiaohong未列出上述 EasyLogger 源文件若你仅在GN 构建下编译需要在sources中自行追加同等列表并保证能包含cmsis_os2.h与stdio.hprintf。4. WS63 移植层实现要点elog_port.c本工程elog_port.c已实现下列移植接口函数名由 EasyLogger 约定不可随意改名接口职责本工程实现摘要elog_port_init初始化锁、异步所需信号量与线程osSemaphoreNew异步模式下osThreadNew(async_output, …)elog_port_deinit释放信号量释放output_lock/output_notice未终止异步线程若需完整 deinit 可自行扩展elog_port_output将已格式化的日志写出printf(%.*s, (int)size, log)elog_port_output_lock/unlock多线程互斥二值信号量osSemaphoreAcquire/Releaseelog_port_get_time时间戳字符串osKernelGetTickCount()换算为秒.毫秒形式elog_port_get_p_info进程信息固定返回appelog_port_get_t_info线程信息osThreadGetName或回退tidelog_async_output_notice通知异步输出线程取日志osSemaphoreRelease(output_notice)仅ELOG_ASYNC_OUTPUT_ENABLE时4.1 为何使用 CMSIS-RTOS2WS63 SDK 工程通常已链接CMSIS-RTOS2适配层与LiteOS线程模型一致。EasyLogger 官方示例里异步模式常见POSIX pthreadELOG_ASYNC_OUTPUT_USING_PTHREAD在 WS63 上不要打开该宏而应像本工程一样在elog_port.c内实现elog_async_output_notice使用osThreadNew跑async_output循环从elog_async_get_line_log/elog_async_get_log取数据再printf。这样避免引入pthread、semaphore.h等与当前 SDK 不完全一致的依赖。4.2printf与 UARTelog_port_output使用printf。请确保在 WS63 工程中printf已重定向到所用调试 UART例如通过 SDK 的console或uart适配。若printf未初始化或阻塞时间过长会表现为日志卡顿或早期启动无输出。4.3 时间戳与内核 Tickelog_port_get_time中当前实现假设Tick 周期为 1 msticks/1000为秒。若你的osKernelGetTickFreq()与 1000 Hz 不一致应改为按实际 Tick 频率换算否则时间戳会偏差。5. 配置说明elog_cfg.h以下为本仓库当前配置的语义说明具体数值以文件为准移植时可按 RAM 预算调整。5.1 输出总开关与静态级别ELOG_OUTPUT_ENABLE关闭后所有elog_*/log_*宏为空操作。ELOG_OUTPUT_LVL编译期静态裁剪高于该级别的宏不生成代码例如设为ELOG_LVL_INFO则 Debug/Verbose 宏为空。5.2 缓冲区ELOG_LINE_BUF_SIZE单行上限含前缀本工程可设为128省 RAM超长截断。开目录/颜色时前缀易占满可关ELOG_COLOR_ENABLE、ELOG_FMT_USING_DIR或加大本值。ELOG_ASYNC_OUTPUT_ENABLE启用异步环形缓冲与后台输出。ELOG_ASYNC_OUTPUT_BUF_SIZE异步环缓大小本工程由ELOG_ASYNC_RING_LINE_SLOTS默认3×ELOG_LINE_BUF_SIZE得出RAM 极紧时槽位过小会在日志突发时更易丢尾。ELOG_ASYNC_LINE_OUTPUT按行从环缓取出便于一行一行printf。ELOG_ASYNC_OUTPUT_LVL与elog_async.c中level OUTPUT_LVL走异步的逻辑配合使用级别数值越小表示越“严重”Assert 为 0Verbose 为 5。设为ELOG_LVL_ASSERT时所有级别均满足 0一般会全部走异步若希望低级别同步、高级别异步可改为例如ELOG_LVL_INFO需对照业务理解同步/异步划分。5.3 缓冲模式elog_bufELOG_BUF_OUTPUT_ENABLE与ELOG_BUF_OUTPUT_BUF_SIZE在异步之外再叠一层缓冲减少零碎写RAM 紧张时可评估是否关闭。5.4 颜色与格式ELOG_COLOR_ENABLEANSI 颜色部分串口终端支持纯 UART 工具可能显示转义字符可按需关闭。ELOG_FMT_USING_DIR/FUNC/LINE控制是否输出文件名、函数名、行号会增大日志体积与格式化开销。5.5 不要在本平台打开的宏ELOG_ASYNC_OUTPUT_USING_PTHREAD应保持注释WS63 本工程使用CMSIS 线程 elog_async_output_notice方案。6. 编译系统集成6.1 CMake本仓库已集成示例在父级CMakeLists.txt中已包含类似片段路径按仓库实际为准PRIVATE_SOURCES增加elog_port.c、elog.c、elog_utils.c、elog_buf.c、elog_async.cinclude增加src/easylogger/inc。6.2 GNOpenHarmony 风格若目标产物通过BUILD.gn构建在static_library(xiaohong)或你的模块名的sources中加入与 CMake 相同的 5 个.c文件在include_dirs中加入src/easylogger/inc或//vendor/.../xiaohong/src/easylogger/inc等 GN 绝对路径写法确认cmsis_os2.h所在路径已被该模块引用本仓库BUILD.gn已包含kernel/osal等目录时可与现有模块对齐。7. 初始化与运行期 API7.1 推荐启动顺序在内核与线程环境已就绪、UART/printf 可用之后调用#includeelog.hvoidapp_log_init(void){if(elog_init()!ELOG_NO_ERR){/* 处理错误信号量/线程创建失败等 */return;}elog_start();/* 打开输出启用 async/buf 等 */}elog_init()内部调用elog_port_init()、elog_async_init()并设置默认过滤与格式。elog_start()使能输出及异步/缓冲模块与elog_cfg.h宏相关。结束或重启前可调用elog_stop()、elog_deinit()注意异步线程与资源释放策略见下文「常见问题」。7.2 常用输出方式方式 A带 tag 的宏推荐#defineLOG_TAGwifi#defineLOG_LVLELOG_LVL_INFO#includeelog.hvoidfoo(void){log_i(connected, rssi%d,rssi);log_e(assoc failed, code%u,code);}方式 B显式 tagelog_i(net,ipIPSTR,IP2STR(ip));原始输出不经完整格式前缀时可用elog_raw_output(boot stage %d\r\n,stage);十六进制 dumpelog_hexdump(buf,16,data,len);7.3 过滤与格式运行期elog_set_filter_lvl(ELOG_LVL_WARN);/* 全局级别 */elog_set_filter_tag(noisy_mod);/* 只输出某 tag */elog_set_filter_tag_lvl(spi,ELOG_LVL_INFO);/* 按 tag 设级别 */elog_set_fmt(ELOG_LVL_INFO,ELOG_FMT_LVL|ELOG_FMT_TAG|ELOG_FMT_TIME);8. RAM、线程与实时性建议项目说明异步线程栈ELOG_PORT_ASYNC_STACK_SIZE默认768poll_get_buf为 static。栈不够再加大。环缓大小ELOG_ASYNC_OUTPUT_BUF_SIZE过小易丢日志或阻塞格式化路径过大占 RAMWS63 小 RAM 场景建议实测峰值打印速率。锁与优先级输出互斥使用信号量异步线程优先级为osPriorityBelowNormal避免抢占关键实时任务但若日志洪峰仍可能占用 CPU需配合ELOG_OUTPUT_LVL与过滤。启动早期在osKernel未就绪时调用osKernelGetTickCount/ 创建线程可能失败应将elog_init放在RTOS 已启动之后的应用入口。9. 可选插件Flash / 文件后端仓库plugins/flash、plugins/file提供将日志写入 Flash 或文件系统的扩展需额外编译对应elog_flash.c/elog_file.c及各自*_port.c在elog_flash_cfg.h/elog_file_cfg.h中配置分区或路径在业务中调用插件初始化与 flush 策略。默认 CMake 列出的 5 个文件不包含插件若 WS63 上已使用 LittleFS可在此基础上评估文件日志是否与现有 FS 线程安全策略一致。10. 常见问题排查编译找不到cmsis_os2.h检查 GN/CMake 的include_dirs是否包含 OSAL / CMSIS-RTOS2 头路径。无串口输出确认printf重定向、UART 初始化顺序早于elog_start以及线波特率与 PC 终端一致。异步模式无输出确认elog_port_init中osThreadNew成功且elog_async_output_notice在elog_async.c中被调用ELOG_ASYNC_OUTPUT_ENABLE打开。颜色乱码关闭ELOG_COLOR_ENABLE或换支持 ANSI 的终端。时间戳不准按osKernelGetTickFreq()修正elog_port_get_time的换算。elog_port_deinit与异步线程已在elog_port_deinit中osThreadTerminate(async_thread_id)后再删除信号量elog_deinit时请先elog_stop避免业务线程与析构竞态。11. 参考与延伸上游EasyLogger官方文档与示例检索armink EasyLogger。本仓库RTOS 相关BUILD.gn中ws63_sdk_path、kernel/osal等 include便于对齐与你 SDK 版本一致的头文件。同仓库内另一套日志方案src/ulog/及《ulog 日志库移植到海思 WS63 平台》类文档可按项目规范二选一或分层使用避免混用两套宏导致风格分裂。总结EasyLogger 在 WS63 上的移植核心是用 CMSIS-RTOS2 实现elog_port.c的锁、时间与异步通知线程保证与 LiteOS 线程模型一致通过elog_cfg.h在 RAM 与实时性之间做裁剪依赖已就绪的printf/UART 作为最终输出。本仓库已提供可直接参考的elog_port.c与 CMake 集成列表若使用GN 构建只需将相同源文件与头路径补进模块即可。按本文完成集成后建议在多线程压力场景下做一次日志洪峰测试根据是否丢日志、栈是否溢出微调ELOG_ASYNC_OUTPUT_BUF_SIZE、异步栈大小与输出级别使 WS63 小内存环境下的日志既可用又可控。