Logging Library

Overview

Ameba SDK provides a unified tag-based logging system available across ROM, bootloader, and application firmware stages. Log output is controlled at two independent layers:

  • Compile-time filtering via COMPIL_LOG_LEVEL: log calls that exceed this level are removed entirely by the preprocessor, producing zero code or data overhead.

  • Runtime filtering via rtk_log_level_set(): controls which compiled-in logs are actually printed, without affecting binary size.

Log Levels

Log levels are defined by the enumeration rtk_log_level_t:

typedef enum {
    RTK_LOG_NONE,    /* 0 */
    RTK_LOG_ALWAYS,  /* 1 */
    RTK_LOG_ERROR,   /* 2 */
    RTK_LOG_WARN,    /* 3 */
    RTK_LOG_INFO,    /* 4 */
    RTK_LOG_DEBUG    /* 5 */
} rtk_log_level_t;

Level

Value

Letter

Description

RTK_LOG_NONE

0

Disable all output.

RTK_LOG_ALWAYS

1

A

Critical information that must always be shown, but does not indicate a warning or error.

RTK_LOG_ERROR

2

E

Error messages, such as incorrect API usage.

RTK_LOG_WARN

3

W

Inappropriate configuration that still works, or situations that may lead to errors.

RTK_LOG_INFO

4

I

Normal and necessary operational messages (default level).

RTK_LOG_DEBUG

5

D

Diagnostic information for faults, such as pointer values and memory contents.

To change the compile-time or runtime log level, see the Log Level Configuration section.

Log Format

Output format

The output format depends on the tag argument passed to the macro.

  • With tag prefix (normal call):

    [TAG-X] message content
    
  • Without tag prefix (passing NOTAG):

    message content
    

where X is the level letter (A, E, W, I, or D). No newline is appended automatically; a trailing \n must be included in every format string. NOTAG is intended for cases where a repeated prefix is not needed, such as continuation lines inside a loop.

Tag naming rules

Each module identifies itself with a tag string. The rules are:

  • Define the tag as a const char * pointer, typically at file scope.

  • All files within the same component, or a single file acting as its own module, share one tag as a unique identifier.

  • The tag string must be all uppercase, at most 9 characters, and contain only digits, letters, or underscores. Hyphens are not allowed.

  • The tag variable should be named with a TAG_ prefix (e.g. TAG_WIFI).

static const char *TAG_APP = "APP";

Logging macros

Ameba SDK provides two macro families to suit different use cases.

1. Standard macros (RTK_LOGx)

These macros use the DiagPrintf backend and support all format specifiers except floating-point. The log level is encoded in the macro name, making them suitable for general task contexts:

RTK_LOGA(tag, format, ...)   /* RTK_LOG_ALWAYS */
RTK_LOGE(tag, format, ...)   /* RTK_LOG_ERROR  */
RTK_LOGW(tag, format, ...)   /* RTK_LOG_WARN   */
RTK_LOGI(tag, format, ...)   /* RTK_LOG_INFO   */
RTK_LOGD(tag, format, ...)   /* RTK_LOG_DEBUG  */
  • tag: module tag string, or NOTAG to suppress the prefix.

  • format: a printf-style format string.

2. Lightweight macro (RTK_LOGS)

RTK_LOGS uses the DiagPrintfNano backend. It has a smaller stack footprint and limited format specifier support, making it suitable for interrupt handlers (ISR) or stack-constrained tasks:

RTK_LOGS(tag, level, format, ...)
  • tag: module tag string, or NOTAG to suppress the prefix.

  • level: one of the rtk_log_level_t values.

  • format: a printf-style format string.

Usage example

#include "log.h"

static const char *TAG_APP = "APP";

void app_init(void)
{
    int err = 1;

    /* Recommended: nano backend, lower stack usage */
    RTK_LOGS(TAG_APP, RTK_LOG_INFO,  "version %d\n", 1);
    RTK_LOGS(TAG_APP, RTK_LOG_ERROR, "open failed, ret=%d\n", err);

    /* Print a header line, then loop items without repeating the prefix */
    RTK_LOGI(TAG_APP, "command list start\n");
    for (int i = 0; i < count; i++) {
        RTK_LOGI(NOTAG, "  [%d] %s\n", i, cmd_table[i].name);
    }
    RTK_LOGI(TAG_APP, "command list end\n");
}

Expected output:

[APP-I] version 1
[APP-E] open failed, ret=1
[APP-I] command list start
  [0] help
  [1] reset
[APP-I] command list end

Log Level Configuration

Compile-Time Log Level Setting

The macro COMPIL_LOG_LEVEL is a global definition that determines which log levels are compiled into the image. Any call whose level exceeds COMPIL_LOG_LEVEL is eliminated at the preprocessing stage and occupies no flash or RAM.

Default log level is RTK_LOG_INFO (DEBUG stripped by default, set in log.h).

To change the compile level for a single file or an entire component, see the override methods below.

Per-file override

Define COMPIL_LOG_LEVEL before including the header. This overrides the default for that translation unit only:

#define COMPIL_LOG_LEVEL  RTK_LOG_ERROR
#include "log.h"

static const char *TAG_FOO = "FOO";

/* Only ALWAYS and ERROR calls survive compilation in this file. */
RTK_LOGE(TAG_FOO, "error code: %d\n", err);
RTK_LOGD(TAG_FOO, "debug value: %08x\n", val);  /* compiled out */

Per-component override

To change the compile level for all files in a component, append the definition to private_definitions in the component’s CMakeLists.txt:

ameba_list_append(private_definitions COMPIL_LOG_LEVEL=RTK_LOG_DEBUG)

This is equivalent to passing -DCOMPIL_LOG_LEVEL=RTK_LOG_DEBUG to the compiler for every source file in that component.

Note

COMPIL_LOG_LEVEL is the compile-time ceiling. A log call that was not compiled into the image cannot be enabled at runtime, regardless of the level set by rtk_log_level_set(). The runtime level can only suppress output further — it cannot recover logs that were removed at compile time.

Runtime Log Level Setting

At runtime the log level can be adjusted per-tag or globally without affecting binary size.

rtk_log_level_set

Items

Description

Introduction

Set the log output level for a specific module tag, or set the global default level.

Parameter

  • tag: module tag string, or "*" to update the global default level (rtk_log_default_level).

  • level: desired log level (RTK_LOG_NONERTK_LOG_DEBUG).

Return

RTK_SUCCESS (0) on success; RTK_FAIL (-1) if tag is NULL or level is out of range.

rtk_log_level_get

Items

Description

Introduction

Query the effective log level for a module tag.

Parameter

  • tag: module tag string to look up.

Return

The level registered for the tag if found in the cache; otherwise the global default level (rtk_log_default_level).

rtk_log_array_clear

Items

Description

Introduction

Clear all per-tag level entries from the cache and reset the entry counter to zero.

Parameter

None

Return

None

rtk_log_array_print

Items

Description

Introduction

Print all tag/level entries currently stored in the cache.

Parameter

  • rtk_log_tag_array: pointer to the global cache array (pass rtk_log_tag_array directly).

Return

RTK_SUCCESS (0) on success; RTK_FAIL (-1) if the pointer is NULL.

Global level and per-module level

The runtime log level operates on two independent dimensions:

  • Global default level (rtk_log_default_level): set via rtk_log_level_set("*", level); applies to all modules that do not have an individually registered entry in the tag cache.

  • Per-module level: set via rtk_log_level_set(tag, level) for a specific tag and stored in the tag cache. When a tag has a cached entry, that value is returned directly by rtk_log_level_get and the global default level has no effect on it.

The two dimensions are fully independent. Updating the global default level does not affect tags that have a cached per-module entry; updating a per-module level does not affect the global default or any other module.

Tag Cache Management

The tag cache holds at most LOG_TAG_CACHE_ARRAY_SIZE (4) entries for per-module level storage. When the cache is full and a new tag is written, the slot at index count % 4 is overwritten following a ring policy. The wildcard "*" does not consume a cache slot; it only updates the global default level variable.

Usage example

/* Suppress DEBUG globally */
rtk_log_level_set("*", RTK_LOG_INFO);

/* Enable DEBUG for the WiFi module only */
rtk_log_level_set("WIFI", RTK_LOG_DEBUG);

/* Query effective level */
rtk_log_level_t lvl = rtk_log_level_get("WIFI");  /* RTK_LOG_DEBUG */

/* Inspect the cache */
rtk_log_array_print(rtk_log_tag_array);

/* Clear all per-tag settings */
rtk_log_array_clear();

AT command

The runtime log level can also be controlled over AT commands. See AT+LOG for the full AT+LOG command reference.

Performance Overhead

The two macro families differ in stack usage and format specifier support:

  • RTK_LOGS call chain: RTK_LOGS -> rtk_log_write_nano() -> DiagPrintfNano / DiagVprintfNano. Typical stack usage is ~136 B; limited format specifier support.

  • RTK_LOGx call chain: RTK_LOGx -> rtk_log_write() -> DiagPrintf / DiagVprintf. Typical stack usage is ~252 B; supports format specifiers except floating-point.

Macro

Backend function

Stack (typical)

Format support

RTK_LOGS

DiagVprintfNano

~136 B

Limited specifiers

RTK_LOGx

DiagVprintf

~252 B

Except floating-point

Selection guidance:

  • Use RTK_LOGS in interrupt handlers or stack-constrained tasks.

  • Use RTK_LOGx when long integer format specifiers such as %lld or %lu are needed.

  • Floating-point specifiers (%f, %g, etc.) are not supported by either macro family.

Memory Dump

Three helper functions produce hex dumps of a memory region to log output.

rtk_log_memory_dump_word

Items

Description

Introduction

Dump a memory region as 32-bit words, 8 words per line.

Parameter

  • src: start address of the memory region.

  • len: number of 32-bit words to dump.

Return

None

Example output:

[200447b4] 20015e08 00000000 20000674 000055d9 0c002763 20000749 0c0067f4 00000000

rtk_log_memory_dump_byte

Items

Description

Introduction

Dump a memory region as bytes, 8 bytes per line.

Parameter

  • src: start address of the memory region.

  • len: number of bytes to dump.

Return

None

Example output:

[200447b4] 08 5e 01 20 00 00 00 00

rtk_log_memory_dump2char

Items

Description

Introduction

Dump a memory region in combined hex and printable-ASCII format, 16 bytes per line.

Parameter

  • src_buff: start address of the memory region.

  • buff_len: number of bytes to dump.

Return

None

Example output:

[0xe005263]   7c 03 f0 7f 03 23 74 cf  e7 07 25 cd e7 a1 69 30  ||....#t...%...i0|

API Reference

Include log.h before using any of the following APIs.

API / Macro

Description

RTK_LOGS(tag, level, fmt, ...)

Log with nano backend (recommended)

RTK_LOGA(tag, fmt, ...)

Log at ALWAYS level

RTK_LOGE(tag, fmt, ...)

Log at ERROR level

RTK_LOGW(tag, fmt, ...)

Log at WARN level

RTK_LOGI(tag, fmt, ...)

Log at INFO level

RTK_LOGD(tag, fmt, ...)

Log at DEBUG level

rtk_log_level_set(tag, level)

Set runtime level for a tag or global default

rtk_log_level_get(tag)

Get runtime level for a tag

rtk_log_array_clear()

Clear tag level cache

rtk_log_array_print(rtk_log_tag_array)

Print tag level cache

rtk_log_memory_dump_word(src, len)

Hex dump: 32-bit words

rtk_log_memory_dump_byte(src, len)

Hex dump: bytes

rtk_log_memory_dump2char(src_buff, buff_len)

Hex dump: bytes + ASCII

rtk_log_mutex_init()

Init log mutex (RTL8730E only)