/* * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include static K_SEM_DEFINE(g_mbox_data_rx_sem, 0, 1); static uint32_t g_mbox_received_data; static uint32_t g_mbox_expected_data; static uint32_t g_mbox_received_channel; static uint32_t g_mbox_expected_channel; static bool g_received_size_error; static size_t g_received_size; static int g_max_transfer_size_bytes; #define CHANNELS_TO_TEST 4 #define TX_CHANNEL_INDEX 0 #define RX_CHANNEL_INDEX 1 static const struct mbox_dt_spec channels[CHANNELS_TO_TEST][2] = { { MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), tx0), MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), rx0), }, { MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), tx1), MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), rx1), }, { MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), tx2), MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), rx2), }, { MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), tx3), MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), rx3), }, }; static uint32_t current_channel_index; static void callback(const struct device *dev, uint32_t channel, void *user_data, struct mbox_msg *data) { /* Handle the case if received invalid size */ if (data->size > sizeof(g_mbox_received_data)) { g_received_size_error = true; g_received_size = data->size; } else { memcpy(&g_mbox_received_data, data->data, data->size); } g_mbox_received_channel = channel; k_sem_give(&g_mbox_data_rx_sem); } static void mbox_data_tests_before(void *f) { zassert_false(current_channel_index >= CHANNELS_TO_TEST, "Channel to test is out of range"); const struct mbox_dt_spec *tx_channel = &channels[current_channel_index][TX_CHANNEL_INDEX]; const struct mbox_dt_spec *rx_channel = &channels[current_channel_index][RX_CHANNEL_INDEX]; int ret_val = 0; g_max_transfer_size_bytes = mbox_mtu_get_dt(tx_channel); /* Test currently supports only transfer size up to 4 bytes */ if ((g_max_transfer_size_bytes < 0) || (g_max_transfer_size_bytes > 4)) { printk("mbox_mtu_get() error\n"); zassert_false(1, "mbox invalid maximum transfer unit: %d", g_max_transfer_size_bytes); } ret_val = mbox_register_callback_dt(rx_channel, callback, NULL); zassert_false(ret_val != 0, "mbox failed to register callback. ret_val", ret_val); ret_val = mbox_set_enabled_dt(rx_channel, 1); zassert_false(ret_val != 0, "mbox failed to enable mbox. ret_val: %d", ret_val); } static void mbox_data_tests_after(void *f) { zassert_false(current_channel_index >= CHANNELS_TO_TEST, "Channel to test is out of range"); const struct mbox_dt_spec *rx_channel = &channels[current_channel_index][RX_CHANNEL_INDEX]; /* Disable channel after test end */ int ret_val = mbox_set_enabled_dt(rx_channel, 0); zassert_false(ret_val != 0, "mbox failed to disable mbox. ret_val: %d", ret_val); /* Increment current channel index to its prepared for next test */ current_channel_index++; } static void mbox_test(const uint32_t data) { struct mbox_msg msg = {0}; uint32_t test_data = data; int test_count = 0; int ret_val = 0; while (test_count < 100) { const struct mbox_dt_spec *tx_channel = &channels[current_channel_index][TX_CHANNEL_INDEX]; /* Main core prepare test data */ msg.data = &test_data; msg.size = g_max_transfer_size_bytes; /* Main core send test data */ ret_val = mbox_send_dt(tx_channel, &msg); zassert_false(ret_val < 0, "mbox failed to send. ret_val: %d", ret_val); /* Expect next received data will be incremented by one. * And based on Maximum Transfer Unit determine expected data. * Currently supported MTU's are 1, 2, 3, and 4 bytes. */ g_mbox_expected_data = test_data & ~(0xFFFFFFFF << (g_max_transfer_size_bytes * 8)); g_mbox_expected_data++; k_sem_take(&g_mbox_data_rx_sem, K_FOREVER); if (g_received_size_error) { zassert_false(1, "mbox received invalid size in callback: %d", g_received_size); } test_data = g_mbox_received_data; /* Main core check received data */ zassert_equal(g_mbox_expected_data, test_data, "Received test_data does not match!: Expected: %08X, Got: %08X", g_mbox_expected_data, test_data); /* Expect reception of data on current RX channel */ g_mbox_expected_channel = channels[current_channel_index][RX_CHANNEL_INDEX].channel_id; zassert_equal(g_mbox_expected_channel, g_mbox_received_channel, "Received channel does not match!: Expected: %d, Got: %d", g_mbox_expected_channel, g_mbox_received_channel); /* Increment for next send */ test_data++; test_count++; } } /** * @brief MBOX Data transfer by ping pong for first set of channels * * This test verifies that the data transfer via MBOX. * Main core will transfer test data to remote core. * Remote core will increment data by one and transfer it back to Main core. * Main core will check that data it sent to remote core was incremented by one. * Main core will again increment test data by one, send it to remote core and repeat 100 times. */ ZTEST(mbox_data_tests, test_ping_pong_1) { mbox_test(0xADADADAD); } /** * @brief MBOX Data transfer by ping pong for second set of channels * * Description same as for test_ping_pong_1 * */ ZTEST(mbox_data_tests, test_ping_pong_2) { mbox_test(0xDADADADA); } /** * @brief MBOX Data transfer by ping pong for third set of channels * * Description same as for test_ping_pong_1 * */ ZTEST(mbox_data_tests, test_ping_pong_3) { mbox_test(0xADADADAD); } /** * @brief MBOX Data transfer by ping pong for forth set of channels * * Description same as for test_ping_pong_1 * */ ZTEST(mbox_data_tests, test_ping_pong_4) { mbox_test(0xDADADADA); } ZTEST_SUITE(mbox_data_tests, NULL, NULL, mbox_data_tests_before, mbox_data_tests_after, NULL);