1 /**************************************************************************//**
3 * @brief CMSIS compiler specific macros, functions, instructions
6 ******************************************************************************/
8 * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
10 * SPDX-License-Identifier: Apache-2.0
12 * Licensed under the Apache License, Version 2.0 (the License); you may
13 * not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
16 * www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
25 #ifndef __CMSIS_ARMCC_H
26 #define __CMSIS_ARMCC_H
28 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
29 #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
32 /* CMSIS compiler control architecture macros */
33 #if (defined (__TARGET_ARCH_7_A ) && (__TARGET_ARCH_7_A == 1))
34 #define __ARM_ARCH_7A__ 1
37 /* CMSIS compiler specific defines */
42 #define __INLINE __inline
44 #ifndef __STATIC_INLINE
45 #define __STATIC_INLINE static __inline
48 #define __NO_RETURN __declspec(noreturn)
51 #define __USED __attribute__((used))
54 #define __WEAK __attribute__((weak))
57 #define __PACKED __attribute__((packed))
59 #ifndef __PACKED_STRUCT
60 #define __PACKED_STRUCT __packed struct
62 #ifndef __UNALIGNED_UINT16_WRITE
63 #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
65 #ifndef __UNALIGNED_UINT16_READ
66 #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
68 #ifndef __UNALIGNED_UINT32_WRITE
69 #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
71 #ifndef __UNALIGNED_UINT32_READ
72 #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
75 #define __ALIGNED(x) __attribute__((aligned(x)))
78 #define __PACKED __attribute__((packed))
82 /* ########################### Core Function Access ########################### */
85 \brief Get FPSCR (Floating Point Status/Control)
86 \return Floating Point Status/Control register value
88 __STATIC_INLINE uint32_t __get_FPSCR(void)
90 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
91 (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
92 register uint32_t __regfpscr __ASM("fpscr");
100 \brief Set FPSCR (Floating Point Status/Control)
101 \param [in] fpscr Floating Point Status/Control value to set
103 __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
105 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
106 (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
107 register uint32_t __regfpscr __ASM("fpscr");
108 __regfpscr = (fpscr);
114 /* ########################## Core Instruction Access ######################### */
121 \brief Wait For Interrupt
126 \brief Wait For Event
136 \brief Instruction Synchronization Barrier
138 #define __ISB() do {\
139 __schedule_barrier();\
141 __schedule_barrier();\
145 \brief Data Synchronization Barrier
147 #define __DSB() do {\
148 __schedule_barrier();\
150 __schedule_barrier();\
154 \brief Data Memory Barrier
156 #define __DMB() do {\
157 __schedule_barrier();\
159 __schedule_barrier();\
163 \brief Reverse byte order (32 bit)
164 \param [in] value Value to reverse
165 \return Reversed value
170 \brief Reverse byte order (16 bit)
171 \param [in] value Value to reverse
172 \return Reversed value
174 #ifndef __NO_EMBEDDED_ASM
175 __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
183 \brief Reverse byte order in signed short value
184 \param [in] value Value to reverse
185 \return Reversed value
187 #ifndef __NO_EMBEDDED_ASM
188 __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
196 \brief Rotate Right in unsigned value (32 bit)
197 \param [in] op1 Value to rotate
198 \param [in] op2 Number of Bits to rotate
199 \return Rotated value
205 \param [in] value is ignored by the processor.
206 If required, a debugger can use it to store additional information about the breakpoint.
208 #define __BKPT(value) __breakpoint(value)
211 \brief Reverse bit order of value
212 \param [in] value Value to reverse
213 \return Reversed value
215 #define __RBIT __rbit
218 \brief Count leading zeros
219 \param [in] value Value to count the leading zeros
220 \return number of leading zeros in value
225 \brief LDR Exclusive (8 bit)
226 \details Executes a exclusive LDR instruction for 8 bit value.
227 \param [in] ptr Pointer to data
228 \return value of type uint8_t at (*ptr)
230 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
231 #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
233 #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
237 \brief LDR Exclusive (16 bit)
238 \details Executes a exclusive LDR instruction for 16 bit values.
239 \param [in] ptr Pointer to data
240 \return value of type uint16_t at (*ptr)
242 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
243 #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
245 #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
249 \brief LDR Exclusive (32 bit)
250 \details Executes a exclusive LDR instruction for 32 bit values.
251 \param [in] ptr Pointer to data
252 \return value of type uint32_t at (*ptr)
254 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
255 #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
257 #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
261 \brief STR Exclusive (8 bit)
262 \details Executes a exclusive STR instruction for 8 bit values.
263 \param [in] value Value to store
264 \param [in] ptr Pointer to location
265 \return 0 Function succeeded
266 \return 1 Function failed
268 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
269 #define __STREXB(value, ptr) __strex(value, ptr)
271 #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
275 \brief STR Exclusive (16 bit)
276 \details Executes a exclusive STR instruction for 16 bit values.
277 \param [in] value Value to store
278 \param [in] ptr Pointer to location
279 \return 0 Function succeeded
280 \return 1 Function failed
282 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
283 #define __STREXH(value, ptr) __strex(value, ptr)
285 #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
289 \brief STR Exclusive (32 bit)
290 \details Executes a exclusive STR instruction for 32 bit values.
291 \param [in] value Value to store
292 \param [in] ptr Pointer to location
293 \return 0 Function succeeded
294 \return 1 Function failed
296 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
297 #define __STREXW(value, ptr) __strex(value, ptr)
299 #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
303 \brief Remove the exclusive lock
304 \details Removes the exclusive lock which is created by LDREX.
306 #define __CLREX __clrex
308 /** \brief Get CPSR (Current Program Status Register)
309 \return CPSR Register value
311 __STATIC_INLINE uint32_t __get_CPSR(void)
313 register uint32_t __regCPSR __ASM("cpsr");
318 /** \brief Set CPSR (Current Program Status Register)
319 \param [in] cpsr CPSR value to set
321 __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
323 register uint32_t __regCPSR __ASM("cpsr");
328 \return Processor Mode
330 __STATIC_INLINE uint32_t __get_mode(void) {
331 return (__get_CPSR() & 0x1FU);
335 \param [in] mode Mode value to set
337 __STATIC_INLINE __ASM void __set_mode(uint32_t mode) {
343 /** \brief Set Stack Pointer
344 \param [in] stack Stack Pointer value to set
346 __STATIC_INLINE __ASM void __set_SP(uint32_t stack)
352 /** \brief Set USR/SYS Stack Pointer
353 \param [in] topOfProcStack USR/SYS Stack Pointer value to set
355 __STATIC_INLINE __ASM void __set_SP_usr(uint32_t topOfProcStack)
360 BIC R0, R0, #7 ;ensure stack is 8-byte aligned
362 CPS #0x1F ;no effect in USR mode
364 MSR CPSR_c, R1 ;no effect in USR mode
369 /** \brief Get FPEXC (Floating Point Exception Control Register)
370 \return Floating Point Exception Control Register value
372 __STATIC_INLINE uint32_t __get_FPEXC(void)
374 #if (__FPU_PRESENT == 1)
375 register uint32_t __regfpexc __ASM("fpexc");
382 /** \brief Set FPEXC (Floating Point Exception Control Register)
383 \param [in] fpexc Floating Point Exception Control value to set
385 __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
387 #if (__FPU_PRESENT == 1)
388 register uint32_t __regfpexc __ASM("fpexc");
389 __regfpexc = (fpexc);
393 /** \brief Get ACTLR (Auxiliary Control Register)
394 \return Auxiliary Control Register value
396 __STATIC_INLINE uint32_t __get_ACTLR(void)
398 register uint32_t __regACTLR __ASM("cp15:0:c1:c0:1");
402 /** \brief Set ACTLR (Auxiliary Control Register)
403 \param [in] actlr Auxiliary Control value to set
405 __STATIC_INLINE void __set_ACTLR(uint32_t actlr)
407 register uint32_t __regACTLR __ASM("cp15:0:c1:c0:1");
411 /** \brief Get CPACR (Coprocessor Access Control Register)
412 \return Coprocessor Access Control Register value
414 __STATIC_INLINE uint32_t __get_CPACR(void)
416 register uint32_t __regCPACR __ASM("cp15:0:c1:c0:2");
420 /** \brief Set CPACR (Coprocessor Access Control Register)
421 \param [in] cpacr Coprocessor Access Control value to set
423 __STATIC_INLINE void __set_CPACR(uint32_t cpacr)
425 register uint32_t __regCPACR __ASM("cp15:0:c1:c0:2");
429 /** \brief Get DFSR (Data Fault Status Register)
430 \return Data Fault Status Register value
432 __STATIC_INLINE uint32_t __get_DFSR(void)
434 register uint32_t __regDFSR __ASM("cp15:0:c5:c0:0");
438 /** \brief Set DFSR (Data Fault Status Register)
439 \param [in] dfsr Data Fault Status value to set
441 __STATIC_INLINE void __set_DFSR(uint32_t dfsr)
443 register uint32_t __regDFSR __ASM("cp15:0:c5:c0:0");
447 /** \brief Get IFSR (Instruction Fault Status Register)
448 \return Instruction Fault Status Register value
450 __STATIC_INLINE uint32_t __get_IFSR(void)
452 register uint32_t __regIFSR __ASM("cp15:0:c5:c0:1");
456 /** \brief Set IFSR (Instruction Fault Status Register)
457 \param [in] ifsr Instruction Fault Status value to set
459 __STATIC_INLINE void __set_IFSR(uint32_t ifsr)
461 register uint32_t __regIFSR __ASM("cp15:0:c5:c0:1");
465 /** \brief Get ISR (Interrupt Status Register)
466 \return Interrupt Status Register value
468 __STATIC_INLINE uint32_t __get_ISR(void)
470 register uint32_t __regISR __ASM("cp15:0:c5:c0:1");
474 /** \brief Get CBAR (Configuration Base Address Register)
475 \return Configuration Base Address Register value
477 __STATIC_INLINE uint32_t __get_CBAR() {
478 register uint32_t __regCBAR __ASM("cp15:4:c15:c0:0");
482 /** \brief Get TTBR0 (Translation Table Base Register 0)
483 \return Translation Table Base Register 0 value
485 __STATIC_INLINE uint32_t __get_TTBR0() {
486 register uint32_t __regTTBR0 __ASM("cp15:0:c2:c0:0");
490 /** \brief Set TTBR0 Translation Table Base Register 0
491 \param [in] ttbr0 Translation Table Base Register 0 value to set
493 __STATIC_INLINE void __set_TTBR0(uint32_t ttbr0) {
494 register uint32_t __regTTBR0 __ASM("cp15:0:c2:c0:0");
498 /** \brief Get DACR (Domain Access Control Register)
499 \return Domain Access Control Register value
501 __STATIC_INLINE uint32_t __get_DACR() {
502 register uint32_t __regDACR __ASM("cp15:0:c3:c0:0");
506 /** \brief Set DACR (Domain Access Control Register)
507 \param [in] dacr Domain Access Control Register value to set
509 __STATIC_INLINE void __set_DACR(uint32_t dacr) {
510 register uint32_t __regDACR __ASM("cp15:0:c3:c0:0");
514 /** \brief Set SCTLR (System Control Register).
515 \param [in] sctlr System Control Register value to set
517 __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
519 register uint32_t __regSCTLR __ASM("cp15:0:c1:c0:0");
523 /** \brief Get SCTLR (System Control Register).
524 \return System Control Register value
526 __STATIC_INLINE uint32_t __get_SCTLR() {
527 register uint32_t __regSCTLR __ASM("cp15:0:c1:c0:0");
531 /** \brief Set ACTRL (Auxiliary Control Register)
532 \param [in] actrl Auxiliary Control Register value to set
534 __STATIC_INLINE void __set_ACTRL(uint32_t actrl)
536 register uint32_t __regACTRL __ASM("cp15:0:c1:c0:1");
540 /** \brief Get ACTRL (Auxiliary Control Register)
541 \return Auxiliary Control Register value
543 __STATIC_INLINE uint32_t __get_ACTRL(void)
545 register uint32_t __regACTRL __ASM("cp15:0:c1:c0:1");
549 /** \brief Get MPIDR (Multiprocessor Affinity Register)
550 \return Multiprocessor Affinity Register value
552 __STATIC_INLINE uint32_t __get_MPIDR(void)
554 register uint32_t __regMPIDR __ASM("cp15:0:c0:c0:5");
558 /** \brief Get VBAR (Vector Base Address Register)
559 \return Vector Base Address Register
561 __STATIC_INLINE uint32_t __get_VBAR(void)
563 register uint32_t __regVBAR __ASM("cp15:0:c12:c0:0");
567 /** \brief Set VBAR (Vector Base Address Register)
568 \param [in] vbar Vector Base Address Register value to set
570 __STATIC_INLINE void __set_VBAR(uint32_t vbar)
572 register uint32_t __regVBAR __ASM("cp15:0:c12:c0:0");
576 /** \brief Set CNTFRQ (Counter Frequency Register)
577 \param [in] value CNTFRQ Register value to set
579 __STATIC_INLINE void __set_CNTFRQ(uint32_t value) {
580 register uint32_t __regCNTFRQ __ASM("cp15:0:c14:c0:0");
584 /** \brief Set CNTP_TVAL (PL1 Physical TimerValue Register)
585 \param [in] value CNTP_TVAL Register value to set
587 __STATIC_INLINE void __set_CNTP_TVAL(uint32_t value) {
588 register uint32_t __regCNTP_TVAL __ASM("cp15:0:c14:c2:0");
589 __regCNTP_TVAL = value;
592 /** \brief Get CNTP_TVAL (PL1 Physical TimerValue Register)
593 \return CNTP_TVAL Register value
595 __STATIC_INLINE uint32_t __get_CNTP_TVAL() {
596 register uint32_t __regCNTP_TVAL __ASM("cp15:0:c14:c2:0");
597 return(__regCNTP_TVAL);
600 /** \brief Set CNTP_CTL (PL1 Physical Timer Control Register)
601 \param [in] value CNTP_CTL Register value to set
603 __STATIC_INLINE void __set_CNTP_CTL(uint32_t value) {
604 register uint32_t __regCNTP_CTL __ASM("cp15:0:c14:c2:1");
605 __regCNTP_CTL = value;
608 /** \brief Get CNTP_CTL register
609 \return CNTP_CTL Register value
611 __STATIC_INLINE uint32_t __get_CNTP_CTL() {
612 register uint32_t __regCNTP_CTL __ASM("cp15:0:c14:c2:1");
613 return(__regCNTP_CTL);
616 /** \brief Set TLBIALL (Invalidate Entire Unified TLB)
618 __STATIC_INLINE void __set_TLBIALL(uint32_t value) {
619 register uint32_t __TLBIALL __ASM("cp15:0:c8:c7:0");
623 /** \brief Set BPIALL (Branch Predictor Invalidate All)
624 * \param [in] value BPIALL value to set
626 __STATIC_INLINE void __set_BPIALL(uint32_t value) {
627 register uint32_t __BPIALL __ASM("cp15:0:c7:c5:6");
631 /** \brief Set ICIALLU (Instruction Cache Invalidate All)
632 * \param [in] value ICIALLU value to set
634 __STATIC_INLINE void __set_ICIALLU(uint32_t value) {
635 register uint32_t __ICIALLU __ASM("cp15:0:c7:c5:0");
639 /** \brief Set DCCMVAC (Clean data or unified cache line by MVA to PoC)
640 * \param [in] value DCCMVAC value to set
642 __STATIC_INLINE void __set_DCCMVAC(uint32_t value) {
643 register uint32_t __DCCMVAC __ASM("cp15:0:c7:c10:1");
647 /** \brief Set DCIMVAC (Invalidate data or unified cache line by MVA to PoC)
648 * \param [in] value DCIMVAC value to set
650 __STATIC_INLINE void __set_DCIMVAC(uint32_t value) {
651 register uint32_t __DCIMVAC __ASM("cp15:0:c7:c6:1");
655 /** \brief Set DCCIMVAC (Clean and Invalidate data or unified cache line by MVA to PoC)
656 * \param [in] value DCCIMVAC value to set
658 __STATIC_INLINE void __set_DCCIMVAC(uint32_t value) {
659 register uint32_t __DCCIMVAC __ASM("cp15:0:c7:c14:1");
663 /** \brief Clean and Invalidate the entire data or unified cache
664 * \param [in] op 0 - invalidate, 1 - clean, otherwise - invalidate and clean
666 __STATIC_INLINE __ASM void __L1C_CleanInvalidateCache(uint32_t op) {
671 MRC p15, 1, R6, c0, c0, 1 // Read CLIDR
672 ANDS R3, R6, #0x07000000 // Extract coherency level
673 MOV R3, R3, LSR #23 // Total cache levels << 1
674 BEQ Finished // If 0, no need to clean
676 MOV R10, #0 // R10 holds current cache level << 1
677 Loop1 ADD R2, R10, R10, LSR #1 // R2 holds cache "Set" position
678 MOV R1, R6, LSR R2 // Bottom 3 bits are the Cache-type for this level
679 AND R1, R1, #7 // Isolate those lower 3 bits
681 BLT Skip // No cache or only instruction cache at this level
683 MCR p15, 2, R10, c0, c0, 0 // Write the Cache Size selection register
684 ISB // ISB to sync the change to the CacheSizeID reg
685 MRC p15, 1, R1, c0, c0, 0 // Reads current Cache Size ID register
686 AND R2, R1, #7 // Extract the line length field
687 ADD R2, R2, #4 // Add 4 for the line length offset (log2 16 bytes)
689 ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
690 CLZ R5, R4 // R5 is the bit position of the way size increment
692 ANDS R7, R7, R1, LSR #13 // R7 is the max number of the index size (right aligned)
694 Loop2 MOV R9, R4 // R9 working copy of the max way size (right aligned)
696 Loop3 ORR R11, R10, R9, LSL R5 // Factor in the Way number and cache number into R11
697 ORR R11, R11, R7, LSL R2 // Factor in the Set number
700 MCR p15, 0, R11, c7, c6, 2 // DCISW. Invalidate by Set/Way
704 MCR p15, 0, R11, c7, c10, 2 // DCCSW. Clean by Set/Way
706 Dccisw MCR p15, 0, R11, c7, c14, 2 // DCCISW. Clean and Invalidate by Set/Way
707 cont SUBS R9, R9, #1 // Decrement the Way number
709 SUBS R7, R7, #1 // Decrement the Set number
711 Skip ADD R10, R10, #2 // Increment the cache number
721 /** \brief Enable Floating Point Unit
723 Critical section, called from undef handler, so systick is disabled
725 __STATIC_INLINE __ASM void __FPU_Enable(void) {
728 //Permit access to VFP/NEON, registers by modifying CPACR
730 ORR R1,R1,#0x00F00000
733 //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
738 ORR R1,R1,#0x40000000
741 //Initialise VFP/NEON registers to 0
743 IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16
744 //Initialise D16 registers to 0
762 IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
763 //Initialise D32 registers to 0
782 //Initialise FPSCR to a known state
784 LDR R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
791 #endif /* __CMSIS_ARMCC_H */