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|

Raw API

Exported Types

enum rtk_log_level_t

Log output level definition, in ascending verbosity order.

Values:

/* Logging completely disabled */
RTK_LOG_NONE

/* Always printed; not classified as warning or error */
RTK_LOG_ALWAYS

/* Error conditions */
RTK_LOG_ERROR

/* Warning conditions */
RTK_LOG_WARN

/* Informational messages (default level) */
RTK_LOG_INFO

/* Debug-level messages */
RTK_LOG_DEBUG
typedef struct rtk_log_tag_t *rtk_log_tag_p
struct rtk_log_tag_t

Per-tag runtime log level cache entry.

Public Members

rtk_log_level_t level

Cached log level for this tag

char tag[LOG_TAG_MAX_LEN + 1]

NUL-terminated tag string (max LOG_TAG_MAX_LEN chars)

Exported Constants

/* Maximum number of entries held in the runtime tag-level cache. */
#define LOG_TAG_CACHE_ARRAY_SIZE 4

/* Maximum tag string length, excluding the NUL terminator. */
#define LOG_TAG_MAX_LEN 9

Compile-time Options

/* Default log level used when COMPIL_LOG_LEVEL is not overridden. Resolves to RTK_LOG_INFO. */
#define RTK_LOG_DEFAULT_LEVEL RTK_LOG_INFO

/* Compile-time log level gate. */
#define COMPIL_LOG_LEVEL RTK_LOG_DEFAULT_LEVEL

Logging Macros

/* Special tag token for log messages that carry no module label. */
#define NOTAG "#"

/* Number of 32-bit words printed per row by rtk_log_memory_dump_word(). */
#define DISPLAY_NUMBER 8

/* Number of bytes printed per row by rtk_log_memory_dump_byte(). */
#define BYTES_PER_LINE 16

/* Core log dispatch macro; compile-time gated by COMPIL_LOG_LEVEL. */
#define RTK_LOG_ITEM do {               \
        if ( COMPIL_LOG_LEVEL >= level ) rtk_log_write(level, tag, letter, format, ##__VA_ARGS__); \
    } while(0)

/* Log at ALWAYS level (bypasses runtime tag filter). */
#define RTK_LOGA RTK_LOG_ITEM(RTK_LOG_ALWAYS,  tag, format, 'A', ##__VA_ARGS__)

/* Log at ERROR level. */
#define RTK_LOGE RTK_LOG_ITEM(RTK_LOG_ERROR,   tag, format, 'E', ##__VA_ARGS__)

/* Log at WARN level. */
#define RTK_LOGW RTK_LOG_ITEM(RTK_LOG_WARN,    tag, format, 'W', ##__VA_ARGS__)

/* Log at INFO level. */
#define RTK_LOGI RTK_LOG_ITEM(RTK_LOG_INFO,    tag, format, 'I', ##__VA_ARGS__)

/* Log at DEBUG level. */
#define RTK_LOGD RTK_LOG_ITEM(RTK_LOG_DEBUG,   tag, format, 'D', ##__VA_ARGS__)

/* Recommended log macro — emit a formatted message at the specified level. */
#define RTK_LOGS RTK_LOG_ITEMS_LEVEL(level, tag,  format, ##__VA_ARGS__)

Exported Functions

Level Control

void rtk_log_array_clear(void)

Clear all entries in the per-tag runtime level cache. After this call rtk_log_level_get() returns RTK_LOG_DEFAULT_LEVEL for every tag until new entries are written via rtk_log_level_set().

int rtk_log_array_print(rtk_log_tag_t *rtk_log_tag_array)

Print all entries in a tag-level cache array.

Parameters:
  • rtk_log_tag_array – Pointer to the cache array to print.

Returns:

Status code:

  • 0: Success (RTK_SUCCESS).

  • -1: rtk_log_tag_array is NULL (RTK_FAIL).

rtk_log_level_t rtk_log_level_get(const char *tag)

Query the effective log level for a tag. Searches the runtime cache for tag. Returns the cached level when found, or RTK_LOG_DEFAULT_LEVEL if the tag has no cache entry.

Parameters:
  • tag – NUL-terminated module tag string.

Returns:

Effective rtk_log_level_t for tag.

int rtk_log_level_set(const char *tag, rtk_log_level_t level)

Set the runtime log level for a tag. Writes or updates a tag entry in the runtime level cache. When the cache is full and the tag is new, the oldest entry is evicted.

Parameters:
  • tag – NUL-terminated module tag string to configure.

  • level – New log level (rtk_log_level_t).

Returns:

Status code:

  • 0: Success.

  • -1: Invalid argument; tag is NULL or level exceeds RTK_LOG_DEBUG.

Memory Dump

void rtk_log_memory_dump2char(const char *src_buff, uint32_t buff_len)

Dump a memory region as bytes to the log output. Prints buff_len bytes starting at src_buff in a formatted hex + ASCII table, BYTES_PER_LINE bytes per row, with address offsets.

Parameters:
  • src_buff – Pointer to the source buffer.

  • buff_len – Number of bytes to dump.

void rtk_log_memory_dump_byte(uint8_t *src, uint32_t len)

Dump a memory region as bytes to the log output. Prints len bytes starting at src in a formatted hex + ASCII table, BYTES_PER_LINE bytes per row, with address offsets.

Parameters:
  • src – Pointer to the start of the memory region.

  • len – Number of bytes to dump.

void rtk_log_memory_dump_word(uint32_t *src, uint32_t len)

Dump a memory region as 32-bit words to the log output. Prints len words starting at src in a formatted hexadecimal table, DISPLAY_NUMBER words per row, with address offsets.

Parameters:
  • src – Pointer to the start of the memory region (must be 4-byte aligned).

  • len – Number of 32-bit words to dump.

Write

void rtk_log_write(rtk_log_level_t level, const char *tag, const char letter, const char *fmt, ...)

Low-level formatted log write (standard path). Formats and outputs a log line prefixed with the level letter and tag. Called internally by RTK_LOG_ITEM(); use RTK_LOGS() or RTK_LOGx() macros in application code.

Parameters:
  • level – Log level (rtk_log_level_t).

  • tag – Module tag string.

  • letter – Single-character level indicator (A/E/W/I/D).

  • fmt – printf-style format string.

  • ... – Additional arguments for fmt.

void rtk_log_write_nano(rtk_log_level_t level, const char *tag, const char letter, const char *fmt, ...)

Low-footprint log write variant optimized for ROM/bootloader. Functionally equivalent to rtk_log_write() but uses a compact internal buffer to minimize code size. Called internally by RTK_LOG_ITEMS().

Parameters:
  • level – Log level (rtk_log_level_t).

  • tag – Module tag string.

  • letter – Single-character level indicator (A/E/W/I/D).

  • fmt – printf-style format string.

  • ... – Additional arguments for fmt.

RTL8721Dx:

Not supported.