Zephyr API Documentation 4.4.0
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
asm_inline_gcc.h
Go to the documentation of this file.
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_ASM_INLINE_GCC_H_
12#define ZEPHYR_INCLUDE_ARCH_ARM_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/toolchain.h>
22#include <zephyr/types.h>
24#if defined(CONFIG_CPU_AARCH32_ARM9)
26static inline void __enable_irq(void)
27{
28 uint32_t cpsr;
29
30 __asm__ volatile("mrs %0, cpsr" : "=r"(cpsr));
31 __asm__ volatile("msr cpsr_c, %0" :: "r"(cpsr & ~I_BIT));
32}
33
34static inline void __disable_irq(void)
35{
36 uint32_t cpsr;
37
38 __asm__ volatile("mrs %0, cpsr" : "=r"(cpsr));
39 __asm__ volatile("msr cpsr_c, %0" :: "r"(cpsr | I_BIT));
40}
41#include <soc.h> /* align with the including of soc.h in cmsis_core.h */
42#else
43#include <cmsis_core.h>
44#endif
45
46#if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A)
48#endif
49
50#ifdef __cplusplus
51extern "C" {
52#endif
53
54/* On ARMv7-M and ARMv8-M Mainline CPUs, this function prevents regular
55 * exceptions (i.e. with interrupt priority lower than or equal to
56 * _EXC_IRQ_DEFAULT_PRIO) from interrupting the CPU. NMI, Faults, SVC,
57 * and Zero Latency IRQs (if supported) may still interrupt the CPU.
58 *
59 * On ARMv6-M and ARMv8-M Baseline CPUs, this function reads the value of
60 * PRIMASK which shows if interrupts are enabled, then disables all interrupts
61 * except NMI.
62 */
63
64static ALWAYS_INLINE unsigned int arch_irq_lock(void)
65{
66 unsigned int key;
67#if defined(CONFIG_ARMV5)
68 unsigned int tmp;
69#endif
70
71#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
72#if CONFIG_MP_MAX_NUM_CPUS == 1 || defined(CONFIG_ARMV8_M_BASELINE)
73 key = __get_PRIMASK();
74 __disable_irq();
75#else
76#error "Cortex-M0 and Cortex-M0+ require SoC specific support for cross core synchronisation."
77#endif
78#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
79 key = __get_BASEPRI();
80 __set_BASEPRI_MAX(_EXC_IRQ_DEFAULT_PRIO);
81 __ISB();
82#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \
83 || defined(CONFIG_ARMV7_A)
84 __asm__ volatile(
85 "mrs %0, cpsr;"
86 "and %0, #" STRINGIFY(I_BIT) ";"
87 "cpsid i;"
88 : "=r" (key)
89 :
90 : "memory", "cc");
91#elif defined(CONFIG_ARMV5)
92 __asm__ volatile(
93 "mrs %0, cpsr;"
94 "orr %1, %0, #" STRINGIFY(I_BIT) ";"
95 "and %0, #" STRINGIFY(I_BIT) ";"
96 "msr cpsr, %1;"
97 : "=r" (key), "=r" (tmp)
98 :
99 : "memory", "cc");
100#else
101#error Unknown ARM architecture
102#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
103
104 return key;
105}
106
107
108/* On Cortex-M0/M0+, this enables all interrupts if they were not
109 * previously disabled.
110 */
111
112static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
113{
114#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
115 if (key != 0U) {
116 return;
117 }
118 __enable_irq();
119 __ISB();
120#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
121 __set_BASEPRI(key);
122 __ISB();
123#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \
124 || defined(CONFIG_ARMV7_A) || defined(CONFIG_ARMV5)
125 if (key != 0U) {
126 return;
127 }
128 __enable_irq();
129#else
130#error Unknown ARM architecture
131#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
132}
133
134static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key)
135{
136 /* This convention works for both PRIMASK and BASEPRI */
137 return key == 0U;
138}
139
142{
143#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
144 return __get_PRIMASK() == 0U;
145#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
146 return __get_BASEPRI() == 0U;
147#elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \
148 || defined(CONFIG_ARMV7_A) || defined(CONFIG_ARMV5)
149 unsigned int cpsr;
150
151 __asm__ volatile("mrs %0, cpsr" : "=r" (cpsr));
152 return (cpsr & I_BIT) == 0U;
153#else
154#error Unknown ARM architecture
155#endif
156}
157
158#ifdef CONFIG_ZERO_LATENCY_IRQS
159
160static ALWAYS_INLINE unsigned int arch_zli_lock(void)
161{
162 unsigned int key;
163
164 key = __get_PRIMASK();
165
166 /*
167 * The cpsid instruction is self synchronizing within the instruction stream, no need for
168 * an explicit __ISB().
169 */
170 __disable_irq();
171
172 return key;
173}
174
175static ALWAYS_INLINE void arch_zli_unlock(unsigned int key)
176{
177 __set_PRIMASK(key);
178 __ISB();
179}
180
181#endif /* CONFIG_ZERO_LATENCY_IRQS */
182
183#ifdef __cplusplus
184}
185#endif
186
187#endif /* _ASMLANGUAGE */
188
189#endif /* ZEPHYR_INCLUDE_ARCH_ARM_ASM_INLINE_GCC_H_ */
#define I_BIT
Definition cpu.h:32
static ALWAYS_INLINE unsigned int arch_irq_lock(void)
Definition asm_inline_gcc.h:26
static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
Definition asm_inline_gcc.h:40
static ALWAYS_INLINE bool arch_cpu_irqs_are_enabled(void)
Implementation of arch_cpu_irqs_are_enabled.
Definition asm_inline_gcc.h:52
static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key)
Definition asm_inline_gcc.h:45
#define STRINGIFY(s)
Definition common.h:166
#define ALWAYS_INLINE
Definition common.h:161
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
Macros to abstract toolchain specific capabilities.