logo
pub unsafe trait Logger {
    fn acquire();
    unsafe fn flush();
    unsafe fn release();
    unsafe fn write(bytes: &[u8]);
}
Expand description

Global logger acquire-release mechanism

This trait’s methods will be called by the defmt logging macros to transmit the encoded log data over the wire. The call order is:

  • One acquire() call to start the log frame.
  • Multiple write() calls, with fragments of the log frame data each.
  • One release() call.

The data passed to write() is unencoded. Implementations MUST encode it with Encoder prior to sending it over the wire. The simplest way is for acquire() to call Encoder::start_frame(), write() to call Encoder::write(), and release() to call Encoder::end_frame().

The global logger can be acquired once for each “execution context”. The definition of execution context is up to the implementation. For example, it can be:

  • the entire process.
  • one thread in std environments.
  • one interrupt priority level in embedded devices.

Safety contract

  • acquire logically acquires the global logger in the current execution context. The acquiring is tracked internally, no Rust object is returned representing ownership.
  • acquire is a safe function, therefore it must be thread-safe and interrupt-safe

And, not safety related, the methods should never be invoked from user code. The easiest way to ensure this is to implement Logger on a private struct and mark that struct as the #[global_logger].

Required Methods

Acquire the global logger in the current execution context.

This will be called by the defmt logging macros before writing each log frame.

Panics if already acquired in the current execution context. Otherwise it must never fail.

Block until host has read all pending data.

The flush operation must not fail. This is a “best effort” operation, I/O errors should be discarded.

Safety

Must only be called when the global logger is acquired in the current execution context. (i.e. between acquire() and release()).

Releases the global logger in the current execution context.

This will be called by the defmt logging macros after writing each log frame.

Safety

Must be called exactly once for each acquire(), in the same execution context.

Writes bytes to the destination.

This will be called by the defmt logging macros to transmit frame data. One log frame may cause multiple write calls.

The write operation must not fail. This is a “best effort” operation, I/O errors should be discarded.

The bytes are unencoded log frame data, they MUST be encoded with Encoder prior to sending over the wire.

Note that a call to write does not correspond to a defmt logging macro invocation. A single defmt::info! call can result in an arbitrary number of write calls.

Safety

Must only be called when the global logger is acquired in the current execution context. (i.e. between acquire() and release()).

Implementors