blob: 0b9f65087401df485dc722dfab24b9a78ff3f755 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/dif/dif_uart.h"
#include "gtest/gtest.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/base/mock_mmio.h"
#include "sw/device/lib/dif/dif_test_base.h"
#include "uart_regs.h" // Generated.
namespace dif_uart_unittest {
namespace {
using mock_mmio::MmioTest;
using mock_mmio::MockDevice;
using testing::Each;
using testing::Eq;
using testing::Test;
const std::vector<uint8_t> kBytesArray = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
};
class UartTest : public Test, public MmioTest {
protected:
void ExpectDeviceReset() {
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, 0);
EXPECT_WRITE32(UART_FIFO_CTRL_REG_OFFSET,
{
{UART_FIFO_CTRL_RXRST_BIT, true},
{UART_FIFO_CTRL_TXRST_BIT, true},
});
EXPECT_WRITE32(UART_OVRD_REG_OFFSET, 0);
EXPECT_WRITE32(UART_TIMEOUT_CTRL_REG_OFFSET, 0);
EXPECT_WRITE32(UART_INTR_ENABLE_REG_OFFSET, 0);
EXPECT_WRITE32(UART_INTR_STATE_REG_OFFSET,
std::numeric_limits<uint32_t>::max());
}
dif_uart_t uart_ = {
.base_addr = dev().region(),
};
// NCO is calculated as NCO = 2^20 * fbaud / fpclk, so the following values
// should result in NCO of 1. This is the default configuration, which will
// be used unless the values are overridden.
dif_uart_config_t config_ = {
.baudrate = 1,
.clk_freq_hz = 1048576,
.parity_enable = kDifToggleDisabled,
.parity = kDifUartParityEven,
.tx_enable = kDifToggleEnabled,
.rx_enable = kDifToggleEnabled,
};
};
class ConfigTest : public UartTest {};
TEST_F(ConfigTest, NullArgs) {
EXPECT_DIF_BADARG(dif_uart_configure(nullptr, config_));
}
TEST_F(ConfigTest, DefaultTxRxEnabled) {
ExpectDeviceReset();
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_TX_BIT, true},
{UART_CTRL_RX_BIT, true},
{UART_CTRL_NCO_OFFSET, 1},
});
EXPECT_WRITE32(UART_INTR_ENABLE_REG_OFFSET, 0);
EXPECT_DIF_OK(dif_uart_configure(&uart_, config_));
}
TEST_F(ConfigTest, DefaultTxEnabled) {
ExpectDeviceReset();
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_TX_BIT, true},
{UART_CTRL_NCO_OFFSET, 1},
});
EXPECT_WRITE32(UART_INTR_ENABLE_REG_OFFSET, 0);
config_.rx_enable = kDifToggleDisabled;
EXPECT_DIF_OK(dif_uart_configure(&uart_, config_));
}
TEST_F(ConfigTest, DefaultRxEnabled) {
ExpectDeviceReset();
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, true},
{UART_CTRL_NCO_OFFSET, 1},
});
EXPECT_WRITE32(UART_INTR_ENABLE_REG_OFFSET, 0);
config_.tx_enable = kDifToggleDisabled;
EXPECT_DIF_OK(dif_uart_configure(&uart_, config_));
}
TEST_F(ConfigTest, DefaultTxRxDisabled) {
ExpectDeviceReset();
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {{UART_CTRL_NCO_OFFSET, 1}});
EXPECT_WRITE32(UART_INTR_ENABLE_REG_OFFSET, 0);
config_.tx_enable = kDifToggleDisabled;
config_.rx_enable = kDifToggleDisabled;
EXPECT_DIF_OK(dif_uart_configure(&uart_, config_));
}
TEST_F(ConfigTest, ParityEven) {
config_.parity_enable = kDifToggleEnabled;
config_.parity = kDifUartParityEven;
ExpectDeviceReset();
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_TX_BIT, true},
{UART_CTRL_RX_BIT, true},
{UART_CTRL_PARITY_EN_BIT, true},
{UART_CTRL_NCO_OFFSET, 1},
});
EXPECT_WRITE32(UART_INTR_ENABLE_REG_OFFSET, 0);
EXPECT_DIF_OK(dif_uart_configure(&uart_, config_));
}
TEST_F(ConfigTest, ParityOdd) {
config_.parity_enable = kDifToggleEnabled;
config_.parity = kDifUartParityOdd;
ExpectDeviceReset();
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_TX_BIT, true},
{UART_CTRL_RX_BIT, true},
{UART_CTRL_PARITY_EN_BIT, true},
{UART_CTRL_PARITY_ODD_BIT, true},
{UART_CTRL_NCO_OFFSET, 1},
});
EXPECT_WRITE32(UART_INTR_ENABLE_REG_OFFSET, 0);
EXPECT_DIF_OK(dif_uart_configure(&uart_, config_));
}
class WatermarkRxSetTest : public UartTest {};
TEST_F(WatermarkRxSetTest, UartNull) {
dif_result_t result =
dif_uart_watermark_rx_set(nullptr, kDifUartWatermarkByte1);
EXPECT_DIF_BADARG(result);
}
/**
* Tests the first and the last RX watermark variants.
*/
TEST_F(WatermarkRxSetTest, Success) {
EXPECT_MASK32(UART_FIFO_CTRL_REG_OFFSET,
{
{UART_FIFO_CTRL_RXILVL_OFFSET, UART_FIFO_CTRL_RXILVL_MASK,
UART_FIFO_CTRL_RXILVL_VALUE_RXLVL1},
});
EXPECT_DIF_OK(dif_uart_watermark_rx_set(&uart_, kDifUartWatermarkByte1));
EXPECT_MASK32(UART_FIFO_CTRL_REG_OFFSET,
{
{UART_FIFO_CTRL_RXILVL_OFFSET, UART_FIFO_CTRL_RXILVL_MASK,
UART_FIFO_CTRL_RXILVL_VALUE_RXLVL30},
});
EXPECT_DIF_OK(dif_uart_watermark_rx_set(&uart_, kDifUartWatermarkByte30));
}
class WatermarkTxSetTest : public UartTest {};
TEST_F(WatermarkTxSetTest, NullArgs) {
EXPECT_DIF_BADARG(dif_uart_watermark_tx_set(nullptr, kDifUartWatermarkByte1));
}
TEST_F(WatermarkTxSetTest, InvalidWatermark) {
EXPECT_EQ(dif_uart_watermark_tx_set(&uart_, kDifUartWatermarkByte30),
kDifError);
}
/**
* Tests the first and the last TX watermark variants.
*/
TEST_F(WatermarkTxSetTest, Success) {
EXPECT_MASK32(UART_FIFO_CTRL_REG_OFFSET,
{
{UART_FIFO_CTRL_TXILVL_OFFSET, UART_FIFO_CTRL_TXILVL_MASK,
UART_FIFO_CTRL_TXILVL_VALUE_TXLVL1},
});
EXPECT_DIF_OK(dif_uart_watermark_tx_set(&uart_, kDifUartWatermarkByte1));
EXPECT_MASK32(UART_FIFO_CTRL_REG_OFFSET,
{
{UART_FIFO_CTRL_TXILVL_OFFSET, UART_FIFO_CTRL_TXILVL_MASK,
UART_FIFO_CTRL_TXILVL_VALUE_TXLVL16},
});
EXPECT_DIF_OK(dif_uart_watermark_tx_set(&uart_, kDifUartWatermarkByte16));
}
class SetEnableTest : public UartTest {};
TEST_F(SetEnableTest, NullArg) {
EXPECT_DIF_BADARG(
dif_uart_set_enable(nullptr, kDifUartDatapathAll, kDifToggleEnabled));
}
TEST_F(SetEnableTest, BadEnabled) {
EXPECT_DIF_BADARG(dif_uart_set_enable(&uart_, kDifUartDatapathAll,
static_cast<dif_toggle_t>(2)));
}
TEST_F(SetEnableTest, BadDatapath) {
EXPECT_READ32(UART_CTRL_REG_OFFSET, 0);
EXPECT_DIF_BADARG(dif_uart_set_enable(
&uart_, static_cast<dif_uart_datapath_t>(kDifUartDatapathAll + 1),
kDifToggleEnabled));
}
TEST_F(SetEnableTest, SuccessRxEnabledDisabled) {
EXPECT_READ32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 0},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_DIF_OK(
dif_uart_set_enable(&uart_, kDifUartDatapathRx, kDifToggleEnabled));
EXPECT_READ32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 0},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_DIF_OK(
dif_uart_set_enable(&uart_, kDifUartDatapathRx, kDifToggleDisabled));
}
TEST_F(SetEnableTest, SuccessTxEnabledDisabled) {
EXPECT_READ32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 0},
});
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_DIF_OK(
dif_uart_set_enable(&uart_, kDifUartDatapathTx, kDifToggleEnabled));
EXPECT_READ32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 0},
});
EXPECT_DIF_OK(
dif_uart_set_enable(&uart_, kDifUartDatapathTx, kDifToggleDisabled));
}
TEST_F(SetEnableTest, SuccessRxTxEnabledDisabled) {
EXPECT_READ32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 0},
{UART_CTRL_TX_BIT, 0},
});
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_DIF_OK(
dif_uart_set_enable(&uart_, kDifUartDatapathAll, kDifToggleEnabled));
EXPECT_READ32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 1},
{UART_CTRL_TX_BIT, 1},
});
EXPECT_WRITE32(UART_CTRL_REG_OFFSET, {
{UART_CTRL_RX_BIT, 0},
{UART_CTRL_TX_BIT, 0},
});
EXPECT_DIF_OK(
dif_uart_set_enable(&uart_, kDifUartDatapathAll, kDifToggleDisabled));
}
class BytesSendTest : public UartTest {
protected:
/**
* Sets TX bytes expectations.
*
* Every sent byte by the "send bytes" routine is expected to result in the
* STATUS read of 0 (FIFO not full), and write to WDATA.
*/
void ExpectSendBytes(int num_elements = kBytesArray.size()) {
ASSERT_LE(num_elements, kBytesArray.size());
for (int i = 0; i < num_elements; ++i) {
uint32_t value = static_cast<uint32_t>(kBytesArray[i]);
EXPECT_READ32(UART_STATUS_REG_OFFSET, 0);
EXPECT_WRITE32(UART_WDATA_REG_OFFSET, value);
}
}
};
TEST_F(BytesSendTest, NullArgs) {
EXPECT_DIF_BADARG(
dif_uart_bytes_send(nullptr, kBytesArray.data(), 1, nullptr));
EXPECT_DIF_BADARG(dif_uart_bytes_send(&uart_, nullptr, 1, nullptr));
EXPECT_DIF_BADARG(dif_uart_bytes_send(nullptr, nullptr, 1, nullptr));
}
TEST_F(BytesSendTest, TxFifoEmptyBytesWrittenNull) {
ExpectSendBytes();
EXPECT_DIF_OK(dif_uart_bytes_send(&uart_, kBytesArray.data(),
kBytesArray.size(), nullptr));
}
TEST_F(BytesSendTest, TxFifoEmpty) {
ExpectSendBytes();
size_t bytes_written;
EXPECT_DIF_OK(dif_uart_bytes_send(&uart_, kBytesArray.data(),
kBytesArray.size(), &bytes_written));
EXPECT_EQ(bytes_written, kBytesArray.size());
}
TEST_F(BytesSendTest, TxFifoFull) {
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_TXFULL_BIT, true}});
size_t bytes_written;
EXPECT_DIF_OK(dif_uart_bytes_send(&uart_, kBytesArray.data(),
kBytesArray.size(), &bytes_written));
EXPECT_EQ(bytes_written, 0);
}
class BytesReceiveTest : public UartTest {
protected:
/**
* Sets RX bytes expectations.
*
* Every read byte by the "receive bytes" routine is expected to result in the
* STATUS read of 0 (FIFO not empty), and read of RDATA.
*/
void ExpectReceiveBytes(int num_elements) {
for (int i = 0; i < num_elements; ++i) {
uint32_t value = static_cast<uint32_t>(kBytesArray[i]);
EXPECT_READ32(UART_STATUS_REG_OFFSET, 0);
EXPECT_READ32(UART_RDATA_REG_OFFSET, value);
}
}
};
TEST_F(BytesReceiveTest, UartNull) {
std::vector<uint8_t> receive_bytes(1);
EXPECT_DIF_BADARG(
dif_uart_bytes_receive(nullptr, 1, receive_bytes.data(), nullptr));
EXPECT_THAT(receive_bytes, Each(Eq(0)));
EXPECT_DIF_BADARG(dif_uart_bytes_receive(&uart_, 1, nullptr, nullptr));
EXPECT_DIF_BADARG(dif_uart_bytes_receive(nullptr, 1, nullptr, nullptr));
}
TEST_F(BytesReceiveTest, RxFifoFullBytesWrittenNull) {
uint8_t num_bytes = kBytesArray.size();
ExpectReceiveBytes(num_bytes);
std::vector<uint8_t> receive_bytes(num_bytes);
EXPECT_DIF_OK(
dif_uart_bytes_receive(&uart_, num_bytes, receive_bytes.data(), nullptr));
EXPECT_EQ(receive_bytes, kBytesArray);
}
TEST_F(BytesReceiveTest, RxFifoFull) {
uint8_t num_bytes = kBytesArray.size();
ExpectReceiveBytes(num_bytes);
size_t bytes_read;
std::vector<uint8_t> receive_bytes(num_bytes);
EXPECT_DIF_OK(dif_uart_bytes_receive(&uart_, num_bytes, receive_bytes.data(),
&bytes_read));
EXPECT_EQ(bytes_read, num_bytes);
EXPECT_EQ(receive_bytes, kBytesArray);
}
TEST_F(BytesReceiveTest, RxFifoEmpty) {
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_RXEMPTY_BIT, true}});
uint8_t num_bytes = kBytesArray.size();
size_t bytes_read;
std::vector<uint8_t> receive_bytes(num_bytes);
EXPECT_DIF_OK(dif_uart_bytes_receive(&uart_, num_bytes, receive_bytes.data(),
&bytes_read));
EXPECT_EQ(bytes_read, 0);
EXPECT_THAT(receive_bytes, Each(Eq(0)));
}
class BytesSendPolledTest : public UartTest {};
TEST_F(BytesSendPolledTest, NullArgs) {
dif_result_t result = dif_uart_byte_send_polled(nullptr, 'X');
EXPECT_DIF_BADARG(result);
}
TEST_F(BytesSendPolledTest, Success) {
// Busy loop 1 iteration (waiting for TX FIFO to free up)
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_TXFULL_BIT, true}});
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_TXFULL_BIT, false}});
// Set expectations for the byte to be set
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_TXFULL_BIT, false}});
EXPECT_WRITE32(UART_WDATA_REG_OFFSET, 'X');
// Busy loop 1 iteration (waiting for the byte to be sent out by the HW)
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_TXIDLE_BIT, false}});
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_TXIDLE_BIT, true}});
EXPECT_DIF_OK(dif_uart_byte_send_polled(&uart_, 'X'));
}
class BytesReceivePolledTest : public UartTest {};
TEST_F(BytesReceivePolledTest, NullArgs) {
uint8_t byte;
EXPECT_DIF_BADARG(dif_uart_byte_receive_polled(nullptr, &byte));
EXPECT_DIF_BADARG(dif_uart_byte_receive_polled(&uart_, nullptr));
EXPECT_DIF_BADARG(dif_uart_byte_receive_polled(nullptr, nullptr));
}
TEST_F(BytesReceivePolledTest, Success) {
// Busy loop 1 iteration (waiting for RX FIFO to fill up)
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_RXEMPTY_BIT, true}});
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_RXEMPTY_BIT, false}});
// Set expectations for the byte to be read
EXPECT_READ32(UART_STATUS_REG_OFFSET, {{UART_STATUS_RXEMPTY_BIT, false}});
EXPECT_READ32(UART_RDATA_REG_OFFSET, 'X');
uint8_t byte = 'Y';
EXPECT_DIF_OK(dif_uart_byte_receive_polled(&uart_, &byte));
EXPECT_EQ(byte, 'X');
}
class RxBytesAvailableTest : public UartTest {};
TEST_F(RxBytesAvailableTest, NullArgs) {
size_t num_bytes;
EXPECT_DIF_BADARG(dif_uart_rx_bytes_available(nullptr, &num_bytes));
EXPECT_DIF_BADARG(dif_uart_rx_bytes_available(&uart_, nullptr));
EXPECT_DIF_BADARG(dif_uart_rx_bytes_available(nullptr, nullptr));
}
TEST_F(RxBytesAvailableTest, FifoFull) {
// kDifUartFifoSizeBytes bytes available to read.
EXPECT_READ32(UART_FIFO_STATUS_REG_OFFSET,
{{UART_FIFO_STATUS_RXLVL_OFFSET, kDifUartFifoSizeBytes}});
size_t num_bytes;
EXPECT_DIF_OK(dif_uart_rx_bytes_available(&uart_, &num_bytes));
EXPECT_EQ(num_bytes, kDifUartFifoSizeBytes);
}
TEST_F(RxBytesAvailableTest, FifoEmpty) {
// 0 bytes available to read.
EXPECT_READ32(UART_FIFO_STATUS_REG_OFFSET,
{{UART_FIFO_STATUS_RXLVL_OFFSET, 0}});
size_t num_bytes;
EXPECT_DIF_OK(dif_uart_rx_bytes_available(&uart_, &num_bytes));
EXPECT_EQ(num_bytes, 0);
}
class TxBytesAvailableTest : public UartTest {};
TEST_F(TxBytesAvailableTest, NullArgs) {
size_t num_bytes;
EXPECT_DIF_BADARG(dif_uart_tx_bytes_available(nullptr, &num_bytes));
EXPECT_DIF_BADARG(dif_uart_tx_bytes_available(&uart_, nullptr));
EXPECT_DIF_BADARG(dif_uart_tx_bytes_available(nullptr, nullptr));
}
TEST_F(TxBytesAvailableTest, FifoFull) {
// 0 bytes available to write.
EXPECT_READ32(UART_FIFO_STATUS_REG_OFFSET,
{{UART_FIFO_STATUS_TXLVL_OFFSET, kDifUartFifoSizeBytes}});
size_t num_bytes;
EXPECT_DIF_OK(dif_uart_tx_bytes_available(&uart_, &num_bytes));
EXPECT_EQ(num_bytes, 0);
}
TEST_F(TxBytesAvailableTest, FifoEmpty) {
// kDifUartFifoSizeBytes available to write.
EXPECT_READ32(UART_FIFO_STATUS_REG_OFFSET,
{{UART_FIFO_STATUS_TXLVL_OFFSET, 0}});
size_t num_bytes;
EXPECT_DIF_OK(dif_uart_tx_bytes_available(&uart_, &num_bytes));
EXPECT_EQ(num_bytes, kDifUartFifoSizeBytes);
}
class FifoResetTest : public UartTest {};
TEST_F(FifoResetTest, NullArgs) {
dif_result_t result = dif_uart_fifo_reset(nullptr, kDifUartDatapathRx);
EXPECT_DIF_BADARG(result);
}
TEST_F(FifoResetTest, Success) {
EXPECT_READ32(UART_FIFO_CTRL_REG_OFFSET, 0);
EXPECT_WRITE32(UART_FIFO_CTRL_REG_OFFSET, {{UART_FIFO_CTRL_RXRST_BIT, true}});
EXPECT_DIF_OK(dif_uart_fifo_reset(&uart_, kDifUartDatapathRx));
EXPECT_READ32(UART_FIFO_CTRL_REG_OFFSET, 0);
EXPECT_WRITE32(UART_FIFO_CTRL_REG_OFFSET, {{UART_FIFO_CTRL_TXRST_BIT, true}});
EXPECT_DIF_OK(dif_uart_fifo_reset(&uart_, kDifUartDatapathTx));
EXPECT_READ32(UART_FIFO_CTRL_REG_OFFSET, 0);
EXPECT_WRITE32(UART_FIFO_CTRL_REG_OFFSET,
{
{UART_FIFO_CTRL_RXRST_BIT, true},
{UART_FIFO_CTRL_TXRST_BIT, true},
});
EXPECT_DIF_OK(dif_uart_fifo_reset(&uart_, kDifUartDatapathAll));
}
class LoopbackSetTest : public UartTest {};
TEST_F(LoopbackSetTest, NullArgs) {
EXPECT_DIF_BADARG(dif_uart_loopback_set(nullptr, kDifUartLoopbackSystem,
kDifToggleEnabled));
}
TEST_F(LoopbackSetTest, Success) {
EXPECT_MASK32(UART_CTRL_REG_OFFSET, {{UART_CTRL_SLPBK_BIT, 0x1, true}});
EXPECT_DIF_OK(
dif_uart_loopback_set(&uart_, kDifUartLoopbackSystem, kDifToggleEnabled));
EXPECT_MASK32(UART_CTRL_REG_OFFSET, {{UART_CTRL_SLPBK_BIT, 0x1, false}});
EXPECT_DIF_OK(dif_uart_loopback_set(&uart_, kDifUartLoopbackSystem,
kDifToggleDisabled));
EXPECT_MASK32(UART_CTRL_REG_OFFSET, {{UART_CTRL_LLPBK_BIT, 0x1, true}});
EXPECT_DIF_OK(
dif_uart_loopback_set(&uart_, kDifUartLoopbackLine, kDifToggleEnabled));
EXPECT_MASK32(UART_CTRL_REG_OFFSET, {{UART_CTRL_LLPBK_BIT, 0x1, false}});
EXPECT_DIF_OK(
dif_uart_loopback_set(&uart_, kDifUartLoopbackLine, kDifToggleDisabled));
}
class RxTimeoutTest : public UartTest {};
TEST_F(RxTimeoutTest, NullArgs) {
EXPECT_DIF_BADARG(dif_uart_enable_rx_timeout(nullptr, 1));
EXPECT_DIF_BADARG(dif_uart_disable_rx_timeout(nullptr));
uint32_t value; // optional
dif_toggle_t status; // mandatory
EXPECT_DIF_BADARG(dif_uart_get_rx_timeout(nullptr, &status, &value));
EXPECT_DIF_BADARG(dif_uart_get_rx_timeout(&uart_, nullptr, &value));
}
TEST_F(RxTimeoutTest, OutOfRange) {
// RX timeout value must be in the range [0,0xffffff].
EXPECT_DIF_BADARG(dif_uart_enable_rx_timeout(&uart_, 0x01000000));
EXPECT_DIF_BADARG(dif_uart_enable_rx_timeout(&uart_, 0xffffffff));
}
TEST_F(RxTimeoutTest, Enable) {
// Enable RX timeout and set to 0x123.
const uint32_t duration = 0x123;
EXPECT_WRITE32(UART_TIMEOUT_CTRL_REG_OFFSET,
{{UART_TIMEOUT_CTRL_VAL_OFFSET, duration},
{UART_TIMEOUT_CTRL_EN_BIT, true}});
EXPECT_DIF_OK(dif_uart_enable_rx_timeout(&uart_, duration));
}
TEST_F(RxTimeoutTest, Disable) {
// Disable RX timeout.
EXPECT_WRITE32(
UART_TIMEOUT_CTRL_REG_OFFSET,
{{UART_TIMEOUT_CTRL_VAL_OFFSET, 0}, {UART_TIMEOUT_CTRL_EN_BIT, false}});
EXPECT_DIF_OK(dif_uart_disable_rx_timeout(&uart_));
}
TEST_F(RxTimeoutTest, GetStatusOnly) {
// Enable RX timeout and set to 0x800000.
const uint32_t duration = 0x800000;
EXPECT_WRITE32(UART_TIMEOUT_CTRL_REG_OFFSET,
{{UART_TIMEOUT_CTRL_VAL_OFFSET, duration},
{UART_TIMEOUT_CTRL_EN_BIT, true}});
EXPECT_DIF_OK(dif_uart_enable_rx_timeout(&uart_, duration));
// Read out status only.
dif_toggle_t status = kDifToggleDisabled;
EXPECT_READ32(UART_TIMEOUT_CTRL_REG_OFFSET,
{{UART_TIMEOUT_CTRL_VAL_OFFSET, duration},
{UART_TIMEOUT_CTRL_EN_BIT, true}});
EXPECT_DIF_OK(dif_uart_get_rx_timeout(&uart_, &status, nullptr));
EXPECT_EQ(status, kDifToggleEnabled);
}
TEST_F(RxTimeoutTest, GetAll) {
// Enable RX timeout and set to 0xf0f0f0.
const uint32_t duration = 0xf0f0f0;
EXPECT_WRITE32(UART_TIMEOUT_CTRL_REG_OFFSET,
{{UART_TIMEOUT_CTRL_VAL_OFFSET, duration},
{UART_TIMEOUT_CTRL_EN_BIT, true}});
EXPECT_DIF_OK(dif_uart_enable_rx_timeout(&uart_, duration));
// Read out duration and status.
uint32_t out = 0;
dif_toggle_t status = kDifToggleDisabled;
EXPECT_READ32(UART_TIMEOUT_CTRL_REG_OFFSET,
{{UART_TIMEOUT_CTRL_VAL_OFFSET, duration},
{UART_TIMEOUT_CTRL_EN_BIT, true}});
EXPECT_DIF_OK(dif_uart_get_rx_timeout(&uart_, &status, &out));
EXPECT_EQ(status, kDifToggleEnabled);
EXPECT_EQ(out, duration);
}
} // namespace
} // namespace dif_uart_unittest