tests: drivers: i2s_speed: Allow testing on nRF52840 DK and nRF5340 DK
This is a follow-up to commit 954dfa755b
.
Apply adjustments made in the i2s_api test to the i2s_speed one so that
it can also be executed successfully on the nRF DK boards.
Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
parent
8e1682d1ea
commit
0f949caee1
8 changed files with 333 additions and 52 deletions
|
@ -12,3 +12,25 @@ config I2S_TEST_SEPARATE_DEVICES
|
||||||
bool "Use two separate I2S ports for loopback"
|
bool "Use two separate I2S ports for loopback"
|
||||||
help
|
help
|
||||||
Use separate I2S ports for transmit and receive.
|
Use separate I2S ports for transmit and receive.
|
||||||
|
|
||||||
|
config I2S_TEST_USE_I2S_DIR_BOTH
|
||||||
|
bool "Use I2S_DIR_BOTH value to perform RX/TX transfers"
|
||||||
|
help
|
||||||
|
Use the I2S_DIR_BOTH enumeration value to trigger commands in test
|
||||||
|
cases involving both reception and transmission. Use of this option
|
||||||
|
is essential for devices that cannot independently start and stop
|
||||||
|
the RX and TX streams.
|
||||||
|
|
||||||
|
config I2S_TEST_USE_GPIO_LOOPBACK
|
||||||
|
bool "Use GPIO loopback"
|
||||||
|
help
|
||||||
|
Use wiring between the data-out and data-in pins for looping back
|
||||||
|
data. This option is intended to be used for devices that do not
|
||||||
|
provide the internal loopback functionality.
|
||||||
|
|
||||||
|
config I2S_TEST_ALLOWED_DATA_OFFSET
|
||||||
|
int "Allowed offset in received data"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
Maximum allowed offset between sent and received samples. Non-zero
|
||||||
|
value of this option may be needed when GPIO loopback is used.
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
CONFIG_I2S_TEST_USE_I2S_DIR_BOTH=y
|
||||||
|
CONFIG_I2S_TEST_USE_GPIO_LOOPBACK=y
|
||||||
|
CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET=2
|
||||||
|
CONFIG_I2S_LOG_LEVEL_INF=y
|
|
@ -0,0 +1,11 @@
|
||||||
|
&uart1 {
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2s0 {
|
||||||
|
status = "okay";
|
||||||
|
sck-pin = <36>;
|
||||||
|
lrck-pin = <35>;
|
||||||
|
sdout-pin = <34>;
|
||||||
|
sdin-pin = <33>;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
CONFIG_I2S_TEST_USE_I2S_DIR_BOTH=y
|
||||||
|
CONFIG_I2S_TEST_USE_GPIO_LOOPBACK=y
|
||||||
|
CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET=2
|
||||||
|
CONFIG_I2S_LOG_LEVEL_INF=y
|
|
@ -0,0 +1,11 @@
|
||||||
|
&uart1 {
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
&i2s0 {
|
||||||
|
status = "okay";
|
||||||
|
sck-pin = <37>;
|
||||||
|
lrck-pin = <36>;
|
||||||
|
sdout-pin = <33>;
|
||||||
|
sdin-pin = <32>;
|
||||||
|
};
|
|
@ -13,12 +13,19 @@ void test_i2s_rx_transfer_configure(void);
|
||||||
void test_i2s_transfer_short(void);
|
void test_i2s_transfer_short(void);
|
||||||
void test_i2s_transfer_long(void);
|
void test_i2s_transfer_long(void);
|
||||||
|
|
||||||
|
void test_i2s_dir_both_transfer_configure(void);
|
||||||
|
void test_i2s_dir_both_transfer_short(void);
|
||||||
|
void test_i2s_dir_both_transfer_long(void);
|
||||||
|
|
||||||
void test_main(void)
|
void test_main(void)
|
||||||
{
|
{
|
||||||
ztest_test_suite(i2s_speed_test,
|
ztest_test_suite(i2s_speed_test,
|
||||||
ztest_unit_test(test_i2s_tx_transfer_configure),
|
ztest_unit_test(test_i2s_tx_transfer_configure),
|
||||||
ztest_unit_test(test_i2s_rx_transfer_configure),
|
ztest_unit_test(test_i2s_rx_transfer_configure),
|
||||||
ztest_unit_test(test_i2s_transfer_short),
|
ztest_unit_test(test_i2s_transfer_short),
|
||||||
ztest_unit_test(test_i2s_transfer_long));
|
ztest_unit_test(test_i2s_transfer_long),
|
||||||
|
ztest_unit_test(test_i2s_dir_both_transfer_configure),
|
||||||
|
ztest_unit_test(test_i2s_dir_both_transfer_short),
|
||||||
|
ztest_unit_test(test_i2s_dir_both_transfer_long));
|
||||||
ztest_run_test_suite(i2s_speed_test);
|
ztest_run_test_suite(i2s_speed_test);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,11 @@ static int16_t data_r[SAMPLE_NO] = {
|
||||||
K_MEM_SLAB_DEFINE(rx_0_mem_slab, BLOCK_SIZE, NUM_BLOCKS + 2, 32);
|
K_MEM_SLAB_DEFINE(rx_0_mem_slab, BLOCK_SIZE, NUM_BLOCKS + 2, 32);
|
||||||
K_MEM_SLAB_DEFINE(tx_0_mem_slab, BLOCK_SIZE, NUM_BLOCKS, 32);
|
K_MEM_SLAB_DEFINE(tx_0_mem_slab, BLOCK_SIZE, NUM_BLOCKS, 32);
|
||||||
|
|
||||||
|
static const struct device *dev_i2s_rx;
|
||||||
|
static const struct device *dev_i2s_tx;
|
||||||
|
static const struct device *dev_i2s_rxtx;
|
||||||
|
static bool dir_both_supported;
|
||||||
|
|
||||||
static void fill_buf(int16_t *tx_block, int att)
|
static void fill_buf(int16_t *tx_block, int att)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SAMPLE_NO; i++) {
|
for (int i = 0; i < SAMPLE_NO; i++) {
|
||||||
|
@ -63,7 +68,28 @@ static void fill_buf(int16_t *tx_block, int att)
|
||||||
|
|
||||||
static int verify_buf(int16_t *rx_block, int att)
|
static int verify_buf(int16_t *rx_block, int att)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SAMPLE_NO; i++) {
|
int sample_no = SAMPLE_NO;
|
||||||
|
|
||||||
|
#if (CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET > 0)
|
||||||
|
static ZTEST_DMEM int offset = -1;
|
||||||
|
|
||||||
|
if (offset < 0) {
|
||||||
|
do {
|
||||||
|
++offset;
|
||||||
|
if (offset > CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET) {
|
||||||
|
TC_PRINT("Allowed data offset exceeded\n");
|
||||||
|
return -TC_FAIL;
|
||||||
|
}
|
||||||
|
} while (rx_block[2 * offset] != data_l[0] >> att);
|
||||||
|
|
||||||
|
TC_PRINT("Using data offset: %d\n", offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_block += 2 * offset;
|
||||||
|
sample_no -= offset;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i = 0; i < sample_no; i++) {
|
||||||
if (rx_block[2 * i] != data_l[i] >> att) {
|
if (rx_block[2 * i] != data_l[i] >> att) {
|
||||||
TC_PRINT("Error: att %d: data_l mismatch at position "
|
TC_PRINT("Error: att %d: data_l mismatch at position "
|
||||||
"%d, expected %d, actual %d\n",
|
"%d, expected %d, actual %d\n",
|
||||||
|
@ -84,58 +110,80 @@ static int verify_buf(int16_t *rx_block, int att)
|
||||||
#define TIMEOUT 2000
|
#define TIMEOUT 2000
|
||||||
#define FRAME_CLK_FREQ 44000
|
#define FRAME_CLK_FREQ 44000
|
||||||
|
|
||||||
/** Configure I2S TX transfer. */
|
static int configure_stream(const struct device *dev_i2s, enum i2s_dir dir)
|
||||||
void test_i2s_tx_transfer_configure(void)
|
|
||||||
{
|
{
|
||||||
const struct device *dev_i2s;
|
|
||||||
struct i2s_config i2s_cfg;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
struct i2s_config i2s_cfg;
|
||||||
dev_i2s = device_get_binding(I2S_DEV_NAME_TX);
|
|
||||||
zassert_not_null(dev_i2s, "device " I2S_DEV_NAME_TX " not found");
|
|
||||||
|
|
||||||
/* Configure */
|
|
||||||
|
|
||||||
i2s_cfg.word_size = 16U;
|
i2s_cfg.word_size = 16U;
|
||||||
i2s_cfg.channels = 2U;
|
i2s_cfg.channels = 2U;
|
||||||
i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
|
i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
|
||||||
/* Configure the Transmit port as Master */
|
|
||||||
i2s_cfg.options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER;
|
|
||||||
i2s_cfg.frame_clk_freq = FRAME_CLK_FREQ;
|
i2s_cfg.frame_clk_freq = FRAME_CLK_FREQ;
|
||||||
i2s_cfg.block_size = BLOCK_SIZE;
|
i2s_cfg.block_size = BLOCK_SIZE;
|
||||||
i2s_cfg.mem_slab = &tx_0_mem_slab;
|
|
||||||
i2s_cfg.timeout = TIMEOUT;
|
i2s_cfg.timeout = TIMEOUT;
|
||||||
i2s_cfg.options = I2S_OPT_LOOPBACK;
|
|
||||||
|
|
||||||
|
if (dir == I2S_DIR_TX) {
|
||||||
|
/* Configure the Transmit port as Master */
|
||||||
|
i2s_cfg.options = I2S_OPT_FRAME_CLK_MASTER
|
||||||
|
| I2S_OPT_BIT_CLK_MASTER;
|
||||||
|
} else if (dir == I2S_DIR_RX) {
|
||||||
|
/* Configure the Receive port as Slave */
|
||||||
|
i2s_cfg.options = I2S_OPT_FRAME_CLK_SLAVE
|
||||||
|
| I2S_OPT_BIT_CLK_SLAVE;
|
||||||
|
} else { /* dir == I2S_DIR_BOTH */
|
||||||
|
i2s_cfg.options = I2S_OPT_FRAME_CLK_MASTER
|
||||||
|
| I2S_OPT_BIT_CLK_MASTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_I2S_TEST_USE_GPIO_LOOPBACK)) {
|
||||||
|
i2s_cfg.options |= I2S_OPT_LOOPBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir == I2S_DIR_TX || dir == I2S_DIR_BOTH) {
|
||||||
|
i2s_cfg.mem_slab = &tx_0_mem_slab;
|
||||||
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
|
ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
|
||||||
zassert_equal(ret, 0, "Failed to configure I2S TX stream");
|
if (ret < 0) {
|
||||||
|
TC_PRINT("Failed to configure I2S TX stream (%d)\n",
|
||||||
|
ret);
|
||||||
|
return -TC_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir == I2S_DIR_RX || dir == I2S_DIR_BOTH) {
|
||||||
|
i2s_cfg.mem_slab = &rx_0_mem_slab;
|
||||||
|
ret = i2s_configure(dev_i2s, I2S_DIR_RX, &i2s_cfg);
|
||||||
|
if (ret < 0) {
|
||||||
|
TC_PRINT("Failed to configure I2S RX stream (%d)\n",
|
||||||
|
ret);
|
||||||
|
return -TC_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TC_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Configure I2S TX transfer. */
|
||||||
|
void test_i2s_tx_transfer_configure(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev_i2s_tx = device_get_binding(I2S_DEV_NAME_TX);
|
||||||
|
zassert_not_null(dev_i2s_tx, "device " I2S_DEV_NAME_TX " not found");
|
||||||
|
|
||||||
|
ret = configure_stream(dev_i2s_tx, I2S_DIR_TX);
|
||||||
|
zassert_equal(ret, TC_PASS, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Configure I2S RX transfer. */
|
/** Configure I2S RX transfer. */
|
||||||
void test_i2s_rx_transfer_configure(void)
|
void test_i2s_rx_transfer_configure(void)
|
||||||
{
|
{
|
||||||
const struct device *dev_i2s;
|
|
||||||
struct i2s_config i2s_cfg;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_i2s = device_get_binding(I2S_DEV_NAME_RX);
|
dev_i2s_rx = device_get_binding(I2S_DEV_NAME_RX);
|
||||||
zassert_not_null(dev_i2s, "device " I2S_DEV_NAME_RX " not found");
|
zassert_not_null(dev_i2s_rx, "device " I2S_DEV_NAME_RX " not found");
|
||||||
|
|
||||||
/* Configure */
|
ret = configure_stream(dev_i2s_rx, I2S_DIR_RX);
|
||||||
|
zassert_equal(ret, TC_PASS, NULL);
|
||||||
i2s_cfg.word_size = 16U;
|
|
||||||
i2s_cfg.channels = 2U;
|
|
||||||
i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
|
|
||||||
/* Configure the Receive port as Slave */
|
|
||||||
i2s_cfg.options = I2S_OPT_FRAME_CLK_SLAVE | I2S_OPT_BIT_CLK_SLAVE;
|
|
||||||
i2s_cfg.frame_clk_freq = FRAME_CLK_FREQ;
|
|
||||||
i2s_cfg.block_size = BLOCK_SIZE;
|
|
||||||
i2s_cfg.mem_slab = &rx_0_mem_slab;
|
|
||||||
i2s_cfg.timeout = TIMEOUT;
|
|
||||||
i2s_cfg.options = I2S_OPT_LOOPBACK;
|
|
||||||
|
|
||||||
ret = i2s_configure(dev_i2s, I2S_DIR_RX, &i2s_cfg);
|
|
||||||
zassert_equal(ret, 0, "Failed to configure I2S RX stream");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Short I2S transfer.
|
/** @brief Short I2S transfer.
|
||||||
|
@ -148,19 +196,17 @@ void test_i2s_rx_transfer_configure(void)
|
||||||
*/
|
*/
|
||||||
void test_i2s_transfer_short(void)
|
void test_i2s_transfer_short(void)
|
||||||
{
|
{
|
||||||
const struct device *dev_i2s_rx;
|
if (IS_ENABLED(CONFIG_I2S_TEST_USE_I2S_DIR_BOTH)) {
|
||||||
const struct device *dev_i2s_tx;
|
TC_PRINT("RX/TX transfer requires use of I2S_DIR_BOTH.\n");
|
||||||
|
ztest_test_skip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void *rx_block[3];
|
void *rx_block[3];
|
||||||
void *tx_block;
|
void *tx_block;
|
||||||
size_t rx_size;
|
size_t rx_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_i2s_rx = device_get_binding(I2S_DEV_NAME_RX);
|
|
||||||
zassert_not_null(dev_i2s_rx, "device " I2S_DEV_NAME_RX " not found");
|
|
||||||
|
|
||||||
dev_i2s_tx = device_get_binding(I2S_DEV_NAME_TX);
|
|
||||||
zassert_not_null(dev_i2s_tx, "device " I2S_DEV_NAME_TX " not found");
|
|
||||||
|
|
||||||
/* Prefill TX queue */
|
/* Prefill TX queue */
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block, K_FOREVER);
|
ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block, K_FOREVER);
|
||||||
|
@ -228,8 +274,12 @@ void test_i2s_transfer_short(void)
|
||||||
*/
|
*/
|
||||||
void test_i2s_transfer_long(void)
|
void test_i2s_transfer_long(void)
|
||||||
{
|
{
|
||||||
const struct device *dev_i2s_rx;
|
if (IS_ENABLED(CONFIG_I2S_TEST_USE_I2S_DIR_BOTH)) {
|
||||||
const struct device *dev_i2s_tx;
|
TC_PRINT("RX/TX transfer requires use of I2S_DIR_BOTH.\n");
|
||||||
|
ztest_test_skip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void *rx_block[NUM_BLOCKS];
|
void *rx_block[NUM_BLOCKS];
|
||||||
void *tx_block[NUM_BLOCKS];
|
void *tx_block[NUM_BLOCKS];
|
||||||
size_t rx_size;
|
size_t rx_size;
|
||||||
|
@ -238,12 +288,6 @@ void test_i2s_transfer_long(void)
|
||||||
int num_verified;
|
int num_verified;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_i2s_rx = device_get_binding(I2S_DEV_NAME_RX);
|
|
||||||
zassert_not_null(dev_i2s_rx, "device " I2S_DEV_NAME_RX " not found");
|
|
||||||
|
|
||||||
dev_i2s_tx = device_get_binding(I2S_DEV_NAME_TX);
|
|
||||||
zassert_not_null(dev_i2s_tx, "device " I2S_DEV_NAME_TX " not found");
|
|
||||||
|
|
||||||
/* Prepare TX data blocks */
|
/* Prepare TX data blocks */
|
||||||
for (tx_idx = 0; tx_idx < NUM_BLOCKS; tx_idx++) {
|
for (tx_idx = 0; tx_idx < NUM_BLOCKS; tx_idx++) {
|
||||||
ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block[tx_idx],
|
ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block[tx_idx],
|
||||||
|
@ -310,3 +354,173 @@ void test_i2s_transfer_long(void)
|
||||||
}
|
}
|
||||||
zassert_equal(num_verified, NUM_BLOCKS, "Invalid RX blocks received");
|
zassert_equal(num_verified, NUM_BLOCKS, "Invalid RX blocks received");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_i2s_dir_both_transfer_configure(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev_i2s_rxtx = device_get_binding(I2S_DEV_NAME_RX);
|
||||||
|
zassert_not_null(dev_i2s_rxtx, "device " I2S_DEV_NAME_RX " not found");
|
||||||
|
|
||||||
|
ret = configure_stream(dev_i2s_rxtx, I2S_DIR_BOTH);
|
||||||
|
zassert_equal(ret, TC_PASS, NULL);
|
||||||
|
|
||||||
|
/* Check if the tested driver supports the I2S_DIR_BOTH value.
|
||||||
|
* Use the DROP trigger for this, as in the current state of the driver
|
||||||
|
* (READY, both TX and RX queues empty) it is actually a no-op.
|
||||||
|
*/
|
||||||
|
ret = i2s_trigger(dev_i2s_rxtx, I2S_DIR_BOTH, I2S_TRIGGER_DROP);
|
||||||
|
dir_both_supported = (ret == 0);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_I2S_TEST_USE_I2S_DIR_BOTH)) {
|
||||||
|
zassert_true(dir_both_supported,
|
||||||
|
"I2S_DIR_BOTH value is supposed to be supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Short I2S transfer using I2S_DIR_BOTH.
|
||||||
|
*
|
||||||
|
* - START trigger starts both the transmission and reception.
|
||||||
|
* - Sending / receiving a short sequence of data returns success.
|
||||||
|
* - DRAIN trigger empties the transmit queue and stops both streams.
|
||||||
|
*/
|
||||||
|
void test_i2s_dir_both_transfer_short(void)
|
||||||
|
{
|
||||||
|
if (!dir_both_supported) {
|
||||||
|
TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
|
||||||
|
ztest_test_skip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *rx_block[3];
|
||||||
|
void *tx_block;
|
||||||
|
size_t rx_size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Prefill TX queue */
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block, K_FOREVER);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
fill_buf((uint16_t *)tx_block, i);
|
||||||
|
|
||||||
|
ret = i2s_write(dev_i2s_rxtx, tx_block, BLOCK_SIZE);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
|
||||||
|
TC_PRINT("%d->OK\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = i2s_trigger(dev_i2s_rxtx, I2S_DIR_BOTH, I2S_TRIGGER_START);
|
||||||
|
zassert_equal(ret, 0, "RX/TX START trigger failed\n");
|
||||||
|
|
||||||
|
/* All data written, drain TX queue and stop both streams. */
|
||||||
|
ret = i2s_trigger(dev_i2s_rxtx, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
|
||||||
|
zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
|
||||||
|
|
||||||
|
ret = i2s_read(dev_i2s_rxtx, &rx_block[0], &rx_size);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
zassert_equal(rx_size, BLOCK_SIZE, NULL);
|
||||||
|
|
||||||
|
ret = i2s_read(dev_i2s_rxtx, &rx_block[1], &rx_size);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
zassert_equal(rx_size, BLOCK_SIZE, NULL);
|
||||||
|
|
||||||
|
ret = i2s_read(dev_i2s_rxtx, &rx_block[2], &rx_size);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
zassert_equal(rx_size, BLOCK_SIZE, NULL);
|
||||||
|
|
||||||
|
/* Verify received data */
|
||||||
|
ret = verify_buf((uint16_t *)rx_block[0], 0);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
k_mem_slab_free(&rx_0_mem_slab, &rx_block[0]);
|
||||||
|
TC_PRINT("%d<-OK\n", 1);
|
||||||
|
|
||||||
|
ret = verify_buf((uint16_t *)rx_block[1], 1);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
k_mem_slab_free(&rx_0_mem_slab, &rx_block[1]);
|
||||||
|
TC_PRINT("%d<-OK\n", 2);
|
||||||
|
|
||||||
|
ret = verify_buf((uint16_t *)rx_block[2], 2);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
k_mem_slab_free(&rx_0_mem_slab, &rx_block[2]);
|
||||||
|
TC_PRINT("%d<-OK\n", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Long I2S transfer using I2S_DIR_BOTH.
|
||||||
|
*
|
||||||
|
* - START trigger starts both the transmission and reception.
|
||||||
|
* - Sending / receiving a long sequence of data returns success.
|
||||||
|
* - DRAIN trigger empties the transmit queue and stops both streams.
|
||||||
|
*/
|
||||||
|
void test_i2s_dir_both_transfer_long(void)
|
||||||
|
{
|
||||||
|
if (!dir_both_supported) {
|
||||||
|
TC_PRINT("I2S_DIR_BOTH value is not supported.\n");
|
||||||
|
ztest_test_skip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *rx_block[NUM_BLOCKS];
|
||||||
|
void *tx_block[NUM_BLOCKS];
|
||||||
|
size_t rx_size;
|
||||||
|
int tx_idx;
|
||||||
|
int rx_idx = 0;
|
||||||
|
int num_verified;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Prepare TX data blocks */
|
||||||
|
for (tx_idx = 0; tx_idx < NUM_BLOCKS; tx_idx++) {
|
||||||
|
ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block[tx_idx],
|
||||||
|
K_FOREVER);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
fill_buf((uint16_t *)tx_block[tx_idx], tx_idx % 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_idx = 0;
|
||||||
|
|
||||||
|
/* Prefill TX queue */
|
||||||
|
ret = i2s_write(dev_i2s_rxtx, tx_block[tx_idx++], BLOCK_SIZE);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
|
||||||
|
ret = i2s_write(dev_i2s_rxtx, tx_block[tx_idx++], BLOCK_SIZE);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
|
||||||
|
ret = i2s_trigger(dev_i2s_rxtx, I2S_DIR_BOTH, I2S_TRIGGER_START);
|
||||||
|
zassert_equal(ret, 0, "RX/TX START trigger failed\n");
|
||||||
|
|
||||||
|
for (; tx_idx < NUM_BLOCKS; ) {
|
||||||
|
ret = i2s_write(dev_i2s_rxtx, tx_block[tx_idx++], BLOCK_SIZE);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
|
||||||
|
ret = i2s_read(dev_i2s_rxtx, &rx_block[rx_idx++], &rx_size);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
zassert_equal(rx_size, BLOCK_SIZE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All data written, drain TX queue and stop both streams. */
|
||||||
|
ret = i2s_trigger(dev_i2s_rxtx, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN);
|
||||||
|
zassert_equal(ret, 0, "RX/TX DRAIN trigger failed");
|
||||||
|
|
||||||
|
ret = i2s_read(dev_i2s_rxtx, &rx_block[rx_idx++], &rx_size);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
zassert_equal(rx_size, BLOCK_SIZE, NULL);
|
||||||
|
|
||||||
|
ret = i2s_read(dev_i2s_rxtx, &rx_block[rx_idx++], &rx_size);
|
||||||
|
zassert_equal(ret, 0, NULL);
|
||||||
|
zassert_equal(rx_size, BLOCK_SIZE, NULL);
|
||||||
|
|
||||||
|
TC_PRINT("%d TX blocks sent\n", tx_idx);
|
||||||
|
TC_PRINT("%d RX blocks received\n", rx_idx);
|
||||||
|
|
||||||
|
/* Verify received data */
|
||||||
|
num_verified = 0;
|
||||||
|
for (rx_idx = 0; rx_idx < NUM_BLOCKS; rx_idx++) {
|
||||||
|
ret = verify_buf((uint16_t *)rx_block[rx_idx], rx_idx % 3);
|
||||||
|
if (ret != 0) {
|
||||||
|
TC_PRINT("%d RX block invalid\n", rx_idx);
|
||||||
|
} else {
|
||||||
|
num_verified++;
|
||||||
|
}
|
||||||
|
k_mem_slab_free(&rx_0_mem_slab, &rx_block[rx_idx]);
|
||||||
|
}
|
||||||
|
zassert_equal(num_verified, NUM_BLOCKS, "Invalid RX blocks received");
|
||||||
|
}
|
||||||
|
|
|
@ -2,3 +2,11 @@ tests:
|
||||||
drivers.i2s.speed:
|
drivers.i2s.speed:
|
||||||
depends_on: i2s
|
depends_on: i2s
|
||||||
tags: drivers i2s
|
tags: drivers i2s
|
||||||
|
filter: not CONFIG_I2S_TEST_USE_GPIO_LOOPBACK
|
||||||
|
drivers.i2s.speed.gpio_loopback:
|
||||||
|
depends_on: i2s
|
||||||
|
tags: drivers i2s
|
||||||
|
filter: CONFIG_I2S_TEST_USE_GPIO_LOOPBACK
|
||||||
|
harness: ztest
|
||||||
|
harness_config:
|
||||||
|
fixture: gpio_loopback
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue