From 8f89df495f20d46a57592f8e77242eb9c1954a10 Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Fri, 2 May 2025 14:38:30 +0100 Subject: [PATCH 1/8] arch/aarch64: Return error if IAR queried outside ISR The AArch64 interrupt interface is currently inconsistent with the Arm-m interface in that it returns FWK_SUCCESS if the current interrupt ID is queried outside of an interrupt handler. Add logic to arch_interrupt_get_current to return FWK_E_STATE instead in this condition. Signed-off-by: Peter Hoyes --- arch/arm/aarch64/src/arch_gic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/aarch64/src/arch_gic.c b/arch/arm/aarch64/src/arch_gic.c index fd01fe5f4..0790cb70d 100644 --- a/arch/arm/aarch64/src/arch_gic.c +++ b/arch/arm/aarch64/src/arch_gic.c @@ -272,6 +272,10 @@ int arch_interrupt_get_current(unsigned int *interrupt) return FWK_E_PARAM; } + if (current_iar >= INTERRUPT_ID_ISR_LIMIT) { + return FWK_E_STATE; + } + *interrupt = current_iar; return FWK_SUCCESS; -- GitLab From 7c00612f89b23eaab186dfe14487562521e092e5 Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Fri, 2 May 2025 14:42:13 +0100 Subject: [PATCH 2/8] fwk/debugger: Support 64-bit builds Certain parts of the debugger CLI assume that pointers are 32-bits. Replace uint32_t with uintptr_t in these instances. Fix cppcheck issues related to const pointers. Signed-off-by: Peter Hoyes --- debugger/src/cli/cli_commands_core.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/debugger/src/cli/cli_commands_core.c b/debugger/src/cli/cli_commands_core.c index 81e15c04f..7fed18fbd 100644 --- a/debugger/src/cli/cli_commands_core.c +++ b/debugger/src/cli/cli_commands_core.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -58,6 +58,7 @@ #include +#include #include #include #include @@ -81,15 +82,15 @@ static int32_t dump_memory_f(int32_t argc, char **argv) * size parameters. */ uint32_t j; - uint32_t addr = (uint32_t)(strtoul(argv[1], 0, 0) & 0xFFFFFFF8); - uint32_t size = (uint32_t)(strtoul(argv[2], 0, 0) & 0x000003F8); + uintptr_t addr = (uintptr_t)(strtoul(argv[1], 0, 0) & 0xFFFFFFF8); + size_t size = (size_t)(strtoul(argv[2], 0, 0) & 0x000003F8); uint32_t i = 0; /* Sanity check. */ if (size == 0) return FWK_E_PARAM; - cli_printf(NONE, "Reading %d bytes from 0x%08x.\n", size, addr); + cli_printf(NONE, "Reading %zu bytes from 0x%" PRIxPTR ".\n", size, addr); /* Loop through all bytes. */ for (i = 0; i < size; i = i + NUM_BYTES_PER_LINE) { @@ -125,7 +126,7 @@ static int32_t dump_memory_f(int32_t argc, char **argv) * deviations for given iteration */ #define MAX_CYCLE_BUFFER_SZ 256 -volatile uint32_t cycle_buffer[MAX_CYCLE_BUFFER_SZ] = { 0 }; +volatile uintptr_t cycle_buffer[MAX_CYCLE_BUFFER_SZ] = { 0 }; static const char cycle_memory_call[] = "cyclemem"; static const char cycle_memory_help[] = @@ -135,10 +136,10 @@ static const char cycle_memory_help[] = " Base address and size must be on 4 byte boundaries.\n"; static int32_t cycle_memory_f(int32_t argc, char **argv) { - uint32_t addr = (uint32_t)(strtoul(argv[1], 0, 0) & 0xFFFFFFF8); - uint32_t size = (uint32_t)strtoul(argv[2], 0, 0); + uintptr_t addr = (uintptr_t)(strtoul(argv[1], 0, 0) & 0xFFFFFFF8); + size_t size = (size_t)strtoul(argv[2], 0, 0); uint32_t iterations = (uint32_t)strtoul(argv[3], 0, 0); - volatile uint32_t *tmp_address = (volatile uint32_t *)addr; + volatile uintptr_t *tmp_address = (volatile uintptr_t *)addr; uint32_t deviation_count = 0; uint32_t cycle_count, index = 0; @@ -146,7 +147,7 @@ static int32_t cycle_memory_f(int32_t argc, char **argv) if ((size == 0) || (size > MAX_CYCLE_BUFFER_SZ)) return FWK_E_PARAM; - memset((void *)cycle_buffer, 0, sizeof(uint32_t) * MAX_CYCLE_BUFFER_SZ); + memset((void *)cycle_buffer, 0, sizeof(uintptr_t) * MAX_CYCLE_BUFFER_SZ); cli_printf( NONE, -- GitLab From 4827721eb3b1310c7c338ac9ed64f4e250fe4cf4 Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Wed, 13 Nov 2024 16:47:01 +0000 Subject: [PATCH 3/8] arch/aarch64: Add support for FWK_CONSTRUCTOR functions Certain SCP-firmware framework functionality (notifications, time, buffered logging) requires initializers that run before arm_main(), using the FWK_CONSTRUCTOR attribute. Newlib provides __libc_init_array to iterate and call these, so add this to arch_crt0.s, so long as Newlib is being used. __libc_init_array calls _init, which is defined in crti, which is linked by default by GCC but must be manually linked when using Clang. Therefore add the path of crti to the Clang linker flags. Add a note to aarch64.md about the Newlib requirement to use FWK_CONSTRUCTOR attributes. Signed-off-by: Peter Hoyes --- arch/arm/aarch64/src/arch_crt0.S | 8 ++++++++ cmake/Toolchain/Clang-Baremetal.cmake | 8 ++++++++ doc/aarch64.md | 3 +++ 3 files changed, 19 insertions(+) diff --git a/arch/arm/aarch64/src/arch_crt0.S b/arch/arm/aarch64/src/arch_crt0.S index 667d72db0..b791cd857 100644 --- a/arch/arm/aarch64/src/arch_crt0.S +++ b/arch/arm/aarch64/src/arch_crt0.S @@ -10,6 +10,9 @@ .section .entrypoint, "ax" +#ifdef USE_NEWLIB + .extern __libc_init_array +#endif .extern arm_main .global arch_exception_reset; @@ -110,6 +113,11 @@ skip_bss: ldr x0, =stack_top mov sp, x0 +#ifdef USE_NEWLIB + /* Call FWK_CONSTRUCTOR functions */ + bl __libc_init_array +#endif + bl arm_main wfe_loop: diff --git a/cmake/Toolchain/Clang-Baremetal.cmake b/cmake/Toolchain/Clang-Baremetal.cmake index ee5fb82e9..274327a45 100644 --- a/cmake/Toolchain/Clang-Baremetal.cmake +++ b/cmake/Toolchain/Clang-Baremetal.cmake @@ -89,6 +89,14 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT "-I\"${LLVM_SYSROOT_PATH}/include\" ") if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT "-L${GCC_LIBGCC_PATH} ") + foreach(crtobj IN ITEMS crti) + execute_process( + COMMAND "${SCP_LLVM_SYSROOT_CC}" "--print-file-name=${crtobj}.o" + OUTPUT_VARIABLE gcc-${crtobj} + OUTPUT_STRIP_TRAILING_WHITESPACE) + cmake_path(NORMAL_PATH gcc-${crtobj} OUTPUT_VARIABLE gcc-${crtobj}) + string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT "${gcc-${crtobj}} ") + endforeach() else() string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT "-L${LLVM_SYSROOT_PATH}/lib/${gcc-multi-dir} ") diff --git a/doc/aarch64.md b/doc/aarch64.md index 94deec64a..c788f212f 100644 --- a/doc/aarch64.md +++ b/doc/aarch64.md @@ -15,6 +15,9 @@ Note that AArch64 support only uses one exception level, the initial EL at boot. For Armv8-R64, this means the firmware runs exclusively at secure EL2, and no attempts are made to initialize the EL1/0 environment. +Newlib is required to use certain SCP-firmware features on AArch64 that require +early initialization, such as notifications. + Both GCC and Clang are supported, but not Arm Clang. ## Interrupt handling -- GitLab From a1c7efe85d53aa1cece6928cc4ed45db5265f4f2 Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Fri, 2 May 2025 14:35:11 +0100 Subject: [PATCH 4/8] mod/integration_test: Introduce module Introduce a module to simplify running integration tests using the Unity test framework. It allows tests to be executed either automatically on boot or via the debugger CLI. Tests triggered via the debugger CLI are scheduled to run on the main event loop. Signed-off-by: Peter Hoyes Signed-off-by: Athul P Satheesan --- module/CMakeLists.txt | 1 + module/integration_test/CMakeLists.txt | 32 ++ module/integration_test/Module.cmake | 9 + .../integration_test/doc/integration_test.md | 72 +++++ .../include/mod_integration_test.h | 99 ++++++ .../integration_test/include/unity_config.h | 19 ++ .../src/mod_integration_test.c | 291 ++++++++++++++++++ 7 files changed, 523 insertions(+) create mode 100644 module/integration_test/CMakeLists.txt create mode 100644 module/integration_test/Module.cmake create mode 100644 module/integration_test/doc/integration_test.md create mode 100644 module/integration_test/include/mod_integration_test.h create mode 100644 module/integration_test/include/unity_config.h create mode 100644 module/integration_test/src/mod_integration_test.c diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index 4bca96c97..22e73b53c 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -41,6 +41,7 @@ list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/atu_mmio") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/gicx00") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/gtimer") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/i2c") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/integration_test") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/isys_rom") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/metrics_analyzer") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/mhu") diff --git a/module/integration_test/CMakeLists.txt b/module/integration_test/CMakeLists.txt new file mode 100644 index 000000000..63ab61799 --- /dev/null +++ b/module/integration_test/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(CONTRIB_ROOT ${CMAKE_SOURCE_DIR}/contrib) +set(UNITY_SRC_ROOT ${CONTRIB_ROOT}/cmock/git/vendor/unity/src) +set(UNIT_TEST_ROOT ${CMAKE_SOURCE_DIR}/unit_test) + +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories( + ${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${UNIT_TEST_ROOT}/unity_mocks" + ${CMOCK_SRC_ROOT} + ${UNITY_SRC_ROOT}) + +target_sources( + ${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_integration_test.c" + "${UNITY_SRC_ROOT}/unity.c" + "${UNIT_TEST_ROOT}/unity_mocks/scp_unity.c") + +get_target_property(target_type ${SCP_MODULE_TARGET} TYPE) +if(NOT target_type STREQUAL "INTERFACE_LIBRARY") + target_compile_definitions( + ${SCP_MODULE_TARGET} + PUBLIC "UNITY_INCLUDE_CONFIG_H") +endif() diff --git a/module/integration_test/Module.cmake b/module/integration_test/Module.cmake new file mode 100644 index 000000000..96b70d411 --- /dev/null +++ b/module/integration_test/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "integration-test") +set(SCP_MODULE_TARGET "module-integration-test") diff --git a/module/integration_test/doc/integration_test.md b/module/integration_test/doc/integration_test.md new file mode 100644 index 000000000..5608ee34c --- /dev/null +++ b/module/integration_test/doc/integration_test.md @@ -0,0 +1,72 @@ +\ingroup GroupModules Modules +\defgroup GroupIntegrationTest Integration Test + +# Integration Test + +This is a module to help orchestrate integration tests written using the Unity +test framework at runtime. Tests may run automatically at boot, or on demand +using the debugger CLI. + +## Design goals + + * Use the same test framework for integration tests as for unit tests. + * Test suites may use the event loop (i.e. tests triggered using the CLI are + scheduled for execution once the CLI is exited). Tests may return to the + event loop during test execution. + * Test suites may be triggered on demand (i.e. do not interfere with the + normal boot flow). + * Test suites can be configured to run automatically during system boot + +## Writing an integration test + +Integration tests should be written as standard SCP-firmware modules which +expose the `mod_integration_test_api` API. At least the `run` and `test_name` +methods should be implemented: + * `run`: Points to a method which switches control flow to the relevant + test function + * `test_name`: Points to a method which returns the name of the currently active + test case. + +The `setup` and `teardown` methods may also be implemented, which will execute +before and after (respectively) each test case in the test suite. + +## Configuration + +The integration test module should be configured at the product level using +element-based configuration. Each test suite is defined as a module element +with associated metadata, e.g.: + +```C +#include + +#include + +static const struct fwk_element config_integration_test_elements[] = { + [TEST_ABC] = { + .name = "abc", + .data = &(struct mod_integration_test_config){ + .test_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TEST_ABC), + .run_at_start = false, + .num_test_cases = 3, + }, + }, + [TEST_COUNT] = { 0 }, +}; + +/* + * Configuration for the integration test module + */ + struct fwk_module_config config_integration_test = { + .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(config_integration_test_elements), +}; + +``` + +## Usage + +- Test suites may be triggered: + - Automatically at boot (if configured with `run_at_start = true`) + - On demand using the debugger CLI: + 1. Enter the debugger CLI using Ctrl+E. + 2. Run the command `test abc`, where abc is the test name defined above. + 3. Exit the debugger CLI using Ctrl+D to run the test. diff --git a/module/integration_test/include/mod_integration_test.h b/module/integration_test/include/mod_integration_test.h new file mode 100644 index 000000000..e457510c4 --- /dev/null +++ b/module/integration_test/include/mod_integration_test.h @@ -0,0 +1,99 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Integration test module definition. + */ + +#ifndef MOD_INTEGRATION_TEST_H +#define MOD_INTEGRATION_TEST_H + +#include +#include + +#include +#include + +/*! + * \ingroup GroupModules + * \defgroup GroupIntegrationTest Integration Test + * \{ + */ + +/*! + * \brief Event indices. + */ +enum mod_integration_test_event_idx { + MOD_INTEGRATION_TEST_EVENT_IDX_RUN_TEST_SUITE, + MOD_INTEGRATION_TEST_EVENT_IDX_CONTINUE_STEP, + MOD_INTEGRATION_TEST_EVENT_IDX_COUNT, +}; + +/*! + * \brief Event ID used by test modules to signal continuation of a test step. + */ +#define MOD_INTEGRATION_TEST_EVENT_ID_STEP_CONTINUE \ + FWK_ID_EVENT_INIT( \ + FWK_MODULE_IDX_INTEGRATION_TEST, \ + MOD_INTEGRATION_TEST_EVENT_IDX_CONTINUE_STEP) + +/*! + * \brief APIs that the module makes available to entities requesting binding. + */ +enum mod_integration_test_api_idx { + /*! Integration test */ + MOD_INTEGRATION_TEST_API_IDX_TEST, + + /*! Number of defined APIs */ + MOD_INTEGRATION_TEST_API_COUNT, +}; + +/*! + * \brief API to be exposed by test modules. + */ +struct mod_integration_test_api { + /*! Run test suite */ + int (*run)( + unsigned int case_idx, + unsigned int step_idx, + const struct fwk_event *event); + + /*! Obtain test case name */ + const char *(*test_name)(unsigned int case_idx); + + /*! Setup before each test case (may be NULL) */ + void (*setup)(void); + + /*! Teardown after each test case (may be NULL) */ + void (*teardown)(void); +}; + +/*! + * \brief Integration test device descriptor + */ +struct mod_integration_test_config { + /*! + * \brief Test module ID + */ + fwk_id_t test_id; + + /*! + * \brief Run the test suite automatically at boot + * + * This may be useful during test development. + */ + bool run_at_start; + /*! + * \brief Number of Test cases + */ + unsigned int num_test_cases; +}; + +/*! + * \} + */ + +#endif /* MOD_INTEGRATION_TEST_H */ diff --git a/module/integration_test/include/unity_config.h b/module/integration_test/include/unity_config.h new file mode 100644 index 000000000..19ece8f05 --- /dev/null +++ b/module/integration_test/include/unity_config.h @@ -0,0 +1,19 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UNITY_CONFIG_H +#define UNITY_CONFIG_H +#include +#define UNITY_OUTPUT_CHAR(a) fwk_io_putch(fwk_io_stdout, a) +#define UNITY_OUTPUT_FLUSH() +#define UNITY_PRINT_EOL() \ + { \ + UNITY_OUTPUT_CHAR('\r'); \ + UNITY_OUTPUT_CHAR('\n'); \ + } + +#endif diff --git a/module/integration_test/src/mod_integration_test.c b/module/integration_test/src/mod_integration_test.c new file mode 100644 index 000000000..0e666071d --- /dev/null +++ b/module/integration_test/src/mod_integration_test.c @@ -0,0 +1,291 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef BUILD_HAS_DEBUGGER +# include +#endif + +#include "unity.h" + +#define MOD_NAME "[INTEGRATION_TEST] " + +static const fwk_id_t mod_integration_test = + FWK_ID_MODULE_INIT(FWK_MODULE_IDX_INTEGRATION_TEST); + +/*! + * \brief Identifier for the + * ::MOD_INTEGRATION_TEST_EVENT_IDX_RUN_TEST_SUITE event. + */ +static const fwk_id_t mod_integration_test_event_id_run_suite = + FWK_ID_EVENT_INIT( + FWK_MODULE_IDX_INTEGRATION_TEST, + MOD_INTEGRATION_TEST_EVENT_IDX_RUN_TEST_SUITE); +/*! + * \brief Identifier for the + * ::MOD_INTEGRATION_TEST_EVENT_IDX_CONTINUE_STEP event. + */ +static const fwk_id_t mod_integration_test_event_id_step_continue = + FWK_ID_EVENT_INIT( + FWK_MODULE_IDX_INTEGRATION_TEST, + MOD_INTEGRATION_TEST_EVENT_IDX_CONTINUE_STEP); + +#define MAX_TEST_NAME_LENGTH 256 + +static struct { + unsigned int suite_idx; + unsigned int case_idx; + const struct mod_integration_test_config *config; + const struct mod_integration_test_api **apis; +} ctx; + +#ifdef BUILD_HAS_DEBUGGER +static int32_t schedule_integration_test(int32_t argc, char **argv) +{ + int status; + const char *suite_name; + size_t test_suite_count, idx = 0; + + if (argc != 2) { + return FWK_E_PARAM; + } + + suite_name = argv[1]; + + status = + fwk_module_get_element_count(mod_integration_test, &test_suite_count); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR("Failed to get test suite count (status = %d)", status); + return status; + } + + for (idx = 0; idx < test_suite_count; idx++) { + fwk_id_t element_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_INTEGRATION_TEST, idx); + const char *name = fwk_module_get_element_name(element_id); + if (cli_strncmp(name, suite_name, MAX_TEST_NAME_LENGTH) == 0) { + struct fwk_event event = { + .id = mod_integration_test_event_id_run_suite, + .source_id = mod_integration_test, + .target_id = mod_integration_test, + .params = { idx } + }; + return fwk_put_event(&event); + } + } + + return FWK_E_PARAM; +} +#endif + +void setUp(void) +{ + if (ctx.apis[ctx.suite_idx]->setup != NULL) { + ctx.apis[ctx.suite_idx]->setup(); + } +} + +void tearDown(void) +{ + if (ctx.apis[ctx.suite_idx]->teardown != NULL) { + ctx.apis[ctx.suite_idx]->teardown(); + } +} + +static int run_test_case(void) +{ + const char *test_name = ctx.apis[ctx.suite_idx]->test_name(ctx.case_idx); + UNITY_NEW_TEST(test_name); + /* Call the setUp function, ensuring that any assertions return + here */ + if (TEST_PROTECT()) { + setUp(); + } + + struct fwk_event event = { .id = + mod_integration_test_event_id_step_continue, + .target_id = mod_integration_test, + .params = { ctx.suite_idx, 0 } }; + + return fwk_put_event(&event); +} + +static int continue_test_case(const struct fwk_event *event) +{ + int status; + unsigned int step_idx = event->params[1]; + volatile fwk_id_t element_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_INTEGRATION_TEST, ctx.suite_idx); + const struct mod_integration_test_config *config = + fwk_module_get_data(element_id); + + /* Run the test case, ensuring that any assertions return here */ + if (TEST_PROTECT()) { + status = ctx.apis[ctx.suite_idx]->run(ctx.case_idx, step_idx, event); + /* Tests return FWK_PENDING to indicate they are awaiting an event */ + if (status == FWK_PENDING) + return FWK_SUCCESS; + } + + /* The test finished (success or failure) so call tearDown */ + if (TEST_PROTECT()) { + if (!TEST_IS_IGNORED) { + tearDown(); + } + UnityConcludeTest(); + } + + /* Advance to the next test case in the suite */ + ctx.case_idx++; + + if (ctx.case_idx >= config->num_test_cases) { + /* The test suite has finished */ + int status = UNITY_END(); + FWK_LOG_INFO( + MOD_NAME "End: %s", fwk_module_get_element_name(element_id)); + return status; + } + + return run_test_case(); +} + +static int start_test(unsigned int idx) +{ + /* Set idx in the context for setup/teardown functions to use */ + ctx.suite_idx = idx; + ctx.case_idx = 0; + + FWK_LOG_INFO( + MOD_NAME "Start: %s", + fwk_module_get_element_name( + FWK_ID_ELEMENT(FWK_MODULE_IDX_INTEGRATION_TEST, idx))); + + UNITY_BEGIN(); + return run_test_case(); +} + +static int integration_test_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + ctx.config = data; + +#ifdef BUILD_HAS_DEBUGGER + int status; + status = cli_command_register((cli_command_st){ + "test", "Schedule test suite(s)", schedule_integration_test, false }); + if (status != FWK_SUCCESS) { + return status; + } +#endif + + fwk_assert(element_count < UINT8_MAX); + + /* Allocate context */ + ctx.apis = fwk_mm_calloc(element_count, sizeof(*ctx.apis)); + + return FWK_SUCCESS; +} + +static int integration_test_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + +static int integration_test_bind(fwk_id_t id, unsigned int round) +{ + unsigned int idx; + int status; + + if (round > 0) { + return FWK_SUCCESS; + } + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) + return FWK_SUCCESS; + + const struct mod_integration_test_config *config = fwk_module_get_data(id); + idx = fwk_id_get_element_idx(id); + fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_INTEGRATION_TEST, idx); + const char *name = fwk_module_get_element_name(elem_id); + status = fwk_module_bind( + config->test_id, + FWK_ID_API( + fwk_id_get_module_idx(config->test_id), + MOD_INTEGRATION_TEST_API_IDX_TEST), + &ctx.apis[idx]); + if (status != FWK_SUCCESS) { + FWK_LOG_ERR("Error binding to test %s", name); + return status; + } + return FWK_SUCCESS; +} + +static int integration_test_process_event( + const struct fwk_event *event, + struct fwk_event *resp_event) +{ + /* Process event to start a specific suite (triggered from CLI or boot) */ + if (fwk_id_is_equal(event->id, mod_integration_test_event_id_run_suite)) { + return start_test(event->params[0]); + } + + /* Handle continuation step for an in-progress test case */ + if (fwk_id_is_equal( + event->id, mod_integration_test_event_id_step_continue)) { + return continue_test_case(event); + } + return FWK_E_PARAM; +} + +static int integration_test_start(fwk_id_t id) +{ + int status = FWK_SUCCESS; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) + return FWK_SUCCESS; + + const struct mod_integration_test_config *config = fwk_module_get_data(id); + + if (config->run_at_start) { + struct fwk_event event = { .id = + mod_integration_test_event_id_run_suite, + .source_id = mod_integration_test, + .target_id = mod_integration_test, + .params = { fwk_id_get_element_idx(id) } }; + + status = fwk_put_event(&event); + if (status != FWK_SUCCESS) { + fwk_unexpected(); + } + } + + return status; +} + +const struct fwk_module module_integration_test = { + .type = FWK_MODULE_TYPE_SERVICE, + .init = integration_test_init, + .element_init = integration_test_element_init, + .bind = integration_test_bind, + .process_event = integration_test_process_event, + .event_count = MOD_INTEGRATION_TEST_EVENT_IDX_COUNT, + .start = integration_test_start, +}; -- GitLab From 0ac8b791c72f7462d9ec71ed68bf6934401acfb0 Mon Sep 17 00:00:00 2001 From: Athul P Satheesan Date: Wed, 18 Jun 2025 10:27:18 +0530 Subject: [PATCH 5/8] arch/aarch64: Allow '0' as valid ISR parameter in interrupt registration The arch_interrupt_set_isr_irq_param() implementation previously rejected registration of an interrupt handler if the parameter value was 0. This prevented valid use cases such as debugger CLI modules which legitimately use 0 as the callback parameter. Signed-off-by: Athul P Satheesan --- arch/arm/aarch64/src/arch_gic.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/arm/aarch64/src/arch_gic.c b/arch/arm/aarch64/src/arch_gic.c index 0790cb70d..6c5970ccc 100644 --- a/arch/arm/aarch64/src/arch_gic.c +++ b/arch/arm/aarch64/src/arch_gic.c @@ -47,6 +47,7 @@ struct isr_callback { void (*func_with_param)(uintptr_t); }; uintptr_t param; + bool use_param; }; static unsigned int current_iar = INTERRUPT_ID_INVALID; @@ -73,10 +74,12 @@ void irq_global(void) entry = &callback[current_iar]; - if (entry->func != NULL) { - if (entry->param == 0) { + if (entry->use_param == false) { + if (entry->func != NULL) { entry->func(); - } else { + } + } else { + if (entry->func_with_param != NULL) { entry->func_with_param(entry->param); } } @@ -220,6 +223,7 @@ int arch_interrupt_set_isr_irq(unsigned int interrupt, void (*isr)(void)) entry = &callback[interrupt]; entry->func = isr; entry->param = 0; + entry->use_param = false; return FWK_SUCCESS; } @@ -231,13 +235,14 @@ int arch_interrupt_set_isr_irq_param( { struct isr_callback *entry; - if (interrupt >= INTERRUPT_ID_ISR_LIMIT || isr == NULL || parameter == 0) { + if (interrupt >= INTERRUPT_ID_ISR_LIMIT || isr == NULL) { return FWK_E_PARAM; } entry = &callback[interrupt]; entry->func_with_param = isr; entry->param = parameter; + entry->use_param = true; return FWK_SUCCESS; } -- GitLab From 9e6ee7f7e939b1c69beace5e74246b2d2e3e57f6 Mon Sep 17 00:00:00 2001 From: Athul P Satheesan Date: Tue, 17 Jun 2025 13:00:03 +0530 Subject: [PATCH 6/8] prod/fvp_baser_aemv8r: Enable the debugger CLI Define the FVP BaseR generic timer Add configuration for the debugger CLI and include the module only if the debugger is enabled globally. Signed-off-by: Athul P Satheesan --- product/fvp-baser-aemv8r/fw/CMakeLists.txt | 9 +++- product/fvp-baser-aemv8r/fw/Firmware.cmake | 20 ++++++--- .../fvp-baser-aemv8r/fw/config_armv8r_mpu.c | 22 +++++++++- .../fvp-baser-aemv8r/fw/config_debugger_cli.c | 24 +++++++++++ product/fvp-baser-aemv8r/fw/config_gtimer.c | 43 +++++++++++++++++++ product/fvp-baser-aemv8r/fw/config_sp805.c | 6 +-- product/fvp-baser-aemv8r/fw/config_timer.c | 32 ++++++++++++++ .../fw/fvp_baser_aemv8r_mmap.h | 8 +++- .../fw/fvp_baser_cfgd_timer.h | 20 +++++++++ product/fvp-baser-aemv8r/fw/fvp_baser_irq.h | 24 +++++++++++ 10 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 product/fvp-baser-aemv8r/fw/config_debugger_cli.c create mode 100644 product/fvp-baser-aemv8r/fw/config_gtimer.c create mode 100644 product/fvp-baser-aemv8r/fw/config_timer.c create mode 100644 product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h create mode 100644 product/fvp-baser-aemv8r/fw/fvp_baser_irq.h diff --git a/product/fvp-baser-aemv8r/fw/CMakeLists.txt b/product/fvp-baser-aemv8r/fw/CMakeLists.txt index fc7ca9a80..a8f2056ab 100644 --- a/product/fvp-baser-aemv8r/fw/CMakeLists.txt +++ b/product/fvp-baser-aemv8r/fw/CMakeLists.txt @@ -1,6 +1,6 @@ # # Arm SCP/MCP Software -# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -13,4 +13,11 @@ target_sources(fvp-baser-aemv8r PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_armv8r_mpu.c" "${CMAKE_CURRENT_SOURCE_DIR}/config_gicx00.c" "${CMAKE_CURRENT_SOURCE_DIR}/config_sp805.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_timer.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_gtimer.c" ) + +if(SCP_ENABLE_DEBUGGER) + target_compile_definitions(fvp-baser-aemv8r PRIVATE BUILD_HAS_DEBUGGER) + target_sources(fvp-baser-aemv8r PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_debugger_cli.c") +endif() diff --git a/product/fvp-baser-aemv8r/fw/Firmware.cmake b/product/fvp-baser-aemv8r/fw/Firmware.cmake index 251908ed0..64e4e7530 100644 --- a/product/fvp-baser-aemv8r/fw/Firmware.cmake +++ b/product/fvp-baser-aemv8r/fw/Firmware.cmake @@ -1,6 +1,6 @@ # # Arm SCP/MCP Software -# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -14,9 +14,15 @@ set(SCP_GENERATE_FLAT_BINARY_INIT TRUE) set(SCP_ARCHITECTURE "aarch64") -list(APPEND SCP_MODULES - "armv8r-mpu" - "pl011" - "gicx00" - "sp805" -) +set(SCP_ENABLE_DEBUGGER_INIT FALSE) + +list(APPEND SCP_MODULES "armv8r-mpu") +list(APPEND SCP_MODULES "pl011") +list(APPEND SCP_MODULES "gicx00") +list(APPEND SCP_MODULES "sp805") +list(APPEND SCP_MODULES "gtimer") +list(APPEND SCP_MODULES "timer") + +if(SCP_ENABLE_DEBUGGER) + list(APPEND SCP_MODULES "debugger-cli") +endif() diff --git a/product/fvp-baser-aemv8r/fw/config_armv8r_mpu.c b/product/fvp-baser-aemv8r/fw/config_armv8r_mpu.c index 6596db97d..dec99ca18 100644 --- a/product/fvp-baser-aemv8r/fw/config_armv8r_mpu.c +++ b/product/fvp-baser-aemv8r/fw/config_armv8r_mpu.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -61,6 +61,26 @@ static struct mod_armv8r_mpu_region mem_regions[] = { PRLAR_NS_SECURE, MPU_ATTR_1, PRLAR_EN_ENABLED) }, + { .prbar = PRBAR_VALUE( + FVP_GTIMER_BASE, + PRBAR_SH_NON_SHAREABLE, + PRBAR_AP_RW_EL2, + PRBAR_XN_NOT_PERMITTED), + .prlar = PRLAR_VALUE( + FVP_GTIMER_BASE + FVP_GTIMER_SIZE - 1, + PRLAR_NS_SECURE, + MPU_ATTR_1, + PRLAR_EN_ENABLED) }, + { .prbar = PRBAR_VALUE( + FVP_CNTCONTROL_BASE, + PRBAR_SH_NON_SHAREABLE, + PRBAR_AP_RW_EL2, + PRBAR_XN_NOT_PERMITTED), + .prlar = PRLAR_VALUE( + FVP_CNTCONTROL_BASE + FVP_CNTCONTROL_SIZE - 1, + PRLAR_NS_SECURE, + MPU_ATTR_1, + PRLAR_EN_ENABLED) }, { .prbar = PRBAR_VALUE( FVP_WATCHDOG_BASE, PRBAR_SH_NON_SHAREABLE, diff --git a/product/fvp-baser-aemv8r/fw/config_debugger_cli.c b/product/fvp-baser-aemv8r/fw/config_debugger_cli.c new file mode 100644 index 000000000..1806d0314 --- /dev/null +++ b/product/fvp-baser-aemv8r/fw/config_debugger_cli.c @@ -0,0 +1,24 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +static const struct mod_debugger_cli_module_config debugger_cli_data = { + .alarm_id = FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_TIMER, + 0, + FVP_BASE_R_TIMER_ALARM_IDX_DEBUGGER), + .poll_period = 100000 +}; + +struct fwk_module_config config_debugger_cli = { + .data = &debugger_cli_data, +}; diff --git a/product/fvp-baser-aemv8r/fw/config_gtimer.c b/product/fvp-baser-aemv8r/fw/config_gtimer.c new file mode 100644 index 000000000..32d193782 --- /dev/null +++ b/product/fvp-baser-aemv8r/fw/config_gtimer.c @@ -0,0 +1,43 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'gtimer'. + */ + +#include + +#include + +#include +#include +#include +#include + +#define GTIMER_FREQ_HZ (100UL * FWK_MHZ) + +static const struct fwk_element gtimer_dev_table[] = { + [0] = { + .name = "CLI_TIMER", + .data = &((struct mod_gtimer_dev_config){ + .hw_timer = FVP_HW_TIMER_BASE, + .hw_counter = FVP_HW_COUNTER_BASE, + .control = FVP_CNTCONTROL_BASE, + .frequency = GTIMER_FREQ_HZ, + .clock_id = FWK_ID_NONE_INIT, + }), + }, + { 0 } +}; + +struct fwk_module_config config_gtimer = { + .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(gtimer_dev_table), +}; + +struct fwk_time_driver fwk_time_driver(const void **ctx) +{ + return mod_gtimer_driver(ctx, config_gtimer.elements.table[0].data); +} diff --git a/product/fvp-baser-aemv8r/fw/config_sp805.c b/product/fvp-baser-aemv8r/fw/config_sp805.c index 1ff23f2af..8ba3f6f12 100644 --- a/product/fvp-baser-aemv8r/fw/config_sp805.c +++ b/product/fvp-baser-aemv8r/fw/config_sp805.c @@ -1,20 +1,18 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "fvp_baser_aemv8r_mmap.h" +#include "fvp_baser_irq.h" #include #include #include -/* FVP watchdog interrupt line */ -#define FVP_WATCHDOG_IRQ 32 - /* Reload value for the WdogLoad register */ #define LOAD_VALUE 0x0fffffff diff --git a/product/fvp-baser-aemv8r/fw/config_timer.c b/product/fvp-baser-aemv8r/fw/config_timer.c new file mode 100644 index 000000000..4e146d62f --- /dev/null +++ b/product/fvp-baser-aemv8r/fw/config_timer.c @@ -0,0 +1,32 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Configuration data for module 'timer'. + */ + +#include +#include + +#include + +#include + +static const struct fwk_element timer_elements[] = { + { + .name = "TIMER0", + .data = &((struct mod_timer_dev_config){ + .id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_GTIMER, 0), + .timer_irq = FVP_SYSTEM_TIMER_IRQ, + }), + .sub_element_count = FVP_BASE_R_TIMER_ALARM_IDX_COUNT, + }, + { 0 } +}; + +struct fwk_module_config config_timer = { + .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(timer_elements), +}; diff --git a/product/fvp-baser-aemv8r/fw/fvp_baser_aemv8r_mmap.h b/product/fvp-baser-aemv8r/fw/fvp_baser_aemv8r_mmap.h index 2d7291d9b..24d97ef37 100644 --- a/product/fvp-baser-aemv8r/fw/fvp_baser_aemv8r_mmap.h +++ b/product/fvp-baser-aemv8r/fw/fvp_baser_aemv8r_mmap.h @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -25,5 +25,11 @@ #define FVP_UART_SIZE (64 * FWK_KIB) #define FVP_WATCHDOG_BASE (FVP_PERIPHERAL_BASE + 0x1C0F0000) #define FVP_WATCHDOG_SIZE (64 * FWK_KIB) +#define FVP_GTIMER_BASE (FVP_PERIPHERAL_BASE + 0x2A800000) +#define FVP_GTIMER_SIZE (1 * FWK_MIB) +#define FVP_CNTCONTROL_BASE (FVP_PERIPHERAL_BASE + 0x2A430000) +#define FVP_CNTCONTROL_SIZE (64 * FWK_KIB) +#define FVP_HW_COUNTER_BASE (FVP_PERIPHERAL_BASE + 0x2A810000) +#define FVP_HW_TIMER_BASE (FVP_PERIPHERAL_BASE + 0x2A820000) #endif /* FVP_BASER_AEMV8R_MMAP_H */ diff --git a/product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h b/product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h new file mode 100644 index 000000000..403a979bf --- /dev/null +++ b/product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Definitions for timer module configuration data in SCP firmware. + */ + +#ifndef FVP_BASER_CFGD_TIMER_H +#define FVP_BASER_CFGD_TIMER_H + +/* Alarm sub-element indices */ +enum timer_alarm_idx { + FVP_BASE_R_TIMER_ALARM_IDX_DEBUGGER, + FVP_BASE_R_TIMER_ALARM_IDX_COUNT, +}; + +#endif /* FVP_BASER_CFGD_TIMER_H */ diff --git a/product/fvp-baser-aemv8r/fw/fvp_baser_irq.h b/product/fvp-baser-aemv8r/fw/fvp_baser_irq.h new file mode 100644 index 000000000..4125adf11 --- /dev/null +++ b/product/fvp-baser-aemv8r/fw/fvp_baser_irq.h @@ -0,0 +1,24 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_BASER_IRQ_H +#define FVP_BASER_IRQ_H + +#include + +typedef enum IRQn { + + /* FVP watchdog interrupt line */ + FVP_WATCHDOG_IRQ = 32, + + /* FVP BaseR Generic Timer */ + FVP_SYSTEM_TIMER_IRQ = 57, + + IRQn_MAX = INT16_MAX, +} IRQn_Type; + +#endif /* FVP_BASER_IRQ_H */ -- GitLab From ef14ff2b32a3ab424c05374135d40cca409357ca Mon Sep 17 00:00:00 2001 From: Athul P Satheesan Date: Tue, 17 Jun 2025 19:40:08 +0530 Subject: [PATCH 7/8] prod/fvp_baser_aemv8r/test_timer: Introduce module The fvp_baser_aemv8r/test-timer module is used to test the timer module to showcase the functionality of integration test module. There is only one sample test case added, which is a basic integration-test case for the timer module to verify one-shot alarm triggering and callback functionality. The test asserts correct callback execution using Unity framework. Signed-off-by: Athul P Satheesan --- .../module/test_timer/CMakeLists.txt | 18 +++ .../module/test_timer/Module.cmake | 9 ++ .../test_timer/include/mod_test_timer.h | 17 +++ .../module/test_timer/src/mod_test_timer.c | 140 ++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100644 product/fvp-baser-aemv8r/module/test_timer/CMakeLists.txt create mode 100644 product/fvp-baser-aemv8r/module/test_timer/Module.cmake create mode 100644 product/fvp-baser-aemv8r/module/test_timer/include/mod_test_timer.h create mode 100644 product/fvp-baser-aemv8r/module/test_timer/src/mod_test_timer.c diff --git a/product/fvp-baser-aemv8r/module/test_timer/CMakeLists.txt b/product/fvp-baser-aemv8r/module/test_timer/CMakeLists.txt new file mode 100644 index 000000000..f71f7c343 --- /dev/null +++ b/product/fvp-baser-aemv8r/module/test_timer/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_test_timer.c") + +target_link_libraries(${SCP_MODULE_TARGET} + PRIVATE module-integration-test module-timer) + +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/product/fvp-baser-aemv8r/module/test_timer/Module.cmake b/product/fvp-baser-aemv8r/module/test_timer/Module.cmake new file mode 100644 index 000000000..6c34b376a --- /dev/null +++ b/product/fvp-baser-aemv8r/module/test_timer/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "test-timer") +set(SCP_MODULE_TARGET "module-test-timer") diff --git a/product/fvp-baser-aemv8r/module/test_timer/include/mod_test_timer.h b/product/fvp-baser-aemv8r/module/test_timer/include/mod_test_timer.h new file mode 100644 index 000000000..f781264f6 --- /dev/null +++ b/product/fvp-baser-aemv8r/module/test_timer/include/mod_test_timer.h @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MOD_TEST_TIMER_H +#define MOD_TEST_TIMER_H + +#include + +/* Configuration structure for the test-timer module */ +struct mod_test_timer_config { + fwk_id_t alarm_id; +}; + +#endif /* MOD_TEST_TIMER_H */ diff --git a/product/fvp-baser-aemv8r/module/test_timer/src/mod_test_timer.c b/product/fvp-baser-aemv8r/module/test_timer/src/mod_test_timer.c new file mode 100644 index 000000000..18924ae65 --- /dev/null +++ b/product/fvp-baser-aemv8r/module/test_timer/src/mod_test_timer.c @@ -0,0 +1,140 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + +enum test_case_idx { TEST_CASE_TIMER_ALARM_TRIGGER, TEST_CASE_COUNT }; + +static const struct mod_timer_alarm_api *alarm_api; +static fwk_id_t alarm_id; +static bool callback_invoked = false; + +struct test_timer_context { + unsigned int case_idx; + unsigned int step_idx; +}; + +static void alarm_callback(uintptr_t param) +{ + const struct test_timer_context *ctx = (const void *)param; + callback_invoked = true; + + struct fwk_event event = { + .id = MOD_INTEGRATION_TEST_EVENT_ID_STEP_CONTINUE, + .source_id = FWK_ID_MODULE(FWK_MODULE_IDX_TEST_TIMER), + .target_id = FWK_ID_MODULE(FWK_MODULE_IDX_INTEGRATION_TEST), + .params = { ctx->case_idx, ctx->step_idx } + }; + + int status = fwk_put_event(&event); + fwk_assert(status == FWK_SUCCESS); +} + +static int test_timer_alarm_trigger( + unsigned int step_idx, + const struct fwk_event *event) +{ + switch (step_idx) { + case 0: + callback_invoked = false; + static struct test_timer_context ctx = { + .case_idx = TEST_CASE_TIMER_ALARM_TRIGGER, + .step_idx = 1, + }; + alarm_api->start( + alarm_id, + 100000, + MOD_TIMER_ALARM_TYPE_ONCE, + alarm_callback, + (uintptr_t)&ctx); + return FWK_PENDING; + case 1: + TEST_ASSERT_TRUE(callback_invoked); + return FWK_SUCCESS; + default: + return FWK_E_PARAM; + } +} + +static int run( + unsigned int case_idx, + unsigned int step_idx, + const struct fwk_event *event) +{ + switch (case_idx) { + case TEST_CASE_TIMER_ALARM_TRIGGER: + return test_timer_alarm_trigger(step_idx, event); + default: + return FWK_E_PARAM; + } +} + +static const char *test_name(unsigned int case_idx) +{ + switch (case_idx) { + case TEST_CASE_TIMER_ALARM_TRIGGER: + return "test_timer_alarm_trigger"; + default: + return NULL; + } +} + +static const struct mod_integration_test_api test_api = { + .run = run, + .test_name = test_name, +}; + +static int test_timer_init( + fwk_id_t module_id, + unsigned int unused, + const void *data) +{ + const struct mod_test_timer_config *config = data; + + alarm_id = config->alarm_id; + return FWK_SUCCESS; +} + +static int test_timer_bind(fwk_id_t id, unsigned int round) +{ + if (round > 0) { + return FWK_SUCCESS; + } + + return fwk_module_bind( + alarm_id, MOD_TIMER_API_ID_ALARM, (void **)&alarm_api); +} + +static int test_timer_process_bind_request( + fwk_id_t requester_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + if (fwk_id_get_api_idx(api_id) != MOD_INTEGRATION_TEST_API_IDX_TEST) { + return FWK_E_PARAM; + } + + *api = &test_api; + return FWK_SUCCESS; +} + +const struct fwk_module module_test_timer = { + .type = FWK_MODULE_TYPE_SERVICE, + .init = test_timer_init, + .process_bind_request = test_timer_process_bind_request, + .api_count = MOD_INTEGRATION_TEST_API_COUNT, + .bind = test_timer_bind, +}; -- GitLab From d69de1f7d44fcbe1207bee2349bc3b7258aabbaa Mon Sep 17 00:00:00 2001 From: Athul P Satheesan Date: Tue, 17 Jun 2025 20:12:57 +0530 Subject: [PATCH 8/8] prod/fvp_baser_aemv8r: Enable Integration-test and test-timer modules Introduce configuration for the integration_test and test_timer modules, only if the debugger is enabled globally. Signed-off-by: Athul P Satheesan --- product/fvp-baser-aemv8r/fw/CMakeLists.txt | 4 ++- product/fvp-baser-aemv8r/fw/Firmware.cmake | 6 ++++ .../fw/config_integration_test.c | 32 +++++++++++++++++++ .../fvp-baser-aemv8r/fw/config_test_timer.c | 25 +++++++++++++++ .../fw/fvp_baser_cfgd_timer.h | 1 + 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 product/fvp-baser-aemv8r/fw/config_integration_test.c create mode 100644 product/fvp-baser-aemv8r/fw/config_test_timer.c diff --git a/product/fvp-baser-aemv8r/fw/CMakeLists.txt b/product/fvp-baser-aemv8r/fw/CMakeLists.txt index a8f2056ab..30218905a 100644 --- a/product/fvp-baser-aemv8r/fw/CMakeLists.txt +++ b/product/fvp-baser-aemv8r/fw/CMakeLists.txt @@ -19,5 +19,7 @@ target_sources(fvp-baser-aemv8r PRIVATE if(SCP_ENABLE_DEBUGGER) target_compile_definitions(fvp-baser-aemv8r PRIVATE BUILD_HAS_DEBUGGER) - target_sources(fvp-baser-aemv8r PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_debugger_cli.c") + target_sources(fvp-baser-aemv8r PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_debugger_cli.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_integration_test.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_test_timer.c") endif() diff --git a/product/fvp-baser-aemv8r/fw/Firmware.cmake b/product/fvp-baser-aemv8r/fw/Firmware.cmake index 64e4e7530..c70843c98 100644 --- a/product/fvp-baser-aemv8r/fw/Firmware.cmake +++ b/product/fvp-baser-aemv8r/fw/Firmware.cmake @@ -23,6 +23,12 @@ list(APPEND SCP_MODULES "sp805") list(APPEND SCP_MODULES "gtimer") list(APPEND SCP_MODULES "timer") +set(SCP_ENABLE_NOTIFICATIONS TRUE) + if(SCP_ENABLE_DEBUGGER) list(APPEND SCP_MODULES "debugger-cli") + list(APPEND SCP_MODULES "integration-test") + list(APPEND SCP_MODULES "test-timer") + list(PREPEND SCP_MODULE_PATHS + "${CMAKE_CURRENT_LIST_DIR}/../module/test_timer") endif() diff --git a/product/fvp-baser-aemv8r/fw/config_integration_test.c b/product/fvp-baser-aemv8r/fw/config_integration_test.c new file mode 100644 index 000000000..4dc0fa5ac --- /dev/null +++ b/product/fvp-baser-aemv8r/fw/config_integration_test.c @@ -0,0 +1,32 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include + +enum test_cases { + TEST_TIMER, + TEST_COUNT, +}; + +static const struct fwk_element config_integration_test_elements[] = { + [TEST_TIMER] = { + .name = "timer", + .data = &(struct mod_integration_test_config){ + .test_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TEST_TIMER), + .run_at_start = false, + .num_test_cases = 1, + }, + }, + [TEST_COUNT] = { 0 } +}; + +struct fwk_module_config config_integration_test = { + .elements = + FWK_MODULE_STATIC_ELEMENTS_PTR(config_integration_test_elements), +}; diff --git a/product/fvp-baser-aemv8r/fw/config_test_timer.c b/product/fvp-baser-aemv8r/fw/config_test_timer.c new file mode 100644 index 000000000..27019d60f --- /dev/null +++ b/product/fvp-baser-aemv8r/fw/config_test_timer.c @@ -0,0 +1,25 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +static const struct mod_test_timer_config test_timer_config = { + .alarm_id = FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_TIMER, + 0, + FVP_BASE_R_TIMER_ALARM_IDX_TEST_TIMER), +}; + +struct fwk_module_config config_test_timer = { + .data = &test_timer_config, +}; diff --git a/product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h b/product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h index 403a979bf..e4e441355 100644 --- a/product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h +++ b/product/fvp-baser-aemv8r/fw/fvp_baser_cfgd_timer.h @@ -14,6 +14,7 @@ /* Alarm sub-element indices */ enum timer_alarm_idx { FVP_BASE_R_TIMER_ALARM_IDX_DEBUGGER, + FVP_BASE_R_TIMER_ALARM_IDX_TEST_TIMER, FVP_BASE_R_TIMER_ALARM_IDX_COUNT, }; -- GitLab