The latest development version of this page may be more current than this released 0.4.3 version.

Debugging Methods

This document guides you through the debugging methods for w800 :

  1. Adding Debug Information

  2. Using Debugger for Online Debugging

  3. Analyzing Post-Mortem Information

Adding Debug Information

Using wm_log_xx to Print Log Information:

The wm_log_xx function is declared in the wm_log.h header file and provides 5 log levels for users to choose from based on their needs: error , warn, info, debug, verbose, . It also offers assertion interfaces, hexadecimal dump interfaces, and raw information output interfaces. Different levels of information can be marked and displayed in different colors (provided the serial port tool supports color functionality).

The usage of wm_log_xx is similar to the C library function printf ‘s features and also has special features like %M for directly printing MAC addresses, %V for directly printing IPv4 addresses, and %V for directly printing IPv6 addresses. When using the wm_log_xx series of interfaces, except for the raw information output interface, a newline character is automatically added at the end, reducing the developer’s workload.

When using this, you can configure it via menuconfig by navigating to Components configuration —> log —> default log level to select the log level. It can also be dynamically controlled through the API within the program.

In the CLI, when viewing log information, you can also set the display level using commands, such as setting debug level information:

log debug

Additionally, for users needing asynchronous printing, wm_log also supports task-based printing. You need to enable log task printing through menuconfig and then adjust the appropriate log task priority and log buffer queue size. However, note that a log task priority that is too high may lose its asynchronous nature, and a log buffer queue that is too small may result in the loss of some log information.

By default, log information is output using uart0. If users wish to select a different output, for example, setting the output port to uart1, the operation is as follows:

Using the Debugger for Online Debugging

Online debugging requires the use of a cklink debugger. Download and install the debug server software. For detailed usage of cklink and the debug server, please refer to the T-Head Debugger Server User Guide.

The w800 uses the cklink debugger with the following connections:

w800

cklink

Description

PIN_NUM_1(PA1)s

TCK

Must be connected

PIN_NUM_4(PA4)

TMS

Must be connected

GND

GND

Must be connected

RST(Reset pin)

TRST

Optional (Recommended for stable hardware reset)

3V3

3V3

Optional

GDB is already included in the build toolchain and does not need to be installed separately.

GDB Command Line:

After connecting the w800 to the cklink debugger, start by running the debug server.Then,

use the following command in the compile command line:

wm.py gdb

This will start GDB and enter debugging mode. For more GDB operations, please refer to T-HEAD CPU Debugging Tips.

Additionally, the WM IoT SDK provides 4 debugging commands, each serving a specific purpose:

  • wmbt : View the status of all tasks in FreeRTOS.

  • wmst : Switch the CPU context to the call stack of the task displayed by wmbt based on the task index.

  • wmbk : Restore the CPU context to the task call stack at the first entry to the debugger.

  • wmheap : View the current heap memory allocation status.

IDE Debugging:

Analyzing the Site After an Exception

The WM IoT SDK provides a method to analyze the site after an exception without requiring a debugger.

Viewing the Cause and Current Address of the Crash (Following the Exception Prompt):

When a crash or exception occurs, w800 will print the error information, current address, and exception name.

For example, in the case of a divide-by-zero exception, w800 will print the following exception information:

CPU Exception : 3
Exception name: Divide by zero

r0 : 0x00000000 r1 : 0x0000000a r2 : 0x0000000a r3 : 0x00000000
r4 : 0x04040404 r5 : 0x05050505 r6 : 0x06060606 r7 : 0x07070707
r8 : 0x20006000 r9 : 0x09090909 r10: 0x10101010 r11: 0x11111111
r12: 0x12121212 r13: 0x13131313 r14: 0x20005ffc r15: 0x0800cc0e

psr: 0x80000340
pc : 0x0800cc12

Show pc info by run: csky-elfabiv2-addr2line -p -f -e ./build/hello_world.elf -a 0x0800cc12
0x0800cc0e

Next, simply run the suggested command in the compile command line:

csky-elfabiv2-addr2line -p -f -e ./build/hello_world.elf -a 0x0800cc12
0x0800cc0e

This will show the location of the error:

0x0800cc12: test_task at winnermicro-iot-os/examples/hello_world/main/src/main.c:9
0x0800cc0e: test_task at winnermicro-iot-os/examples/hello_world/main/src/main.c:9

This method can be used for simple problems. For more complex issues, it is recommended to use the following method.

ramdump Analysis:

ramdump analysis mainly includes two steps:

  1. Use wm.py ramdump –p port to export the site

When an error or exception occurs, do not reset the system. Enter the following command in the compile command line:

wm.py ramdump -p port

Where port is the port number. If there is only one serial port, this parameter can be omitted. Once completed, you can use the following command.。

  1. Use wm.py debug to analyze the exported RAM dump

After exporting the ramdump, enter wm.py debug to enter debug mode. The debugging method from this point on is exactly the same as GDB command line online debugging and will not be reintroduced here.

For example, in the case of a repeated memory free, w800 will immediately print the following exception information:

CPU Exception : 16
Exception name: Trap instruction

r0 : 0x0000004d r1 : 0x0000000a r2 : 0x0000000a r3 : 0x0000004d
r4 : 0x20005fc0 r5 : 0x05050505 r6 : 0x06060606 r7 : 0x07070707
r8 : 0x20005fd0 r9 : 0x09090909 r10: 0x10101010 r11: 0x11111111
r12: 0x0800b9bc r13: 0x20005f9c r14: 0x20005fbc r15: 0x0801a7d4

psr: 0x80000340
pc : 0x0801a7d4

Show pc info by run: csky-elfabiv2-addr2line -p -f -e ./build/hello_world.elf -a 0x0801a7d4 0x0801a7d4

At this point, we use wm.py ramdump -p port to export the exception site, then use wwm.py debug to enter gdb debugging, and use the bt command. You will see the following information:

(cskygdb) bt
#0  0x0801a7d4 in heap_free (pv=0x200060b0) at winnermicro-iot-os/components/heap/src/wm_heap.c:245
#1  0x0801ab74 in wm_heap_caps_free (p=0x200060b0) at winnermicro-iot-os/components/heap/src/wm_heap.c:513
#2  0x08018456 in free (ptr=0x200060b0) at winnermicro-iot-os/components/wm_hal/src/wm_hal_mem.c:43
#3  0x0800cc32 in test_task (parameters=0x0) at winnermicro-iot-os/examples/hello_world/main/src/main.c:11
#4  0xfffffffe in ?? ()

It is clear that in the test_task function in main.c , an exception was triggered by calling the free function at line 11.

Hint

  • The current ramdump analysis function does not support viewing data in peripheral registers.

  • The current ramdump analysis function only supports direct use on Windows and Linux systems. To use it on macOS, you need to build gdbstub_ck804 <https://github.com/wdyichen/mini-gdbstub-ck804>`_yourself, then rename it to ``mac_gdb.stub` and place it in the tools/wm path.