1 /*
2  * Copyright (c) 2025 Silicon Laboratories Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Test for driver relocation to RAM for ISRs
10  *
11  * This test demonstrates how to use the fake_driver and verify
12  * that the callback are properly relocated to RAM.
13  */
14 
15 #if !defined(CONFIG_CPU_CORTEX_M)
16 #error project can only run on Cortex-M for now
17 #endif
18 
19 #include <zephyr/ztest.h>
20 #include "fake_driver.h"
21 
22 static volatile bool test_flag;
23 
test_irq_callback(const struct device * dev,void * user_data)24 static void test_irq_callback(const struct device *dev, void *user_data)
25 {
26 	uintptr_t func_addr = (uintptr_t)test_irq_callback;
27 	uintptr_t driver_isr_addr, arch_isr_wrapper_addr;
28 
29 	test_flag = true;
30 
31 	/* Retrieve the caller address (the arch specific isr wrapper since driver isr will be
32 	 * optimized by the compiler)
33 	 */
34 	__asm__ volatile("mov %0, lr" : "=r"(arch_isr_wrapper_addr));
35 
36 	/* retrieve the fake_driver_isr function address that was stored in user_data */
37 	driver_isr_addr = (uintptr_t)user_data;
38 
39 	/* Check that the function and its call stack are in RAM */
40 	zassert_true(func_addr >= CONFIG_SRAM_BASE_ADDRESS &&
41 			     func_addr <= CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_SIZE * 1024,
42 		     "%s is not in RAM! Address: 0x%lx", __func__, func_addr);
43 
44 	zassert_true(driver_isr_addr >= CONFIG_SRAM_BASE_ADDRESS &&
45 			     driver_isr_addr <= CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_SIZE * 1024,
46 		     "fake_driver_isr is not in RAM! Address: 0x%lx", driver_isr_addr);
47 
48 	zassert_true(arch_isr_wrapper_addr >= CONFIG_SRAM_BASE_ADDRESS &&
49 			     arch_isr_wrapper_addr <=
50 				     CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_SIZE * 1024,
51 		     "arch_isr_wrapper_addr is not in RAM! Address: 0x%lx", arch_isr_wrapper_addr);
52 
53 	TC_PRINT("Callback function address: 0x%lx\n", func_addr);
54 	TC_PRINT("Driver ISR address: 0x%lx\n", driver_isr_addr);
55 	TC_PRINT("Arch ISR wrapper address: 0x%lx\n", arch_isr_wrapper_addr);
56 }
57 
ZTEST(ram_context_for_isr,test_fake_driver_in_ram)58 ZTEST(ram_context_for_isr, test_fake_driver_in_ram)
59 {
60 	const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(fakedriver));
61 	const struct fake_driver_api *api = DEVICE_API_GET(fake, dev);
62 	uintptr_t dev_addr = (uintptr_t)dev;
63 
64 	zassert_true(dev_addr >= CONFIG_SRAM_BASE_ADDRESS &&
65 			     dev_addr <= CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_SIZE * 1024,
66 		     "fake driver device is not in RAM! Address: 0x%lx", dev_addr);
67 
68 	TC_PRINT("Fake driver device address: 0x%lx\n", dev_addr);
69 
70 	zassert_not_null(api, "Failed to get fake driver API");
71 
72 	api->register_irq_callback(dev, test_irq_callback, NULL);
73 	test_flag = false;
74 
75 	NVIC_SetPendingIRQ(TEST_IRQ_NUM);
76 
77 	k_busy_wait(1000);
78 
79 	zassert_true(test_flag, "ISR callback was not called");
80 }
81 
82 ZTEST_SUITE(ram_context_for_isr, NULL, NULL, NULL, NULL, NULL);
83