tests: mbox: Add test for mbox with data transfer

This commit adds extended test for mbox driver with
data transfer to verify correct mbox functionality.

Signed-off-by: Tomas Galbicka <tomas.galbicka@nxp.com>
This commit is contained in:
Tomas Galbicka 2024-01-12 15:50:35 +01:00 committed by Fabio Baltieri
parent e776051cad
commit 554f2ba08e
22 changed files with 663 additions and 0 deletions

View file

@ -0,0 +1,29 @@
# Copyright 2024 NXP
#
# SPDX-License-Identifier: Apache-2.0
#
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/../remote/zephyr)
if(("${BOARD}" STREQUAL "mimxrt1170_evkb_cm7") OR
("${BOARD}" STREQUAL "mimxrt1170_evk_cm7") OR
("${BOARD}" STREQUAL "mimxrt1160_evk_cm7"))
message(STATUS "${BOARD} compile as Main in this sample")
else()
message(FATAL_ERROR "${BOARD} is not supported for this sample")
endif()
project(mbox_data_ipc)
enable_language(C ASM)
if(CONFIG_INCLUDE_REMOTE_DIR)
target_include_directories(zephyr_interface
INTERFACE ${REMOTE_ZEPHYR_DIR}/include/public)
endif()
target_sources(app PRIVATE src/main.c)

View file

@ -0,0 +1,11 @@
# Copyright 2024 NXP
#
# SPDX-License-Identifier: Apache-2.0
source "Kconfig.zephyr"
config INCLUDE_REMOTE_DIR
bool "Include remote core header directory"
help
Include remote build header files. Can be used if primary image
needs to be aware of size or base address of secondary image

View file

@ -0,0 +1,11 @@
# Copyright 2024 NXP
#
# SPDX-License-Identifier: Apache-2.0
source "share/sysbuild/Kconfig"
config REMOTE_BOARD
string
default "mimxrt1170_evkb_cm4" if $(BOARD) = "mimxrt1170_evkb_cm7"
default "mimxrt1170_evk_cm4" if $(BOARD) = "mimxrt1170_evk_cm7"
default "mimxrt1160_evk_cm4" if $(BOARD) = "mimxrt1160_evk_cm7"

View file

@ -0,0 +1,3 @@
CONFIG_MBOX_NXP_IMX_MU=y
CONFIG_INCLUDE_REMOTE_DIR=y
CONFIG_SECOND_CORE_MCUX=y

View file

@ -0,0 +1,29 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
/* Delete ipc chosen property where old IPM mailbox driver bellow is
* configured.
*/
/delete-property/ zephyr,ipc;
};
soc {
/* Delete IPM Driver node nxp,imx-mu */
/delete-node/ mailbox@40c48000;
/* Attach MBOX driver to MU Unit */
mbox:mbox@40c48000 {
compatible = "nxp,mbox-imx-mu";
reg = <0x40c48000 0x4000>;
interrupts = <118 0>;
rx-channels = <4>;
#mbox-cells = <1>;
status = "okay";
};
};
};

View file

@ -0,0 +1,3 @@
CONFIG_MBOX_NXP_IMX_MU=y
CONFIG_INCLUDE_REMOTE_DIR=y
CONFIG_SECOND_CORE_MCUX=y

View file

@ -0,0 +1,29 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
/* Delete ipc chosen property where old IPM mailbox driver bellow is
* configured.
*/
/delete-property/ zephyr,ipc;
};
soc {
/* Delete IPM Driver node nxp,imx-mu */
/delete-node/ mailbox@40c48000;
/* Attach MBOX driver to MU Unit */
mbox:mbox@40c48000 {
compatible = "nxp,mbox-imx-mu";
reg = <0x40c48000 0x4000>;
interrupts = <118 0>;
rx-channels = <4>;
#mbox-cells = <1>;
status = "okay";
};
};
};

View file

@ -0,0 +1,3 @@
CONFIG_MBOX_NXP_IMX_MU=y
CONFIG_SECOND_CORE_MCUX=y
CONFIG_INCLUDE_REMOTE_DIR=y

View file

@ -0,0 +1,29 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
/* Delete ipc chosen property where old IPM mailbox driver bellow is
* configured.
*/
/delete-property/ zephyr,ipc;
};
soc {
/* Delete IPM Driver node nxp,imx-mu */
/delete-node/ mailbox@40c48000;
/* Attach MBOX driver to MU Unit */
mbox:mbox@40c48000 {
compatible = "nxp,mbox-imx-mu";
reg = <0x40c48000 0x4000>;
interrupts = <118 0>;
rx-channels = <4>;
#mbox-cells = <1>;
status = "okay";
};
};
};

View file

@ -0,0 +1,3 @@
CONFIG_PRINTK=y
CONFIG_MBOX=y
CONFIG_ZTEST=y

View file

@ -0,0 +1,20 @@
# Copyright 2024 NXP
#
# SPDX-License-Identifier: Apache-2.0
#
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
if(("${BOARD}" STREQUAL "mimxrt1170_evkb_cm4") OR
("${BOARD}" STREQUAL "mimxrt1170_evk_cm4") OR
("${BOARD}" STREQUAL "mimxrt1160_evk_cm4"))
message(STATUS "${BOARD} compile as remote in this sample")
else()
message(FATAL_ERROR "${BOARD} is not supported for this sample")
endif()
project(mbox_data_ipc_remote)
target_sources(app PRIVATE src/main.c)

View file

@ -0,0 +1,4 @@
CONFIG_MBOX_NXP_IMX_MU=y
CONFIG_BUILD_OUTPUT_INFO_HEADER=y
CONFIG_BUILD_OUTPUT_HEX=y
CONFIG_SECOND_CORE_MCUX=y

View file

@ -0,0 +1,54 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
zephyr,flash = &ocram;
zephyr,console = &lpuart2;
zephyr,shell-uart = &lpuart2;
/* Delete ipc chosen property where old IPM mailbox driver bellow is
* configured.
*/
/delete-property/ zephyr,ipc;
};
soc {
/delete-node/ gpt@400f0000;
/* Replace GPT2 with another GPT kernel timer */
gpt2_hw_timer:gpt@400f0000 {
compatible = "nxp,gpt-hw-timer";
reg = <0x400f0000 0x4000>;
interrupts = <120 0>;
status = "okay";
};
/* Delete IPM Driver node nxp,imx-mu */
/delete-node/ mailbox@40c4c000;
/* Attach MBOX driver to MU Unit */
mbox:mbox@40c4c000 {
compatible = "nxp,mbox-imx-mu";
reg = <0x40c4c000 0x4000>;
interrupts = <118 0>;
rx-channels = <4>;
#mbox-cells = <1>;
status = "okay";
};
};
};
/* Enable secondary LPUART */
&lpuart2 {
status = "okay";
current-speed = <115200>;
};
/* Disable primary GPT timer */
&gpt_hw_timer {
status = "disabled";
};

View file

@ -0,0 +1,4 @@
CONFIG_MBOX_NXP_IMX_MU=y
CONFIG_BUILD_OUTPUT_INFO_HEADER=y
CONFIG_BUILD_OUTPUT_HEX=y
CONFIG_SECOND_CORE_MCUX=y

View file

@ -0,0 +1,54 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
zephyr,flash = &ocram;
zephyr,console = &lpuart2;
zephyr,shell-uart = &lpuart2;
/* Delete ipc chosen property where old IPM mailbox driver bellow is
* configured.
*/
/delete-property/ zephyr,ipc;
};
soc {
/delete-node/ gpt@400f0000;
/* Replace GPT2 with another GPT kernel timer */
gpt2_hw_timer:gpt@400f0000 {
compatible = "nxp,gpt-hw-timer";
reg = <0x400f0000 0x4000>;
interrupts = <120 0>;
status = "okay";
};
/* Delete IPM Driver node nxp,imx-mu */
/delete-node/ mailbox@40c4c000;
/* Attach MBOX driver to MU Unit */
mbox:mbox@40c4c000 {
compatible = "nxp,mbox-imx-mu";
reg = <0x40c4c000 0x4000>;
interrupts = <118 0>;
rx-channels = <4>;
#mbox-cells = <1>;
status = "okay";
};
};
};
/* Enable secondary LPUART */
&lpuart2 {
status = "okay";
current-speed = <115200>;
};
/* Disable primary GPT timer */
&gpt_hw_timer {
status = "disabled";
};

View file

@ -0,0 +1,4 @@
CONFIG_MBOX_NXP_IMX_MU=y
CONFIG_BUILD_OUTPUT_INFO_HEADER=y
CONFIG_BUILD_OUTPUT_HEX=y
CONFIG_SECOND_CORE_MCUX=y

View file

@ -0,0 +1,55 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
zephyr,flash = &ocram;
zephyr,console = &lpuart2;
zephyr,shell-uart = &lpuart2;
/* Delete ipc chosen property where old IPM mailbox driver bellow is
* configured.
*/
/delete-property/ zephyr,ipc;
};
soc {
/delete-node/ gpt@400f0000;
/* Replace GPT2 with another GPT kernel timer */
gpt2_hw_timer:gpt@400f0000 {
compatible = "nxp,gpt-hw-timer";
reg = <0x400f0000 0x4000>;
interrupts = <120 0>;
status = "okay";
};
/* Delete IPM Driver node nxp,imx-mu */
/delete-node/ mailbox@40c4c000;
/* Attach MBOX driver to MU Unit */
mbox:mbox@40c4c000 {
compatible = "nxp,mbox-imx-mu";
reg = <0x40c4c000 0x4000>;
interrupts = <118 0>;
rx-channels = <4>;
#mbox-cells = <1>;
status = "okay";
};
};
};
/* Enable secondary LPUART */
&lpuart2 {
status = "okay";
current-speed = <115200>;
};
/* Disable primary GPT timer */
&gpt_hw_timer {
status = "disabled";
};

View file

@ -0,0 +1,3 @@
CONFIG_STDOUT_CONSOLE=n
CONFIG_MBOX=y
# CONFIG_NO_OPTIMIZATIONS=y

View file

@ -0,0 +1,91 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/mbox.h>
static K_SEM_DEFINE(g_mbox_data_rx_sem, 0, 1);
static uint32_t g_mbox_received_data;
static uint32_t g_mbox_received_channel;
#define TX_ID0 (2)
#define RX_ID0 (3)
#define TX_ID1 (0)
#define RX_ID1 (1)
#define TX_ID2 (3)
#define RX_ID2 (2)
#define TX_ID3 (1)
#define RX_ID3 (0)
#define CHANNELS_TO_TEST (4)
#define TX_CHANNEL_INDEX (0)
#define RX_CHANNEL_INDEX (1)
const static uint32_t TEST_CHANNELS[CHANNELS_TO_TEST][2] = {
{TX_ID0, RX_ID0}, {TX_ID1, RX_ID1}, {TX_ID2, RX_ID2}, {TX_ID3, RX_ID3}};
static void callback(const struct device *dev, uint32_t channel, void *user_data,
struct mbox_msg *data)
{
if (data != NULL) {
memcpy(&g_mbox_received_data, data->data, data->size);
g_mbox_received_channel = channel;
}
k_sem_give(&g_mbox_data_rx_sem);
}
int main(void)
{
struct mbox_channel tx_channel;
struct mbox_channel rx_channel;
const struct device *dev;
struct mbox_msg msg = {0};
uint32_t message = 0;
dev = DEVICE_DT_GET(DT_NODELABEL(mbox));
for (int i_test_channel = 0; i_test_channel < CHANNELS_TO_TEST; i_test_channel++) {
mbox_init_channel(&tx_channel, dev,
TEST_CHANNELS[i_test_channel][TX_CHANNEL_INDEX]);
mbox_init_channel(&rx_channel, dev,
TEST_CHANNELS[i_test_channel][RX_CHANNEL_INDEX]);
if (mbox_register_callback(&rx_channel, callback, NULL)) {
printk("mbox_register_callback() error\n");
return 0;
}
if (mbox_set_enabled(&rx_channel, 1)) {
printk("mbox_set_enable() error\n");
return 0;
}
int test_count = 0;
while (test_count < 100) {
test_count++;
k_sem_take(&g_mbox_data_rx_sem, K_FOREVER);
message = g_mbox_received_data;
message++;
msg.data = &message;
msg.size = 4;
if (mbox_send(&tx_channel, &msg) < 0) {
printk("mbox_send() error\n");
return 0;
}
}
/* Disable current rx channel after channel loop */
mbox_set_enabled(&rx_channel, 0);
}
}

View file

@ -0,0 +1,184 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/mbox.h>
#include <zephyr/ztest.h>
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 struct mbox_channel g_tx_channel;
static struct mbox_channel g_rx_channel;
#define TX_ID0 (3)
#define RX_ID0 (2)
#define TX_ID1 (1)
#define RX_ID1 (0)
#define TX_ID2 (2)
#define RX_ID2 (3)
#define TX_ID3 (0)
#define RX_ID3 (1)
#define CHANNELS_TO_TEST (4)
#define TX_CHANNEL_INDEX (0)
#define RX_CHANNEL_INDEX (1)
const static uint32_t TEST_CHANNELS[CHANNELS_TO_TEST][2] = {
{TX_ID0, RX_ID0}, {TX_ID1, RX_ID1}, {TX_ID2, RX_ID2}, {TX_ID3, RX_ID3}};
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 device *dev;
int ret_val = 0;
dev = DEVICE_DT_GET(DT_NODELABEL(mbox));
mbox_init_channel(&g_tx_channel, dev,
TEST_CHANNELS[current_channel_index][TX_CHANNEL_INDEX]);
mbox_init_channel(&g_rx_channel, dev,
TEST_CHANNELS[current_channel_index][RX_CHANNEL_INDEX]);
ret_val = mbox_register_callback(&g_rx_channel, callback, NULL);
zassert_false(ret_val != 0, "mbox failed to register callback. ret_val", ret_val);
ret_val = mbox_set_enabled(&g_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)
{
/* Disable channel after test end */
int ret_val = mbox_set_enabled(&g_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) {
/* Main core prepare test data */
msg.data = &test_data;
msg.size = 4;
/* Main core send test data */
ret_val = mbox_send(&g_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 */
g_mbox_expected_data = test_data;
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 = TEST_CHANNELS[current_channel_index][RX_CHANNEL_INDEX];
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);

View file

@ -0,0 +1,28 @@
# Copyright 2024 NXP
#
# SPDX-License-Identifier: Apache-2.0
if("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "")
message(FATAL_ERROR
"Target ${BOARD} not supported for this sample. "
"There is no remote board selected in Kconfig.sysbuild")
endif()
set(REMOTE_APP remote)
ExternalZephyrProject_Add(
APPLICATION ${REMOTE_APP}
SOURCE_DIR ${APP_DIR}/${REMOTE_APP}
BOARD ${SB_CONFIG_REMOTE_BOARD}
)
if ("${BOARD}" STREQUAL "mimxrt1170_evkb_cm7" OR
"${BOARD}" STREQUAL "mimxrt1170_evk_cm7" OR
"${BOARD}" STREQUAL "mimxrt1160_evk_cm7"
)
# For these NXP boards the main core application is dependent on
# 'zephyr_image_info.h' generated by remote application.
# Let's build the remote application first
add_dependencies(${DEFAULT_IMAGE} ${REMOTE_APP})
endif()

View file

@ -0,0 +1,12 @@
tests:
drivers.mbox_data:
tags:
- drivers
- mbox
sysbuild: true
platform_allow:
- mimxrt1170_evkb_cm7
- mimxrt1170_evk_cm7
- mimxrt1160_evk_cm7
integration_platforms:
- mimxrt1170_evkb_cm7