Skip to content

Commit

Permalink
sw: Refactored pinmux driver
Browse files Browse the repository at this point in the history
The changes allow for easier access control and compartmentalisation.
  • Loading branch information
HU90m committed Nov 14, 2024
1 parent a24c10e commit 28232be
Show file tree
Hide file tree
Showing 12 changed files with 668 additions and 651 deletions.
47 changes: 22 additions & 25 deletions sw/cheri/checks/pinmux_all_blocks_check.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ using namespace CHERI;

SonataGpioFull gpio_full = get_full_gpio_ptrs(root);

Capability<volatile uint8_t> pinmux = root.cast<volatile uint8_t>();
pinmux.address() = PINMUX_ADDRESS;
pinmux.bounds() = PINMUX_BOUNDS;
SonataPinmux Pinmux = SonataPinmux(pinmux);
PinmuxPtrs pinmux = std::pair{pin_sinks_ptr(root), block_sinks_ptr(root)};

// Initialise Pseudo-Random Number Generation for use in Pinmux UART testing
ds::xoroshiro::P32R8 prng;
Expand All @@ -64,33 +61,33 @@ using namespace CHERI;
// initializers, as that requires `memcpy` to exist which we do not have.
// Likewise, arrays with multiple pins/inputs must be individually set, or
// we will get errors with `memcpy`.
OutputPinAssignment pmod_test_gpio_on_pins[] = {{SonataPinmux::OutputPin::pmod0_2, 1}};
BlockInputAssignment pmod_test_gpio_on_inputs[] = {{SonataPinmux::BlockInput::gpio_2_ios_2, 1}};
OutputPinAssignment pmod_test_gpio_off_pins[] = {{SonataPinmux::OutputPin::pmod0_2, 0}};
BlockInputAssignment pmod_test_gpio_off_inputs[] = {{SonataPinmux::BlockInput::gpio_2_ios_2, 0}};
OutputPinAssignment pmod_test_gpio_on_pins[] = {{SonataPinmux::PinSink::pmod0_2, 1}};
BlockInputAssignment pmod_test_gpio_on_inputs[] = {{SonataPinmux::BlockSink::gpio_2_ios_2, 1}};
OutputPinAssignment pmod_test_gpio_off_pins[] = {{SonataPinmux::PinSink::pmod0_2, 0}};
BlockInputAssignment pmod_test_gpio_off_inputs[] = {{SonataPinmux::BlockSink::gpio_2_ios_2, 0}};

OutputPinAssignment pmod_test_uart_on_pins[] = {{SonataPinmux::OutputPin::pmod0_2, 4}};
BlockInputAssignment pmod_test_uart_on_inputs[] = {{SonataPinmux::BlockInput::uart_1_rx, 5}};
OutputPinAssignment pmod_test_uart_off_pins[] = {{SonataPinmux::OutputPin::pmod0_2, 0}};
BlockInputAssignment pmod_test_uart_off_inputs[] = {{SonataPinmux::BlockInput::uart_1_rx, 0}};
OutputPinAssignment pmod_test_uart_on_pins[] = {{SonataPinmux::PinSink::pmod0_2, 4}};
BlockInputAssignment pmod_test_uart_on_inputs[] = {{SonataPinmux::BlockSink::uart_1_rx, 5}};
OutputPinAssignment pmod_test_uart_off_pins[] = {{SonataPinmux::PinSink::pmod0_2, 0}};
BlockInputAssignment pmod_test_uart_off_inputs[] = {{SonataPinmux::BlockSink::uart_1_rx, 0}};

OutputPinAssignment pmod_test_i2c_on_pins[2];
pmod_test_i2c_on_pins[0] = {SonataPinmux::OutputPin::pmod0_3, 2}; // Mux to I2C SDA
pmod_test_i2c_on_pins[1] = {SonataPinmux::OutputPin::pmod0_4, 3}; // Mux to I2C SCL
pmod_test_i2c_on_pins[0] = {SonataPinmux::PinSink::pmod0_3, 2}; // Mux to I2C SDA
pmod_test_i2c_on_pins[1] = {SonataPinmux::PinSink::pmod0_4, 3}; // Mux to I2C SCL
OutputPinAssignment pmod_test_i2c_off_pins[2];
pmod_test_i2c_off_pins[0] = {SonataPinmux::OutputPin::pmod0_3, 0};
pmod_test_i2c_off_pins[1] = {SonataPinmux::OutputPin::pmod0_4, 0};
pmod_test_i2c_off_pins[0] = {SonataPinmux::PinSink::pmod0_3, 0};
pmod_test_i2c_off_pins[1] = {SonataPinmux::PinSink::pmod0_4, 0};

OutputPinAssignment pmod_test_spi_on_pins[3];
pmod_test_spi_on_pins[0] = {SonataPinmux::OutputPin::pmod0_1, 2}; // Mux to SPI CS
pmod_test_spi_on_pins[1] = {SonataPinmux::OutputPin::pmod0_2, 2}; // Mux to SPI COPI
pmod_test_spi_on_pins[2] = {SonataPinmux::OutputPin::pmod0_4, 2}; // Mux to SPI SCK
BlockInputAssignment pmod_test_spi_on_inputs[] = {{SonataPinmux::BlockInput::spi_1_cipo, 3}};
pmod_test_spi_on_pins[0] = {SonataPinmux::PinSink::pmod0_1, 2}; // Mux to SPI CS
pmod_test_spi_on_pins[1] = {SonataPinmux::PinSink::pmod0_2, 2}; // Mux to SPI COPI
pmod_test_spi_on_pins[2] = {SonataPinmux::PinSink::pmod0_4, 2}; // Mux to SPI SCK
BlockInputAssignment pmod_test_spi_on_inputs[] = {{SonataPinmux::BlockSink::spi_1_cipo, 3}};
OutputPinAssignment pmod_test_spi_off_pins[3];
pmod_test_spi_off_pins[0] = {SonataPinmux::OutputPin::pmod0_1, 0};
pmod_test_spi_off_pins[1] = {SonataPinmux::OutputPin::pmod0_2, 0};
pmod_test_spi_off_pins[2] = {SonataPinmux::OutputPin::pmod0_4, 0};
BlockInputAssignment pmod_test_spi_off_inputs[] = {{SonataPinmux::BlockInput::spi_1_cipo, 0}};
pmod_test_spi_off_pins[0] = {SonataPinmux::PinSink::pmod0_1, 0};
pmod_test_spi_off_pins[1] = {SonataPinmux::PinSink::pmod0_2, 0};
pmod_test_spi_off_pins[2] = {SonataPinmux::PinSink::pmod0_4, 0};
BlockInputAssignment pmod_test_spi_off_inputs[] = {{SonataPinmux::BlockSink::spi_1_cipo, 0}};

// The pinmux testplan to execute. This testplan runs through testing GPIO, UART, I2C and SPI
// all on the same PMOD pins, with users manually changing out the connected devices between
Expand Down Expand Up @@ -213,7 +210,7 @@ using namespace CHERI;

// Execute the pinmux testplan
const uint8_t NumTests = ARRAYSIZE(pinmux_testplan);
execute_testplan(pinmux_testplan, NumTests, log, prng, &gpio_full, uarts, spis, i2cs, &Pinmux);
execute_testplan(pinmux_testplan, NumTests, log, prng, &gpio_full, uarts, spis, i2cs, pinmux);

// Infinite loop to stop execution returning
while (true) {
Expand Down
16 changes: 6 additions & 10 deletions sw/cheri/checks/pinmux_check.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../../common/defs.h"
#include "../common/uart-utils.hh"
#include "../common/platform-pinmux.hh"
#include "../common/sonata-devices.hh"
#include <cheri.hh>

#define LOG(...) write_str(uart, __VA_ARGS__)
Expand Down Expand Up @@ -38,29 +39,24 @@ void block_until_uart_tx_done(Capability<volatile OpenTitanUart> uart) {
[[noreturn]] extern "C" void entry_point(void *rwRoot) {
Capability<void> root{rwRoot};

Capability<volatile OpenTitanUart> uart = root.cast<volatile OpenTitanUart>();
uart.address() = UART_ADDRESS;
uart.bounds() = UART_BOUNDS;
UartPtr uart = uart_ptr(root);
uart->init(BAUD_RATE);

Capability<volatile uint8_t> pinmux = root.cast<volatile uint8_t>();
pinmux.address() = PINMUX_ADDRESS;
pinmux.bounds() = PINMUX_BOUNDS;

SonataPinmux Pinmux = SonataPinmux(pinmux);
SonataPinmux::Sink ser0_tx = pin_sinks_ptr(root)->get(SonataPinmux::PinSink::ser0_tx);

LOG("Starting check.\r\n");

LOG("You should see this message, as UART0 is pinmuxed by default.\r\n");
block_until_uart_tx_done(uart);

// Pinmux Serial 0 TX (used by console UART) to OFF.
Pinmux.output_pin_select(SonataPinmux::OutputPin::ser0_tx, PINMUX_SER0_TX_DISABLED);

ser0_tx.disable();
LOG("You should NOT see this message, as we just used pinmux to disable UART0 output.\r\n");
block_until_uart_tx_done(uart);

// Pinmux Serial 0 TX (used by console UART) to UART0_TX.
Pinmux.output_pin_select(SonataPinmux::OutputPin::ser0_tx, PINMUX_SER0_TX_UART0_TX);
ser0_tx.select(PINMUX_SER0_TX_UART0_TX);
LOG("You should see this message, as UART0 has just been re-enabled.\r\n");

LOG("Check completed.\r\n");
Expand Down
8 changes: 4 additions & 4 deletions sw/cheri/checks/pinmux_checker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static inline bool joystick_moved(SonataGpioFull *gpio) {
* otherwise.
*/
bool execute_test(const Test &test, uint32_t test_num, Log &log, ds::xoroshiro::P32R8 &prng, SonataGpioFull *gpio,
UartPtr uarts[2], SpiPtr spis[3], I2cPtr i2cs[2], SonataPinmux *pinmux) {
UartPtr uarts[2], SpiPtr spis[3], I2cPtr i2cs[2], PinmuxPtrs pinmux) {
// If manual intervention is required, print out the test instruction and wait
// for the user to press the joystick to signal that they are ready.
if (test.manual_required) {
Expand All @@ -172,15 +172,15 @@ bool execute_test(const Test &test, uint32_t test_num, Log &log, ds::xoroshiro::
// Configure the output pins and block inputs via pinmux
for (uint32_t i = 0; i < test.num_output_pins; i++) {
auto pin_assign = test.output_pins[i];
if (!pinmux->output_pin_select(pin_assign.pin, pin_assign.select)) {
if (!std::get<PinSinksPtr>(pinmux)->get(pin_assign.pin).select(pin_assign.select)) {
log.println("");
log.print("{}Error: invalid pinmux output pin selection.", prefix);
return false;
}
}
for (uint32_t i = 0; i < test.num_block_inputs; i++) {
auto block_assign = test.block_inputs[i];
if (!pinmux->block_input_select(block_assign.input, block_assign.select)) {
if (!std::get<BlockSinksPtr>(pinmux)->get(block_assign.input).select(block_assign.select)) {
log.println("");
log.print("{}Error: invalid pinmux block input selection.", prefix);
return false;
Expand Down Expand Up @@ -264,7 +264,7 @@ bool ask_retry_last_test(Log &log, SonataGpioFull *gpio) {
* otherwise. Will return true even if there were retries.
*/
bool execute_testplan(Test *testplan, uint8_t NumTests, Log &log, ds::xoroshiro::P32R8 &prng, SonataGpioFull *gpio,
UartPtr uarts[2], SpiPtr spis[3], I2cPtr i2cs[2], SonataPinmux *pinmux) {
UartPtr uarts[2], SpiPtr spis[3], I2cPtr i2cs[2], PinmuxPtrs pinmux) {
log.println("");
log.println("{}Starting check.", prefix);
log.println("");
Expand Down
6 changes: 3 additions & 3 deletions sw/cheri/checks/pinmux_checker.hh
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ struct SpiTest {

// An output pin assignment to be made via Pinmux for a test
struct OutputPinAssignment {
SonataPinmux::OutputPin pin;
SonataPinmux::PinSink pin;
uint8_t select;
};

// A block input assignment to be made via Pinmux for a test
struct BlockInputAssignment {
SonataPinmux::BlockInput input;
SonataPinmux::BlockSink input;
uint8_t select;
};

Expand Down Expand Up @@ -126,4 +126,4 @@ struct Test {
};

bool execute_testplan(Test *testplan, uint8_t NumTests, Log &log, ds::xoroshiro::P32R8 &prng, SonataGpioFull *gpio,
UartPtr uarts[4], SpiPtr spis[3], I2cPtr i2cs[2], SonataPinmux *pinmux);
UartPtr uarts[4], SpiPtr spis[3], I2cPtr i2cs[2], PinmuxPtrs pinmux);
15 changes: 4 additions & 11 deletions sw/cheri/checks/rs485_check.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "../common/uart-utils.hh"
#include "../common/platform-pinmux.hh"
#include "../common/timer-utils.hh"
#include "../common/sonata-devices.hh"
#include <cheri.hh>

#define RS485_UART 2
Expand All @@ -21,18 +22,10 @@ using namespace CHERI;
[[noreturn]] extern "C" void entry_point(void *rwRoot) {
Capability<void> root{rwRoot};

Capability<volatile uint8_t> pinmux = root.cast<volatile uint8_t>();
pinmux.address() = PINMUX_ADDRESS;
pinmux.bounds() = PINMUX_BOUNDS;
pin_sinks_ptr(root)->get(SonataPinmux::PinSink::rs485_tx).select(1);
block_sinks_ptr(root)->get(SonataPinmux::BlockSink::uart_2_rx).select(3);

SonataPinmux Pinmux = SonataPinmux(pinmux);

Pinmux.output_pin_select(SonataPinmux::OutputPin::rs485_tx, 1);
Pinmux.block_input_select(SonataPinmux::BlockInput::uart_2_rx, 3);

Capability<volatile OpenTitanUart> uart = root.cast<volatile OpenTitanUart>();
uart.address() = UART_ADDRESS;
uart.bounds() = UART_BOUNDS;
UartPtr uart = uart_ptr(root, 0);
uart->init(BAUD_RATE);

Capability<volatile OpenTitanUart> rs485_uart = root.cast<volatile OpenTitanUart>();
Expand Down
15 changes: 4 additions & 11 deletions sw/cheri/checks/rs485_spam_check.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "../common/uart-utils.hh"
#include "../common/platform-pinmux.hh"
#include "../common/timer-utils.hh"
#include "../common/sonata-devices.hh"
#include <cheri.hh>

#define RS485_UART 2
Expand All @@ -22,18 +23,10 @@ using namespace CHERI;
[[noreturn]] extern "C" void entry_point(void *rwRoot) {
Capability<void> root{rwRoot};

Capability<volatile uint8_t> pinmux = root.cast<volatile uint8_t>();
pinmux.address() = PINMUX_ADDRESS;
pinmux.bounds() = PINMUX_BOUNDS;
pin_sinks_ptr(root)->get(SonataPinmux::PinSink::rs485_tx).select(1);
block_sinks_ptr(root)->get(SonataPinmux::BlockSink::uart_2_rx).select(3);

SonataPinmux Pinmux = SonataPinmux(pinmux);

Pinmux.output_pin_select(SonataPinmux::OutputPin::rs485_tx, 1);
Pinmux.block_input_select(SonataPinmux::BlockInput::uart_2_rx, 3);

Capability<volatile OpenTitanUart> uart = root.cast<volatile OpenTitanUart>();
uart.address() = UART_ADDRESS;
uart.bounds() = UART_BOUNDS;
UartPtr uart = uart_ptr(root, 0);
uart->init(BAUD_RATE);

Capability<volatile OpenTitanUart> rs485_uart = root.cast<volatile OpenTitanUart>();
Expand Down
Loading

0 comments on commit 28232be

Please sign in to comment.