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 \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
152 \param [in] value Value to reverse
153 \return Reversed value
155 #define __REV(value) __builtin_bswap32(value)
158 \brief Reverse byte order (16 bit)
159 \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
160 \param [in] value Value to reverse
161 \return Reversed value
163 #define __REV16(value) __ROR(__REV(value), 16)
167 \brief Reverse byte order (16 bit)
168 \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
169 \param [in] value Value to reverse
170 \return Reversed value
172 #define __REVSH(value) (int16_t)__builtin_bswap16(value)
176 \brief Rotate Right in unsigned value (32 bit)
177 \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
178 \param [in] op1 Value to rotate
179 \param [in] op2 Number of Bits to rotate
180 \return Rotated value
182 __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
188 return (op1 >> op2) | (op1 << (32U - op2));
194 \param [in] value is ignored by the processor.
195 If required, a debugger can use it to store additional information about the breakpoint.
197 #define __BKPT(value) __ASM volatile ("bkpt "#value)
200 \brief Reverse bit order of value
201 \param [in] value Value to reverse
202 \return Reversed value
204 #define __RBIT __builtin_arm_rbit
207 \brief Count leading zeros
208 \param [in] value Value to count the leading zeros
209 \return number of leading zeros in value
211 #define __CLZ (uint8_t)__builtin_clz
214 \brief LDR Exclusive (8 bit)
215 \details Executes a exclusive LDR instruction for 8 bit value.
216 \param [in] ptr Pointer to data
217 \return value of type uint8_t at (*ptr)
219 #define __LDREXB (uint8_t)__builtin_arm_ldrex
223 \brief LDR Exclusive (16 bit)
224 \details Executes a exclusive LDR instruction for 16 bit values.
225 \param [in] ptr Pointer to data
226 \return value of type uint16_t at (*ptr)
228 #define __LDREXH (uint16_t)__builtin_arm_ldrex
231 \brief LDR Exclusive (32 bit)
232 \details Executes a exclusive LDR instruction for 32 bit values.
233 \param [in] ptr Pointer to data
234 \return value of type uint32_t at (*ptr)
236 #define __LDREXW (uint32_t)__builtin_arm_ldrex
239 \brief STR Exclusive (8 bit)
240 \details Executes a exclusive STR instruction for 8 bit values.
241 \param [in] value Value to store
242 \param [in] ptr Pointer to location
243 \return 0 Function succeeded
244 \return 1 Function failed
246 #define __STREXB (uint32_t)__builtin_arm_strex
249 \brief STR Exclusive (16 bit)
250 \details Executes a exclusive STR instruction for 16 bit values.
251 \param [in] value Value to store
252 \param [in] ptr Pointer to location
253 \return 0 Function succeeded
254 \return 1 Function failed
256 #define __STREXH (uint32_t)__builtin_arm_strex
259 \brief STR Exclusive (32 bit)
260 \details Executes a exclusive STR instruction for 32 bit values.
261 \param [in] value Value to store
262 \param [in] ptr Pointer to location
263 \return 0 Function succeeded
264 \return 1 Function failed
266 #define __STREXW (uint32_t)__builtin_arm_strex
269 \brief Remove the exclusive lock
270 \details Removes the exclusive lock which is created by LDREX.
272 #define __CLREX __builtin_arm_clrex
275 \brief Signed Saturate
276 \details Saturates a signed value.
277 \param [in] value Value to be saturated
278 \param [in] sat Bit position to saturate to (1..32)
279 \return Saturated value
281 #define __SSAT __builtin_arm_ssat
284 \brief Unsigned Saturate
285 \details Saturates an unsigned value.
286 \param [in] value Value to be saturated
287 \param [in] sat Bit position to saturate to (0..31)
288 \return Saturated value
290 #define __USAT __builtin_arm_usat
293 /* ########################### Core Function Access ########################### */
297 \details Returns the current value of the Floating Point Status/Control register.
298 \return Floating Point Status/Control register value
300 #define __get_FPSCR __builtin_arm_get_fpscr
304 \details Assigns the given value to the Floating Point Status/Control register.
305 \param [in] fpscr Floating Point Status/Control value to set
307 #define __set_FPSCR __builtin_arm_set_fpscr
309 /** \brief Get CPSR Register
310 \return CPSR Register value
312 __STATIC_FORCEINLINE uint32_t __get_CPSR(void)
315 __ASM volatile("MRS %0, cpsr" : "=r" (result) );
319 /** \brief Set CPSR Register
320 \param [in] cpsr CPSR value to set
322 __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
324 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
328 \return Processor Mode
330 __STATIC_FORCEINLINE uint32_t __get_mode(void)
332 return (__get_CPSR() & 0x1FU);
336 \param [in] mode Mode value to set
338 __STATIC_FORCEINLINE void __set_mode(uint32_t mode)
340 __ASM volatile("MSR cpsr_c, %0" : : "r" (mode) : "memory");
343 /** \brief Get Stack Pointer
344 \return Stack Pointer value
346 __STATIC_FORCEINLINE uint32_t __get_SP()
349 __ASM volatile("MOV %0, sp" : "=r" (result) : : "memory");
353 /** \brief Set Stack Pointer
354 \param [in] stack Stack Pointer value to set
356 __STATIC_FORCEINLINE void __set_SP(uint32_t stack)
358 __ASM volatile("MOV sp, %0" : : "r" (stack) : "memory");
361 /** \brief Get USR/SYS Stack Pointer
362 \return USR/SYS Stack Pointer value
364 __STATIC_FORCEINLINE uint32_t __get_SP_usr()
370 "CPS #0x1F \n" // no effect in USR mode
372 "MSR cpsr_c, %2 \n" // no effect in USR mode
373 "ISB" : "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
378 /** \brief Set USR/SYS Stack Pointer
379 \param [in] topOfProcStack USR/SYS Stack Pointer value to set
381 __STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
386 "CPS #0x1F \n" // no effect in USR mode
388 "MSR cpsr_c, %2 \n" // no effect in USR mode
389 "ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
394 \return Floating Point Exception Control register value
396 __STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
398 #if (__FPU_PRESENT == 1)
400 __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
408 \param [in] fpexc Floating Point Exception Control value to set
410 __STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
412 #if (__FPU_PRESENT == 1)
413 __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
418 * Include common core functions to access Coprocessor 15 registers
421 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
422 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
423 #define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" )
424 #define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" )
426 #include "cmsis_cp15.h"
429 /** \brief Clean and Invalidate the entire data or unified cache
431 Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
433 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op)
438 " MRC p15, 1, R6, c0, c0, 1 \n" // Read CLIDR
439 " ANDS R3, R6, #0x07000000 \n" // Extract coherency level
440 " MOV R3, R3, LSR #23 \n" // Total cache levels << 1
441 " BEQ Finished \n" // If 0, no need to clean
443 " MOV R10, #0 \n" // R10 holds current cache level << 1
444 "Loop1: ADD R2, R10, R10, LSR #1 \n" // R2 holds cache "Set" position
445 " MOV R1, R6, LSR R2 \n" // Bottom 3 bits are the Cache-type for this level
446 " AND R1, R1, #7 \n" // Isolate those lower 3 bits
448 " BLT Skip \n" // No cache or only instruction cache at this level
450 " MCR p15, 2, R10, c0, c0, 0 \n" // Write the Cache Size selection register
451 " ISB \n" // ISB to sync the change to the CacheSizeID reg
452 " MRC p15, 1, R1, c0, c0, 0 \n" // Reads current Cache Size ID register
453 " AND R2, R1, #7 \n" // Extract the line length field
454 " ADD R2, R2, #4 \n" // Add 4 for the line length offset (log2 16 bytes)
456 " ANDS R4, R4, R1, LSR #3 \n" // R4 is the max number on the way size (right aligned)
457 " CLZ R5, R4 \n" // R5 is the bit position of the way size increment
458 " LDR R7, =0x7FFF \n"
459 " ANDS R7, R7, R1, LSR #13 \n" // R7 is the max number of the index size (right aligned)
461 "Loop2: MOV R9, R4 \n" // R9 working copy of the max way size (right aligned)
463 "Loop3: ORR R11, R10, R9, LSL R5 \n" // Factor in the Way number and cache number into R11
464 " ORR R11, R11, R7, LSL R2 \n" // Factor in the Set number
467 " MCR p15, 0, R11, c7, c6, 2 \n" // DCISW. Invalidate by Set/Way
469 "Dccsw: CMP R0, #1 \n"
471 " MCR p15, 0, R11, c7, c10, 2 \n" // DCCSW. Clean by Set/Way
473 "Dccisw: MCR p15, 0, R11, c7, c14, 2 \n" // DCCISW. Clean and Invalidate by Set/Way
474 "cont: SUBS R9, R9, #1 \n" // Decrement the Way number
476 " SUBS R7, R7, #1 \n" // Decrement the Set number
478 "Skip: ADD R10, R10, #2 \n" // Increment the cache number
488 /** \brief Enable Floating Point Unit
490 Critical section, called from undef handler, so systick is disabled
492 __STATIC_INLINE void __FPU_Enable(void)
495 //Permit access to VFP/NEON, registers by modifying CPACR
496 " MRC p15,0,R1,c1,c0,2 \n"
497 " ORR R1,R1,#0x00F00000 \n"
498 " MCR p15,0,R1,c1,c0,2 \n"
500 //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
505 " ORR R1,R1,#0x40000000 \n"
508 //Initialise VFP/NEON registers to 0
511 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT >= 16
512 //Initialise D16 registers to 0
531 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
532 //Initialise D32 registers to 0
551 //Initialise FPSCR to a known state
553 " LDR R3,=0x00086060 \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
559 #endif /* __CMSIS_ARMCLANG_H */