1 /**************************************************************************//**
2 * @file cmsis_armclang.h
3 * @brief CMSIS compiler specific macros, functions, instructions
6 ******************************************************************************/
8 * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
10 * SPDX-License-Identifier: Apache-2.0
12 * Licensed under the Apache License, Version 2.0 (the License); you may
13 * not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
16 * www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
25 #ifndef __CMSIS_ARMCLANG_H
26 #define __CMSIS_ARMCLANG_H
28 #ifndef __ARM_COMPAT_H
29 #include <arm_compat.h> /* Compatibility header for ARM Compiler 5 intrinsics */
32 /* CMSIS compiler specific defines */
37 #define __INLINE __inline
40 #define __FORCEINLINE __attribute__((always_inline))
42 #ifndef __STATIC_INLINE
43 #define __STATIC_INLINE static __inline
45 #ifndef __STATIC_FORCEINLINE
46 #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline
49 #define __NO_RETURN __declspec(noreturn)
52 #define __USED __attribute__((used))
55 #define __WEAK __attribute__((weak))
58 #define __PACKED __attribute__((packed, aligned(1)))
60 #ifndef __PACKED_STRUCT
61 #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
63 #ifndef __UNALIGNED_UINT16_WRITE
64 #pragma clang diagnostic push
65 #pragma clang diagnostic ignored "-Wpacked"
66 /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
67 __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
68 #pragma clang diagnostic pop
69 #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
71 #ifndef __UNALIGNED_UINT16_READ
72 #pragma clang diagnostic push
73 #pragma clang diagnostic ignored "-Wpacked"
74 /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
75 __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
76 #pragma clang diagnostic pop
77 #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
79 #ifndef __UNALIGNED_UINT32_WRITE
80 #pragma clang diagnostic push
81 #pragma clang diagnostic ignored "-Wpacked"
82 /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
83 __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
84 #pragma clang diagnostic pop
85 #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
87 #ifndef __UNALIGNED_UINT32_READ
88 #pragma clang diagnostic push
89 #pragma clang diagnostic ignored "-Wpacked"
90 __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
91 #pragma clang diagnostic pop
92 #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
95 #define __ALIGNED(x) __attribute__((aligned(x)))
98 #define __PACKED __attribute__((packed))
101 /* ########################## Core Instruction Access ######################### */
105 #define __NOP __builtin_arm_nop
108 \brief Wait For Interrupt
110 #define __WFI __builtin_arm_wfi
113 \brief Wait For Event
115 #define __WFE __builtin_arm_wfe
120 #define __SEV __builtin_arm_sev
123 \brief Instruction Synchronization Barrier
125 #define __ISB() do {\
126 __schedule_barrier();\
127 __builtin_arm_isb(0xF);\
128 __schedule_barrier();\
132 \brief Data Synchronization Barrier
134 #define __DSB() do {\
135 __schedule_barrier();\
136 __builtin_arm_dsb(0xF);\
137 __schedule_barrier();\
141 \brief Data Memory Barrier
143 #define __DMB() do {\
144 __schedule_barrier();\
145 __builtin_arm_dmb(0xF);\
146 __schedule_barrier();\
150 \brief Reverse byte order (32 bit)
151 \param [in] value Value to reverse
152 \return Reversed value
154 #define __REV __builtin_bswap32
157 \brief Reverse byte order (16 bit)
158 \param [in] value Value to reverse
159 \return Reversed value
161 #ifndef __NO_EMBEDDED_ASM
162 __attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
165 __ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
171 \brief Reverse byte order in signed short value
172 \param [in] value Value to reverse
173 \return Reversed value
175 #ifndef __NO_EMBEDDED_ASM
176 __attribute__((section(".revsh_text"))) __STATIC_INLINE int32_t __REVSH(int32_t value)
179 __ASM volatile("revsh %0, %1" : "=r" (result) : "r" (value));
185 \brief Rotate Right in unsigned value (32 bit)
186 \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
187 \param [in] op1 Value to rotate
188 \param [in] op2 Number of Bits to rotate
189 \return Rotated value
191 __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
193 return (op1 >> op2) | (op1 << (32U - op2));
198 \param [in] value is ignored by the processor.
199 If required, a debugger can use it to store additional information about the breakpoint.
201 #define __BKPT(value) __ASM volatile ("bkpt "#value)
204 \brief Reverse bit order of value
205 \param [in] value Value to reverse
206 \return Reversed value
208 #define __RBIT __builtin_arm_rbit
211 \brief Count leading zeros
212 \param [in] value Value to count the leading zeros
213 \return number of leading zeros in value
215 #define __CLZ __builtin_clz
218 \brief LDR Exclusive (8 bit)
219 \details Executes a exclusive LDR instruction for 8 bit value.
220 \param [in] ptr Pointer to data
221 \return value of type uint8_t at (*ptr)
223 #define __LDREXB (uint8_t)__builtin_arm_ldrex
227 \brief LDR Exclusive (16 bit)
228 \details Executes a exclusive LDR instruction for 16 bit values.
229 \param [in] ptr Pointer to data
230 \return value of type uint16_t at (*ptr)
232 #define __LDREXH (uint16_t)__builtin_arm_ldrex
235 \brief LDR Exclusive (32 bit)
236 \details Executes a exclusive LDR instruction for 32 bit values.
237 \param [in] ptr Pointer to data
238 \return value of type uint32_t at (*ptr)
240 #define __LDREXW (uint32_t)__builtin_arm_ldrex
243 \brief STR Exclusive (8 bit)
244 \details Executes a exclusive STR instruction for 8 bit values.
245 \param [in] value Value to store
246 \param [in] ptr Pointer to location
247 \return 0 Function succeeded
248 \return 1 Function failed
250 #define __STREXB (uint32_t)__builtin_arm_strex
253 \brief STR Exclusive (16 bit)
254 \details Executes a exclusive STR instruction for 16 bit values.
255 \param [in] value Value to store
256 \param [in] ptr Pointer to location
257 \return 0 Function succeeded
258 \return 1 Function failed
260 #define __STREXH (uint32_t)__builtin_arm_strex
263 \brief STR Exclusive (32 bit)
264 \details Executes a exclusive STR instruction for 32 bit values.
265 \param [in] value Value to store
266 \param [in] ptr Pointer to location
267 \return 0 Function succeeded
268 \return 1 Function failed
270 #define __STREXW (uint32_t)__builtin_arm_strex
273 \brief Remove the exclusive lock
274 \details Removes the exclusive lock which is created by LDREX.
276 #define __CLREX __builtin_arm_clrex
279 \brief Signed Saturate
280 \details Saturates a signed value.
281 \param [in] value Value to be saturated
282 \param [in] sat Bit position to saturate to (1..32)
283 \return Saturated value
285 #define __SSAT __builtin_arm_ssat
288 \brief Unsigned Saturate
289 \details Saturates an unsigned value.
290 \param [in] value Value to be saturated
291 \param [in] sat Bit position to saturate to (0..31)
292 \return Saturated value
294 #define __USAT __builtin_arm_usat
297 /* ########################### Core Function Access ########################### */
301 \details Returns the current value of the Floating Point Status/Control register.
302 \return Floating Point Status/Control register value
304 #define __get_FPSCR __builtin_arm_get_fpscr
308 \details Assigns the given value to the Floating Point Status/Control register.
309 \param [in] fpscr Floating Point Status/Control value to set
311 #define __set_FPSCR __builtin_arm_set_fpscr
313 /** \brief Get CPSR Register
314 \return CPSR Register value
316 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CPSR(void)
319 __ASM volatile("MRS %0, cpsr" : "=r" (result) );
323 /** \brief Set CPSR Register
324 \param [in] cpsr CPSR value to set
326 __attribute__((always_inline)) __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
328 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
332 \return Processor Mode
334 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_mode(void)
336 return (__get_CPSR() & 0x1FU);
340 \param [in] mode Mode value to set
342 __attribute__((always_inline)) __STATIC_INLINE void __set_mode(uint32_t mode)
344 __ASM volatile("MSR cpsr_c, %0" : : "r" (mode) : "memory");
347 /** \brief Get Stack Pointer
348 \return Stack Pointer value
350 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_SP()
353 __ASM volatile("MOV %0, sp" : "=r" (result) : : "memory");
357 /** \brief Set Stack Pointer
358 \param [in] stack Stack Pointer value to set
360 __attribute__((always_inline)) __STATIC_INLINE void __set_SP(uint32_t stack)
362 __ASM volatile("MOV sp, %0" : : "r" (stack) : "memory");
365 /** \brief Get USR/SYS Stack Pointer
366 \return USR/SYS Stack Pointer value
368 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_SP_usr()
374 "CPS #0x1F \n" // no effect in USR mode
376 "MSR cpsr_c, %2 \n" // no effect in USR mode
377 "ISB" : "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
382 /** \brief Set USR/SYS Stack Pointer
383 \param [in] topOfProcStack USR/SYS Stack Pointer value to set
385 __attribute__((always_inline)) __STATIC_INLINE void __set_SP_usr(uint32_t topOfProcStack)
390 "CPS #0x1F \n" // no effect in USR mode
392 "MSR cpsr_c, %2 \n" // no effect in USR mode
393 "ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
398 \return Floating Point Exception Control register value
400 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPEXC(void)
402 #if (__FPU_PRESENT == 1)
404 __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
412 \param [in] fpexc Floating Point Exception Control value to set
414 __attribute__((always_inline)) __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
416 #if (__FPU_PRESENT == 1)
417 __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
422 * Include common core functions to access Coprocessor 15 registers
425 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
426 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
428 #include "cmsis_cp15.h"
431 /** \brief Clean and Invalidate the entire data or unified cache
433 Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
435 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op)
440 " MRC p15, 1, R6, c0, c0, 1 \n" // Read CLIDR
441 " ANDS R3, R6, #0x07000000 \n" // Extract coherency level
442 " MOV R3, R3, LSR #23 \n" // Total cache levels << 1
443 " BEQ Finished \n" // If 0, no need to clean
445 " MOV R10, #0 \n" // R10 holds current cache level << 1
446 "Loop1: ADD R2, R10, R10, LSR #1 \n" // R2 holds cache "Set" position
447 " MOV R1, R6, LSR R2 \n" // Bottom 3 bits are the Cache-type for this level
448 " AND R1, R1, #7 \n" // Isolate those lower 3 bits
450 " BLT Skip \n" // No cache or only instruction cache at this level
452 " MCR p15, 2, R10, c0, c0, 0 \n" // Write the Cache Size selection register
453 " ISB \n" // ISB to sync the change to the CacheSizeID reg
454 " MRC p15, 1, R1, c0, c0, 0 \n" // Reads current Cache Size ID register
455 " AND R2, R1, #7 \n" // Extract the line length field
456 " ADD R2, R2, #4 \n" // Add 4 for the line length offset (log2 16 bytes)
458 " ANDS R4, R4, R1, LSR #3 \n" // R4 is the max number on the way size (right aligned)
459 " CLZ R5, R4 \n" // R5 is the bit position of the way size increment
460 " LDR R7, =0x7FFF \n"
461 " ANDS R7, R7, R1, LSR #13 \n" // R7 is the max number of the index size (right aligned)
463 "Loop2: MOV R9, R4 \n" // R9 working copy of the max way size (right aligned)
465 "Loop3: ORR R11, R10, R9, LSL R5 \n" // Factor in the Way number and cache number into R11
466 " ORR R11, R11, R7, LSL R2 \n" // Factor in the Set number
469 " MCR p15, 0, R11, c7, c6, 2 \n" // DCISW. Invalidate by Set/Way
471 "Dccsw: CMP R0, #1 \n"
473 " MCR p15, 0, R11, c7, c10, 2 \n" // DCCSW. Clean by Set/Way
475 "Dccisw: MCR p15, 0, R11, c7, c14, 2 \n" // DCCISW. Clean and Invalidate by Set/Way
476 "cont: SUBS R9, R9, #1 \n" // Decrement the Way number
478 " SUBS R7, R7, #1 \n" // Decrement the Set number
480 "Skip: ADD R10, R10, #2 \n" // Increment the cache number
490 /** \brief Enable Floating Point Unit
492 Critical section, called from undef handler, so systick is disabled
494 __STATIC_INLINE void __FPU_Enable(void)
497 //Permit access to VFP/NEON, registers by modifying CPACR
498 " MRC p15,0,R1,c1,c0,2 \n"
499 " ORR R1,R1,#0x00F00000 \n"
500 " MCR p15,0,R1,c1,c0,2 \n"
502 //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
507 " ORR R1,R1,#0x40000000 \n"
510 //Initialise VFP/NEON registers to 0
513 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT >= 16
514 //Initialise D16 registers to 0
533 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
534 //Initialise D32 registers to 0
553 //Initialise FPSCR to a known state
555 " LDR R3,=0x00086060 \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
561 #endif /* __CMSIS_ARMCLANG_H */