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 |
|
Critical information that must always be shown, but does not indicate a warning or error. |
RTK_LOG_ERROR |
2 |
|
Error messages, such as incorrect API usage. |
RTK_LOG_WARN |
3 |
|
Inappropriate configuration that still works, or situations that may lead to errors. |
RTK_LOG_INFO |
4 |
|
Normal and necessary operational messages (default level). |
RTK_LOG_DEBUG |
5 |
|
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
NOTAGto 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
NOTAGto suppress the prefix.level: one of the
rtk_log_level_tvalues.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 |
|
Return |
|
rtk_log_level_get
Items |
Description |
|---|---|
Introduction |
Query the effective log level for a module tag. |
Parameter |
|
Return |
The level registered for the tag if found in the cache; otherwise
the global 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 |
|
Return |
|
Global level and per-module level
The runtime log level operates on two independent dimensions:
Global default level (
rtk_log_default_level): set viartk_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 byrtk_log_level_getand 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.
Print Backend
Each log macro call passes through two filtering stages before reaching the actual print backend, as shown in the following diagram.
The two filtering stages are:
Compile-time filter (
COMPIL_LOG_LEVEL): any call whose level exceeds this value is removed by the preprocessor and generates no code.Runtime filter (
rtk_log_level_get): checks the effective level for the tag against the current call level. If the tag has been individually registered viartk_log_level_set(), that level is used; otherwise the global default (rtk_log_default_level) applies.
Two print backends are available:
DiagPrintfNano: lower stack usage, suitable for interrupt handlers and small-stack tasks; limited format specifier support.DiagPrintf: supports format specifiers except floating-point (%f,%g, etc.), suitable for general use.
Performance Overhead
The two macro families differ in stack usage and format specifier support:
RTK_LOGScall chain:RTK_LOGS->rtk_log_write_nano()->DiagPrintfNano/DiagVprintfNano. Typical stack usage is ~136 B; limited format specifier support.RTK_LOGxcall 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_LOGSin interrupt handlers or stack-constrained tasks.Use
RTK_LOGxwhen long integer format specifiers such as%lldor%luare 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 |
|
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 |
|
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 |
|
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)
-
rtk_log_level_t level
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.
Not supported.
Not supported.
Not supported.
Not supported.
Not supported.
-
void rtk_log_mutex_init(void)
Initialize the internal print mutex for CA32 multi-core log safety.
Note
Must be called once during system initialization on CA32 cores before any log output; no-op on other core types.
Not supported.
Not supported.