Skip to content

Commit

Permalink
[rom] Make the banner message non-blocking
Browse files Browse the repository at this point in the history
1. The ROM banner takes about 2 ms to be sent from the UART at 115200
   bps.  Rather than wait for it to complete transmission, emit the
   characters into the UART FIFO and proceed with boot.  Hashing the
   FLASH contents and performing signature verification typically will
   take an additional 2.4 + 4.2 ms.  There is no need to delay boot
   waiting for the UART.
2. Fix the ROM's terminal states to wait for UART output to complete.

Signed-off-by: Chris Frantz <[email protected]>
  • Loading branch information
cfrantz committed Jun 27, 2024
1 parent 4998f98 commit 8db2a18
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 29 deletions.
12 changes: 6 additions & 6 deletions sw/device/silicon_creator/lib/drivers/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,16 @@ static bool uart_tx_idle(void) {
return bitfield_bit32_read(reg, UART_STATUS_TXIDLE_BIT);
}

void uart_putchar(uint8_t byte) {
static void putchar_nonblocking(uint8_t byte) {
// If the transmit FIFO is full, wait.
while (uart_tx_full()) {
}
uint32_t reg = bitfield_field32_write(0, UART_WDATA_WDATA_FIELD, byte);
abs_mmio_write32(TOP_EARLGREY_UART0_BASE_ADDR + UART_WDATA_REG_OFFSET, reg);
}

void uart_putchar(uint8_t byte) {
putchar_nonblocking(byte);
// If the transmitter is active, wait.
while (!uart_tx_idle()) {
}
Expand All @@ -111,14 +114,14 @@ void uart_write_hex(uint32_t val, size_t len, uint32_t after) {
size_t i = len * 8;
do {
i -= 4;
uart_putchar(kHexTable[(val >> i) & 0xF]);
putchar_nonblocking(kHexTable[(val >> i) & 0xF]);
} while (i > 0);
uart_write_imm(after);
}

void uart_write_imm(uint64_t imm) {
while (imm) {
uart_putchar(imm & 0xFF);
putchar_nonblocking(imm & 0xFF);
imm >>= 8;
}
}
Expand Down Expand Up @@ -162,6 +165,3 @@ size_t uart_sink(void *uart, const char *data, size_t len) {
uart_write((const uint8_t *)data, len);
return len;
}

// Provide link locations for inline functions.
extern void uart_write_newline(void);
9 changes: 4 additions & 5 deletions sw/device/silicon_creator/lib/drivers/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ void uart_write(const void *data, size_t len);
/**
* Write an unsigned integer as hex to the UART.
*
* Note: this function does not block waiting for the transmitter to finish.
*
* @param val The value to write to the UART.
* @param len The length of the value in bytes (1, 2, or 4 bytes).
* @param after Packed ASCII values to write after the hex value.
Expand All @@ -71,15 +73,12 @@ void uart_write_hex(uint32_t val, size_t len, uint32_t after);
* order (ie: the string is reversed). A maximum of eight bytes can be printed
* in this way. A zero byte in the value terminates the output.
*
* Note: this function does not block waiting for the transmitter to finish.
*
* @param val The bytes to print.
*/
void uart_write_imm(uint64_t val);

inline void uart_write_newline(void) {
// \n\r
uart_write_imm(0x0a0d);
}

/**
* Read from the UART into a buffer.
*
Expand Down
37 changes: 22 additions & 15 deletions sw/device/silicon_creator/lib/shutdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,24 @@ enum {
kUartFifoSize = UART_PARAM_TX_FIFO_DEPTH,
};

OT_ALWAYS_INLINE
static void shutdown_tx_wait(void) {
#ifdef OT_PLATFORM_RV32
// Wait until UART TX is complete.
static_assert(kErrorMsgLen <= kUartFifoSize,
"Total message length must be less than TX FIFO size.");
CSR_WRITE(CSR_REG_MCYCLE, 0);
uint32_t mcycle;
bool tx_idle;
do {
tx_idle =
bitfield_bit32_read(abs_mmio_read32(kUartBase + UART_STATUS_REG_OFFSET),
UART_STATUS_TXIDLE_BIT);
CSR_READ(CSR_REG_MCYCLE, &mcycle);
} while (mcycle < kUartTxFifoCpuCycles && !tx_idle);
#endif
}

/**
* Prints a fixed-length (`kErrorMsgLen`) error message.
*
Expand Down Expand Up @@ -363,21 +381,7 @@ static void shutdown_print(shutdown_log_prefix_t prefix, uint32_t val) {

abs_mmio_write32(kUartBase + UART_WDATA_REG_OFFSET, '\r');
abs_mmio_write32(kUartBase + UART_WDATA_REG_OFFSET, '\n');

#ifdef OT_PLATFORM_RV32
// Wait until UART TX is complete.
static_assert(kErrorMsgLen <= kUartFifoSize,
"Total message length must be less than TX FIFO size.");
CSR_WRITE(CSR_REG_MCYCLE, 0);
uint32_t mcycle;
bool tx_idle;
do {
tx_idle =
bitfield_bit32_read(abs_mmio_read32(kUartBase + UART_STATUS_REG_OFFSET),
UART_STATUS_TXIDLE_BIT);
CSR_READ(CSR_REG_MCYCLE, &mcycle);
} while (mcycle < kUartTxFifoCpuCycles && !tx_idle);
#endif
shutdown_tx_wait();
}

SHUTDOWN_FUNC(NO_MODIFIERS, shutdown_report_error(rom_error_t reason)) {
Expand All @@ -397,6 +401,9 @@ SHUTDOWN_FUNC(NO_MODIFIERS, shutdown_report_error(rom_error_t reason)) {
// Store redacted shutdown reason in retention SRAM.
retention_sram_get()->creator.last_shutdown_reason = redacted_error;

// If there are any characters in the TX FIFO, wait for them to be sent.
shutdown_tx_wait();

// Reset UART TX fifo and enable TX.
abs_mmio_write32(kUartBase + UART_FIFO_CTRL_REG_OFFSET,
bitfield_bit32_write(0, UART_FIFO_CTRL_TXRST_BIT, true));
Expand Down
7 changes: 4 additions & 3 deletions sw/device/silicon_creator/lib/stack_utilization.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ void stack_utilization_print(void) {
uint32_t used = total - free;
// : K T S
const uint32_t kPrefix = 0x3a4b5453;
// \n\r
const uint32_t kNewline = 0x0a0d;
uart_write_imm(kPrefix);
uart_write_hex(used, sizeof(used), '/');
uart_write_hex(total, sizeof(total), kNewline);
uart_write_hex(total, sizeof(total), '\r');
// Send the last char with putchar so we'll wait for the
// transmitter to finish.
uart_putchar('\n');
}
#endif

0 comments on commit 8db2a18

Please sign in to comment.