|
14 | 14 | * limitations under the License.
|
15 | 15 | */
|
16 | 16 |
|
| 17 | +#if !defined(COMPONENT_PSA_SRV_IPC) |
| 18 | +#error [NOT_SUPPORTED] Test supported only on PSA targets |
| 19 | +#endif |
| 20 | + |
| 21 | +#if (defined( __CC_ARM ) || defined(__ARMCC_VERSION) || defined( __ICCARM__ )) |
| 22 | +#error [NOT_SUPPORTED] this test is supported on GCC only |
| 23 | +#endif |
| 24 | + |
17 | 25 | #include "utest/utest.h"
|
18 | 26 | #include "unity/unity.h"
|
19 | 27 | #include "greentea-client/test_env.h"
|
20 | 28 | #include "cmsis.h"
|
21 | 29 | #include "spm_api.h"
|
22 | 30 | #include <stdlib.h>
|
| 31 | +#include "fault_functions.h" |
23 | 32 |
|
24 | 33 | using namespace utest::v1;
|
25 | 34 |
|
26 |
| -#if !defined(COMPONENT_PSA_SRV_IPC) |
27 |
| -#error [NOT_SUPPORTED] Test supported only on PSA targets |
28 |
| -#endif |
29 |
| - |
30 |
| -#if !defined ( __GNUC__ ) |
31 |
| -#error [NOT_SUPPORTED] this test is supported on GCC only |
32 |
| -#endif |
33 | 35 |
|
34 |
| -extern "C" { |
35 | 36 | #define HARDFAULT_IRQn ((IRQn_Type)-13)
|
36 | 37 | #define EXC_RETURN_RETURN_STACK_MSK ((uint32_t)(0x00000004))
|
37 | 38 | #define PC_INDEX_IN_STACK_FRAME 6
|
38 | 39 |
|
39 |
| - volatile uint32_t fault_occurred; |
40 |
| - uint32_t real_hard_fault_handler; |
| 40 | +volatile uint32_t fault_occurred; |
| 41 | +uint32_t real_hard_fault_handler; |
41 | 42 |
|
42 |
| - __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_LR(void) |
43 |
| - { |
44 |
| - register uint32_t result; |
| 43 | +__STATIC_FORCEINLINE uint32_t __get_LR(void) |
| 44 | +{ |
| 45 | + uint32_t result; |
45 | 46 |
|
46 |
| - __ASM volatile("MOV %0, LR\n" : "=r"(result)); |
47 |
| - return result; |
48 |
| - } |
| 47 | + __ASM volatile("MOV %0, lr" : "=r"(result)); |
| 48 | + return (result); |
| 49 | +} |
49 | 50 |
|
50 |
| -// This function is required as we need a symbol/address |
51 |
| -// to jump to from fault handler. |
52 |
| - void do_nothing(void) |
53 |
| - { |
54 |
| - __NOP(); |
55 |
| - } |
| 51 | +void do_nothing(void) |
| 52 | +{ |
| 53 | + __NOP(); |
| 54 | +} |
56 | 55 |
|
57 |
| -// Test exception handler |
58 |
| - static void hard_fault_handler_test() |
59 |
| - { |
60 |
| - fault_occurred++; |
61 |
| - // LR is set EXC_RETURN |
62 |
| - // lowest bits identify PSP vs MSP stack used for stacking |
63 |
| - uint32_t lr = __get_LR(); |
64 |
| - uint32_t sp; |
65 |
| - |
66 |
| - if (lr & EXC_RETURN_RETURN_STACK_MSK) { |
67 |
| - sp = __get_PSP(); |
68 |
| - } else { |
69 |
| - sp = __get_MSP(); |
70 |
| - } |
71 |
| - |
72 |
| - // Overwrite return address. |
73 |
| - // Fake return to a our special function since current |
74 |
| - // instruction under test will always fail due to memory protection |
75 |
| - ((uint32_t *)sp)[PC_INDEX_IN_STACK_FRAME] = (uint32_t)do_nothing; |
| 56 | +static void hard_fault_handler_test() |
| 57 | +{ |
| 58 | + fault_occurred++; |
| 59 | + // LR is set EXC_RETURN |
| 60 | + // lowest bits identify PSP vs MSP stack used for stacking |
| 61 | + uint32_t lr = __get_LR(); |
| 62 | + uint32_t sp; |
| 63 | + |
| 64 | + if (lr & EXC_RETURN_RETURN_STACK_MSK) { |
| 65 | + sp = __get_PSP(); |
| 66 | + } else { |
| 67 | + sp = __get_MSP(); |
76 | 68 | }
|
77 | 69 |
|
78 |
| -// Using naked function as it will not be executed from beginning to the end. |
79 |
| -// The execution flow expected to be interrupted by exception and we will |
80 |
| -// return to other function. |
81 |
| -// compiler will not produce prolog and epilog code for naked function |
82 |
| -// and thus will preserve stack in un-corrupted state |
83 |
| - __attribute__((naked)) void call_mem(uint32_t addr) |
84 |
| - { |
85 |
| - // Only first instruction will be executed in positive flow, |
86 |
| - // since exception will be generated for invalid memory access. |
87 |
| - // Other instructions are for calling do_nothing function according to AAPCS. |
88 |
| - __ASM( |
89 |
| - "LDR r1, [r0]\n" |
90 |
| - "BX lr\n" |
91 |
| - ); |
92 |
| - } |
| 70 | + // Overwrite return address. |
| 71 | + // Fake return to a our special function since current |
| 72 | + // instruction under test will always fail due to memory protection |
| 73 | + ((uint32_t *)sp)[PC_INDEX_IN_STACK_FRAME] = (uint32_t)do_nothing; |
| 74 | +} |
| 75 | + |
| 76 | +__attribute__((naked)) void call_mem(uint32_t addr) |
| 77 | +{ |
| 78 | + // Only first instruction will be executed in positive flow, |
| 79 | + // since exception will be generated for invalid memory access. |
| 80 | + // Other instructions are for calling do_nothing function according to AAPCS. |
| 81 | + __ASM( |
| 82 | + "LDR r1, [r0]\n" |
| 83 | + "BX lr\n" |
| 84 | + ); |
93 | 85 | }
|
94 | 86 |
|
95 | 87 | static void test_memory(uint32_t addr, uint32_t expected_fatal_count)
|
|
0 commit comments