12 #include "sw/device/lib/runtime/irq.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
15 #include "sw/device/lib/testing/test_framework/ottf_console.h"
17 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
18 #include "sw/device/lib/testing/test_framework/status.h"
19 #include "sw/device/lib/testing/uart_testutils.h"
23 static dif_pinmux_t pinmux;
24 static dif_rv_plic_t rv_plic;
25 static dif_uart_t uart;
32 static volatile uint8_t parity = UINT8_MAX;
33 static volatile uint8_t uart_idx = UINT8_MAX;
39 static volatile bool uart_irq_rx_parity_err_expected =
false;
40 static volatile bool uart_irq_rx_parity_err_fired =
false;
42 static volatile bool uart_irq_rx_break_err_expected =
false;
43 static volatile bool uart_irq_rx_break_err_fired =
false;
47 kCommandTimeoutMicros = 5 * 1000 * 1000,
49 kParityErrTimeoutMicros = 1 * 1000 * 1000,
52 typedef enum test_phase {
58 kTestPhaseBreakErrDone,
60 static volatile uint8_t test_phase = kTestPhaseCfg;
63 static const uint8_t kUartData[32] = {
64 0x3f, 0x39, 0xb0, 0x4e, 0xa6, 0xce, 0xe5, 0xb7, 0x94, 0x48, 0xec,
65 0xb5, 0x48, 0x5c, 0x08, 0x5b, 0xcd, 0x47, 0xae, 0x80, 0xbb, 0x49,
66 0xa1, 0x7c, 0x39, 0x20, 0xd1, 0x6d, 0x2f, 0x4f, 0x94, 0xd8,
70 static status_t configure_uart(
void) {
81 .parity_enable = parity_enable,
87 TRY(uart_testutils_select_pinmux(&pinmux, uart_idx, kUartPinmuxChannelDut));
97 static status_t configure_interrupts(
void) {
98 TRY(dif_uart_irq_disable_all(&uart, NULL));
100 TRY(dif_uart_irq_set_enabled(&uart, kDifUartIrqRxParityErr,
102 TRY(dif_uart_irq_set_enabled(&uart, kDifUartIrqRxBreakErr,
121 irq_global_ctrl(
true);
122 irq_external_ctrl(
true);
132 void ottf_external_isr(uint32_t *exc_info) {
143 if (peripheral != uart_cfg.peripheral_id) {
144 ottf_console_flow_control_isr(exc_info);
148 uint32_t uart_irq_id = 0;
149 if (plic_irq_id == uart_cfg.irq_rx_parity_err_id) {
150 CHECK(uart_irq_rx_parity_err_expected,
"Unexpected parity error interrupt");
151 uart_irq_rx_parity_err_fired =
true;
152 uart_irq_id = kDifUartIrqRxParityErr;
153 }
else if (plic_irq_id == uart_cfg.irq_rx_break_err_id) {
154 CHECK(uart_irq_rx_break_err_expected,
"Unexpected break error interrupt");
155 uart_irq_rx_break_err_fired =
true;
156 uart_irq_id = kDifUartIrqRxBreakErr;
158 CHECK(
false,
"Unexpected interrupt from UART: %d", plic_irq_id);
163 CHECK_DIF_OK(dif_uart_irq_is_pending(&uart, uart_irq_id, &is_pending));
164 CHECK(is_pending,
"UART interrupt fired at PLIC did not fire at UART");
167 CHECK_DIF_OK(dif_uart_irq_acknowledge(&uart, uart_irq_id));
177 static status_t execute_test(
void) {
179 OTTF_WAIT_FOR(test_phase == kTestPhaseSend, kCommandTimeoutMicros);
181 size_t bytes_to_send =
ARRAYSIZE(kUartData);
182 uint8_t *send_buf = (uint8_t *)kUartData;
185 while (bytes_to_send > 0) {
186 size_t bytes_sent = 0;
188 bytes_to_send -= bytes_sent;
189 send_buf += bytes_sent;
193 OTTF_WAIT_FOR(test_phase == kTestPhaseRecv, kCommandTimeoutMicros);
195 size_t bytes_to_recv =
ARRAYSIZE(kUartData);
196 uint8_t recv_buf[
ARRAYSIZE(kUartData)] = {0};
197 uint8_t *recv_ptr = recv_buf;
199 LOG_INFO(
"Receiving data with correct parity...");
200 while (bytes_to_recv > 0) {
203 bytes_to_recv -= len;
207 TRY_CHECK_ARRAYS_EQ(recv_buf, kUartData,
ARRAYSIZE(kUartData));
213 uart_irq_rx_parity_err_expected =
true;
214 OTTF_WAIT_FOR(test_phase == kTestPhaseRecvErr, kCommandTimeoutMicros);
216 LOG_INFO(
"Receiving data with wrong parity");
217 ATOMIC_WAIT_FOR_INTERRUPT(uart_irq_rx_parity_err_fired);
222 kDifUartRxBreakLevel2,
223 kDifUartRxBreakLevel4,
224 kDifUartRxBreakLevel8,
225 kDifUartRxBreakLevel16,
228 for (
int i = 0; i <
ARRAYSIZE(break_levels); i++) {
232 uart_irq_rx_break_err_expected =
true;
233 OTTF_WAIT_FOR(test_phase == kTestPhaseBreakErr, kCommandTimeoutMicros);
236 ATOMIC_WAIT_FOR_INTERRUPT(uart_irq_rx_break_err_fired);
238 test_phase = kTestPhaseBreakErrDone;
244 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control =
true);
249 CHECK_DIF_OK(dif_pinmux_init(base_addr, &pinmux));
251 CHECK_DIF_OK(dif_rv_plic_init(base_addr, &rv_plic));
254 OTTF_WAIT_FOR(uart_idx != UINT8_MAX && parity != UINT8_MAX,
255 kCommandTimeoutMicros);
260 uart_testutils_select_pinmux(&pinmux, 1, kUartPinmuxChannelConsole));
265 CHECK_STATUS_OK(configure_uart());
266 CHECK_STATUS_OK(configure_interrupts());
268 LOG_INFO(
"UART%d configured", uart_idx);
272 return status_ok(result);