TI Utilities API
Macros | Typedefs | Enumerations
Log Interface

The Log module provides APIs to instrument source code. More...

Macros

#define ti_utils_runtime_Log_USE_LTO   0
 
#define ti_utils_runtime_Log_USE_PPO   1
 
#define Log_DECLARE_MODULE(module)
 
#define Log_event(module, level, ...)   _Log_GUARD_MACRO(_Log_event_B(module, level, __VA_ARGS__))
 Raise a log event to the logger. More...
 
#define Log_EVENT_CONSTRUCT(module, name, fmt)
 Construct a log event object. More...
 
#define Log_buf(module, level, format, data, size)   _Log_GUARD_MACRO(_Log_buf_B(module, level, format, data, size))
 Log a continuous block of memory. More...
 
#define Log_printf(module, level, ...)   _Log_GUARD_MACRO(_Log_printf_B(module, level, __VA_ARGS__))
 Emit a printf formatted log. More...
 

Typedefs

typedef enum Log_Level Log_Level
 

Enumerations

enum  Log_Level {
  Log_INFO1 = 1,
  Log_INFO2 = 2,
  Log_INFO3 = 4,
  Log_INFO4 = 8,
  Log_INFO5 = 16,
  Log_INFO6 = 32,
  Log_WARN = 64,
  Log_ERROR = 128
}
 

Detailed Description

The Log module provides APIs to instrument source code.

To access the LOG APIs, the application should include its header file as follows:

When the application is configured using syscfg, the generated ti_utils_build_linker command file will pull in the necessary libraries based on the options selected in the UI.

If syscfg is not used, the developer must add any relevant Logger transport libraries to the link line. An example is shown below for LoggerBuf which is a memory based log transport:

.../source/ti/loggers/utils/lib/{toolchain}/{isa}/loggers_{profile}.a

Beta Disclaimer

The logging ecosystem are to be considered beta quality. They are not recommended for use in production code by TI. APIs and behaviour will change in future releases. Please report issues or feedback to E2E.

Definitions

The following terms are used throughout the log documentation.

Term Definition
LogModule A parameter passed to Log APIs to indicate which software module the log

statement originated from. | | LogLevel | The severity or importance of a given log statement. | | BackendDelegate | Also simply called a logger. This is a transport specific logger implementation.
The Logging framework is flexible such that multiple backend delegates may exist in a single firmware image. | | CallSite | A specific invocation of a Log API in a given file or program. | | LogSite | The syscfg module that handles routing of LogModules to specific BackendDelegates. | | Link Time Optimization (LTO) | Conditional inclusion/exclusion of logs using link time optimization/dead code elimination.
This approach will push the decision of log inclusion to the linker.
In order to achieve good performance all code and libraries participating in logging must be compiled and linked at the highest optimization level. | | Preprocessor Optimization (PPO) | Conditional inclusion/exclusion of logs using the C preprocessor. The decision to include/exclude logs is made during preprocessing. |

Modules

When adding log statements to the target software, it is recommended to create a logging module for each software component in the image. Modules enable the reader to understand where the log record originated from. Some log visualizers may allow the reader to filter or sort log statements by module. It is also recommended to namespace modules.

For example, a good module name for the UART driver that exists in source/ti/drivers, would be ti_drivers_UART.

Modules also control the routing of log records to a backend delegate. Routing is controlled via the LogSite panel in syscfg. The default log module is called ti_utils_runtime_LogMain and is always available. All other modules must be created via LogSite. Enabling a module via LogSite will generate externs and definitions in ti_utils_runtime_config. Each extern and definition is namespaced by the module.

An example of the definitions generated for the default log module is shown below:

const uint32_t ti_utils_runtime_LogMain_LogSite_level = 0;
const ILogger_Handle ti_utils_runtime_LogMain_LogSite_handle = &ti_loggers_utils_LoggerBuf_config[0];
extern void ti_utils_runtime_LogMain_LogSite_event(ILogger_Handle, uint32_t, uintptr_t, uintptr_t,
uintptr_t, uintptr_t, uintptr_t); extern void ti_utils_runtime_LogMain_LogSite_printf(ILogger_Handle,
uint32_t, uint32_t, ...); extern void ti_utils_runtime_LogMain_LogSite_buf(ILogger_Handle, uint32_t, const
char*, uint8_t *, size_t);

In summary, each new module will instantiate a level bitmask and handle. It will also create externs of each log API that is prefixed with the module name. The extern definitions allow routing of different modules to different logger backends.

The routing of module –> backend is achieved at link time by remapping the externed symbol generated above to the actual backend logger API. Routing is achieved by using the symbol renaming function of the linker. The LogSite syscfg will generate a file called ti_utils_runtime_LogSite.cmd.genlibs that does this mapping at link time. A sample of this for the TI ARM compiler is shown below. It will route the externs created above to the LoggerBuf backend.

--symbol_map=ti_utils_runtime_LogMain_LogSite_event=ti_loggers_utils_LoggerBuf_event
--symbol_map=ti_utils_runtime_LogMain_LogSite_printf=ti_loggers_utils_LoggerBuf_printf
--symbol_map=ti_utils_runtime_LogMain_LogSite_buf=ti_loggers_utils_LoggerBuf_buf

Levels

Log levels are a way to indicate the severity or importance of the contents of a particular log call site. Each call site takes an argument that allows the user to specify the level. As with modules, log visualization tools allow the user to sort or filter on a given level. This can help the reader to find important or relevant log statements in visualization.

Log levels are also used to control the emission of logs. Each call site will check that the level is enabled before calling the underlying log API.

When using LTO log levels are configurable on a per module basis while when using PPO the levels are controlled via preprocessor definitions for example: ti_utils_runtime_Log_ENABLE_INFO1. For PPO, all log levels of interest must be enabled in the preprocessor options. For LTO, they are controlled via syscfg.

For PPO:

if ((level) & module##_LogSite_level) {
// Call Log API
}

For LTO:

if ((level) & module##_LogSite_level) {
// Call Log API
}
Remarks

Log Metadata

Each time a Log API is invoked, a metadata string is placed in the .out file. This string contains information about the API type, file, line module, level, and other information associated with the log call site. Each call site emits a string to a specific memory section called .log_data. In order to use logging, this section should be added to the linker command file. By default, this section points to a nonloadable region of memory. Meaning that the metadata will not be loaded on the target device. Instead, the various logging visualization tools such as wireshark and TI ROV2 will read the metadata from this section and properly decode the log statements. The benefit of this approach is that very little memory is consumed on target. Additionally, the log transport only needs to store or send pointers to this meta section when a log API is called.

In summary, this approach minimizes the amount of memory consumed on device and bytes sent over the transport. This section can be loaded on target if desired or if you are creating a custom logger. The design does not preclude this.

In order to use the logging framework, the log section must be added to the linker command file. Here is a sample for the TI linker. Other examples can be found in the TI provided linker files for each toolchain.

MEMORY
{
// List other memory regions here
LOG_DATA (R) : origin = 0x90000000, length = 0x40000
}
SECTIONS
{
.log_data : > LOG_DATA, type = COPY
}

Usage

This section provides a basic usage summary and a set of examples in the form of commented code fragments. Detailed descriptions of the LOG APIs are provided in subsequent sections.

Synopsis

// Import the Log header
// Printf is the easiest to use log-api. It offers medium performance
// for most transport mechanisms
Log_printf(ti_utils_runtime_LogMain, Log_INFO1, "Hello World!");

Examples

Log Event: The following example demonstrates how to create a log event object and use it in the code. There are two steps to using a log event: 1. instantiation and 2. call site(s). Instantiation creates the event and the necessary metadata, and call site is where the event is actually recorded by the logger framework. Because most of the metadata and arguments are statically created, the event is the most efficient log statement.

// Create a log event data type called LogEvent_count
// The log module is ti_utils_runtime_LogMain
// The format string is "count=%d" -- this should describe what the event
// does
Log_EVENT_CONSTRUCT(ti_utils_runtime_LogMain, LogEvent_count, "count=%d");

Later on, in the application, the count event is consumed. Note the log module must match between event creation and call site. In the code below, a LogEvent record is created for serialization or stage by the backend logger.

Log_event(ti_utils_runtime_LogMain, Log_INFO1, LogEvent_count, count++);

Log Printf: The following example demonstrates use of the Log printf API. in code. Printf will embed the format string in the call site and will take arguments using varadic arguments

Log_printf(ti_utils_runtime_LogMain, Log_INFO1, "Hello World!");

Log Buf: The following example demonstrates use of the Log buf API. in code. Printf will embed the format string in the call site and will take the buffer as a pointer and length. Buffers are treated as arrays of bytes. The buffer API should only be used when it is necessary to log data that is only available at runtime. It will actually send or store the entire contents of the buffer, so this API should be used sparingly as it is costly in terms of runtime and memory overhead.

uint8_t bufferToLog[] = {0, 1, 2, 3, 4, 5};
Log_buf(ti_utils_runtime_LogMain,
"The contents of bufferToLog are: ",
bufferToLog,
sizeof(bufferToLog));

Macro Definition Documentation

§ ti_utils_runtime_Log_USE_LTO

#define ti_utils_runtime_Log_USE_LTO   0

§ ti_utils_runtime_Log_USE_PPO

#define ti_utils_runtime_Log_USE_PPO   1

§ Log_DECLARE_MODULE

#define Log_DECLARE_MODULE (   module)
Value:
_Log_DECL_Write(module); \
_Log_DECL_Printf(module); \
_Log_DECL_buf(module); \
_Log_DECL_Handle(module); \
_Log_DECL_Level(module);

Declare a log module other than the default (ti_utils_runtime_LogMain)

This macro will create the necessary externs used to route this module's traffic to a logger instance. It can be useful for statically linked libraries to forward declare their modules so that they can be routed at link time

This must be combined with a symbol remapping to the specific backend logger that will accept this modules log statements. This is discussed in the modules section above. If using syscfg, this macro is not required as the externs are generated by the LogSite module.

Parameters
[in]moduleLog module to declare

§ Log_event

#define Log_event (   module,
  level,
  ... 
)    _Log_GUARD_MACRO(_Log_event_B(module, level, __VA_ARGS__))

Raise a log event to the logger.

This API will emit a log record with the user provided event arguments. This event is linked to the one constructed by Log_EVENT_CONSTRUCT through a pointer to the metadata location. Separate construct and consume APIs means that an event can be constructed in the code and reused multiple places in the code with different runtime arguments.

Parameters
[in]moduleLog module that the event belongs to
[in]levellog level
[in]...Variadic arguments consisting of the following
  • event structure declared by Log_EVENT_CONSTRUCT. This is required
  • a0-a3 arguments consumed by the Log_EVENT_CONSTRUCT format string. These are optional
Remarks
The maximum number of arguments is four. All 4 arguments will always be provided to the backend. Unused arguments are passed as 0.

§ Log_EVENT_CONSTRUCT

#define Log_EVENT_CONSTRUCT (   module,
  name,
  fmt 
)
Value:
_Log_PLACE_FORMAT_IN_SECTOR(_Log_CONCAT2(LogSymbol, name), LOG_EVENT_CONSTRUCT, name, module, fmt, 0) \
const char *_Log_CONCAT2(module, name) = _Log_CONCAT2(LogSymbol, name);

Construct a log event object.

Use this marco to define a log event object. The object is private to the current file. Use the object handle in a call to Log_event to raise that event to the logger.

Parameters
[in]moduleLog module that the event belongs to
[in]nameEvent variable name, to be passed to Log_event API
[in]fmtRestricted format string. Note s is not supported. Supported format specifiers include: c, f, d, x
Remarks
The module passed here must match the one from the callsite

§ Log_buf

#define Log_buf (   module,
  level,
  format,
  data,
  size 
)    _Log_GUARD_MACRO(_Log_buf_B(module, level, format, data, size))

Log a continuous block of memory.

Use this marco to send out runtime data from the device. This API should be used when the data is non constant and can only be derived at runtime. It is the most intrusive in terms of record overhead and instructions used.

Parameters
[in]moduleLog module that the buffer originated from
[in]levellog level of type Log_Level
[in]formatRestricted format string.
[in]dataPointer to array of bytes (uint8_t *)
[in]sizeSize in bytes of array to send

§ Log_printf

#define Log_printf (   module,
  level,
  ... 
)    _Log_GUARD_MACRO(_Log_printf_B(module, level, __VA_ARGS__))

Emit a printf formatted log.

Use this marco to enable printf style logging. This API offers the most flexibility as the construction of the format string is embedded in the call site of the API. It also supports true variadic arguments.

Parameters
[in]moduleLog module that the buffer originated from
[in]levellog level of type Log_Level
[in]...Variadic arguments consisting of the following
  • format format string. This is required
  • a0-a3 arguments consumed by the format string. These are optional
Remarks
The number of arguments is currently limited to 4. Only used arguments are included in the record.

Typedef Documentation

§ Log_Level

typedef enum Log_Level Log_Level

Enumeration Type Documentation

§ Log_Level

enum Log_Level
Enumerator
Log_INFO1 
Log_INFO2 
Log_INFO3 
Log_INFO4 
Log_INFO5 
Log_INFO6 
Log_WARN 
Log_ERROR 
© Copyright 1995-2022, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale