TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_arch_v6m_v7m.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <inttypes.h>
9 #include "tfm_hal_device_header.h"
10 #include "tfm_arch.h"
11 
12 #if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && \
13  !defined(__ARM_ARCH_7EM__)
14 #error "Unsupported ARM Architecture."
15 #endif
16 
17 extern uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr);
18 
19 /*
20  * Stack status at PendSV entry:
21  *
22  * [ R0 - R3 ]<- PSP
23  * [ R12 ]
24  * [ LR_of_RA ]
25  * MSP->[ ........ ] [ RA ]
26  * [ ........ ] [ XPSR ]
27  * [ ........ ]
28  * [ ........ ]
29  *
30  * Stack status before calling tfm_pendsv_do_schedule():
31  *
32  * MSP->[ R8 - R9 ]
33  * [ R4 - R7 ]
34  * [ PSP ]--->[ R0 - R3 ]
35  * [ LR ] [ R12 ]
36  * [ ........ ] [ LR_of_RA ]
37  * [ ........ ] [ RA ]
38  * [ XPSR ]
39  * [ ........ ]
40  * [ ........ ]
41  *
42  * tfm_pendsv_do_schedule() updates stacked context into current thread and
43  * replace stacked context with context of next thread.
44  *
45  * Scheduler does not support handler mode thread so take PSP as thread SP.
46  */
47 #if defined(__ICCARM__)
48 extern void tfm_pendsv_do_schedule(void);
49 #pragma required = tfm_pendsv_do_schedule
50 #endif
51 
52 __attribute__((naked)) void PendSV_Handler(void)
53 {
54  __ASM volatile(
55  "MRS r0, psp \n"
56  "PUSH {r0, lr} \n"
57  "PUSH {r4-r7} \n"
58  "MOV r4, r8 \n"
59  "MOV r5, r9 \n"
60  "MOV r6, r10 \n"
61  "MOV r7, r11 \n"
62  "PUSH {r4-r7} \n"
63  "MOV r0, sp \n"
64  "BL tfm_pendsv_do_schedule \n"
65  "POP {r4-r7} \n"
66  "MOV r8, r4 \n"
67  "MOV r9, r5 \n"
68  "MOV r10, r6 \n"
69  "MOV r11, r7 \n"
70  "POP {r4-r7} \n"
71  "POP {r0, r1} \n"
72  "MOV lr, r1 \n"
73  "MSR psp, r0 \n"
74  "BX lr \n"
75  );
76 }
77 
78 void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx,
79  uint32_t sp, uint32_t sp_limit)
80 {
81  (void)sp_limit;
82 
83  p_actx->sp = sp;
84  p_actx->lr = EXC_RETURN_THREAD_S_PSP;
85 }
86 
87 #if defined(__ICCARM__)
88 uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return);
89 #pragma required = tfm_core_svc_handler
90 #endif
91 
92 __attribute__((naked)) void SVC_Handler(void)
93 {
94  __ASM volatile(
95  "MOVS r0, #4 \n" /* Check store SP in thread mode to r0 */
96  "MOV r1, lr \n"
97  "TST r0, r1 \n"
98  "BEQ handler \n"
99  "MRS r0, PSP \n" /* Coming from thread mode */
100  "B sp_stored \n"
101  "handler: \n"
102  "BX lr \n" /* Coming from handler mode */
103  "sp_stored: \n"
104  "MOV r1, lr \n"
105  "BL tfm_core_svc_handler \n"
106  "BX r0 \n"
107  );
108 }
109 
113 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
114 void HardFault_Handler(void)
115 {
116  /* HFSR can be read to provide further information of cause of HardFault */
117  __ASM volatile("b .");
118 }
119 #elif defined(__ARM_ARCH_6M__)
120 void HardFault_Handler(void)
121 {
122  /* In a baseline implementation there is no way, to find out whether this is
123  * a hard fault triggered directly, or another fault that has been
124  * escalated.
125  */
126  __ASM volatile("b .");
127 }
128 #endif
129 
130 /* Reserved for future usage */
131 __attribute__((naked)) void MemManage_Handler(void)
132 {
133  __ASM volatile("b .");
134 }
135 
136 __attribute__((naked)) void BusFault_Handler(void)
137 {
138  __ASM volatile("b .");
139 }
140 
141 __attribute__((naked)) void UsageFault_Handler(void)
142 {
143  __ASM volatile("b .");
144 }
145 
147 {
148  /* Set fault priority to the highest */
149 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
150  NVIC_SetPriority(MemoryManagement_IRQn, 0);
151  NVIC_SetPriority(BusFault_IRQn, 0);
152 #endif
153 
154  NVIC_SetPriority(SVCall_IRQn, 0);
155  NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
156 }
157 
159 {
160  /* There are no coprocessors in Armv6-M implementations */
161 #ifndef __ARM_ARCH_6M__
162 #if defined (__FPU_USED) && (__FPU_USED == 1U)
163  /* Enable privileged and unprivilged access to the floating-point
164  * coprocessor.
165  */
166  SCB->CPACR |= (3U << 10U*2U) /* enable CP10 full access */
167  | (3U << 11U*2U); /* enable CP11 full access */
168 #endif
169 #endif
170 }
171 
172 /* There is no FPCA in v6m */
173 #ifndef __ARM_ARCH_6M__
174 __attribute__((naked, noinline)) void tfm_arch_clear_fp_status(void)
175 {
176  __ASM volatile(
177  ".syntax unified \n"
178  "mrs r0, control \n"
179  "bics r0, r0, #4 \n"
180  "msr control, r0 \n"
181  "isb \n"
182  "bx lr \n"
183  );
184 }
185 #else
186 void tfm_arch_clear_fp_status(void)
187 {
188 }
189 #endif
void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx, uint32_t sp, uint32_t sp_limit)
void HardFault_Handler(void)
Definition: arch.c:364
void SVC_Handler(void)
void tfm_arch_set_secure_exception_priorities(void)
void BusFault_Handler(void)
#define EXC_RETURN_THREAD_S_PSP
void tfm_pendsv_do_schedule(struct tfm_arch_ctx_t *p_actx)
Definition: spm_ipc.c:756
void PendSV_Handler(void)
void MemManage_Handler(void)
Overwrites default Hard fault handler.
void tfm_arch_configure_coprocessors(void)
Configure coprocessors.
uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t lr, uint32_t *msp)
void UsageFault_Handler(void)
void tfm_arch_clear_fp_status(void)
uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr)