vos/ambiq-hal-sys/ambiq-sparkfun-sdk/mcu/apollo2/hal/am_hal_sysctrl.c
2022-10-23 23:45:43 -07:00

883 lines
28 KiB
C

//*****************************************************************************
//
// am_hal_sysctrl.c
//! @file
//!
//! @brief Functions for interfacing with the M4F system control registers
//!
//! @addtogroup sysctrl2 System Control (SYSCTRL)
//! @ingroup apollo2hal
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2020, Ambiq Micro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// Third party software included in this distribution is subject to the
// additional license terms as defined in the /docs/licenses directory.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include "am_mcu_apollo.h"
//*****************************************************************************
//
// Local macro constants
//
//*****************************************************************************
//
// Define ZX workaround values.
// These values are defined by the factory.
//
#define COREZXVALUE 0x07
#define MEMZXVALUE 0x07
//
// Define values for g_ui32CoreBuck, which indicates which timer carries
// the signal for the CORE Buck, and which also implies that the other timer
// carries the signal for the MEM buck.
//
#define COREBUCK_TIMERA 1 // Core buck signal comes in on timer A
#define COREBUCK_TIMERB 2 // Core buck signal comes in on timer B
//
// Define the bit values for static function g_buckZX_chk;
//
#define CHKBUCKZX_BUCKS 0x01 // The bucks are enabled
#define CHKBUCKZX_REV 0x02 // This chip rev needs the workaround
#define CHKBUCKZX_TIMER 0x04 // A valid timer has been allocated
#define CHKBUCKZX_DEVEN 0x08 // Devices are powered up and enabled
//*****************************************************************************
//
// Prototypes
//
//*****************************************************************************
static void am_hal_sysctrl_buckA_ctimer_isr(void);
static void am_hal_sysctrl_buckB_ctimer_isr(void);
//*****************************************************************************
//
// Globals
//
//*****************************************************************************
static volatile uint32_t g_ui32BuckTimer = 0;
static volatile uint32_t g_ui32BuckInputs = 0;
static volatile bool g_bBuckRestoreComplete = false;
static volatile bool g_bBuckTimed = false;
static uint32_t g_ui32SaveCoreBuckZX, g_ui32SaveMemBuckZX;
static uint32_t g_buckZX_chk = 0;
static volatile uint32_t g_ui32CoreBuck;
//
// Timer configuration for BUCK inputs.
//
static const am_hal_ctimer_config_t g_sBuckTimer =
{
// Don't link timers.
0,
// Set up Timer0A.
(AM_HAL_CTIMER_FN_ONCE |
AM_HAL_CTIMER_INT_ENABLE |
AM_HAL_CTIMER_BUCK),
// Set up Timer0B.
(AM_HAL_CTIMER_FN_ONCE |
AM_HAL_CTIMER_INT_ENABLE |
AM_HAL_CTIMER_BUCK),
};
//*****************************************************************************
//
// Determine if we need to do the zero cross workaround on this device.
// Three criteria are used. All three must be true.
// 1. Are the bucks enabled?
// 2. Is the chip rev appropriate for the workaround?
// 3. Has a timer been allocated to do the workaround?
// 4. Are certain peripherals powered up?
//
// Saves the bitmask to the global g_buckZX_chk.
// Bitmask bits are defined as: CHKBUCKZX_BUCKS, CHKBUCKZX_REV, CHKBUCKZX_TIMER.
//
// Returns true if all criteria are met, false otherwise.
// g_buckZX_chk can be probed to determine which criteria passed or failed.
//
//*****************************************************************************
static bool
buckZX_chk(void)
{
uint32_t ui32SupplySrc;
//
// Is this chip rev appropriate to do the workaround?
//
g_buckZX_chk = AM_BFM(MCUCTRL, CHIPREV, REVMAJ) == AM_REG_MCUCTRL_CHIPREV_REVMAJ_B ?
CHKBUCKZX_REV : 0x0;
//
// Has a timer been configured to handle the workaround?
//
g_buckZX_chk |= ( g_ui32BuckTimer - 1 ) <= BUCK_TIMER_MAX ?
CHKBUCKZX_TIMER : 0x0;
//
// Are either or both of the bucks actually enabled?
//
ui32SupplySrc = AM_REG(PWRCTRL, SUPPLYSRC);
g_buckZX_chk |= (ui32SupplySrc &
(AM_REG_PWRCTRL_SUPPLYSRC_COREBUCKEN_M |
AM_REG_PWRCTRL_SUPPLYSRC_MEMBUCKEN_M) ) ?
CHKBUCKZX_BUCKS : 0x0;
//
// Finally, if any peripheral (other than ADC-only) is already powered up,
// we don't need to do the ZX workaround because in this case the bucks
// remain in active mode.
// If ONLY the ADC is powered up (and no other peripherals), a case occurs
// which is complex to handle. However it can also be completely handled
// via the ZX workaround, so that case is also checked at this point.
// For more information on both issues see erratum ERR010 and ERR019.
//
ui32SupplySrc = AM_REG(PWRCTRL, DEVICEEN);
g_buckZX_chk |= ( ui32SupplySrc &
(AM_REG_PWRCTRL_DEVICEEN_PWRPDM_M |
AM_REG_PWRCTRL_DEVICEEN_PWRUART1_M |
AM_REG_PWRCTRL_DEVICEEN_PWRUART0_M |
AM_REG_PWRCTRL_DEVICEEN_IO_MASTER5_M |
AM_REG_PWRCTRL_DEVICEEN_IO_MASTER4_M |
AM_REG_PWRCTRL_DEVICEEN_IO_MASTER3_M |
AM_REG_PWRCTRL_DEVICEEN_IO_MASTER2_M |
AM_REG_PWRCTRL_DEVICEEN_IO_MASTER1_M |
AM_REG_PWRCTRL_DEVICEEN_IO_MASTER0_M |
AM_REG_PWRCTRL_DEVICEEN_IO_SLAVE_M) ) ?
0x0 : CHKBUCKZX_DEVEN;
//
// If all 4 criteria were met, we're good to do the workaround.
//
return ( g_buckZX_chk ==
(CHKBUCKZX_BUCKS | CHKBUCKZX_REV |
CHKBUCKZX_TIMER | CHKBUCKZX_DEVEN) ) ? true : false;
}
//*****************************************************************************
//
// Set the buck zero cross settings to the values given.
//
// ui32Flags, one or more of the following:
// SETBUCKZX_USE_PROVIDED_SETTINGS - Use the values provided in the parameters
// to set the trim value(s).
// SETBUCKZX_USE_SAVED_SETTINGS - Use the values that were previously saved
// to set the trim value(s).
// SETBUCKZX_SAVE_CURR_SETTINGS - Save the current trim values before
// setting the new ones.
// SETBUCKZX_RESTORE_CORE_ONLY - Restore the Core trim and save the current
// value of the core buck trim iff
// SETBUCKZX_SAVE_CURR_SETTINGS is set.
// SETBUCKZX_RESTORE_MEM_ONLY - Restore the Mem trim and save the current
// value of the mem buck trim iff
// SETBUCKZX_SAVE_CURR_SETTINGS is set.
// SETBUCKZX_RESTORE_BOTH - Restore both buck trims and save the
// current value of both iff
// SETBUCKZX_SAVE_CURR_SETTINGS is set.
//
//*****************************************************************************
#define SETBUCKZX_USE_PROVIDED_SETTINGS 0x01
#define SETBUCKZX_USE_SAVED_SETTINGS 0x02
#define SETBUCKZX_SAVE_CURR_SETTINGS 0x04
#define SETBUCKZX_RESTORE_CORE_ONLY 0x10
#define SETBUCKZX_RESTORE_MEM_ONLY 0x20
#define SETBUCKZX_RESTORE_BOTH ( SETBUCKZX_RESTORE_CORE_ONLY | \
SETBUCKZX_RESTORE_MEM_ONLY )
static void
setBuckZX(uint32_t ui32CoreBuckZX, uint32_t ui32MemBuckZX, uint32_t ui32Flags)
{
uint32_t ui32SaveCore, ui32SaveMem, ui32NewCore, ui32NewMem;
bool bDoRestore = false;
//
// Begin critical section.
//
AM_CRITICAL_BEGIN
//
// Get the current zero cross trim values.
//
ui32SaveCore = AM_BFR(MCUCTRL, BUCK3, COREBUCKZXTRIM);
ui32SaveMem = AM_BFR(MCUCTRL, BUCK3, MEMBUCKZXTRIM);
//
// Determine which values will be restored.
//
if ( ui32Flags & SETBUCKZX_USE_SAVED_SETTINGS )
{
//
// Use saved settings
//
ui32NewCore = g_ui32SaveCoreBuckZX;
ui32NewMem = g_ui32SaveMemBuckZX;
bDoRestore = true;
}
else if ( ui32Flags & SETBUCKZX_USE_PROVIDED_SETTINGS )
{
//
// Use settings provided in the call parameters
//
ui32NewCore = ui32CoreBuckZX;
ui32NewMem = ui32MemBuckZX;
bDoRestore = true;
}
//
// Restore the buck Core and Mem trim registers.
//
if ( bDoRestore )
{
if ( ui32Flags & SETBUCKZX_RESTORE_CORE_ONLY )
{
AM_BFW(MCUCTRL, BUCK3, COREBUCKZXTRIM, ui32NewCore);
}
if ( ui32Flags & SETBUCKZX_RESTORE_MEM_ONLY )
{
AM_BFW(MCUCTRL, BUCK3, MEMBUCKZXTRIM, ui32NewMem);
}
}
if ( ui32Flags & SETBUCKZX_SAVE_CURR_SETTINGS )
{
//
// Save off the zero cross values as read on entry to the function.
//
if ( ui32Flags & SETBUCKZX_RESTORE_CORE_ONLY )
{
g_ui32SaveCoreBuckZX = ui32SaveCore;
}
if ( ui32Flags & SETBUCKZX_RESTORE_MEM_ONLY )
{
g_ui32SaveMemBuckZX = ui32SaveMem;
}
}
//
// Done with critical section.
//
AM_CRITICAL_END
}
//*****************************************************************************
//
//! @brief Place the core into sleep or deepsleep.
//!
//! @param bSleepDeep - False for Normal or True Deep sleep.
//!
//! This function puts the MCU to sleep or deepsleep depending on bSleepDeep.
//!
//! Valid values for bSleepDeep are:
//!
//! AM_HAL_SYSCTRL_SLEEP_NORMAL
//! AM_HAL_SYSCTRL_SLEEP_DEEP
//!
//! @return None.
//
//*****************************************************************************
void
am_hal_sysctrl_sleep(bool bSleepDeep)
{
uint32_t ui32Critical;
// uint32_t ui32DebugGpioSleep = g_ui32DebugGpioSleep - 1;
bool bBuckZX_chk;
volatile uint32_t ui32BuckTimer;
//
// Disable interrupts and save the previous interrupt state.
//
ui32Critical = am_hal_interrupt_master_disable();
//
// If the user selected DEEPSLEEP and the TPIU is off, attempt to enter
// DEEP SLEEP.
//
if ((bSleepDeep == AM_HAL_SYSCTRL_SLEEP_DEEP) &&
(AM_BFM(MCUCTRL, TPIUCTRL, ENABLE) == AM_REG_MCUCTRL_TPIUCTRL_ENABLE_DIS))
{
//
// Prepare the core for deepsleep (write 1 to the DEEPSLEEP bit).
//
AM_BFW(SYSCTRL, SCR, SLEEPDEEP, 1);
//
// Check if special buck handling is needed
//
bBuckZX_chk = buckZX_chk();
if ( bBuckZX_chk )
{
ui32BuckTimer = g_ui32BuckTimer - 1;
//
// Before going to sleep, clear the buck timers.
// This will also handle the case where we're going back to
// sleep before the buck sequence has even completed.
//
am_hal_ctimer_clear(ui32BuckTimer, AM_HAL_CTIMER_BOTH);
//
// Set CMPR0 of both timerA and timerB to the period value
//
#define TIMER_PERIOD_BUCKS 1
am_hal_ctimer_period_set(ui32BuckTimer,
AM_HAL_CTIMER_BOTH,
TIMER_PERIOD_BUCKS |
(TIMER_PERIOD_BUCKS << 16),
0);
//
// Disable bucks before going to sleep.
//
am_hal_pwrctrl_bucks_disable();
}
//
// Before executing WFI, flush any buffered core and peripheral writes.
//
AM_ASM_DSB
//
// Execute the sleep instruction.
//
AM_ASM_WFI;
//
// Upon wake, execute the Instruction Sync Barrier instruction.
//
AM_ASM_ISB
//
// Return from sleep
//
if ( bBuckZX_chk )
{
//
// Adjust the core and mem trims
//
setBuckZX(COREZXVALUE, MEMZXVALUE,
SETBUCKZX_USE_PROVIDED_SETTINGS |
SETBUCKZX_RESTORE_BOTH );
//
// Delay for 2us before enabling bucks.
//
am_hal_flash_delay( FLASH_CYCLES_US(2) );
//
// Turn on the bucks
//
am_hal_pwrctrl_bucks_enable();
//
// Get the actual timer number
//
ui32BuckTimer = g_ui32BuckTimer - 1;
//
// Initialize the complete flag
//
g_bBuckRestoreComplete = false;
//
// Initialize the input flags
//
g_ui32BuckInputs = 0;
//
// Delay for 5us to make sure we're receiving clean buck signals.
//
am_hal_flash_delay( FLASH_CYCLES_US(5) );
//
// Start timers (set the enable bit, clear the clear bit)
//
am_hal_ctimer_start(ui32BuckTimer, AM_HAL_CTIMER_BOTH);
}
else
{
//
// Since we're not doing anything, we're done, so set the done flag.
//
g_bBuckRestoreComplete = true;
}
}
else
{
//
// Prepare the core for normal sleep (write 0 to the DEEPSLEEP bit).
//
AM_BFW(SYSCTRL, SCR, SLEEPDEEP, 0);
//
// Before executing WFI, flush any buffered core and peripheral writes.
//
AM_ASM_DSB
//
// Go to sleep.
//
AM_ASM_WFI;
//
// Upon wake, execute the Instruction Sync Barrier instruction.
//
AM_ASM_ISB
}
//
// Restore the interrupt state.
//
am_hal_interrupt_master_set(ui32Critical);
}
//*****************************************************************************
//
//! @brief Enable the floating point module.
//!
//! Call this function to enable the ARM hardware floating point module.
//!
//! @return None.
//
//*****************************************************************************
void
am_hal_sysctrl_fpu_enable(void)
{
//
// Enable access to the FPU in both privileged and user modes.
// NOTE: Write 0s to all reserved fields in this register.
//
AM_REG(SYSCTRL, CPACR) = (AM_REG_SYSCTRL_CPACR_CP11(0x3) |
AM_REG_SYSCTRL_CPACR_CP10(0x3));
}
//*****************************************************************************
//
//! @brief Disable the floating point module.
//!
//! Call this function to disable the ARM hardware floating point module.
//!
//! @return None.
//
//*****************************************************************************
void
am_hal_sysctrl_fpu_disable(void)
{
//
// Disable access to the FPU in both privileged and user modes.
// NOTE: Write 0s to all reserved fields in this register.
//
AM_REG(SYSCTRL, CPACR) = 0x00000000 &
~(AM_REG_SYSCTRL_CPACR_CP11(0x3) |
AM_REG_SYSCTRL_CPACR_CP10(0x3));
}
//*****************************************************************************
//
//! @brief Enable stacking of FPU registers on exception entry.
//!
//! @param bLazy - Set to "true" to enable "lazy stacking".
//!
//! This function allows the core to save floating-point information to the
//! stack on exception entry. Setting the bLazy option enables "lazy stacking"
//! for interrupt handlers. Normally, mixing floating-point code and interrupt
//! driven routines causes increased interrupt latency, because the core must
//! save extra information to the stack upon exception entry. With the lazy
//! stacking option enabled, the core will skip the saving of floating-point
//! registers when possible, reducing average interrupt latency.
//!
//! @note At reset of the Cortex M4, the ASPEN and LSPEN bits are set to 1,
//! enabling Lazy mode by default. Therefore this function will generally
//! only have an affect when setting for full-context save (or when switching
//! from full-context to lazy mode).
//!
//! @note See also:
//! infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0298a/DAFGGBJD.html
//!
//! @note Three valid FPU context saving modes are possible.
//! 1. Lazy ASPEN=1 LSPEN=1 am_hal_sysctrl_fpu_stacking_enable(true)
//! and default.
//! 2. Full-context ASPEN=1 LSPEN=0 am_hal_sysctrl_fpu_stacking_enable(false)
//! 3. No FPU state ASPEN=0 LSPEN=0 am_hal_sysctrl_fpu_stacking_disable()
//! 4. Invalid ASPEN=0 LSPEN=1
//!
//! @return None.
//
//*****************************************************************************
void
am_hal_sysctrl_fpu_stacking_enable(bool bLazy)
{
#define SYSCTRL_FPCCR_LAZY (AM_REG_SYSCTRL_FPCCR_ASPEN_M | AM_REG_SYSCTRL_FPCCR_LSPEN_M)
uint32_t ui32fpccr;
//
// Set the requested FPU stacking mode in ISRs.
//
AM_CRITICAL_BEGIN
ui32fpccr = AM_REG(SYSCTRL, FPCCR);
ui32fpccr &= ~(SYSCTRL_FPCCR_LAZY);
ui32fpccr |= (bLazy ? SYSCTRL_FPCCR_LAZY : AM_REG_SYSCTRL_FPCCR_ASPEN_M);
AM_REG(SYSCTRL, FPCCR) = ui32fpccr;
AM_CRITICAL_END
}
//*****************************************************************************
//
//! @brief Disable FPU register stacking on exception entry.
//!
//! This function disables all stacking of floating point registers for
//! interrupt handlers. This mode should only be used when it is absolutely
//! known that no FPU instructions will be executed in an ISR.
//!
//! @return None.
//
//*****************************************************************************
void
am_hal_sysctrl_fpu_stacking_disable(void)
{
//
// Completely disable FPU context save on entry to ISRs.
//
AM_CRITICAL_BEGIN
AM_REG(SYSCTRL, FPCCR) &= ~SYSCTRL_FPCCR_LAZY;
AM_CRITICAL_END
}
//*****************************************************************************
//
//! @brief Issue a system wide reset using the AIRCR bit in the M4 system ctrl.
//!
//! This function issues a system wide reset (Apollo POR level reset).
//!
//! @return None.
//
//*****************************************************************************
void
am_hal_sysctrl_aircr_reset(void)
{
//
// Set the system reset bit in the AIRCR register
//
AM_REG(SYSCTRL, AIRCR) = AM_REG_SYSCTRL_AIRCR_VECTKEY(0x5FA) |
AM_REG_SYSCTRL_AIRCR_SYSRESETREQ(1);
}
//*****************************************************************************
//
//! @brief Buck CTimer ISR initializer.
//!
//! @param ui32BuckTimerNumber - Timer number to be used for handling the buck.
//! Must be 0-3.
//!
//! If called with an invalid timer (that is, not 0 - 3, or greater than
//! BUCK_TIMER_MAX), then the workaround will not be enabled.
//!
//! Instead, the bucks will be initialized with a value that will avoid the
//! issues described in the Errata (ERR019). However, this will cause a
//! less efficient energy usage condtion.
//!
//! @return 0.
//
//*****************************************************************************
uint32_t
am_hal_sysctrl_buck_ctimer_isr_init(uint32_t ui32BuckTimerNumber)
{
uint32_t ui32RetVal = 0;
//
// Initialize the input flags
//
g_ui32BuckInputs = 0;
//
// Initialize operation complete flag
//
g_bBuckRestoreComplete = false;
//
// Initialize to assume there is no valid timer.
//
g_ui32BuckTimer = 0;
if ( ui32BuckTimerNumber > BUCK_TIMER_MAX )
{
if ( ( ui32BuckTimerNumber & 0xFFFF0000 ) ==
AM_HAL_SYSCTRL_BUCK_CTIMER_ZX_CONSTANT )
{
//
// The caller is asking for the hard option, which changes the
// settings to the more noise-immune, if less efficient, settings.
// While we're at it, go ahead and save off the current settings.
//
if ( (ui32BuckTimerNumber & 0x0000FFFF) == 0 )
{
setBuckZX(COREZXVALUE, MEMZXVALUE,
SETBUCKZX_USE_PROVIDED_SETTINGS |
SETBUCKZX_SAVE_CURR_SETTINGS |
SETBUCKZX_RESTORE_BOTH );
}
else
{
uint32_t ui32Core, ui32Mem;
//
// Use the setting provided in the parameter.
//
ui32Core = (((ui32BuckTimerNumber & 0x001F) >> 0) - 1) & 0xF;
ui32Mem = (((ui32BuckTimerNumber & 0x1F00) >> 8) - 1) & 0xF;
setBuckZX(ui32Core, ui32Mem,
SETBUCKZX_USE_PROVIDED_SETTINGS |
SETBUCKZX_SAVE_CURR_SETTINGS |
SETBUCKZX_RESTORE_BOTH );
}
}
}
else
{
//
// Save off the current trim settings (but don't change any settings).
//
setBuckZX(0, 0, SETBUCKZX_SAVE_CURR_SETTINGS | SETBUCKZX_RESTORE_BOTH);
//
// The timer number will be maintained as (n + 1). Therefore, a value
// of 0 saved in the global is an invalid timer. 1=timer0, 2=timer1...
//
g_ui32BuckTimer = ui32BuckTimerNumber + 1;
//
// Register the timer ISRs
//
am_hal_ctimer_int_register( AM_HAL_CTIMER_INT_TIMERA0C0 <<
(ui32BuckTimerNumber * 2),
am_hal_sysctrl_buckA_ctimer_isr );
am_hal_ctimer_int_register( AM_HAL_CTIMER_INT_TIMERB0C0 <<
(ui32BuckTimerNumber * 2),
am_hal_sysctrl_buckB_ctimer_isr );
//
// Determine which timer input (A or B) is core buck and which is mem
// buck based on the timer number.
// For CTIMER 0 & 1: Timer A is mem buck, Timer B is core buck
// For CTIMER 2 & 3: Timer A is core buck, Timer B is mem buck
//
if ( (ui32BuckTimerNumber == 0) || (ui32BuckTimerNumber == 1) )
{
//
// Indicate that TimerB is core buck.
//
g_ui32CoreBuck = COREBUCK_TIMERB;
}
else
{
//
// Indicate that TimerA is core buck
//
g_ui32CoreBuck = COREBUCK_TIMERA;
}
//
// Clear and configure the timers
//
am_hal_ctimer_clear(ui32BuckTimerNumber, AM_HAL_CTIMER_BOTH);
am_hal_ctimer_config(ui32BuckTimerNumber,
(am_hal_ctimer_config_t*)&g_sBuckTimer);
//
// Enable the interrupts for timers A and B
//
am_hal_ctimer_int_enable( (AM_HAL_CTIMER_INT_TIMERA0C0 |
AM_HAL_CTIMER_INT_TIMERB0C0 ) <<
(ui32BuckTimerNumber * 2) );
//
// Enable the timer interrupt in the NVIC.
//
am_hal_interrupt_enable(AM_HAL_INTERRUPT_CTIMER);
}
return ui32RetVal;
}
//*****************************************************************************
//
// Get buck update complete status.
//
//*****************************************************************************
bool
am_hal_sysctrl_buck_update_complete(void)
{
return g_bBuckRestoreComplete;
}
//*****************************************************************************
//
// Buck CTIMER ISR (for handling buck switching via TimerA).
//
// Note: This handler assumes that the interrupt is cleared in am_ctimer_isr().
//
//*****************************************************************************
static void
am_hal_sysctrl_buckA_ctimer_isr(void)
{
//
// Begin critical section.
// Although a relatively long time, the following 2us delay is critically
// timed for re-trimming the buck and thus cannot be extended. Therefore,
// we must keep it inside the critical section.
//
AM_CRITICAL_BEGIN
//
// Delay for 2us.
//
am_hal_flash_delay( FLASH_CYCLES_US(2) );
//
// Determine which buck (core or mem) needs to be updated.
//
if ( g_ui32CoreBuck == COREBUCK_TIMERA )
{
//
// Timer A buck signal is the CORE buck.
// Restore the core buck.
//
setBuckZX(0, 0, SETBUCKZX_RESTORE_CORE_ONLY |
SETBUCKZX_USE_SAVED_SETTINGS );
}
else
{
//
// Timer A buck signal is the MEM buck.
// Restore the mem buck.
//
setBuckZX(0, 0, SETBUCKZX_RESTORE_MEM_ONLY |
SETBUCKZX_USE_SAVED_SETTINGS );
}
g_ui32BuckInputs |= 0x1;
if ( g_ui32BuckInputs == 0x3 )
{
g_bBuckRestoreComplete = true;
g_ui32BuckInputs = 0;
}
//
// End critical section.
//
AM_CRITICAL_END
}
//*****************************************************************************
//
// Buck CTIMER ISR (for handling buck switching via TimerB).
//
// Note: This handler assumes that the interrupt is cleared in am_ctimer_isr().
//
//*****************************************************************************
static void
am_hal_sysctrl_buckB_ctimer_isr(void)
{
//
// Begin critical section.
// Although a relatively long time, the following 2us delay is critically
// timed for re-trimming the buck and thus cannot be extended. Therefore,
// we must keep it inside the critical section.
//
AM_CRITICAL_BEGIN
//
// Delay for 2us.
//
am_hal_flash_delay( FLASH_CYCLES_US(2) );
//
// Determine which buck (core or mem) needs to be updated.
//
if ( g_ui32CoreBuck == COREBUCK_TIMERB )
{
//
// Timer B buck signal is the CORE buck.
// Restore the core buck.
//
setBuckZX(0, 0, SETBUCKZX_RESTORE_CORE_ONLY |
SETBUCKZX_USE_SAVED_SETTINGS );
}
else
{
//
// Timer B buck signal is the MEM buck.
// Restore the mem buck.
//
setBuckZX(0, 0, SETBUCKZX_RESTORE_MEM_ONLY |
SETBUCKZX_USE_SAVED_SETTINGS );
}
g_ui32BuckInputs |= 0x2;
if ( g_ui32BuckInputs == 0x3 )
{
g_bBuckRestoreComplete = true;
g_ui32BuckInputs = 0;
}
//
// End critical section.
//
AM_CRITICAL_END
}
//*****************************************************************************
//
// End Doxygen group.
//! @}
//
//*****************************************************************************