Software APIs
uart_loopback_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
9 #include "sw/device/lib/testing/test_framework/check.h"
10 #include "sw/device/lib/testing/test_framework/ottf_console.h"
12 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
13 #include "sw/device/lib/testing/uart_testutils.h"
14 
16 
17 static const uint8_t kSendData[] = "Loopback test!";
18 static const uint32_t kBaseAddrs[4] = {
23 };
24 enum {
25  kTestTimeoutMicros = 1000000,
26 };
27 
28 typedef enum test_phases {
29  kTestPhaseCfg,
30  kTestPhaseLine,
31  kTestPhaseSystem,
32  kTestPhaseDone,
33 } test_phase_t;
34 
35 static volatile uint8_t uart_idx = 0xff;
36 static volatile uint8_t test_phase = kTestPhaseCfg;
37 
38 static dif_uart_t uart;
39 static dif_pinmux_t pinmux;
40 
41 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
42 
43 bool test_main(void) {
44  mmio_region_t base_addr;
45 
46  // Wait for the testbench to set the `uart_idx`.
47  OTTF_WAIT_FOR(uart_idx != 0xff, kTestTimeoutMicros);
48 
50  CHECK_DIF_OK(dif_pinmux_init(base_addr, &pinmux));
51 
52  // If we're testing UART0 we need to move the console to UART1.
53  if (uart_idx == 0) {
54  CHECK_STATUS_OK(
55  uart_testutils_select_pinmux(&pinmux, 1, kUartPinmuxChannelConsole));
56  ottf_console_configure_uart(TOP_EARLGREY_UART1_BASE_ADDR);
57  }
58 
59  // Attach the UART under test to the DUT channel.
60  CHECK_STATUS_OK(
61  uart_testutils_select_pinmux(&pinmux, uart_idx, kUartPinmuxChannelDut));
62 
63  base_addr = mmio_region_from_addr(kBaseAddrs[uart_idx]);
64  CHECK_DIF_OK(dif_uart_init(base_addr, &uart));
65 
66  CHECK_DIF_OK(dif_uart_configure(
67  &uart, (dif_uart_config_t){
68  .baudrate = (uint32_t)kUartBaudrate,
69  .clk_freq_hz = (uint32_t)kClockFreqPeripheralHz,
70  .parity_enable = kDifToggleDisabled,
71  .parity = kDifUartParityEven,
72  .tx_enable = kDifToggleDisabled,
73  .rx_enable = kDifToggleDisabled,
74  }));
75 
76  LOG_INFO("UART%d configured", uart_idx);
77 
78  // First, enable the line loopback which echoes whatever is received to it.
79  // Enable the TX line once it's enabled.
80  CHECK_DIF_OK(
82  CHECK_DIF_OK(
84 
85  CHECK_DIF_OK(dif_uart_fifo_reset(&uart, kDifUartDatapathAll));
86 
87  OTTF_WAIT_FOR(test_phase == kTestPhaseLine, kTestTimeoutMicros);
88  LOG_INFO("Testing the line loopback");
89 
90  // Wait for the line test to be finished before configuring the UART for the
91  // system loopback.
92  OTTF_WAIT_FOR(test_phase == kTestPhaseSystem, kTestTimeoutMicros);
93  LOG_INFO("Testing the system loopback");
94 
95  CHECK_DIF_OK(
97  CHECK_DIF_OK(
99 
100  CHECK_DIF_OK(dif_uart_fifo_reset(&uart, kDifUartDatapathAll));
101 
102  for (int i = 0; i < sizeof(kSendData); ++i) {
103  CHECK_DIF_OK(dif_uart_byte_send_polled(&uart, kSendData[i]));
104 
105  uint8_t receive_byte;
106  CHECK_DIF_OK(dif_uart_byte_receive_polled(&uart, &receive_byte));
107  CHECK(kSendData[i] == receive_byte, "expected %c, got %c", kSendData[i],
108  receive_byte);
109  }
110 
111  test_phase = kTestPhaseDone;
112 
113  return true;
114 }