[dv/top] Test uart multiple instances
Pick a uart to test, backdoor modify memory to let SW test the
uart we pick.
Update pinmux to enable the other 3 uarts
Remove uart mon connection with scb, which is unused
Signed-off-by: Weicai Yang <weicai@google.com>
diff --git a/hw/top_earlgrey/data/chip_testplan.hjson b/hw/top_earlgrey/data/chip_testplan.hjson
index be2a800..a2ebdd1 100644
--- a/hw/top_earlgrey/data/chip_testplan.hjson
+++ b/hw/top_earlgrey/data/chip_testplan.hjson
@@ -45,7 +45,8 @@
on all UART ports across the instances.
'''
milestone: V1
- tests: ["chip_sw_uart_tx_rx"]
+ tests: ["chip_sw_uart_tx_rx", "chip_sw_uart_tx_rx_idx1", "chip_sw_uart_tx_rx_idx2",
+ "chip_sw_uart_tx_rx_idx3"]
}
{
name: chip_uart_tx_rx_alt_clk_freq
diff --git a/hw/top_earlgrey/dv/chip_sim_cfg.hjson b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
index 5ecdcc2..4b5e272 100644
--- a/hw/top_earlgrey/dv/chip_sim_cfg.hjson
+++ b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
@@ -166,6 +166,31 @@
uvm_test_seq: chip_sw_uart_tx_rx_vseq
sw_images: ["sw/device/tests/uart_tx_rx_test:1"]
en_run_modes: ["sw_test_mode"]
+ reseed: 10
+ }
+ {
+ name: chip_sw_uart_tx_rx_idx1
+ uvm_test_seq: chip_sw_uart_tx_rx_vseq
+ sw_images: ["sw/device/tests/uart_tx_rx_test:1"]
+ en_run_modes: ["sw_test_mode"]
+ run_opts: ["+uart_idx=1"]
+ reseed: 10
+ }
+ {
+ name: chip_sw_uart_tx_rx_idx2
+ uvm_test_seq: chip_sw_uart_tx_rx_vseq
+ sw_images: ["sw/device/tests/uart_tx_rx_test:1"]
+ en_run_modes: ["sw_test_mode"]
+ run_opts: ["+uart_idx=2"]
+ reseed: 10
+ }
+ {
+ name: chip_sw_uart_tx_rx_idx3
+ uvm_test_seq: chip_sw_uart_tx_rx_vseq
+ sw_images: ["sw/device/tests/uart_tx_rx_test:1"]
+ en_run_modes: ["sw_test_mode"]
+ run_opts: ["+uart_idx=3"]
+ reseed: 10
}
{
name: chip_sw_uart_tx_rx_bootstrap
diff --git a/hw/top_earlgrey/dv/env/chip_env.sv b/hw/top_earlgrey/dv/env/chip_env.sv
index 33b01f4..d9f2043 100644
--- a/hw/top_earlgrey/dv/env/chip_env.sv
+++ b/hw/top_earlgrey/dv/env/chip_env.sv
@@ -10,7 +10,7 @@
);
`uvm_component_utils(chip_env)
- uart_agent m_uart_agent;
+ uart_agent m_uart_agents[NUM_UARTS];
jtag_riscv_agent m_jtag_riscv_agent;
spi_agent m_spi_agent;
@@ -62,8 +62,11 @@
end
// create components
- m_uart_agent = uart_agent::type_id::create("m_uart_agent", this);
- uvm_config_db#(uart_agent_cfg)::set(this, "m_uart_agent*", "cfg", cfg.m_uart_agent_cfg);
+ foreach (m_uart_agents[i]) begin
+ m_uart_agents[i] = uart_agent::type_id::create($sformatf("m_uart_agent%0d", i), this);
+ uvm_config_db#(uart_agent_cfg)::set(this, $sformatf("m_uart_agent%0d*", i), "cfg",
+ cfg.m_uart_agent_cfgs[i]);
+ end
m_jtag_riscv_agent = jtag_riscv_agent::type_id::create("m_jtag_riscv_agent", this);
uvm_config_db#(jtag_riscv_agent_cfg)::set(this, "m_jtag_riscv_agent*", "cfg",
@@ -81,12 +84,12 @@
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
if (cfg.en_scb) begin
- m_uart_agent.monitor.tx_analysis_port.connect(scoreboard.uart_tx_fifo.analysis_export);
- m_uart_agent.monitor.rx_analysis_port.connect(scoreboard.uart_rx_fifo.analysis_export);
m_jtag_riscv_agent.monitor.analysis_port.connect(scoreboard.jtag_fifo.analysis_export);
end
- if (cfg.is_active && cfg.m_uart_agent_cfg.is_active) begin
- virtual_sequencer.uart_sequencer_h = m_uart_agent.sequencer;
+ foreach (m_uart_agents[i]) begin
+ if (cfg.is_active && cfg.m_uart_agent_cfgs[i].is_active) begin
+ virtual_sequencer.uart_sequencer_hs[i] = m_uart_agents[i].sequencer;
+ end
end
if (cfg.is_active && cfg.m_jtag_riscv_agent_cfg.is_active) begin
virtual_sequencer.jtag_sequencer_h = m_jtag_riscv_agent.sequencer;
@@ -96,7 +99,10 @@
end
// Connect the DUT's UART TX TLM port to the sequencer.
- m_uart_agent.monitor.tx_analysis_port.connect(virtual_sequencer.uart_tx_fifo.analysis_export);
+ foreach (m_uart_agents[i]) begin
+ m_uart_agents[i].monitor.tx_analysis_port.connect(
+ virtual_sequencer.uart_tx_fifos[i].analysis_export);
+ end
endfunction
virtual function void end_of_elaboration_phase(uvm_phase phase);
diff --git a/hw/top_earlgrey/dv/env/chip_env_cfg.sv b/hw/top_earlgrey/dv/env/chip_env_cfg.sv
index 89c5e33..10ba957 100644
--- a/hw/top_earlgrey/dv/env/chip_env_cfg.sv
+++ b/hw/top_earlgrey/dv/env/chip_env_cfg.sv
@@ -58,13 +58,12 @@
sw_test_status_vif sw_test_status_vif;
// ext component cfgs
- rand uart_agent_cfg m_uart_agent_cfg;
+ rand uart_agent_cfg m_uart_agent_cfgs[NUM_UARTS];
rand jtag_riscv_agent_cfg m_jtag_riscv_agent_cfg;
rand spi_agent_cfg m_spi_agent_cfg;
`uvm_object_utils_begin(chip_env_cfg)
`uvm_field_int (stub_cpu, UVM_DEFAULT)
- `uvm_field_object(m_uart_agent_cfg, UVM_DEFAULT)
`uvm_field_object(m_jtag_riscv_agent_cfg, UVM_DEFAULT)
`uvm_field_object(m_spi_agent_cfg, UVM_DEFAULT)
`uvm_object_utils_end
@@ -89,7 +88,9 @@
m_tl_agent_cfg.valid_a_source_width = 6;
// create uart agent config obj
- m_uart_agent_cfg = uart_agent_cfg::type_id::create("m_uart_agent_cfg");
+ foreach (m_uart_agent_cfgs[i]) begin
+ m_uart_agent_cfgs[i] = uart_agent_cfg::type_id::create($sformatf("m_uart_agent_cfg%0d", i));
+ end
// create jtag agent config obj
m_jtag_riscv_agent_cfg = jtag_riscv_agent_cfg::type_id::create("m_jtag_riscv_agent_cfg");
diff --git a/hw/top_earlgrey/dv/env/chip_env_pkg.sv b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
index 72b7c6b..427ed49 100644
--- a/hw/top_earlgrey/dv/env/chip_env_pkg.sv
+++ b/hw/top_earlgrey/dv/env/chip_env_pkg.sv
@@ -34,6 +34,7 @@
// local parameters and types
parameter uint NUM_GPIOS = 16;
+ parameter uint NUM_UARTS = 4;
// Buffer is half of SPI_DEVICE Dual Port SRAM
parameter uint SPI_FRAME_BYTE_SIZE = spi_device_reg_pkg::SPI_DEVICE_BUFFER_SIZE/2;
diff --git a/hw/top_earlgrey/dv/env/chip_scoreboard.sv b/hw/top_earlgrey/dv/env/chip_scoreboard.sv
index c3078ef..22a2df8 100644
--- a/hw/top_earlgrey/dv/env/chip_scoreboard.sv
+++ b/hw/top_earlgrey/dv/env/chip_scoreboard.sv
@@ -12,8 +12,6 @@
// local variables
// TLM agent fifos
- uvm_tlm_analysis_fifo #(uart_item) uart_tx_fifo;
- uvm_tlm_analysis_fifo #(uart_item) uart_rx_fifo;
uvm_tlm_analysis_fifo #(jtag_riscv_item) jtag_fifo;
// local queues to hold incoming packets pending comparison
@@ -25,8 +23,6 @@
function void build_phase(uvm_phase phase);
super.build_phase(phase);
- uart_tx_fifo = new("uart_tx_fifo", this);
- uart_rx_fifo = new("uart_rx_fifo", this);
jtag_fifo = new("jtag_fifo", this);
endfunction
diff --git a/hw/top_earlgrey/dv/env/chip_virtual_sequencer.sv b/hw/top_earlgrey/dv/env/chip_virtual_sequencer.sv
index cf5e17e..9c4bfad 100644
--- a/hw/top_earlgrey/dv/env/chip_virtual_sequencer.sv
+++ b/hw/top_earlgrey/dv/env/chip_virtual_sequencer.sv
@@ -8,18 +8,18 @@
);
`uvm_component_utils(chip_virtual_sequencer)
- uart_sequencer uart_sequencer_h;
+ uart_sequencer uart_sequencer_hs[NUM_UARTS];
jtag_riscv_sequencer jtag_sequencer_h;
spi_sequencer spi_sequencer_h;
// Grab packets from UART TX port for in-sequence checking.
- uvm_tlm_analysis_fifo #(uart_item) uart_tx_fifo;
+ uvm_tlm_analysis_fifo #(uart_item) uart_tx_fifos[NUM_UARTS];
`uvm_component_new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
- uart_tx_fifo = new("uart_tx_fifo", this);
+ foreach (uart_tx_fifos[i]) uart_tx_fifos[i] = new($sformatf("uart_tx_fifo%0d", i), this);
endfunction
endclass
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv
index 782b83c..765085c 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_base_vseq.sv
@@ -80,10 +80,10 @@
endtask
// Grab packets sent by the DUT over the UART TX port.
- virtual task get_uart_tx_items();
+ virtual task get_uart_tx_items(int uart_idx = 0);
uart_item item;
forever begin
- p_sequencer.uart_tx_fifo.get(item);
+ p_sequencer.uart_tx_fifos[uart_idx].get(item);
`uvm_info(`gfn, $sformatf("Received UART data over TX:\n%0h", item.data), UVM_HIGH)
uart_tx_data_q.push_back(item.data);
end
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_stub_cpu_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_stub_cpu_base_vseq.sv
index 8945824..3997ced 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_stub_cpu_base_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_stub_cpu_base_vseq.sv
@@ -19,9 +19,10 @@
// In top-level uart RX pin may be selected in pinmux. CSR tests may randomly enable line
// loopback, which will connect TX with RX. If RX isn't enabled in pinmux, it will be 0.
// moniter will start to check the TX data when it changes from 1 to 0. But the length of 0 may
- // be not right in CSR test.
- // In block-level, we always ties RX to 1 (idle) in CSR test. No need to disable the monitor
- cfg.m_uart_agent_cfg.en_tx_monitor = 0;
+ // be not right in CSR test, which causes a protocal error on TX
+ // In block-level, we always tie RX to 1 (idle) in CSR test so that we don't need to disable TX
+ // monitor in block-level
+ foreach (cfg.m_uart_agent_cfgs[i]) cfg.m_uart_agent_cfgs[i].en_tx_monitor = 0;
endtask
task post_start();
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv
index 8707f9b..4206cb9 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv
@@ -17,8 +17,10 @@
// Backdoor load the sw test image, setup UART, logger and test status interfaces.
virtual task cpu_init();
// TODO: Fixing this for now - need to find a way to pass this on to the SW test.
- cfg.m_uart_agent_cfg.set_parity(1'b0, 1'b0);
- cfg.m_uart_agent_cfg.set_baud_rate(cfg.uart_baud_rate);
+ foreach (cfg.m_uart_agent_cfgs[i]) begin
+ cfg.m_uart_agent_cfgs[i].set_parity(1'b0, 1'b0);
+ cfg.m_uart_agent_cfgs[i].set_baud_rate(cfg.uart_baud_rate);
+ end
// initialize the sw logger interface
foreach (cfg.sw_images[i]) begin
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_uart_tx_rx_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_uart_tx_rx_vseq.sv
index 188f826..dc4e08d 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_uart_tx_rx_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_uart_tx_rx_vseq.sv
@@ -22,17 +22,29 @@
uart_rx_data.size() == UART_DATASET_SIZE;
}
+ byte uart_idx = 0;
+
+ task pre_start();
+ void'($value$plusargs("uart_idx=%0d", uart_idx));
+ `DV_CHECK_LT(uart_idx, NUM_UARTS)
+ super.pre_start();
+ endtask
+
virtual task cpu_init();
+ // sw_symbol_backdoor_overwrite takes an array as the input
+ byte uart_idx_data[] = {uart_idx};
+
super.cpu_init();
- sw_symbol_backdoor_overwrite("uart_tx_data", exp_uart_tx_data);
- sw_symbol_backdoor_overwrite("exp_uart_rx_data", uart_rx_data);
+ sw_symbol_backdoor_overwrite("kUartTxData", exp_uart_tx_data);
+ sw_symbol_backdoor_overwrite("kExpUartRxData", uart_rx_data);
+ sw_symbol_backdoor_overwrite("kUartIdx", uart_idx_data);
endtask
virtual task body();
super.body();
// Spawn off a thread to retrieve UART TX items.
- fork get_uart_tx_items(); join_none
+ fork get_uart_tx_items(uart_idx); join_none
// Wait until we receive at least 1 byte from the DUT (SW test).
wait(uart_tx_data_q.size() > 0);
@@ -56,7 +68,7 @@
// Send data over RX.
virtual task send_uart_rx_data(int size = -1, bit random = 0);
uart_default_seq send_rx_seq;
- `uvm_create_on(send_rx_seq, p_sequencer.uart_sequencer_h);
+ `uvm_create_on(send_rx_seq, p_sequencer.uart_sequencer_hs[uart_idx]);
if (size == -1) size = uart_rx_data.size();
for (int i = 0; i < size; i++) begin
byte rx_data = random ? $urandom : uart_rx_data[i];
diff --git a/hw/top_earlgrey/dv/tb/tb.sv b/hw/top_earlgrey/dv/tb/tb.sv
index ce96884..9e99edb 100644
--- a/hw/top_earlgrey/dv/tb/tb.sv
+++ b/hw/top_earlgrey/dv/tb/tb.sv
@@ -40,7 +40,7 @@
wire usb_dp0, usb_dn0, usb_sense0, usb_dppullup0, usb_dnpullup0;
- wire uart_rx, uart_tx;
+ wire uart_rx[NUM_UARTS], uart_tx[NUM_UARTS];
bit stub_cpu;
bit en_sim_sram = 1'b1;
@@ -62,7 +62,7 @@
pins_if #(1) rst_n_mon_if(.pins(cpu_rst_n));
spi_if spi_if(.rst_n);
tl_if cpu_d_tl_if(.clk(cpu_clk), .rst_n(cpu_rst_n));
- uart_if uart_if();
+ uart_if uart_if[NUM_UARTS-1:0]();
jtag_if jtag_if();
// TODO: Replace with correct interfaces once
@@ -129,8 +129,8 @@
.IOC7(tie_off[7]), // MIO 29
.IOC8(tap_straps[0]), // MIO 30
.IOC9(tie_off[8]), // MIO 31
- .IOC10(uart_rx), // MIO 32
- .IOC11(uart_tx), // MIO 33
+ .IOC10(uart_rx[0]), // MIO 32
+ .IOC11(uart_tx[0]), // MIO 33
.IOC12(tie_off[9]), // MIO 34
// Bank R (VCC domain)
.IOR0(jtag_tms), // MIO 35
@@ -138,14 +138,14 @@
.IOR2(jtag_tdi), // MIO 37
.IOR3(jtag_tck), // MIO 38
.IOR4(jtag_trst_n), // MIO 39
- .IOR5(tie_off[10]), // MIO 40
- .IOR6(tie_off[11]), // MIO 41
- .IOR7(tie_off[12]), // MIO 42
- .IOR8(tie_off[13]), // MIO 43
- .IOR9(tie_off[14]), // MIO 44
- .IOR10(tie_off[15]), // MIO 45
- .IOR11(tie_off[16]), // MIO 46
- .IOR12(tie_off[17]), // MIO 47
+ .IOR5(uart_rx[1]), // MIO 40
+ .IOR6(uart_tx[1]), // MIO 41
+ .IOR7(uart_rx[2]), // MIO 42
+ .IOR8(tie_off[13]), // MIO 43, Dedicated sysrst_ctrl output (ec_rst_l)
+ .IOR9(tie_off[14]), // MIO 44, Dedicated sysrst_ctrl output (pwrb_out)
+ .IOR10(uart_tx[2]), // MIO 45
+ .IOR11(uart_rx[3]), // MIO 46
+ .IOR12(uart_tx[3]), // MIO 47
.IOR13(tie_off[18]), // MIO 48
// DCD (VCC domain)
.CC1(tie_off[19]),
@@ -180,13 +180,6 @@
assign spi_device_sdi_i = spi_if.sio[0];
assign spi_if.sio[1] = spi_device_sdo_o;
- // TODO: Replace this weak pull to a known value with initialization
- // in the agent/interface.
- assign (weak0, weak1) uart_rx = 1'b1;
- assign (weak0, weak1) uart_tx = 1'b1;
- assign uart_rx = uart_if.uart_rx;
- assign uart_if.uart_tx = uart_tx;
-
// TODO: USB-related signals, hookup an interface.
assign usb_rst_n = `USBDEV_HIER.rst_usb_48mhz_ni;
assign usb_dp0 = 1'b1;
@@ -248,7 +241,6 @@
// IO Interfaces
uvm_config_db#(virtual pins_if #(NUM_GPIOS))::set(null, "*.env", "gpio_vif", gpio_if);
- uvm_config_db#(virtual uart_if)::set(null, "*.env.m_uart_agent*", "vif", uart_if);
uvm_config_db#(virtual jtag_if)::set(null, "*.env.m_jtag_riscv_agent*", "vif", jtag_if);
uvm_config_db#(virtual spi_if)::set(null, "*.env.m_spi_agent*", "vif", spi_if);
uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", cpu_d_tl_if);
@@ -278,6 +270,19 @@
run_test();
end
+ for (genvar i = 0; i < NUM_UARTS; i++) begin : gen_uart_if
+ // TODO: Replace this weak pull to a known value with initialization
+ // in the agent/interface.
+ assign (weak0, weak1) uart_rx[i] = 1'b1;
+ assign (weak0, weak1) uart_tx[i] = 1'b1;
+ assign uart_rx[i] = uart_if[i].uart_rx;
+ assign uart_if[i].uart_tx = uart_tx[i];
+
+ initial begin
+ uvm_config_db#(virtual uart_if)::set(null, $sformatf("*.env.m_uart_agent%0d*", i),
+ "vif", uart_if[i]);
+ end
+ end
`undef SIM_SRAM_IF
// Instantitate the memory backdoor util instances.
diff --git a/hw/top_earlgrey/dv/tests/chip_base_test.sv b/hw/top_earlgrey/dv/tests/chip_base_test.sv
index 1da340b..e3aa51b 100644
--- a/hw/top_earlgrey/dv/tests/chip_base_test.sv
+++ b/hw/top_earlgrey/dv/tests/chip_base_test.sv
@@ -38,8 +38,8 @@
// Knob to enable logging over UART (disabled by default).
void'($value$plusargs("en_uart_logger=%0b", cfg.en_uart_logger));
- cfg.m_uart_agent_cfg.en_logger = cfg.en_uart_logger;
- cfg.m_uart_agent_cfg.write_logs_to_file = cfg.write_sw_logs_to_file;
+ cfg.m_uart_agent_cfgs[0].en_logger = cfg.en_uart_logger;
+ cfg.m_uart_agent_cfgs[0].write_logs_to_file = cfg.write_sw_logs_to_file;
// Knob to set the sw_test_timeout_ns (set to 5ms by default).
void'($value$plusargs("sw_test_timeout_ns=%0d", cfg.sw_test_timeout_ns));
diff --git a/sw/device/tests/sim_dv/meson.build b/sw/device/tests/sim_dv/meson.build
index 636b8e2..b45ed9c 100644
--- a/sw/device/tests/sim_dv/meson.build
+++ b/sw/device/tests/sim_dv/meson.build
@@ -5,7 +5,10 @@
uart_tx_rx_test_lib = declare_dependency(
link_with: static_library(
'uart_tx_rx_test_lib',
- sources: ['uart_tx_rx_test.c'],
+ sources: [
+ # TODO, remove it once pinout configuration is provided
+ hw_top_earlgrey_pinmux_reg_h,
+ 'uart_tx_rx_test.c'],
dependencies: [
sw_lib_dif_uart,
sw_lib_dif_plic,
diff --git a/sw/device/tests/sim_dv/uart_tx_rx_test.c b/sw/device/tests/sim_dv/uart_tx_rx_test.c
index f5b6b17..23168eb 100644
--- a/sw/device/tests/sim_dv/uart_tx_rx_test.c
+++ b/sw/device/tests/sim_dv/uart_tx_rx_test.c
@@ -16,6 +16,9 @@
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
+// TODO, remove it once pinout configuration is provided
+#include "pinmux_regs.h"
+
#define UART_DATASET_SIZE 128
static dif_uart_t uart;
@@ -48,10 +51,22 @@
kUartReceive,
} uart_direction_t;
-// TODO: Make these datasets random.
+/**
+ * Indicates the UART instance under test.
+ *
+ * From the software / compiler's perspective, this is a constant (hence the
+ * `const` qualifier). However, the external DV testbench finds this symbol's
+ * address and modifies it via backdoor, to test a different UART instance with
+ * the same test SW image. Hence, we add the `volatile` keyword to prevent the
+ * compiler from optimizing it out.
+ * The `const` is needed to put it in the .rodata section, otherwise it gets
+ * placed in .data section in the main SRAM. We cannot backdoor write anything
+ * in SRAM at the start of the test because the CRT init code wipes it to 0s.
+ */
+static volatile const uint8_t kUartIdx = 0x0;
// A set of bytes to be send out of TX.
-static const uint8_t uart_tx_data[UART_DATASET_SIZE] = {
+static const uint8_t kUartTxData[UART_DATASET_SIZE] = {
0xe8, 0x50, 0xc6, 0xb4, 0xbe, 0x16, 0xed, 0x55, 0x16, 0x1d, 0xe6, 0x1c,
0xde, 0x9f, 0xfd, 0x24, 0x89, 0x81, 0x4d, 0x0d, 0x1a, 0x12, 0x4f, 0x57,
0xea, 0xd6, 0x6f, 0xc0, 0x7d, 0x46, 0xe7, 0x37, 0x81, 0xd3, 0x8e, 0x16,
@@ -66,7 +81,7 @@
};
// The set of bytes expected to be received over RX.
-static const uint8_t exp_uart_rx_data[UART_DATASET_SIZE] = {
+static const uint8_t kExpUartRxData[UART_DATASET_SIZE] = {
0x1b, 0x95, 0xc5, 0xb5, 0x8a, 0xa4, 0xa8, 0x9f, 0x6a, 0x7d, 0x6b, 0x0c,
0xcd, 0xd5, 0xa6, 0x8f, 0x07, 0x3a, 0x9e, 0x82, 0xe6, 0xa2, 0x2b, 0xe0,
0x0c, 0x30, 0xe8, 0x5a, 0x05, 0x14, 0x79, 0x8a, 0xFf, 0x88, 0x29, 0xda,
@@ -80,9 +95,25 @@
0xc7, 0x33, 0xd1, 0x6a, 0xc7, 0xba, 0x78, 0x69,
};
-// Set our expectation & event indications of the interrupts we intend to
-// exercise in this test. These are declared volatile since they are used by the
-// interrupt handler.
+// There are multiple uart instances in the chip. These variables will be
+// updated according to the uart we select.
+static volatile uint32_t uart_base_addr;
+static volatile uint32_t uart_peripheral_id;
+static volatile uint32_t uart_irq_tx_watermartk_id;
+static volatile uint32_t uart_irq_rx_watermartk_id;
+static volatile uint32_t uart_irq_tx_empty_id;
+static volatile uint32_t uart_irq_rx_overflow_id;
+static volatile uint32_t uart_irq_rx_frame_err_id;
+static volatile uint32_t uart_irq_rx_frame_err_id;
+static volatile uint32_t uart_irq_rx_break_err_id;
+static volatile uint32_t uart_irq_rx_timeout_id;
+static volatile uint32_t uart_irq_rx_parity_err_id;
+
+/**
+ * Set our expectation & event indications of the interrupts we intend to
+ * exercise in this test. These are declared volatile since they are used by the
+ * interrupt handler.
+ */
static volatile bool exp_uart_irq_tx_watermark;
static volatile bool uart_irq_tx_watermark_fired;
static volatile bool exp_uart_irq_rx_watermark;
@@ -92,6 +123,95 @@
static volatile bool exp_uart_irq_rx_overflow;
static volatile bool uart_irq_rx_overflow_fired;
+// Configures the pinmux to connect the UART instance to chip IOs based on the
+// ChromeOS pinout configuration.
+//
+// The pinout configuration is documented here:
+// https://github.com/lowRISC/opentitan/blob/master/hw/top_earlgrey/data/top_earlgrey.hjson
+// TODO: Pinout configuration APIs based on customer usecases will be
+// auto-generated in future. This function is a stop-gap solution until that is
+// made available.
+static void pinmux_connect_uart_to_pads(uint32_t rx_pin_in_idx,
+ uint32_t rx_uart_idx,
+ uint32_t tx_pin_out_idx,
+ uint32_t tx_uart_idx) {
+ mmio_region_t reg32 = mmio_region_from_addr(
+ TOP_EARLGREY_PINMUX_AON_BASE_ADDR + PINMUX_MIO_PERIPH_INSEL_0_REG_OFFSET);
+ uint32_t reg_value = rx_pin_in_idx;
+ // We've got one insel configuration field per register. Hence, we have to
+ // convert the enumeration index into a byte address using << 2.
+ uint32_t reg_offset = rx_uart_idx << 2;
+ uint32_t mask = PINMUX_MIO_PERIPH_INSEL_0_IN_0_MASK;
+ mmio_region_write32(reg32, reg_offset, reg_value & mask);
+
+ reg32 = mmio_region_from_addr(TOP_EARLGREY_PINMUX_AON_BASE_ADDR +
+ PINMUX_MIO_OUTSEL_0_REG_OFFSET);
+ reg_value = tx_uart_idx;
+ // We've got one insel configuration field per register. Hence, we have to
+ // convert the enumeration index into a byte address using << 2.
+ reg_offset = tx_pin_out_idx << 2;
+ mask = PINMUX_MIO_OUTSEL_0_OUT_0_MASK;
+ mmio_region_write32(reg32, reg_offset, reg_value & mask);
+}
+
+void update_uart_base_addr_and_irq_id(void) {
+ switch (kUartIdx) {
+ case 0:
+ uart_base_addr = TOP_EARLGREY_UART0_BASE_ADDR;
+ uart_peripheral_id = kTopEarlgreyPlicPeripheralUart0;
+ uart_irq_tx_watermartk_id = kTopEarlgreyPlicIrqIdUart0TxWatermark;
+ uart_irq_rx_watermartk_id = kTopEarlgreyPlicIrqIdUart0RxWatermark;
+ uart_irq_tx_empty_id = kTopEarlgreyPlicIrqIdUart0TxEmpty;
+ uart_irq_rx_overflow_id = kTopEarlgreyPlicIrqIdUart0RxOverflow;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart0RxFrameErr;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart0RxFrameErr;
+ uart_irq_rx_break_err_id = kTopEarlgreyPlicIrqIdUart0RxBreakErr;
+ uart_irq_rx_timeout_id = kTopEarlgreyPlicIrqIdUart0RxTimeout;
+ uart_irq_rx_parity_err_id = kTopEarlgreyPlicIrqIdUart0RxParityErr;
+ break;
+ case 1:
+ uart_base_addr = TOP_EARLGREY_UART1_BASE_ADDR;
+ uart_peripheral_id = kTopEarlgreyPlicPeripheralUart1;
+ uart_irq_tx_watermartk_id = kTopEarlgreyPlicIrqIdUart1TxWatermark;
+ uart_irq_rx_watermartk_id = kTopEarlgreyPlicIrqIdUart1RxWatermark;
+ uart_irq_tx_empty_id = kTopEarlgreyPlicIrqIdUart1TxEmpty;
+ uart_irq_rx_overflow_id = kTopEarlgreyPlicIrqIdUart1RxOverflow;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart1RxFrameErr;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart1RxFrameErr;
+ uart_irq_rx_break_err_id = kTopEarlgreyPlicIrqIdUart1RxBreakErr;
+ uart_irq_rx_timeout_id = kTopEarlgreyPlicIrqIdUart1RxTimeout;
+ uart_irq_rx_parity_err_id = kTopEarlgreyPlicIrqIdUart1RxParityErr;
+ break;
+ case 2:
+ uart_base_addr = TOP_EARLGREY_UART2_BASE_ADDR;
+ uart_peripheral_id = kTopEarlgreyPlicPeripheralUart2;
+ uart_irq_tx_watermartk_id = kTopEarlgreyPlicIrqIdUart2TxWatermark;
+ uart_irq_rx_watermartk_id = kTopEarlgreyPlicIrqIdUart2RxWatermark;
+ uart_irq_tx_empty_id = kTopEarlgreyPlicIrqIdUart2TxEmpty;
+ uart_irq_rx_overflow_id = kTopEarlgreyPlicIrqIdUart2RxOverflow;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart2RxFrameErr;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart2RxFrameErr;
+ uart_irq_rx_break_err_id = kTopEarlgreyPlicIrqIdUart2RxBreakErr;
+ uart_irq_rx_timeout_id = kTopEarlgreyPlicIrqIdUart2RxTimeout;
+ uart_irq_rx_parity_err_id = kTopEarlgreyPlicIrqIdUart2RxParityErr;
+ break;
+ case 3:
+ uart_base_addr = TOP_EARLGREY_UART3_BASE_ADDR;
+ uart_peripheral_id = kTopEarlgreyPlicPeripheralUart3;
+ uart_irq_tx_watermartk_id = kTopEarlgreyPlicIrqIdUart3TxWatermark;
+ uart_irq_rx_watermartk_id = kTopEarlgreyPlicIrqIdUart3RxWatermark;
+ uart_irq_tx_empty_id = kTopEarlgreyPlicIrqIdUart3TxEmpty;
+ uart_irq_rx_overflow_id = kTopEarlgreyPlicIrqIdUart3RxOverflow;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart3RxFrameErr;
+ uart_irq_rx_frame_err_id = kTopEarlgreyPlicIrqIdUart3RxFrameErr;
+ uart_irq_rx_break_err_id = kTopEarlgreyPlicIrqIdUart3RxBreakErr;
+ uart_irq_rx_timeout_id = kTopEarlgreyPlicIrqIdUart3RxTimeout;
+ uart_irq_rx_parity_err_id = kTopEarlgreyPlicIrqIdUart3RxParityErr;
+ break;
+ default:
+ LOG_FATAL("Unsupported uart ID %x", kUartIdx);
+ }
+}
/**
* Provides external irq handling for this test.
*
@@ -108,39 +228,34 @@
// Check if it is the right peripheral.
top_earlgrey_plic_peripheral_t peripheral = (top_earlgrey_plic_peripheral_t)
top_earlgrey_plic_interrupt_for_peripheral[plic_irq_id];
- CHECK(peripheral == kTopEarlgreyPlicPeripheralUart0,
+ CHECK(peripheral == uart_peripheral_id,
"Interurpt from unexpected peripheral: %d", peripheral);
// Correlate the interrupt fired at PLIC with UART.
dif_uart_irq_t uart_irq;
- switch (plic_irq_id) {
- case kTopEarlgreyPlicIrqIdUart0TxWatermark:
- CHECK(exp_uart_irq_tx_watermark, "Unexpected TX watermark interrupt");
- uart_irq_tx_watermark_fired = true;
- uart_irq = kDifUartIrqTxWatermark;
- break;
- case kTopEarlgreyPlicIrqIdUart0RxWatermark:
- CHECK(exp_uart_irq_rx_watermark, "Unexpected RX watermark interrupt");
- uart_irq_rx_watermark_fired = true;
- uart_irq = kDifUartIrqRxWatermark;
- break;
- case kTopEarlgreyPlicIrqIdUart0TxEmpty:
- CHECK(exp_uart_irq_tx_empty, "Unexpected TX empty interrupt");
- uart_irq_tx_empty_fired = true;
- uart_irq = kDifUartIrqTxEmpty;
- break;
- case kTopEarlgreyPlicIrqIdUart0RxOverflow:
- CHECK(exp_uart_irq_rx_overflow, "Unexpected RX overflow interrupt");
- uart_irq_rx_overflow_fired = true;
- uart_irq = kDifUartIrqRxOverflow;
- break;
- default:
- LOG_ERROR("Unexpected interrupt (at PLIC): %d", plic_irq_id);
- test_status_set(kTestStatusFailed);
- // The `abort()` call below is redundant. It is added to prevent the
- // compilation error due to not initializing the `uart_irq` enum variable
- // above. See issue #2157 for moe details.
- abort();
+ if (plic_irq_id == uart_irq_tx_watermartk_id) {
+ CHECK(exp_uart_irq_tx_watermark, "Unexpected TX watermark interrupt");
+ uart_irq_tx_watermark_fired = true;
+ uart_irq = kDifUartIrqTxWatermark;
+ } else if (plic_irq_id == uart_irq_rx_watermartk_id) {
+ CHECK(exp_uart_irq_rx_watermark, "Unexpected RX watermark interrupt");
+ uart_irq_rx_watermark_fired = true;
+ uart_irq = kDifUartIrqRxWatermark;
+ } else if (plic_irq_id == uart_irq_tx_empty_id) {
+ CHECK(exp_uart_irq_tx_empty, "Unexpected TX empty interrupt");
+ uart_irq_tx_empty_fired = true;
+ uart_irq = kDifUartIrqTxEmpty;
+ } else if (plic_irq_id == uart_irq_rx_overflow_id) {
+ CHECK(exp_uart_irq_rx_overflow, "Unexpected RX overflow interrupt");
+ uart_irq_rx_overflow_fired = true;
+ uart_irq = kDifUartIrqRxOverflow;
+ } else {
+ LOG_ERROR("Unexpected interrupt (at PLIC): %d", plic_irq_id);
+ test_status_set(kTestStatusFailed);
+ // The `abort()` call below is redundant. It is added to prevent the
+ // compilation error due to not initializing the `uart_irq` enum variable
+ // above. See issue #2157 for moe details.
+ abort();
}
// Check if the same interrupt fired at UART as well.
@@ -205,63 +320,63 @@
* Initializes PLIC and enables the relevant UART interrupts.
*/
static void plic_init_with_irqs(mmio_region_t base_addr, dif_plic_t *plic) {
- LOG_INFO("Initializing the PLIC.");
+ LOG_INFO("Initializing the PLIC. %0x", uart_irq_tx_watermartk_id);
CHECK(dif_plic_init((dif_plic_params_t){.base_addr = base_addr}, plic) ==
kDifPlicOk,
"dif_plic_init failed");
// Enable UART interrupts at PLIC as edge triggered.
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0TxWatermark,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_tx_watermartk_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0RxWatermark,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_rx_watermartk_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0TxEmpty,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_tx_empty_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0RxOverflow,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_rx_overflow_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0RxFrameErr,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_rx_frame_err_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0RxBreakErr,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_rx_break_err_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0RxTimeout,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_rx_timeout_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
- CHECK(dif_plic_irq_set_trigger(plic, kTopEarlgreyPlicIrqIdUart0RxParityErr,
+ CHECK(dif_plic_irq_set_trigger(plic, uart_irq_rx_parity_err_id,
kDifPlicIrqTriggerEdge) == kDifPlicOk,
"dif_plic_irq_set_trigger failed");
// Set the priority of UART interrupts at PLIC to be >=1 (so ensure the target
// does get interrupted).
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0TxWatermark,
- 0x1) == kDifPlicOk,
+ CHECK(dif_plic_irq_set_priority(plic, uart_irq_tx_watermartk_id, 0x1) ==
+ kDifPlicOk,
"dif_plic_irq_set_priority failed");
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0RxWatermark,
- 0x2) == kDifPlicOk,
+ CHECK(dif_plic_irq_set_priority(plic, uart_irq_rx_watermartk_id, 0x2) ==
+ kDifPlicOk,
"dif_plic_irq_set_priority failed");
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0TxEmpty,
- 0x3) == kDifPlicOk,
- , "dif_plic_irq_set_priority failed");
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0RxOverflow,
- 0x1) == kDifPlicOk,
+ CHECK(
+ dif_plic_irq_set_priority(plic, uart_irq_tx_empty_id, 0x3) == kDifPlicOk,
+ , "dif_plic_irq_set_priority failed");
+ CHECK(dif_plic_irq_set_priority(plic, uart_irq_rx_overflow_id, 0x1) ==
+ kDifPlicOk,
"dif_plic_irq_set_priority failed");
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0RxFrameErr,
- 0x2) == kDifPlicOk,
+ CHECK(dif_plic_irq_set_priority(plic, uart_irq_rx_frame_err_id, 0x2) ==
+ kDifPlicOk,
"dif_plic_irq_set_priority failed");
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0RxBreakErr,
- 0x3) == kDifPlicOk,
+ CHECK(dif_plic_irq_set_priority(plic, uart_irq_rx_break_err_id, 0x3) ==
+ kDifPlicOk,
"dif_plic_irq_set_priority failed");
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0RxTimeout,
- 0x1) == kDifPlicOk,
+ CHECK(dif_plic_irq_set_priority(plic, uart_irq_rx_timeout_id, 0x1) ==
+ kDifPlicOk,
"dif_plic_irq_set_priority failed");
- CHECK(dif_plic_irq_set_priority(plic, kTopEarlgreyPlicIrqIdUart0RxParityErr,
- 0x2) == kDifPlicOk,
+ CHECK(dif_plic_irq_set_priority(plic, uart_irq_rx_parity_err_id, 0x2) ==
+ kDifPlicOk,
"dif_plic_irq_set_priority failed");
// Set the threshold for the Ibex to 0.
@@ -270,42 +385,42 @@
"dif_plic_target_set_threshold failed");
// Enable all UART interrupts at the PLIC.
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0TxWatermark,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_tx_watermartk_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0RxWatermark,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_rx_watermartk_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0TxEmpty,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_tx_empty_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0RxOverflow,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_rx_overflow_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0RxFrameErr,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_rx_frame_err_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0RxBreakErr,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_rx_break_err_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0RxTimeout,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_rx_timeout_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
- CHECK(dif_plic_irq_set_enabled(plic, kTopEarlgreyPlicIrqIdUart0RxParityErr,
+ CHECK(dif_plic_irq_set_enabled(plic, uart_irq_rx_parity_err_id,
kTopEarlgreyPlicTargetIbex0,
kDifPlicToggleEnabled) == kDifPlicOk,
"dif_plic_irq_set_enabled failed");
@@ -378,10 +493,10 @@
if (!uart_tx_done && uart_irq_tx_watermark_fired) {
uart_irq_tx_watermark_fired = false;
- // Send the remaining uart_tx_data as and when the TX watermark fires.
- CHECK(uart_transfer_ongoing_bytes(
- uart, kUartSend, (uint8_t *)uart_tx_data, UART_DATASET_SIZE,
- &uart_tx_bytes_written, &uart_tx_done));
+ // Send the remaining kUartTxData as and when the TX watermark fires.
+ CHECK(uart_transfer_ongoing_bytes(uart, kUartSend, (uint8_t *)kUartTxData,
+ UART_DATASET_SIZE,
+ &uart_tx_bytes_written, &uart_tx_done));
if (uart_tx_done) {
// At this point, we have sent the required number of bytes.
@@ -432,9 +547,9 @@
// Check data consistency.
LOG_INFO("Checking the received UART RX data for consistency.");
for (int i = 0; i < UART_DATASET_SIZE; ++i) {
- CHECK(uart_rx_data[i] == exp_uart_rx_data[i],
+ CHECK(uart_rx_data[i] == kExpUartRxData[i],
"UART RX data[%0d] mismatched: {act: %x, exp: %x}", i,
- uart_rx_data[i], exp_uart_rx_data[i]);
+ uart_rx_data[i], kExpUartRxData[i]);
}
// If we reached here, then the test passed.
@@ -444,12 +559,27 @@
const test_config_t kTestConfig;
bool test_main(void) {
- LOG_INFO("UART TX RX test");
+ update_uart_base_addr_and_irq_id();
+
+ LOG_INFO("Test UART%d with base_addr: %8x", kUartIdx, uart_base_addr);
+
+ // TODO, remove thse once pinout configuration is provided
+ pinmux_connect_uart_to_pads(
+ kTopEarlgreyPinmuxInselIoc10, kTopEarlgreyPinmuxPeripheralInUart0Rx,
+ kTopEarlgreyPinmuxMioOutIoc11, kTopEarlgreyPinmuxOutselUart0Tx);
+ pinmux_connect_uart_to_pads(
+ kTopEarlgreyPinmuxInselIor5, kTopEarlgreyPinmuxPeripheralInUart1Rx,
+ kTopEarlgreyPinmuxMioOutIor6, kTopEarlgreyPinmuxOutselUart1Tx);
+ pinmux_connect_uart_to_pads(
+ kTopEarlgreyPinmuxInselIor7, kTopEarlgreyPinmuxPeripheralInUart2Rx,
+ kTopEarlgreyPinmuxMioOutIor10, kTopEarlgreyPinmuxOutselUart2Tx);
+ pinmux_connect_uart_to_pads(
+ kTopEarlgreyPinmuxInselIor11, kTopEarlgreyPinmuxPeripheralInUart3Rx,
+ kTopEarlgreyPinmuxMioOutIor12, kTopEarlgreyPinmuxOutselUart3Tx);
// Initialize the UART.
- mmio_region_t uart_base_addr =
- mmio_region_from_addr(TOP_EARLGREY_UART0_BASE_ADDR);
- uart_init_with_irqs(uart_base_addr, &uart);
+ mmio_region_t chosen_uart_region = mmio_region_from_addr(uart_base_addr);
+ uart_init_with_irqs(chosen_uart_region, &uart);
// Initialize the PLIC.
mmio_region_t plic_base_addr =