/* ARM AArch32 GCC specific public inline assembler functions and macros */ /* * Copyright (c) 2015, Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ /* Either public functions or macros or invoked by public functions */ #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ASM_INLINE_GCC_H_ #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ASM_INLINE_GCC_H_ /* * The file must not be included directly * Include arch/cpu.h instead */ #ifndef _ASMLANGUAGE #include #include #if defined(CONFIG_CPU_AARCH32_CORTEX_R) || defined(CONFIG_CPU_AARCH32_CORTEX_A) #include #endif #ifdef __cplusplus extern "C" { #endif /* On ARMv7-M and ARMv8-M Mainline CPUs, this function prevents regular * exceptions (i.e. with interrupt priority lower than or equal to * _EXC_IRQ_DEFAULT_PRIO) from interrupting the CPU. NMI, Faults, SVC, * and Zero Latency IRQs (if supported) may still interrupt the CPU. * * On ARMv6-M and ARMv8-M Baseline CPUs, this function reads the value of * PRIMASK which shows if interrupts are enabled, then disables all interrupts * except NMI. */ static ALWAYS_INLINE unsigned int arch_irq_lock(void) { unsigned int key; #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) && !defined(CONFIG_ARMV8_M_BASELINE) #if CONFIG_MP_MAX_NUM_CPUS == 1 __asm__ volatile("mrs %0, PRIMASK;" "cpsid i" : "=r" (key) : : "memory"); #else #error "Cortex-M0 and Cortex-M0+ require SoC specific support for cross core synchronisation." #endif #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) || defined(CONFIG_ARMV8_M_BASELINE) unsigned int tmp; __asm__ volatile( "mov %1, %2;" "mrs %0, BASEPRI;" "msr BASEPRI_MAX, %1;" "isb;" : "=r"(key), #if defined(CONFIG_ARMV8_M_BASELINE) /* armv8-m.baseline's mov is limited to registers r0-r7. * Let the compiler know we have this constraint on tmp. */ "=l"(tmp) #else "=r"(tmp) #endif : "i"(_EXC_IRQ_DEFAULT_PRIO) : "memory"); #elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ || defined(CONFIG_ARMV7_A) __asm__ volatile( "mrs %0, cpsr;" "and %0, #" TOSTR(I_BIT) ";" "cpsid i;" : "=r" (key) : : "memory", "cc"); #else #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ return key; } /* On Cortex-M0/M0+, this enables all interrupts if they were not * previously disabled. */ static ALWAYS_INLINE void arch_irq_unlock(unsigned int key) { #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) && !defined(CONFIG_ARMV8_M_BASELINE) if (key != 0U) { return; } __asm__ volatile( "cpsie i;" "isb" : : : "memory"); #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) || defined(CONFIG_ARMV8_M_BASELINE) __asm__ volatile( "msr BASEPRI, %0;" "isb;" : : "r"(key) : "memory"); #elif defined(CONFIG_ARMV7_R) || defined(CONFIG_AARCH32_ARMV8_R) \ || defined(CONFIG_ARMV7_A) if (key != 0U) { return; } __asm__ volatile( "cpsie i;" : : : "memory", "cc"); #else #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ } static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) { /* This convention works for both PRIMASK and BASEPRI */ return key == 0U; } #ifdef __cplusplus } #endif #endif /* _ASMLANGUAGE */ #endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ASM_INLINE_GCC_H_ */