Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ottf,opentitanlib,test] Impl spi device ottf tx console #24380

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions sw/device/lib/testing/test_framework/ottf_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,31 @@ status_t ottf_console_flow_control(const dif_uart_t *uart,
}

uint32_t ottf_console_get_flow_control_irqs(void) { return flow_control_irqs; }

static bool spi_tx_last_data_chunk(upload_info_t *info) {
const static size_t kSpiTxTerminateMagicAddress = 0x100;
return info->address == kSpiTxTerminateMagicAddress;
}

size_t ottf_console_spi_device_read(size_t buf_size, uint8_t *const buf) {
size_t received_data_len = 0;
upload_info_t info;
memset(&info, 0, sizeof(upload_info_t));
while (!spi_tx_last_data_chunk(&info)) {
CHECK_STATUS_OK(
spi_device_testutils_wait_for_upload(&ottf_console_spi_device, &info));
if (received_data_len < buf_size) {
size_t remaining_buf_size = buf_size - received_data_len;
size_t bytes_to_copy = remaining_buf_size < info.data_len
? remaining_buf_size
: info.data_len;
memcpy(buf + received_data_len, info.data, bytes_to_copy);
}

received_data_len += info.data_len;
CHECK_DIF_OK(dif_spi_device_set_flash_status_registers(
&ottf_console_spi_device, 0x00));
}

return received_data_len;
}
15 changes: 15 additions & 0 deletions sw/device/lib/testing/test_framework/ottf_console.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,19 @@ bool ottf_console_flow_control_isr(uint32_t *exc_info);
*/
uint32_t ottf_console_get_flow_control_irqs(void);

/**
* Read data from the host via the OTTF SPI device console into a provided
* buffer.
*
* The function waits for spi upload commands, then transfers data in chunks
* until a transmission complete signal is received. If the size of data sent
* from the host is greater than the provided buffer, then the excess data will
* be discarded.
*
* @param buf_size The size, in bytes, of the `buf`.
* @param[out] buf A pointer to the location where the data should be stored.
* @return The number of bytes actually received from the host.
*/
size_t ottf_console_spi_device_read(size_t buf_size, uint8_t *const buf);

#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_TEST_FRAMEWORK_OTTF_CONSOLE_H_
47 changes: 40 additions & 7 deletions sw/device/tests/spi_device_ottf_console_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

#include "sw/device/lib/dif/dif_spi_device.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/spi_device_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_console.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
Expand Down Expand Up @@ -93,22 +95,53 @@ static const char kTest4KbDataStr[] =
"B30518D571FDD6D38E0477F6CB83C7729A45494F5D7805CCC1432C816B7D8CB089CEA56216"
"9489E4F80E70FA685F39E1CD0AD7AD703C2E9601D442004F3D4CE043F0E84007FB7438FE82"
"DF4D9304C90B48BB25762DD29D";

static uint8_t input_buf[5120];

bool test_main(void) {
LOG_INFO("Sending empty string...");
LOG_INFO("Sending empty string to Host...");
LOG_INFO("");
LOG_INFO("Sending test string...");
LOG_INFO("Sending test string to Host...");
LOG_INFO("%s", kTestStr);
LOG_INFO("Sending 64B data...");
LOG_INFO("SYNC: Waiting for console data");
size_t received_data_len =
ottf_console_spi_device_read(sizeof(input_buf), input_buf);
CHECK(received_data_len == sizeof(kTestStr));
CHECK_ARRAYS_EQ(input_buf, kTestStr, ARRAYSIZE(kTestStr));

LOG_INFO("Sending 64B data to Host...");
LOG_INFO("%s", kTest64bDataStr);
LOG_INFO("Sending 256B data...");
LOG_INFO("SYNC: Waiting for console data");
received_data_len =
ottf_console_spi_device_read(sizeof(input_buf), input_buf);
CHECK(received_data_len == sizeof(kTest64bDataStr));
CHECK_ARRAYS_EQ(input_buf, kTest64bDataStr, ARRAYSIZE(kTest64bDataStr));

LOG_INFO("Sending 256B data to Host...");
LOG_INFO("%s", kTest256bDataStr);
LOG_INFO("Sending 1KB data...");
LOG_INFO("SYNC: Waiting for console data");
received_data_len =
ottf_console_spi_device_read(sizeof(input_buf), input_buf);
CHECK(received_data_len == sizeof(kTest256bDataStr));
CHECK_ARRAYS_EQ(input_buf, kTest256bDataStr, ARRAYSIZE(kTest256bDataStr));

LOG_INFO("Sending 1KB data to Host...");
for (int i = 1; i <= 2; i++) {
LOG_INFO("Round: %d", i);
LOG_INFO("%s", kTest1KbDataStr);
LOG_INFO("SYNC: Waiting for console data");
received_data_len =
ottf_console_spi_device_read(sizeof(input_buf), input_buf);
CHECK(received_data_len == sizeof(kTest1KbDataStr));
CHECK_ARRAYS_EQ(input_buf, kTest1KbDataStr, ARRAYSIZE(kTest1KbDataStr));
}
LOG_INFO("Sending 4KB data...");
LOG_INFO("%s", kTest4KbDataStr);

LOG_INFO("Sending 4KB data to Host...");
LOG_INFO("%s", kTest4KbDataStr);
LOG_INFO("SYNC: Waiting for console data");
received_data_len =
ottf_console_spi_device_read(sizeof(input_buf), input_buf);
CHECK(received_data_len == sizeof(kTest4KbDataStr));
CHECK_ARRAYS_EQ(input_buf, kTest4KbDataStr, ARRAYSIZE(kTest4KbDataStr));
return true;
}
25 changes: 25 additions & 0 deletions sw/host/opentitanlib/src/console/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ impl<'a> SpiConsoleDevice<'a> {
const SPI_FLASH_READ_BUFFER_SIZE: u32 = 2048;
const SPI_MAX_DATA_LENGTH: usize = 2036;
const SPI_FRAME_MAGIC_NUMBER: u32 = 0xa5a5beef;
const SPI_FLASH_PAYLOAD_BUFFER_SIZE: usize = 256;
const SPI_TX_LAST_CHUNK_MAGIC_ADDRESS: u32 = 0x100;

pub fn new(spi: &'a dyn Target) -> Result<Self> {
let mut flash = SpiFlash {
Expand Down Expand Up @@ -112,4 +114,27 @@ impl<'a> ConsoleDevice for SpiConsoleDevice<'a> {

Ok(i)
}

fn console_write(&self, buf: &[u8]) -> Result<()> {
let buf_len: usize = buf.len();
let mut written_data_len: usize = 0;
while written_data_len < buf_len {
let mut write_address = SpiConsoleDevice::SPI_TX_LAST_CHUNK_MAGIC_ADDRESS;
let mut data_len: usize = buf_len - written_data_len;

if data_len > SpiConsoleDevice::SPI_FLASH_PAYLOAD_BUFFER_SIZE {
data_len = SpiConsoleDevice::SPI_FLASH_PAYLOAD_BUFFER_SIZE;
write_address = 0;
}

self.flash.program(
self.spi,
write_address,
&buf[written_data_len..written_data_len + data_len],
)?;
written_data_len += data_len;
}

Ok(())
}
}
27 changes: 25 additions & 2 deletions sw/host/tests/chip/spi_device_ottf_console/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::time::Duration;
use opentitanlib::app::TransportWrapper;
use opentitanlib::console::spi::SpiConsoleDevice;
use opentitanlib::execute_test;
use opentitanlib::io::console::ConsoleDevice;
use opentitanlib::test_utils;
use opentitanlib::test_utils::init::InitializeTest;
use opentitanlib::uart::console::{ExitStatus, UartConsole};
Expand All @@ -34,6 +35,8 @@ struct Opts {
firmware_elf: PathBuf,
}

const SYNC_MSG: &str = r"SYNC:.*\r\n";

fn spi_device_console_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
let mut console = UartConsole {
timeout: Some(opts.timeout),
Expand All @@ -54,20 +57,40 @@ fn spi_device_console_test(opts: &Opts, transport: &TransportWrapper) -> Result<
let mut data = test_utils::object::symbol_data(&object, "kTestStr")?;
let mut data_str = std::str::from_utf8(&data)?.trim_matches(char::from(0));
_ = UartConsole::wait_for(&spi_console_device, data_str, opts.timeout)?;
log::info!("Sending test string to Device...");
_ = UartConsole::wait_for(&spi_console_device, SYNC_MSG, opts.timeout)?;
spi_console_device.console_write(&data)?;

data = test_utils::object::symbol_data(&object, "kTest64bDataStr")?;
data_str = std::str::from_utf8(&data)?.trim_matches(char::from(0));
_ = UartConsole::wait_for(&spi_console_device, data_str, opts.timeout)?;
log::info!("Sending 64B data to Device...");
_ = UartConsole::wait_for(&spi_console_device, SYNC_MSG, opts.timeout)?;
spi_console_device.console_write(&data)?;

data = test_utils::object::symbol_data(&object, "kTest256bDataStr")?;
data_str = std::str::from_utf8(&data)?.trim_matches(char::from(0));
_ = UartConsole::wait_for(&spi_console_device, data_str, opts.timeout)?;
log::info!("Sending 256 data to Device...");
_ = UartConsole::wait_for(&spi_console_device, SYNC_MSG, opts.timeout)?;
spi_console_device.console_write(&data)?;

data = test_utils::object::symbol_data(&object, "kTest1KbDataStr")?;
data_str = std::str::from_utf8(&data)?.trim_matches(char::from(0));
// 1KB data will be sent twice.
_ = UartConsole::wait_for(&spi_console_device, data_str, opts.timeout)?;
_ = UartConsole::wait_for(&spi_console_device, data_str, opts.timeout)?;
for _round in 0..2 {
_ = UartConsole::wait_for(&spi_console_device, data_str, opts.timeout)?;
log::info!("Sending 1KB data to Device...");
_ = UartConsole::wait_for(&spi_console_device, SYNC_MSG, opts.timeout)?;
spi_console_device.console_write(&data)?;
}

data = test_utils::object::symbol_data(&object, "kTest4KbDataStr")?;
data_str = std::str::from_utf8(&data)?.trim_matches(char::from(0));
_ = UartConsole::wait_for(&spi_console_device, data_str, opts.timeout)?;
log::info!("Sending 4KB data to Device...");
_ = UartConsole::wait_for(&spi_console_device, SYNC_MSG, opts.timeout)?;
spi_console_device.console_write(&data)?;

let result = console.interact(&spi_console_device, None, Some(&mut stdout))?;
match result {
Expand Down