]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_armclang.h
Core: Fixed MISRA warnings.
[cmsis] / CMSIS / Core_A / Include / cmsis_armclang.h
1 /**************************************************************************//**
2  * @file     cmsis_armclang.h
3  * @brief    CMSIS compiler specific macros, functions, instructions
4  * @version  V1.0.1
5  * @date     07. Sep 2017
6  ******************************************************************************/
7 /*
8  * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  *
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
15  *
16  * www.apache.org/licenses/LICENSE-2.0
17  *
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.
23  */
24
25 #ifndef __CMSIS_ARMCLANG_H
26 #define __CMSIS_ARMCLANG_H
27
28 #ifndef __ARM_COMPAT_H
29 #include <arm_compat.h>    /* Compatibility header for ARM Compiler 5 intrinsics */
30 #endif
31
32 /* CMSIS compiler specific defines */
33 #ifndef   __ASM
34   #define __ASM                                  __asm
35 #endif                                          
36 #ifndef   __INLINE                              
37   #define __INLINE                               __inline
38 #endif                                          
39 #ifndef   __FORCEINLINE                              
40   #define __FORCEINLINE                          __attribute__((always_inline))
41 #endif                                          
42 #ifndef   __STATIC_INLINE                       
43   #define __STATIC_INLINE                        static __inline
44 #endif                                                                                    
45 #ifndef   __STATIC_FORCEINLINE                 
46   #define __STATIC_FORCEINLINE                   __attribute__((always_inline)) static __inline
47 #endif                                           
48 #ifndef   __NO_RETURN                           
49   #define __NO_RETURN                            __declspec(noreturn)
50 #endif                                          
51 #ifndef   __USED                                
52   #define __USED                                 __attribute__((used))
53 #endif                                          
54 #ifndef   __WEAK                                
55   #define __WEAK                                 __attribute__((weak))
56 #endif
57 #ifndef   __PACKED
58   #define __PACKED                               __attribute__((packed, aligned(1)))
59 #endif
60 #ifndef   __PACKED_STRUCT
61   #define __PACKED_STRUCT                        struct __attribute__((packed, aligned(1)))
62 #endif
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))
70 #endif
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)
78 #endif
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))
86 #endif
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)
93 #endif
94 #ifndef   __ALIGNED
95   #define __ALIGNED(x)                           __attribute__((aligned(x)))
96 #endif                                        
97 #ifndef   __PACKED                            
98   #define __PACKED                               __attribute__((packed))
99 #endif
100
101 /* ##########################  Core Instruction Access  ######################### */
102 /**
103   \brief   No Operation
104  */
105 #define __NOP                             __builtin_arm_nop
106
107 /**
108   \brief   Wait For Interrupt
109  */
110 #define __WFI                             __builtin_arm_wfi
111
112 /**
113   \brief   Wait For Event
114  */
115 #define __WFE                             __builtin_arm_wfe
116
117 /**
118   \brief   Send Event
119  */
120 #define __SEV                             __builtin_arm_sev
121
122 /**
123   \brief   Instruction Synchronization Barrier
124  */
125 #define __ISB() do {\
126                    __schedule_barrier();\
127                    __builtin_arm_isb(0xF);\
128                    __schedule_barrier();\
129                 } while (0U)
130
131 /**
132   \brief   Data Synchronization Barrier
133  */
134 #define __DSB() do {\
135                    __schedule_barrier();\
136                    __builtin_arm_dsb(0xF);\
137                    __schedule_barrier();\
138                 } while (0U)
139
140 /**
141   \brief   Data Memory Barrier
142  */
143 #define __DMB() do {\
144                    __schedule_barrier();\
145                    __builtin_arm_dmb(0xF);\
146                    __schedule_barrier();\
147                 } while (0U)
148
149 /**
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
154  */
155 #define __REV(value)   __builtin_bswap32(value)
156
157 /**
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
162  */
163 #define __REV16(value) __ROR(__REV(value), 16)
164
165
166 /**
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
171  */
172 #define __REVSH(value) (int16_t)__builtin_bswap16(value)
173
174
175 /**
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
181  */
182 __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
183 {
184   op2 %= 32U;
185   if (op2 == 0U) {
186     return op1;
187   }
188   return (op1 >> op2) | (op1 << (32U - op2));
189 }
190
191
192 /**
193   \brief   Breakpoint
194   \param [in]    value  is ignored by the processor.
195                  If required, a debugger can use it to store additional information about the breakpoint.
196  */
197 #define __BKPT(value)   __ASM volatile ("bkpt "#value)
198
199 /**
200   \brief   Reverse bit order of value
201   \param [in]    value  Value to reverse
202   \return               Reversed value
203  */
204 #define __RBIT          __builtin_arm_rbit
205
206 /**
207   \brief   Count leading zeros
208   \param [in]  value  Value to count the leading zeros
209   \return             number of leading zeros in value
210  */
211 #define __CLZ           (uint8_t)__builtin_clz
212
213 /**
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)
218  */
219 #define __LDREXB        (uint8_t)__builtin_arm_ldrex
220
221
222 /**
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)
227  */
228 #define __LDREXH        (uint16_t)__builtin_arm_ldrex
229
230 /**
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)
235  */
236 #define __LDREXW        (uint32_t)__builtin_arm_ldrex
237
238 /**
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
245  */
246 #define __STREXB        (uint32_t)__builtin_arm_strex
247
248 /**
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
255  */
256 #define __STREXH        (uint32_t)__builtin_arm_strex
257
258 /**
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
265  */
266 #define __STREXW        (uint32_t)__builtin_arm_strex
267
268 /**
269   \brief   Remove the exclusive lock
270   \details Removes the exclusive lock which is created by LDREX.
271  */
272 #define __CLREX             __builtin_arm_clrex
273
274 /**
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
280  */
281 #define __SSAT             __builtin_arm_ssat
282
283 /**
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
289  */
290 #define __USAT             __builtin_arm_usat
291
292
293 /* ###########################  Core Function Access  ########################### */
294
295 /**
296   \brief   Get FPSCR
297   \details Returns the current value of the Floating Point Status/Control register.
298   \return               Floating Point Status/Control register value
299  */
300 #define __get_FPSCR      __builtin_arm_get_fpscr
301
302 /**
303   \brief   Set 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
306  */
307 #define __set_FPSCR      __builtin_arm_set_fpscr
308
309 /** \brief  Get CPSR Register
310     \return               CPSR Register value
311  */
312 __STATIC_FORCEINLINE uint32_t __get_CPSR(void)
313 {
314   uint32_t result;
315   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
316   return(result);
317 }
318
319 /** \brief  Set CPSR Register
320     \param [in]    cpsr  CPSR value to set
321  */
322 __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
323 {
324 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
325 }
326
327 /** \brief  Get Mode
328     \return                Processor Mode
329  */
330 __STATIC_FORCEINLINE uint32_t __get_mode(void)
331 {
332         return (__get_CPSR() & 0x1FU);
333 }
334
335 /** \brief  Set Mode
336     \param [in]    mode  Mode value to set
337  */
338 __STATIC_FORCEINLINE void __set_mode(uint32_t mode)
339 {
340   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
341 }
342
343 /** \brief  Get Stack Pointer
344     \return Stack Pointer value
345  */
346 __STATIC_FORCEINLINE uint32_t __get_SP()
347 {
348   uint32_t result;
349   __ASM volatile("MOV  %0, sp" : "=r" (result) : : "memory");
350   return result;
351 }
352
353 /** \brief  Set Stack Pointer
354     \param [in]    stack  Stack Pointer value to set
355  */
356 __STATIC_FORCEINLINE void __set_SP(uint32_t stack)
357 {
358   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
359 }
360
361 /** \brief  Get USR/SYS Stack Pointer
362     \return USR/SYS Stack Pointer value
363  */
364 __STATIC_FORCEINLINE uint32_t __get_SP_usr()
365 {
366   uint32_t cpsr;
367   uint32_t result;
368   __ASM volatile(
369     "MRS     %0, cpsr   \n"
370     "CPS     #0x1F      \n" // no effect in USR mode
371     "MOV     %1, sp     \n"
372     "MSR     cpsr_c, %2 \n" // no effect in USR mode
373     "ISB" :  "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
374    );
375   return result;
376 }
377
378 /** \brief  Set USR/SYS Stack Pointer
379     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
380  */
381 __STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
382 {
383   uint32_t cpsr;
384   __ASM volatile(
385     "MRS     %0, cpsr   \n"
386     "CPS     #0x1F      \n" // no effect in USR mode
387     "MOV     sp, %1     \n"
388     "MSR     cpsr_c, %2 \n" // no effect in USR mode
389     "ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
390    );
391 }
392
393 /** \brief  Get FPEXC
394     \return               Floating Point Exception Control register value
395  */
396 __STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
397 {
398 #if (__FPU_PRESENT == 1)
399   uint32_t result;
400   __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
401   return(result);
402 #else
403   return(0);
404 #endif
405 }
406
407 /** \brief  Set FPEXC
408     \param [in]    fpexc  Floating Point Exception Control value to set
409  */
410 __STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
411 {
412 #if (__FPU_PRESENT == 1)
413   __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
414 #endif
415 }
416
417 /*
418  * Include common core functions to access Coprocessor 15 registers
419  */
420
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" )
425
426 #include "cmsis_cp15.h"
427
428
429 /** \brief  Clean and Invalidate the entire data or unified cache
430
431   Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
432  */
433 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op)
434 {
435   __ASM volatile(
436     "        PUSH    {R4-R11}                   \n"
437
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
442
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
447     "        CMP     R1, #2                     \n"
448     "        BLT     Skip                       \n" // No cache or only instruction cache at this level
449
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)
455     "        LDR     R4, =0x3FF                 \n"
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)
460
461     "Loop2:  MOV     R9, R4                     \n" // R9 working copy of the max way size (right aligned)
462
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
465     "        CMP     R0, #0                     \n"
466     "        BNE     Dccsw                      \n"
467     "        MCR     p15, 0, R11, c7, c6, 2     \n" // DCISW. Invalidate by Set/Way
468     "        B       cont                       \n"
469     "Dccsw:  CMP     R0, #1                     \n"
470     "        BNE     Dccisw                     \n"
471     "        MCR     p15, 0, R11, c7, c10, 2    \n" // DCCSW. Clean by Set/Way
472     "        B       cont                       \n"
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
475     "        BGE     Loop3                      \n"
476     "        SUBS    R7, R7, #1                 \n" // Decrement the Set number
477     "        BGE     Loop2                      \n"
478     "Skip:   ADD     R10, R10, #2               \n" // Increment the cache number
479     "        CMP     R3, R10                    \n"
480     "        BGT     Loop1                      \n"
481
482     "Finished:                                  \n"
483     "        DSB                                \n"
484     "        POP    {R4-R11}                      "
485   );
486 }
487
488 /** \brief  Enable Floating Point Unit
489
490   Critical section, called from undef handler, so systick is disabled
491  */
492 __STATIC_INLINE void __FPU_Enable(void)
493 {
494   __ASM volatile(
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"
499
500             //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
501     "        ISB                       \n"
502
503             //Enable VFP/NEON
504     "        VMRS    R1,FPEXC          \n"
505     "        ORR     R1,R1,#0x40000000 \n"
506     "        VMSR    FPEXC,R1          \n"
507
508             //Initialise VFP/NEON registers to 0
509     "        MOV     R2,#0             \n"
510
511 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT >= 16
512             //Initialise D16 registers to 0
513     "        VMOV    D0, R2,R2         \n"
514     "        VMOV    D1, R2,R2         \n"
515     "        VMOV    D2, R2,R2         \n"
516     "        VMOV    D3, R2,R2         \n"
517     "        VMOV    D4, R2,R2         \n"
518     "        VMOV    D5, R2,R2         \n"
519     "        VMOV    D6, R2,R2         \n"
520     "        VMOV    D7, R2,R2         \n"
521     "        VMOV    D8, R2,R2         \n"
522     "        VMOV    D9, R2,R2         \n"
523     "        VMOV    D10,R2,R2         \n"
524     "        VMOV    D11,R2,R2         \n"
525     "        VMOV    D12,R2,R2         \n"
526     "        VMOV    D13,R2,R2         \n"
527     "        VMOV    D14,R2,R2         \n"
528     "        VMOV    D15,R2,R2         \n"
529 #endif
530
531 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
532             //Initialise D32 registers to 0
533     "        VMOV    D16,R2,R2         \n"
534     "        VMOV    D17,R2,R2         \n"
535     "        VMOV    D18,R2,R2         \n"
536     "        VMOV    D19,R2,R2         \n"
537     "        VMOV    D20,R2,R2         \n"
538     "        VMOV    D21,R2,R2         \n"
539     "        VMOV    D22,R2,R2         \n"
540     "        VMOV    D23,R2,R2         \n"
541     "        VMOV    D24,R2,R2         \n"
542     "        VMOV    D25,R2,R2         \n"
543     "        VMOV    D26,R2,R2         \n"
544     "        VMOV    D27,R2,R2         \n"
545     "        VMOV    D28,R2,R2         \n"
546     "        VMOV    D29,R2,R2         \n"
547     "        VMOV    D30,R2,R2         \n"
548     "        VMOV    D31,R2,R2         \n"
549     ".endif                            \n"
550 #endif
551             //Initialise FPSCR to a known state
552     "        VMRS    R2,FPSCR          \n"
553     "        LDR     R3,=0x00086060    \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
554     "        AND     R2,R2,R3          \n"
555     "        VMSR    FPSCR,R2            "
556   );
557 }
558
559 #endif /* __CMSIS_ARMCLANG_H */