]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_armcc.h
Core: Fixed minor compiler and MISRA warnings.
[cmsis] / CMSIS / Core_A / Include / cmsis_armcc.h
1 /**************************************************************************//**
2  * @file     cmsis_armcc.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_ARMCC_H
26 #define __CMSIS_ARMCC_H
27
28 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
29   #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
30 #endif
31
32 /* CMSIS compiler control architecture macros */
33 #if (defined (__TARGET_ARCH_7_A ) && (__TARGET_ARCH_7_A  == 1))
34   #define __ARM_ARCH_7A__           1
35 #endif
36
37 /* CMSIS compiler specific defines */
38 #ifndef   __ASM
39   #define __ASM                                  __asm
40 #endif                                          
41 #ifndef   __INLINE                              
42   #define __INLINE                               __inline
43 #endif                                          
44 #ifndef   __FORCEINLINE                              
45   #define __FORCEINLINE                          __forceinline
46 #endif                                          
47 #ifndef   __STATIC_INLINE                       
48   #define __STATIC_INLINE                        static __inline
49 #endif                                                                                   
50 #ifndef   __STATIC_FORCEINLINE                 
51   #define __STATIC_FORCEINLINE                   static __forceinline
52 #endif                                                                                   
53 #ifndef   __NO_RETURN                           
54   #define __NO_RETURN                            __declspec(noreturn)
55 #endif                                          
56 #ifndef   __USED                                
57   #define __USED                                 __attribute__((used))
58 #endif                                          
59 #ifndef   __WEAK                                
60   #define __WEAK                                 __attribute__((weak))
61 #endif
62 #ifndef   __PACKED
63   #define __PACKED                               __attribute__((packed))
64 #endif
65 #ifndef   __PACKED_STRUCT
66   #define __PACKED_STRUCT                        __packed struct
67 #endif
68 #ifndef   __UNALIGNED_UINT16_WRITE
69   #define __UNALIGNED_UINT16_WRITE(addr, val)    ((*((__packed uint16_t *)(addr))) = (val))
70 #endif
71 #ifndef   __UNALIGNED_UINT16_READ
72   #define __UNALIGNED_UINT16_READ(addr)          (*((const __packed uint16_t *)(addr)))
73 #endif
74 #ifndef   __UNALIGNED_UINT32_WRITE
75   #define __UNALIGNED_UINT32_WRITE(addr, val)    ((*((__packed uint32_t *)(addr))) = (val))
76 #endif
77 #ifndef   __UNALIGNED_UINT32_READ
78   #define __UNALIGNED_UINT32_READ(addr)          (*((const __packed uint32_t *)(addr)))
79 #endif
80 #ifndef   __ALIGNED
81   #define __ALIGNED(x)                           __attribute__((aligned(x)))
82 #endif                                          
83 #ifndef   __PACKED                              
84   #define __PACKED                               __attribute__((packed))
85 #endif
86
87 /* ##########################  Core Instruction Access  ######################### */
88 /**
89   \brief   No Operation
90  */
91 #define __NOP                             __nop
92
93 /**
94   \brief   Wait For Interrupt
95  */
96 #define __WFI                             __wfi
97
98 /**
99   \brief   Wait For Event
100  */
101 #define __WFE                             __wfe
102
103 /**
104   \brief   Send Event
105  */
106 #define __SEV                             __sev
107
108 /**
109   \brief   Instruction Synchronization Barrier
110  */
111 #define __ISB() do {\
112                    __schedule_barrier();\
113                    __isb(0xF);\
114                    __schedule_barrier();\
115                 } while (0U)
116
117 /**
118   \brief   Data Synchronization Barrier
119  */
120 #define __DSB() do {\
121                    __schedule_barrier();\
122                    __dsb(0xF);\
123                    __schedule_barrier();\
124                 } while (0U)
125
126 /**
127   \brief   Data Memory Barrier
128  */
129 #define __DMB() do {\
130                    __schedule_barrier();\
131                    __dmb(0xF);\
132                    __schedule_barrier();\
133                 } while (0U)
134
135 /**
136   \brief   Reverse byte order (32 bit)
137   \param [in]    value  Value to reverse
138   \return               Reversed value
139  */
140 #define __REV                             __rev
141
142 /**
143   \brief   Reverse byte order (16 bit)
144   \param [in]    value  Value to reverse
145   \return               Reversed value
146  */
147 #ifndef __NO_EMBEDDED_ASM
148 __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
149 {
150   rev16 r0, r0
151   bx lr
152 }
153 #endif
154
155 /**
156   \brief   Reverse byte order in signed short value
157   \param [in]    value  Value to reverse
158   \return               Reversed value
159  */
160 #ifndef __NO_EMBEDDED_ASM
161 __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
162 {
163   revsh r0, r0
164   bx lr
165 }
166 #endif
167
168 /**
169   \brief   Rotate Right in unsigned value (32 bit)
170   \param [in]    op1  Value to rotate
171   \param [in]    op2  Number of Bits to rotate
172   \return               Rotated value
173  */
174 #define __ROR                             __ror
175
176 /**
177   \brief   Breakpoint
178   \param [in]    value  is ignored by the processor.
179                  If required, a debugger can use it to store additional information about the breakpoint.
180  */
181 #define __BKPT(value)                     __breakpoint(value)
182
183 /**
184   \brief   Reverse bit order of value
185   \param [in]    value  Value to reverse
186   \return               Reversed value
187  */
188 #define __RBIT                            __rbit
189
190 /**
191   \brief   Count leading zeros
192   \param [in]  value  Value to count the leading zeros
193   \return             number of leading zeros in value
194  */
195 #define __CLZ                             __clz
196
197 /**
198   \brief   LDR Exclusive (8 bit)
199   \details Executes a exclusive LDR instruction for 8 bit value.
200   \param [in]    ptr  Pointer to data
201   \return             value of type uint8_t at (*ptr)
202  */
203 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
204   #define __LDREXB(ptr)                                                        ((uint8_t ) __ldrex(ptr))
205 #else
206   #define __LDREXB(ptr)          _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr))  _Pragma("pop")
207 #endif
208
209 /**
210   \brief   LDR Exclusive (16 bit)
211   \details Executes a exclusive LDR instruction for 16 bit values.
212   \param [in]    ptr  Pointer to data
213   \return        value of type uint16_t at (*ptr)
214  */
215 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
216   #define __LDREXH(ptr)                                                        ((uint16_t) __ldrex(ptr))
217 #else
218   #define __LDREXH(ptr)          _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr))  _Pragma("pop")
219 #endif
220
221 /**
222   \brief   LDR Exclusive (32 bit)
223   \details Executes a exclusive LDR instruction for 32 bit values.
224   \param [in]    ptr  Pointer to data
225   \return        value of type uint32_t at (*ptr)
226  */
227 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
228   #define __LDREXW(ptr)                                                        ((uint32_t ) __ldrex(ptr))
229 #else
230   #define __LDREXW(ptr)          _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr))  _Pragma("pop")
231 #endif
232
233 /**
234   \brief   STR Exclusive (8 bit)
235   \details Executes a exclusive STR instruction for 8 bit values.
236   \param [in]  value  Value to store
237   \param [in]    ptr  Pointer to location
238   \return          0  Function succeeded
239   \return          1  Function failed
240  */
241 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
242   #define __STREXB(value, ptr)                                                 __strex(value, ptr)
243 #else
244   #define __STREXB(value, ptr)   _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr)        _Pragma("pop")
245 #endif
246
247 /**
248   \brief   STR Exclusive (16 bit)
249   \details Executes a exclusive STR instruction for 16 bit values.
250   \param [in]  value  Value to store
251   \param [in]    ptr  Pointer to location
252   \return          0  Function succeeded
253   \return          1  Function failed
254  */
255 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
256   #define __STREXH(value, ptr)                                                 __strex(value, ptr)
257 #else
258   #define __STREXH(value, ptr)   _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr)        _Pragma("pop")
259 #endif
260
261 /**
262   \brief   STR Exclusive (32 bit)
263   \details Executes a exclusive STR instruction for 32 bit values.
264   \param [in]  value  Value to store
265   \param [in]    ptr  Pointer to location
266   \return          0  Function succeeded
267   \return          1  Function failed
268  */
269 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
270   #define __STREXW(value, ptr)                                                 __strex(value, ptr)
271 #else
272   #define __STREXW(value, ptr)   _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr)        _Pragma("pop")
273 #endif
274
275 /**
276   \brief   Remove the exclusive lock
277   \details Removes the exclusive lock which is created by LDREX.
278  */
279 #define __CLREX                           __clrex
280
281
282 /**
283   \brief   Signed Saturate
284   \details Saturates a signed value.
285   \param [in]  value  Value to be saturated
286   \param [in]    sat  Bit position to saturate to (1..32)
287   \return             Saturated value
288  */
289 #define __SSAT                            __ssat
290
291 /**
292   \brief   Unsigned Saturate
293   \details Saturates an unsigned value.
294   \param [in]  value  Value to be saturated
295   \param [in]    sat  Bit position to saturate to (0..31)
296   \return             Saturated value
297  */
298 #define __USAT                            __usat
299
300 /* ###########################  Core Function Access  ########################### */
301
302 /**
303   \brief   Get FPSCR (Floating Point Status/Control)
304   \return               Floating Point Status/Control register value
305  */
306 __STATIC_INLINE uint32_t __get_FPSCR(void)
307 {
308 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
309      (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
310   register uint32_t __regfpscr         __ASM("fpscr");
311   return(__regfpscr);
312 #else
313    return(0U);
314 #endif
315 }
316
317 /**
318   \brief   Set FPSCR (Floating Point Status/Control)
319   \param [in]    fpscr  Floating Point Status/Control value to set
320  */
321 __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
322 {
323 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
324      (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
325   register uint32_t __regfpscr         __ASM("fpscr");
326   __regfpscr = (fpscr);
327 #else
328   (void)fpscr;
329 #endif
330 }
331
332 /** \brief  Get CPSR (Current Program Status Register)
333     \return               CPSR Register value
334  */
335 __STATIC_INLINE uint32_t __get_CPSR(void)
336 {
337   register uint32_t __regCPSR          __ASM("cpsr");
338   return(__regCPSR);
339 }
340
341
342 /** \brief  Set CPSR (Current Program Status Register)
343     \param [in]    cpsr  CPSR value to set
344  */
345 __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
346 {
347   register uint32_t __regCPSR          __ASM("cpsr");
348   __regCPSR = cpsr;
349 }
350
351 /** \brief  Get Mode
352     \return                Processor Mode
353  */
354 __STATIC_INLINE uint32_t __get_mode(void) {
355   return (__get_CPSR() & 0x1FU);
356 }
357
358 /** \brief  Set Mode
359     \param [in]    mode  Mode value to set
360  */
361 __STATIC_INLINE __ASM void __set_mode(uint32_t mode) {
362   MOV  r1, lr
363   MSR  CPSR_C, r0
364   BX   r1
365 }
366
367 /** \brief  Get Stack Pointer
368     \return Stack Pointer
369  */
370 __STATIC_INLINE __ASM uint32_t __get_SP(void)
371 {
372   MOV  r0, sp
373   BX   lr
374 }
375
376 /** \brief  Set Stack Pointer 
377     \param [in]    stack  Stack Pointer value to set
378  */
379 __STATIC_INLINE __ASM void __set_SP(uint32_t stack)
380 {
381   MOV  sp, r0
382   BX   lr
383 }
384
385
386 /** \brief  Get USR/SYS Stack Pointer
387     \return USR/SYSStack Pointer
388  */
389 __STATIC_INLINE __ASM uint32_t __get_SP_usr(void)
390 {
391   ARM
392   PRESERVE8
393
394   MRS     R1, CPSR
395   CPS     #0x1F       ;no effect in USR mode
396   MOV     R0, SP
397   MSR     CPSR_c, R1  ;no effect in USR mode
398   ISB
399   BX      LR
400 }
401
402 /** \brief  Set USR/SYS Stack Pointer
403     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
404  */
405 __STATIC_INLINE __ASM void __set_SP_usr(uint32_t topOfProcStack)
406 {
407   ARM
408   PRESERVE8
409
410   MRS     R1, CPSR
411   CPS     #0x1F       ;no effect in USR mode
412   MOV     SP, R0
413   MSR     CPSR_c, R1  ;no effect in USR mode
414   ISB
415   BX      LR
416 }
417
418 /** \brief  Get FPEXC (Floating Point Exception Control Register)
419     \return               Floating Point Exception Control Register value
420  */
421 __STATIC_INLINE uint32_t __get_FPEXC(void)
422 {
423 #if (__FPU_PRESENT == 1)
424   register uint32_t __regfpexc         __ASM("fpexc");
425   return(__regfpexc);
426 #else
427   return(0);
428 #endif
429 }
430
431 /** \brief  Set FPEXC (Floating Point Exception Control Register)
432     \param [in]    fpexc  Floating Point Exception Control value to set
433  */
434 __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
435 {
436 #if (__FPU_PRESENT == 1)
437   register uint32_t __regfpexc         __ASM("fpexc");
438   __regfpexc = (fpexc);
439 #endif
440 }
441
442 /*
443  * Include common core functions to access Coprocessor 15 registers
444  */
445  
446 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) do { register uint32_t tmp __ASM("cp15:0:c1:c0:1"); Rt = tmp; } while(0)
447 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) do { register uint32_t tmp __ASM("cp15:0:c1:c0:1"); tmp = Rt; } while(0)
448
449 #include "cmsis_cp15.h"
450
451 /** \brief  Clean and Invalidate the entire data or unified cache
452  * \param [in] op 0 - invalidate, 1 - clean, otherwise - invalidate and clean
453  */
454 __STATIC_INLINE __ASM void __L1C_CleanInvalidateCache(uint32_t op) {
455         ARM
456
457         PUSH    {R4-R11}
458
459         MRC     p15, 1, R6, c0, c0, 1      // Read CLIDR
460         ANDS    R3, R6, #0x07000000        // Extract coherency level
461         MOV     R3, R3, LSR #23            // Total cache levels << 1
462         BEQ     Finished                   // If 0, no need to clean
463
464         MOV     R10, #0                    // R10 holds current cache level << 1
465 Loop1   ADD     R2, R10, R10, LSR #1       // R2 holds cache "Set" position
466         MOV     R1, R6, LSR R2             // Bottom 3 bits are the Cache-type for this level
467         AND     R1, R1, #7                 // Isolate those lower 3 bits
468         CMP     R1, #2
469         BLT     Skip                       // No cache or only instruction cache at this level
470
471         MCR     p15, 2, R10, c0, c0, 0     // Write the Cache Size selection register
472         ISB                                // ISB to sync the change to the CacheSizeID reg
473         MRC     p15, 1, R1, c0, c0, 0      // Reads current Cache Size ID register
474         AND     R2, R1, #7                 // Extract the line length field
475         ADD     R2, R2, #4                 // Add 4 for the line length offset (log2 16 bytes)
476         LDR     R4, =0x3FF
477         ANDS    R4, R4, R1, LSR #3         // R4 is the max number on the way size (right aligned)
478         CLZ     R5, R4                     // R5 is the bit position of the way size increment
479         LDR     R7, =0x7FFF
480         ANDS    R7, R7, R1, LSR #13        // R7 is the max number of the index size (right aligned)
481
482 Loop2   MOV     R9, R4                     // R9 working copy of the max way size (right aligned)
483
484 Loop3   ORR     R11, R10, R9, LSL R5       // Factor in the Way number and cache number into R11
485         ORR     R11, R11, R7, LSL R2       // Factor in the Set number
486         CMP     R0, #0
487         BNE     Dccsw
488         MCR     p15, 0, R11, c7, c6, 2     // DCISW. Invalidate by Set/Way
489         B       cont
490 Dccsw   CMP     R0, #1
491         BNE     Dccisw
492         MCR     p15, 0, R11, c7, c10, 2    // DCCSW. Clean by Set/Way
493         B       cont
494 Dccisw  MCR     p15, 0, R11, c7, c14, 2    // DCCISW. Clean and Invalidate by Set/Way
495 cont    SUBS    R9, R9, #1                 // Decrement the Way number
496         BGE     Loop3
497         SUBS    R7, R7, #1                 // Decrement the Set number
498         BGE     Loop2
499 Skip    ADD     R10, R10, #2               // Increment the cache number
500         CMP     R3, R10
501         BGT     Loop1
502
503 Finished
504         DSB
505         POP    {R4-R11}
506         BX     lr
507 }
508
509 /** \brief  Enable Floating Point Unit
510
511   Critical section, called from undef handler, so systick is disabled
512  */
513 __STATIC_INLINE __ASM void __FPU_Enable(void) {
514         ARM
515
516         //Permit access to VFP/NEON, registers by modifying CPACR
517         MRC     p15,0,R1,c1,c0,2
518         ORR     R1,R1,#0x00F00000
519         MCR     p15,0,R1,c1,c0,2
520
521         //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
522         ISB
523
524         //Enable VFP/NEON
525         VMRS    R1,FPEXC
526         ORR     R1,R1,#0x40000000
527         VMSR    FPEXC,R1
528
529         //Initialise VFP/NEON registers to 0
530         MOV     R2,#0
531   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16
532         //Initialise D16 registers to 0
533         VMOV    D0, R2,R2
534         VMOV    D1, R2,R2
535         VMOV    D2, R2,R2
536         VMOV    D3, R2,R2
537         VMOV    D4, R2,R2
538         VMOV    D5, R2,R2
539         VMOV    D6, R2,R2
540         VMOV    D7, R2,R2
541         VMOV    D8, R2,R2
542         VMOV    D9, R2,R2
543         VMOV    D10,R2,R2
544         VMOV    D11,R2,R2
545         VMOV    D12,R2,R2
546         VMOV    D13,R2,R2
547         VMOV    D14,R2,R2
548         VMOV    D15,R2,R2
549   ENDIF
550   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
551         //Initialise D32 registers to 0
552         VMOV    D16,R2,R2
553         VMOV    D17,R2,R2
554         VMOV    D18,R2,R2
555         VMOV    D19,R2,R2
556         VMOV    D20,R2,R2
557         VMOV    D21,R2,R2
558         VMOV    D22,R2,R2
559         VMOV    D23,R2,R2
560         VMOV    D24,R2,R2
561         VMOV    D25,R2,R2
562         VMOV    D26,R2,R2
563         VMOV    D27,R2,R2
564         VMOV    D28,R2,R2
565         VMOV    D29,R2,R2
566         VMOV    D30,R2,R2
567         VMOV    D31,R2,R2
568   ENDIF
569
570         //Initialise FPSCR to a known state
571         VMRS    R2,FPSCR
572         LDR     R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
573         AND     R2,R2,R3
574         VMSR    FPSCR,R2
575
576         BX      LR
577 }
578
579 #endif /* __CMSIS_ARMCC_H */