1 //*****************************************************************************
2 //
3 // am_hal_sysctrl.c
4 //! @file
5 //!
6 //! @brief Functions for interfacing with the M4F system control registers
7 //!
8 //! @addtogroup sysctrl2 System Control (SYSCTRL)
9 //! @ingroup apollo2hal
10 //! @{
11 //
12 //*****************************************************************************
13
14 //*****************************************************************************
15 //
16 // Copyright (c) 2017, Ambiq Micro
17 // All rights reserved.
18 //
19 // Redistribution and use in source and binary forms, with or without
20 // modification, are permitted provided that the following conditions are met:
21 //
22 // 1. Redistributions of source code must retain the above copyright notice,
23 // this list of conditions and the following disclaimer.
24 //
25 // 2. Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // 3. Neither the name of the copyright holder nor the names of its
30 // contributors may be used to endorse or promote products derived from this
31 // software without specific prior written permission.
32 //
33 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
37 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 // POSSIBILITY OF SUCH DAMAGE.
44 //
45 // This is part of revision 1.2.11 of the AmbiqSuite Development Package.
46 //
47 //*****************************************************************************
48
49 #include <stdint.h>
50 #include <stdbool.h>
51 #include "am_mcu_apollo.h"
52
53 //*****************************************************************************
54 //
55 // Local macro constants
56 //
57 //*****************************************************************************
58 //
59 // Define ZX workaround values.
60 // These values are defined by the factory.
61 //
62 #define COREZXVALUE 0x07
63 #define MEMZXVALUE 0x07
64
65 //
66 // Define values for g_ui32CoreBuck, which indicates which timer carries
67 // the signal for the CORE Buck, and which also implies that the other timer
68 // carries the signal for the MEM buck.
69 //
70 #define COREBUCK_TIMERA 1 // Core buck signal comes in on timer A
71 #define COREBUCK_TIMERB 2 // Core buck signal comes in on timer B
72
73 //
74 // Define the bit values for static function g_buckZX_chk;
75 //
76 #define CHKBUCKZX_BUCKS 0x01 // The bucks are enabled
77 #define CHKBUCKZX_REV 0x02 // This chip rev needs the workaround
78 #define CHKBUCKZX_TIMER 0x04 // A valid timer has been allocated
79 #define CHKBUCKZX_DEVEN 0x08 // Devices are powered up and enabled
80
81 //*****************************************************************************
82 //
83 // Prototypes
84 //
85 //*****************************************************************************
86 static void am_hal_sysctrl_buckA_ctimer_isr(void);
87 static void am_hal_sysctrl_buckB_ctimer_isr(void);
88
89 //*****************************************************************************
90 //
91 // Globals
92 //
93 //*****************************************************************************
94 static volatile uint32_t g_ui32BuckTimer = 0;
95 static volatile uint32_t g_ui32BuckInputs = 0;
96 static volatile bool g_bBuckRestoreComplete = false;
97 static volatile bool g_bBuckTimed = false;
98 static uint32_t g_ui32SaveCoreBuckZX, g_ui32SaveMemBuckZX;
99 static uint32_t g_buckZX_chk = 0;
100 static volatile uint32_t g_ui32CoreBuck;
101
102 //
103 // Timer configuration for BUCK inputs.
104 //
105 static const am_hal_ctimer_config_t g_sBuckTimer =
106 {
107 // Don't link timers.
108 0,
109
110 // Set up Timer0A.
111 (AM_HAL_CTIMER_FN_ONCE |
112 AM_HAL_CTIMER_INT_ENABLE |
113 AM_HAL_CTIMER_BUCK),
114
115 // Set up Timer0B.
116 (AM_HAL_CTIMER_FN_ONCE |
117 AM_HAL_CTIMER_INT_ENABLE |
118 AM_HAL_CTIMER_BUCK),
119 };
120
121 //*****************************************************************************
122 //
123 // Determine if we need to do the zero cross workaround on this device.
124 // Three criteria are used. All three must be true.
125 // 1. Are the bucks enabled?
126 // 2. Is the chip rev appropriate for the workaround?
127 // 3. Has a timer been allocated to do the workaround?
128 // 4. Are certain peripherals powered up?
129 //
130 // Saves the bitmask to the global g_buckZX_chk.
131 // Bitmask bits are defined as: CHKBUCKZX_BUCKS, CHKBUCKZX_REV, CHKBUCKZX_TIMER.
132 //
133 // Returns true if all criteria are met, false otherwise.
134 // g_buckZX_chk can be probed to determine which criteria passed or failed.
135 //
136 //*****************************************************************************
137 static bool
buckZX_chk(void)138 buckZX_chk(void)
139 {
140 uint32_t ui32SupplySrc;
141
142 //
143 // Is this chip rev appropriate to do the workaround?
144 //
145 g_buckZX_chk = AM_BFM(MCUCTRL, CHIPREV, REVMAJ) == AM_REG_MCUCTRL_CHIPREV_REVMAJ_B ?
146 CHKBUCKZX_REV : 0x0;
147
148 //
149 // Has a timer been configured to handle the workaround?
150 //
151 g_buckZX_chk |= ( g_ui32BuckTimer - 1 ) <= BUCK_TIMER_MAX ?
152 CHKBUCKZX_TIMER : 0x0;
153
154 //
155 // Are either or both of the bucks actually enabled?
156 //
157 ui32SupplySrc = AM_REG(PWRCTRL, SUPPLYSRC);
158
159 g_buckZX_chk |= (ui32SupplySrc &
160 (AM_REG_PWRCTRL_SUPPLYSRC_COREBUCKEN_M |
161 AM_REG_PWRCTRL_SUPPLYSRC_MEMBUCKEN_M) ) ?
162 CHKBUCKZX_BUCKS : 0x0;
163
164 //
165 // Finally, if any peripheral is already powered up, we don't need to do the
166 // ZX workaround because in this case the bucks remain in active mode.
167 //
168 ui32SupplySrc = AM_REG(PWRCTRL, DEVICEEN);
169
170 g_buckZX_chk |= ( ui32SupplySrc &
171 (AM_REG_PWRCTRL_DEVICEEN_PDM_M |
172 AM_REG_PWRCTRL_DEVICEEN_UART1_M |
173 AM_REG_PWRCTRL_DEVICEEN_UART0_M |
174 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER5_M |
175 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER4_M |
176 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER3_M |
177 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER2_M |
178 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER1_M |
179 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER0_M |
180 AM_REG_PWRCTRL_DEVICEEN_IO_SLAVE_M) ) ?
181 0x0 : CHKBUCKZX_DEVEN;
182
183 //
184 // If all 4 criteria were met, we're good to do the workaround.
185 //
186 return ( g_buckZX_chk ==
187 (CHKBUCKZX_BUCKS | CHKBUCKZX_REV |
188 CHKBUCKZX_TIMER | CHKBUCKZX_DEVEN) ) ? true : false;
189 }
190
191 //*****************************************************************************
192 //
193 // Set the buck zero cross settings to the values given.
194 //
195 // ui32Flags, one or more of the following:
196 // SETBUCKZX_USE_PROVIDED_SETTINGS - Use the values provided in the parameters
197 // to set the trim value(s).
198 // SETBUCKZX_USE_SAVED_SETTINGS - Use the values that were previously saved
199 // to set the trim value(s).
200 // SETBUCKZX_SAVE_CURR_SETTINGS - Save the current trim values before
201 // setting the new ones.
202 // SETBUCKZX_RESTORE_CORE_ONLY - Restore the Core trim and save the current
203 // value of the core buck trim iff
204 // SETBUCKZX_SAVE_CURR_SETTINGS is set.
205 // SETBUCKZX_RESTORE_MEM_ONLY - Restore the Mem trim and save the current
206 // value of the mem buck trim iff
207 // SETBUCKZX_SAVE_CURR_SETTINGS is set.
208 // SETBUCKZX_RESTORE_BOTH - Restore both buck trims and save the
209 // current value of both iff
210 // SETBUCKZX_SAVE_CURR_SETTINGS is set.
211 //
212 //*****************************************************************************
213 #define SETBUCKZX_USE_PROVIDED_SETTINGS 0x01
214 #define SETBUCKZX_USE_SAVED_SETTINGS 0x02
215 #define SETBUCKZX_SAVE_CURR_SETTINGS 0x04
216 #define SETBUCKZX_RESTORE_CORE_ONLY 0x10
217 #define SETBUCKZX_RESTORE_MEM_ONLY 0x20
218 #define SETBUCKZX_RESTORE_BOTH ( SETBUCKZX_RESTORE_CORE_ONLY | \
219 SETBUCKZX_RESTORE_MEM_ONLY )
220 static void
setBuckZX(uint32_t ui32CoreBuckZX,uint32_t ui32MemBuckZX,uint32_t ui32Flags)221 setBuckZX(uint32_t ui32CoreBuckZX, uint32_t ui32MemBuckZX, uint32_t ui32Flags)
222 {
223 uint32_t ui32SaveCore, ui32SaveMem, ui32NewCore, ui32NewMem;
224 bool bDoRestore = false;
225
226 //
227 // Begin critical section.
228 //
229 AM_CRITICAL_BEGIN_ASM
230
231 //
232 // Get the current zero cross trim values.
233 //
234 ui32SaveCore = AM_BFR(MCUCTRL, BUCK3, COREBUCKZXTRIM);
235 ui32SaveMem = AM_BFR(MCUCTRL, BUCK3, MEMBUCKZXTRIM);
236
237 //
238 // Determine which values will be restored.
239 //
240 if ( ui32Flags & SETBUCKZX_USE_SAVED_SETTINGS )
241 {
242 //
243 // Use saved settings
244 //
245 ui32NewCore = g_ui32SaveCoreBuckZX;
246 ui32NewMem = g_ui32SaveMemBuckZX;
247 bDoRestore = true;
248 }
249 else if ( ui32Flags & SETBUCKZX_USE_PROVIDED_SETTINGS )
250 {
251 //
252 // Use settings provided in the call parameters
253 //
254 ui32NewCore = ui32CoreBuckZX;
255 ui32NewMem = ui32MemBuckZX;
256 bDoRestore = true;
257 }
258
259 //
260 // Restore the buck Core and Mem trim registers.
261 //
262 if ( bDoRestore )
263 {
264 if ( ui32Flags & SETBUCKZX_RESTORE_CORE_ONLY )
265 {
266 AM_BFW(MCUCTRL, BUCK3, COREBUCKZXTRIM, ui32NewCore);
267 }
268
269 if ( ui32Flags & SETBUCKZX_RESTORE_MEM_ONLY )
270 {
271 AM_BFW(MCUCTRL, BUCK3, MEMBUCKZXTRIM, ui32NewMem);
272 }
273 }
274
275 if ( ui32Flags & SETBUCKZX_SAVE_CURR_SETTINGS )
276 {
277 //
278 // Save off the zero cross values as read on entry to the function.
279 //
280 if ( ui32Flags & SETBUCKZX_RESTORE_CORE_ONLY )
281 {
282 g_ui32SaveCoreBuckZX = ui32SaveCore;
283 }
284
285 if ( ui32Flags & SETBUCKZX_RESTORE_MEM_ONLY )
286 {
287 g_ui32SaveMemBuckZX = ui32SaveMem;
288 }
289 }
290
291 //
292 // Done with critical section.
293 //
294 AM_CRITICAL_END_ASM
295 }
296
297 //*****************************************************************************
298 //
299 //! @brief Place the core into sleep or deepsleep.
300 //!
301 //! @param bSleepDeep - False for Normal or True Deep sleep.
302 //!
303 //! This function puts the MCU to sleep or deepsleep depending on bSleepDeep.
304 //!
305 //! Valid values for bSleepDeep are:
306 //!
307 //! AM_HAL_SYSCTRL_SLEEP_NORMAL
308 //! AM_HAL_SYSCTRL_SLEEP_DEEP
309 //!
310 //! @return None.
311 //
312 //*****************************************************************************
313 void
am_hal_sysctrl_sleep(bool bSleepDeep)314 am_hal_sysctrl_sleep(bool bSleepDeep)
315 {
316 uint32_t ui32Critical;
317 // uint32_t ui32DebugGpioSleep = g_ui32DebugGpioSleep - 1;
318 bool bBuckZX_chk;
319 volatile uint32_t ui32BuckTimer;
320
321 //
322 // Disable interrupts and save the previous interrupt state.
323 //
324 ui32Critical = am_hal_interrupt_master_disable();
325
326 //
327 // If the user selected DEEPSLEEP and the TPIU is off, attempt to enter
328 // DEEP SLEEP.
329 //
330 if ((bSleepDeep == AM_HAL_SYSCTRL_SLEEP_DEEP) &&
331 (AM_BFM(MCUCTRL, TPIUCTRL, ENABLE) == AM_REG_MCUCTRL_TPIUCTRL_ENABLE_DIS))
332 {
333 //
334 // Prepare the core for deepsleep (write 1 to the DEEPSLEEP bit).
335 //
336 AM_BFW(SYSCTRL, SCR, SLEEPDEEP, 1);
337
338 //
339 // Check if special buck handling is needed
340 //
341 bBuckZX_chk = buckZX_chk();
342
343 if ( bBuckZX_chk )
344 {
345 ui32BuckTimer = g_ui32BuckTimer - 1;
346
347 //
348 // Before going to sleep, clear the buck timers.
349 // This will also handle the case where we're going back to
350 // sleep before the buck sequence has even completed.
351 //
352 am_hal_ctimer_clear(ui32BuckTimer, AM_HAL_CTIMER_BOTH);
353
354 //
355 // Set CMPR0 of both timerA and timerB to the period value
356 //
357 #define TIMER_PERIOD_BUCKS 1
358 am_hal_ctimer_period_set(ui32BuckTimer,
359 AM_HAL_CTIMER_BOTH,
360 TIMER_PERIOD_BUCKS |
361 (TIMER_PERIOD_BUCKS << 16),
362 0);
363
364 //
365 // Disable bucks before going to sleep.
366 //
367 am_hal_pwrctrl_bucks_disable();
368 }
369
370 //
371 // Execute the sleep instruction.
372 //
373 AM_ASM_WFI;
374
375 //
376 // Return from sleep
377 //
378 if ( bBuckZX_chk )
379 {
380 //
381 // Adjust the core and mem trims
382 //
383 setBuckZX(COREZXVALUE, MEMZXVALUE,
384 SETBUCKZX_USE_PROVIDED_SETTINGS |
385 SETBUCKZX_RESTORE_BOTH );
386
387 //
388 // Delay for 2us before enabling bucks.
389 //
390 am_hal_flash_delay( FLASH_CYCLES_US(2) );
391
392 //
393 // Turn on the bucks
394 //
395 am_hal_pwrctrl_bucks_enable();
396
397 //
398 // Get the actual timer number
399 //
400 ui32BuckTimer = g_ui32BuckTimer - 1;
401
402 //
403 // Initialize the complete flag
404 //
405 g_bBuckRestoreComplete = false;
406
407 //
408 // Initialize the input flags
409 //
410 g_ui32BuckInputs = 0;
411
412 //
413 // Delay for 5us to make sure we're receiving clean buck signals.
414 //
415 am_hal_flash_delay( FLASH_CYCLES_US(5) );
416
417 //
418 // Start timers (set the enable bit, clear the clear bit)
419 //
420 am_hal_ctimer_start(ui32BuckTimer, AM_HAL_CTIMER_BOTH);
421 }
422 else
423 {
424 //
425 // Since we're not doing anything, we're done, so set the done flag.
426 //
427 g_bBuckRestoreComplete = true;
428 }
429 }
430 else
431 {
432 //
433 // Prepare the core for normal sleep (write 0 to the DEEPSLEEP bit).
434 //
435 AM_BFW(SYSCTRL, SCR, SLEEPDEEP, 0);
436
437 //
438 // Go to sleep.
439 //
440 AM_ASM_WFI;
441 }
442
443 //
444 // Restore the interrupt state.
445 //
446 am_hal_interrupt_master_set(ui32Critical);
447 }
448
449 //*****************************************************************************
450 //
451 //! @brief Enable the floating point module.
452 //!
453 //! Call this function to enable the ARM hardware floating point module.
454 //!
455 //! @return None.
456 //
457 //*****************************************************************************
458 void
am_hal_sysctrl_fpu_enable(void)459 am_hal_sysctrl_fpu_enable(void)
460 {
461 //
462 // Enable access to the FPU in both privileged and user modes.
463 // NOTE: Write 0s to all reserved fields in this register.
464 //
465 AM_REG(SYSCTRL, CPACR) = (AM_REG_SYSCTRL_CPACR_CP11(0x3) |
466 AM_REG_SYSCTRL_CPACR_CP10(0x3));
467 }
468
469 //*****************************************************************************
470 //
471 //! @brief Disable the floating point module.
472 //!
473 //! Call this function to disable the ARM hardware floating point module.
474 //!
475 //! @return None.
476 //
477 //*****************************************************************************
478 void
am_hal_sysctrl_fpu_disable(void)479 am_hal_sysctrl_fpu_disable(void)
480 {
481 //
482 // Disable access to the FPU in both privileged and user modes.
483 // NOTE: Write 0s to all reserved fields in this register.
484 //
485 AM_REG(SYSCTRL, CPACR) = 0x00000000 &
486 ~(AM_REG_SYSCTRL_CPACR_CP11(0x3) |
487 AM_REG_SYSCTRL_CPACR_CP10(0x3));
488 }
489
490 //*****************************************************************************
491 //
492 //! @brief Enable stacking of FPU registers on exception entry.
493 //!
494 //! @param bLazy - Set to "true" to enable "lazy stacking".
495 //!
496 //! This function allows the core to save floating-point information to the
497 //! stack on exception entry. Setting the bLazy option enables "lazy stacking"
498 //! for interrupt handlers. Normally, mixing floating-point code and interrupt
499 //! driven routines causes increased interrupt latency, because the core must
500 //! save extra information to the stack upon exception entry. With the lazy
501 //! stacking option enabled, the core will skip the saving of floating-point
502 //! registers when possible, reducing average interrupt latency.
503 //!
504 //! @note This function should be called before the floating-point module is
505 //! used in interrupt-driven code. If it is not called, the core will not have
506 //! any way to save context information for floating-point variables on
507 //! exception entry.
508 //!
509 //! @return None.
510 //
511 //*****************************************************************************
512 void
am_hal_sysctrl_fpu_stacking_enable(bool bLazy)513 am_hal_sysctrl_fpu_stacking_enable(bool bLazy)
514 {
515 if ( bLazy )
516 {
517 //
518 // Enable automatic saving of FPU registers on exception entry, using lazy
519 // context saving.
520 //
521 AM_REG(SYSCTRL, FPCCR) |= (AM_REG_SYSCTRL_FPCCR_ASPEN(0x1) |
522 AM_REG_SYSCTRL_FPCCR_LSPEN(0x1));
523 }
524 else
525 {
526 //
527 // Enable automatic saving of FPU registers on exception entry.
528 //
529 AM_REG(SYSCTRL, FPCCR) |= AM_REG_SYSCTRL_FPCCR_ASPEN(0x1);
530 }
531 }
532
533 //*****************************************************************************
534 //
535 //! @brief Disable FPU register stacking on exception entry.
536 //!
537 //! This function disables all stacking of floating point registers for
538 //! interrupt handlers.
539 //!
540 //! @return None.
541 //
542 //*****************************************************************************
543 void
am_hal_sysctrl_fpu_stacking_disable(void)544 am_hal_sysctrl_fpu_stacking_disable(void)
545 {
546 //
547 // Enable automatic saving of FPU registers on exception entry, using lazy
548 // context saving.
549 //
550 AM_REG(SYSCTRL, FPCCR) &= ~(AM_REG_SYSCTRL_FPCCR_ASPEN(0x1) |
551 AM_REG_SYSCTRL_FPCCR_LSPEN(0x1));
552 }
553
554 //*****************************************************************************
555 //
556 //! @brief Issue a system wide reset using the AIRCR bit in the M4 system ctrl.
557 //!
558 //! This function issues a system wide reset (Apollo POR level reset).
559 //!
560 //! @return None.
561 //
562 //*****************************************************************************
563 void
am_hal_sysctrl_aircr_reset(void)564 am_hal_sysctrl_aircr_reset(void)
565 {
566 //
567 // Set the system reset bit in the AIRCR register
568 //
569 AM_REG(SYSCTRL, AIRCR) = AM_REG_SYSCTRL_AIRCR_VECTKEY(0x5FA) |
570 AM_REG_SYSCTRL_AIRCR_SYSRESETREQ(1);
571 }
572
573 //*****************************************************************************
574 //
575 //! @brief Buck CTimer ISR initializer.
576 //!
577 //! @param ui32BuckTimerNumber - Timer number to be used for handling the buck.
578 //! Must be 0-3.
579 //!
580 //! If called with an invalid timer (that is, not 0 - 3, or greater than
581 //! BUCK_TIMER_MAX), then the workaround will not be enabled.
582 //!
583 //! Instead, the bucks will be initialized with a value that will avoid the
584 //! issues described in the Errata (ERR019). However, this will cause a
585 //! less efficient energy usage condtion.
586 //!
587 //! @return 0.
588 //
589 //*****************************************************************************
590 uint32_t
am_hal_sysctrl_buck_ctimer_isr_init(uint32_t ui32BuckTimerNumber)591 am_hal_sysctrl_buck_ctimer_isr_init(uint32_t ui32BuckTimerNumber)
592 {
593 uint32_t ui32RetVal = 0;
594
595 //
596 // Initialize the input flags
597 //
598 g_ui32BuckInputs = 0;
599
600 //
601 // Initialize operation complete flag
602 //
603 g_bBuckRestoreComplete = false;
604
605 //
606 // Initialize to assume there is no valid timer.
607 //
608 g_ui32BuckTimer = 0;
609
610 if ( ui32BuckTimerNumber > BUCK_TIMER_MAX )
611 {
612 if ( ( ui32BuckTimerNumber & 0xFFFF0000 ) ==
613 AM_HAL_SYSCTRL_BUCK_CTIMER_ZX_CONSTANT )
614 {
615 //
616 // The caller is asking for the hard option, which changes the
617 // settings to the more noise-immune, if less efficient, settings.
618 // While we're at it, go ahead and save off the current settings.
619 //
620 if ( (ui32BuckTimerNumber & 0x0000FFFF) == 0 )
621 {
622 setBuckZX(COREZXVALUE, MEMZXVALUE,
623 SETBUCKZX_USE_PROVIDED_SETTINGS |
624 SETBUCKZX_SAVE_CURR_SETTINGS |
625 SETBUCKZX_RESTORE_BOTH );
626 }
627 else
628 {
629 uint32_t ui32Core, ui32Mem;
630
631 //
632 // Use the setting provided in the parameter.
633 //
634 ui32Core = (((ui32BuckTimerNumber & 0x001F) >> 0) - 1) & 0xF;
635 ui32Mem = (((ui32BuckTimerNumber & 0x1F00) >> 8) - 1) & 0xF;
636
637 setBuckZX(ui32Core, ui32Mem,
638 SETBUCKZX_USE_PROVIDED_SETTINGS |
639 SETBUCKZX_SAVE_CURR_SETTINGS |
640 SETBUCKZX_RESTORE_BOTH );
641 }
642 }
643 }
644 else
645 {
646 //
647 // Save off the current trim settings (but don't change any settings).
648 //
649 setBuckZX(0, 0, SETBUCKZX_SAVE_CURR_SETTINGS | SETBUCKZX_RESTORE_BOTH);
650
651 //
652 // The timer number will be maintained as (n + 1). Therefore, a value
653 // of 0 saved in the global is an invalid timer. 1=timer0, 2=timer1...
654 //
655 g_ui32BuckTimer = ui32BuckTimerNumber + 1;
656
657 //
658 // Register the timer ISRs
659 //
660 am_hal_ctimer_int_register( AM_HAL_CTIMER_INT_TIMERA0C0 <<
661 (ui32BuckTimerNumber * 2),
662 am_hal_sysctrl_buckA_ctimer_isr );
663
664 am_hal_ctimer_int_register( AM_HAL_CTIMER_INT_TIMERB0C0 <<
665 (ui32BuckTimerNumber * 2),
666 am_hal_sysctrl_buckB_ctimer_isr );
667
668 //
669 // Determine which timer input (A or B) is core buck and which is mem
670 // buck based on the timer number.
671 // For CTIMER 0 & 1: Timer A is mem buck, Timer B is core buck
672 // For CTIMER 2 & 3: Timer A is core buck, Timer B is mem buck
673 //
674 if ( (ui32BuckTimerNumber == 0) || (ui32BuckTimerNumber == 1) )
675 {
676 //
677 // Indicate that TimerB is core buck.
678 //
679 g_ui32CoreBuck = COREBUCK_TIMERB;
680 }
681 else
682 {
683 //
684 // Indicate that TimerA is core buck
685 //
686 g_ui32CoreBuck = COREBUCK_TIMERA;
687 }
688
689 //
690 // Clear and configure the timers
691 //
692 am_hal_ctimer_clear(ui32BuckTimerNumber, AM_HAL_CTIMER_BOTH);
693
694 am_hal_ctimer_config(ui32BuckTimerNumber,
695 (am_hal_ctimer_config_t*)&g_sBuckTimer);
696
697 //
698 // Enable the interrupts for timers A and B
699 //
700 am_hal_ctimer_int_enable( (AM_HAL_CTIMER_INT_TIMERA0C0 |
701 AM_HAL_CTIMER_INT_TIMERB0C0 ) <<
702 (ui32BuckTimerNumber * 2) );
703
704 //
705 // Enable the timer interrupt in the NVIC.
706 //
707 am_hal_interrupt_enable(AM_HAL_INTERRUPT_CTIMER);
708 }
709
710 return ui32RetVal;
711 }
712
713 //*****************************************************************************
714 //
715 // Get buck update complete status.
716 //
717 //*****************************************************************************
718 bool
am_hal_sysctrl_buck_update_complete(void)719 am_hal_sysctrl_buck_update_complete(void)
720 {
721 return g_bBuckRestoreComplete;
722 }
723
724 //*****************************************************************************
725 //
726 // Buck CTIMER ISR (for handling buck switching via TimerA).
727 //
728 // Note: This handler assumes that the interrupt is cleared in am_ctimer_isr().
729 //
730 //*****************************************************************************
731 static void
am_hal_sysctrl_buckA_ctimer_isr(void)732 am_hal_sysctrl_buckA_ctimer_isr(void)
733 {
734 //
735 // Begin critical section.
736 // Although a relatively long time, the following 2us delay is critically
737 // timed for re-trimming the buck and thus cannot be extended. Therefore,
738 // we must keep it inside the critical section.
739 //
740 AM_CRITICAL_BEGIN_ASM
741
742 //
743 // Delay for 2us.
744 //
745 am_hal_flash_delay( FLASH_CYCLES_US(2) );
746
747 //
748 // Determine which buck (core or mem) needs to be updated.
749 //
750 if ( g_ui32CoreBuck == COREBUCK_TIMERA )
751 {
752 //
753 // Timer A buck signal is the CORE buck.
754 // Restore the core buck.
755 //
756 setBuckZX(0, 0, SETBUCKZX_RESTORE_CORE_ONLY |
757 SETBUCKZX_USE_SAVED_SETTINGS );
758 }
759 else
760 {
761 //
762 // Timer A buck signal is the MEM buck.
763 // Restore the mem buck.
764 //
765 setBuckZX(0, 0, SETBUCKZX_RESTORE_MEM_ONLY |
766 SETBUCKZX_USE_SAVED_SETTINGS );
767 }
768
769 g_ui32BuckInputs |= 0x1;
770
771 if ( g_ui32BuckInputs == 0x3 )
772 {
773 g_bBuckRestoreComplete = true;
774 g_ui32BuckInputs = 0;
775 }
776
777 //
778 // End critical section.
779 //
780 AM_CRITICAL_END_ASM
781 }
782
783 //*****************************************************************************
784 //
785 // Buck CTIMER ISR (for handling buck switching via TimerB).
786 //
787 // Note: This handler assumes that the interrupt is cleared in am_ctimer_isr().
788 //
789 //*****************************************************************************
790 static void
am_hal_sysctrl_buckB_ctimer_isr(void)791 am_hal_sysctrl_buckB_ctimer_isr(void)
792 {
793 //
794 // Begin critical section.
795 // Although a relatively long time, the following 2us delay is critically
796 // timed for re-trimming the buck and thus cannot be extended. Therefore,
797 // we must keep it inside the critical section.
798 //
799 AM_CRITICAL_BEGIN_ASM
800
801 //
802 // Delay for 2us.
803 //
804 am_hal_flash_delay( FLASH_CYCLES_US(2) );
805
806 //
807 // Determine which buck (core or mem) needs to be updated.
808 //
809 if ( g_ui32CoreBuck == COREBUCK_TIMERB )
810 {
811 //
812 // Timer B buck signal is the CORE buck.
813 // Restore the core buck.
814 //
815 setBuckZX(0, 0, SETBUCKZX_RESTORE_CORE_ONLY |
816 SETBUCKZX_USE_SAVED_SETTINGS );
817 }
818 else
819 {
820 //
821 // Timer B buck signal is the MEM buck.
822 // Restore the mem buck.
823 //
824 setBuckZX(0, 0, SETBUCKZX_RESTORE_MEM_ONLY |
825 SETBUCKZX_USE_SAVED_SETTINGS );
826 }
827
828 g_ui32BuckInputs |= 0x2;
829
830 if ( g_ui32BuckInputs == 0x3 )
831 {
832 g_bBuckRestoreComplete = true;
833 g_ui32BuckInputs = 0;
834 }
835
836 //
837 // End critical section.
838 //
839 AM_CRITICAL_END_ASM
840 }
841
842 //*****************************************************************************
843 //
844 // End Doxygen group.
845 //! @}
846 //
847 //*****************************************************************************
848