capsules_core

Module console_ordered

Source
Expand description

Provides userspace with access to a serial interface whose output is in-order with respect to kernel debug!() operations.

Prints to the console are atomic up to particular constant length, which can be set at capsule instantiation.

Note that this capsule does not buffer writes in an additional buffer; this is critical to ensure ordering. Instead, it pushes writes into the kernel debug buffer. If there is insufficient space in the buffer for the write (or an atomic block size chunk of a very large write), the capsule waits and uses a retry timer. This means that in-kernel debug statements can starve userspace prints, e.g., if they always keep the kernel debug buffer full.

§Setup

This capsule allows userspace programs to print to the kernel debug log. This ensures that (as long as the writes are not truncated) that kernel and userspace print operations are in order. It requires a reference to an Alarm for timers to issue callbacks and send more data. The three configuration constants are:

  • ATOMIC_SIZE: the minimum block of buffer that will be sent. If there is not enough space in the debug buffer to send ATOMIC_SIZE bytes, the console retries later.
  • RETRY_TIMER: if there is not enough space in the debug buffer to send the next chunk of a write, the console waits RETRY_TIMER ticks of the supplied alarm.
  • WRITE_TIMER: after completing a write, the console waits WRITE_TIMER ticks of the supplied alarm before issuing a callback or writing more.

RETRY_TIMER and WRITE_TIMER should be set based on the speed of the underlying UART and desired load. Generally speaking, setting them around 50-100 byte times is good. For example, this means on a 115200 UART, setting them to 5ms (576 bits, or 72 bytes) is reasonable. ATOMIC_SIZE should be at least 80 (row width of a standard console).

let console = static_init!(
    ConsoleOrdered,
    ConsoleOrdered::new(virtual_alarm,
                        board_kernel.create_grant(capsules_core::console_ordered::DRIVER_NUM,
                                                  &grant_cap),
                        ATOMIC_SIZE,
                        RETRY_TIMER,
                        WRITE_TIMER));

§Usage

The user must perform three steps in order to write a buffer:

// (Optional) Set a callback to be invoked when the buffer has been written
subscribe(CONSOLE_DRIVER_NUM, 1, my_callback);
// Share the buffer from userspace with the driver
allow(CONSOLE_DRIVER_NUM, buffer, buffer_len_in_bytes);
// Initiate the transaction
command(CONSOLE_DRIVER_NUM, 1, len_to_write_in_bytes)

Structs§

Constants§