1 /*
2  * Copyright (c) 2025 Silicon Laboratories Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #if !defined(CONFIG_CPU_CORTEX_M)
8 #error project can only run on Cortex-M
9 #endif
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/printk.h>
13 #include <zephyr/ztest.h>
14 #include <zephyr/devicetree.h>
15 
16 #if defined(CONFIG_ARM_VECTOR_TABLE_DTCM)
17 #define DTCM_NODE    DT_CHOSEN(zephyr_dtcm)
18 #define SRAM_VT_BASE DT_REG_ADDR(DTCM_NODE)
19 #define SRAM_VT_SIZE DT_REG_SIZE(DTCM_NODE)
20 #elif defined(CONFIG_ARM_VECTOR_TABLE_ITCM)
21 #define ITCM_NODE    DT_CHOSEN(zephyr_itcm)
22 #define SRAM_VT_BASE DT_REG_ADDR(ITCM_NODE)
23 #define SRAM_VT_SIZE DT_REG_SIZE(ITCM_NODE)
24 #else
25 #define SRAM_VT_BASE CONFIG_SRAM_BASE_ADDRESS
26 #define SRAM_VT_SIZE (CONFIG_SRAM_SIZE * 1024U)
27 #endif
28 
29 #ifdef SCB_VTOR_TBLBASE_Msk
30 #define VTOR_MASK (SCB_VTOR_TBLBASE_Msk | SCB_VTOR_TBLOFF_Msk)
31 #else
32 #define VTOR_MASK SCB_VTOR_TBLOFF_Msk
33 #endif
34 
35 /* This function will allow execute from sram region.
36  * This is needed only for this sample because by default all soc will
37  * disable the execute from SRAM.
38  * An application that requires that the code be executed from SRAM will
39  *  have to configure the region appropriately in arm_mpu_regions.c.
40  */
41 
42 #if (defined(CONFIG_ARM_MPU) && !defined(CONFIG_CPU_HAS_NXP_SYSMPU))
43 #include <cmsis_core.h>
disable_mpu_rasr_xn(void)44 static void disable_mpu_rasr_xn(void)
45 {
46 	uint32_t index;
47 	/* Kept the max index as 8(irrespective of soc) because the sram
48 	 * would most likely be set at index 2.
49 	 */
50 	for (index = 0U; index < 8; index++) {
51 		MPU->RNR = index;
52 #if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE)
53 		if (MPU->RBAR & MPU_RBAR_XN_Msk) {
54 			MPU->RBAR ^= MPU_RBAR_XN_Msk;
55 		}
56 #else
57 		if (MPU->RASR & MPU_RASR_XN_Msk) {
58 			MPU->RASR ^= MPU_RASR_XN_Msk;
59 		}
60 #endif /* CONFIG_ARMV8_M_BASELINE || CONFIG_ARMV8_M_MAINLINE */
61 	}
62 }
63 #endif /* CONFIG_ARM_MPU */
64 
ZTEST(vector_table_relocation,test_vector_table_in_ram)65 ZTEST(vector_table_relocation, test_vector_table_in_ram)
66 {
67 	/* Check that VTOR register effectively point to a RAM based location */
68 	volatile uint32_t vtor_address = SCB->VTOR & VTOR_MASK;
69 
70 	printf("VTOR address: 0x%x\n", vtor_address);
71 	zassert_true(vtor_address >= SRAM_VT_BASE && vtor_address <= SRAM_VT_BASE + SRAM_VT_SIZE,
72 		     "Vector table is not in RAM! Address: 0x%x", vtor_address);
73 }
74 
relocate_code_setup(void)75 void *relocate_code_setup(void)
76 {
77 #if (defined(CONFIG_ARM_MPU) && !defined(CONFIG_CPU_HAS_NXP_SYSMPU))
78 	disable_mpu_rasr_xn();
79 #endif /* CONFIG_ARM_MPU */
80 	return NULL;
81 }
82 
83 ZTEST_SUITE(vector_table_relocation, NULL, relocate_code_setup, NULL, NULL, NULL);
84