14 #include "sw/device/lib/runtime/irq.h"
16 #include "sw/device/lib/testing/clkmgr_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
18 #include "sw/device/lib/testing/test_framework/ottf_console.h"
20 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
21 #include "sw/device/lib/testing/test_framework/status.h"
22 #include "sw/device/lib/testing/uart_testutils.h"
26 #define UART_DATASET_SIZE 64
28 static dif_clkmgr_t clkmgr;
29 static dif_pinmux_t pinmux;
30 static dif_rv_plic_t plic;
31 static dif_uart_t uart;
55 typedef enum uart_direction {
72 OTTF_BACKDOOR_VAR_DV uint8_t kUartIdxDv = 0xff;
79 static volatile uint8_t kUartIdx = 0xff;
85 OTTF_BACKDOOR_VAR_DV uint64_t kUartBaudrateDV = 0u;
90 OTTF_BACKDOOR_VAR_DV uint64_t kUartClockFreqHzDV = 0u;
97 static volatile const bool kUseExtClk =
false;
98 static volatile const bool kUseLowSpeedSel =
false;
104 static volatile const uint8_t kUartTxData[UART_DATASET_SIZE] = {
105 0xff, 0x50, 0xc6, 0xb4, 0xbe, 0x16, 0xed, 0x55, 0x16, 0x1d, 0xe6,
106 0x1c, 0xde, 0x9f, 0xfd, 0x24, 0x89, 0x81, 0x4d, 0x0d, 0x1a, 0x12,
107 0x4f, 0x57, 0xea, 0xd6, 0x6f, 0xc0, 0x7d, 0x46, 0xe7, 0x37, 0x81,
108 0xd3, 0x8e, 0x16, 0xad, 0x7b, 0xd0, 0xe2, 0x4f, 0xff, 0x39, 0xe6,
109 0x71, 0x3c, 0x82, 0x04, 0xec, 0x3a, 0x27, 0xcc, 0x3d, 0x58, 0x0e,
110 0x56, 0xd2, 0xd2, 0xb9, 0xa3, 0xb5, 0x3d, 0xc0, 0x40,
114 static volatile const uint8_t kExpUartRxData[UART_DATASET_SIZE] = {
115 0x1b, 0x95, 0xc5, 0xb5, 0x8a, 0xa4, 0xa8, 0x9f, 0x6a, 0x7d, 0x6b,
116 0x0c, 0xcd, 0xd5, 0xa6, 0x8f, 0x07, 0x3a, 0x9e, 0x82, 0xe6, 0xa2,
117 0x2b, 0xe0, 0x0c, 0x30, 0xe8, 0x5a, 0x05, 0x14, 0x79, 0x8a, 0xFf,
118 0x88, 0x29, 0xda, 0xc8, 0xdd, 0x82, 0xd5, 0x68, 0xa5, 0x9d, 0x5a,
119 0x48, 0x02, 0x7f, 0x24, 0x32, 0xaf, 0x9d, 0xca, 0xa7, 0x06, 0x0c,
120 0x96, 0x65, 0x18, 0xe4, 0x7f, 0x26, 0x44, 0xf3, 0x14,
132 static volatile bool exp_uart_irq_tx_watermark;
133 static volatile bool uart_irq_tx_watermark_fired;
134 static volatile bool exp_uart_irq_tx_empty;
135 static volatile bool uart_irq_tx_empty_fired;
136 static volatile bool exp_uart_irq_rx_watermark;
137 static volatile bool uart_irq_rx_watermark_fired;
138 static volatile bool exp_uart_irq_tx_done;
139 static volatile bool uart_irq_tx_done_fired;
140 static volatile bool exp_uart_irq_rx_overflow;
141 static volatile bool uart_irq_rx_overflow_fired;
144 kCommandTimeout = 5000000,
152 void ottf_external_isr(uint32_t *exc_info) {
161 CHECK(peripheral == uart_cfg.peripheral_id,
162 "Interrupt from unexpected peripheral: %d", peripheral);
165 dif_uart_irq_t uart_irq;
166 if (plic_irq_id == uart_cfg.irq_tx_watermark_id) {
167 CHECK_DIF_OK(dif_uart_irq_set_enabled(&uart, kDifUartIrqTxWatermark,
169 CHECK(exp_uart_irq_tx_watermark,
"Unexpected TX watermark interrupt");
170 uart_irq_tx_watermark_fired =
true;
171 uart_irq = kDifUartIrqTxWatermark;
172 }
else if (plic_irq_id == uart_cfg.irq_tx_empty_id) {
173 CHECK_DIF_OK(dif_uart_irq_set_enabled(&uart, kDifUartIrqTxEmpty,
175 CHECK(exp_uart_irq_tx_empty,
"Unexpected TX empty interrupt");
176 uart_irq_tx_empty_fired =
true;
177 uart_irq = kDifUartIrqTxEmpty;
178 }
else if (plic_irq_id == uart_cfg.irq_rx_watermark_id) {
179 CHECK_DIF_OK(dif_uart_irq_set_enabled(&uart, kDifUartIrqRxWatermark,
181 CHECK(exp_uart_irq_rx_watermark,
"Unexpected RX watermark interrupt");
182 uart_irq_rx_watermark_fired =
true;
183 uart_irq = kDifUartIrqRxWatermark;
184 }
else if (plic_irq_id == uart_cfg.irq_tx_done_id) {
185 CHECK(exp_uart_irq_tx_done,
"Unexpected TX done interrupt");
186 uart_irq_tx_done_fired =
true;
187 uart_irq = kDifUartIrqTxDone;
188 }
else if (plic_irq_id == uart_cfg.irq_rx_overflow_id) {
189 CHECK(exp_uart_irq_rx_overflow,
"Unexpected RX overflow interrupt");
190 uart_irq_rx_overflow_fired =
true;
191 uart_irq = kDifUartIrqRxOverflow;
193 LOG_ERROR(
"Unexpected interrupt (at PLIC): %d", plic_irq_id);
194 test_status_set(kTestStatusFailed);
203 CHECK_DIF_OK(dif_uart_irq_is_pending(&uart, uart_irq, &is_pending));
204 CHECK(is_pending,
"UART interrupt fired at PLIC did not fire at UART");
207 CHECK_DIF_OK(dif_uart_irq_acknowledge(&uart, uart_irq));
217 static void uart_init_with_irqs(
mmio_region_t base_addr, dif_uart_t *uart,
218 uint32_t uartBaudrate, uint32_t uartFreqHz) {
221 CHECK_DIF_OK(dif_uart_init(base_addr, uart));
223 .baudrate = (uint32_t)uartBaudrate,
224 .clk_freq_hz = (uint32_t)uartFreqHz,
238 CHECK_DIF_OK(dif_uart_irq_set_enabled(uart, kDifUartIrqRxWatermark,
249 static void plic_init_with_irqs(
mmio_region_t base_addr, dif_rv_plic_t *plic) {
250 LOG_INFO(
"Initializing the PLIC. %08x", uart_cfg.irq_tx_watermark_id);
252 CHECK_DIF_OK(dif_rv_plic_init(base_addr, plic));
328 static bool uart_transfer_ongoing_bytes(
const dif_uart_t *uart,
329 uart_direction_t uart_direction,
330 uint8_t *data,
size_t dataset_size,
331 size_t *dataset_index,
332 size_t max_xfer_size,
333 bool *transfer_done) {
334 size_t bytes_remaining = dataset_size - *dataset_index;
335 size_t bytes_to_xfer =
336 max_xfer_size < bytes_remaining ? max_xfer_size : bytes_remaining;
337 size_t bytes_transferred = 0;
339 switch (uart_direction) {
342 &bytes_transferred) ==
kDifOk;
344 CHECK_DIF_OK(dif_uart_irq_set_enabled(uart, kDifUartIrqTxWatermark,
346 CHECK_DIF_OK(dif_uart_irq_set_enabled(uart, kDifUartIrqTxEmpty,
352 &bytes_transferred) ==
kDifOk;
354 CHECK_DIF_OK(dif_uart_irq_set_enabled(uart, kDifUartIrqRxWatermark,
358 LOG_FATAL(
"Invalid UART data transfer direction!");
360 *dataset_index += bytes_transferred;
361 *transfer_done = *dataset_index == dataset_size;
365 static void execute_test(
const dif_uart_t *uart) {
366 bool uart_tx_done =
false;
367 size_t uart_tx_bytes_written = 0;
368 exp_uart_irq_tx_watermark =
true;
369 exp_uart_irq_tx_empty =
true;
373 uart_irq_tx_watermark_fired =
true;
374 exp_uart_irq_tx_done =
false;
375 uart_irq_tx_done_fired =
false;
377 bool uart_rx_done =
false;
378 size_t uart_rx_bytes_read = 0;
379 exp_uart_irq_rx_watermark =
true;
383 uart_irq_rx_watermark_fired =
true;
384 exp_uart_irq_rx_overflow =
false;
385 uart_irq_rx_overflow_fired =
false;
388 uint8_t uart_rx_data[UART_DATASET_SIZE];
391 while (!uart_tx_done || !uart_rx_done || !uart_irq_tx_done_fired ||
392 !uart_irq_rx_overflow_fired) {
393 if (!uart_tx_done && uart_irq_tx_watermark_fired) {
394 uart_irq_tx_watermark_fired =
false;
399 CHECK(uart_transfer_ongoing_bytes(
400 uart, kUartSend, (uint8_t *)kUartTxData, UART_DATASET_SIZE,
401 &uart_tx_bytes_written, 32, &uart_tx_done));
406 exp_uart_irq_tx_done =
true;
410 if (!uart_rx_done && uart_irq_rx_watermark_fired) {
411 uart_irq_rx_watermark_fired =
false;
417 CHECK(uart_transfer_ongoing_bytes(
418 uart, kUartReceive, uart_rx_data, UART_DATASET_SIZE,
419 &uart_rx_bytes_read, UART_DATASET_SIZE, &uart_rx_done));
420 }
while (!uart_rx_done && (UART_DATASET_SIZE - uart_rx_bytes_read < 16));
423 exp_uart_irq_rx_watermark =
false;
427 CHECK_DIF_OK(dif_uart_irq_set_enabled(uart, kDifUartIrqRxWatermark,
430 exp_uart_irq_rx_overflow =
true;
434 if (uart_irq_tx_done_fired) {
435 exp_uart_irq_tx_watermark =
false;
436 exp_uart_irq_tx_empty =
false;
437 exp_uart_irq_tx_done =
false;
439 CHECK(uart_irq_tx_empty_fired ==
true,
"TX empty interrupt did not fire");
442 if (uart_irq_rx_overflow_fired) {
443 exp_uart_irq_rx_overflow =
false;
451 if (!uart_irq_rx_watermark_fired && !uart_irq_tx_watermark_fired &&
452 !uart_irq_rx_overflow_fired) {
458 LOG_INFO(
"Checking the received UART RX data for consistency.");
459 for (
int i = 0; i < UART_DATASET_SIZE; ++i) {
460 CHECK(uart_rx_data[i] == kExpUartRxData[i],
461 "UART RX data[%d] mismatched: {act: %x, exp: %x}", i, uart_rx_data[i],
466 void config_external_clock(
const dif_clkmgr_t *clkmgr) {
470 CHECK_DIF_OK(dif_lc_ctrl_init(lc_ctrl_base_addr, &lc));
472 LOG_INFO(
"Read and check LC state.");
476 "LC State isn't in {kDifLcCtrlStateRma, kDifLcCtrlStateDev}!");
479 clkmgr_testutils_enable_external_clock_blocking(clkmgr, kUseLowSpeedSel));
482 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control =
true);
488 CHECK_DIF_OK(dif_clkmgr_init(base_addr, &clkmgr));
491 CHECK_DIF_OK(dif_pinmux_init(base_addr, &pinmux));
493 if (kUartIdxDv != 0xff) {
494 kUartIdx = kUartIdxDv;
496 OTTF_WAIT_FOR(kUartIdx != 0xff, kCommandTimeout);
506 if (kUartBaudrateDV) {
507 uartBaudrate = kUartBaudrateDV;
509 if (kUartClockFreqHzDV) {
510 uartFreqHz = kUartClockFreqHzDV;
512 CHECK(uartBaudrate <= UINT32_MAX,
"uartBaudrate must fit in uint32_t");
513 CHECK(uartFreqHz <= UINT32_MAX,
"uartFreqHz must fit in uint32_t");
518 uart_testutils_select_pinmux(&pinmux, 1, kUartPinmuxChannelConsole));
525 LOG_INFO(
"Test UART%d with base_addr: %08x", kUartIdx, uart_cfg.base_addr);
529 uart_testutils_select_pinmux(&pinmux, kUartIdx, kUartPinmuxChannelDut));
532 config_external_clock(&clkmgr);
534 CHECK_STATUS_OK(clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
535 &clkmgr,
false, kUseExtClk, kUseLowSpeedSel));
539 uart_init_with_irqs(chosen_uart_region, &uart, (uint32_t)uartBaudrate,
540 (uint32_t)uartFreqHz);
545 plic_init_with_irqs(plic_base_addr, &plic);
548 irq_global_ctrl(
true);
549 irq_external_ctrl(
true);
553 CHECK_STATUS_OK(clkmgr_testutils_check_measurement_counts(&clkmgr));