meta data for this page
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
embedded:nordic:sdk5:log [2024/10/14 21:20] – created niziak | embedded:nordic:sdk5:log [2024/10/24 11:26] (current) – niziak | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== log ====== | ====== log ====== | ||
+ | ===== Flow ===== | ||
+ | |||
+ | Application: | ||
+ | * every call to '' | ||
+ | * NOT DEFERRED: '' | ||
+ | |||
+ | Frontend: | ||
+ | * DEFERRED: Application calls '' | ||
+ | * '' | ||
+ | * one entry is pop-ed from ringbuffer | ||
+ | * new memobj is allocated from '' | ||
+ | * all registered backends are iterated: | ||
+ | * check if backend is enabled '' | ||
+ | * filters: check if module log level and log entry severity level matches | ||
+ | * if log entry should be send to backend - call '' | ||
+ | * **BACKEND: | ||
+ | * '' | ||
+ | |||
+ | <uml> | ||
+ | participant Application as APP | ||
+ | queue " | ||
+ | queue "// | ||
+ | control "// | ||
+ | note over MEM | ||
+ | **NRF_LOG_MSGPOOL_ELEMENT_SIZE** | ||
+ | **x** | ||
+ | **NRF_LOG_MSGPOOL_ELEMENT_COUNT** | ||
+ | endnote | ||
+ | control " | ||
+ | control " | ||
+ | control " | ||
+ | |||
+ | APP -> CB: NRF_LOG_INFO() | ||
+ | activate CB | ||
+ | APP -> CB: NRF_LOG_DEBUG() | ||
+ | activate CB | ||
+ | APP -> CB: NRF_LOG_HEXDUMP() | ||
+ | activate CB | ||
+ | ... | ||
+ | APP -> DE: NRF_LOG_PROCESS() | ||
+ | activate DE | ||
+ | DE <-- MEM: nrf_memobj_alloc() | ||
+ | activate MEM | ||
+ | activate DE | ||
+ | CB --> DE: pop one entry | ||
+ | deactivate CB | ||
+ | DE --> DE: copy entry to allocated\nmempool object | ||
+ | DE <-- DE: backend1: | ||
+ | DE --> B1: mempool object | ||
+ | DE <-- DE: backend2: | ||
+ | DE --> B2: mempool object | ||
+ | DE <-- DE: backend3: | ||
+ | DE --> B3: mempool object | ||
+ | MEM <-- DE: nrf_memobj_put() | ||
+ | deactivate MEM | ||
+ | DE --> APP: return " | ||
+ | deactivate DE | ||
+ | deactivate DE | ||
+ | </ | ||
+ | |||
+ | ===== buffer sizes ===== | ||
+ | |||
+ | * Circular buffer of **NRF_LOG_BUFSIZE (1024)**: | ||
+ | * Its aim is to store log entry from app as fast as possible without further processing. | ||
+ | * DEFERRED: should be big enough to store all log entries until apps calls log to be processed. | ||
+ | * Dynamic memory pool: | ||
+ | * size is '' | ||
+ | * provides dynamic memory access, even to fragmented memory. | ||
+ | * provides storage for log entry qualified to be passed to backends. | ||
+ | * provides '' | ||
+ | * It looks like to be designed for background backends. Counting semaphore will keep object locked until all backends finish. | ||
+ | * Background backends: | ||
+ | * **NRF_CLI_LOG_BACKEND** | ||
+ | * Backends are using temporary string buffers - this is the real place where printf-like function writes generated strings. | ||
+ | * '' | ||
+ | |||
+ | ===== Backends api ===== | ||
+ | |||
+ | |||
+ | <code c> | ||
+ | typedef struct | ||
+ | { | ||
+ | void (*put)(nrf_log_backend_t const * p_backend, nrf_log_entry_t * p_entry); | ||
+ | void (*panic_set)(nrf_log_backend_t const * p_backend); | ||
+ | void (*flush)(nrf_log_backend_t const * p_backend); | ||
+ | } nrf_log_backend_api_t; | ||
+ | </ | ||
+ | |||
+ | * '' | ||
+ | * UART/ | ||
+ | * printf-like processing | ||
+ | * memobj with log entry is released ('' | ||
+ | * CLI: | ||
+ | * memobj is not released. '' | ||
+ | * own **queue** size is defined by '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * RTT: empty | ||
+ | * UART: uninit uart driver | ||
+ | * '' | ||
+ | * CLI: '' | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * result of processing is passed to printf-like writer '' | ||
+ | * '' | ||
+ | * cli_uart_write puts data to UART TX ringbuffer defined by macro NRF_CLI_UART_DEF | ||
+ | |||
+ | ===== using CLI and deferred log ===== | ||
+ | |||
+ | SUMMARY: | ||
+ | * app logs data and metadata to ringbuffer: '' | ||
+ | * app idle calls: '' | ||
+ | * if dynamic log levels enabled it filter what to log | ||
+ | * it copies entries from ringbuffer to memobj (dynamic memory of size '' | ||
+ | * each one memobj log entry is passed to all active backends (multiple reference locking possible by counting semaphore) | ||
+ | * UART backend: it process log entry (printf-like formatting) and put it in UART TX buffer. Memobj log entry is released. | ||
+ | * RTT backend: it process log entry (printf-like formatting) and put it in RTT buffer. Memobj log entry is released. | ||
+ | * CLI backend: it puts log entry into own queue. Memobj log entry is **NOT released**. | ||
+ | * **conclusion**: | ||
+ | * **conclusion**: | ||
+ | * app idle calls: '' | ||
+ | * whole queue is processed in loop | ||
+ | * each memobj log entry is processed (printf-like formatting) and put into UART TX ring buffer (size defined by '' | ||