1 //*****************************************************************************
2 //
3 //! @file am_hal_interrupt.c
4 //!
5 //! @brief Helper functions supporting interrupts and NVIC operation.
6 //!
7 //! These functions may be used for NVIC-level interrupt configuration.
8 //!
9 //! @addtogroup interrupt3p Interrupt - ARM NVIC support functions
10 //! @ingroup apollo3p_hal
11 //! @{
12 //
13 //*****************************************************************************
14 
15 //*****************************************************************************
16 //
17 // Copyright (c) 2023, Ambiq Micro, Inc.
18 // All rights reserved.
19 //
20 // Redistribution and use in source and binary forms, with or without
21 // modification, are permitted provided that the following conditions are met:
22 //
23 // 1. Redistributions of source code must retain the above copyright notice,
24 // this list of conditions and the following disclaimer.
25 //
26 // 2. Redistributions in binary form must reproduce the above copyright
27 // notice, this list of conditions and the following disclaimer in the
28 // documentation and/or other materials provided with the distribution.
29 //
30 // 3. Neither the name of the copyright holder nor the names of its
31 // contributors may be used to endorse or promote products derived from this
32 // software without specific prior written permission.
33 //
34 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
35 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
38 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44 // POSSIBILITY OF SUCH DAMAGE.
45 //
46 // This is part of revision release_sdk_3_1_1-10cda4b5e0 of the AmbiqSuite Development Package.
47 //
48 //*****************************************************************************
49 
50 #include <stdint.h>
51 #include <stdbool.h>
52 #include "am_mcu_apollo.h"
53 
54 //*****************************************************************************
55 //
56 //! @brief Globally enable interrupt service routines
57 //!
58 //! This function allows interrupt signals from the NVIC to trigger ISR entry
59 //! in the CPU. This function must be called if interrupts are to be serviced
60 //! in software.
61 //!
62 //! @return 1 if interrupts were previously disabled, 0 otherwise.
63 //
64 //*****************************************************************************
65 #if (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION < 6000000)
66 __asm uint32_t
am_hal_interrupt_master_enable(void)67 am_hal_interrupt_master_enable(void)
68 {
69     mrs     r0, PRIMASK
70     cpsie   i
71     bx      lr
72 }
73 #elif (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION >= 6000000)
74 uint32_t __attribute__((naked))
am_hal_interrupt_master_enable(void)75 am_hal_interrupt_master_enable(void)
76 {
77     __asm("    mrs     r0, PRIMASK");
78     __asm("    cpsie i");
79     __asm("    bx lr");
80 }
81 #elif defined(__GNUC_STDC_INLINE__)
82 uint32_t __attribute__((naked))
am_hal_interrupt_master_enable(void)83 am_hal_interrupt_master_enable(void)
84 {
85     __asm("    mrs     r0, PRIMASK");
86     __asm("    cpsie i");
87     __asm("    bx lr");
88 }
89 #elif defined(__IAR_SYSTEMS_ICC__)
90 #pragma diag_suppress = Pe940   // Suppress IAR compiler warning about missing
91                                 // return statement on a non-void function
92 __stackless uint32_t
am_hal_interrupt_master_enable(void)93 am_hal_interrupt_master_enable(void)
94 {
95     __asm("    mrs     r0, PRIMASK");
96     __asm("    cpsie i");
97     __asm("    bx lr");
98 }
99 #pragma diag_default = Pe940    // Restore IAR compiler warning
100 #else
101 #error Compiler is unknown, please contact Ambiq support team
102 #endif
103 
104 //*****************************************************************************
105 //
106 //! @brief Globally disable interrupt service routines
107 //!
108 //! This function prevents interrupt signals from the NVIC from triggering ISR
109 //! entry in the CPU. This will effectively stop incoming interrupt sources
110 //! from triggering their corresponding ISRs.
111 //!
112 //! @note Any external interrupt signal that occurs while the master interrupt
113 //! disable is active will still reach the "pending" state in the NVIC, but it
114 //! will not be allowed to reach the "active" state or trigger the
115 //! corresponding ISR. Instead, these interrupts are essentially "queued" until
116 //! the next time the master interrupt enable instruction is executed. At that
117 //! time, the interrupt handlers will be executed in order of decreasing
118 //! priority.
119 //!
120 //! @return 1 if interrupts were previously disabled, 0 otherwise.
121 //
122 //*****************************************************************************
123 #if (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION < 6000000)
124 __asm uint32_t
am_hal_interrupt_master_disable(void)125 am_hal_interrupt_master_disable(void)
126 {
127     mrs     r0, PRIMASK
128     cpsid   i
129     bx      lr
130 }
131 #elif (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION >= 6000000)
132 uint32_t __attribute__((naked))
am_hal_interrupt_master_disable(void)133 am_hal_interrupt_master_disable(void)
134 {
135     __asm("    mrs     r0, PRIMASK");
136     __asm("    cpsid i");
137     __asm("    bx lr");
138 }
139 #elif defined(__GNUC_STDC_INLINE__)
140 uint32_t __attribute__((naked))
am_hal_interrupt_master_disable(void)141 am_hal_interrupt_master_disable(void)
142 {
143     __asm("    mrs     r0, PRIMASK");
144     __asm("    cpsid i");
145     __asm("    bx lr");
146 }
147 #elif defined(__IAR_SYSTEMS_ICC__)
148 #pragma diag_suppress = Pe940   // Suppress IAR compiler warning about missing
149                                 // return statement on a non-void function
150 __stackless uint32_t
am_hal_interrupt_master_disable(void)151 am_hal_interrupt_master_disable(void)
152 {
153     __asm("    mrs     r0, PRIMASK");
154     __asm("    cpsid i");
155     __asm("    bx lr");
156 }
157 #pragma diag_default = Pe940    // Restore IAR compiler warning
158 #else
159 #error Compiler is unknown, please contact Ambiq support team
160 #endif
161 
162 //*****************************************************************************
163 //
164 //! @brief Sets the master interrupt state based on the input.
165 //!
166 //! @param ui32InterruptState - Desired PRIMASK value.
167 //!
168 //! This function directly writes the PRIMASK register in the ARM core. A value
169 //! of 1 will disable interrupts, while a value of zero will enable them.
170 //!
171 //! This function may be used along with am_hal_interrupt_master_disable() to
172 //! implement a nesting critical section. To do this, call
173 //! am_hal_interrupt_master_disable() to start the critical section, and save
174 //! its return value. To complete the critical section, call
175 //! am_hal_interrupt_master_set() using the saved return value as \e
176 //! ui32InterruptState. This will safely restore PRIMASK to the value it
177 //! contained just before the start of the critical section.
178 //!
179 //! @return None.
180 //
181 //*****************************************************************************
182 #if (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION <  6000000)
183 __asm void
am_hal_interrupt_master_set(uint32_t ui32InterruptState)184 am_hal_interrupt_master_set(uint32_t ui32InterruptState)
185 {
186     msr     PRIMASK, r0
187     bx      lr
188 }
189 #elif (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION >= 6000000)
190 void __attribute__((naked))
am_hal_interrupt_master_set(uint32_t ui32InterruptState)191 am_hal_interrupt_master_set(uint32_t ui32InterruptState)
192 {
193     __asm("    msr     PRIMASK, r0");
194     __asm("    bx lr");
195 }
196 #elif defined(__GNUC_STDC_INLINE__)
197 void __attribute__((naked))
am_hal_interrupt_master_set(uint32_t ui32InterruptState)198 am_hal_interrupt_master_set(uint32_t ui32InterruptState)
199 {
200     __asm("    msr     PRIMASK, r0");
201     __asm("    bx lr");
202 }
203 #elif defined(__IAR_SYSTEMS_ICC__)
204 #pragma diag_suppress = Pe940   // Suppress IAR compiler warning about missing
205                                 // return statement on a non-void function
206 __stackless void
am_hal_interrupt_master_set(uint32_t ui32InterruptState)207 am_hal_interrupt_master_set(uint32_t ui32InterruptState)
208 {
209     __asm("    msr     PRIMASK, r0");
210     __asm("    bx lr");
211 }
212 #pragma diag_default = Pe940    // Restore IAR compiler warning
213 #endif
214 
215 //*****************************************************************************
216 //
217 // End Doxygen group.
218 //! @}
219 //
220 //*****************************************************************************
221