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 '' | ||