Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | /* * Copyright (c) 2020 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include <kernel.h> #include <sys/printk.h> #include <sys/__assert.h> #include <arch/arm/aarch32/cortex_m/cmsis.h> #if !defined(CONFIG_CPU_CORTEX_M) #error test can only run on Cortex-M MCUs #endif #if defined(CONFIG_ARMV8_1_M_MAINLINE) /* * For ARMv8.1-M, the FPSCR[18:16] LTPSIZE field may always read 0b010 if MVE * is not implemented, so mask it when validating the value of the FPSCR. */ #define FPSCR_MASK (~FPU_FPDSCR_LTPSIZE_Msk) #else #define FPSCR_MASK (0xffffffffU) #endif extern K_THREAD_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE); static volatile int test_flag; static unsigned int expected_reason; void arm_isr_handler(const void *args) { ARG_UNUSED(args); test_flag++; } void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) { printk("Caught system error -- reason %d\n", reason); if (expected_reason == -1) { printk("Was not expecting a crash\n"); k_fatal_halt(reason); } if (reason != expected_reason) { printk("Wrong crash type got %d expected %d\n", reason, expected_reason); k_fatal_halt(reason); } expected_reason = -1; } void test_main(void) { printk("ARM no-multithreading test\n"); uint32_t psp = (uint32_t)__get_PSP(); uint32_t main_stack_base = (uint32_t)Z_THREAD_STACK_BUFFER(z_main_stack); uint32_t main_stack_top = (uint32_t)(Z_THREAD_STACK_BUFFER(z_main_stack) + K_THREAD_STACK_SIZEOF(z_main_stack)); __ASSERT( (psp >= main_stack_base) && (psp <= main_stack_top), "PSP out of bounds: 0x%x (0x%x - 0x%x)", psp, main_stack_base, main_stack_top); #if defined(CONFIG_FPU) __ASSERT((__get_FPSCR() & FPSCR_MASK) == 0, "FPSCR not zero (0x%x)", __get_FPSCR()); #endif #if defined(CONFIG_BUILTIN_STACK_GUARD) uint32_t psplim = (uint32_t)__get_PSPLIM(); __ASSERT( (psplim == main_stack_base), "PSPLIM not set to main stack base: (0x%x)", psplim); #endif int key = arch_irq_lock(); __ASSERT(arch_irq_unlocked(key), "IRQs locked in main()"); arch_irq_unlock(key); /* Verify activating the PendSV IRQ triggers a K_ERR_SPURIOUS_IRQ */ expected_reason = K_ERR_CPU_EXCEPTION; SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; __DSB(); __ISB(); /* Determine an NVIC IRQ line that is not currently in use. */ int i, flag = test_flag; __ASSERT(flag == 0, "Test flag not initialized to 0\n"); for (i = CONFIG_NUM_IRQS - 1; i >= 0; i--) { if (NVIC_GetEnableIRQ(i) == 0) { /* * Interrupts configured statically with IRQ_CONNECT(.) * are automatically enabled. NVIC_GetEnableIRQ() * returning false, here, implies that the IRQ line is * either not implemented or it is not enabled, thus, * currently not in use by Zephyr. */ /* Set the NVIC line to pending. */ NVIC_SetPendingIRQ(i); if (NVIC_GetPendingIRQ(i)) { /* If the NVIC line is pending, it is * guaranteed that it is implemented; clear the * line. */ NVIC_ClearPendingIRQ(i); if (!NVIC_GetPendingIRQ(i)) { /* * If the NVIC line can be successfully * un-pended, it is guaranteed that it * can be used for software interrupt * triggering. Trigger it. */ NVIC_SetPendingIRQ(i); break; } } } } if (i >= 0) { printk("Available IRQ line: %u\n", i); arch_irq_connect_dynamic(i, 0 /* highest priority */, arm_isr_handler, NULL, 0); NVIC_EnableIRQ(i); __DSB(); __ISB(); flag = test_flag; __ASSERT(flag > 0, "Test flag not set by IRQ\n"); printk("ARM no multithreading test successful\n"); } else { __ASSERT(0, "No available IRQ line to use in the test\n"); } } |