APP LOG模块常见问题
1. UART打LOG最高波特率能到多少?
GR5xx系列SoC的UART最大波特率均为4M,但考虑到误码率以及串口转USB芯片的能力,非常不推荐使用4M来打LOG。另外,GR5xx Starter Kit板载的J-Link OB芯片最大支持的波特率只到460800,所以如果对波特率有更高的要求,需要用户外接性能更好的串口转USB板。
2. 使用串口打LOG在电脑上看不到输出怎么办?
可以根据以下步骤逐一进行排查:
检查串口工具的配置,包括波特率、奇偶校验、数据位、停止位、流控等配置,与代码中初始化UART时的配置保持一致。
检查_custom_config.h_的配置。
APP_LOG_ENABLE宏应当为1,APP_LOG_PORT宏应当为0。检查APP LOG模块与UART是否正确初始化。在调用
app_log_init()函数时,第二个参数trans_func应当是使用对应UART进行输出的函数。具体写法可参考SDK的实现platform\boards\board_SK.c或《GR5xx APP Log应用说明》“模块初始化与调度”章节。检查UART初始化时Pin Mux是否正确配置。具体的Pin Mux值请参考所使用SoC的Datasheet。
如果打LOG时使用了DMA方式,需要检查UART DMA的配置是否正确,以及使用的UART是否支持DMA(例如GR551x SoC的UART1是不支持DMA的)。
如果经过上述5步仍不能解决问题,则建议使用逻辑分析仪或示波器在UART TX/RX线上抓取波形,来判断GR5xx SoC是否有输出正确的UART信号。如果有,则需要进一步排查串口转USB或串口工具的问题。如果没有,则推荐先用SDK中的Example工程进行对比测试,来确认是硬件问题还是软件问题,然后针对具体问题进行分析排查。
3. 怎么用SEGGER RTT打LOG?
SDK提供的所有模板工程均支持通过SEGGER RTT打LOG。在工程对应的_custom_config.h_中找到APP_LOG_PORT宏,将值修改为1:
// <o> APP log port type
// <0=> UART
// <1=> RTT
// <2=> ITM
#ifndef APP_LOG_PORT
#define APP_LOG_PORT 1
#endif
然后重新编译下载即可。在J-Link RTT Viewer中连接设备时,Connection to J-Link一栏一般选择USB,Specify Target Device一栏填写Cortex-M4,Target Interface & Speed选择SWD和4000kHz,RTT Control Block中有两种填写方法,第一种是在编译产生的.map中寻找_SEGGER_RTT符号的地址,然后在RTT Viewer中使用Address选项填写;第二种方式是填写地址范围让RTT Viewer自动搜索,这里通常填写完整的SRAM范围即可。各SoC的地址范围请参考下表:
| SoC | Search Range |
|---|---|
| GR5515 | 0x30000000 0x3003FFFF |
| GR5513 | 0x30000000 0x3001FFFF |
| GR5525 | 0x20000000 0x2003FFFF |
| GR5526 | 0x20000000 0x2007FFFF |
| GR533x | 0x20000000 9x20017FFF |
如果是自己的工程,请参考SDK的实现进行移植,或参考《GR5xx APP Log应用说明》“模块初始化与调度”章节。
4. 为什么RTT打印日志一段时间后就不再打印了,系统也卡死了?
不再打印日志的原因是RTT方式打印日志依赖J-Link连接,当GR5xx SoC进入睡眠模式之后,J-Link连接会断开,J-Link RTT Viewer不具备自动重连功能,当系统再次唤醒时,J-Link连接已经断开了,所以表现为不再打印后续LOG。
系统卡死的原因则很有可能是RTT打印模式为阻塞模式,当传输FIFO满了之后,RTT就会阻塞等待上位机将FIFO读空。结合第1点中描述的原因,睡眠唤醒之后J-Link连接已经断开,上位机没有再继续读取FIFO,当FIFO满了之后再打LOG,阻塞等待的行为就会表现为卡死。
解决办法有2种:
关闭低功耗模式,在系统初始化时加入
pwr_mgmt_mode_set(PMR_MGMT_ACTIVE_MODE);,让SoC保持在Active状态可以避免J-Link连接断掉,同时规避“丢LOG”与“系统卡死”的问题,缺点是无法针对低功耗部分进行有效调试。将RTT输出模式更改为非阻塞模式,在初始化RTT时使用
SEGGER_RTT_ConfigUpBuffer()函数来修改输出模式。非阻塞模式分两种:SEGGER_RTT_MODE_NO_BLOCK_SKIP和SEGGER_RTT_MODE_NO_BLOCK_TRIM。当遇到FIFO剩余空间不足以放下完整的待打印日志,如果设置为SKIP,则跳过该次打印;如果设置为TRIM,则只把FIFO填满,超出的部分全部丢弃。这种方法虽然不影响低功耗,只能避免J-Link连接断开后不会阻塞卡死,并不能避免丢LOG的情况。
5. J-Link RTT Viewer连上之后看不到LOG怎么办?
可以根据以下步骤逐一进行排查:
检查_custom_config.h_的配置。
APP_LOG_ENABLE宏应当为1,APP_LOG_PORT宏应当为1。检查APP LOG模块与RTT是否正确初始化。在调用
app_log_init()函数时,第二个参数trans_func应当是使用SEGGER_RTT_Write()进行输出的函数(但不能是SEGGER_RTT_Write()本身,因为入参不一样)。具体写法可参考SDK的实现platform\boards\board_SK.c或《GR5xx APP Log应用说明》“模块初始化与调度”章节。检查RTT中的各项配置。首先检查
_SEGGER_RTT变量是否被正确放置。通常情况下不推荐将_SEGGER_RTT变量放置到固定的地址,但如果用户选择了将这个变量放到固定地址,则需要确保这个固定地址存在于SRAM地址范围以内。检查J-Link RTT Viewer连接时
RTT Control Block的地址设置是否正确。GR5xx SoC暂不支持Auto Detection模式,需要使用Address模式手动填入,或者使用Search Range模式并填入地址范围让RTT Viewer自动去搜索。具体的设置方法请参考“怎么用SEGGER RTT打LOG?”章节的回答。如果经过上述4步依然无法定位并解决问题,则需要通过单步调试跟踪来确定每一个打LOG的每一个环节是否都正确执行,入参与返回值是否符合预期等等。
6. 存储的LOG怎么导出来?
使用Android端的GRToolbox App导出,具体操作请参考《GR5xx APP Log应用说明》“获取日志”章节。
7. 使用GRToolbox导出存储LOG时,LOG不完整怎么办?
很有可能是由于用来临时存储LOG的RingBuffer溢出导致的。为了尽可能降低擦写Flash对应用时序的影响,打LOG时并不会进行真正的存储操作,而是将LOG数据放入缓存RingBuffer中,并在
app_log_store_schedule()函数中真正写入Flash。如果在app_log_store_schedule()执行之前就输出了超过RingBuffer大小的LOG,就会出现LOG不完整甚至丢LOG的情况。针对此问题有两种解决办法:增大缓存RingBuffer。根据情况修改
components\libraries\app_log\app_log_store.h中APP_LOG_STORE_LINE_SIZE与APP_LOG_STORE_CACHE_NUM的值可以增大缓存RingBuffer,但同时也会增加RAM占用。增加调用
app_log_store_schedule()的频次。例如在使用RTOS的环境下,视情况提高用于运行app_log_store_schedule()的任务的优先级可以让该任务得到更多次的调度,但更高频次地操作Flash可能会对某些时序敏感的应用造成影响。
8. 使用GRToolbox导出日志时,发现只有最近的日志,无法获取更早的日志怎么办?
LOG存储使用了环形覆盖机制,当存储空间不足时,会用新的LOG去覆盖最老的LOG。所以这个问题无法真正地解决,只能通过增大存储区和减少不必要的LOG来尽量缓解问题。