1 //*****************************************************************************
2 //
3 //! @file am_hal_sysctrl.c
4 //!
5 //! @brief Functions for interfacing with the M4F system control registers
6 //!
7 //! @addtogroup sysctrl3 SYSCTRL - System Control
8 //! @ingroup apollo3_hal
9 //! @{
10 //
11 //*****************************************************************************
12
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51
52
53 //*****************************************************************************
54 //
55 // Globals
56 //
57 //*****************************************************************************
58 uint32_t g_am_hal_sysctrl_sleep_count = 0;
59
60 //*****************************************************************************
61 //
62 // @brief Place the core into sleep or deepsleep.
63 //
64 // @param bSleepDeep - False for Normal or True Deep sleep.
65 //
66 // This function puts the MCU to sleep or deepsleep depending on bSleepDeep.
67 //
68 // Valid values for bSleepDeep are:
69 //
70 // AM_HAL_SYSCTRL_SLEEP_NORMAL
71 // AM_HAL_SYSCTRL_SLEEP_DEEP
72 //
73 //*****************************************************************************
74 void
am_hal_sysctrl_sleep(bool bSleepDeep)75 am_hal_sysctrl_sleep(bool bSleepDeep)
76 {
77 //
78 // Disable interrupts and save the previous interrupt state.
79 //
80 AM_CRITICAL_BEGIN
81
82 g_am_hal_sysctrl_sleep_count++;
83
84 //
85 // If the user selected DEEPSLEEP and the TPIU is off, attempt to enter
86 // DEEP SLEEP.
87 //
88 if ( (bSleepDeep == AM_HAL_SYSCTRL_SLEEP_DEEP) &&
89 (MCUCTRL->TPIUCTRL_b.ENABLE == MCUCTRL_TPIUCTRL_ENABLE_DIS) )
90 {
91
92 //
93 // Retrieve the reset generator status bits
94 // This gets reset on Deep Sleep, so we take a snapshot here
95 //
96 if (!gAmHalResetStatus)
97 {
98 gAmHalResetStatus = RSTGEN->STAT;
99 }
100
101 //
102 // save original SIMOBUCK1 value, it will be restored
103 //
104 uint32_t ui32Simobuck1Backup = MCUCTRL->SIMOBUCK1;
105
106 //
107 // increase VDDC by 9 counts
108 //
109 uint32_t ui32Vddc = _FLD2VAL( MCUCTRL_SIMOBUCK1_MEMACTIVETRIM, ui32Simobuck1Backup );
110 ui32Vddc += 9;
111
112 //
113 // check for overflow and limit
114 //
115 ui32Vddc = ui32Vddc > (MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk>>MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos) ?
116 (MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk>>MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos) :
117 ui32Vddc;
118
119 ui32Vddc = _VAL2FLD(MCUCTRL_SIMOBUCK1_MEMACTIVETRIM, ui32Vddc );
120
121 //
122 // increase VDDF by 24 counts
123 //
124 uint32_t ui32Vddf = _FLD2VAL( MCUCTRL_SIMOBUCK1_COREACTIVETRIM, ui32Simobuck1Backup ) ;
125 ui32Vddf += 24 ;
126
127 //
128 // check for overflow and limit
129 //
130 ui32Vddf = ui32Vddf > (MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Pos) ?
131 (MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Pos) :
132 ui32Vddf;
133 ui32Vddf = _VAL2FLD(MCUCTRL_SIMOBUCK1_COREACTIVETRIM, ui32Vddf );
134
135 //
136 // remove original values of vddc and vddf and replace with modified values
137 //
138 uint32_t ui32VddVffMask = MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk | MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Msk;
139 uint32_t ui32SimoBuck1Working =
140 (ui32Simobuck1Backup & ~ui32VddVffMask) | ui32Vddc | ui32Vddf;
141
142 //
143 // write updated vddc and vddf to SIMOBUCK1 and wait for 20 microseconds
144 //
145 MCUCTRL->SIMOBUCK1 = ui32SimoBuck1Working;
146
147 //
148 // 20 micosecond delay
149 //
150 am_hal_flash_delay(FLASH_CYCLES_US(20));
151
152 //
153 // just before sleep, restore SIMONBUCK1 to original value
154 //
155 MCUCTRL->SIMOBUCK1 = ui32Simobuck1Backup;
156
157 //
158 // Prepare the core for deepsleep (write 1 to the DEEPSLEEP bit).
159 //
160 SCB->SCR |= _VAL2FLD(SCB_SCR_SLEEPDEEP, 1);
161 }
162 else
163 {
164 //
165 // Prepare the core for normal sleep (write 0 to the DEEPSLEEP bit).
166 //
167 SCB->SCR &= ~_VAL2FLD(SCB_SCR_SLEEPDEEP, 1);
168 }
169
170 //
171 // Before executing WFI, flush any buffered core and peripheral writes.
172 //
173 __DSB();
174 am_hal_sysctrl_bus_write_flush();
175
176 //
177 // Execute the sleep instruction.
178 //
179 __WFI();
180
181 //
182 // Upon wake, execute the Instruction Sync Barrier instruction.
183 //
184 __ISB();
185
186 //
187 // Restore the interrupt state.
188 //
189 AM_CRITICAL_END
190 }
191
192 //*****************************************************************************
193 //
194 // @brief Enable the floating point module.
195 //
196 // Call this function to enable the ARM hardware floating point module.
197 //
198 //*****************************************************************************
199 void
am_hal_sysctrl_fpu_enable(void)200 am_hal_sysctrl_fpu_enable(void)
201 {
202 //
203 // Enable access to the FPU in both privileged and user modes.
204 // NOTE: Write 0s to all reserved fields in this register.
205 //
206 SCB->CPACR = _VAL2FLD(SCB_CPACR_CP11, 0x3) |
207 _VAL2FLD(SCB_CPACR_CP10, 0x3);
208 }
209
210 //*****************************************************************************
211 //
212 // @brief Disable the floating point module.
213 //
214 // Call this function to disable the ARM hardware floating point module.
215 //
216 //*****************************************************************************
217 void
am_hal_sysctrl_fpu_disable(void)218 am_hal_sysctrl_fpu_disable(void)
219 {
220 //
221 // Disable access to the FPU in both privileged and user modes.
222 // NOTE: Write 0s to all reserved fields in this register.
223 //
224 SCB->CPACR = 0x00000000 &
225 ~(_VAL2FLD(SCB_CPACR_CP11, 0x3) |
226 _VAL2FLD(SCB_CPACR_CP10, 0x3));
227 }
228
229 //*****************************************************************************
230 //
231 // @brief Enable stacking of FPU registers on exception entry.
232 //
233 // @param bLazy - Set to "true" to enable "lazy stacking".
234 //
235 // This function allows the core to save floating-point information to the
236 // stack on exception entry. Setting the bLazy option enables "lazy stacking"
237 // for interrupt handlers. Normally, mixing floating-point code and interrupt
238 // driven routines causes increased interrupt latency, because the core must
239 // save extra information to the stack upon exception entry. With the lazy
240 // stacking option enabled, the core will skip the saving of floating-point
241 // registers when possible, reducing average interrupt latency.
242 //
243 // @note At reset of the Cortex M4, the ASPEN and LSPEN bits are set to 1,
244 // enabling Lazy mode by default. Therefore this function will generally
245 // only have an affect when setting for full-context save (or when switching
246 // from full-context to lazy mode).
247 //
248 // @note See also:
249 // infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0298a/DAFGGBJD.html
250 //
251 // @note Three valid FPU context saving modes are possible.
252 // 1. Lazy ASPEN=1 LSPEN=1 am_hal_sysctrl_fpu_stacking_enable(true)
253 // and default.
254 // 2. Full-context ASPEN=1 LSPEN=0 am_hal_sysctrl_fpu_stacking_enable(false)
255 // 3. No FPU state ASPEN=0 LSPEN=0 am_hal_sysctrl_fpu_stacking_disable()
256 // 4. Invalid ASPEN=0 LSPEN=1
257 //
258 //*****************************************************************************
259 void
am_hal_sysctrl_fpu_stacking_enable(bool bLazy)260 am_hal_sysctrl_fpu_stacking_enable(bool bLazy)
261 {
262 uint32_t ui32fpccr;
263
264 //
265 // Set the requested FPU stacking mode in ISRs.
266 //
267 AM_CRITICAL_BEGIN
268 #define SYSCTRL_FPCCR_LAZY (FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk)
269 ui32fpccr = FPU->FPCCR;
270 ui32fpccr &= ~SYSCTRL_FPCCR_LAZY;
271 ui32fpccr |= (bLazy ? SYSCTRL_FPCCR_LAZY : FPU_FPCCR_ASPEN_Msk);
272 FPU->FPCCR = ui32fpccr;
273 AM_CRITICAL_END
274 }
275
276 //*****************************************************************************
277 //
278 // @brief Disable FPU register stacking on exception entry.
279 //
280 // This function disables all stacking of floating point registers for
281 // interrupt handlers. This mode should only be used when it is absolutely
282 // known that no FPU instructions will be executed in an ISR.
283 //
284 //*****************************************************************************
285 void
am_hal_sysctrl_fpu_stacking_disable(void)286 am_hal_sysctrl_fpu_stacking_disable(void)
287 {
288 //
289 // Completely disable FPU context save on entry to ISRs.
290 //
291 AM_CRITICAL_BEGIN
292 FPU->FPCCR &= ~SYSCTRL_FPCCR_LAZY;
293 AM_CRITICAL_END
294 }
295
296 //*****************************************************************************
297 //
298 // @brief Issue a system wide reset using the AIRCR bit in the M4 system ctrl.
299 //
300 // This function issues a system wide reset (Apollo POR level reset).
301 //
302 //*****************************************************************************
303 void
am_hal_sysctrl_aircr_reset(void)304 am_hal_sysctrl_aircr_reset(void)
305 {
306 //
307 // Set the system reset bit in the AIRCR register
308 //
309 __NVIC_SystemReset();
310 }
311
312 //*****************************************************************************
313 //
314 // End Doxygen group.
315 //! @}
316 //
317 //*****************************************************************************
318