1 /* ARM AArch32 GCC specific public inline assembler functions and macros */
2
3 /*
4 * Copyright (c) 2015, Wind River Systems, Inc.
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 /* Either public functions or macros or invoked by public functions */
10
11 #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ASM_INLINE_GCC_H_
12 #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ASM_INLINE_GCC_H_
13
14 /*
15 * The file must not be included directly
16 * Include arch/cpu.h instead
17 */
18
19 #ifndef _ASMLANGUAGE
20
21 #include <zephyr/types.h>
22 #include <zephyr/arch/arm/exc.h>
23
24 #if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A)
25 #include <zephyr/arch/arm/cortex_a_r/cpu.h>
26 #endif
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 /* On ARMv7-M and ARMv8-M Mainline CPUs, this function prevents regular
33 * exceptions (i.e. with interrupt priority lower than or equal to
34 * _EXC_IRQ_DEFAULT_PRIO) from interrupting the CPU. NMI, Faults, SVC,
35 * and Zero Latency IRQs (if supported) may still interrupt the CPU.
36 *
37 * On ARMv6-M and ARMv8-M Baseline CPUs, this function reads the value of
38 * PRIMASK which shows if interrupts are enabled, then disables all interrupts
39 * except NMI.
40 */
41
arch_irq_lock(void)42 static ALWAYS_INLINE unsigned int arch_irq_lock(void)
43 {
44 unsigned int key;
45
46 #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) && !defined(CONFIG_ARMV8_M_BASELINE)
47 #if CONFIG_MP_MAX_NUM_CPUS == 1
48 __asm__ volatile("mrs %0, PRIMASK;"
49 "cpsid i"
50 : "=r" (key)
51 :
52 : "memory");
53 #else
54 #error "Cortex-M0 and Cortex-M0+ require SoC specific support for cross core synchronisation."
55 #endif
56 #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) || defined(CONFIG_ARMV8_M_BASELINE)
57 unsigned int tmp;
58
59 __asm__ volatile(
60 "mov %1, %2;"
61 "mrs %0, BASEPRI;"
62 "msr BASEPRI_MAX, %1;"
63 "isb;"
64 : "=r"(key),
65 #if defined(CONFIG_ARMV8_M_BASELINE)
66 /* armv8-m.baseline's mov is limited to registers r0-r7.
67 * Let the compiler know we have this constraint on tmp.
68 */
69 "=l"(tmp)
70 #else
71 "=r"(tmp)
72 #endif
73 : "i"(_EXC_IRQ_DEFAULT_PRIO)
74 : "memory");
75 #elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \
76 || defined(CONFIG_ARMV7_A)
77 __asm__ volatile(
78 "mrs %0, cpsr;"
79 "and %0, #" TOSTR(I_BIT) ";"
80 "cpsid i;"
81 : "=r" (key)
82 :
83 : "memory", "cc");
84 #else
85 #error Unknown ARM architecture
86 #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
87
88 return key;
89 }
90
91
92 /* On Cortex-M0/M0+, this enables all interrupts if they were not
93 * previously disabled.
94 */
95
arch_irq_unlock(unsigned int key)96 static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
97 {
98 #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) && !defined(CONFIG_ARMV8_M_BASELINE)
99 if (key != 0U) {
100 return;
101 }
102 __asm__ volatile(
103 "cpsie i;"
104 "isb"
105 : : : "memory");
106 #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) || defined(CONFIG_ARMV8_M_BASELINE)
107 __asm__ volatile(
108 "msr BASEPRI, %0;"
109 "isb;"
110 : : "r"(key) : "memory");
111 #elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \
112 || defined(CONFIG_ARMV7_A)
113 if (key != 0U) {
114 return;
115 }
116 __asm__ volatile(
117 "cpsie i;"
118 : : : "memory", "cc");
119 #else
120 #error Unknown ARM architecture
121 #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
122 }
123
arch_irq_unlocked(unsigned int key)124 static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key)
125 {
126 /* This convention works for both PRIMASK and BASEPRI */
127 return key == 0U;
128 }
129
130 #ifdef __cplusplus
131 }
132 #endif
133
134 #endif /* _ASMLANGUAGE */
135
136 #endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ASM_INLINE_GCC_H_ */
137