-
Notifications
You must be signed in to change notification settings - Fork 914
Description
This RFC proposes changes to how OTTF communicates with test harnesses.
The key points are:
- Introduction of a new binary SPI protocol.
- Deprecation of SPI console.
- Deprecation of UJSON.
The idea is to use UART exclusively for asynchronous logs and SPI for binary data transfers and synchronisation.
Current communication flow
OTTF communicates with the host test harness via a console which may use either the UART or SPI device as its transport.
Logs, data, and synchronisation messages are sent over the console. Data is encoded as JSON and serialized / deserialized at each end of the transport (UJSON). The UART console is asynchronous but uses software flow control to mitigate data loss. The SPI console is synchronous and requires polling from the host in order for the device to send logs. There is an optional TX notification GPIO available for the SPI console.
Problems
Serializing data as JSON is required over the UART console to allow for in-band flow control support. The (de)serialization adds complexity and overheads. The in-band software flow control is not foolproof and has shown reliability problems in the past with lost data. Increasing reliability requires slowing the data rate by "pacing" each byte to give time for flow control bytes to arrive.
The SPI console uses a (subjectively) complex framing protocol to transport data in chunks. Asynchronous logs from the host cannot be sent until the host polls for them. An extra GPIO pin can be used to notify the host of awaiting data, but adds further complexity. Data is still serialized as UJSON over the SPI console potentially unnecessarily.
Binary SPI protocol
This RFC proposes splitting the work of logs and data between two transports.
UART will be used exclusively for informative logs and not for data transfers or synchronisation. Device-side tests should not rely on the host receiving UART logs for test success.
The SPI will be used to transfer binary data between the device and host and for synchronising control flow. The protocol is built on the following SPI commands sent from the host to device:
READ <addr>- read bytes fromaddron the device.WRITE <addr>- write bytes toaddron the device.SYNC <code>- synchronise with the device using somecode.READ_STATUS- poll the busy status of OTTF synchronisation.
Commands 1-3 will interrupt OTTF and cause an upload. Command 4 will be handled by the SPI device hardware.
The host is able to read and write data to any address at any time. The intended use is writing test data and reading test results to/from SRAM. Known SRAM addresses are obtained from the ELF as is currently done with UJSON. Struct layouts are generated for Rust from the C using bindgen unlike the macro generation system from UJSON.
Synchronisation
The SYNC and READ_STATUS commands are used together for synchronisation.
At startup, the device:
- Configures the SPI device to upload the
SYNCcommand and set the busy bit. - When
SYNCis uploaded, the interrupt handler writes thecodeto a global OTTF variable.
To synchronise, the host:
- Sends a
SYNC <code>command. - Sends a
READ_STATUScommand and continuously reads until the device is no longer busy. - The host now knows that the device has synchronised with the same
code.
To synchronise, the device:
- Continuously reads the global OTTF variable until it matches the expected
code. - Clears the
busybit in the SPI device. - The device now knows that the host has also synchronised with the same
code.
Test results
Instead of reading PASS! and FAIL! messages from the UART, the host should synchronise on a special end-of-test code and then read the test status from SRAM.
Similarly the host may choose to read out coverage data from a known location in SRAM at the end of the test. This replaces the current coverage data transfer mechanism.
Migration plan
The following is the proposed migration plan for the master branch:
- Introduce the binary SPI protocol to OTTF and OpenTitanLib.
- Introduce an OTTF API for synchronisation and migrate all tests.
- Depending on the console that is used:
- For UART: log over UART but synchronise and send binary data via the SPI.
- For SPI: log, synchronise, and send UJSON data over the SPI console still.
- Deprecate and remove the SPI console.
- Deprecate and remove UJSON.
Benefits
The new flow should be faster as the UART does not need to be paced, the SPI does not need to be framed, and JSON (de)serialization is no longer needed.
The protocol complexity should be reduced as the SPI no longer requires framing or a GPIO to notify of asynchronous data from the device. The new protocol is expected to be simpler than the current SPI console protocol.
We expect improved reliability by using a synchronous protocol for data transfer instead of UART. We have frequently had problems with data loss and parsing by sending both logs and data over the same UART console channel.
Drawbacks
Two channels are now required for testing instead of one. We currently require both UART and SPI for tests anyway in order to bootstrap, so this should not add extra overhead for Earl Grey.
Inspecting ASCII JSON over the console for debugging (as is currently done) could be easier than inspecting binary data (as would be required). The tools used to capture signals often translate binary into ASCII anyway (for example most logic analyzer viewers can do this).
Interrupts must be enabled in order to process SPI commands.
Future possibilities
The binary protocol doesn't necessarily need to use SPI as its transport. Future posibilities include USB, I2C, and JTAG.