Non-blocking Console Logging
This section details Console Logging and how log messages are sent by the Managers to the App and printed without blocking the Manager. Non-blocking Console Logging is important as most threads have strict deadlines to meet and the overhead ordinarily added by Console Logging makes it completely infeasible.

Console Logs are posted by the Managers (from within their threads) to the App's Console Logger, and are consumed in FIFO order, i.e. they lack priorities. Each Console Log consists of a format string and arguments, which are processed into a single string before being printed to the console. Formatting happens in the Manager's thread, but the transmission of the resultant string (over UART) is non-blocking. This has the following benefits -
- Disabling/re-enabling a ConsoleLog does not noticeably change the behavior of the Manager. Formatting is orders of magnitude faster than IO and has no significant effect on the timing.
- IO is a slow operation that can hinder a Manager's ability to meet deadlines. By shifting the overhead out, it is easier to meet deadlines and manage timing (especially for high-frequency, periodic tasks).
While Console Logs lack priorities, they have 5 levels (from lowest to highest) -
- Info
- Verbose
- Warning
- Error
- Fatal
The Console Logger API includes separate interfaces for each of the above levels, and the level in-use can be set in the build system. The interfaces for lower-level logs will be removed during compilation.

Console Logging from the Managers follows the given sequence -
- The Manager (from on of its threads) posts a Console Log (format string and arguments) to the App through the Console Logger API.
- The Console Logger API performs formatting to generate a single formatted string. If this process fails, or the length of the resultant string is outside of bounds, the operation is cancelled and a failure is returned to the caller, otherwise continue.
- The resultant string is pushed to the Console Logger's Queue. If the Queue is full, the operation is cancelled a failure is returned to the caller, otherwise a success is returned.
- The Console Logger's thread waits for strings on the Queue. Once a string is available, it receives it and uses the Glue Layer APIs to start transmitting it. The thread waits for the transmission to finish before moving onto the next string.
- Once a string is fully transmitted, the hardware calls an ISR and uses the Glue Layer API to forward this notification to the App.
The Console Logger thread must wait for a buffer to be fully transmitted before moving onto the next one because -
- Generally, the DMA/Interrupt peripheral on most MCUs do not support queuing and require the current buffer to be fully copied before moving onto the next one.
- The buffer given to the DMA peripheral is used immediately without any further copies. This is faster but requires the buffer to not be left alone while the transmission is not complete.