]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_gcc.h
CMSIS-Core(M): Prefixed all MPU functions with ARM_ to prevent name clashes with...
[cmsis] / CMSIS / Core_A / Include / cmsis_gcc.h
1 /**************************************************************************//**
2  * @file     cmsis_gcc.h
3  * @brief    CMSIS compiler specific macros, functions, instructions
4  * @version  V1.00
5  * @date     06. Jul 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_GCC_H
26 #define __CMSIS_GCC_H
27
28 /* ignore some GCC warnings */
29 #pragma GCC diagnostic push
30 #pragma GCC diagnostic ignored "-Wsign-conversion"
31 #pragma GCC diagnostic ignored "-Wconversion"
32 #pragma GCC diagnostic ignored "-Wunused-parameter"
33
34 /* Fallback for __has_builtin */
35 #ifndef __has_builtin
36   #define __has_builtin(x) (0)
37 #endif
38
39 /* CMSIS compiler specific defines */
40 #ifndef   __ASM
41   #define __ASM                                  asm
42 #endif
43 #ifndef   __INLINE
44   #define __INLINE                               inline
45 #endif
46 #ifndef   __STATIC_INLINE
47   #define __STATIC_INLINE                        static inline
48 #endif
49 #ifndef   __NO_RETURN
50   #define __NO_RETURN                            __attribute__((noreturn))
51 #endif
52 #ifndef   __USED
53   #define __USED                                 __attribute__((used))
54 #endif
55 #ifndef   __WEAK
56   #define __WEAK                                 __attribute__((weak))
57 #endif
58 #ifndef   __PACKED
59   #define __PACKED                               __attribute__((packed, aligned(1)))
60 #endif
61 #ifndef   __PACKED_STRUCT
62   #define __PACKED_STRUCT                        struct __attribute__((packed, aligned(1)))
63 #endif
64 #ifndef   __UNALIGNED_UINT16_WRITE
65   #pragma GCC diagnostic push
66   #pragma GCC diagnostic ignored "-Wpacked"
67 /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
68   __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
69   #pragma GCC diagnostic pop
70   #define __UNALIGNED_UINT16_WRITE(addr, val)    (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
71 #endif
72 #ifndef   __UNALIGNED_UINT16_READ
73   #pragma GCC diagnostic push
74   #pragma GCC diagnostic ignored "-Wpacked"
75 /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
76   __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
77   #pragma GCC diagnostic pop
78   #define __UNALIGNED_UINT16_READ(addr)          (((const struct T_UINT16_READ *)(const void *)(addr))->v)
79 #endif
80 #ifndef   __UNALIGNED_UINT32_WRITE
81   #pragma GCC diagnostic push
82   #pragma GCC diagnostic ignored "-Wpacked"
83 /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
84   __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
85   #pragma GCC diagnostic pop
86   #define __UNALIGNED_UINT32_WRITE(addr, val)    (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
87 #endif
88 #ifndef   __UNALIGNED_UINT32_READ
89   #pragma GCC diagnostic push
90   #pragma GCC diagnostic ignored "-Wpacked"
91   __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
92   #pragma GCC diagnostic pop
93   #define __UNALIGNED_UINT32_READ(addr)          (((const struct T_UINT32_READ *)(const void *)(addr))->v)
94 #endif
95 #ifndef   __ALIGNED
96   #define __ALIGNED(x)                           __attribute__((aligned(x)))
97 #endif
98
99
100 /* ###########################  Core Function Access  ########################### */
101
102 /**
103   \brief   Get FPSCR
104   \details Returns the current value of the Floating Point Status/Control register.
105   \return Floating Point Status/Control register value
106 */
107 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void)
108 {
109   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
110        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
111   #if __has_builtin(__builtin_arm_get_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
112     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
113     return __builtin_arm_get_fpscr();
114   #else
115     uint32_t result;
116
117     __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
118     return(result);
119   #endif
120   #else
121     return(0U);
122   #endif
123 }
124
125
126 /**
127   \brief   Set FPSCR
128   \details Assigns the given value to the Floating Point Status/Control register.
129   \param [in] fpscr  Floating Point Status/Control value to set
130 */
131 __attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
132 {
133   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
134        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
135   #if __has_builtin(__builtin_arm_set_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
136     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
137     __builtin_arm_set_fpscr(fpscr);
138   #else
139     __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
140   #endif
141   #else
142     (void)fpscr;
143   #endif
144 }
145
146 /* ##########################  Core Instruction Access  ######################### */
147 /**
148   \brief   No Operation
149  */
150 #define __NOP                             __builtin_arm_nop
151
152 /**
153   \brief   Wait For Interrupt
154  */
155 #define __WFI                             __builtin_arm_wfi
156
157 /**
158   \brief   Wait For Event
159  */
160 #define __WFE                             __builtin_arm_wfe
161
162 /**
163   \brief   Send Event
164  */
165 #define __SEV                             __builtin_arm_sev
166
167 /**
168   \brief   Instruction Synchronization Barrier
169   \details Instruction Synchronization Barrier flushes the pipeline in the processor,
170            so that all instructions following the ISB are fetched from cache or memory,
171            after the instruction has been completed.
172  */
173 __attribute__((always_inline)) __STATIC_INLINE void __ISB(void)
174 {
175   __ASM volatile ("isb 0xF":::"memory");
176 }
177
178
179 /**
180   \brief   Data Synchronization Barrier
181   \details Acts as a special kind of Data Memory Barrier.
182            It completes when all explicit memory accesses before this instruction complete.
183  */
184 __attribute__((always_inline)) __STATIC_INLINE void __DSB(void)
185 {
186   __ASM volatile ("dsb 0xF":::"memory");
187 }
188
189 /**
190   \brief   Data Memory Barrier
191   \details Ensures the apparent order of the explicit memory operations before
192            and after the instruction, without ensuring their completion.
193  */
194 __attribute__((always_inline)) __STATIC_INLINE void __DMB(void)
195 {
196   __ASM volatile ("dmb 0xF":::"memory");
197 }
198
199 /**
200   \brief   Reverse byte order (32 bit)
201   \details Reverses the byte order in integer value.
202   \param [in]    value  Value to reverse
203   \return               Reversed value
204  */
205 __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value)
206 {
207 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
208   return __builtin_bswap32(value);
209 #else
210   uint32_t result;
211
212   __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
213   return(result);
214 #endif
215 }
216
217 /**
218   \brief   Reverse byte order (16 bit)
219   \param [in]    value  Value to reverse
220   \return               Reversed value
221  */
222 #ifndef __NO_EMBEDDED_ASM
223 __attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
224 {
225   uint32_t result;
226   __ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
227   return result;
228 }
229 #endif
230
231 /**
232   \brief   Reverse byte order in signed short value
233   \details Reverses the byte order in a signed short value with sign extension to integer.
234   \param [in]    value  Value to reverse
235   \return               Reversed value
236  */
237 __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value)
238 {
239 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
240   return (short)__builtin_bswap16(value);
241 #else
242   int32_t result;
243
244   __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
245   return(result);
246 #endif
247 }
248
249 /**
250   \brief   Rotate Right in unsigned value (32 bit)
251   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
252   \param [in]    op1  Value to rotate
253   \param [in]    op2  Number of Bits to rotate
254   \return               Rotated value
255  */
256 __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
257 {
258   return (op1 >> op2) | (op1 << (32U - op2));
259 }
260
261 /**
262   \brief   Breakpoint
263   \param [in]    value  is ignored by the processor.
264                  If required, a debugger can use it to store additional information about the breakpoint.
265  */
266 #define __BKPT(value)                       __ASM volatile ("bkpt "#value)
267
268 /**
269   \brief   Reverse bit order of value
270   \details Reverses the bit order of the given value.
271   \param [in]    value  Value to reverse
272   \return               Reversed value
273  */
274 __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
275 {
276   uint32_t result;
277
278 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
279      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
280      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
281    __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
282 #else
283   int32_t s = (4 /*sizeof(v)*/ * 8) - 1; /* extra shift needed at end */
284
285   result = value;                      /* r will be reversed bits of v; first get LSB of v */
286   for (value >>= 1U; value; value >>= 1U)
287   {
288     result <<= 1U;
289     result |= value & 1U;
290     s--;
291   }
292   result <<= s;                        /* shift when v's highest bits are zero */
293 #endif
294   return(result);
295 }
296
297 /**
298   \brief   Count leading zeros
299   \param [in]  value  Value to count the leading zeros
300   \return             number of leading zeros in value
301  */
302 #define __CLZ                             __builtin_clz
303
304 /**
305   \brief   LDR Exclusive (8 bit)
306   \details Executes a exclusive LDR instruction for 8 bit value.
307   \param [in]    ptr  Pointer to data
308   \return             value of type uint8_t at (*ptr)
309  */
310 __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
311 {
312     uint32_t result;
313
314 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
315    __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
316 #else
317     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
318        accepted by assembler. So has to use following less efficient pattern.
319     */
320    __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
321 #endif
322    return ((uint8_t) result);    /* Add explicit type cast here */
323 }
324
325
326 /**
327   \brief   LDR Exclusive (16 bit)
328   \details Executes a exclusive LDR instruction for 16 bit values.
329   \param [in]    ptr  Pointer to data
330   \return        value of type uint16_t at (*ptr)
331  */
332 __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
333 {
334     uint32_t result;
335
336 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
337    __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
338 #else
339     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
340        accepted by assembler. So has to use following less efficient pattern.
341     */
342    __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
343 #endif
344    return ((uint16_t) result);    /* Add explicit type cast here */
345 }
346
347
348 /**
349   \brief   LDR Exclusive (32 bit)
350   \details Executes a exclusive LDR instruction for 32 bit values.
351   \param [in]    ptr  Pointer to data
352   \return        value of type uint32_t at (*ptr)
353  */
354 __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
355 {
356     uint32_t result;
357
358    __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
359    return(result);
360 }
361
362
363 /**
364   \brief   STR Exclusive (8 bit)
365   \details Executes a exclusive STR instruction for 8 bit values.
366   \param [in]  value  Value to store
367   \param [in]    ptr  Pointer to location
368   \return          0  Function succeeded
369   \return          1  Function failed
370  */
371 __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
372 {
373    uint32_t result;
374
375    __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
376    return(result);
377 }
378
379
380 /**
381   \brief   STR Exclusive (16 bit)
382   \details Executes a exclusive STR instruction for 16 bit values.
383   \param [in]  value  Value to store
384   \param [in]    ptr  Pointer to location
385   \return          0  Function succeeded
386   \return          1  Function failed
387  */
388 __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
389 {
390    uint32_t result;
391
392    __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
393    return(result);
394 }
395
396
397 /**
398   \brief   STR Exclusive (32 bit)
399   \details Executes a exclusive STR instruction for 32 bit values.
400   \param [in]  value  Value to store
401   \param [in]    ptr  Pointer to location
402   \return          0  Function succeeded
403   \return          1  Function failed
404  */
405 __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
406 {
407    uint32_t result;
408
409    __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
410    return(result);
411 }
412
413
414 /**
415   \brief   Remove the exclusive lock
416   \details Removes the exclusive lock which is created by LDREX.
417  */
418 __attribute__((always_inline)) __STATIC_INLINE void __CLREX(void)
419 {
420   __ASM volatile ("clrex" ::: "memory");
421 }
422
423 /** \brief  Get CPSR Register
424     \return               CPSR Register value
425  */
426 __STATIC_INLINE uint32_t __get_CPSR(void)
427 {
428   uint32_t result;
429   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
430   return(result);
431 }
432
433 /** \brief  Set CPSR Register
434     \param [in]    cpsr  CPSR value to set
435  */
436 __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
437 {
438 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
439 }
440
441 /** \brief  Get Mode
442     \return                Processor Mode
443  */
444 __STATIC_INLINE uint32_t __get_mode(void) {
445     return (__get_CPSR() & 0x1FU);
446 }
447
448 /** \brief  Set Mode
449     \param [in]    mode  Mode value to set
450  */
451 __STATIC_INLINE void __set_mode(uint32_t mode) {
452   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
453 }
454
455 /** \brief  Set Stack Pointer
456     \param [in]    stack  Stack Pointer value to set
457  */
458 __STATIC_INLINE void __set_SP(uint32_t stack)
459 {
460   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
461 }
462
463 /** \brief  Set USR/SYS Stack Pointer
464     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
465  */
466 __STATIC_INLINE void __set_SP_usr(uint32_t topOfProcStack)
467 {
468   __ASM volatile(
469     ".preserve8         \n"
470     "BIC     r0, r0, #7 \n" // ensure stack is 8-byte aligned
471     "MRS     r1, cpsr   \n"
472     "CPS     #0x1F      \n" // no effect in USR mode
473     "MOV     sp, r0     \n"
474     "MSR     cpsr_c, r1 \n" // no effect in USR mode
475     "ISB"
476    );
477 }
478
479 /** \brief  Get FPEXC
480     \return               Floating Point Exception Control register value
481  */
482 __STATIC_INLINE uint32_t __get_FPEXC(void)
483 {
484 #if (__FPU_PRESENT == 1)
485   uint32_t result;
486   __ASM volatile("MRS %0, fpexc" : "=r" (result) );
487   return(result);
488 #else
489   return(0);
490 #endif
491 }
492
493 /** \brief  Set FPEXC
494     \param [in]    fpexc  Floating Point Exception Control value to set
495  */
496 __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
497 {
498 #if (__FPU_PRESENT == 1)
499   __ASM volatile ("MSR fpexc, %0" : : "r" (fpexc) : "memory");
500 #endif
501 }
502
503 /** \brief  Get ACTLR
504     \return               Auxiliary Control register value
505  */
506 __STATIC_INLINE uint32_t __get_ACTLR(void)
507 {
508   uint32_t result;
509   __ASM volatile("MRS %0, actlr" : "=r" (result) );
510   return(result);
511 }
512
513 /** \brief  Set ACTLR
514     \param [in]    actlr  Auxiliary Control value to set
515  */
516 __STATIC_INLINE void __set_ACTLR(uint32_t actlr)
517 {
518   __ASM volatile ("MSR fpexc, %0" : : "r" (actlr) : "memory");
519 }
520 /** \brief  Get CPACR
521     \return               Coprocessor Access Control register value
522  */
523 __STATIC_INLINE uint32_t __get_CPACR(void)
524 {
525   uint32_t result;
526   __ASM volatile("MRC p15, 0, %0, c1, c0, 2" : "=r"(result));
527   return result;
528 }
529
530 /** \brief  Set CPACR
531     \param [in]    cpacr  Coprocessor Access Control value to set
532  */
533 __STATIC_INLINE void __set_CPACR(uint32_t cpacr)
534 {
535   __ASM volatile("MCR p15, 0, %0, c1, c0, 2" : : "r"(cpacr) : "memory");
536 }
537
538 /** \brief  Get CBAR
539     \return               Configuration Base Address register value
540  */
541 __STATIC_INLINE uint32_t __get_CBAR() {
542   uint32_t result;
543   __ASM volatile("MRC p15, 4, %0, c15, c0, 0" : "=r"(result));
544   return result;
545 }
546
547 /** \brief  Get TTBR0
548
549     This function returns the value of the Translation Table Base Register 0.
550
551     \return               Translation Table Base Register 0 value
552  */
553 __STATIC_INLINE uint32_t __get_TTBR0() {
554   uint32_t result;
555   __ASM volatile("MRC p15, 0, %0, c2, c0, 0" : "=r"(result));
556   return result;
557 }
558
559 /** \brief  Set TTBR0
560
561     This function assigns the given value to the Translation Table Base Register 0.
562
563     \param [in]    ttbr0  Translation Table Base Register 0 value to set
564  */
565 __STATIC_INLINE void __set_TTBR0(uint32_t ttbr0) {
566   __ASM volatile("MCR p15, 0, %0, c2, c0, 0" : : "r"(ttbr0) : "memory");
567 }
568
569 /** \brief  Get DACR
570
571     This function returns the value of the Domain Access Control Register.
572
573     \return               Domain Access Control Register value
574  */
575 __STATIC_INLINE uint32_t __get_DACR() {
576   uint32_t result;
577   __ASM volatile("MRC p15, 0, %0, c3, c0, 0" : "=r"(result));
578   return result;
579 }
580
581 /** \brief  Set DACR
582
583     This function assigns the given value to the Domain Access Control Register.
584
585     \param [in]    dacr   Domain Access Control Register value to set
586  */
587 __STATIC_INLINE void __set_DACR(uint32_t dacr) {
588   __ASM volatile("MCR p15, 0, %0, c3, c0, 0" : : "r"(dacr) : "memory");
589 }
590
591 /** \brief  Set SCTLR
592
593     This function assigns the given value to the System Control Register.
594
595     \param [in]    sctlr  System Control Register value to set
596  */
597 __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
598 {
599   __ASM volatile("MCR p15, 0, %0, c1, c0, 0" : : "r"(sctlr) : "memory");
600 }
601
602 /** \brief  Get SCTLR
603     \return               System Control Register value
604  */
605 __STATIC_INLINE uint32_t __get_SCTLR() {
606   uint32_t result;
607   __ASM volatile("MRC p15, 0, %0, c1, c0, 0" : "=r"(result));
608   return result;
609 }
610
611 /** \brief  Set ACTRL
612     \param [in]    actrl  Auxiliary Control Register value to set
613  */
614 __STATIC_INLINE void __set_ACTRL(uint32_t actrl)
615 {
616   __ASM volatile("MCR p15, 0, %0, c1, c0, 1" : : "r"(actrl) : "memory");
617 }
618
619 /** \brief  Get ACTRL
620     \return               Auxiliary Control Register value
621  */
622 __STATIC_INLINE uint32_t __get_ACTRL(void)
623 {
624   uint32_t result;
625   __ASM volatile("MRC p15, 0, %0, c1, c0, 1" : "=r"(result));
626   return result;
627 }
628
629 /** \brief  Get MPIDR
630
631     This function returns the value of the Multiprocessor Affinity Register.
632
633     \return               Multiprocessor Affinity Register value
634  */
635 __STATIC_INLINE uint32_t __get_MPIDR(void)
636 {
637   uint32_t result;
638   __ASM volatile("MRC p15, 0, %0, c0, c0, 5" : "=r"(result));
639   return result;
640 }
641
642  /** \brief  Get VBAR
643
644     This function returns the value of the Vector Base Address Register.
645
646     \return               Vector Base Address Register
647  */
648 __STATIC_INLINE uint32_t __get_VBAR(void)
649 {
650   uint32_t result;
651   __ASM volatile("MRC p15, 0, %0, c12, c0, 0" : "=r"(result));
652   return result;
653 }
654
655 /** \brief  Set VBAR
656
657     This function assigns the given value to the Vector Base Address Register.
658
659     \param [in]    vbar  Vector Base Address Register value to set
660  */
661 __STATIC_INLINE void __set_VBAR(uint32_t vbar)
662 {
663   __ASM volatile("MCR p15, 0, %0, c12, c0, 1" : : "r"(vbar) : "memory");
664 }
665
666 /** \brief  Set CNTFRQ
667
668   This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ).
669
670   \param [in]    value  CNTFRQ Register value to set
671 */
672 __STATIC_INLINE void __set_CNTFRQ(uint32_t value) {
673   __ASM volatile("MCR p15, 0, %0, c14, c0, 0" : : "r"(value) : "memory");
674 }
675
676 /** \brief  Set CNTP_TVAL
677
678   This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
679
680   \param [in]    value  CNTP_TVAL Register value to set
681 */
682 __STATIC_INLINE void __set_CNTP_TVAL(uint32_t value) {
683   __ASM volatile("MCR p15, 0, %0, c14, c2, 0" : : "r"(value) : "memory");
684 }
685
686 /** \brief  Get CNTP_TVAL
687
688     This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
689
690     \return               CNTP_TVAL Register value
691  */
692 __STATIC_INLINE uint32_t __get_CNTP_TVAL() {
693   uint32_t result;
694   __ASM volatile("MRC p15, 0, %0, c14, c2, 0" : "=r"(result));
695   return result;
696 }
697
698 /** \brief  Set CNTP_CTL
699
700   This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
701
702   \param [in]    value  CNTP_CTL Register value to set
703 */
704 __STATIC_INLINE void __set_CNTP_CTL(uint32_t value) {
705   __ASM volatile("MCR p15, 0, %0, c14, c2, 1" : : "r"(value) : "memory");
706 }
707
708 /** \brief  Get CNTP_CTL register
709     \return               CNTP_CTL Register value
710  */
711 __STATIC_INLINE uint32_t __get_CNTP_CTL() {
712   uint32_t result;
713   __ASM volatile("MRC p15, 0, %0, c14, c2, 1" : "=r"(result));
714   return result;
715 }
716
717 /** \brief  Set TLBIALL
718
719   TLB Invalidate All
720  */
721 __STATIC_INLINE void __set_TLBIALL(uint32_t value) {
722   __ASM volatile("MCR p15, 0, %0, c8, c7, 0" : : "r"(value) : "memory");
723 }
724
725 /** \brief  Set BPIALL.
726
727   Branch Predictor Invalidate All
728  */
729 __STATIC_INLINE void __set_BPIALL(uint32_t value) {
730   __ASM volatile("MCR p15, 0, %0, c7, c5, 6" : : "r"(value) : "memory");
731 }
732
733 /** \brief  Set ICIALLU
734
735   Instruction Cache Invalidate All
736  */
737 __STATIC_INLINE void __set_ICIALLU(uint32_t value) {
738   __ASM volatile("MCR p15, 0, %0, c7, c5, 0" : : "r"(value) : "memory");
739 }
740
741 /** \brief  Set DCCMVAC
742
743   Data cache clean
744  */
745 __STATIC_INLINE void __set_DCCMVAC(uint32_t value) {
746   __ASM volatile("MCR p15, 0, %0, c7, c10, 1" : : "r"(value) : "memory");
747 }
748
749 /** \brief  Set DCIMVAC
750
751   Data cache invalidate
752  */
753 __STATIC_INLINE void __set_DCIMVAC(uint32_t value) {
754   __ASM volatile("MCR p15, 0, %0, c7, c6, 1" : : "r"(value) : "memory");
755 }
756
757 /** \brief  Set DCCIMVAC
758
759   Data cache clean and invalidate
760  */
761 __STATIC_INLINE void __set_DCCIMVAC(uint32_t value) {
762   __ASM volatile("MCR p15, 0, %0, c7, c14, 1" : : "r"(value) : "memory");
763 }
764
765
766 /** \brief  Set CCSIDR
767  */
768 __STATIC_INLINE void __set_CCSIDR(uint32_t value) {
769   __ASM volatile("MCR p15, 2, %0, c0, c0, 0" : : "r"(value) : "memory");
770 }
771
772 /** \brief  Get CCSIDR
773     \return CCSIDR Register value
774  */
775 __STATIC_INLINE uint32_t __get_CCSIDR() {
776   uint32_t result;
777   __ASM volatile("MRC p15, 1, %0, c0, c0, 0" : "=r"(result));
778   return result;
779 }
780
781 /** \brief  Get CLIDR
782     \return CLIDR Register value
783  */
784 __STATIC_INLINE uint32_t __get_CLIDR() {
785   uint32_t result;
786   __ASM volatile("MRC p15, 1, %0, c0, c0, 1" : "=r"(result));
787   return result;
788 }
789
790 __STATIC_INLINE int32_t log2_up(uint32_t n)
791 {
792   int32_t log = -1;
793   uint32_t t = n;
794   while(t)
795   {
796     log++; t >>=1;
797   }
798   /* if n not power of 2 -> round up*/
799   if ( n & (n - 1) ) log++;
800   return log;
801 }
802
803 __STATIC_INLINE void __L1C_MaintainDCacheSetWay(uint32_t level, uint32_t maint)
804 {
805   register volatile uint32_t Dummy;
806   register volatile uint32_t ccsidr;
807   uint32_t num_sets;
808   uint32_t num_ways;
809   uint32_t shift_way;
810   uint32_t log2_linesize;
811   uint32_t log2_num_ways;
812
813   Dummy = level << 1;
814   /* set csselr, select ccsidr register */
815   __set_CCSIDR(Dummy);
816   /* get current ccsidr register */
817   ccsidr = __get_CCSIDR();
818   num_sets = ((ccsidr & 0x0FFFE000) >> 13) + 1;
819   num_ways = ((ccsidr & 0x00001FF8) >> 3) + 1;
820   log2_linesize = (ccsidr & 0x00000007) + 2 + 2;
821   log2_num_ways = log2_up(num_ways);
822   shift_way = 32 - log2_num_ways;
823   for(int way = num_ways-1; way >= 0; way--) {
824     for(int set = num_sets-1; set >= 0; set--) {
825       Dummy = (level << 1) | (set << log2_linesize) | (way << shift_way);
826       switch (maint)
827       {
828         case 0:
829           __ASM volatile("MCR p15, 0, %0, c7, c6, 2" : : "r"(Dummy) : "memory"); // DCISW. Invalidate by Set/Way
830           break;
831
832         case 1:
833           __ASM volatile("MCR p15, 0, %0, c7, c10, 2" : : "r"(Dummy) : "memory"); // DCCSW. Clean by Set/Way
834           break;
835
836         default:
837           __ASM volatile("MCR p15, 0, %0, c7, c14, 2" : : "r"(Dummy) : "memory"); // DCCISW. Clean and Invalidate by Set/Way
838           break;
839
840       }
841     }
842   }
843   __DMB();
844 }
845
846 /** \brief  Clean and Invalidate the entire data or unified cache
847
848   Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
849  */
850 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op) {
851   register volatile uint32_t clidr;
852   uint32_t cache_type;
853   clidr =  __get_CLIDR();
854   for(uint32_t i = 0; i<7; i++)
855   {
856     cache_type = (clidr >> i*3) & 0x7UL;
857     if ((cache_type >= 2) && (cache_type <= 4))
858     {
859       __L1C_MaintainDCacheSetWay(i, op);
860     }
861   }
862
863 }
864
865 /** \brief  Enable Floating Point Unit
866
867   Critical section, called from undef handler, so systick is disabled
868  */
869 __STATIC_INLINE void __FPU_Enable(void) {
870   __ASM volatile(
871         //Permit access to VFP/NEON, registers by modifying CPACR
872     "        MRC     p15,0,R1,c1,c0,2  \n"
873     "        ORR     R1,R1,#0x00F00000 \n"
874     "        MCR     p15,0,R1,c1,c0,2  \n"
875
876         //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
877     "        ISB                       \n"
878
879         //Enable VFP/NEON
880     "        VMRS    R1,FPEXC          \n"
881     "        ORR     R1,R1,#0x40000000 \n"
882     "        VMSR    FPEXC,R1          \n"
883
884         //Initialise VFP/NEON registers to 0
885     "        MOV     R2,#0             \n"
886
887 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT >= 16
888         //Initialise D16 registers to 0
889     "        VMOV    D0, R2,R2         \n"
890     "        VMOV    D1, R2,R2         \n"
891     "        VMOV    D2, R2,R2         \n"
892     "        VMOV    D3, R2,R2         \n"
893     "        VMOV    D4, R2,R2         \n"
894     "        VMOV    D5, R2,R2         \n"
895     "        VMOV    D6, R2,R2         \n"
896     "        VMOV    D7, R2,R2         \n"
897     "        VMOV    D8, R2,R2         \n"
898     "        VMOV    D9, R2,R2         \n"
899     "        VMOV    D10,R2,R2         \n"
900     "        VMOV    D11,R2,R2         \n"
901     "        VMOV    D12,R2,R2         \n"
902     "        VMOV    D13,R2,R2         \n"
903     "        VMOV    D14,R2,R2         \n"
904     "        VMOV    D15,R2,R2         \n"
905 #endif
906
907 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
908         //Initialise D32 registers to 0
909     "        VMOV    D16,R2,R2         \n"
910     "        VMOV    D17,R2,R2         \n"
911     "        VMOV    D18,R2,R2         \n"
912     "        VMOV    D19,R2,R2         \n"
913     "        VMOV    D20,R2,R2         \n"
914     "        VMOV    D21,R2,R2         \n"
915     "        VMOV    D22,R2,R2         \n"
916     "        VMOV    D23,R2,R2         \n"
917     "        VMOV    D24,R2,R2         \n"
918     "        VMOV    D25,R2,R2         \n"
919     "        VMOV    D26,R2,R2         \n"
920     "        VMOV    D27,R2,R2         \n"
921     "        VMOV    D28,R2,R2         \n"
922     "        VMOV    D29,R2,R2         \n"
923     "        VMOV    D30,R2,R2         \n"
924     "        VMOV    D31,R2,R2         \n"
925 #endif
926   );
927
928   // Initialise FPSCR to a known state
929   // Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
930   __set_FPSCR(__get_FPSCR() & 0x00086060u);
931 }
932
933 #pragma GCC diagnostic pop
934
935 #endif /* __CMSIS_GCC_H */