]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_armcc.h
CoreValidation: Fixed test projects for Cortex-M0+
[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   \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
138   \param [in]    value  Value to reverse
139   \return               Reversed value
140  */
141 #define __REV                             __rev
142
143 /**
144   \brief   Reverse byte order (16 bit)
145   \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
146   \param [in]    value  Value to reverse
147   \return               Reversed value
148  */
149 #ifndef __NO_EMBEDDED_ASM
150 __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
151 {
152   rev16 r0, r0
153   bx lr
154 }
155 #endif
156
157 /**
158   \brief   Reverse byte order (16 bit)
159   \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
160   \param [in]    value  Value to reverse
161   \return               Reversed value
162  */
163 #ifndef __NO_EMBEDDED_ASM
164 __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
165 {
166   revsh r0, r0
167   bx lr
168 }
169 #endif
170
171 /**
172   \brief   Rotate Right in unsigned value (32 bit)
173   \param [in]    op1  Value to rotate
174   \param [in]    op2  Number of Bits to rotate
175   \return               Rotated value
176  */
177 #define __ROR                             __ror
178
179 /**
180   \brief   Breakpoint
181   \param [in]    value  is ignored by the processor.
182                  If required, a debugger can use it to store additional information about the breakpoint.
183  */
184 #define __BKPT(value)                     __breakpoint(value)
185
186 /**
187   \brief   Reverse bit order of value
188   \param [in]    value  Value to reverse
189   \return               Reversed value
190  */
191 #define __RBIT                            __rbit
192
193 /**
194   \brief   Count leading zeros
195   \param [in]  value  Value to count the leading zeros
196   \return             number of leading zeros in value
197  */
198 #define __CLZ                             __clz
199
200 /**
201   \brief   LDR Exclusive (8 bit)
202   \details Executes a exclusive LDR instruction for 8 bit value.
203   \param [in]    ptr  Pointer to data
204   \return             value of type uint8_t at (*ptr)
205  */
206 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
207   #define __LDREXB(ptr)                                                        ((uint8_t ) __ldrex(ptr))
208 #else
209   #define __LDREXB(ptr)          _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr))  _Pragma("pop")
210 #endif
211
212 /**
213   \brief   LDR Exclusive (16 bit)
214   \details Executes a exclusive LDR instruction for 16 bit values.
215   \param [in]    ptr  Pointer to data
216   \return        value of type uint16_t at (*ptr)
217  */
218 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
219   #define __LDREXH(ptr)                                                        ((uint16_t) __ldrex(ptr))
220 #else
221   #define __LDREXH(ptr)          _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr))  _Pragma("pop")
222 #endif
223
224 /**
225   \brief   LDR Exclusive (32 bit)
226   \details Executes a exclusive LDR instruction for 32 bit values.
227   \param [in]    ptr  Pointer to data
228   \return        value of type uint32_t at (*ptr)
229  */
230 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
231   #define __LDREXW(ptr)                                                        ((uint32_t ) __ldrex(ptr))
232 #else
233   #define __LDREXW(ptr)          _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr))  _Pragma("pop")
234 #endif
235
236 /**
237   \brief   STR Exclusive (8 bit)
238   \details Executes a exclusive STR instruction for 8 bit values.
239   \param [in]  value  Value to store
240   \param [in]    ptr  Pointer to location
241   \return          0  Function succeeded
242   \return          1  Function failed
243  */
244 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
245   #define __STREXB(value, ptr)                                                 __strex(value, ptr)
246 #else
247   #define __STREXB(value, ptr)   _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr)        _Pragma("pop")
248 #endif
249
250 /**
251   \brief   STR Exclusive (16 bit)
252   \details Executes a exclusive STR instruction for 16 bit values.
253   \param [in]  value  Value to store
254   \param [in]    ptr  Pointer to location
255   \return          0  Function succeeded
256   \return          1  Function failed
257  */
258 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
259   #define __STREXH(value, ptr)                                                 __strex(value, ptr)
260 #else
261   #define __STREXH(value, ptr)   _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr)        _Pragma("pop")
262 #endif
263
264 /**
265   \brief   STR Exclusive (32 bit)
266   \details Executes a exclusive STR instruction for 32 bit values.
267   \param [in]  value  Value to store
268   \param [in]    ptr  Pointer to location
269   \return          0  Function succeeded
270   \return          1  Function failed
271  */
272 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
273   #define __STREXW(value, ptr)                                                 __strex(value, ptr)
274 #else
275   #define __STREXW(value, ptr)   _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr)        _Pragma("pop")
276 #endif
277
278 /**
279   \brief   Remove the exclusive lock
280   \details Removes the exclusive lock which is created by LDREX.
281  */
282 #define __CLREX                           __clrex
283
284
285 /**
286   \brief   Signed Saturate
287   \details Saturates a signed value.
288   \param [in]  value  Value to be saturated
289   \param [in]    sat  Bit position to saturate to (1..32)
290   \return             Saturated value
291  */
292 #define __SSAT                            __ssat
293
294 /**
295   \brief   Unsigned Saturate
296   \details Saturates an unsigned value.
297   \param [in]  value  Value to be saturated
298   \param [in]    sat  Bit position to saturate to (0..31)
299   \return             Saturated value
300  */
301 #define __USAT                            __usat
302
303 /* ###########################  Core Function Access  ########################### */
304
305 /**
306   \brief   Get FPSCR (Floating Point Status/Control)
307   \return               Floating Point Status/Control register value
308  */
309 __STATIC_INLINE uint32_t __get_FPSCR(void)
310 {
311 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
312      (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
313   register uint32_t __regfpscr         __ASM("fpscr");
314   return(__regfpscr);
315 #else
316    return(0U);
317 #endif
318 }
319
320 /**
321   \brief   Set FPSCR (Floating Point Status/Control)
322   \param [in]    fpscr  Floating Point Status/Control value to set
323  */
324 __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
325 {
326 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
327      (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
328   register uint32_t __regfpscr         __ASM("fpscr");
329   __regfpscr = (fpscr);
330 #else
331   (void)fpscr;
332 #endif
333 }
334
335 /** \brief  Get CPSR (Current Program Status Register)
336     \return               CPSR Register value
337  */
338 __STATIC_INLINE uint32_t __get_CPSR(void)
339 {
340   register uint32_t __regCPSR          __ASM("cpsr");
341   return(__regCPSR);
342 }
343
344
345 /** \brief  Set CPSR (Current Program Status Register)
346     \param [in]    cpsr  CPSR value to set
347  */
348 __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
349 {
350   register uint32_t __regCPSR          __ASM("cpsr");
351   __regCPSR = cpsr;
352 }
353
354 /** \brief  Get Mode
355     \return                Processor Mode
356  */
357 __STATIC_INLINE uint32_t __get_mode(void)
358 {
359   return (__get_CPSR() & 0x1FU);
360 }
361
362 /** \brief  Set Mode
363     \param [in]    mode  Mode value to set
364  */
365 __STATIC_INLINE __ASM void __set_mode(uint32_t mode)
366 {
367   MOV  r1, lr
368   MSR  CPSR_C, r0
369   BX   r1
370 }
371
372 /** \brief  Get Stack Pointer
373     \return Stack Pointer
374  */
375 __STATIC_INLINE __ASM uint32_t __get_SP(void)
376 {
377   MOV  r0, sp
378   BX   lr
379 }
380
381 /** \brief  Set Stack Pointer 
382     \param [in]    stack  Stack Pointer value to set
383  */
384 __STATIC_INLINE __ASM void __set_SP(uint32_t stack)
385 {
386   MOV  sp, r0
387   BX   lr
388 }
389
390
391 /** \brief  Get USR/SYS Stack Pointer
392     \return USR/SYSStack Pointer
393  */
394 __STATIC_INLINE __ASM uint32_t __get_SP_usr(void)
395 {
396   ARM
397   PRESERVE8
398
399   MRS     R1, CPSR
400   CPS     #0x1F       ;no effect in USR mode
401   MOV     R0, SP
402   MSR     CPSR_c, R1  ;no effect in USR mode
403   ISB
404   BX      LR
405 }
406
407 /** \brief  Set USR/SYS Stack Pointer
408     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
409  */
410 __STATIC_INLINE __ASM void __set_SP_usr(uint32_t topOfProcStack)
411 {
412   ARM
413   PRESERVE8
414
415   MRS     R1, CPSR
416   CPS     #0x1F       ;no effect in USR mode
417   MOV     SP, R0
418   MSR     CPSR_c, R1  ;no effect in USR mode
419   ISB
420   BX      LR
421 }
422
423 /** \brief  Get FPEXC (Floating Point Exception Control Register)
424     \return               Floating Point Exception Control Register value
425  */
426 __STATIC_INLINE uint32_t __get_FPEXC(void)
427 {
428 #if (__FPU_PRESENT == 1)
429   register uint32_t __regfpexc         __ASM("fpexc");
430   return(__regfpexc);
431 #else
432   return(0);
433 #endif
434 }
435
436 /** \brief  Set FPEXC (Floating Point Exception Control Register)
437     \param [in]    fpexc  Floating Point Exception Control value to set
438  */
439 __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
440 {
441 #if (__FPU_PRESENT == 1)
442   register uint32_t __regfpexc         __ASM("fpexc");
443   __regfpexc = (fpexc);
444 #endif
445 }
446
447 /*
448  * Include common core functions to access Coprocessor 15 registers
449  */
450  
451 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) do { register uint32_t tmp __ASM("cp" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2); Rt = tmp; } while(0)
452 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) do { register uint32_t tmp __ASM("cp" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2); tmp = Rt; } while(0)
453 #define __get_CP64(cp, op1, Rt, CRm) \
454   do { \
455     uint32_t ltmp, htmp; \
456     __ASM volatile("MRRC p" # cp ", " # op1 ", ltmp, htmp, c" # CRm); \
457     Rt = (((uint64_t)htmp) << 32U) | ((uint64_t)ltmp); \
458   } while(0)
459
460 #define __set_CP64(cp, op1, Rt, CRm) \
461   do { \
462     const uint32_t ltmp = (uint32_t)Rt; \
463     const uint32_t htmp = (uint32_t)(Rt >> 32); \
464     __ASM volatile("MCRR p" # cp ", " # op1 ", ltmp, htmp, c" # CRm); \
465   } while(0)
466
467 #include "cmsis_cp15.h"
468
469 /** \brief  Clean and Invalidate the entire data or unified cache
470  * \param [in] op 0 - invalidate, 1 - clean, otherwise - invalidate and clean
471  */
472 __STATIC_INLINE __ASM void __L1C_CleanInvalidateCache(uint32_t op)
473 {
474         ARM
475
476         PUSH    {R4-R11}
477
478         MRC     p15, 1, R6, c0, c0, 1      // Read CLIDR
479         ANDS    R3, R6, #0x07000000        // Extract coherency level
480         MOV     R3, R3, LSR #23            // Total cache levels << 1
481         BEQ     Finished                   // If 0, no need to clean
482
483         MOV     R10, #0                    // R10 holds current cache level << 1
484 Loop1   ADD     R2, R10, R10, LSR #1       // R2 holds cache "Set" position
485         MOV     R1, R6, LSR R2             // Bottom 3 bits are the Cache-type for this level
486         AND     R1, R1, #7                 // Isolate those lower 3 bits
487         CMP     R1, #2
488         BLT     Skip                       // No cache or only instruction cache at this level
489
490         MCR     p15, 2, R10, c0, c0, 0     // Write the Cache Size selection register
491         ISB                                // ISB to sync the change to the CacheSizeID reg
492         MRC     p15, 1, R1, c0, c0, 0      // Reads current Cache Size ID register
493         AND     R2, R1, #7                 // Extract the line length field
494         ADD     R2, R2, #4                 // Add 4 for the line length offset (log2 16 bytes)
495         LDR     R4, =0x3FF
496         ANDS    R4, R4, R1, LSR #3         // R4 is the max number on the way size (right aligned)
497         CLZ     R5, R4                     // R5 is the bit position of the way size increment
498         LDR     R7, =0x7FFF
499         ANDS    R7, R7, R1, LSR #13        // R7 is the max number of the index size (right aligned)
500
501 Loop2   MOV     R9, R4                     // R9 working copy of the max way size (right aligned)
502
503 Loop3   ORR     R11, R10, R9, LSL R5       // Factor in the Way number and cache number into R11
504         ORR     R11, R11, R7, LSL R2       // Factor in the Set number
505         CMP     R0, #0
506         BNE     Dccsw
507         MCR     p15, 0, R11, c7, c6, 2     // DCISW. Invalidate by Set/Way
508         B       cont
509 Dccsw   CMP     R0, #1
510         BNE     Dccisw
511         MCR     p15, 0, R11, c7, c10, 2    // DCCSW. Clean by Set/Way
512         B       cont
513 Dccisw  MCR     p15, 0, R11, c7, c14, 2    // DCCISW. Clean and Invalidate by Set/Way
514 cont    SUBS    R9, R9, #1                 // Decrement the Way number
515         BGE     Loop3
516         SUBS    R7, R7, #1                 // Decrement the Set number
517         BGE     Loop2
518 Skip    ADD     R10, R10, #2               // Increment the cache number
519         CMP     R3, R10
520         BGT     Loop1
521
522 Finished
523         DSB
524         POP    {R4-R11}
525         BX     lr
526 }
527
528 /** \brief  Enable Floating Point Unit
529
530   Critical section, called from undef handler, so systick is disabled
531  */
532 __STATIC_INLINE __ASM void __FPU_Enable(void)
533 {
534         ARM
535
536         //Permit access to VFP/NEON, registers by modifying CPACR
537         MRC     p15,0,R1,c1,c0,2
538         ORR     R1,R1,#0x00F00000
539         MCR     p15,0,R1,c1,c0,2
540
541         //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
542         ISB
543
544         //Enable VFP/NEON
545         VMRS    R1,FPEXC
546         ORR     R1,R1,#0x40000000
547         VMSR    FPEXC,R1
548
549         //Initialise VFP/NEON registers to 0
550         MOV     R2,#0
551   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16
552         //Initialise D16 registers to 0
553         VMOV    D0, R2,R2
554         VMOV    D1, R2,R2
555         VMOV    D2, R2,R2
556         VMOV    D3, R2,R2
557         VMOV    D4, R2,R2
558         VMOV    D5, R2,R2
559         VMOV    D6, R2,R2
560         VMOV    D7, R2,R2
561         VMOV    D8, R2,R2
562         VMOV    D9, R2,R2
563         VMOV    D10,R2,R2
564         VMOV    D11,R2,R2
565         VMOV    D12,R2,R2
566         VMOV    D13,R2,R2
567         VMOV    D14,R2,R2
568         VMOV    D15,R2,R2
569   ENDIF
570   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
571         //Initialise D32 registers to 0
572         VMOV    D16,R2,R2
573         VMOV    D17,R2,R2
574         VMOV    D18,R2,R2
575         VMOV    D19,R2,R2
576         VMOV    D20,R2,R2
577         VMOV    D21,R2,R2
578         VMOV    D22,R2,R2
579         VMOV    D23,R2,R2
580         VMOV    D24,R2,R2
581         VMOV    D25,R2,R2
582         VMOV    D26,R2,R2
583         VMOV    D27,R2,R2
584         VMOV    D28,R2,R2
585         VMOV    D29,R2,R2
586         VMOV    D30,R2,R2
587         VMOV    D31,R2,R2
588   ENDIF
589
590         //Initialise FPSCR to a known state
591         VMRS    R2,FPSCR
592         LDR     R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
593         AND     R2,R2,R3
594         VMSR    FPSCR,R2
595
596         BX      LR
597 }
598
599 #endif /* __CMSIS_ARMCC_H */