summaryrefslogtreecommitdiff
path: root/bsp/apollo2/libraries/drivers/hal
diff options
context:
space:
mode:
authorlin <[email protected]>2017-09-15 18:10:51 +0800
committerlin <[email protected]>2017-09-15 18:10:51 +0800
commitc19fb2ab58d0ea77263a5eafa28fe2cf6ca9dec6 (patch)
tree57bc0303655afa55ae17dfbd2c0c72ae11432200 /bsp/apollo2/libraries/drivers/hal
parent7b4e7224e4fba7080c33ebf11b45dc9b093a73d6 (diff)
Add bsp apollo2
Diffstat (limited to 'bsp/apollo2/libraries/drivers/hal')
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_adc.c553
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_adc.h348
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.c576
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.h211
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.c491
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.h206
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.c1687
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.h278
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_debug.c81
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_debug.h89
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_flash.c1449
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_flash.h297
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_global.c59
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_global.h114
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_gpio.c503
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_gpio.h684
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.c757
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.h100
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.c407
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.h159
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_iom.c4426
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_iom.h559
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_ios.c1303
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_ios.h362
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_itm.c453
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_itm.h107
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.c292
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.h212
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_otp.c173
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_otp.h108
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_pdm.c158
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_pdm.h665
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_pin.h557
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.c558
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.h342
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_queue.c286
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_queue.h123
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_reset.c160
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_reset.h119
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_rtc.c678
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_rtc.h185
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_stimer.c525
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_stimer.h242
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.c851
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.h119
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_systick.c453
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_systick.h83
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.c381
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.h193
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_ttp.c205
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_ttp.h72
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_uart.c1160
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_uart.h345
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.c287
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.h176
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_wdt.c454
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_wdt.h184
57 files changed, 26605 insertions, 0 deletions
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_adc.c b/bsp/apollo2/libraries/drivers/hal/am_hal_adc.c
new file mode 100644
index 0000000000..957408d0e5
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_adc.c
@@ -0,0 +1,553 @@
+//*****************************************************************************
+//
+// am_hal_adc.c
+//! @file
+//!
+//! @brief Functions for interfacing with the Analog to Digital Converter.
+//!
+//! @addtogroup adc2 Analog-to-Digital Converter (ADC)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Private SRAM view of temperature trims.
+//!
+//! This static SRAM union is private to the ADC HAL functions.
+//
+//*****************************************************************************
+static union
+{
+ //! These trim values are loaded as uint32_t values.
+ struct
+ {
+ //! Temperature of the package test head (in degrees Kelvin)
+ uint32_t ui32CalibrationTemperature;
+
+ //! Voltage corresponding to temperature measured on test head.
+ uint32_t ui32CalibrationVoltage;
+
+ //! ADC offset voltage measured on the package test head.
+ uint32_t ui32CalibrationOffset;
+
+ //! Flag if default (guess) or measured.
+ bool bMeasured;
+ } ui32;
+ //! These trim values are accessed as floats when used in temp calculations.
+ struct
+ {
+ //! Temperature of the package test head in degrees Kelvin
+ float fCalibrationTemperature;
+
+ //! Voltage corresponding to temperature measured on test head.
+ float fCalibrationVoltage;
+
+ //! ADC offset voltage measured on the package test head.
+ float fCalibrationOffset;
+
+ //! Flag if default (guess) or measured.
+ float fMeasuredFlag;
+ } flt;
+} priv_temp_trims;
+
+//*****************************************************************************
+//
+//! @brief Configure the ADC.
+//!
+//! @param psConfig - pointer to the configuration structure for the ADC.
+//!
+//! This function may be used to perform the initial setup of the ADC based on
+//! setting found in a configuration structure.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_config(am_hal_adc_config_t *psConfig)
+{
+ //
+ // Set general ADC configuration parameters.
+ //
+ AM_REG(ADC, CFG) = (psConfig->ui32Clock |
+ psConfig->ui32TriggerConfig |
+ psConfig->ui32Reference |
+ psConfig->ui32ClockMode |
+ psConfig->ui32PowerMode |
+ psConfig->ui32Repeat |
+ AM_REG_ADC_CFG_ADCEN(1));
+
+ //
+ // Grab the temperature trims.
+ //
+ priv_temp_trims.ui32.ui32CalibrationTemperature =
+ am_hal_flash_load_ui32(AM_HAL_ADC_CALIB_TEMP_ADDR);
+ priv_temp_trims.ui32.ui32CalibrationVoltage =
+ am_hal_flash_load_ui32(AM_HAL_ADC_CALIB_AMBIENT_ADDR);
+ priv_temp_trims.ui32.ui32CalibrationOffset =
+ am_hal_flash_load_ui32(AM_HAL_ADC_CALIB_ADC_OFFSET_ADDR);
+
+ if ( (priv_temp_trims.ui32.ui32CalibrationTemperature == 0xffffffff) ||
+ (priv_temp_trims.ui32.ui32CalibrationVoltage == 0xffffffff) ||
+ (priv_temp_trims.ui32.ui32CalibrationOffset == 0xffffffff) )
+ {
+ //
+ // Since the device has not been calibrated on the tester, we'll load
+ // default calibration values. These default values should result
+ // in worst-case temperature measurements of +-6 degress C.
+ //
+ priv_temp_trims.flt.fCalibrationTemperature = AM_HAL_ADC_CALIB_TEMP_DEFAULT;
+ priv_temp_trims.flt.fCalibrationVoltage = AM_HAL_ADC_CALIB_AMBIENT_DEFAULT;
+ priv_temp_trims.flt.fCalibrationOffset = AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT;
+ priv_temp_trims.ui32.bMeasured = false;
+ }
+ else
+ {
+ priv_temp_trims.ui32.bMeasured = true;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Get the temperature trim parameters after configuring the ADC.
+//!
+//! @param pfTemp - pointer to a location to store the calibration temperature.
+//! @param pfVoltage - pointer to a location to store the calibration voltage.
+//! @param pfOffsetV - pointer to a location to store the calibration offset.
+//!
+//! This function may be used to access the actual temperature sensor trim
+//! values from the private structure.
+//!
+//! WARNING: only call this after the ADC has been configured with
+//! am_hal_adc_config.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_temp_trims_get(float * pfTemp, float * pfVoltage, float * pfOffsetV)
+{
+ //
+ // Return trim temperature as a float, if you can.
+ //
+ if ( pfTemp != NULL )
+ {
+ *pfTemp = priv_temp_trims.flt.fCalibrationTemperature;
+ }
+
+ //
+ // Return trim voltage as a float, if you can.
+ //
+ if ( pfVoltage != NULL )
+ {
+ *pfVoltage = priv_temp_trims.flt.fCalibrationVoltage;
+ }
+
+ //
+ // Return trim ADC offset voltage as a float, if you can.
+ //
+ if ( pfOffsetV != NULL )
+ {
+ *pfOffsetV = priv_temp_trims.flt.fCalibrationOffset;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Set the ADC window parameters.
+//!
+//! @param ui32Upper - the upper limit for the ADC window.
+//! @param ui32Upper - the lower limit for the ADC window.
+//!
+//! This function may be used to change the ADC window parameters. Please note
+//! that the upper and lower limits are only 16-bits wide in the ADC hardware.
+//! This function will ignore the upper 16 bits of these arguments.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_window_set(uint32_t ui32Upper, uint32_t ui32Lower)
+{
+ //
+ // Set the window limits for the ADC.
+ //
+ AM_BFW(ADC, WULIM, ULIM, ui32Upper);
+ AM_BFW(ADC, WLLIM, LLIM, ui32Lower);
+}
+
+//*****************************************************************************
+//
+//! @brief Configure a single ADC slot.
+//!
+//! @param ui32SlotNumber - the number of the ADC slot to be configured.
+//! @param ui32SlotConfig - contains slot-specific options.
+//!
+//! This function may be used to configure the settings for an individual ADC
+//! slot. The parameter \b ui32SlotConfig should be the logical 'OR' of a slot
+//! average macro, a slot hold-time macro, a slot channel macro, and
+//! optionally, the slot window enable macro.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_slot_config(uint32_t ui32SlotNumber, uint32_t ui32SlotConfig)
+{
+ uint32_t ui32RegOffset;
+
+ //
+ // Make sure we're accessing a real slot.
+ //
+ am_hal_debug_assert_msg((ui32SlotNumber & 0xFFFFFFFF0) == 0,
+ "Trying to configure an ADC slot that doesn't exist.");
+
+ //
+ // Locate the correct register for this ADC slot.
+ //
+ ui32RegOffset = (AM_REG_ADCn(0) + AM_REG_ADC_SL0CFG_O + (4 * ui32SlotNumber));
+
+ //
+ // Write the register with the caller's configuration value.
+ //
+ AM_REGVAL(ui32RegOffset) = ui32SlotConfig;
+}
+
+//*****************************************************************************
+//
+//! @brief Peek at the next fifo entry.
+//!
+//! This function reads the oldest value in the ADC sample fifo but doesn't
+//! actually advance the fifo to the next entry. This function is useful when
+//! you need information from the fifo but you don't want to also empty the
+//! fifo. This could be helpful if you want to check the FIFO depth without
+//! pulling any data out.
+//!
+//! The value returned by this function is the raw 32-bit value provided by the
+//! ADC hardware. In order to interpret this value, you will need to use one of
+//! the following macros.
+//!
+//! @return 32-bit FIFO entry.
+//!
+//
+//*****************************************************************************
+uint32_t
+am_hal_adc_fifo_peek(void)
+{
+ uint32_t ui32FIFOValue;
+
+ //
+ // Grab a value from the ADC FIFO.
+ //
+ ui32FIFOValue = AM_REG(ADC, FIFO);
+
+ //
+ // Return FIFO entry.
+ //
+ return ui32FIFOValue;
+}
+
+//*****************************************************************************
+//
+//! @brief
+//!
+//! This function reads the oldest value in the ADC fifo and then pops the
+//! fifo. Use this function when you actually want to pull data out of the
+//! fifo.
+//!
+//! @return 32-bit FIFO entry.
+//!
+//
+//*****************************************************************************
+uint32_t
+am_hal_adc_fifo_pop(void)
+{
+ uint32_t ui32FIFOValue;
+
+ //
+ // Grab a value from the ADC FIFO.
+ //
+ ui32FIFOValue = AM_REG(ADC, FIFO);
+
+ //
+ // Pop the FIFO.
+ //
+ AM_REG(ADC, FIFO) = 0;
+
+ //
+ // Return FIFO valid bits.
+ //
+ return ui32FIFOValue;
+}
+
+//*****************************************************************************
+//
+//! @brief Issue Software Trigger to the ADC.
+//!
+//! This function issues the software trigger to the ADC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_trigger(void)
+{
+ //
+ // Write to the Software trigger register in the ADC.
+ //
+ AM_REG(ADC, SWT) = 0x37;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the ADC.
+//!
+//! Use this function to enable the ADC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_enable(void)
+{
+ //
+ // Enable the ADC.
+ //
+ AM_BFW(ADC, CFG, ADCEN, 0x1);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the ADC.
+//!
+//! Use this function to disable the ADC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_disable(void)
+{
+ //
+ // Disable the ADC.
+ //
+ AM_BFW(ADC, CFG, ADCEN, 0x0);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable selected ADC Interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_adc.h.
+//!
+//! Use this function to enable the ADC interrupts.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_int_enable(uint32_t ui32Interrupt)
+{
+ //
+ // Enable the interrupts.
+ //
+ AM_REG(ADC, INTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return enabled ADC Interrupts.
+//!
+//! Use this function to get all enabled ADC interrupts.
+//!
+//! @return enabled ADC Interrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_adc_int_enable_get(void)
+{
+ //
+ // Return enabled interrupts.
+ //
+ return AM_REG(ADC, INTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable selected ADC Interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_adc.h.
+//!
+//! Use this function to disable the ADC interrupts.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_int_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Disable the interrupts.
+ //
+ AM_REG(ADC, INTEN) &= ~ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Clear selected ADC Interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_adc.h.
+//!
+//! Use this function to clear the ADC interrupts.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Clear the interrupts.
+ //
+ AM_REG(ADC, INTCLR) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Set selected ADC Interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_adc.h.
+//!
+//! Use this function to set the ADC interrupts.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_adc_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Set the interrupts.
+ //
+ AM_REG(ADC, INTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return either enabled or raw selected ADC interrupt status.
+//!
+//! @param bEnabledOnly - return the status of only the enabled interrupts.
+//!
+//! Use this function to get the ADC interrupt status.
+//!
+//! @return enabled or raw ADC interrupt status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_adc_int_status_get(bool bEnabledOnly)
+{
+ //
+ // Return the status.
+ //
+ if (bEnabledOnly)
+ {
+ uint32_t u32RetVal = AM_REG(ADC, INTEN);
+ u32RetVal &= AM_REG(ADC, INTSTAT);
+ return u32RetVal;
+ }
+ else
+ {
+ return AM_REG(ADC, INTSTAT);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Return temperature in degrees C of supplied voltage.
+//!
+//! @param fVoltage - return the temperature corresponding to this voltage.
+//!
+//! Use this function to convert volts from the temperature sensor into degrees
+//! C. Caller converts ADC binary code to volts based on reference used.
+//! This routine looks up the trim parameters and returns corrected temperature.
+//!
+//! The computation is based on a line running through 0 degrees K.
+//! We find the slope from the trimmed temperature calibration point.
+//!
+//!
+//! @return the temperature in degrees C.
+//
+//*****************************************************************************
+float
+am_hal_adc_volts_to_celsius(float fVoltage)
+{
+ float fTemp;
+
+ //
+ // Get calibration temperature from trimmed values & convert to degrees K.
+ //
+ float fCalibration_temp = priv_temp_trims.flt.fCalibrationTemperature;
+
+ //
+ // Get remaining trimmed values.
+ //
+ float fCalibration_voltage = priv_temp_trims.flt.fCalibrationVoltage;
+ float fCalibration_offset = priv_temp_trims.flt.fCalibrationOffset;
+
+ //
+ // Compute the temperature.
+ //
+ fTemp = fCalibration_temp;
+ fTemp /= (fCalibration_voltage - fCalibration_offset);
+ fTemp *= (fVoltage - fCalibration_offset);
+
+ //
+ // Give it back to the caller in Celsius.
+ //
+ return fTemp - 273.15f;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_adc.h b/bsp/apollo2/libraries/drivers/hal/am_hal_adc.h
new file mode 100644
index 0000000000..86b48b162c
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_adc.h
@@ -0,0 +1,348 @@
+//*****************************************************************************
+//
+// am_hal_adc.h
+//! @file
+//!
+//! @brief Functions for interfacing with the Analog to Digital Converter
+//!
+//! @addtogroup adc2 Analog-to-Digital Converter (ADC)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_ADC_H
+#define AM_HAL_ADC_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! @name Clock Selection
+//! @brief These macros may be used to set the ADC module's clock source.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_CLOCK_OFF AM_REG_ADC_CFG_CLKSEL_OFF
+#define AM_HAL_ADC_CLOCK_HFRC AM_REG_ADC_CFG_CLKSEL_HFRC
+#define AM_HAL_ADC_CLOCK_DIV2 AM_REG_ADC_CFG_CLKSEL_HFRC_DIV2
+//! @}
+
+//*****************************************************************************
+//
+//! @name Trigger Settings
+//! @brief ADC trigger setting macros.
+//!
+//! These macros alter the ADC's trigger source and trigger polarity. Note that
+//! the external trigger setting needs to be ORed with a POS or NEG option to
+//! define the desired trigger polarity.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_TRIGGER_SOFT AM_REG_ADC_CFG_TRIGSEL_SWT
+#define AM_HAL_ADC_TRIGGER_VCOMP AM_REG_ADC_CFG_TRIGSEL_VCOMP
+#define AM_HAL_ADC_TRIGGER_EXT0 AM_REG_ADC_CFG_TRIGSEL_EXT0
+#define AM_HAL_ADC_TRIGGER_EXT1 AM_REG_ADC_CFG_TRIGSEL_EXT1
+#define AM_HAL_ADC_TRIGGER_EXT2 AM_REG_ADC_CFG_TRIGSEL_EXT2
+#define AM_HAL_ADC_TRIGGER_EXT3 AM_REG_ADC_CFG_TRIGSEL_EXT3
+#define AM_HAL_ADC_TRIGGER_FALL AM_REG_ADC_CFG_TRIGPOL_FALLING_EDGE
+#define AM_HAL_ADC_TRIGGER_RISE AM_REG_ADC_CFG_TRIGPOL_RISING_EDGE
+//! @}
+
+//*****************************************************************************
+//
+//! @name Reference Settings
+//! @brief ADC reference voltage setting macros.
+//!
+//! These macros control the ADC reference voltage source.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_REF_EXT_2P0 AM_REG_ADC_CFG_REFSEL_EXT2P0
+#define AM_HAL_ADC_REF_EXT_1P5 AM_REG_ADC_CFG_REFSEL_EXT1P5
+#define AM_HAL_ADC_REF_INT_2P0 AM_REG_ADC_CFG_REFSEL_INT2P0
+#define AM_HAL_ADC_REF_INT_1P5 AM_REG_ADC_CFG_REFSEL_INT1P5
+//! @}
+
+//*****************************************************************************
+//
+//! @name Clock Mode
+//! @brief ADC clock mode settings
+//!
+//! These macros determine whether the ADC shuts down its clock between
+//! samples. Shutting down the clock will reduce power consumption, but
+//! increase latency. This setting is only valid for LPMODE 0. For other modes,
+//! it will be ignored.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_CK_LOW_POWER AM_REG_ADC_CFG_CKMODE_LPCKMODE
+#define AM_HAL_ADC_CK_LOW_LATENCY AM_REG_ADC_CFG_CKMODE_LLCKMODE
+//! @}
+
+//*****************************************************************************
+//
+//! @name Low Power Mode
+//! @brief ADC power conservation settings.
+//!
+//! These macros select the power state to enter between active scans. Each low
+//! power mode has its own set of timing constraints. Please see the datasheet
+//! for additional timing information on each power mode.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_LPMODE_0 AM_REG_ADC_CFG_LPMODE_MODE0
+#define AM_HAL_ADC_LPMODE_1 AM_REG_ADC_CFG_LPMODE_MODE1
+//! @}
+
+//*****************************************************************************
+//
+//! @name Repeat Mode
+//! @brief Enable repeating scan mode.
+//!
+//! Use this macro to enable repeating scans using timer 3.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_REPEAT AM_REG_ADC_CFG_RPTEN(1)
+#define AM_HAL_ADC_NO_REPEAT AM_REG_ADC_CFG_RPTEN(0)
+//! @}
+
+//*****************************************************************************
+//
+//! @name Slot configuration
+//! @brief Slot configuration macros
+//!
+//! These macros may be used to configure an individual ADC slot.
+//! @{
+//
+//*****************************************************************************
+
+// Set number of samples to average.
+#define AM_HAL_ADC_SLOT_AVG_1 AM_REG_ADC_SL0CFG_ADSEL0(0)
+#define AM_HAL_ADC_SLOT_AVG_2 AM_REG_ADC_SL0CFG_ADSEL0(1)
+#define AM_HAL_ADC_SLOT_AVG_4 AM_REG_ADC_SL0CFG_ADSEL0(2)
+#define AM_HAL_ADC_SLOT_AVG_8 AM_REG_ADC_SL0CFG_ADSEL0(3)
+#define AM_HAL_ADC_SLOT_AVG_16 AM_REG_ADC_SL0CFG_ADSEL0(4)
+#define AM_HAL_ADC_SLOT_AVG_32 AM_REG_ADC_SL0CFG_ADSEL0(5)
+#define AM_HAL_ADC_SLOT_AVG_64 AM_REG_ADC_SL0CFG_ADSEL0(6)
+#define AM_HAL_ADC_SLOT_AVG_128 AM_REG_ADC_SL0CFG_ADSEL0(7)
+
+// Set slot precision mode.
+#define AM_HAL_ADC_SLOT_14BIT AM_REG_ADC_SL0CFG_PRMODE0_P14B
+#define AM_HAL_ADC_SLOT_12BIT AM_REG_ADC_SL0CFG_PRMODE0_P14B
+#define AM_HAL_ADC_SLOT_10BIT AM_REG_ADC_SL0CFG_PRMODE0_P14B
+#define AM_HAL_ADC_SLOT_8BIT AM_REG_ADC_SL0CFG_PRMODE0_P14B
+
+// Select a channel by number.
+#define AM_HAL_ADC_SLOT_CHANNEL(n) AM_REG_ADC_SL0CFG_CHSEL0(n)
+
+// Single-ended channels
+#define AM_HAL_ADC_SLOT_CHSEL_SE0 AM_REG_ADC_SL0CFG_CHSEL0_SE0
+#define AM_HAL_ADC_SLOT_CHSEL_SE1 AM_REG_ADC_SL0CFG_CHSEL0_SE1
+#define AM_HAL_ADC_SLOT_CHSEL_SE2 AM_REG_ADC_SL0CFG_CHSEL0_SE2
+#define AM_HAL_ADC_SLOT_CHSEL_SE3 AM_REG_ADC_SL0CFG_CHSEL0_SE3
+#define AM_HAL_ADC_SLOT_CHSEL_SE4 AM_REG_ADC_SL0CFG_CHSEL0_SE4
+#define AM_HAL_ADC_SLOT_CHSEL_SE5 AM_REG_ADC_SL0CFG_CHSEL0_SE5
+#define AM_HAL_ADC_SLOT_CHSEL_SE6 AM_REG_ADC_SL0CFG_CHSEL0_SE6
+#define AM_HAL_ADC_SLOT_CHSEL_SE7 AM_REG_ADC_SL0CFG_CHSEL0_SE7
+#define AM_HAL_ADC_SLOT_CHSEL_SE8 AM_REG_ADC_SL0CFG_CHSEL0_SE8
+#define AM_HAL_ADC_SLOT_CHSEL_SE9 AM_REG_ADC_SL0CFG_CHSEL0_SE9
+
+// Differential channels.
+#define AM_HAL_ADC_SLOT_CHSEL_DF0 AM_REG_ADC_SL0CFG_CHSEL0_DF0
+#define AM_HAL_ADC_SLOT_CHSEL_DF1 AM_REG_ADC_SL0CFG_CHSEL0_DF1
+
+// Miscellaneous other signals.
+#define AM_HAL_ADC_SLOT_CHSEL_TEMP AM_REG_ADC_SL0CFG_CHSEL0_TEMP
+#define AM_HAL_ADC_SLOT_CHSEL_VSS AM_REG_ADC_SL0CFG_CHSEL0_VSS
+#define AM_HAL_ADC_SLOT_CHSEL_VBATT AM_REG_ADC_SL0CFG_CHSEL0_BATT
+
+// Window enable.
+#define AM_HAL_ADC_SLOT_WINDOW_EN AM_REG_ADC_SL0CFG_WCEN0(1)
+
+// Enable the slot.
+#define AM_HAL_ADC_SLOT_ENABLE AM_REG_ADC_SL0CFG_SLEN0(1)
+//! @}
+
+//*****************************************************************************
+//
+//! @name Interrupt Status Bits
+//! @brief Interrupt Status Bits for enable/disble use
+//!
+//! These macros may be used to enable an individual ADC interrupt cause.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_INT_WCINC AM_REG_ADC_INTEN_WCINC(1)
+#define AM_HAL_ADC_INT_WCEXC AM_REG_ADC_INTEN_WCEXC(1)
+#define AM_HAL_ADC_INT_FIFOOVR2 AM_REG_ADC_INTEN_FIFOOVR2(1)
+#define AM_HAL_ADC_INT_FIFOOVR1 AM_REG_ADC_INTEN_FIFOOVR1(1)
+#define AM_HAL_ADC_INT_SCNCMP AM_REG_ADC_INTEN_SCNCMP(1)
+#define AM_HAL_ADC_INT_CNVCMP AM_REG_ADC_INTEN_CNVCMP(1)
+//! @}
+
+//*****************************************************************************
+//
+//! @name Temperature Trim Value Locations
+//! @brief Temperature calibration cofficients are stored in readable space.
+//!
+//! These macros are used to access the temperature trim values in readable
+//! space.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_CALIB_TEMP_ADDR (0x50023010)
+#define AM_HAL_ADC_CALIB_AMBIENT_ADDR (0x50023014)
+#define AM_HAL_ADC_CALIB_ADC_OFFSET_ADDR (0x50023018)
+
+//
+// Default coefficients (used when trims not provided):
+// TEMP_DEFAULT = Temperature in deg K (e.g. 299.5 - 273.15 = 26.35)
+// AMBIENT_DEFAULT = Voltage measurement at default temperature.
+// OFFSET_DEFAULT = Default ADC offset at 1v.
+//
+#define AM_HAL_ADC_CALIB_TEMP_DEFAULT (299.5F)
+#define AM_HAL_ADC_CALIB_AMBIENT_DEFAULT (1.02809F)
+#define AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT (-0.004281F)
+//! @}
+
+//*****************************************************************************
+//
+//! @brief Configuration structure for the ADC.
+//
+//*****************************************************************************
+typedef struct
+{
+ //! Select the ADC Clock source using one of the clock source macros.
+ uint32_t ui32Clock;
+
+ //! Select the ADC trigger source using a trigger source macro.
+ uint32_t ui32TriggerConfig;
+
+ //! Use a macro to select the ADC reference voltage.
+ uint32_t ui32Reference;
+
+ //! Use a macro to decide whether to disable clocks between samples.
+ uint32_t ui32ClockMode;
+
+ //! Use a macro to select the ADC power mode.
+ uint32_t ui32PowerMode;
+
+ //! Select whether the ADC will re-trigger based on a signal from timer 3.
+ uint32_t ui32Repeat;
+}
+am_hal_adc_config_t;
+
+//*****************************************************************************
+//
+//! @brief ADC Fifo Read macros
+//!
+//! These are helper macros for interpreting FIFO data. Each ADC FIFO entry
+//! contains information about the slot number and the FIFO depth alongside the
+//! current sample. These macros perform the correct masking and shifting to
+//! read those values.
+//!
+//! The SAMPLE and FULL_SAMPLE options refer to the fractional part of averaged
+//! samples. If you are not using hardware averaging or don't need the
+//! fractional part of the ADC sample, you should just use
+//! AM_HAL_ADC_FIFO_SAMPLE.
+//!
+//! If you do need the fractional part, use AM_HAL_ADC_FIFO_FULL_SAMPLE. This
+//! macro will keep six bits of precision past the decimal point. Depending on
+//! the number of averaged samples, anywhere between 1 and 6 of these bits will
+//! be valid. Please consult the datasheet to find out how many bits of data
+//! are valid for your chosen averaging settings.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_ADC_FIFO_SAMPLE(value) \
+ ((((value) & AM_REG_ADC_FIFO_DATA_M) >> AM_REG_ADC_FIFO_DATA_S) >> 6)
+
+#define AM_HAL_ADC_FIFO_FULL_SAMPLE(value) \
+ (((value) & AM_REG_ADC_FIFO_DATA_M) >> AM_REG_ADC_FIFO_DATA_S )
+
+#define AM_HAL_ADC_FIFO_SLOT(value) \
+ (((value) & AM_REG_ADC_FIFO_SLOTNUM_M) >> AM_REG_ADC_FIFO_SLOTNUM_S)
+
+#define AM_HAL_ADC_FIFO_COUNT(value) \
+ (((value) & AM_REG_ADC_FIFO_COUNT_M) >> AM_REG_ADC_FIFO_COUNT_S)
+//! @}
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_adc_config(am_hal_adc_config_t *psConfig);
+extern void am_hal_adc_window_set(uint32_t ui32Upper, uint32_t ui32Lower);
+extern void am_hal_adc_slot_config(uint32_t ui32SlotNumber,
+ uint32_t ui32SlotConfig);
+
+extern uint32_t am_hal_adc_fifo_peek(void);
+extern uint32_t am_hal_adc_fifo_pop(void);
+
+extern void am_hal_adc_trigger(void);
+extern void am_hal_adc_enable(void);
+extern void am_hal_adc_disable(void);
+extern void am_hal_adc_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_adc_int_enable_get(void);
+extern void am_hal_adc_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_adc_int_clear(uint32_t ui32Interrupt);
+extern void am_hal_adc_int_set(uint32_t ui32Interrupt);
+extern uint32_t am_hal_adc_int_status_get(bool bEnabledOnly);
+extern float am_hal_adc_volts_to_celsius(float fVoltage);
+extern void am_hal_adc_temp_trims_get(float * pfTemp, float * pfVoltage, float * pfOffsetV);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_ADC_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.c b/bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.c
new file mode 100644
index 0000000000..23c7164418
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.c
@@ -0,0 +1,576 @@
+//*****************************************************************************
+//
+// am_hal_cachectrl.c
+//! @file
+//!
+//! @brief Functions for interfacing with the CACHE controller.
+//!
+//! @addtogroup clkgen2 Clock Generator (CACHE)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Default settings for the cache.
+//
+//*****************************************************************************
+const am_hal_cachectrl_config_t am_hal_cachectrl_defaults =
+{
+ .ui32EnableCache = 1,
+ .ui32LRU = 0,
+ .ui32EnableNCregions = 0,
+ .ui32Config = AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_512,
+ .ui32SerialCacheMode = 0,
+ .ui32FlashCachingEnables = 3,
+ .ui32EnableCacheClockGating = 1,
+ .ui32EnableLightSleep = 0,
+ .ui32Dly = 1,
+ .ui32SMDly = 1,
+ .ui32EnableDataClockGating = 1,
+ .ui32EnableCacheMonitoring = 0,
+};
+
+//*****************************************************************************
+//
+//! @brief Enable the cache using the supplied settings
+//!
+//! @param psConfig - pointer to a config structure containing cache settings.
+//!
+//! This function takes in a structure of cache settings, and uses them to
+//! enable the cache. This function will take care of the necessary register
+//! writes both in this module and in the power control module, so a separate
+//! powerctrl call is not necessary.
+//!
+//! For most applications, the default cache settings will be the most
+//! efficient choice. To use the default cache settings with this function, use
+//! the address of the global am_hal_cachectrl_defaults structure as the
+//! psConfig argument.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_cachectrl_enable(const am_hal_cachectrl_config_t *psConfig)
+{
+ uint32_t ui32ConfigValue;
+ uint32_t ui32Timeout;
+
+ //
+ // Pull the configuration data from the structure, and prepare to write the
+ // cache configuration register.
+ //
+ // NOTE: ICACHE and DCACHE settings were left out from this step. This is a
+ // workaround for a timing issue with early versions of Apollo2 that caused
+ // the cache to incorrectly mark itself valid during the startup sequence.
+ // The workaround calls for us to start the cache, manually invalidate it,
+ // and then enable ICACHE and DCACHE operation.
+ //
+ ui32ConfigValue = (AM_REG_CACHECTRL_CACHECFG_ENABLE( 1 ) |
+ AM_REG_CACHECTRL_CACHECFG_LRU( psConfig->ui32LRU ) |
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC0( (psConfig->ui32EnableNCregions & 0x1) >> 0 ) |
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC1( (psConfig->ui32EnableNCregions & 0x2) >> 1 ) |
+ psConfig->ui32Config |
+ AM_REG_CACHECTRL_CACHECFG_SERIAL(psConfig->ui32SerialCacheMode) |
+ AM_REG_CACHECTRL_CACHECFG_CACHE_CLKGATE( psConfig->ui32EnableCacheClockGating ) |
+ AM_REG_CACHECTRL_CACHECFG_CACHE_LS(psConfig->ui32EnableLightSleep ) |
+ AM_REG_CACHECTRL_CACHECFG_DLY( psConfig->ui32Dly ) |
+ AM_REG_CACHECTRL_CACHECFG_SMDLY( psConfig->ui32SMDly ) |
+ AM_REG_CACHECTRL_CACHECFG_DATA_CLKGATE(psConfig->ui32EnableDataClockGating) |
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_MONITOR(psConfig->ui32EnableCacheMonitoring) );
+
+ //
+ // Make sure the cache is enabled in the power control block.
+ //
+ am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEMEN_CACHE);
+
+ //
+ // Set the initial cache settings.
+ //
+ AM_REG(CACHECTRL, CACHECFG) = ui32ConfigValue;
+
+ //
+ // Wait for the cache ready signal.
+ //
+ for (ui32Timeout = 0; ui32Timeout < 50; ui32Timeout++)
+ {
+ if (AM_BFM(CACHECTRL, CACHECTRL, CACHE_READY))
+ {
+ break;
+ }
+ }
+
+ //
+ // Manually invalidate the cache (workaround for the issue described above.)
+ //
+ AM_BFW(CACHECTRL, CACHECTRL, INVALIDATE, 1);
+
+ //
+ // Wait for the cache ready signal again.
+ //
+ for (ui32Timeout = 0; ui32Timeout < 50; ui32Timeout++)
+ {
+ if (AM_BFM(CACHECTRL, CACHECTRL, CACHE_READY))
+ {
+ break;
+ }
+ }
+
+ //
+ // Now that the cache is running, and correctly marked invalid, we can OR in
+ // the ICACHE and DCACHE settings.
+ //
+ ui32ConfigValue |= (AM_REG_CACHECTRL_CACHECFG_ICACHE_ENABLE( (psConfig->ui32FlashCachingEnables & 0x1) >> 0 ) |
+ AM_REG_CACHECTRL_CACHECFG_DCACHE_ENABLE( (psConfig->ui32FlashCachingEnables & 0x2) >> 1 ) );
+
+ //
+ // Write the final configuration settings to the CACHECTRL register.
+ //
+ AM_REG(CACHECTRL, CACHECFG) = ui32ConfigValue;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the cache.
+//!
+//! Call this function to completely shut down cache features.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_cachectrl_disable(void)
+{
+ uint32_t ui32CacheCfg;
+
+ //
+ // Save the cache settings.
+ //
+ ui32CacheCfg = AM_REG(CACHECTRL, CACHECFG);
+
+ //
+ // Remove the ICACHE and DCACHE settings.
+ //
+ ui32CacheCfg &= (AM_REG_CACHECTRL_CACHECFG_DCACHE_ENABLE(0) |
+ AM_REG_CACHECTRL_CACHECFG_ICACHE_ENABLE(0));
+
+ //
+ // Write the resulting value back to the register.
+ //
+ AM_REG(CACHECTRL, CACHECFG) = ui32CacheCfg;
+
+ //
+ // Read the CACHECTRL register a few times
+ //
+ AM_REG(CACHECTRL, CACHECTRL);
+ AM_REG(CACHECTRL, CACHECTRL);
+ AM_REG(CACHECTRL, CACHECTRL);
+
+ //
+ // Disable the cache completely.
+ //
+ AM_BFW(CACHECTRL, CACHECFG, ENABLE, 0);
+
+ //
+ // Power the cache down in the powerctrl block.
+ //
+ am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEMEN_CACHE_DIS);
+}
+
+//*****************************************************************************
+//
+//! @brief Set a default cache configuration.
+//!
+//! This function is used to set a default cache configuration.
+//
+//*****************************************************************************
+void
+am_hal_cachectrl_config_default(void)
+{
+ //
+ // Set PWRCTRL
+ //
+ am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEMEN_CACHE);
+
+ //
+ // Write a default configuration to the CACHECFG register.
+ //
+ AM_REG(CACHECTRL, CACHECFG) = \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE( 1 ) | \
+ AM_REG_CACHECTRL_CACHECFG_LRU( 0 ) | \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC0( 0 ) | \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC1( 0 ) | \
+ AM_REG_CACHECTRL_CACHECFG_CONFIG_W2_128B_512E | \
+ AM_REG_CACHECTRL_CACHECFG_SERIAL( 0 ) | \
+ AM_REG_CACHECTRL_CACHECFG_ICACHE_ENABLE( 1 ) | \
+ AM_REG_CACHECTRL_CACHECFG_DCACHE_ENABLE( 1 ) | \
+ AM_REG_CACHECTRL_CACHECFG_CACHE_CLKGATE( 1 ) | \
+ AM_REG_CACHECTRL_CACHECFG_CACHE_LS( 0 ) | \
+ AM_REG_CACHECTRL_CACHECFG_DLY( 1 ) | \
+ AM_REG_CACHECTRL_CACHECFG_SMDLY( 1 ) | \
+ AM_REG_CACHECTRL_CACHECFG_DATA_CLKGATE( 1 ) | \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_MONITOR( 0 );
+
+ //
+ // Write a default configuration to the FLASHCFG register.
+ //
+ AM_REG(CACHECTRL, FLASHCFG) = AM_REG_CACHECTRL_FLASHCFG_RD_WAIT(1);
+
+ //
+ // Write a default configuration to the CACHECTRL register.
+ //
+ AM_REG(CACHECTRL, CACHECTRL) = \
+ AM_REG_CACHECTRL_CACHECTRL_FLASH1_SLM_ENABLE(1) | \
+ AM_REG_CACHECTRL_CACHECTRL_FLASH1_SLM_DISABLE(0) | \
+ AM_REG_CACHECTRL_CACHECTRL_FLASH0_SLM_ENABLE(1) | \
+ AM_REG_CACHECTRL_CACHECTRL_FLASH0_SLM_DISABLE(0) | \
+ AM_REG_CACHECTRL_CACHECTRL_RESET_STAT(0) | \
+ AM_REG_CACHECTRL_CACHECTRL_INVALIDATE(0);
+
+ //
+ // Write a default configuration to the NCR0START and NCR0END registers.
+ //
+ AM_REG(CACHECTRL, NCR0START) = \
+ AM_REG_CACHECTRL_NCR0START_ADDR(0);
+ AM_REG(CACHECTRL, NCR0END) = \
+ AM_REG_CACHECTRL_NCR0END_ADDR(0);
+
+ //
+ // Write a default configuration to the NCR1START and NCR1END registers.
+ //
+ AM_REG(CACHECTRL, NCR1START) = \
+ AM_REG_CACHECTRL_NCR1START_ADDR(0);
+ AM_REG(CACHECTRL, NCR1END) = \
+ AM_REG_CACHECTRL_NCR1END_ADDR(0);
+
+ //
+ // Write a default configuration to the DMONn and IMONn registers.
+ //
+ AM_REG(CACHECTRL, DMON0) = \
+ AM_REG_CACHECTRL_DMON0_DACCESS_COUNT(0);
+ AM_REG(CACHECTRL, DMON1) = \
+ AM_REG_CACHECTRL_DMON1_DLOOKUP_COUNT(0);
+ AM_REG(CACHECTRL, DMON2) = \
+ AM_REG_CACHECTRL_DMON2_DHIT_COUNT(0);
+ AM_REG(CACHECTRL, DMON3) = \
+ AM_REG_CACHECTRL_DMON3_DLINE_COUNT(0);
+ AM_REG(CACHECTRL, IMON0) = \
+ AM_REG_CACHECTRL_IMON0_IACCESS_COUNT(0);
+ AM_REG(CACHECTRL, IMON1) = \
+ AM_REG_CACHECTRL_IMON1_ILOOKUP_COUNT(0);
+ AM_REG(CACHECTRL, IMON2) = \
+ AM_REG_CACHECTRL_IMON2_IHIT_COUNT(0);
+ AM_REG(CACHECTRL, IMON3) = \
+ AM_REG_CACHECTRL_IMON3_ILINE_COUNT(0);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the flash cache controller via a configuration structure.
+//!
+//! @param psConfig - Pointer to a data structure containing all of the data
+// necessary to configure the CACHECFG register.
+//!
+//! This function is used to configure all fields of the CACHECFG.
+//
+//*****************************************************************************
+void
+am_hal_cachectrl_config(am_hal_cachectrl_config_t *psConfig)
+{
+ uint32_t u32ConfigValue;
+
+ //
+ // Arrange all of the members of the data structure into a single u32 that
+ // can be written to the register.
+ //
+ u32ConfigValue =
+ AM_REG_CACHECTRL_CACHECFG_ENABLE( psConfig->ui32EnableCache ) |
+ AM_REG_CACHECTRL_CACHECFG_LRU( psConfig->ui32LRU ) |
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC0(
+ (psConfig->ui32EnableNCregions & 0x1) >> 0 ) |
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC1(
+ (psConfig->ui32EnableNCregions & 0x2) >> 1 ) |
+ psConfig->ui32Config |
+ AM_REG_CACHECTRL_CACHECFG_SERIAL(psConfig->ui32SerialCacheMode) |
+ AM_REG_CACHECTRL_CACHECFG_ICACHE_ENABLE(
+ (psConfig->ui32FlashCachingEnables & 0x1) >> 0 ) |
+ AM_REG_CACHECTRL_CACHECFG_DCACHE_ENABLE(
+ (psConfig->ui32FlashCachingEnables & 0x2) >> 1 ) |
+ AM_REG_CACHECTRL_CACHECFG_CACHE_CLKGATE(
+ psConfig->ui32EnableCacheClockGating ) |
+ AM_REG_CACHECTRL_CACHECFG_CACHE_LS(
+ psConfig->ui32EnableLightSleep ) |
+ AM_REG_CACHECTRL_CACHECFG_DLY( psConfig->ui32Dly ) |
+ AM_REG_CACHECTRL_CACHECFG_SMDLY( psConfig->ui32SMDly ) |
+ AM_REG_CACHECTRL_CACHECFG_DATA_CLKGATE(
+ psConfig->ui32EnableDataClockGating ) |
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_MONITOR(
+ psConfig->ui32EnableCacheMonitoring );
+
+ //
+ // Write the configuration value to the CACHECFG register.
+ //
+ AM_REG(CACHECTRL, CACHECFG) = u32ConfigValue;
+}
+
+//*****************************************************************************
+//
+//! @brief Configure the various flash cache controller enables.
+//!
+//! @param u32EnableMask - Mask of features to be enabled.
+//! @param u32DisableMask - Mask of features to be disabled.
+//!
+//! This function is used to enable or disable the various flash cache
+//! controller configuration enables which consist of the following:
+//! AM_HAL_CACHECTRL_CACHECFG_ENABLE Flash cache controller
+//! AM_HAL_CACHECTRL_CACHECFG_LRU_ENABLE LRU (disabled = LRR)
+//! AM_HAL_CACHECTRL_CACHECFG_NC0_ENABLE Non-cacheable region 0
+//! AM_HAL_CACHECTRL_CACHECFG_NC1_ENABLE Non-cacheable region 1
+//! AM_HAL_CACHECTRL_CACHECFG_SERIAL_ENABLE Serial cache mode
+//! AM_HAL_CACHECTRL_CACHECFG_ICACHE_ENABLE Instruction caching
+//! AM_HAL_CACHECTRL_CACHECFG_DCACHE_ENABLE Data caching.
+//! AM_HAL_CACHECTRL_CACHECFG_CACHE_CLKGATE_ENABLE Cache clock gating
+//! AM_HAL_CACHECTRL_CACHECFG_LS_ENABLE Light sleep cache RAMs
+//! AM_HAL_CACHECTRL_CACHECFG_DATA_CLKGATE_ENABLE Data clock gating
+//! AM_HAL_CACHECTRL_CACHECFG_MONITOR_ENABLE Cache Monitoring Stats
+//!
+//! Note that if both an enable and disable are provided in their respective
+//! masks, the enable will take precendence.
+//!
+//! @return The previous status of the flash cache controller enables.
+//
+//*****************************************************************************
+#define CACHECTRL_VALID_ENABLES ( \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_M | \
+ AM_REG_CACHECTRL_CACHECFG_LRU_M | \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC0_M | \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_NC1_M | \
+ AM_REG_CACHECTRL_CACHECFG_SERIAL_M | \
+ AM_REG_CACHECTRL_CACHECFG_ICACHE_ENABLE_M | \
+ AM_REG_CACHECTRL_CACHECFG_DCACHE_ENABLE_M | \
+ AM_REG_CACHECTRL_CACHECFG_CACHE_CLKGATE_M | \
+ AM_REG_CACHECTRL_CACHECFG_CACHE_LS_M | \
+ AM_REG_CACHECTRL_CACHECFG_DATA_CLKGATE_M | \
+ AM_REG_CACHECTRL_CACHECFG_ENABLE_MONITOR_M )
+
+uint32_t
+am_hal_cachectrl_cache_enables(uint32_t u32EnableMask, uint32_t u32DisableMask)
+{
+ uint32_t ui32RetVal = AM_BFR(CACHECTRL, CACHECFG, ENABLE) &
+ CACHECTRL_VALID_ENABLES;
+
+ //
+ // Make sure the enable masks include only valid bits.
+ //
+ u32EnableMask &= CACHECTRL_VALID_ENABLES;
+ u32DisableMask &= CACHECTRL_VALID_ENABLES;
+
+ //
+ // First, do the disables.
+ //
+ AM_REG(CACHECTRL, CACHECFG) &= ~u32DisableMask;
+
+ //
+ // Now set the enables.
+ //
+ AM_REG(CACHECTRL, CACHECFG) |= u32EnableMask;
+
+ return ui32RetVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Select the cache configuration type.
+//!
+//! This functions only sets the CACHECFG CONFIG field.
+//!
+//! @param ui32CacheConfig - The cache configuration value.
+//!
+//! This function can be used to select the type of cache.frequency of the main
+//! system clock. The ui32CacheConfig parameter should be set to one of the
+//! following values:
+//!
+//! AM_HAL_CACHECTRL_CACHECFG_CONFIG_DIRECT_256 : Direct mapped,
+//! 128-bit linesize, 256 entries (2 SRAMs active).
+//! AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_256 : Two-way set associative,
+//! 128-bit linesize, 256 entries (4 SRAMs active).
+//! AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_512 : Two-way set associative,
+//! 128-bit linesize, 512 entries (8 SRAMs active).
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_cachectrl_cache_config(uint32_t ui32CacheConfig)
+{
+ //
+ // Clear the bitfield
+ //
+ AM_REG(CACHECTRL, CACHECFG) &= ~AM_REG_CACHECTRL_CACHECFG_CONFIG_M;
+
+ //
+ // Write the new value to the bitfield.
+ //
+ AM_REG(CACHECTRL, CACHECFG) |= ui32CacheConfig &
+ AM_REG_CACHECTRL_CACHECFG_CONFIG_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Invalidate the flash cache.
+//!
+//! This function is used to invalidate the flash cache.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_cachectrl_invalidate_flash_cache(void)
+{
+ //
+ // Write the bit to invalidate the flash cache.
+ // Note - this bit is not sticky, no need to write it back to 0.
+ //
+ AM_REG(CACHECTRL, CACHECTRL) |= AM_REG_CACHECTRL_CACHECTRL_INVALIDATE_GO;
+}
+
+//*****************************************************************************
+//
+//! @brief Reset cache statistics.
+//!
+//! This function is used to reset cache statistics.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_cachectrl_reset_statistics(void)
+{
+ //
+ // Write the bit to reset flash statistics.
+ // Note - this bit is not sticky, no need to write it back to 0.
+ //
+ AM_REG(CACHECTRL, CACHECTRL) |= AM_REG_CACHECTRL_CACHECTRL_RESET_STAT_CLEAR;
+}
+
+//*****************************************************************************
+//
+//! @brief Get flash cache sleep mode status.
+//!
+//! This function returns flash cache sleep mode statuses.
+//!
+//! @return
+//! bit0 indicates that flash0 flash sleep mode is enabled.
+//! bit1 indicates that flash1 flash sleep mode is enabled.
+//
+//*****************************************************************************
+uint32_t
+am_hal_cachectrl_sleep_mode_status(void)
+{
+ uint32_t ui32Status, ui32Ret;
+
+ //
+ // Get the current sleep mode status bits.
+ //
+ ui32Status = AM_REG(CACHECTRL, CACHECTRL);
+ ui32Ret = (ui32Status & \
+ AM_REG_CACHECTRL_CACHECTRL_FLASH0_SLM_STATUS_M) >> \
+ (AM_REG_CACHECTRL_CACHECTRL_FLASH0_SLM_STATUS_S - 0);
+ ui32Ret |= (ui32Status & \
+ AM_REG_CACHECTRL_CACHECTRL_FLASH1_SLM_STATUS_M) >> \
+ (AM_REG_CACHECTRL_CACHECTRL_FLASH1_SLM_STATUS_S - 1);
+
+ return ui32Ret;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable or disable flash cache sleep mode.
+//!
+//! This function enables or disables flash cache sleep mode.
+//! @param ui32EnableMask - bit0 for flash0, bit1 for flash1.
+//! @param ui32DisableMask - bit0 for flash0, bit1 for flash1.
+//!
+//! Note that if both an enable and disable are provided in their respective
+//! masks, the enable will take precedence.
+//!
+//! @return Previous status.
+//! bit0 indicates that flash0 flash sleep mode was previously enabled.
+//! bit1 indicates that flash1 flash sleep mode was previously enabled.
+//
+//*****************************************************************************
+uint32_t
+am_hal_cachectrl_sleep_mode_enable(uint32_t ui32EnableMask,
+ uint32_t ui32DisableMask)
+{
+ uint32_t ui32Ret = am_hal_cachectrl_sleep_mode_status();
+
+ if ( ui32DisableMask & 0x1 )
+ {
+ AM_REG(CACHECTRL, CACHECTRL) |= AM_REG_CACHECTRL_CACHECTRL_FLASH0_SLM_DISABLE_M;
+ }
+
+ if ( ui32DisableMask & 0x2 )
+ {
+ AM_REG(CACHECTRL, CACHECTRL) |= AM_REG_CACHECTRL_CACHECTRL_FLASH1_SLM_DISABLE_M;
+ }
+
+ if ( ui32EnableMask & 0x1 )
+ {
+ AM_REG(CACHECTRL, CACHECTRL) |= AM_REG_CACHECTRL_CACHECTRL_FLASH0_SLM_ENABLE_M;
+ }
+
+ if ( ui32EnableMask & 0x2 )
+ {
+ AM_REG(CACHECTRL, CACHECTRL) |= AM_REG_CACHECTRL_CACHECTRL_FLASH1_SLM_ENABLE_M;
+ }
+
+ return ui32Ret;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.h b/bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.h
new file mode 100644
index 0000000000..b8ce914b94
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_cachectrl.h
@@ -0,0 +1,211 @@
+//*****************************************************************************
+//
+// am_hal_cachectrl.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the CACHE controller.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_CACHECTRL_H
+#define AM_HAL_CACHECTRL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Cache configuration structure
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! Set to 1 to enable the cache.
+ //
+ uint8_t ui32EnableCache;
+
+ //
+ //! Set to 1 to enable the LRU cache replacement policy.
+ //! Set to 0 to enable the LRR (least recently used) replacement policy.
+ //! LEE minimizes writes to the TAG SRAM.
+ //
+ uint8_t ui32LRU;
+
+ //
+ //! Set to 3 to enable non-cachable region 1 and non-cachable region 0.
+ //! Set to 2 to enable non-cachable region 1.
+ //! Set to 1 to enable non-cachable region 0.
+ //! Set to 0 to make all regions cacheable.
+ //
+ uint8_t ui32EnableNCregions;
+
+ //
+ //! Set to:
+ //! AM_HAL_CACHECTRL_CACHECFG_CONFIG_DIRECT_256 for direct-mapped,
+ //! 128-bit linesize, 256 entries (2 SRAMs active)
+ //! AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_256 for two-way set associative,
+ //! 128-bit linesize, 256 entries (4 SRAMs active)
+ //! AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_512 for two-way set associative,
+ //! 128-bit linesize, 512 entries (8 SRAMs active)
+ //
+ uint8_t ui32Config;
+
+ //
+ //! Set to 1 to enable serial cache mode.
+ //
+ uint8_t ui32SerialCacheMode;
+
+ //
+ //! Set to 3 to enable flash data caching and flash instruction caching.
+ //! Set to 2 to enable flash data caching.
+ //! Set to 1 to enable flash instruction caching.
+ //! Set to 0 to disable flash data caching and flash instruction caching.
+ //
+ uint8_t ui32FlashCachingEnables;
+
+ //
+ //! Set to 1 to enable clock gating of cache RAMs.
+ //
+ uint8_t ui32EnableCacheClockGating;
+
+ //
+ //! Set to 1 to enable light sleep of cache RAMs.
+ //
+ uint8_t ui32EnableLightSleep;
+
+ //
+ //! Set Data RAM delay value (0x0 - 0xF).
+ //
+ uint8_t ui32Dly;
+
+ //
+ //! Set SM Data RAM delay value (0x0 - 0xF).
+ //
+ uint8_t ui32SMDly;
+
+ //
+ //! Set to 1 to enable clock gating of the entire data array.
+ //
+ uint8_t ui32EnableDataClockGating;
+
+ //
+ //! Set to 1 to enable cache monitor statistics.
+ //
+ uint8_t ui32EnableCacheMonitoring;
+}
+am_hal_cachectrl_config_t;
+
+extern const am_hal_cachectrl_config_t am_hal_cachectrl_defaults;
+
+//*****************************************************************************
+//
+//! @name Cache enables
+//! @brief Configuration selection for the various cache enables.
+//!
+//! These macros may be used in conjunction with the
+//! am_hal_cachectrl_cache_enable() function to enable various cache features.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CACHECTRL_CACHECFG_ENABLE AM_REG_CACHECTRL_CACHECFG_ENABLE_M
+#define AM_HAL_CACHECTRL_CACHECFG_LRU_ENABLE AM_REG_CACHECTRL_CACHECFG_LRU_M
+#define AM_HAL_CACHECTRL_CACHECFG_NC0_ENABLE AM_REG_CACHECTRL_CACHECFG_ENABLE_NC0_M
+#define AM_HAL_CACHECTRL_CACHECFG_NC1_ENABLE AM_REG_CACHECTRL_CACHECFG_ENABLE_NC1_M
+#define AM_HAL_CACHECTRL_CACHECFG_SERIAL_ENABLE AM_REG_CACHECTRL_CACHECFG_SERIAL_M
+#define AM_HAL_CACHECTRL_CACHECFG_ICACHE_ENABLE AM_REG_CACHECTRL_CACHECFG_ICACHE_ENABLE_M
+#define AM_HAL_CACHECTRL_CACHECFG_DCACHE_ENABLE AM_REG_CACHECTRL_CACHECFG_DCACHE_ENABLE_M
+#define AM_HAL_CACHECTRL_CACHECFG_CACHE_CLKGATE_ENABLE AM_REG_CACHECTRL_CACHECFG_CACHE_CLKGATE_M
+#define AM_HAL_CACHECTRL_CACHECFG_LS_ENABLE AM_REG_CACHECTRL_CACHECFG_CACHE_LS_M
+#define AM_HAL_CACHECTRL_CACHECFG_DATA_CLKGATE_ENABLE AM_REG_CACHECTRL_CACHECFG_DATA_CLKGATE_M
+#define AM_HAL_CACHECTRL_CACHECFG_MONITOR_ENABLE AM_REG_CACHECTRL_CACHECFG_ENABLE_MONITOR_M
+//! @}
+
+//*****************************************************************************
+//
+//! @name Cache Config
+//! @brief Configuration selection for the cache.
+//!
+//! These macros may be used in conjunction with the
+//! am_hal_cachectrl_cache_config() function to select the cache type.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CACHECTRL_CACHECFG_CONFIG_DIRECT_256 AM_REG_CACHECTRL_CACHECFG_CONFIG_W1_128B_256E
+#define AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_256 AM_REG_CACHECTRL_CACHECFG_CONFIG_W2_128B_256E
+#define AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_512 AM_REG_CACHECTRL_CACHECFG_CONFIG_W2_128B_512E
+//! @}
+
+//*****************************************************************************
+//
+// Default cache settings
+//
+//*****************************************************************************
+#define AM_HAL_CACHECTRL_DEFAULTS \
+ (AM_HAL_CACHECTRL_CACHECFG_ICACHE_ENABLE | \
+ AM_HAL_CACHECTRL_CACHECFG_DCACHE_ENABLE | \
+ AM_HAL_CACHECTRL_CACHECFG_CACHE_CLKGATE_ENABLE | \
+ AM_HAL_CACHECTRL_CACHECFG_DATA_CLKGATE_ENABLE | \
+ AM_HAL_CACHECTRL_CACHECFG_CONFIG_2WAY_512)
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_cachectrl_enable(const am_hal_cachectrl_config_t *psConfig);
+extern void am_hal_cachectrl_disable(void);
+extern void am_hal_cachectrl_config_default(void);
+extern void am_hal_cachectrl_config(am_hal_cachectrl_config_t *psConfig);
+extern uint32_t am_hal_cachectrl_cache_enables(uint32_t u32EnableMask,
+ uint32_t u32DisableMask);
+extern void am_hal_cachectrl_cache_config(uint32_t ui32CacheConfig);
+extern void am_hal_cachectrl_invalidate_flash_cache(void);
+extern void am_hal_cachectrl_reset_statistics(void);
+extern uint32_t am_hal_cachectrl_sleep_mode_status(void);
+extern uint32_t am_hal_cachectrl_sleep_mode_enable(uint32_t ui32EnableMask,
+ uint32_t ui32DisableMask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_CACHECTRL_H
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.c b/bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.c
new file mode 100644
index 0000000000..d60d7e47b5
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.c
@@ -0,0 +1,491 @@
+//*****************************************************************************
+//
+// am_hal_clkgen.c
+//! @file
+//!
+//! @brief Functions for interfacing with the CLKGEN.
+//!
+//! @addtogroup clkgen2 Clock Generator (CLKGEN)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// CLKGEN HFADJ register
+//
+//*****************************************************************************
+#define AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT 0x5B8
+
+//*****************************************************************************
+//
+//! @brief Select the clock divisor for the main system clock.
+//!
+//! @param ui32ClockSetting - The divisor value for the system clock.
+//!
+//! This function can be used to select the frequency of the main system clock.
+//! The \e ui32ClockSetting parameter should be set to one of the following
+//! values:
+//!
+//! AM_HAL_CLKGEN_SYSCLK_MAX
+//! AM_HAL_CLKGEN_SYSCLK_48MHZ
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_sysclk_select(uint32_t ui32ClockSetting)
+{
+ am_hal_debug_assert_msg(ui32ClockSetting == AM_HAL_CLKGEN_SYSCLK_48MHZ,
+ "am_hal_clkgen_sysclk_select(): invalid clock setting.");
+
+ //
+ // Unlock the clock control register.
+ //
+ AM_REG(CLKGEN, CLKKEY) = AM_REG_CLKGEN_CLKKEY_KEYVAL;
+
+ //
+ // Set the HFRC divisor to the user-selected value.
+ //
+ AM_REG(CLKGEN, CCTRL) = ui32ClockSetting;
+
+ //
+ // Lock the clock configuration registers.
+ //
+ AM_REG(CLKGEN, CLKKEY) = 0;
+}
+
+//*****************************************************************************
+//
+//! @brief Get the current system clock frequency.
+//!
+//! This function can be used to determine the frequency of the main system
+//! clock. The return value is the system clock frequency measured in hertz.
+//!
+//! @return System clock frequency in Hz
+//
+//*****************************************************************************
+uint32_t
+am_hal_clkgen_sysclk_get(void)
+{
+ uint32_t ui32ClockSetting;
+
+ //
+ // Read the value of the clock divider.
+ //
+ ui32ClockSetting = AM_REG(CLKGEN, CCTRL) & AM_REG_CLKGEN_CCTRL_CORESEL_M;
+
+ switch ( ui32ClockSetting )
+ {
+ case AM_REG_CLKGEN_CCTRL_CORESEL_HFRC:
+ return 48000000;
+ case AM_REG_CLKGEN_CCTRL_CORESEL_HFRC_DIV2:
+ return 24000000;
+ default:
+ return 0xFFFFFFFF;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Enable selected CLKGEN Interrupts.
+//!
+//! Use this function to enable the interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_clkgen.h
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_clkgen_int_enable(uint32_t ui32Interrupt)
+{
+ //
+ // Enable the interrupts.
+ //
+ AM_REG(CLKGEN, INTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return enabled CLKGEN Interrupts.
+//!
+//! Use this function to get all enabled CLKGEN interrupts.
+//!
+//! @return enabled CLKGEN interrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_clkgen_int_enable_get(void)
+{
+ //
+ // Return the enabled interrupts.
+ //
+ return AM_REG(CLKGEN, INTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable selected CLKGEN Interrupts.
+//!
+//! Use this function to disable the CLKGEN interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_clkgen.h
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_clkgen_int_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Disable the interrupts.
+ //
+ AM_REG(CLKGEN, INTEN) &= ~ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Sets the interrupt status.
+//!
+//! @param ui32IntFlags interrupts to be enabled.
+//!
+//! This function sets the interrupts.
+//!
+//! Valid values for ui32IntFlags are:
+//!
+//! AM_HAL_CLKGEN_INT_RTC_ALARM
+//! AM_HAL_CLKGEN_INT_XT_FAIL
+//! AM_HAL_CLKGEN_INT_AUTOCAL_COMPLETE
+//! AM_HAL_CLKGEN_INT AUTOCAL_FAIL
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Set the interrupt status.
+ //
+ AM_REG(CLKGEN, INTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Gets the interrupt configuration.
+//!
+//! @param bEnabledOnly - return the status of only the enabled interrupts.
+//!
+//! This function gets the currently configured interrupts.
+//!
+//! @return the configured interrupts.
+//!
+//! Possible values for the return are:
+//!
+//! AM_HAL_CLKGEN_INT_RTC_ALARM
+//! AM_HAL_CLKGEN_INT_XT_FAIL
+//! AM_HAL_CLKGEN_INT_AUTOCAL_COMPLETE
+//! AM_HAL_CLKGEN_INT AUTOCAL_FAIL
+//
+//*****************************************************************************
+uint32_t
+am_hal_clkgen_int_status_get(bool bEnabledOnly)
+{
+ //
+ // Return the status.
+ //
+ if ( bEnabledOnly )
+ {
+ uint32_t u32RetVal = AM_REG(CLKGEN, INTSTAT);
+ u32RetVal &= AM_REG(CLKGEN, INTEN);
+ return u32RetVal;
+ }
+ else
+ {
+ return AM_REG(CLKGEN, INTSTAT);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Clears the interrupts.
+//!
+//! @param ui32IntFlags interrupts to be cleared.
+//!
+//! This function clears the interrupts.
+//!
+//! Valid values for ui32IntFlags are:
+//!
+//! AM_HAL_CLKGEN_INT_RTC_ALARM
+//! AM_HAL_CLKGEN_INT_XT_FAIL
+//! AM_HAL_CLKGEN_INT_AUTOCAL_COMPLETE
+//! AM_HAL_CLKGEN_INT AUTOCAL_FAIL
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Clear the interrupts.
+ //
+ AM_REG(CLKGEN, INTCLR) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Starts the desired oscillator(s) (OSC).
+//!
+//! @param ui32OscFlags oscillator(s) to start.
+//!
+//! This function starts the desired oscillator(s) (OSC).
+//!
+//! Valid values for ui32OscFlags are:
+//!
+//! AM_HAL_CLKGEN_OSC_LFRC
+//! AM_HAL_CLKGEN_OSC_XT
+//!
+//! @return 0 None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_osc_start(uint32_t ui32OscFlags)
+{
+ //
+ // Start the oscillator(s).
+ //
+ AM_REG(CLKGEN, OCTRL) &= ~ui32OscFlags;
+}
+
+//*****************************************************************************
+//
+//! @brief Stops the desired oscillator(s) (OSC).
+//!
+//! @param ui32OscFlags oscillator(s) to stop.
+//!
+//! This function stops the desired oscillator(s) (OSC).
+//!
+//! Valid values for ui32OscFlags are:
+//!
+//! AM_HAL_CLKGEN_OSC_LFRC
+//! AM_HAL_CLKGEN_OSC_XT
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_osc_stop(uint32_t ui32OscFlags)
+{
+ //
+ // Stop the oscillator(s).
+ //
+ AM_REG(CLKGEN, OCTRL) |= ui32OscFlags;
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the clock out signal.
+//!
+//! @param ui32Signal desired location for the clock out signal.
+//!
+//! This function enables the clock out signal. See am_hal_clkgen.h for
+//! available signals.
+//!
+//! e.g. AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC
+//! AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV4
+//! AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_clkout_enable(uint32_t ui32Signal)
+{
+ //
+ // Enable the clock out on desired signal.
+ //
+ AM_REG(CLKGEN, CLKOUT) = AM_REG_CLKGEN_CLKOUT_CKEN_M | ui32Signal;
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the clock out signal.
+//!
+//! This function disables the clock out signal.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_clkout_disable(void)
+{
+ //
+ // Disable the clock out.
+ //
+ AM_REG(CLKGEN, CLKOUT) = 0;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable UART system clock.
+//!
+//! This function enables or disables the UART system clock.
+//!
+//! @param ui32Module is 0 or 1 for Apollo2.
+//! @param ui32UartEn is one of the following.
+//! AM_HAL_CLKGEN_UARTEN_DIS
+//! AM_HAL_CLKGEN_UARTEN_EN
+//! AM_HAL_CLKGEN_UARTEN_REDUCE_FREQ
+//! AM_HAL_CLKGEN_UARTEN_EN_POWER_SAV
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_uarten_set(uint32_t ui32Module, uint32_t ui32UartEn)
+{
+ uint32_t ui32Mask;
+
+ if ( (ui32Module >= AM_REG_UART_NUM_MODULES) ||
+ (ui32UartEn > AM_HAL_CLKGEN_UARTEN_EN_POWER_SAV) )
+ {
+ return;
+ }
+
+ ui32UartEn <<= (ui32Module * AM_HAL_CLKGEN_UARTEN_UARTENn_S(ui32Module));
+ ui32Mask = ~(AM_HAL_CLKGEN_UARTEN_UARTENn_M(ui32Module));
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Set the UART clock
+ //
+ AM_REG(CLKGEN, UARTEN) &= ui32Mask;
+ AM_REG(CLKGEN, UARTEN) |= ui32UartEn;
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_END_ASM
+}
+
+//*****************************************************************************
+//
+//! @brief Enables HFRC auto-adjustment at the specified interval.
+//!
+//! @param ui32Warmup - How long to give the HFRC to stabilize during each
+//! calibration attempt.
+//! @param ui32Frequency - How often the auto-adjustment should happen.
+//!
+//! This function enables HFRC auto-adjustment from an external crystal
+//! oscillator even when the crystal is not normally being used.
+//!
+//! ui32Warmup should be one of the following values:
+//!
+//! AM_REG_CLKGEN_HFADJ_HFWARMUP_1SEC
+//! AM_REG_CLKGEN_HFADJ_HFWARMUP_2SEC
+//!
+//! ui32Frequency should be one of the following values:
+//!
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_4SEC
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_16SEC
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_32SEC
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_64SEC
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_128SEC
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_256SEC
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_512SEC
+//! AM_REG_CLKGEN_HFADJ_HFADJCK_1024SEC
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_hfrc_adjust_enable(uint32_t ui32Warmup, uint32_t ui32Frequency)
+{
+ //
+ // Set the HFRC Auto-adjust register for the user's chosen settings. Assume
+ // that the HFRC should be calibrated to 48 MHz and that the crystal is
+ // running at 32.768 kHz.
+ //
+ AM_REG(CLKGEN, HFADJ) =
+ AM_REG_CLKGEN_HFADJ_HFADJ_GAIN_Gain_of_1_in_2 |
+ ui32Warmup |
+ AM_REG_CLKGEN_HFADJ_HFXTADJ(AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT) |
+ ui32Frequency |
+ AM_REG_CLKGEN_HFADJ_HFADJEN_EN;
+}
+
+//*****************************************************************************
+//
+//! @brief Disables HFRC auto-adjustment.
+//!
+//! This function disables HFRC auto-adjustment.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_clkgen_hfrc_adjust_disable(void)
+{
+ //
+ // Disable the clock out.
+ //
+ AM_REG(CLKGEN, HFADJ) =
+ AM_REG_CLKGEN_HFADJ_HFADJ_GAIN_Gain_of_1_in_2 |
+ AM_REG_CLKGEN_HFADJ_HFWARMUP_1SEC |
+ AM_REG_CLKGEN_HFADJ_HFXTADJ(AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT) |
+ AM_REG_CLKGEN_HFADJ_HFADJCK_4SEC |
+ AM_REG_CLKGEN_HFADJ_HFADJEN_DIS;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.h b/bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.h
new file mode 100644
index 0000000000..fc50cb9b43
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_clkgen.h
@@ -0,0 +1,206 @@
+//*****************************************************************************
+//
+// am_hal_clkgen.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the CLKGEN.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_CLKGEN_H
+#define AM_HAL_CLKGEN_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! @name System Clock max frequency
+//! @brief Defines the maximum clock frequency for this device.
+//!
+//! These macros provide a definition of the maximum clock frequency.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CLKGEN_FREQ_MAX_HZ 48000000
+#define AM_HAL_CLKGEN_FREQ_MAX_MHZ (AM_HAL_CLKGEN_FREQ_MAX_HZ / 1000000)
+//! @}
+
+//*****************************************************************************
+//
+//! @name System Clock Selection
+//! @brief Divisor selection for the main system clock.
+//!
+//! These macros may be used along with the am_hal_clkgen_sysctl_select()
+//! function to select the frequency of the main system clock.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CLKGEN_SYSCLK_MAX AM_REG_CLKGEN_CCTRL_CORESEL_HFRC
+#define AM_HAL_CLKGEN_SYSCLK_48MHZ AM_REG_CLKGEN_CCTRL_CORESEL_HFRC
+//! @}
+
+//*****************************************************************************
+//
+//! @name Interrupt Status Bits
+//! @brief Interrupt Status Bits for enable/disble use
+//!
+//! These macros may be used to set and clear interrupt bits.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CLKGEN_INT_ALM AM_REG_CLKGEN_INTEN_ALM_M
+#define AM_HAL_CLKGEN_INT_OF AM_REG_CLKGEN_INTEN_OF_M
+#define AM_HAL_CLKGEN_INT_ACC AM_REG_CLKGEN_INTEN_ACC_M
+#define AM_HAL_CLKGEN_INT_ACF AM_REG_CLKGEN_INTEN_ACF_M
+//! @}
+
+//*****************************************************************************
+//
+//! @name OSC Start and Stop
+//! @brief OSC Start and Stop defines.
+//!
+//! OSC Start and Stop defines to be used with \e am_hal_clkgen_osc_x().
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CLKGEN_OSC_LFRC AM_REG_CLKGEN_OCTRL_STOPRC_M
+#define AM_HAL_CLKGEN_OSC_XT AM_REG_CLKGEN_OCTRL_STOPXT_M
+//! @}
+
+//*****************************************************************************
+//
+// OSC Start, Stop, Select defines
+//
+//*****************************************************************************
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC AM_REG_CLKGEN_CLKOUT_CKSEL_LFRC
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV2 AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV2
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV4 AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV4
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV8 AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV8
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV16 AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV16
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV32 AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV32
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_RTC_100Hz AM_REG_CLKGEN_CLKOUT_CKSEL_RTC_100Hz
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV2M AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV2M
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT AM_REG_CLKGEN_CLKOUT_CKSEL_XT
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_CG_100Hz AM_REG_CLKGEN_CLKOUT_CKSEL_CG_100Hz
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV4 AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV4
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV8 AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV8
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV32 AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV32
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV64 AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV64
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV128 AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV128
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV256 AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV256
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_CORE_CLK AM_REG_CLKGEN_CLKOUT_CKSEL_CORE_CLK
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_FLASH_CLK AM_REG_CLKGEN_CLKOUT_CKSEL_FLASH_CLK
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC_DIV2 AM_REG_CLKGEN_CLKOUT_CKSEL_LFRC_DIV2
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC_DIV32 AM_REG_CLKGEN_CLKOUT_CKSEL_LFRC_DIV32
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC_DIV512 AM_REG_CLKGEN_CLKOUT_CKSEL_LFRC_DIV512
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC_DIV32K AM_REG_CLKGEN_CLKOUT_CKSEL_LFRC_DIV32K
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV256 AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV256
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV8K AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV8K
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XT_DIV64K AM_REG_CLKGEN_CLKOUT_CKSEL_XT_DIV64K
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV16 AM_REG_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV16
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV128 AM_REG_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV128
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_ULFRC_1Hz AM_REG_CLKGEN_CLKOUT_CKSEL_ULFRC_1Hz
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV4K AM_REG_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV4K
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV1M AM_REG_CLKGEN_CLKOUT_CKSEL_ULFRC_DIV1M
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV64K AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV64K
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV16M AM_REG_CLKGEN_CLKOUT_CKSEL_HFRC_DIV16M
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC_DIV2M AM_REG_CLKGEN_CLKOUT_CKSEL_LFRC_DIV2M
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRCNE AM_REG_CLKGEN_CLKOUT_CKSEL_HFRCNE
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRCNE_DIV8 AM_REG_CLKGEN_CLKOUT_CKSEL_HFRCNE_DIV8
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_CORE_CLKNE AM_REG_CLKGEN_CLKOUT_CKSEL_CORE_CLKNE
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XTNE AM_REG_CLKGEN_CLKOUT_CKSEL_XTNE
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_XTNE_DIV16 AM_REG_CLKGEN_CLKOUT_CKSEL_XTNE_DIV16
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRCNE_DIV32 AM_REG_CLKGEN_CLKOUT_CKSEL_LFRCNE_DIV32
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_FCLKNE AM_REG_CLKGEN_CLKOUT_CKSEL_FCLKNE
+#define AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRCNE AM_REG_CLKGEN_CLKOUT_CKSEL_LFRCNE
+
+//*****************************************************************************
+//
+// UARTEN
+//
+//*****************************************************************************
+#define AM_HAL_CLKGEN_UARTEN_DIS AM_REG_CLKGEN_UARTEN_UART0EN_DIS
+#define AM_HAL_CLKGEN_UARTEN_EN AM_REG_CLKGEN_UARTEN_UART0EN_EN
+#define AM_HAL_CLKGEN_UARTEN_REDUCE_FREQ AM_REG_CLKGEN_UARTEN_UART0EN_REDUCE_FREQ
+#define AM_HAL_CLKGEN_UARTEN_EN_POWER_SAV AM_REG_CLKGEN_UARTEN_UART0EN_EN_POWER_SAV
+
+#define AM_HAL_CLKGEN_UARTEN_UARTENn_S(module) \
+ ((module) * \
+ (AM_REG_CLKGEN_UARTEN_UART1EN_S - AM_REG_CLKGEN_UARTEN_UART0EN_S))
+
+#define AM_HAL_CLKGEN_UARTEN_UARTENn_M(module) \
+ (AM_REG_CLKGEN_UARTEN_UART0EN_M << AM_HAL_CLKGEN_UARTEN_UARTENn_S(module))
+
+//
+// UARTEN: entype is one of DIS, EN, REDUCE_FREQ, EN_POWER_SAV.
+//
+#define AM_HAL_CLKGEN_UARTEN_UARTENn(module, entype) \
+ (AM_REG_CLKGEN_UARTEN_UART0EN_##entype << \
+ AM_HAL_CLKGEN_UARTEN_UARTENn_S(module))
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_clkgen_sysclk_select(uint32_t ui32ClockSetting);
+extern uint32_t am_hal_clkgen_sysclk_get(void);
+extern void am_hal_clkgen_osc_start(uint32_t ui32OscFlags);
+extern void am_hal_clkgen_osc_stop(uint32_t ui32OscFlags);
+extern void am_hal_clkgen_clkout_enable(uint32_t ui32Signal);
+extern void am_hal_clkgen_clkout_disable(void);
+extern void am_hal_clkgen_uarten_set(uint32_t ui32Module, uint32_t ui32UartEn);
+extern void am_hal_clkgen_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_clkgen_int_enable_get(void);
+extern void am_hal_clkgen_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_clkgen_int_clear(uint32_t ui32Interrupt);
+extern void am_hal_clkgen_int_set(uint32_t ui32Interrupt);
+extern uint32_t am_hal_clkgen_int_status_get(bool bEnabledOnly);
+extern void am_hal_clkgen_hfrc_adjust_enable(uint32_t ui32Warmup, uint32_t ui32Frequency);
+extern void am_hal_clkgen_hfrc_adjust_disable(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_CLKGEN_H
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.c b/bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.c
new file mode 100644
index 0000000000..13fc3c07cc
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.c
@@ -0,0 +1,1687 @@
+//*****************************************************************************
+//
+// am_hal_ctimer.c
+//! @file
+//!
+//! @brief Functions for interfacing with the Counter/Timer module.
+//!
+//! @addtogroup ctimer2 Counter/Timer (CTIMER)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Address space distance between timer configuration registers.
+//
+//*****************************************************************************
+#define MAX_CTIMERS 4
+#define TIMER_OFFSET (AM_REG_CTIMER_TMR1_O - AM_REG_CTIMER_TMR0_O)
+#define CTIMER_CMPR_OFFSET (AM_REG_CTIMER_CMPRB0_O - AM_REG_CTIMER_CMPRA0_O)
+
+//*****************************************************************************
+//
+// Adjacency check
+//
+// This is related to the timer read workaround. This macro checks to see if
+// the two supplied count values are within one "tick" of eachother. It should
+// still pass in the event of a timer rollover.
+//
+//*****************************************************************************
+#define adjacent(A, B) (((A) == (B)) || (((A) + 1) == (B)) || ((B) == 0))
+
+//*****************************************************************************
+//
+// Array of function pointers for handling CTimer interrupts.
+//
+//*****************************************************************************
+am_hal_ctimer_handler_t am_hal_ctimer_ppfnHandlers[16];
+
+//*****************************************************************************
+//
+// Static function for reading the timer value.
+//
+//*****************************************************************************
+#if defined(__GNUC_STDC_INLINE__)
+__attribute__((naked))
+static
+void
+back2back_reads(uint32_t u32TimerAddr, uint32_t u32Data[])
+{
+ // u32TimerAddr = address of the timer to be read.
+ // u32Data[] is a pointer to a 3 word data array provided by the caller.
+ __asm
+ (
+ // Do 3 back-to-back reads of the register
+ " push {r4}\n" // Save r4
+ " push {r1}\n" // Save the data array ptr for later
+ " mov r2, r0\n" // Get Timer Addr
+ " mrs r4, PRIMASK\n" // Save PRIMASK
+ " cpsid i\n" // __disable_irq()
+ " nop\n" // Give the disable a cycle to take affect (but almost certainly not really needed)
+ " ldr r0, [r2, #0]\n" // Get TMRn register value
+ " ldr r1, [r2, #0]\n" // Get TMRn register value again
+ " ldr r3, [r2, #0]\n" // Get TMRn register value for a third time
+ " msr PRIMASK, r4\n" // Restore PRIMASK
+ " pop {r2}\n" // Get the array ptr
+ " str r0, [r2, #0]\n" // Store register value to variable
+ " str r1, [r2, #4]\n" // Store register value to variable
+ " str r3, [r2, #8]\n" // Store register value to variable
+ " pop {r4}\n" // restore r4
+ " bx lr\n"
+ );
+}
+
+#elif defined(__ARMCC_VERSION)
+__asm static uint32_t
+back2back_reads( uint32_t u32TimerAddr, uint32_t u32Data[])
+{
+ push {r4} // Save r4
+ push {r1} // Save the data array ptr for later
+ mov r2, r0 // Get Timer Addr
+ mrs r4, PRIMASK // Save PRIMASK
+ cpsid i // __disable_irq()
+ nop // Give the disable a cycle to take affect (but almost certainly not really needed)
+ ldr r0, [r2, #0] // Get TMRn register value
+ ldr r1, [r2, #0] // Get TMRn register value again
+ ldr r3, [r2, #0] // Get TMRn register value for a third time
+ msr PRIMASK, r4 // Restore PRIMASK
+ pop {r2} // Get the array ptr
+ str r0, [r2, #0] // Store register value to variable
+ str r1, [r2, #4] // Store register value to variable
+ str r3, [r2, #8] // Store register value to variable
+ pop {r4} // Restore r4
+ bx lr
+}
+
+#elif defined(__IAR_SYSTEMS_ICC__)
+#pragma diag_suppress = Pe940 // Suppress IAR compiler warning about missing
+ // return statement on a non-void function
+__stackless static uint32_t
+back2back_reads( uint32_t u32TimerAddr, uint32_t u32Data[])
+{
+ __asm(" push {r4}"); // Save r4
+ __asm(" push {r1}"); // Save the data array ptr for later
+ __asm(" mov r2, r0"); // Get Timer Addr
+ __asm(" mrs r4, PRIMASK"); // Save PRIMASK"
+ __asm(" cpsid i"); // __disable_irq()
+ __asm(" nop"); // Give the disable a cycle to take affect (but almost certainly not really needed)
+ __asm(" ldr r0, [r2, #0]"); // Get TMRn register value
+ __asm(" ldr r1, [r2, #0]"); // Get TMRn register value again
+ __asm(" ldr r3, [r2, #0]"); // Get TMRn register value for a third time
+ __asm(" msr PRIMASK, r4"); // Restore PRIMASK
+ __asm(" pop {r2}"); // Get the array ptr
+ __asm(" str r0, [r2, #0]"); // Store register value to variable
+ __asm(" str r1, [r2, #4]"); // Store register value to variable
+ __asm(" str r3, [r2, #8]"); // Store register value to variable
+ __asm(" pop {r4}"); // Restore r4
+ __asm(" bx lr");
+}
+#pragma diag_default = Pe940 // Restore IAR compiler warning
+#endif
+
+//*****************************************************************************
+//
+// @brief Check to see if the given CTimer is using the HFRC
+//
+// Note - Calls to this function should be from inside a critical section.
+//
+//! @return None.
+//
+//*****************************************************************************
+static bool
+ctimer_source_hfrc(uint32_t ui32CtimerNum)
+{
+ uint32_t *pui32ConfigReg;
+ uint32_t ui32TimerASrc, ui32TimerBSrc;
+
+ //
+ // Find the correct register to write.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32CtimerNum * TIMER_OFFSET));
+
+ //
+ // Determine if this timer is using HFRC as the clock source.
+ // The value we are looking for is HFRC_DIV4 to HFRC_DIV4K.
+ // Get the clock sources and 0-base the extracted value.
+ //
+ ui32TimerASrc = AM_BFX(CTIMER, CTRL0, TMRA0CLK, *pui32ConfigReg) -
+ AM_ENUMX(CTIMER, CTRL0, TMRA0CLK, HFRC_DIV4);
+ ui32TimerBSrc = AM_BFX(CTIMER, CTRL0, TMRB0CLK, *pui32ConfigReg) -
+ AM_ENUMX(CTIMER, CTRL0, TMRB0CLK, HFRC_DIV4);
+
+ //
+ // If the source value is 0 to (HFRC_DIV4K - HFRC_DIV4), then it's HFRC.
+ //
+ if ( (ui32TimerASrc <= (AM_ENUMX(CTIMER, CTRL0, TMRA0CLK, HFRC_DIV4K) -
+ AM_ENUMX(CTIMER, CTRL0, TMRA0CLK, HFRC_DIV4))) ||
+ (ui32TimerBSrc <= (AM_ENUMX(CTIMER, CTRL0, TMRB0CLK, HFRC_DIV4K) -
+ AM_ENUMX(CTIMER, CTRL0, TMRB0CLK, HFRC_DIV4))) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+} // ctimer_source_hfrc()
+
+//*****************************************************************************
+//
+// @brief Check to see if any of the CTimers or STimer are using the HFRC.
+//
+// This function should be used to check if the HFRC is being used in order
+// to correctly establish power related settings.
+//
+// Note - Calls to this function should be from inside a critical section.
+//
+//! @return None.
+//
+//*****************************************************************************
+static bool
+timers_use_hfrc(void)
+{
+ uint32_t ui32TimerASrc, ui32CtimerNum;
+
+ //
+ // Check STimer to see if it is using HFRC.
+ //
+ ui32TimerASrc = AM_BFR(CTIMER, STCFG, CLKSEL);
+ if ( (ui32TimerASrc == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV16) ||
+ (ui32TimerASrc == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV256) )
+ {
+ return true;
+ }
+
+ //
+ // Check the CTimers to see if any are using HFRC as their clock source.
+ //
+ for ( ui32CtimerNum = 0; ui32CtimerNum < MAX_CTIMERS; ui32CtimerNum++ )
+ {
+ if ( ctimer_source_hfrc(ui32CtimerNum) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+
+} // timers_use_hfrc()
+
+//*****************************************************************************
+//
+//! @brief Convenience function for responding to CTimer interrupts.
+//!
+//! @param ui32Status is the interrupt status as returned by
+//! am_hal_ctimer_int_status_get()
+//!
+//! This function may be called from am_ctimer_isr() to read the status of
+//! the CTimer interrupts, determine which source caused the most recent
+//! interrupt, and call an interrupt handler function to respond. The interrupt
+//! handler to be called must be first registered with the
+//! am_hal_ctimer_int_register() function.
+//!
+//! In the event that multiple sources are active, the corresponding
+//! interrupt handlers will be called in numerical order based on interrupt def.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_int_service(uint32_t ui32Status)
+{
+ uint32_t ui32Clz;
+
+ am_hal_ctimer_handler_t pfnHandler;
+
+ ui32Status &= 0xFFFF;
+
+ while ( ui32Status )
+ {
+ //
+ // Pick one of any remaining active interrupt bits
+ //
+#ifdef __IAR_SYSTEMS_ICC__
+ ui32Clz = __CLZ(ui32Status);
+#else
+ ui32Clz = __builtin_clz(ui32Status);
+#endif
+
+ //
+ // Turn off the bit we picked in the working copy
+ //
+ ui32Status &= ~(0x80000000 >> ui32Clz);
+
+ //
+ // Check the bit handler table to see if there is an interrupt handler
+ // registered for this particular bit.
+ //
+ pfnHandler = am_hal_ctimer_ppfnHandlers[31 - ui32Clz];
+ if ( pfnHandler )
+ {
+ //
+ // If we found an interrupt handler routine, call it now.
+ //
+ pfnHandler();
+ }
+ }
+} // am_hal_ctimer_int_service()
+
+//*****************************************************************************
+//
+//! @brief Register an interrupt handler for CTimer.
+//!
+//! @param ui32Interrupt - interrupt number to assign this interrupt handler to.
+//! @param pfnHandler - Function to call when this interrupt is received.
+//!
+//! This function allows the caller to specify a function that should be called
+//! any time a Ctimer interrupt is received. Registering an
+//! interrupt handler using this function adds the function pointer to an array
+//! in SRAM. This interrupt handler will be called by am_hal_ctimer_int_service()
+//! whenever the ui32Status parameter indicates that the corresponding interrupt.
+//!
+//! To remove an interrupt handler that has already been registered, the
+//! pfnHandler parameter may be set to zero.
+//!
+//! @note This function will not have any effect unless the
+//! am_hal_ctimer_int_service() function is being used.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_int_register(uint32_t ui32Interrupt,
+ am_hal_ctimer_handler_t pfnHandler)
+{
+ uint32_t intIdx = 0;
+
+ //
+ // Check to make sure the interrupt number is valid. (Debug builds only)
+ //
+ switch (ui32Interrupt)
+ {
+ case AM_REG_CTIMER_INTEN_CTMRA0C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA0C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB0C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB0C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRA1C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA1C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB1C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB1C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRA2C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA2C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB2C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB2C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRA3C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA3C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB3C0INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB3C0INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRA0C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA0C1INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB0C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB0C1INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRA1C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA1C1INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB1C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB1C1INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRA2C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA2C1INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB2C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB2C1INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRA3C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRA3C1INT_S;
+ break;
+
+ case AM_REG_CTIMER_INTEN_CTMRB3C1INT_M:
+ intIdx = AM_REG_CTIMER_INTEN_CTMRB3C1INT_S;
+ break;
+
+ default:
+ am_hal_debug_assert_msg(false, "CTimer interrupt number out of range.");
+ }
+
+ am_hal_ctimer_ppfnHandlers[intIdx] = pfnHandler;
+
+} // am_hal_ctimer_int_register()
+
+//*****************************************************************************
+//
+//! @brief Set up the counter/timer.
+//!
+//! @param ui32TimerNumber is the number of the Timer that should be
+//! configured.
+//!
+//! @param psConfig is a pointer to a structure that holds important settings
+//! for the timer.
+//!
+//! This function should be used to perform the initial set-up of the
+//! counter-timer.
+//!
+//! @note This function will eventually be replaced by
+//! am_hal_ctimer_config_single(), which performs the same configuration
+//! without requiring a structure. Please use am_hal_ctimer_config_single() for
+//! new development.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_config(uint32_t ui32TimerNumber,
+ am_hal_ctimer_config_t *psConfig)
+{
+ uint32_t *pui32ConfigReg;
+ uint32_t ui32ConfigVal;
+
+ //
+ // Start preparing the configuration word for this timer. The configuration
+ // values for Timer A and Timer B provided in the config structure should
+ // match the register definitions already, so we will mostly just need to
+ // OR them together.
+ //
+ ui32ConfigVal = ( (psConfig->ui32TimerAConfig) |
+ (psConfig->ui32TimerBConfig << 16) );
+
+ //
+ // OR in the Link bit if the timers need to be linked.
+ //
+ ui32ConfigVal |= psConfig->ui32Link ? AM_HAL_CTIMER_LINK : 0;
+
+ //
+ // Begin critical section while config registers are read and modified.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Find the correct register to write.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Write our configuration value.
+ //
+ AM_REGVAL(pui32ConfigReg) = ui32ConfigVal;
+
+ //
+ // If all of the clock sources are not HRFC disable LDO when sleeping if timers are enabled.
+ //
+ if ( timers_use_hfrc() )
+ {
+ AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 0);
+ }
+ else
+ {
+ AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 1);
+ }
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+
+} // am_hal_ctimer_config()
+
+//*****************************************************************************
+//
+//! @brief Set up the counter/timer.
+//!
+//! @param ui32TimerNumber is the number of the Timer that should be
+//! configured.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer should be
+//! enabled.
+//!
+//! @param ui32Configval specifies the configuration options for the selected
+//! timer.
+//!
+//! This function should be used to perform the initial set-up of the
+//! counter-timer. It can be used to configure either a 16-bit timer (A or B) or a
+//! 32-bit timer using the BOTH option.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! The timer's clock source, mode, interrupt, and external pin behavior are
+//! all controlled through the \e ui32Configval parameter. The valid options
+//! for ui32ConfigVal include any ORed together combination of the following:
+//!
+//! Clock configuration macros:
+//!
+//! AM_HAL_CTIMER_HFRC_24MHZ
+//! AM_HAL_CTIMER_LFRC_512HZ
+//! ... etc. (See am_hal_ctimer.h for the full set of options.)
+//!
+//! Mode selection macros:
+//!
+//! AM_HAL_CTIMER_FN_ONCE
+//! AM_HAL_CTIMER_FN_REPEAT
+//! AM_HAL_CTIMER_FN_PWM_ONCE
+//! AM_HAL_CTIMER_FN_PWM_REPEAT
+//! AM_HAL_CTIMER_FN_CONTINUOUS
+//!
+//! Interrupt control:
+//!
+//! AM_HAL_CTIMER_INT_ENABLE
+//!
+//! Pin control:
+//!
+//! AM_HAL_CTIMER_PIN_ENABLE
+//! AM_HAL_CTIMER_PIN_INVERT
+//!
+//! ADC trigger (Timer 3 only):
+//!
+//! AM_HAL_CTIMER_ADC_TRIG
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_config_single(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment,
+ uint32_t ui32ConfigVal)
+{
+ volatile uint32_t *pui32ConfigReg;
+ uint32_t ui32WriteVal;
+
+ //
+ // Find the correct register to write based on the timer number.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section while config registers are read and modified.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Save the value that's already in the register.
+ //
+ ui32WriteVal = AM_REGVAL(pui32ConfigReg);
+
+ //
+ // If we're working with TIMERB, we need to shift our configuration value
+ // up by 16 bits.
+ //
+
+ if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
+ {
+ ui32ConfigVal = ((ui32ConfigVal & 0xFFFF) << 16);
+ }
+
+ //
+ // Replace part of the saved register value with the configuration value
+ // from the caller.
+ //
+ ui32WriteVal = (ui32WriteVal & ~(ui32TimerSegment)) | ui32ConfigVal;
+
+ //
+ // If we're configuring both timers, we need to set the "link" bit.
+ //
+ if ( ui32TimerSegment == AM_HAL_CTIMER_BOTH )
+ {
+ ui32WriteVal |= AM_HAL_CTIMER_LINK;
+ }
+
+ //
+ // Write our completed configuration value.
+ //
+ AM_REGVAL(pui32ConfigReg) = ui32WriteVal;
+
+ //
+ // If all of the clock sources are not HRFC disable LDO when sleeping if timers are enabled.
+ //
+ if ( timers_use_hfrc() )
+ {
+ AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 0);
+ }
+ else
+ {
+ AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 1);
+ }
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+
+} // am_hal_ctimer_config_single()
+
+//*****************************************************************************
+//
+//! @brief Start a timer
+//!
+//! @param ui32TimerNumber is the number of the timer to enable
+//!
+//! @param ui32TimerSegment specifies which segment of the timer should be
+//! enabled. Valid values for ui32TimerSegment are:
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! This function will enable a timer to begin incrementing. The \e
+//! ui32TimerNumber parameter selects the timer that should be enabled, for
+//! example, a 0 would target TIMER0. The \e ui32TimerSegment parameter allows
+//! the caller to individually select a segment within a timer to be enabled,
+//! such as TIMER0A, TIMER0B, or both.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_start(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
+{
+ volatile uint32_t *pui32ConfigReg;
+ uint32_t ui32ConfigVal;
+
+ //
+ // Find the correct control register.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section while config registers are read and modified.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Read the current value.
+ //
+ ui32ConfigVal = *pui32ConfigReg;
+
+ //
+ // Clear out the "clear" bit.
+ //
+ ui32ConfigVal &= ~(ui32TimerSegment & (AM_REG_CTIMER_CTRL0_TMRA0CLR_M |
+ AM_REG_CTIMER_CTRL0_TMRB0CLR_M));
+
+ //
+ // Set the "enable bit"
+ //
+ ui32ConfigVal |= (ui32TimerSegment & (AM_REG_CTIMER_CTRL0_TMRA0EN_M |
+ AM_REG_CTIMER_CTRL0_TMRB0EN_M));
+
+ //
+ // Write the value back to the register.
+ //
+ AM_REGVAL(pui32ConfigReg) = ui32ConfigVal;
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_start()
+
+//*****************************************************************************
+//
+//! @brief Stop a timer
+//!
+//! @param ui32TimerNumber is the number of the timer to disable.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer should be
+//! disabled.
+//!
+//! This function will stop the selected timer from incrementing. The \e
+//! ui32TimerNumber parameter selects the timer that should be disabled, for
+//! example, a 0 would target TIMER0. The \e ui32TimerSegment parameter allows
+//! the caller to individually select a segment within a timer to be disabled,
+//! such as TIMER0A, TIMER0B, or both.
+//!
+//! This function will stop a counter/timer from counting, but does not return
+//! the count value to 'zero'. If you would like to reset the counter back to
+//! zero, try the am_hal_ctimer_clear() function instead.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_stop(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
+{
+ volatile uint32_t *pui32ConfigReg;
+
+ //
+ // Find the correct control register.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Clear the "enable" bit
+ //
+ AM_REGVAL(pui32ConfigReg) &= ~(ui32TimerSegment &
+ (AM_REG_CTIMER_CTRL0_TMRA0EN_M |
+ AM_REG_CTIMER_CTRL0_TMRB0EN_M));
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_stop()
+
+//*****************************************************************************
+//
+//! @brief Stops a timer and resets its value back to zero.
+//!
+//! @param ui32TimerNumber is the number of the timer to clear.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer should be
+//! cleared.
+//!
+//! This function will stop a free-running counter-timer, reset its value to
+//! zero, and leave the timer disabled. When you would like to restart the
+//! counter, you will need to call am_hal_ctimer_start().
+//!
+//! The \e ui32TimerSegment parameter allows the caller to individually select
+//! a segment within, such as TIMER0A, TIMER0B, or both.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_clear(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
+{
+ volatile uint32_t *pui32ConfigReg;
+
+ //
+ // Find the correct control register.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Set the "clear" bit
+ //
+ AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
+ (AM_REG_CTIMER_CTRL0_TMRA0CLR_M |
+ AM_REG_CTIMER_CTRL0_TMRB0CLR_M));
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_clear()
+
+//*****************************************************************************
+//
+//! @brief Returns the current free-running value of the selected timer.
+//!
+//! @param ui32TimerNumber is the number of the timer to read.
+//! @param ui32TimerSegment specifies which segment of the timer should be
+//! read.
+//!
+//! This function returns the current free-running value of the selected timer.
+//!
+//! @note When reading from a linked timer, be sure to use AM_HAL_CTIMER both
+//! for the segment argument.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @return Current timer value.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ctimer_read(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
+{
+ volatile uint32_t ui32Value = 0;
+ uint32_t ui32Values[3] = {0};
+ uint32_t ui32TimerAddrTbl[4] =
+ {
+ REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR0_O,
+ REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR1_O,
+ REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR2_O,
+ REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR3_O
+ };
+
+ //
+ // Read the timer with back2back reads. This is a workaround for a clock
+ // domain synchronization issue. Some timer bits may be slow to increment,
+ // which means that the value in the timer register will sometimes be
+ // wrong.
+ //
+ // The architecture guarantees that:
+ //
+ // 1) If the timer is running at a speed close to the core frequency, the
+ // core and timer clock domains will be synchronized, and no "bad" reads
+ // will happen.
+ //
+ // 2) Bad reads will only happen if the core reads the timer register while
+ // the timer value is transitioning from one count to the next.
+ //
+ // 3) The timer will resolve to the correct value within one 24 MHz clock
+ // cycle.
+ //
+ // If we read the timer three times in a row with back-to-back load
+ // instructions, then we can guarantee that the timer will only have time
+ // to increment once, and that only one of the three reads can be wrong.
+ // This routine will perform the back-to-back reads and return all three
+ // values. The rest of this fuction determines which value we should
+ // actually use.
+ //
+ back2back_reads(ui32TimerAddrTbl[ui32TimerNumber], ui32Values);
+
+ //
+ // Shift or mask the values based on the given timer segment.
+ //
+ if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
+ {
+ ui32Values[0] >>= 16;
+ ui32Values[1] >>= 16;
+ ui32Values[2] >>= 16;
+ }
+ else if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )
+ {
+ ui32Values[0] &= 0xFFFF;
+ ui32Values[1] &= 0xFFFF;
+ ui32Values[2] &= 0xFFFF;
+ }
+
+ //
+ // Now, we'll figure out which of the three values is the correct time.
+ //
+ if (ui32Values[0] == ui32Values[1])
+ {
+ //
+ // If the first two values match, then neither one was a bad read.
+ // We'll take this as the current time.
+ //
+ ui32Value = ui32Values[1];
+ }
+ else
+ {
+ //
+ // If the first two values didn't match, then one of them might be bad.
+ // If one of the first two values is bad, then the third one should
+ // always be correct. We'll take the third value as the correct time.
+ //
+ ui32Value = ui32Values[2];
+
+ //
+ // If all of the statements about the architecture are true, the third
+ // value should be correct, and it should always be within one count of
+ // either the first or the second value.
+ //
+ // Just in case, we'll check against the previous two values to make
+ // sure that our final answer was reasonable. If it isn't, we will
+ // flag it as a "bad read", and fail this assert statement.
+ //
+ // This shouldn't ever happen, and it hasn't ever happened in any of
+ // our tests so far.
+ //
+ am_hal_debug_assert_msg((adjacent(ui32Values[1], ui32Values[2]) ||
+ adjacent(ui32Values[0], ui32Values[2])),
+ "Bad CTIMER read");
+ }
+
+ return ui32Value;
+} // am_hal_ctimer_read()
+
+//*****************************************************************************
+//
+//! @brief Enable output to the timer pin
+//!
+//! @param ui32TimerNumber is the number of the timer to configure.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer to use.
+//!
+//! This function will enable the output pin for the selected timer. The \e
+//! ui32TimerSegment parameter allows the caller to individually select a
+//! segment within, such as TIMER0A, TIMER0B, or both.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_pin_enable(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
+{
+ volatile uint32_t *pui32ConfigReg;
+
+ //
+ // Find the correct control register.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Set the pin enable bit
+ //
+ AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
+ (AM_REG_CTIMER_CTRL0_TMRA0PE_M |
+ AM_REG_CTIMER_CTRL0_TMRB0PE_M));
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_pin_enable()
+
+//*****************************************************************************
+//
+//! @brief Disable the output pin.
+//!
+//! @param ui32TimerNumber is the number of the timer to configure.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer to use.
+//!
+//! This function will disable the output pin for the selected timer. The \e
+//! ui32TimerSegment parameter allows the caller to individually select a
+//! segment within, such as TIMER0A, TIMER0B, or both.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_pin_disable(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
+{
+ volatile uint32_t *pui32ConfigReg;
+
+ //
+ // Find the correct control register.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Clear the pin enable bit
+ //
+ AM_REGVAL(pui32ConfigReg) &= ~(ui32TimerSegment &
+ (AM_REG_CTIMER_CTRL0_TMRA0PE_M |
+ AM_REG_CTIMER_CTRL0_TMRB0PE_M));
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_pin_disable()
+
+//*****************************************************************************
+//
+//! @brief Set the polarity of the output pin.
+//!
+//! @param ui32TimerNumber is the number of the timer to configure.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer to use.
+//!
+//! @param bInvertOutpt determines whether the output should be inverted. If
+//! true, the timer output pin for the selected timer segment will be
+//! inverted.
+//!
+//! This function will set the polarity of the the output pin for the selected
+//! timer. The \e ui32TimerSegment parameter allows the caller to individually
+//! select a segment within, such as TIMER0A, TIMER0B, or both.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_pin_invert(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
+ bool bInvertOutput)
+{
+ volatile uint32_t *pui32ConfigReg;
+
+ //
+ // Find the correct control register.
+ //
+ pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Figure out if we're supposed to be setting or clearing the polarity bit.
+ //
+ if ( bInvertOutput )
+ {
+ //
+ // Set the polarity bit to invert the output.
+ //
+ AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
+ (AM_REG_CTIMER_CTRL0_TMRA0POL_M |
+ AM_REG_CTIMER_CTRL0_TMRB0POL_M));
+ }
+ else
+ {
+ //
+ // Clear the polarity bit.
+ //
+ AM_REGVAL(pui32ConfigReg) &= ~(ui32TimerSegment &
+ (AM_REG_CTIMER_CTRL0_TMRA0POL_M |
+ AM_REG_CTIMER_CTRL0_TMRB0POL_M));
+ }
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_pin_invert()
+
+//*****************************************************************************
+//
+//! @brief Set a compare register.
+//!
+//! @param ui32TimerNumber is the number of the timer to configure.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer to use.
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @param ui32CompareReg specifies which compare register should be set
+//! (either 0 or 1)
+//!
+//! @param ui32Value is the value that should be written to the compare
+//! register.
+//!
+//! This function allows the caller to set the values in the compare registers
+//! for a timer. These registers control the period and duty cycle of the
+//! timers and their associated output pins. Please see the datasheet for
+//! further information on the operation of the compare registers. The \e
+//! ui32TimerSegment parameter allows the caller to individually select a
+//! segment within, such as TIMER0A, TIMER0B, or both.
+//!
+//! @note For simple manipulations of period or duty cycle for timers and PWMs,
+//! you may find it easier to use the am_hal_ctimer_period_set() function.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_compare_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
+ uint32_t ui32CompareReg, uint32_t ui32Value)
+{
+ volatile uint32_t *pui32CmprRegA, *pui32CmprRegB;
+ uint32_t ui32CmprRegA, ui32CmprRegB;
+
+ //
+ // Find the correct compare register to write.
+ // Assume A or BOTH. We'll change later if B.
+ //
+ pui32CmprRegA = (uint32_t *)(AM_REG_CTIMERn(0) +
+ AM_REG_CTIMER_CMPRA0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+ pui32CmprRegB = pui32CmprRegA + CTIMER_CMPR_OFFSET;
+
+ //
+ // Write the compare register with the selected value.
+ // Begin critical section while CMPR registers are modified.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ ui32CmprRegA = *pui32CmprRegA;
+ ui32CmprRegB = *pui32CmprRegB;
+
+ if ( ui32CompareReg == 1 )
+ {
+ //
+ // CMPR reg 1
+ // Get the lower 16b (but may not be used if TIMERB).
+ //
+ ui32CmprRegA = ( (ui32CmprRegA & AM_REG_CTIMER_CMPRA0_CMPR0A0_M) |
+ AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Value & 0xFFFF) );
+
+ //
+ // Get the upper 16b (but may not be used if TIMERA)
+ //
+ ui32CmprRegB = ( (ui32CmprRegB & AM_REG_CTIMER_CMPRA0_CMPR0A0_M) |
+ AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Value >> 16) );
+ }
+ else
+ {
+ //
+ // CMPR reg 0
+ // Get the lower 16b (but may not be used if TIMERB)
+ //
+ ui32CmprRegA = ( (ui32CmprRegA & AM_REG_CTIMER_CMPRA0_CMPR1A0_M) |
+ AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Value & 0xFFFF) );
+
+ //
+ // Set the upper 16b (but may not be used if TIMERA)
+ //
+ ui32CmprRegB = ( (ui32CmprRegB & AM_REG_CTIMER_CMPRA0_CMPR1A0_M) |
+ AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Value >> 16) );
+ }
+
+ if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
+ {
+ *pui32CmprRegB = ui32CmprRegB;
+ }
+ else
+ {
+ //
+ // It's TIMERA or BOTH.
+ //
+ *pui32CmprRegA = ui32CmprRegA;
+
+ if ( ui32TimerSegment == AM_HAL_CTIMER_BOTH )
+ {
+ *pui32CmprRegB = ui32CmprRegB;
+ }
+ }
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_compare_set()
+
+//*****************************************************************************
+//
+//! @brief Set the period and duty cycle of a timer.
+//!
+//! @param ui32TimerNumber is the number of the timer to configure.
+//!
+//! @param ui32TimerSegment specifies which segment of the timer to use.
+//!
+//! @param ui32Period specifies the desired period. This parameter effectively
+//! specifies the CTIMER CMPR field(s). The CMPR fields are handled in hardware
+//! as (n+1) values, therefore ui32Period is actually specified as 1 less than
+//! the desired period. Finally, as mentioned in the data sheet, the CMPR fields
+//! cannot be 0 (a value of 1), so neither can ui32Period be 0.
+//!
+//! @param ui32OnTime set the number of clocks where the output signal is high.
+//!
+//! This function should be used for simple manipulations of the period and
+//! duty cycle of a counter/timer. To set the period and/or duty cycle of a
+//! linked timer pair, use AM_HAL_CTIMER_BOTH as the timer segment argument. If
+//! you would like to set the period and/or duty cycle for both TIMERA and
+//! TIMERB you will need to call this function twice: once for TIMERA, and once
+//! for TIMERB.
+//!
+//! Valid values for ui32TimerSegment are:
+//!
+//! AM_HAL_CTIMER_TIMERA
+//! AM_HAL_CTIMER_TIMERB
+//! AM_HAL_CTIMER_BOTH
+//!
+//! @note The ui32OnTime parameter will only work if the timer is currently
+//! operating in one of the PWM modes.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_period_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
+ uint32_t ui32Period, uint32_t ui32OnTime)
+{
+ volatile uint32_t *pui32ControlReg;
+ volatile uint32_t *pui32CompareRegA;
+ volatile uint32_t *pui32CompareRegB;
+ uint32_t ui32Mode, ui32Comp0, ui32Comp1;
+
+ //
+ // Find the correct control register to pull the function select field
+ // from.
+ //
+ pui32ControlReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Find the correct compare registers to write.
+ //
+ pui32CompareRegA = (uint32_t *)(AM_REG_CTIMERn(0) +
+ AM_REG_CTIMER_CMPRA0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ pui32CompareRegB = (uint32_t *)(AM_REG_CTIMERn(0) +
+ AM_REG_CTIMER_CMPRB0_O +
+ (ui32TimerNumber * TIMER_OFFSET));
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Extract the timer mode from the register based on the ui32TimerSegment
+ // selected by the user.
+ //
+ ui32Mode = *pui32ControlReg;
+ if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
+ {
+ ui32Mode = ui32Mode >> 16;
+ }
+
+ //
+ // Mask to get to the bits we're interested in.
+ //
+ ui32Mode = ui32Mode & AM_REG_CTIMER_CTRL0_TMRA0FN_M;
+
+ //
+ // If the mode is a PWM mode, we'll need to calculate the correct CMPR0 and
+ // CMPR1 values here.
+ //
+ if (ui32Mode == AM_HAL_CTIMER_FN_PWM_ONCE ||
+ ui32Mode == AM_HAL_CTIMER_FN_PWM_REPEAT)
+ {
+ ui32Comp0 = ui32Period - ui32OnTime;
+ ui32Comp1 = ui32Period;
+ }
+ else
+ {
+ ui32Comp0 = ui32Period;
+ ui32Comp1 = 0;
+ }
+
+ //
+ // Based on the timer segment argument, write the calculated Compare 0 and
+ // Compare 1 values to the correct halves of the correct registers.
+ //
+ if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )
+ {
+ //
+ // For timer A, write the values to the TIMERA compare register.
+ //
+ *pui32CompareRegA = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0) |
+ AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1));
+ }
+ else if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
+ {
+ //
+ // For timer B, write the values to the TIMERA compare register.
+ //
+ *pui32CompareRegB = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0) |
+ AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1));
+ }
+ else
+ {
+ //
+ // For the linked case, write the lower halves of the values to the
+ // TIMERA compare register, and the upper halves to the TIMERB compare
+ // register.
+ //
+ *pui32CompareRegA = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0) |
+ AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1));
+
+ *pui32CompareRegB = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0 >> 16) |
+ AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1 >> 16));
+ }
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_period_set()
+
+//*****************************************************************************
+//
+//! @brief Enable the TIMERA3 ADC trigger
+//!
+//! This function enables the ADC trigger within TIMERA3.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_adc_trigger_enable(void)
+{
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Enable the ADC trigger.
+ //
+ AM_REGn(CTIMER, 0, CTRL3) |= AM_REG_CTIMER_CTRL3_ADCEN_M;
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_adc_trigger_enable()
+
+//*****************************************************************************
+//
+//! @brief Disable the TIMERA3 ADC trigger
+//!
+//! This function disables the ADC trigger within TIMERA3.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_adc_trigger_disable(void)
+{
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Disable the ADC trigger.
+ //
+ AM_REGn(CTIMER, 0, CTRL3) &= ~AM_REG_CTIMER_CTRL3_ADCEN_M;
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_adc_trigger_disable()
+
+//*****************************************************************************
+//
+//! @brief Enables the selected timer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will enable the selected interrupts in the main CTIMER
+//! interrupt enable register. In order to receive an interrupt from a timer,
+//! you will need to enable the interrupt for that timer in this main register,
+//! as well as in the timer control register (accessible though
+//! am_hal_ctimer_config()), and in the NVIC.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_CTIMER_INT_TIMERA0C0
+//! AM_HAL_CTIMER_INT_TIMERA0C1
+//! AM_HAL_CTIMER_INT_TIMERB0C0
+//! AM_HAL_CTIMER_INT_TIMERB0C1
+//! AM_HAL_CTIMER_INT_TIMERA1C0
+//! AM_HAL_CTIMER_INT_TIMERA1C1
+//! AM_HAL_CTIMER_INT_TIMERB1C0
+//! AM_HAL_CTIMER_INT_TIMERB1C1
+//! AM_HAL_CTIMER_INT_TIMERA2C0
+//! AM_HAL_CTIMER_INT_TIMERA2C1
+//! AM_HAL_CTIMER_INT_TIMERB2C0
+//! AM_HAL_CTIMER_INT_TIMERB2C1
+//! AM_HAL_CTIMER_INT_TIMERA3C0
+//! AM_HAL_CTIMER_INT_TIMERA3C1
+//! AM_HAL_CTIMER_INT_TIMERB3C0
+//! AM_HAL_CTIMER_INT_TIMERB3C1
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_int_enable(uint32_t ui32Interrupt)
+{
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Enable the interrupt at the module level.
+ //
+ AM_REGn(CTIMER, 0, INTEN) |= ui32Interrupt;
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_int_enable()
+
+//*****************************************************************************
+//
+//! @brief Return the enabled timer interrupts.
+//!
+//! This function will return all enabled interrupts in the main CTIMER
+//! interrupt enable register.
+//!
+//! @return return enabled interrupts. This will be a logical or of:
+//!
+//! AM_HAL_CTIMER_INT_TIMERA0C0
+//! AM_HAL_CTIMER_INT_TIMERA0C1
+//! AM_HAL_CTIMER_INT_TIMERB0C0
+//! AM_HAL_CTIMER_INT_TIMERB0C1
+//! AM_HAL_CTIMER_INT_TIMERA1C0
+//! AM_HAL_CTIMER_INT_TIMERA1C1
+//! AM_HAL_CTIMER_INT_TIMERB1C0
+//! AM_HAL_CTIMER_INT_TIMERB1C1
+//! AM_HAL_CTIMER_INT_TIMERA2C0
+//! AM_HAL_CTIMER_INT_TIMERA2C1
+//! AM_HAL_CTIMER_INT_TIMERB2C0
+//! AM_HAL_CTIMER_INT_TIMERB2C1
+//! AM_HAL_CTIMER_INT_TIMERA3C0
+//! AM_HAL_CTIMER_INT_TIMERA3C1
+//! AM_HAL_CTIMER_INT_TIMERB3C0
+//! AM_HAL_CTIMER_INT_TIMERB3C1
+//!
+//! @return Return the enabled timer interrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ctimer_int_enable_get(void)
+{
+ //
+ // Return enabled interrupts.
+ //
+ return AM_REGn(CTIMER, 0, INTEN);
+} // am_hal_ctimer_int_enable_get()
+
+//*****************************************************************************
+//
+//! @brief Disables the selected timer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will disable the selected interrupts in the main CTIMER
+//! interrupt register.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_CTIMER_INT_TIMERA0C0
+//! AM_HAL_CTIMER_INT_TIMERA0C1
+//! AM_HAL_CTIMER_INT_TIMERB0C0
+//! AM_HAL_CTIMER_INT_TIMERB0C1
+//! AM_HAL_CTIMER_INT_TIMERA1C0
+//! AM_HAL_CTIMER_INT_TIMERA1C1
+//! AM_HAL_CTIMER_INT_TIMERB1C0
+//! AM_HAL_CTIMER_INT_TIMERB1C1
+//! AM_HAL_CTIMER_INT_TIMERA2C0
+//! AM_HAL_CTIMER_INT_TIMERA2C1
+//! AM_HAL_CTIMER_INT_TIMERB2C0
+//! AM_HAL_CTIMER_INT_TIMERB2C1
+//! AM_HAL_CTIMER_INT_TIMERA3C0
+//! AM_HAL_CTIMER_INT_TIMERA3C1
+//! AM_HAL_CTIMER_INT_TIMERB3C0
+//! AM_HAL_CTIMER_INT_TIMERB3C1
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_int_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Disable the interrupt at the module level.
+ //
+ AM_REGn(CTIMER, 0, INTEN) &= ~ui32Interrupt;
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+} // am_hal_ctimer_int_disable()
+
+//*****************************************************************************
+//
+//! @brief Clears the selected timer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will clear the selected interrupts in the main CTIMER
+//! interrupt register.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_CTIMER_INT_TIMERA0C0
+//! AM_HAL_CTIMER_INT_TIMERA0C1
+//! AM_HAL_CTIMER_INT_TIMERB0C0
+//! AM_HAL_CTIMER_INT_TIMERB0C1
+//! AM_HAL_CTIMER_INT_TIMERA1C0
+//! AM_HAL_CTIMER_INT_TIMERA1C1
+//! AM_HAL_CTIMER_INT_TIMERB1C0
+//! AM_HAL_CTIMER_INT_TIMERB1C1
+//! AM_HAL_CTIMER_INT_TIMERA2C0
+//! AM_HAL_CTIMER_INT_TIMERA2C1
+//! AM_HAL_CTIMER_INT_TIMERB2C0
+//! AM_HAL_CTIMER_INT_TIMERB2C1
+//! AM_HAL_CTIMER_INT_TIMERA3C0
+//! AM_HAL_CTIMER_INT_TIMERA3C1
+//! AM_HAL_CTIMER_INT_TIMERB3C0
+//! AM_HAL_CTIMER_INT_TIMERB3C1
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Disable the interrupt at the module level.
+ //
+ AM_REGn(CTIMER, 0, INTCLR) = ui32Interrupt;
+} // am_hal_ctimer_int_clear()
+
+//*****************************************************************************
+//
+//! @brief Sets the selected timer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will set the selected interrupts in the main CTIMER
+//! interrupt register.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_CTIMER_INT_TIMERA0C0
+//! AM_HAL_CTIMER_INT_TIMERA0C1
+//! AM_HAL_CTIMER_INT_TIMERB0C0
+//! AM_HAL_CTIMER_INT_TIMERB0C1
+//! AM_HAL_CTIMER_INT_TIMERA1C0
+//! AM_HAL_CTIMER_INT_TIMERA1C1
+//! AM_HAL_CTIMER_INT_TIMERB1C0
+//! AM_HAL_CTIMER_INT_TIMERB1C1
+//! AM_HAL_CTIMER_INT_TIMERA2C0
+//! AM_HAL_CTIMER_INT_TIMERA2C1
+//! AM_HAL_CTIMER_INT_TIMERB2C0
+//! AM_HAL_CTIMER_INT_TIMERB2C1
+//! AM_HAL_CTIMER_INT_TIMERA3C0
+//! AM_HAL_CTIMER_INT_TIMERA3C1
+//! AM_HAL_CTIMER_INT_TIMERB3C0
+//! AM_HAL_CTIMER_INT_TIMERB3C1
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ctimer_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Set the interrupts.
+ //
+ AM_REGn(CTIMER, 0, INTSET) = ui32Interrupt;
+} // am_hal_ctimer_int_set()
+
+//*****************************************************************************
+//
+//! @brief Returns either the enabled or raw timer interrupt status.
+//!
+//! This function will return the timer interrupt status.
+//!
+//! @return bEnabledOnly if true returns the status of the enabled interrupts
+//! only.
+//!
+//! The return value will be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_CTIMER_INT_TIMERA0C0
+//! AM_HAL_CTIMER_INT_TIMERA0C1
+//! AM_HAL_CTIMER_INT_TIMERB0C0
+//! AM_HAL_CTIMER_INT_TIMERB0C1
+//! AM_HAL_CTIMER_INT_TIMERA1C0
+//! AM_HAL_CTIMER_INT_TIMERA1C1
+//! AM_HAL_CTIMER_INT_TIMERB1C0
+//! AM_HAL_CTIMER_INT_TIMERB1C1
+//! AM_HAL_CTIMER_INT_TIMERA2C0
+//! AM_HAL_CTIMER_INT_TIMERA2C1
+//! AM_HAL_CTIMER_INT_TIMERB2C0
+//! AM_HAL_CTIMER_INT_TIMERB2C1
+//! AM_HAL_CTIMER_INT_TIMERA3C0
+//! AM_HAL_CTIMER_INT_TIMERA3C1
+//! AM_HAL_CTIMER_INT_TIMERB3C0
+//! AM_HAL_CTIMER_INT_TIMERB3C1
+//!
+//! @return Returns either the timer interrupt status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ctimer_int_status_get(bool bEnabledOnly)
+{
+ //
+ // Return the desired status.
+ //
+
+ if ( bEnabledOnly )
+ {
+ uint32_t u32RetVal;
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ u32RetVal = AM_REGn(CTIMER, 0, INTSTAT);
+ u32RetVal &= AM_REGn(CTIMER, 0, INTEN);
+
+ //
+ // Done with critical section.
+ //
+ AM_CRITICAL_END_ASM
+
+ return u32RetVal;
+ }
+ else
+ {
+ return AM_REGn(CTIMER, 0, INTSTAT);
+ }
+} // am_hal_ctimer_int_status_get()
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.h b/bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.h
new file mode 100644
index 0000000000..fa1ebe16c4
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_ctimer.h
@@ -0,0 +1,278 @@
+//*****************************************************************************
+//
+// am_hal_ctimer.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the CTIMER.
+//!
+//! @addtogroup ctimer2 Counter/Timer (CTIMER)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_CTIMER_H
+#define AM_HAL_CTIMER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! Number of timers
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_TIMERS_NUM 4
+
+//*****************************************************************************
+//
+//! Timer offset value
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_TIMER_OFFSET (AM_REG_CTIMER_TMR1_O - AM_REG_CTIMER_TMR0_O)
+
+//*****************************************************************************
+//
+//! @name Interrupt Status Bits
+//! @brief Interrupt Status Bits for enable/disble use
+//!
+//! These macros may be used to set and clear interrupt bits
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_INT_TIMERA0C0 AM_REG_CTIMER_INTEN_CTMRA0C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERA0C1 AM_REG_CTIMER_INTEN_CTMRA0C1INT_M
+#define AM_HAL_CTIMER_INT_TIMERA1C0 AM_REG_CTIMER_INTEN_CTMRA1C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERA1C1 AM_REG_CTIMER_INTEN_CTMRA1C1INT_M
+#define AM_HAL_CTIMER_INT_TIMERA2C0 AM_REG_CTIMER_INTEN_CTMRA2C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERA2C1 AM_REG_CTIMER_INTEN_CTMRA2C1INT_M
+#define AM_HAL_CTIMER_INT_TIMERA3C0 AM_REG_CTIMER_INTEN_CTMRA3C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERA3C1 AM_REG_CTIMER_INTEN_CTMRA3C1INT_M
+
+#define AM_HAL_CTIMER_INT_TIMERB0C0 AM_REG_CTIMER_INTEN_CTMRB0C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERB0C1 AM_REG_CTIMER_INTEN_CTMRB0C1INT_M
+#define AM_HAL_CTIMER_INT_TIMERB1C0 AM_REG_CTIMER_INTEN_CTMRB1C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERB1C1 AM_REG_CTIMER_INTEN_CTMRB1C1INT_M
+#define AM_HAL_CTIMER_INT_TIMERB2C0 AM_REG_CTIMER_INTEN_CTMRB2C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERB2C1 AM_REG_CTIMER_INTEN_CTMRB2C1INT_M
+#define AM_HAL_CTIMER_INT_TIMERB3C0 AM_REG_CTIMER_INTEN_CTMRB3C0INT_M
+#define AM_HAL_CTIMER_INT_TIMERB3C1 AM_REG_CTIMER_INTEN_CTMRB3C1INT_M
+
+//
+// Deprecated, use the newer macros above.
+//
+#define AM_HAL_CTIMER_INT_TIMERA0 AM_HAL_CTIMER_INT_TIMERA0C0
+#define AM_HAL_CTIMER_INT_TIMERB0 AM_HAL_CTIMER_INT_TIMERB0C0
+#define AM_HAL_CTIMER_INT_TIMERA1 AM_HAL_CTIMER_INT_TIMERA1C0
+#define AM_HAL_CTIMER_INT_TIMERB1 AM_HAL_CTIMER_INT_TIMERB1C0
+#define AM_HAL_CTIMER_INT_TIMERA2 AM_HAL_CTIMER_INT_TIMERA2C0
+#define AM_HAL_CTIMER_INT_TIMERB2 AM_HAL_CTIMER_INT_TIMERB2C0
+#define AM_HAL_CTIMER_INT_TIMERA3 AM_HAL_CTIMER_INT_TIMERA3C0
+#define AM_HAL_CTIMER_INT_TIMERB3 AM_HAL_CTIMER_INT_TIMERB3C0
+//! @}
+
+//*****************************************************************************
+//
+//! @name Configuration options
+//! @brief Configuration options for \e am_hal_ctimer_config_t
+//!
+//! These options are to be used with the \e am_hal_ctimer_config_t structure
+//! used by \e am_hal_ctimer_config
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_CLK_PIN AM_REG_CTIMER_CTRL0_TMRA0CLK(0x0)
+#define AM_HAL_CTIMER_HFRC_12MHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x1)
+#define AM_HAL_CTIMER_HFRC_3MHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x2)
+#define AM_HAL_CTIMER_HFRC_187_5KHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x3)
+#define AM_HAL_CTIMER_HFRC_47KHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x4)
+#define AM_HAL_CTIMER_HFRC_12KHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x5)
+#define AM_HAL_CTIMER_XT_32_768KHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x6)
+#define AM_HAL_CTIMER_XT_16_384KHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x7)
+#define AM_HAL_CTIMER_XT_2_048KHZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x8)
+#define AM_HAL_CTIMER_XT_256HZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0x9)
+#define AM_HAL_CTIMER_LFRC_512HZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0xA)
+#define AM_HAL_CTIMER_LFRC_32HZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0xB)
+#define AM_HAL_CTIMER_LFRC_1HZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0xC)
+#define AM_HAL_CTIMER_LFRC_1_16HZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0xD)
+#define AM_HAL_CTIMER_RTC_100HZ AM_REG_CTIMER_CTRL0_TMRA0CLK(0xE)
+#define AM_HAL_CTIMER_HCLK AM_REG_CTIMER_CTRL0_TMRA0CLK(0xF)
+#define AM_HAL_CTIMER_BUCK AM_REG_CTIMER_CTRL0_TMRA0CLK(0x10)
+//! @}
+
+//*****************************************************************************
+//
+// Timer function macros.
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_FN_ONCE AM_REG_CTIMER_CTRL0_TMRA0FN(0)
+#define AM_HAL_CTIMER_FN_REPEAT AM_REG_CTIMER_CTRL0_TMRA0FN(1)
+#define AM_HAL_CTIMER_FN_PWM_ONCE AM_REG_CTIMER_CTRL0_TMRA0FN(2)
+#define AM_HAL_CTIMER_FN_PWM_REPEAT AM_REG_CTIMER_CTRL0_TMRA0FN(3)
+#define AM_HAL_CTIMER_FN_CONTINUOUS AM_REG_CTIMER_CTRL0_TMRA0FN(4)
+
+//*****************************************************************************
+//
+// Half-timer options.
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_INT_ENABLE AM_REG_CTIMER_CTRL0_TMRA0IE0_M
+#define AM_HAL_CTIMER_PIN_ENABLE AM_REG_CTIMER_CTRL0_TMRA0PE_M
+#define AM_HAL_CTIMER_PIN_INVERT AM_REG_CTIMER_CTRL0_TMRA0POL_M
+#define AM_HAL_CTIMER_CLEAR AM_REG_CTIMER_CTRL0_TMRA0CLR_M
+
+//*****************************************************************************
+//
+// Additional timer options.
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_LINK AM_REG_CTIMER_CTRL0_CTLINK0_M
+#define AM_HAL_CTIMER_ADC_TRIG AM_REG_CTIMER_CTRL3_ADCEN_M
+
+//*****************************************************************************
+//
+// Timer selection macros.
+//
+//*****************************************************************************
+#define AM_HAL_CTIMER_TIMERA 0x0000FFFF
+#define AM_HAL_CTIMER_TIMERB 0xFFFF0000
+#define AM_HAL_CTIMER_BOTH 0xFFFFFFFF
+//! @}
+
+//*****************************************************************************
+//
+// Timer configuration structure
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! Set to 1 to operate this timer as a 32-bit timer instead of two 16-bit
+ //! timers.
+ //
+ uint32_t ui32Link;
+
+ //
+ //! Configuration options for TIMERA
+ //
+ uint32_t ui32TimerAConfig;
+
+ //
+ //! Configuration options for TIMERB
+ //
+ uint32_t ui32TimerBConfig;
+
+}
+am_hal_ctimer_config_t;
+
+//*****************************************************************************
+//
+// Function pointer type for CTimer interrupt handlers.
+//
+//*****************************************************************************
+typedef void (*am_hal_ctimer_handler_t)(void);
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_ctimer_config(uint32_t ui32TimerNumber,
+ am_hal_ctimer_config_t *psConfig);
+
+extern void am_hal_ctimer_config_single(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment,
+ uint32_t ui32ConfigVal);
+
+extern void am_hal_ctimer_start(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment);
+
+extern void am_hal_ctimer_stop(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment);
+
+extern void am_hal_ctimer_clear(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment);
+
+extern uint32_t am_hal_ctimer_read(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment);
+
+extern void am_hal_ctimer_pin_enable(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment);
+
+extern void am_hal_ctimer_pin_disable(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment);
+
+extern void am_hal_ctimer_pin_invert(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment,
+ bool bInvertOutput);
+
+extern void am_hal_ctimer_compare_set(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment,
+ uint32_t ui32CompareReg,
+ uint32_t ui32Value);
+
+extern void am_hal_ctimer_period_set(uint32_t ui32TimerNumber,
+ uint32_t ui32TimerSegment,
+ uint32_t ui32Period,
+ uint32_t ui32OnTime);
+
+extern void am_hal_ctimer_adc_trigger_enable(void);
+extern void am_hal_ctimer_adc_trigger_disable(void);
+extern void am_hal_ctimer_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_ctimer_int_enable_get(void);
+extern void am_hal_ctimer_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_ctimer_int_set(uint32_t ui32Interrupt);
+extern void am_hal_ctimer_int_clear(uint32_t ui32Interrupt);
+extern uint32_t am_hal_ctimer_int_status_get(bool bEnabledOnly);
+extern void am_hal_ctimer_int_register(uint32_t ui32Interrupt,
+ am_hal_ctimer_handler_t pfnHandler);
+extern void am_hal_ctimer_int_service(uint32_t ui32Status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_CTIMER_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_debug.c b/bsp/apollo2/libraries/drivers/hal/am_hal_debug.c
new file mode 100644
index 0000000000..4078b5a5a0
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_debug.c
@@ -0,0 +1,81 @@
+//*****************************************************************************
+//
+// am_hal_debug.c
+//! @file
+//!
+//! @brief Useful functions for debugging.
+//!
+//! These functions and macros were created to assist with debugging. They are
+//! intended to be as unintrusive as possible and designed to be removed from
+//! the compilation of a project when they are no longer needed.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Default implementation of a failed ASSERT statement.
+//!
+//! @param pcFile is the name of the source file where the error occurred.
+//! @param ui32Line is the line number where the error occurred.
+//! @param pcMessage is an optional message describing the failure.
+//!
+//! This function is called by am_hal_debug_assert() macro when the supplied
+//! condition is not true. The implementation here simply halts the application
+//! for further analysis. Individual applications may define their own
+//! implementations of am_hal_debug_error() to provide more detailed feedback
+//! about the failed am_hal_debug_assert() statement.
+//!
+//! @return
+//
+//*****************************************************************************
+#if defined (__IAR_SYSTEMS_ICC__)
+__weak void
+#else
+void __attribute__((weak))
+#endif
+am_hal_debug_error(const char *pcFile, uint32_t ui32Line, const char *pcMessage)
+{
+ //
+ // Halt for analysis.
+ //
+ while(1);
+}
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_debug.h b/bsp/apollo2/libraries/drivers/hal/am_hal_debug.h
new file mode 100644
index 0000000000..a482799c4f
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_debug.h
@@ -0,0 +1,89 @@
+//*****************************************************************************
+//
+// am_hal_debug.h
+//! @file
+//!
+//! @brief Useful macros for debugging.
+//!
+//! These functions and macros were created to assist with debugging. They are
+//! intended to be as unintrusive as possible and designed to be removed from
+//! the compilation of a project when they are no longer needed.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_DEBUG_H
+#define AM_HAL_DEBUG_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Debug assert macros.
+//
+//*****************************************************************************
+#ifndef AM_HAL_DEBUG_NO_ASSERT
+
+#define am_hal_debug_assert_msg(bCondition, pcMessage) \
+ if ( !(bCondition)) am_hal_debug_error(__FILE__, __LINE__, pcMessage)
+
+#define am_hal_debug_assert(bCondition) \
+ if ( !(bCondition)) am_hal_debug_error(__FILE__, __LINE__, 0)
+
+#else
+
+#define am_hal_debug_assert_msg(bCondition, pcMessage)
+#define am_hal_debug_assert(bCondition)
+
+#endif // AM_DEBUG_ASSERT
+
+//*****************************************************************************
+//
+// External function prototypes.
+//
+//*****************************************************************************
+extern void am_hal_debug_error(const char *pcFile, uint32_t ui32Line,
+ const char *pcMessage);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_DEBUG_H
+
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_flash.c b/bsp/apollo2/libraries/drivers/hal/am_hal_flash.c
new file mode 100644
index 0000000000..cd38da812c
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_flash.c
@@ -0,0 +1,1449 @@
+//*****************************************************************************
+//
+// am_hal_flash.c
+//! @file
+//!
+//! @brief Functions for performing Flash operations.
+//!
+//! @addtogroup flash2 Flash
+//! @ingroup apollo2hal
+//!
+//! IMPORTANT: Interrupts are active during execution of all HAL flash
+//! functions. If an interrupt occurs during execution of a flash function
+//! that programs or erases flash or INFO space, errors will occur if the
+//! interrupt service routine (ISR) is located in on-chip flash.
+//! If interrupts are expected during execution of a flash function that
+//! programs or erases either flash or INFO space:
+//! - Interrupts must be disabled via a critical section handler prior to
+//! calling the flash function.
+//! - Alternatively, applicable ISRs must be located in non-flash address space
+//! (i.e. SRAM, off-chip ROM, etc.).
+//!
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//
+// Look-up table
+//
+g_am_hal_flash_t g_am_hal_flash =
+{
+ //
+ // The basics.
+ //
+ // flash_mass_erase()
+ ((int (*) (uint32_t, uint32_t)) 0x0800004d),
+ // flash_page_erase()
+ ((int (*) (uint32_t, uint32_t, uint32_t)) 0x08000051),
+ // flash_program_main()
+ ((int (*) (uint32_t, uint32_t *, uint32_t *, uint32_t)) 0x08000055),
+ // flash_program_info()
+ ((int (*) (uint32_t, uint32_t, uint32_t *, uint32_t, uint32_t)) 0x08000059),
+
+ //
+ // Non-blocking variants, but be careful these are not interrupt safe so
+ // mask interrupts while these very long operations proceed.
+ //
+ // flash_mass_erase_nb()
+ ((int (*)(uint32_t, uint32_t)) 0x0800006d),
+ // flash_page_erase_nb()
+ ((int (*)(uint32_t, uint32_t, uint32_t)) 0x08000071),
+ // flash_nb_operation_complete()
+ ((bool (*)(void)) 0x0800007d),
+
+ //
+ // Essentially these are recovery options.
+ //
+ // flash_erase_info()
+ ((int (*)(uint32_t, uint32_t)) 0x08000081),
+ // flash_erase_main_plus_info()
+ ((int (*)(uint32_t, uint32_t)) 0x08000089),
+ // flash_erase_main_plus_info_both_instances()
+ ((int (*)(uint32_t)) 0x08000091),
+ // flash_recovery()
+ ((void (*)(uint32_t)) 0x08000099),
+
+ //
+ // Useful utilities.
+ //
+ // flash_util_read_word()
+ ((uint32_t (*)(uint32_t*)) 0x08000075),
+ // flash_util_write_word()
+ ((void (*)(uint32_t*, uint32_t)) 0x08000079),
+ // delay_cycles()
+ ((void (*)(uint32_t)) 0x0800009d),
+
+ //
+ // The following functions pointers must never be called from user
+ // programs. They are here primarily to document these entry points
+ // which are usable from a debugger or debugger script.
+ //
+ // flash_program_main_sram()
+ ((void (*) (void)) 0x0800005d),
+ // flash_program_info_sram()
+ ((void (*) (void)) 0x08000061),
+ // flash_erase_main_pages_sram()
+ ((void (*) (void)) 0x08000065),
+ // flash_mass_erase_sram()
+ ((void (*) (void)) 0x08000069),
+ // flash_erase_info_sram()
+ ((void (*)(void)) 0x08000085),
+ // flash_erase_main_plus_info_sram()
+ ((void (*)(void)) 0x0800008d)
+};
+
+//*****************************************************************************
+//
+//! @brief This function performs a mass erase on a flash instance.
+//!
+//! @param ui32Value - The flash program key.
+//! @param ui32FlashInst - The flash instance to erase.
+//!
+//! This function will erase the desired instance of flash.
+//!
+//! @note For Apollo2, each flash instance contains a maximum of 512KB.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return 0 for success, non-zero for failure.
+//
+//*****************************************************************************
+int
+am_hal_flash_mass_erase(uint32_t ui32Value, uint32_t ui32FlashInst)
+{
+ return g_am_hal_flash.flash_mass_erase(ui32Value, ui32FlashInst);
+}
+
+//*****************************************************************************
+//
+//! @brief This function performs a page erase on a flash instance.
+//!
+//! @param ui32Value - The flash program key.
+//! @param ui32FlashInst - The flash instance to reference the page number with.
+//! @param ui32PageNum - The flash page relative to the specified instance.
+//!
+//! This function will erase the desired flash page in the desired instance of
+//! flash.
+//!
+//! @note For Apollo2, each flash page is 8KB (or AM_HAL_FLASH_PAGE_SIZE).
+//! Each flash instance contains a maximum of 64 pages (or
+//! AM_HAL_FLASH_INSTANCE_PAGES).
+//!
+//! @note When given an absolute flash address, a couple of helpful macros can
+//! be utilized when calling this function.
+//! For example:
+//! am_hal_flash_page_erase(AM_HAL_FLASH_PROGRAM_KEY,
+//! AM_HAL_FLASH_ADDR2INST(ui32Addr),
+//! AM_HAL_FLASH_ADDR2PAGE(ui32Addr) );
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return 0 for success, non-zero for failure.
+//
+//*****************************************************************************
+int
+am_hal_flash_page_erase(uint32_t ui32Value, uint32_t ui32FlashInst,
+ uint32_t ui32PageNum)
+{
+ return g_am_hal_flash.flash_page_erase(ui32Value,
+ ui32FlashInst,
+ ui32PageNum);
+}
+
+//*****************************************************************************
+//
+//! @brief This programs up to N words of the Main array on one flash instance.
+//!
+//! @param ui32Value - The programming key, AM_HAL_FLASH_PROGRAM_KEY.
+//! @param pui32Src - Pointer to word aligned array of data to program into
+//! the flash instance.
+//! @param pui32Dst - Pointer to the word aligned flash location where
+//! programming of the flash instance is to begin.
+//! @param ui32NumWords - The number of words to be programmed.
+//!
+//! This function will program multiple words in main flash.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return 0 for success, non-zero for failure.
+//
+//*****************************************************************************
+int
+am_hal_flash_program_main(uint32_t ui32Value, uint32_t *pui32Src,
+ uint32_t *pui32Dst, uint32_t ui32NumWords)
+{
+ return g_am_hal_flash.flash_program_main(ui32Value, pui32Src,
+ pui32Dst, ui32NumWords);
+}
+
+//*****************************************************************************
+//
+//! @brief This function programs multiple words in the customer INFO space.
+//!
+//! @param ui32Value - The customer INFO space key.
+//! @param ui32InfoInst - The INFO space instance, 0 or 1.
+//! @param *pui32Src - Pointer to word aligned array of data to program into
+//! the customer INFO space.
+//! @param ui32Offset - Word offset into customer INFO space (offset of 0 is
+//! the first word, 1 is second word, etc.).
+//! @param ui32NumWords - The number of words to be programmed, must not
+//! exceed AM_HAL_FLASH_INFO_SIZE/4.
+//!
+//! This function will program multiple words in the customer INFO space.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return 0 for success, non-zero for failure.
+//
+//*****************************************************************************
+int
+am_hal_flash_program_info(uint32_t ui32Value, uint32_t ui32InfoInst,
+ uint32_t *pui32Src, uint32_t ui32Offset,
+ uint32_t ui32NumWords)
+{
+ return g_am_hal_flash.flash_program_info(ui32Value, 0, pui32Src,
+ ui32Offset, ui32NumWords);
+}
+
+//*****************************************************************************
+//
+//! @brief This function erases an instance of the customer INFO space.
+//!
+//! @param ui32ProgramKey - The customer INFO space programming key
+//! (AM_HAL_FLASH_PROGRAM_KEY).
+//! @param ui32Inst - The flash instance, either 0 or 1.
+//!
+//! This function will erase the the customer INFO space of the specified
+//! instance.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return 0 for success, non-zero for failure.
+//
+//*****************************************************************************
+int
+am_hal_flash_erase_info(uint32_t ui32ProgramKey,
+ uint32_t ui32Inst)
+{
+ return g_am_hal_flash.flash_erase_info(ui32ProgramKey, ui32Inst);
+}
+
+//*****************************************************************************
+//
+//! @brief This function erases the main instance + the customer INFO space.
+//!
+//! @param ui32ProgramKey - The customer INFO space key.
+//! @param ui32Inst - The flash instance, either 0 or 1.
+//!
+//! This function will erase the main flash + the customer INFO space of the
+//! specified instance.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return 0 for success, non-zero for failure.
+//
+//*****************************************************************************
+int
+am_hal_flash_erase_main_plus_info(uint32_t ui32ProgramKey,
+ uint32_t ui32Inst)
+{
+ return g_am_hal_flash.flash_erase_main_plus_info(ui32ProgramKey,
+ ui32Inst);
+}
+
+//*****************************************************************************
+//
+//! @brief This function erases the main flash + the customer INFO space.
+//!
+//! @param ui32ProgramKey - The customer INFO space key.
+//!
+//! This function will erase both instances the main flash + the
+//! customer INFO space.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return 0 for success, non-zero for failure.
+//
+//*****************************************************************************
+int
+am_hal_flash_erase_main_plus_info_both_instances(uint32_t ui32ProgramKey)
+{
+ return g_am_hal_flash.flash_erase_main_plus_info_both_instances(
+ ui32ProgramKey);
+}
+
+//*****************************************************************************
+//
+//! @brief This function erases both main flash instances + both customer INFO
+//! space instances.
+//!
+//! @param ui32RecoveryKey - The recovery key.
+//!
+//! This function erases both main instances and both customer INFOinstances
+//! even if the customer INFO space is programmed to not be erasable. This
+//! function completely erases the flash main and info instances and wipes the
+//! SRAM. Upon completion of the erasure operations, it does a POI (power on
+//! initialization) reset.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Never Returns!!!
+//
+//*****************************************************************************
+void
+am_hal_flash_recovery(uint32_t ui32RecoveryKey)
+{
+ g_am_hal_flash.flash_recovery(ui32RecoveryKey);
+}
+
+//*****************************************************************************
+//
+//! @brief Return ui32 value obtained from anywhere in D Code or System Bus
+//!
+//! @param ui32Address - return the value corresponding to this location.
+//!
+//! Use this function to read a value from various peripheral locations
+//! that must be read from code running external to flash.
+//!
+//! @return the value found
+//
+//*****************************************************************************
+uint32_t
+am_hal_flash_load_ui32(uint32_t ui32Address)
+{
+ return g_am_hal_flash.flash_util_read_word((uint32_t*)ui32Address);
+}
+
+//*****************************************************************************
+//
+//! @brief Use the bootrom to write to a location in SRAM or the system bus.
+//!
+//! @param ui32Address - Store the data value corresponding to this location.
+//! @param ui32Data - 32-bit Data to be stored.
+//!
+//! Use this function to store a value to various peripheral or SRAM locations
+//! that can not be touched from code running in SRAM or FLASH. There is no
+//! known need for this function in Apollo2 at this time.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_flash_store_ui32(uint32_t ui32Address, uint32_t ui32Data)
+{
+ g_am_hal_flash.flash_util_write_word((uint32_t*)ui32Address,
+ ui32Data);
+}
+
+//*****************************************************************************
+//
+//! @brief Use the bootrom to implement a spin loop.
+//!
+//! @param ui32Iterations - Number of iterations to delay.
+//!
+//! Use this function to implement a CPU busy waiting spin loop without cache
+//! or delay uncertainties.
+//!
+//! Note that the ROM-based function executes at 3 cycles per iteration plus
+//! the regular function call, entry, and exit overhead.
+//! The call and return overhead, including the call to this function, is
+//! somewhere in the neighborhood of 14 cycles, or 4.7 iterations.
+//!
+//! Example:
+//! - MCU operating at 48MHz -> 20.83 ns / cycle
+//! - Therefore each iteration (once inside the bootrom function) will consume
+//! 62.5ns.
+//! - The total overhead (assuming 14 cycles) is 292ns.
+//! - For ui32Iterations=28: Total delay time = 0.292 + (0.0625 * 28) = 2.04us.
+//!
+//! The FLASH_CYCLES_US(n) macro can be used with am_hal_flash_delay() to
+//! get an approximate microsecond delay.
+//! e.g. For a 2us delay, use:
+//! am_hal_flash_delay( FLASH_CYCLES_US(2) );
+//!
+//! @note Interrupts are active during execution of this function. Therefore,
+//! any interrupt taken will affect the delay timing.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_flash_delay(uint32_t ui32Iterations)
+{
+ g_am_hal_flash.delay_cycles(ui32Iterations);
+}
+
+//*****************************************************************************
+//
+//! @brief Static Helper Function to check customer info valid bits erasure.
+//!
+//! Use this function to test the state of the 128 valid bits at the beginning
+//! of customer info space. If these are all erased then return true.
+//!
+//! @return true if the customer info bits are currently erased.
+//
+//*****************************************************************************
+static bool
+customer_info_signature_erased(void)
+{
+ uint32_t *pui32Signature = (uint32_t *) AM_HAL_FLASH_INFO_ADDR;
+
+ return ( (pui32Signature[3] == 0xFFFFFFFF) &&
+ (pui32Signature[2] == 0xFFFFFFFF) &&
+ (pui32Signature[1] == 0xFFFFFFFF) &&
+ (pui32Signature[0] == 0xFFFFFFFF) ) ? true : false;
+}
+
+//*****************************************************************************
+//
+//! @brief Static Helper Function to set customer info valid bits
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space. If these bits are not set correctly then the
+//! customer protection bits in the INFO space will not be honored by the
+//! hardware.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+static int
+customer_info_signature_set(void)
+{
+ uint32_t ui32Valid[4];
+ int iRC;
+
+ //
+ // If they are already set then we are done.
+ //
+ if ( am_hal_flash_customer_info_signature_check() )
+ {
+ return 0;
+ }
+
+ //
+ // If they are not erased at this point we have an error.
+ //
+ if ( !customer_info_signature_erased() )
+ {
+ return (2 << 16);
+ }
+
+ //
+ // OK they need to be set so do it.
+ //
+ ui32Valid[3] = AM_HAL_FLASH_INFO_SIGNATURE3;
+ ui32Valid[2] = AM_HAL_FLASH_INFO_SIGNATURE2;
+ ui32Valid[1] = AM_HAL_FLASH_INFO_SIGNATURE1;
+ ui32Valid[0] = AM_HAL_FLASH_INFO_SIGNATURE0;
+
+ iRC = g_am_hal_flash.flash_program_info(AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ ui32Valid, // source data
+ 0, // offset
+ 4); // number of words
+ return iRC | ((iRC) ? (1 << 16) : 0);
+}
+
+//*****************************************************************************
+//
+//! @brief Check that the customer info bits are valid.
+//!
+//! Use this function to test the state of the 128 valid bits at the beginning
+//! of customer info space. If these are not set correctly then the customer
+//! protection bits in the INFO space will not be honored by the hardware.
+//!
+//! @return true if valid.
+//
+//*****************************************************************************
+bool
+am_hal_flash_customer_info_signature_check(void)
+{
+ uint32_t *pui32Signature = (uint32_t *)AM_HAL_FLASH_INFO_ADDR;
+
+ return ( (pui32Signature[3] == AM_HAL_FLASH_INFO_SIGNATURE3) &&
+ (pui32Signature[2] == AM_HAL_FLASH_INFO_SIGNATURE2) &&
+ (pui32Signature[1] == AM_HAL_FLASH_INFO_SIGNATURE1) &&
+ (pui32Signature[0] == AM_HAL_FLASH_INFO_SIGNATURE0) );
+}
+
+//*****************************************************************************
+//
+//! @brief INFO signature set.
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space, if needed.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+bool
+am_hal_flash_info_signature_set(void)
+{
+ //
+ // Check and set signature.
+ //
+ return customer_info_signature_set() ? false : true;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable FLASH INFO space.
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space, if needed. Then disable FLASH erasure.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_info_erase_disable(void)
+{
+ int iRC;
+ uint32_t ui32SecurityValue;
+
+ //
+ // Security protection only works if the signature data is correct.
+ //
+ iRC = customer_info_signature_set();
+ if ( iRC )
+ {
+ return iRC;
+ }
+
+ //
+ // Clear bit in INFO space to disable erasure.
+ //
+ ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ ~AM_HAL_FLASH_INFO_SECURITY_ENINFOERASE_M;
+
+ //
+ // Now write the word to the flash INFO space.
+ //
+ return g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32SecurityValue, // source data
+ AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
+ 1 ); // number of words
+}
+
+//*****************************************************************************
+//
+//! @brief Check for Disabled FLASH INFO space.
+//!
+//! Use this function to determine whether FLASH INFO erasure is disabled.
+//!
+//! @return true if FLASH INFO erase is disabled, otherwise false.
+//
+//*****************************************************************************
+bool
+am_hal_flash_info_erase_disable_check(void)
+{
+ //
+ // If they are erased at this point then SRAM wipe can't be enabled.
+ //
+ if ( customer_info_signature_erased() )
+ {
+ return false;
+ }
+
+ //
+ // If they are not valid at this point then SRAM wipe can't be enabled.
+ //
+ if ( !am_hal_flash_customer_info_signature_check() )
+ {
+ return false;
+ }
+
+ //
+ // Looking good so far, now check the SRAM WIPE bit.
+ //
+ return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ AM_HAL_FLASH_INFO_SECURITY_ENINFOERASE_M ? false : true;
+}
+
+//*****************************************************************************
+//
+//! @brief Mask off 1 to 4 quadrants of FLASH INFO space for programming.
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space, if needed. Then and the mask bits with the INFO
+//! space programming disable bits.
+//!
+//! @param ui32Mask - A mask of the 4 quadrants of info space where
+//! bit0 = First quadrant (first 2KB).
+//! bit1 = Second quadrant (second 2KB).
+//! bit2 = Third quadrant (third 2KB).
+//! bit3 = Fourth quadrant (fourth 2KB).
+//!
+//! @note This function disables only, any quadrant already disabled is not
+//! reenabled. That is, any ui32Mask bits specified as 0 are essentially nops.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_info_program_disable(uint32_t ui32Mask)
+{
+ int iRC;
+ uint32_t ui32SecurityValue;
+
+ //
+ // Security protection only works if the signature data is correct.
+ //
+ iRC = customer_info_signature_set();
+ if ( iRC )
+ {
+ return iRC;
+ }
+
+ //
+ // Make sure we have a valid mask and get the mask into the correct position.
+ //
+ ui32Mask <<= AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_S;
+ ui32Mask &= AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_M;
+
+ //
+ // The security bit set to 1 enables programming, 0 disables programming.
+ //
+ ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) & ~ui32Mask;
+
+ //
+ // Now write the word to the flash INFO space.
+ //
+ return g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32SecurityValue, // source data
+ AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
+ 1 ); // number of words
+}
+
+//*****************************************************************************
+//
+//! @brief Return a mask specifying which quadrants of customer INFO space have
+//! been disabled for programming.
+//!
+//! Use this function to determine whether programming of customer INFO space
+//! has been disabled.
+//!
+//! @return A 4-bit mask of the disabled quadrants.
+//! 0xFFFFFFFF indicates an error.
+//! 0x0 indicates all customer INFO space programming is enabled.
+//! 0xF indicates all customer INFO space programming is disabled.
+//! bit0 indicates the first customer INFO space is disabled for programming.
+//! bit1 indicates the second customer INFO space is disabled for programming.
+//! bit2 indicates the third customer INFO space is disabled for programming.
+//! bit3 indicates the fourth customer INFO space is disabled for programming.
+//
+//*****************************************************************************
+uint32_t
+am_hal_flash_info_program_disable_get(void)
+{
+ //
+ // If they are erased at this point then SRAM wipe can't be enabled.
+ //
+ if ( customer_info_signature_erased() )
+ {
+ return 0xFFFFFFFF;
+ }
+
+ //
+ // If not valid at this point, then INFO programming can't be enabled.
+ //
+ if ( !am_hal_flash_customer_info_signature_check() )
+ {
+ return 0xFFFFFFFF;
+ }
+
+ //
+ // Looking good so far, now return a mask of the disabled bits.
+ //
+ return ((AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_M) ^
+ AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_M) >>
+ AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_S;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable FLASH debugger protection (FLASH gets wiped if a debugger is
+//! connected).
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space, if needed. Then set the FLASH wipe bit to zero.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_wipe_flash_enable(void)
+{
+ int iRC;
+ uint32_t ui32SecurityValue;
+
+ //
+ // Security protection only works if the signature data is correct.
+ //
+ iRC = customer_info_signature_set();
+ if ( iRC )
+ {
+ return iRC;
+ }
+
+ //
+ // Clear the FLASH Wipe bit.
+ //
+ ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ ~AM_HAL_FLASH_INFO_SECURITY_FLASHWIPE_M;
+
+ //
+ // Now write the word to the flash INFO space.
+ //
+ return g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32SecurityValue, // source data
+ AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
+ 1 ); // number of words
+}
+
+//*****************************************************************************
+//
+//! @brief check for FLASH wipe protection enabled.
+//!
+//! Use this function to determine if FLASH wipe protection is enabled.
+//!
+//! @return true if FLASH wipe protection is enabled, otherwise false.
+//
+//*****************************************************************************
+bool
+am_hal_flash_wipe_flash_enable_check(void)
+{
+ //
+ // If they are erased at this point then flash wipe can't be enabled.
+ //
+ if ( customer_info_signature_erased() )
+ {
+ return false;
+ }
+
+ //
+ // If they are not valid at this point then flash wipe can't be enabled.
+ //
+ if ( !am_hal_flash_customer_info_signature_check() )
+ {
+ return false;
+ }
+
+ //
+ // Looking good so far, now check the Flash WIPE bit.
+ //
+ return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ AM_HAL_FLASH_INFO_SECURITY_FLASHWIPE_M ? false : true;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable SRAM protection so SRAM gets wiped if a debgger is connected.
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space, if needed. Then set the SRAM wipe bit to zero.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_wipe_sram_enable(void)
+{
+ int iRC;
+ uint32_t ui32SecurityValue;
+
+ //
+ // Security protection only works if the signature data is correct.
+ //
+ iRC = customer_info_signature_set();
+ if ( iRC )
+ {
+ return iRC;
+ }
+
+ //
+ // Clear the SRAM Wipe bit.
+ //
+ ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ ~AM_HAL_FLASH_INFO_SECURITY_SRAMWIPE_M;
+
+ //
+ // Now write the word to the flash INFO space.
+ //
+ return g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32SecurityValue, // source data
+ AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
+ 1 ); // number of words
+}
+
+//*****************************************************************************
+//
+//! @brief check for SRAM protection enabled.
+//!
+//! Use this function to determine if SRAM protection is enabled.
+//!
+//! @return true if SRAM wipe protection is enabled, otherwise false.
+//
+//*****************************************************************************
+bool
+am_hal_flash_wipe_sram_enable_check(void)
+{
+ //
+ // If they are erased at this point then SRAM wipe can't be enabled.
+ //
+ if ( customer_info_signature_erased() )
+ {
+ return false;
+ }
+
+ //
+ // If they are not vale at this point then SRAM wipe can't be enabled.
+ //
+ if ( !am_hal_flash_customer_info_signature_check() )
+ {
+ return false;
+ }
+
+ //
+ // Looking good so far, now check the SRAM WIPE bit.
+ //
+ return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ AM_HAL_FLASH_INFO_SECURITY_SRAMWIPE_M ? false : true;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable Output from ITM/SWO.
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space, if needed. Set the SWO disable bit to zero.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_swo_disable(void)
+{
+ int iRC;
+ uint32_t ui32SecurityValue;
+
+ //
+ // Security protection only works if the signature data is correct.
+ //
+ iRC = customer_info_signature_set();
+ if ( iRC )
+ {
+ return iRC;
+ }
+
+ //
+ // Clear the SWO bit.
+ //
+ ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ ~AM_HAL_FLASH_INFO_SECURITY_SWOCTRL_M;
+
+ //
+ // Now write the word to the flash INFO space.
+ //
+ return g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32SecurityValue, // source data
+ AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
+ 1 ); // number of words
+}
+
+//*****************************************************************************
+//
+//! @brief check for SWO disabled.
+//!
+//! Use this function to determine if the SWO is disabled.
+//!
+//! @return true if the ITM/SWO is disabled, otherwise false.
+//
+//*****************************************************************************
+bool
+am_hal_flash_swo_disable_check(void)
+{
+ //
+ // If they are erased at this point then SRAM wipe can't be enabled.
+ //
+ if ( customer_info_signature_erased() )
+ {
+ return false;
+ }
+
+ //
+ // If they are not vale at this point then SRAM wipe can't be enabled.
+ //
+ if ( !am_hal_flash_customer_info_signature_check() )
+ {
+ return false;
+ }
+
+ //
+ // Looking good so far, now check the SWO bit.
+ //
+ return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ AM_HAL_FLASH_INFO_SECURITY_SWOCTRL_M ? false : true;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable Connections from a debugger on the SWD interface.
+//!
+//! Use this function to set the state of the 128 valid bits at the beginning
+//! of customer info space, if needed. Set the debugger disable bit to zero.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return Zero for success. Non-Zero for errors.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_debugger_disable(void)
+{
+ int iRC;
+ uint32_t ui32SecurityValue;
+
+ //
+ // Security protection only works if the signature data is correct.
+ //
+ iRC = customer_info_signature_set();
+ if ( iRC )
+ {
+ return iRC;
+ }
+
+ //
+ // Clear the DEBUGGER bit.
+ //
+ ui32SecurityValue = AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ ~AM_HAL_FLASH_INFO_SECURITY_DEBUGGERPROT_M;
+
+ //
+ // Now write the word to the flash INFO space.
+ //
+ return g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32SecurityValue, // source data
+ AM_HAL_FLASH_INFO_SECURITY_O / 4, // word offset
+ 1 ); // number of words
+}
+
+//*****************************************************************************
+//
+//! @brief check for debugger disabled.
+//!
+//! Use this function to determine if the debugger is disabled.
+//!
+//! @return true if the debugger is disabled, otherwise false.
+//
+//*****************************************************************************
+bool
+am_hal_flash_debugger_disable_check(void)
+{
+ //
+ // If they are erased at this point then SRAM wipe can't be enabled.
+ //
+ if ( customer_info_signature_erased() )
+ {
+ return false;
+ }
+
+ //
+ // If they are not vale at this point then SRAM wipe can't be enabled.
+ //
+ if ( !am_hal_flash_customer_info_signature_check() )
+ {
+ return false;
+ }
+
+ //
+ // Looking good so far, now check the debugger disable bit.
+ //
+ return AM_REGVAL(AM_HAL_FLASH_INFO_SECURITY_ADDR) &
+ AM_HAL_FLASH_INFO_SECURITY_DEBUGGERPROT_M ? false : true;
+}
+
+//*****************************************************************************
+//
+//! @brief This static helper function generates a 64-bit protection mask.
+//!
+//! @param pui32StartAddress - Starting address in flash to begin protection.
+//! @param pui32StopAddress - Ending address in flash to stop protection.
+//!
+//! This function computes a chunk map for the protection range.
+//!
+//! @return Inverse of the actual chunk mask. That is, chunks to be protected
+//! are represented as 0 in the returned mask, while chunks to be left alone
+//! are represented as 1. This value can therefore be directly ANDed with the
+//! existing bits in INFO space.
+//! Note that -1 is returned if input parameters are invalid - this return
+//! value would indicate that no chunks are to be protected.
+//!
+//
+//*****************************************************************************
+static uint64_t
+generate_chunk_mask(uint32_t *pui32StartAddress, uint32_t *pui32StopAddress)
+{
+ uint32_t ui32ChunkStart, ui32ChunkStop;
+ uint32_t ui32Width;
+ uint64_t ui64Mask;
+
+ //
+ // Validate the address input parameters
+ //
+ if ( (pui32StartAddress > pui32StopAddress) ||
+ (pui32StopAddress > (uint32_t*)AM_HAL_FLASH_LARGEST_VALID_ADDR) )
+ {
+ //
+ // Argument error, return value to leave all chunks unprotected.
+ //
+ return 0xFFFFFFFFFFFFFFFF;
+ }
+
+ //
+ // Extract chunk related information
+ //
+ ui32ChunkStart = AM_HAL_FLASH_INFO_ADDR2CHUNK((uint32_t)pui32StartAddress);
+ ui32ChunkStop = AM_HAL_FLASH_INFO_ADDR2CHUNK((uint32_t)pui32StopAddress);
+ ui32Width = ui32ChunkStop - ui32ChunkStart + 1;
+
+ if ( ui32Width == 64 )
+ {
+ ui64Mask = (uint64_t)0xFFFFFFFFFFFFFFFFLLU;
+ }
+ else
+ {
+ ui64Mask = ( ((uint64_t)0x0000000000000001) << ui32Width) - 1;
+ ui64Mask <<= ui32ChunkStart;
+ }
+
+ //
+ // OK now return the chunk mask (inverted).
+ //
+ return ~ui64Mask;
+}
+
+//*****************************************************************************
+//
+//! @brief This function sets copy protection for a range of flash chunks.
+//!
+//! @param pui32StartAddress - Starting address in flash to begin protection.
+//! @param pui32StopAddress - Ending address in flash to stop protection.
+//!
+//! This function will set copy protection bits for a range of flash chunks
+//!
+//! @note Each flash chunk contains 16KBytes and corresponds to one bit in
+//! the protection register. Set the bit to zero to enable protection.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return
+//! 0 for success.
+//! 0x400000 if the protection bits were already programmed (mask the return
+//! value with 0x3FFFFF to ignore this case and treat as success).
+//! Otherwise, non-zero for failure.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_copy_protect_set(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress)
+{
+ int iRC;
+ bool bModified = false;
+ uint64_t ui64Mask;
+ uint32_t ui32Work;
+ uint32_t ui32Protection[2];
+ uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_COPYPROT_ADDR;
+
+ //
+ // Extract chunk mask from parameters.
+ // Also checks parameter validity (returns -1 if bad parameters).
+ //
+ ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
+ if ( ~ui64Mask == 0x0 )
+ {
+ return 0x100000;
+ }
+
+ //
+ // Go get the current settings for copy protection.
+ //
+ ui32Protection[0] = pui32Protection[0];
+ ui32Protection[1] = pui32Protection[1];
+
+ //
+ // AND mask off the necessary protection bits in the lower word.
+ //
+ ui32Work = (uint32_t)ui64Mask;
+ if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[0] ) )
+ {
+ bModified = true;
+ ui32Protection[0] &= ui32Work;
+ iRC = g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32Protection[0], // source data
+ (AM_HAL_FLASH_INFO_COPYPROT_O / 4) + 0, // word offset
+ 1 ); // number of words
+
+ if ( iRC )
+ {
+ return iRC | 0x10000;
+ }
+ }
+
+ //
+ // AND mask off the necessary protection bits in the upper word.
+ //
+ ui32Work = (uint32_t)(ui64Mask >> 32);
+ if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[1] ) )
+ {
+ bModified = true;
+ ui32Protection[1] &= ui32Work;
+ iRC = g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32Protection[1], // source data
+ (AM_HAL_FLASH_INFO_COPYPROT_O / 4) + 1, // word offset
+ 1 ); // number of words
+
+ if ( iRC )
+ {
+ return iRC | 0x20000;
+ }
+ }
+
+ if ( bModified )
+ {
+ return 0;
+ }
+ else
+ {
+ return 0x400000;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief This function checks copy protection for a range of flash chunks.
+//!
+//! @param pui32StartAddress - Starting address in flash.
+//! @param pui32StopAddress - Ending address in flash.
+//!
+//! This function will check copy protection bits for a range of flash chunks
+//! it expects all chunks in the range to be protected.
+//!
+//! @note Each flash chunk contains 16KBytes and corresponds to one bit in
+//! the protection register. Set the bit to zero to enable protection.
+//!
+//! @return false for at least one chunk in the covered range is not protected,
+//! and true if all chunks in the covered range are protected.
+//!
+//
+//*****************************************************************************
+bool
+am_hal_flash_copy_protect_check(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress)
+{
+ uint64_t ui64Mask;
+ uint32_t ui32Work;
+ uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_COPYPROT_ADDR;
+
+ //
+ // Extract chunk mask from parameters.
+ // Also checks parameter validity (returns -1 if bad parameters).
+ //
+ ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
+ if ( ~ui64Mask == 0x0 )
+ {
+ return false;
+ }
+
+ //
+ // Now check the lower word of protection bits.
+ //
+ ui32Work = (uint32_t)ui64Mask;
+ if ( ~ui32Work & pui32Protection[0] )
+ {
+ return false;
+ }
+
+ //
+ // Now check the lower word of protection bits.
+ //
+ ui32Work = (uint32_t)(ui64Mask >> 32);
+ if ( ~ui32Work & pui32Protection[1] )
+ {
+ return false;
+ }
+
+ //
+ // If we get here, there are no unprotected chunks within specified range.
+ //
+ return true;
+}
+
+//*****************************************************************************
+//
+//! @brief This function sets write protection for a range of flash chunks.
+//!
+//! @param pui32StartAddress - Starting address in flash to begin protection.
+//! @param pui32StopAddress - Ending address in flash to stop protection.
+//!
+//! This function will set write protection bits for a range of flash chunks
+//!
+//! @note Each flash chunk contains 16KBytes and corresponds to one bit in
+//! the protection register. Set the bit to zero to enable protection.
+//!
+//! @note Interrupts are active during execution of this function. Any interrupt
+//! taken could cause execution errors. Please see the IMPORTANT note under
+//! Detailed Description above for more details.
+//!
+//! @return
+//! 0 for success.
+//! 0x400000 if the protection bits were already programmed (mask the return
+//! value with 0x3FFFFF to ignore this case and treat as success).
+//! Otherwise, non-zero for failure.
+//
+//*****************************************************************************
+int32_t
+am_hal_flash_write_protect_set(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress)
+{
+ int iRC;
+ bool bModified = false;
+ uint64_t ui64Mask;
+ uint32_t ui32Work;
+ uint32_t ui32Protection[2];
+ uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_WRITPROT_ADDR;
+
+ //
+ // Extract chunk mask from parameters.
+ // Also checks parameter validity (returns -1 if bad parameters).
+ //
+ ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
+ if ( ~ui64Mask == 0x0 )
+ {
+ return 0x100000;
+ }
+
+ //
+ // Go get the current settings for copy protection.
+ //
+ ui32Protection[0] = pui32Protection[0];
+ ui32Protection[1] = pui32Protection[1];
+
+ //
+ // AND mask off the necessary protection bits in the lower word.
+ //
+ ui32Work = (uint32_t)ui64Mask;
+ if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[0] ) )
+ {
+ bModified = true;
+ ui32Protection[0] &= ui32Work;
+ iRC = g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32Protection[0], // source data
+ (AM_HAL_FLASH_INFO_WRITPROT_O / 4) + 0, // word offset
+ 1 ); // number of words
+
+ if ( iRC )
+ {
+ return iRC | 0x10000;
+ }
+ }
+
+ //
+ // AND mask off the necessary protection bits in the upper word.
+ //
+ ui32Work = (uint32_t)(ui64Mask >> 32);
+ if ( ( ~ui32Work ) && ( ui32Work != ui32Protection[1] ) )
+ {
+ bModified = true;
+ ui32Protection[1] &= ui32Work;
+ iRC = g_am_hal_flash.flash_program_info(
+ AM_HAL_FLASH_PROGRAM_KEY,
+ 0, // instance
+ &ui32Protection[1], // source data
+ (AM_HAL_FLASH_INFO_WRITPROT_O / 4) + 1, // word offset
+ 1 ); // number of words
+
+ if ( iRC )
+ {
+ return iRC | 0x20000;
+ }
+ }
+
+ if ( bModified )
+ {
+ return 0;
+ }
+ else
+ {
+ return 0x400000;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief This function checks write protection for a range of flash chunks.
+//!
+//! @param pui32StartAddress - Starting address in flash.
+//! @param pui32StopAddress - Ending address in flash.
+//!
+//! This function will check write protection bits for a range of flash chunks
+//! it expects all chunks in the range to be protected.
+//!
+//! @note Each flash chunk contains 16KBytes and corresponds to one bit in
+//! the protection register. Set the bit to zero to enable protection.
+//!
+//! @return false for at least one chunk in the covered range is not protected,
+//! and true if all chunks in the covered range are protected.
+//!
+//
+//*****************************************************************************
+bool
+am_hal_flash_write_protect_check(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress)
+{
+ uint64_t ui64Mask;
+ uint32_t ui32Work;
+ uint32_t *pui32Protection = (uint32_t *)AM_HAL_FLASH_INFO_WRITPROT_ADDR;
+
+ //
+ // Extract chunk mask from parameters.
+ // Also checks parameter validity (returns -1 if bad parameters).
+ //
+ ui64Mask = generate_chunk_mask(pui32StartAddress, pui32StopAddress);
+ if ( ~ui64Mask == 0x0 )
+ {
+ return false;
+ }
+
+ //
+ // Now check the lower word of protection bits.
+ //
+ ui32Work = (uint32_t)ui64Mask;
+ if ( ~ui32Work & pui32Protection[0] )
+ {
+ return false;
+ }
+
+ //
+ // Now check the lower word of protection bits.
+ //
+ ui32Work = (uint32_t)(ui64Mask >> 32);
+ if ( ~ui32Work & pui32Protection[1] )
+ {
+ return false;
+ }
+
+ //
+ // If we get here, there are no unprotected chunks within specified range.
+ //
+ return true;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_flash.h b/bsp/apollo2/libraries/drivers/hal/am_hal_flash.h
new file mode 100644
index 0000000000..66d6f5059c
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_flash.h
@@ -0,0 +1,297 @@
+//*****************************************************************************
+//
+// am_hal_flash.h
+//! @file
+//!
+//! @brief Functions for performing Flash operations.
+//!
+//! @addtogroup flash2 Flash
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_FLASH_H
+#define AM_HAL_FLASH_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+//*****************************************************************************
+//
+// Flash Program keys.
+//
+//*****************************************************************************
+#define AM_HAL_FLASH_PROGRAM_KEY 0x12344321
+#define AM_HAL_FLASH_RECOVERY_KEY 0xA35C9B6D
+#define AM_HAL_FLASH_INFO_KEY 0x12344321
+#define AM_HAL_FLASH_OTP_KEY (AM_HAL_FLASH_INFO_KEY)
+
+//*****************************************************************************
+//
+// Some helpful flash values and macros.
+//
+//*****************************************************************************
+#define AM_HAL_FLASH_ADDR 0x00000000
+#define AM_HAL_FLASH_PAGE_SIZE ( 8 * 1024 )
+#define AM_HAL_FLASH_INFO_SIZE AM_HAL_FLASH_PAGE_SIZE
+#define AM_HAL_FLASH_INSTANCE_SIZE ( 512 * 1024 )
+#define AM_HAL_FLASH_INSTANCE_PAGES ( AM_HAL_FLASH_INSTANCE_SIZE / AM_HAL_FLASH_PAGE_SIZE )
+#define AM_HAL_FLASH_TOTAL_SIZE ( AM_HAL_FLASH_INSTANCE_SIZE * 2 )
+#define AM_HAL_FLASH_LARGEST_VALID_ADDR ( AM_HAL_FLASH_ADDR + AM_HAL_FLASH_TOTAL_SIZE - 1 )
+
+//
+// Convert an absolute flash address to a instance
+//
+#define AM_HAL_FLASH_ADDR2INST(addr) ( ( addr >> 19 ) & 1 )
+
+//
+// Convert an absolute flash address to a page number relative to the instance
+//
+#define AM_HAL_FLASH_ADDR2PAGE(addr) ( ( addr >> 13 ) & 0x3F )
+
+//
+// Convert an absolute flash address to an absolute page number
+//
+#define AM_HAL_FLASH_ADDR2ABSPAGE(addr) ( addr >> 13 )
+
+//
+// Given a number of microseconds, convert to a value representing the number of
+// cycles that will give that delay. This macro is basically taking into account
+// some of the call overhead.
+// e.g. To provide a 2us delay:
+// am_hal_flash_delay( FLASH_CYCLES_US(2) );
+//
+#define FLASH_CYCLES_US(n) ((n * (AM_HAL_CLKGEN_FREQ_MAX_MHZ / 3)) - 4)
+
+//
+// Backward compatibility
+//
+#define am_hal_flash_program_otp am_hal_flash_program_info
+#define am_hal_flash_program_otp_sram am_hal_flash_program_info_sram
+
+//*****************************************************************************
+//
+// Structure of function pointers to helper functions for invoking various
+// flash operations. The functions we are pointing to here are in the Apollo 2
+// integrated BOOTROM.
+//
+//*****************************************************************************
+typedef struct am_hal_flash_helper_struct
+{
+ //
+ // The basics.
+ //
+ int (*flash_mass_erase)(uint32_t, uint32_t);
+ int (*flash_page_erase)(uint32_t, uint32_t, uint32_t);
+ int (*flash_program_main)(uint32_t, uint32_t *,
+ uint32_t*, uint32_t);
+ int (*flash_program_info)(uint32_t, uint32_t,
+ uint32_t*, uint32_t, uint32_t);
+
+ //
+ // Non-blocking variants, but be careful these are not interrupt safe so
+ // mask interrupts while these very long operations proceed.
+ //
+ int (*flash_mass_erase_nb)(uint32_t, uint32_t);
+ int (*flash_page_erase_nb)(uint32_t, uint32_t, uint32_t);
+ bool (*flash_nb_operation_complete)(void);
+
+ //
+ // Essentially these are recovery options.
+ //
+ int (*flash_erase_info)(uint32_t, uint32_t);
+ int (*flash_erase_main_plus_info)(uint32_t, uint32_t);
+ int (*flash_erase_main_plus_info_both_instances)(uint32_t);
+ void (*flash_recovery)(uint32_t);
+
+ //
+ // Useful utilities.
+ //
+ uint32_t (*flash_util_read_word)(uint32_t*);
+ void (*flash_util_write_word)(uint32_t*, uint32_t);
+ void (*delay_cycles)(uint32_t);
+
+ //
+ // The following functions pointers will generally never be called from
+ // user programs. They are here primarily to document these entry points
+ // which are usable from a debugger or debugger script.
+ //
+ void (*flash_program_main_sram)(void);
+ void (*flash_program_info_sram)(void);
+ void (*flash_erase_main_pages_sram)(void);
+ void (*flash_mass_erase_sram)(void);
+ void (*flash_erase_info_sram)(void);
+ void (*flash_erase_main_plus_info_sram)(void);
+} g_am_hal_flash_t;
+extern g_am_hal_flash_t g_am_hal_flash;
+
+
+//*****************************************************************************
+//
+// Define some FLASH INFO SPACE values and macros.
+//
+//*****************************************************************************
+#define AM_HAL_FLASH_INFO_ADDR 0x50020000
+#define AM_HAL_FLASH_INFO_SECURITY_O 0x10
+#define AM_HAL_FLASH_INFO_WRITPROT_O 0x20
+#define AM_HAL_FLASH_INFO_COPYPROT_O 0x30
+
+#define AM_HAL_FLASH_INFO_SECURITY_ADDR (AM_HAL_FLASH_INFO_ADDR + AM_HAL_FLASH_INFO_SECURITY_O)
+#define AM_HAL_FLASH_INFO_WRITPROT_ADDR (AM_HAL_FLASH_INFO_ADDR + AM_HAL_FLASH_INFO_WRITPROT_O)
+#define AM_HAL_FLASH_INFO_COPYPROT_ADDR (AM_HAL_FLASH_INFO_ADDR + AM_HAL_FLASH_INFO_COPYPROT_O)
+
+//
+// Define the customer info signature data (at AM_HAL_FLASH_INFO_ADDR).
+// These bits must exist in the customer info space in order for many of the
+// security and protection functions to work.
+//
+#define AM_HAL_FLASH_INFO_SIGNATURE0 0x48EAAD88
+#define AM_HAL_FLASH_INFO_SIGNATURE1 0xC9705737
+#define AM_HAL_FLASH_INFO_SIGNATURE2 0x0A6B8458
+#define AM_HAL_FLASH_INFO_SIGNATURE3 0xE41A9D74
+
+//
+// Define the customer security bits (at AM_HAL_FLASH_INFO_SECURITY_ADDR)
+//
+#define AM_HAL_FLASH_INFO_SECURITY_DEBUGGERPROT_S 0
+#define AM_HAL_FLASH_INFO_SECURITY_SWOCTRL_S 1
+#define AM_HAL_FLASH_INFO_SECURITY_SRAMWIPE_S 2
+#define AM_HAL_FLASH_INFO_SECURITY_FLASHWIPE_S 3
+#define AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_S 4
+#define AM_HAL_FLASH_INFO_SECURITY_ENINFOERASE_S 8
+#define AM_HAL_FLASH_INFO_SECURITY_BOOTLOADERSPIN_S 9
+
+#define AM_HAL_FLASH_INFO_SECURITY_DEBUGGERPROT_M ((uint32_t)(0x1 << AM_HAL_FLASH_INFO_SECURITY_DEBUGGERPROT_S))
+#define AM_HAL_FLASH_INFO_SECURITY_SWOCTRL_M ((uint32_t)(0x1 << AM_HAL_FLASH_INFO_SECURITY_SWOCTRL_S))
+#define AM_HAL_FLASH_INFO_SECURITY_SRAMWIPE_M ((uint32_t)(0x1 << AM_HAL_FLASH_INFO_SECURITY_SRAMWIPE_S))
+#define AM_HAL_FLASH_INFO_SECURITY_FLASHWIPE_M ((uint32_t)(0x1 << AM_HAL_FLASH_INFO_SECURITY_FLASHWIPE_S))
+#define AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_M ((uint32_t)(0xF << AM_HAL_FLASH_INFO_SECURITY_ENINFOPRGM_S))
+#define AM_HAL_FLASH_INFO_SECURITY_ENINFOERASE_M ((uint32_t)(0x1 << AM_HAL_FLASH_INFO_SECURITY_ENINFOERASE_S))
+#define AM_HAL_FLASH_INFO_SECURITY_BOOTLOADERSPIN_M ((uint32_t)(0x1 << AM_HAL_FLASH_INFO_SECURITY_BOOTLOADERSPIN_S))
+#define AM_HAL_FLASH_INFO_SECURITY_DEEPSLEEP_M ((uint32_t)(0x1 << AM_HAL_FLASH_INFO_SECURITY_BOOTLOADERSPIN_S))
+#define AM_HAL_FLASH_INFO_SECURITY_DEEPSLEEP ((uint32_t)(0x0 << AM_HAL_FLASH_INFO_SECURITY_BOOTLOADERSPIN_S))
+
+//
+// Protection chunk macros
+// AM_HAL_FLASH_INFO_CHUNK2ADDR: Convert a chunk number to an address
+// AM_HAL_FLASH_INFO_CHUNK2INST: Convert a chunk number to an instance number
+// AM_HAL_FLASH_INFO_ADDR2CHUNK: Convert an address to a chunk number
+//
+#define AM_HAL_FLASH_INFO_CHUNKSIZE (16*1024)
+
+#define AM_HAL_FLASH_INFO_CHUNK2ADDR(n) (AM_HAL_FLASH_ADDR + (n << 14))
+#define AM_HAL_FLASH_INFO_CHUNK2INST(n) ((n >> 5) & 1
+#define AM_HAL_FLASH_INFO_ADDR2CHUNK(n) ((n) >> 14)
+
+//*****************************************************************************
+//
+// Function prototypes for the helper functions
+//
+//*****************************************************************************
+extern int am_hal_flash_mass_erase(uint32_t ui32Value, uint32_t ui32FlashInst);
+extern int am_hal_flash_page_erase(uint32_t ui32Value, uint32_t ui32FlashInst,
+ uint32_t ui32PageNum);
+extern int am_hal_flash_program_main(uint32_t value, uint32_t *pSrc,
+ uint32_t *pDst, uint32_t NumberOfWords);
+extern int am_hal_flash_program_info(uint32_t ui32Value, uint32_t ui32InfoInst,
+ uint32_t *pui32Src, uint32_t ui32Offset,
+ uint32_t ui32NumWords);
+
+//
+// Recovery type functions for Customer INFO space.
+//
+extern int am_hal_flash_erase_info(uint32_t ui32ProgramKey,
+ uint32_t ui32Instance);
+extern int am_hal_flash_erase_main_plus_info(uint32_t ui32ProgramKey,
+ uint32_t ui32Instance);
+extern int am_hal_flash_erase_main_plus_info_both_instances(
+ uint32_t ui32ProgramKey);
+extern void am_hal_flash_recovery(uint32_t ui32RecoveryKey);
+
+//
+// BOOTROM resident reader, writer and delay utility functions.
+//
+extern uint32_t am_hal_flash_load_ui32(uint32_t ui32Address);
+extern void am_hal_flash_store_ui32(uint32_t ui32Address, uint32_t ui32Data);
+extern void am_hal_flash_delay(uint32_t ui32Iterations);
+
+//
+// These functions update security/protection bits in the customer INFO blOCK.
+//
+extern bool am_hal_flash_customer_info_signature_check(void);
+extern bool am_hal_flash_info_signature_set(void);
+extern int32_t am_hal_flash_info_erase_disable(void);
+extern bool am_hal_flash_info_erase_disable_check(void);
+extern int32_t am_hal_flash_info_program_disable(uint32_t ui32Mask);
+extern uint32_t am_hal_flash_info_program_disable_get(void);
+extern int32_t am_hal_flash_wipe_flash_enable(void);
+extern bool am_hal_flash_wipe_flash_enable_check(void);
+extern int32_t am_hal_flash_wipe_sram_enable(void);
+extern bool am_hal_flash_wipe_sram_enable_check(void);
+extern int32_t am_hal_flash_swo_disable(void);
+extern bool am_hal_flash_swo_disable_check(void);
+extern int32_t am_hal_flash_debugger_disable(void);
+extern bool am_hal_flash_debugger_disable_check(void);
+
+extern int32_t am_hal_flash_copy_protect_set(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress);
+extern bool am_hal_flash_copy_protect_check(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress);
+extern int32_t am_hal_flash_write_protect_set(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress);
+extern bool am_hal_flash_write_protect_check(uint32_t *pui32StartAddress,
+ uint32_t *pui32StopAddress);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_FLASH_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_global.c b/bsp/apollo2/libraries/drivers/hal/am_hal_global.c
new file mode 100644
index 0000000000..498eb1627a
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_global.c
@@ -0,0 +1,59 @@
+//*****************************************************************************
+//
+// am_hal_global.c
+//! @file
+//!
+//! @brief Locate global variables here.
+//!
+//! This module contains global variables that are used throughout the HAL.
+//!
+//! One use in particular is that it uses a global HAL flags variable that
+//! contains flags used in various parts of the HAL.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Global Variables
+//
+//*****************************************************************************
+uint32_t volatile g_ui32HALflags = 0x00000000;
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_global.h b/bsp/apollo2/libraries/drivers/hal/am_hal_global.h
new file mode 100644
index 0000000000..bb437b198a
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_global.h
@@ -0,0 +1,114 @@
+//*****************************************************************************
+//
+// am_hal_global.h
+//! @file
+//!
+//! @brief Locate all HAL global variables here.
+//!
+//! This module contains global variables that are used throughout the HAL,
+//! but not necessarily those designated as const (which typically end up in
+//! flash). Consolidating globals here will make it easier to manage them.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_GLOBAL_H
+#define AM_HAL_GLOBAL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Macro definitions
+//
+//*****************************************************************************
+
+//******************************************************************************
+//
+// Macros used to access the bit fields in the flags variable.
+//
+//******************************************************************************
+#define AM_HAL_FLAGS_BFR(flagnm) \
+ ((g_ui32HALflags & AM_HAL_FLAGS_##flagnm##_M) >> AM_HAL_FLAGS_##flagnm##_S)
+
+#define AM_HAL_FLAGS_BFW(flagnm, value) \
+ g_ui32HALflags = ((g_ui32HALflags & (~(AM_HAL_FLAGS_##flagnm##_M))) | \
+ ((value << AM_HAL_FLAGS_##flagnm##_S) & (AM_HAL_FLAGS_##flagnm##_M)) )
+
+//******************************************************************************
+//
+// ITMSKIPENABLEDISABLE - Set when the ITM is not to be disabled. This is
+// typically needed by Keil debug.ini.
+//
+//******************************************************************************
+#define AM_HAL_FLAGS_ITMSKIPENABLEDISABLE_S 0
+#define AM_HAL_FLAGS_ITMSKIPENABLEDISABLE_M (1 << AM_HAL_FLAGS_ITMSKIPENABLEDISABLE_S)
+#define AM_HAL_FLAGS_ITMSKIPENABLEDISABLE(n) (((n) << AM_HAL_FLAGS_ITMSKIPENABLEDISABLE_S) & AM_HAL_FLAGS_ITMSKIPENABLEDISABLE_M)
+
+//******************************************************************************
+//
+// ITMBKPT - Breakpoint at the end of itm_enable(), which is needed by
+// Keil debug.ini.
+//
+//******************************************************************************
+#define AM_HAL_FLAGS_ITMBKPT_S 1
+#define AM_HAL_FLAGS_ITMBKPT_M (1 << AM_HAL_FLAGS_ITMBKPT_S)
+#define AM_HAL_FLAGS_ITMBKPT(n) (((n) << AM_HAL_FLAGS_ITMBKPT_S) & AM_HAL_FLAGS_ITMBKPT_M)
+
+//******************************************************************************
+//
+// Next available flag or bit field.
+//
+//******************************************************************************
+#define AM_HAL_FLAGS_NEXTBITFIELD_S 2
+#define AM_HAL_FLAGS_NEXTBITFIELD_M (1 << AM_HAL_FLAGS_NEXTBITFIELD_S)
+#define AM_HAL_FLAGS_NEXTBITFIELD(n) (((n) << AM_HAL_FLAGS_NEXTBITFIELD_S) & AM_HAL_FLAGS_NEXTBITFIELD_M)
+
+//*****************************************************************************
+//
+// Global Variables extern declarations.
+//
+//*****************************************************************************
+extern volatile uint32_t g_ui32HALflags;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_GLOBAL_H
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_gpio.c b/bsp/apollo2/libraries/drivers/hal/am_hal_gpio.c
new file mode 100644
index 0000000000..480118da6b
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_gpio.c
@@ -0,0 +1,503 @@
+//*****************************************************************************
+//
+// am_hal_gpio.c
+//! @file
+//!
+//! @brief Functions for interfacing with the GPIO module
+//!
+//! @addtogroup gpio2 GPIO
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Array of function pointers for handling GPIO interrupts.
+//
+//*****************************************************************************
+am_hal_gpio_handler_t am_hal_gpio_ppfnHandlers[64];
+
+//*****************************************************************************
+//
+//! @brief Read the configuration information for the given pin..
+//!
+//! @param ui32GPIONum is the GPIO number whose configuration we want to read.
+//!
+//! This function reads the PADREG, GPIO CFG, and ALTPAD registers for the
+//! given GPIO and returns them in the following format:
+//!
+//! ( (ALTPAD << 16) | (CFG << 8) | PADREG)
+//!
+//! This is the same format used by the \e am_hal_gpio_pin_config()
+//! function-like macro.
+//!
+//! @return Pin configuration information.
+//
+//*****************************************************************************
+uint32_t
+am_hal_gpio_pin_config_read(uint32_t ui32PinNumber)
+{
+ uint32_t ui32CfgVal, ui32PadregVal, ui32AltPadVal;
+
+ am_hal_debug_assert_msg(ui32PinNumber <= 63, "Invalid GPIO number.");
+
+ ui32CfgVal = AM_HAL_GPIO_CFG_R(ui32PinNumber);
+ ui32PadregVal = AM_HAL_GPIO_PADREG_R(ui32PinNumber);
+ ui32AltPadVal = AM_HAL_GPIO_ALTPADREG_R(ui32PinNumber);
+
+ return ( (ui32CfgVal << CFGVAL_GPIOCFG_S) |
+ (ui32PadregVal << CFGVAL_PADREG_S) |
+ (ui32AltPadVal << CFGVAL_ALTPAD_S) );
+}
+
+//*****************************************************************************
+//
+//! @brief Get the state of ALL GPIOs from the INPUT READ REGISTER.
+//!
+//! This function retrieves the state of ALL GPIOs from the INPUT READ
+//! REGISTER.
+//!
+//! @return the state for the requested GPIO or -1 for error.
+//
+//*****************************************************************************
+uint64_t
+am_hal_gpio_input_read(void)
+{
+ //
+ // Combine upper or lower GPIO words into one 64 bit return value.
+ //
+ uint64_t ui64RetVal;
+
+ ui64RetVal = ((uint64_t) AM_REGn(GPIO, 0, RDB)) << 32;
+ ui64RetVal |= ((uint64_t) AM_REGn(GPIO, 0, RDA)) << 0;
+
+ return ui64RetVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Get the state of ALL GPIOs from the DATA OUTPUT REGISTER.
+//!
+//! This function retrieves the state of ALL GPIOs from the DATA OUTPUT
+//! REGISTER.
+//!
+//! @return the state for the requested GPIO or -1 for error.
+//
+//*****************************************************************************
+uint64_t
+am_hal_gpio_out_read(void)
+{
+ //
+ // Combine upper or lower GPIO words into one 64 bit return value.
+ //
+ uint64_t ui64RetVal;
+
+ ui64RetVal = ((uint64_t) AM_REGn(GPIO, 0, WTB)) << 32;
+ ui64RetVal |= ((uint64_t) AM_REGn(GPIO, 0, WTA)) << 0;
+
+ return ui64RetVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Gets the state of one GPIO from the DATA ENABLE REGISTER.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function gets the state of one GPIO from the DATA ENABLE REGISTER.
+//!
+//! @return the current state for the requested GPIO.
+//
+//*****************************************************************************
+uint32_t
+am_hal_gpio_out_enable_bit_get(uint32_t ui32BitNum)
+{
+ //
+ // Return 0 or 1.
+ //
+
+ return (AM_HAL_GPIO_EN(ui32BitNum) & AM_HAL_GPIO_EN_M(ui32BitNum)) ? 1 : 0;
+}
+
+//*****************************************************************************
+//
+//! @brief Gets the state of ALL GPIOs from the DATA ENABLE REGISTER.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function gets the state of all GPIOs from the DATA ENABLE REGISTER.
+//!
+//! @return the current state for the ALL GPIOs.
+//
+//*****************************************************************************
+uint64_t
+am_hal_gpio_out_enable_get(void)
+{
+ //
+ // Combine upper or lower GPIO words into one 64 bit return value.
+ //
+ uint64_t ui64RetVal;
+
+ ui64RetVal = ((uint64_t) AM_REGn(GPIO, 0, ENB)) << 32;
+ ui64RetVal |= ((uint64_t) AM_REGn(GPIO, 0, ENA)) << 0;
+
+ return ui64RetVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable selected GPIO Interrupts.
+//!
+//! @param ui64InterruptMask - GPIOs to enable interrupts on.
+//!
+//! Use this function to enable the GPIO interrupts.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_gpio_int_enable(uint64_t ui64InterruptMask)
+{
+ //
+ // Enable the interrupts.
+ //
+ AM_REG(GPIO, INT1EN) |= (ui64InterruptMask >> 32);
+ AM_REG(GPIO, INT0EN) |= (ui64InterruptMask & 0xFFFFFFFF);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable selected GPIO Interrupts.
+//!
+//! Use this function to enable the GPIO interrupts.
+//!
+//! @return logical or of all enabled interrupts. Use AM_HAL_GPIO_BITx to mask
+//! interrupts of interest.
+//
+//*****************************************************************************
+uint64_t
+am_hal_gpio_int_enable_get(void)
+{
+ //
+ // Return enabled interrupts.
+ //
+ uint64_t ui64RetVal;
+
+ ui64RetVal = ((uint64_t) AM_REGn(GPIO, 0, INT1EN)) << 32;
+ ui64RetVal |= ((uint64_t) AM_REGn(GPIO, 0, INT0EN)) << 0;
+
+ return ui64RetVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable selected GPIO Interrupts.
+//!
+//! @param ui64InterruptMask - GPIOs to disable interrupts on.
+//!
+//! Use this function to disable the GPIO interrupts.
+//!
+//! ui64InterruptMask should be a logical or of AM_HAL_GPIO_BITx defines.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_gpio_int_disable(uint64_t ui64InterruptMask)
+{
+ //
+ // Disable the interrupts.
+ //
+ AM_CRITICAL_BEGIN_ASM
+ AM_REG(GPIO, INT1EN) &= ~(ui64InterruptMask >> 32);
+ AM_REG(GPIO, INT0EN) &= ~(ui64InterruptMask & 0xFFFFFFFF);
+ AM_CRITICAL_END_ASM
+}
+
+//*****************************************************************************
+//
+//! @brief Clear selected GPIO Interrupts.
+//!
+//! @param ui64InterruptMask - GPIOs to clear interrupts on.
+//!
+//! Use this function to clear the GPIO interrupts.
+//!
+//! ui64InterruptMask should be a logical or of AM_HAL_GPIO_BITx defines.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_gpio_int_clear(uint64_t ui64InterruptMask)
+{
+ //
+ // Clear the interrupts.
+ //
+ AM_CRITICAL_BEGIN_ASM
+ AM_REG(GPIO, INT1CLR) = (ui64InterruptMask >> 32);
+ AM_REG(GPIO, INT0CLR) = (ui64InterruptMask & 0xFFFFFFFF);
+ AM_CRITICAL_END_ASM
+}
+
+//*****************************************************************************
+//
+//! @brief Set selected GPIO Interrupts.
+//!
+//! @param ui64InterruptMask - GPIOs to set interrupts on.
+//!
+//! Use this function to set the GPIO interrupts.
+//!
+//! ui64InterruptMask should be a logical or of AM_HAL_GPIO_BITx defines.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_gpio_int_set(uint64_t ui64InterruptMask)
+{
+ //
+ // Set the interrupts.
+ //
+ AM_REG(GPIO, INT1SET) = (ui64InterruptMask >> 32);
+ AM_REG(GPIO, INT0SET) = (ui64InterruptMask & 0xFFFFFFFF);
+}
+
+//*****************************************************************************
+//
+//! @brief Set selected GPIO Interrupts.
+//!
+//! @param bEnabledOnly - return the status of only the enabled interrupts.
+//!
+//! Use this function to set the GPIO interrupts.
+//!
+//! @return None
+//
+//*****************************************************************************
+uint64_t
+am_hal_gpio_int_status_get(bool bEnabledOnly)
+{
+ uint64_t ui64RetVal, ui64Mask;
+
+ //
+ // Combine upper or lower GPIO words into one 64 bit return value.
+ //
+ ui64Mask = 0xFFFFFFFFFFFFFFFF;
+
+ AM_CRITICAL_BEGIN_ASM
+ ui64RetVal = ((uint64_t) AM_REGn(GPIO, 0, INT1STAT)) << 32;
+ ui64RetVal |= ((uint64_t) AM_REGn(GPIO, 0, INT0STAT)) << 0;
+
+ if ( bEnabledOnly )
+ {
+ ui64Mask = ((uint64_t) AM_REGn(GPIO, 0, INT1EN)) << 32;
+ ui64Mask |= ((uint64_t) AM_REGn(GPIO, 0, INT0EN)) << 0;
+ }
+
+ ui64RetVal &= ui64Mask;
+ AM_CRITICAL_END_ASM
+
+ return ui64RetVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Convenience function for responding to pin interrupts.
+//!
+//! @param ui64Status is the interrupt status as returned by
+//! am_hal_gpio_int_status_get()
+//!
+//! This function may be called from am_hal_gpio_isr() to read the status of
+//! the GPIO interrupts, determine which pin(s) caused the most recent
+//! interrupt, and call an interrupt handler function to respond. The interrupt
+//! handler to be called must be first registered with the
+//! am_hal_gpio_int_register() function.
+//!
+//! In the event that multiple GPIO interrupts are active, the corresponding
+//! interrupt handlers will be called in numerical order by GPIO number
+//! starting with the lowest GPIO number.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_gpio_int_service(uint64_t ui64Status)
+{
+ uint32_t ui32Status;
+ uint32_t ui32Clz;
+
+ am_hal_gpio_handler_t pfnHandler;
+
+ //
+ // Handle any active interrupts in the lower 32 bits
+ //
+ ui32Status = (uint32_t) ui64Status;
+ while ( ui32Status )
+ {
+ //
+ // Pick one of any remaining active interrupt bits
+ //
+#ifdef __IAR_SYSTEMS_ICC__
+ ui32Clz = __CLZ(ui32Status);
+#else
+ ui32Clz = __builtin_clz(ui32Status);
+#endif
+
+ //
+ // Turn off the bit we picked in the working copy
+ //
+ ui32Status &= ~(0x80000000 >> ui32Clz);
+
+ //
+ // Check the bit handler table to see if there is an interrupt handler
+ // registered for this particular bit.
+ //
+ pfnHandler = am_hal_gpio_ppfnHandlers[31 - ui32Clz];
+ if ( pfnHandler )
+ {
+ //
+ // If we found an interrupt handler routine, call it now.
+ //
+ pfnHandler();
+ }
+ }
+
+ //
+ // Handle any active interrupts in the upper 32 bits
+ //
+ ui32Status = (uint32_t) (ui64Status >> 32);
+ while ( ui32Status )
+ {
+ //
+ // Pick one of any remaining active interrupt bits
+ //
+#ifdef __IAR_SYSTEMS_ICC__
+ ui32Clz = __CLZ(ui32Status);
+#else
+ ui32Clz = __builtin_clz(ui32Status);
+#endif
+
+ //
+ // Turn off the bit we picked in the working copy
+ //
+ ui32Status &= ~(0x80000000 >> ui32Clz);
+
+ //
+ // Check the bit handler table to see if there is an interrupt handler
+ // registered for this particular bit.
+ //
+ pfnHandler = am_hal_gpio_ppfnHandlers[63 - ui32Clz];
+ if ( pfnHandler )
+ {
+ //
+ // If we found an interrupt handler routine, call it now.
+ //
+ pfnHandler();
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Register an interrupt handler for an individual GPIO pin.
+//!
+//! @param ui32GPIONumber - GPIO number to assign this interrupt handler to.
+//! @param pfnHandler - Function to call when this GPIO interrupt is received.
+//!
+//! This function allows the caller to specify a function that should be called
+//! any time a GPIO interrupt is received on a particular pin. Registering an
+//! interrupt handler using this function adds the function pointer to an array
+//! in SRAM. This interrupt handler will be called by am_hal_gpio_int_service()
+//! whenever the ui64Status parameter indicates that the corresponding pin is
+//! asserting it's interrupt.
+//!
+//! To remove an interrupt handler that has already been registered, the
+//! pfnHandler parameter may be set to zero.
+//!
+//! @note This function will not have any effect unless the
+//! am_hal_gpio_int_service() function is being used.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_gpio_int_register(uint32_t ui32GPIONumber,
+ am_hal_gpio_handler_t pfnHandler)
+{
+ //
+ // Check to make sure the GPIO number is valid. (Debug builds only)
+ //
+ am_hal_debug_assert_msg(ui32GPIONumber < 64, "GPIO number out of range.");
+
+ am_hal_gpio_ppfnHandlers[ui32GPIONumber] = pfnHandler;
+}
+
+//*****************************************************************************
+//
+//! @brief Get the state of one GPIO polarity bit.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function gets the state of one GPIO polarity bit.
+//!
+//! @note When the bit is a one the interrupt polarity is rising edge.
+//!
+//! @return the current polarity.
+//
+//*****************************************************************************
+bool
+am_hal_gpio_int_polarity_bit_get(uint32_t ui32BitNum)
+{
+ //
+ // Check the GPIO_CFGx register's interrupt polarity bit corresponding to
+ // this pin number.
+ //
+ return (AM_REGVAL(AM_HAL_GPIO_CFG(ui32BitNum)) &
+ AM_HAL_GPIO_POL_M(ui32BitNum));
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_gpio.h b/bsp/apollo2/libraries/drivers/hal/am_hal_gpio.h
new file mode 100644
index 0000000000..60e5cf36d6
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_gpio.h
@@ -0,0 +1,684 @@
+//*****************************************************************************
+//
+// am_hal_gpio.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the GPIO module.
+//!
+//! @addtogroup gpio2 GPIO
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#ifndef AM_HAL_GPIO_H
+#define AM_HAL_GPIO_H
+
+// DEVICE ADDRESS IS 8-bits
+#define AM_HAL_GPIO_DEV_ADDR_8 (0)
+
+// DEVICE ADDRESS IS 16-bits
+#define AM_HAL_GPIO_DEV_ADDR_16 (1)
+
+// DEVICE OFFSET IS 8-bits
+#define AM_HAL_GPIO_DEV_OFFSET_8 (0x00000000)
+
+// DEVICE OFFSET IS 16-bits
+#define AM_HAL_GPIO_DEV_OFFSET_16 (0x00010000)
+
+// Maximum number of GPIOs on this device
+#define AM_HAL_GPIO_MAX_PADS (50)
+
+//*****************************************************************************
+//
+//! @name GPIO Pin defines
+//! @brief GPIO Pin defines for use with interrupt functions
+//!
+//! These macros may be used to with \e am_hal_gpio_int_x().
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_BIT(n) (((uint64_t) 0x1) << n)
+//! @}
+
+//
+// Helper macros used for unraveling the GPIO configuration value (configval).
+//
+// Note that the configval, which is passed into functions such as
+// am_hal_gpio_pin_config() as well as various helper macros, is a concatenated
+// value that contains values used in multiple configuration registers.
+//
+// The GPIO configuration value fields are arranged as follows:
+// [ 7: 0] PADREG configuration.
+// [11: 8] GPIOCFG
+// [15:12] Unused.
+// [23:16] ALTPADREG configuration.
+//
+// Define macros describing these configval fields.
+//
+#define CFGVAL_PADREG_S 0
+#define CFGVAL_PADREG_M (0xFF << CFGVAL_PADREG_S)
+#define CFGVAL_GPIOCFG_S 8
+#define CFGVAL_GPIOCFG_M (0x0F << CFGVAL_GPIOCFG_S)
+#define CFGVAL_ALTPAD_S 16
+#define CFGVAL_ALTPAD_M (0xFF << CFGVAL_ALTPAD_S)
+
+//
+// Extraction macros
+//
+#define CFGVAL_PADREG_X(x) (((uint32_t)(x) & CFGVAL_PADREG_M) >> \
+ CFGVAL_PADREG_S)
+#define CFGVAL_GPIOCFG_X(x) (((uint32_t)(x) & CFGVAL_GPIOCFG_M) >> \
+ CFGVAL_GPIOCFG_S)
+#define CFGVAL_ALTPAD_X(x) (((uint32_t)(x) & CFGVAL_ALTPAD_M) >> \
+ CFGVAL_ALTPAD_S)
+
+//*****************************************************************************
+//
+// Input options.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_INPEN (0x02 << CFGVAL_PADREG_S) // Enable input transistors.
+#define AM_HAL_GPIO_INCFG_RDZERO (0x01 << CFGVAL_GPIOCFG_S) // Disable input read registers.
+
+//*****************************************************************************
+//
+// Output options
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_OUT_DISABLE ((0x0 << 1) << CFGVAL_GPIOCFG_S)
+#define AM_HAL_GPIO_OUT_PUSHPULL ((0x1 << 1) << CFGVAL_GPIOCFG_S)
+#define AM_HAL_GPIO_OUT_OPENDRAIN ((0x2 << 1) << CFGVAL_GPIOCFG_S)
+#define AM_HAL_GPIO_OUT_3STATE ((0x3 << 1) << CFGVAL_GPIOCFG_S)
+
+//*****************************************************************************
+//
+// Pad configuration options.
+// (Configuration value bits 7:0.)
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_HIGH_DRIVE (0x04 << CFGVAL_PADREG_S)
+#define AM_HAL_GPIO_LOW_DRIVE (0x00 << CFGVAL_PADREG_S)
+#define AM_HAL_GPIO_PULLUP (0x01 << CFGVAL_PADREG_S)
+#define AM_HAL_GPIO_PULL1_5K ( (0x01 << CFGVAL_PADREG_S) | \
+ AM_HAL_GPIO_PULLUP )
+#define AM_HAL_GPIO_PULL6K ( (0x40 << CFGVAL_PADREG_S) | \
+ AM_HAL_GPIO_PULLUP )
+#define AM_HAL_GPIO_PULL12K ( (0x80 << CFGVAL_PADREG_S) | \
+ AM_HAL_GPIO_PULLUP )
+#define AM_HAL_GPIO_PULL24K ( (0xC0 << CFGVAL_PADREG_S) | \
+ AM_HAL_GPIO_PULLUP )
+
+// POWER SWITCH is available on selected pins
+#define AM_HAL_GPIO_POWER (0x80 << CFGVAL_PADREG_S)
+
+//*****************************************************************************
+//
+//! ALTPADREG configuration options.
+//! (Configuration value bits 23:16.)
+//!
+//! All Apollo2 GPIO pins can be configured for 2mA or 4mA.
+//! AM_HAL_GPIO_DRIVE_2MA = 2mA configuration.
+//! AM_HAL_GPIO_DRIVE_4MA = 4mA configuration.
+//!
+//! Certain Apollo2 GPIO pins can be configured to drive up to 12mA.
+//! AM_HAL_GPIO_DRIVE_8MA = 8mA configuration.
+//! AM_HAL_GPIO_DRIVE_12MA = 12mA configuration.
+//!
+//! Notes:
+//! - Always consult the Apollo2 data sheet for the latest details.
+//! - The higher drive GPIOxx pads generally include:
+//! 0-2,5,7-8,10,12-13,22-23,26-29,38-39,42,44-48.
+//! - GPIOxx pads that do not support the higher drive:
+//! 3-4,6,9,11,14-21,24-25,30-37,40-41,43,49.
+//! - User is responsible for ensuring that the selected pin actually supports
+//! the higher drive (8mA or 12mA) capabilities. See the Apollo2 data sheet.
+//! - Attempting to set the higher drive (8mA or 12mA) configuration on a
+//! non-supporting pad will actually set the pad for 4mA drive strength,
+//! regardless of the lower bit setting.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_DRIVE_2MA ( 0 )
+#define AM_HAL_GPIO_DRIVE_4MA AM_HAL_GPIO_HIGH_DRIVE
+#define AM_HAL_GPIO_DRIVE_8MA ( 0x01 << CFGVAL_ALTPAD_S )
+#define AM_HAL_GPIO_DRIVE_12MA ( (0x01 << CFGVAL_ALTPAD_S) | \
+ AM_HAL_GPIO_HIGH_DRIVE )
+
+#define AM_HAL_GPIO_SLEWRATE ( 0x10 << CFGVAL_ALTPAD_S )
+
+//*****************************************************************************
+//
+// Interrupt polarity
+// These values can be used directly in the configval.
+//
+//*****************************************************************************
+#define AM_HAL_GPIOCFGVAL_FALLING ((1 << 2) << CFGVAL_GPIOCFG_S)
+#define AM_HAL_GPIOCFGVAL_RISING ((0 << 2) << CFGVAL_GPIOCFG_S)
+
+//*****************************************************************************
+//
+// Pad function select
+// This macro represents the 3 bit function select field in the PADREG byte.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_FUNC(x) ((x & 0x7) << 3)
+
+//*****************************************************************************
+//
+//! Interrupt polarity
+//!
+//! Important:
+//! These values are to be used with am_hal_gpio_int_polarity_bit_set().
+// They are not intended to be used as part of the GPIO configval.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_FALLING 0x00000001
+#define AM_HAL_GPIO_RISING 0x00000000
+
+//*****************************************************************************
+//
+// A few common pin configurations.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_DISABLE \
+ (AM_HAL_GPIO_FUNC(3))
+
+#define AM_HAL_GPIO_INPUT \
+ (AM_HAL_GPIO_FUNC(3) | AM_HAL_GPIO_INPEN)
+
+#define AM_HAL_GPIO_OUTPUT \
+ (AM_HAL_GPIO_FUNC(3) | AM_HAL_GPIO_OUT_PUSHPULL)
+
+#define AM_HAL_GPIO_OPENDRAIN \
+ (AM_HAL_GPIO_FUNC(3) | AM_HAL_GPIO_OUT_OPENDRAIN | AM_HAL_GPIO_INPEN)
+
+#define AM_HAL_GPIO_3STATE \
+ (AM_HAL_GPIO_FUNC(3) | AM_HAL_GPIO_OUT_3STATE)
+
+//*****************************************************************************
+//
+// PADREG helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_PADREG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_PADREGA_O + (n & 0xFC))
+
+#define AM_HAL_GPIO_PADREG_S(n) \
+ (((uint32_t)(n) % 4) << 3)
+
+#define AM_HAL_GPIO_PADREG_M(n) \
+ ((uint32_t) 0xFF << AM_HAL_GPIO_PADREG_S(n))
+
+#define AM_HAL_GPIO_PADREG_FIELD(n, configval) \
+ (((uint32_t)(configval) & CFGVAL_PADREG_M) << AM_HAL_GPIO_PADREG_S(n))
+
+#define AM_HAL_GPIO_PADREG_W(n, configval) \
+ AM_REGVAL(AM_HAL_GPIO_PADREG(n)) = \
+ (AM_HAL_GPIO_PADREG_FIELD(n, configval) | \
+ (AM_REGVAL(AM_HAL_GPIO_PADREG(n)) & ~AM_HAL_GPIO_PADREG_M(n)))
+
+#define AM_HAL_GPIO_PADREG_R(n) \
+ ((AM_REGVAL(AM_HAL_GPIO_PADREG(n)) & AM_HAL_GPIO_PADREG_M(n)) >> \
+ AM_HAL_GPIO_PADREG_S(n))
+
+
+//*****************************************************************************
+//
+// ALTPADCFG helper macros.
+// The ALTPADCFG bits are located in [23:16] of the configval.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_ALTPADREG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_ALTPADCFGA_O + (n & 0xFC))
+
+#define AM_HAL_GPIO_ALTPADREG_S(n) \
+ (((uint32_t)(n) % 4) << 3)
+
+#define AM_HAL_GPIO_ALTPADREG_M(n) \
+ ((uint32_t) 0xFF << AM_HAL_GPIO_ALTPADREG_S(n))
+
+#define AM_HAL_GPIO_ALTPADREG_FIELD(n, configval) \
+ (CFGVAL_ALTPAD_X(configval) << AM_HAL_GPIO_ALTPADREG_S(n))
+
+#define AM_HAL_GPIO_ALTPADREG_W(n, configval) \
+ AM_REGVAL(AM_HAL_GPIO_ALTPADREG(n)) = \
+ (AM_HAL_GPIO_ALTPADREG_FIELD(n, configval) | \
+ (AM_REGVAL(AM_HAL_GPIO_ALTPADREG(n)) & ~AM_HAL_GPIO_ALTPADREG_M(n)))
+
+#define AM_HAL_GPIO_ALTPADREG_R(n) \
+ ((AM_REGVAL(AM_HAL_GPIO_ALTPADREG(n)) & AM_HAL_GPIO_ALTPADREG_M(n)) >> \
+ AM_HAL_GPIO_ALTPADREG_S(n))
+
+//*****************************************************************************
+//
+// CFG helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_CFG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_CFGA_O + ((n & 0xF8) >> 1))
+
+#define AM_HAL_GPIO_CFG_S(n) \
+ (((uint32_t)(n) % 8) << 2)
+
+#define AM_HAL_GPIO_CFG_M(n) \
+ ((uint32_t) 0x7 << AM_HAL_GPIO_CFG_S(n))
+
+#define AM_HAL_GPIO_CFG_FIELD(n, configval) \
+ ((((uint32_t)(configval) & 0x700) >> 8) << AM_HAL_GPIO_CFG_S(n))
+
+#define AM_HAL_GPIO_CFG_W(n, configval) \
+ AM_REGVAL(AM_HAL_GPIO_CFG(n)) = \
+ (AM_HAL_GPIO_CFG_FIELD(n, configval) | \
+ (AM_REGVAL(AM_HAL_GPIO_CFG(n)) & ~AM_HAL_GPIO_CFG_M(n)))
+
+#define AM_HAL_GPIO_CFG_R(n) \
+ ((AM_REGVAL(AM_HAL_GPIO_CFG(n)) & AM_HAL_GPIO_CFG_M(n)) >> \
+ AM_HAL_GPIO_CFG_S(n))
+
+//*****************************************************************************
+//
+// Polarity helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_POL_S(n) \
+ ((((uint32_t)(n) % 8) << 2) + 3)
+
+#define AM_HAL_GPIO_POL_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_POL_S(n))
+
+#define AM_HAL_GPIO_POL_FIELD(n, polarity) \
+ (((uint32_t)(polarity) & 0x1) << AM_HAL_GPIO_POL_S(n))
+
+#define AM_HAL_GPIO_POL_W(n, polarity) \
+ AM_REGVAL(AM_HAL_GPIO_CFG(n)) = \
+ (AM_HAL_GPIO_POL_FIELD(n, polarity) | \
+ (AM_REGVAL(AM_HAL_GPIO_CFG(n)) & ~AM_HAL_GPIO_POL_M(n)))
+
+//*****************************************************************************
+//
+// RD helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_RD_REG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_RDA_O + (((uint32_t)(n) & 0x20) >> 3))
+
+#define AM_HAL_GPIO_RD_S(n) \
+ ((uint32_t)(n) % 32)
+
+#define AM_HAL_GPIO_RD_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_RD_S(n))
+
+#define AM_HAL_GPIO_RD(n) \
+ AM_REGVAL(AM_HAL_GPIO_RD_REG(n))
+
+//*****************************************************************************
+//
+// WT helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_WT_REG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_WTA_O + (((uint32_t)(n) & 0x20) >> 3))
+
+#define AM_HAL_GPIO_WT_S(n) \
+ ((uint32_t)(n) % 32)
+
+#define AM_HAL_GPIO_WT_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_WT_S(n))
+
+#define AM_HAL_GPIO_WT(n) \
+ AM_REGVAL(AM_HAL_GPIO_WT_REG(n))
+
+//*****************************************************************************
+//
+// WTS helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_WTS_REG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_WTSA_O + (((uint32_t)(n) & 0x20) >> 3))
+
+#define AM_HAL_GPIO_WTS_S(n) \
+ ((uint32_t)(n) % 32)
+
+#define AM_HAL_GPIO_WTS_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_WTS_S(n))
+
+#define AM_HAL_GPIO_WTS(n) \
+ AM_REGVAL(AM_HAL_GPIO_WTS_REG(n))
+
+//*****************************************************************************
+//
+// WTC helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_WTC_REG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_WTCA_O + (((uint32_t)(n) & 0x20) >> 3))
+
+#define AM_HAL_GPIO_WTC_S(n) \
+ ((uint32_t)(n) % 32)
+
+#define AM_HAL_GPIO_WTC_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_WTC_S(n))
+
+#define AM_HAL_GPIO_WTC(n) \
+ AM_REGVAL(AM_HAL_GPIO_WTC_REG(n))
+
+//*****************************************************************************
+//
+// EN helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_EN_REG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_ENA_O + (((uint32_t)(n) & 0x20) >> 3))
+
+#define AM_HAL_GPIO_EN_S(n) \
+ ((uint32_t)(n) % 32)
+
+#define AM_HAL_GPIO_EN_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_EN_S(n))
+
+#define AM_HAL_GPIO_EN(n) \
+ AM_REGVAL(AM_HAL_GPIO_EN_REG(n))
+
+//*****************************************************************************
+//
+// ENS helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_ENS_REG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_ENSA_O + (((uint32_t)(n) & 0x20) >> 3))
+
+#define AM_HAL_GPIO_ENS_S(n) \
+ ((uint32_t)(n) % 32)
+
+#define AM_HAL_GPIO_ENS_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_ENS_S(n))
+
+#define AM_HAL_GPIO_ENS(n) \
+ AM_REGVAL(AM_HAL_GPIO_ENS_REG(n))
+
+//*****************************************************************************
+//
+// ENC helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_GPIO_ENC_REG(n) \
+ (AM_REG_GPIOn(0) + AM_REG_GPIO_ENCA_O + (((uint32_t)(n) & 0x20) >> 3))
+
+#define AM_HAL_GPIO_ENC_S(n) \
+ ((uint32_t)(n) % 32)
+
+#define AM_HAL_GPIO_ENC_M(n) \
+ ((uint32_t) 0x1 << AM_HAL_GPIO_ENC_S(n))
+
+#define AM_HAL_GPIO_ENC(n) \
+ AM_REGVAL(AM_HAL_GPIO_ENC_REG(n))
+
+//*****************************************************************************
+//
+//! @brief Configure the GPIO PAD MUX & GPIO PIN Configurations
+//!
+//! @param ui32PinNumber - GPIO pin number.
+//! @param ui32Config - Configuration options.
+//!
+//! This function applies the settings for a single GPIO. For a list of valid
+//! options please see the top of this file (am_hal_gpio.h) and am_hal_pin.h.
+//!
+//! Usage examples:
+//! am_hal_gpio_pin_config(11, AM_HAL_GPIO_INPUT);
+//! am_hal_gpio_pin_config(10, AM_HAL_GPIO_OUTPUT);
+//! am_hal_gpio_pin_config(14, AM_HAL_GPIO_OUTPUT | AM_HAL_GPIO_SLEWRATE);
+//! am_hal_gpio_pin_config(15, AM_HAL_GPIO_OUTPUT | AM_HAL_GPIO_HIGHDRIVESTR);
+//
+//*****************************************************************************
+#define am_hal_gpio_pin_config(ui32PinNumber, ui32Config) \
+ if ( (uint32_t)(ui32PinNumber) < AM_HAL_GPIO_MAX_PADS ) \
+ { \
+ AM_CRITICAL_BEGIN_ASM \
+ \
+ AM_REGn(GPIO, 0, PADKEY) = AM_REG_GPIO_PADKEY_KEYVAL; \
+ \
+ AM_HAL_GPIO_CFG_W(ui32PinNumber, ui32Config); \
+ AM_HAL_GPIO_PADREG_W(ui32PinNumber, ui32Config); \
+ AM_HAL_GPIO_ALTPADREG_W(ui32PinNumber, ui32Config); \
+ \
+ AM_REGn(GPIO, 0, PADKEY) = 0; \
+ \
+ AM_CRITICAL_END_ASM \
+ }
+
+//*****************************************************************************
+//
+//! @brief Set the state of one GPIO polarity bit.
+//!
+//! @param ui32BitNum - GPIO number.
+//! @param ui32Polarity - Desired state.
+//!
+//! This function sets the state of one GPIO polarity bit to a supplied value.
+//! The ui32Polarity parameter should be one of the following values:
+//!
+//! AM_HAL_GPIO_FALLING
+//! AM_HAL_GPIO_RISING
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_gpio_int_polarity_bit_set(ui32PinNumber, ui32Polarity) \
+ if ( (uint32_t)(ui32PinNumber) < AM_HAL_GPIO_MAX_PADS ) \
+ { \
+ AM_CRITICAL_BEGIN_ASM \
+ \
+ AM_REGn(GPIO, 0, PADKEY) = AM_REG_GPIO_PADKEY_KEYVAL; \
+ AM_HAL_GPIO_POL_W(ui32PinNumber, ui32Polarity); \
+ AM_REGn(GPIO, 0, PADKEY) = 0; \
+ \
+ AM_CRITICAL_END_ASM \
+ }
+
+//*****************************************************************************
+//
+//! @brief Get the state of one GPIO from the INPUT READ REGISTER.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function retrieves the state of one GPIO from the INPUT READ
+//! REGISTER.
+//!
+//! @return the state for the requested GPIO.
+//
+//*****************************************************************************
+#define am_hal_gpio_input_bit_read(ui32BitNum) \
+ ((AM_HAL_GPIO_RD(ui32BitNum) & AM_HAL_GPIO_RD_M(ui32BitNum)) != 0)
+
+//*****************************************************************************
+//
+//! @brief Get the state of one GPIO in the DATA OUTPUT REGISTER
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function retrieves the state of one GPIO in the DATA OUTPUT REGISTER.
+//!
+//! @return the state for the requested GPIO or -1 for error.
+//
+//*****************************************************************************
+#define am_hal_gpio_out_bit_read(ui32BitNum) \
+ ((AM_HAL_GPIO_WT(ui32BitNum) & AM_HAL_GPIO_WT_M(ui32BitNum)) != 0)
+
+//*****************************************************************************
+//
+//! @brief Set the output state high for one GPIO.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function sets the output state to high for one GPIO.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_gpio_out_bit_set(ui32BitNum) \
+ AM_HAL_GPIO_WTS(ui32BitNum) = AM_HAL_GPIO_WTS_M(ui32BitNum)
+
+//*****************************************************************************
+//
+//! @brief Sets the output state to low for one GPIO.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function sets the output state to low for one GPIO.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_gpio_out_bit_clear(ui32BitNum) \
+ AM_HAL_GPIO_WTC(ui32BitNum) = AM_HAL_GPIO_WTC_M(ui32BitNum)
+
+//*****************************************************************************
+//
+//! @brief Sets the output state to ui32Value for one GPIO.
+//!
+//! @param ui32BitNum - GPIO number.
+//! @param ui32Value - Desired output state.
+//!
+//! This function sets the output state to ui32Value for one GPIO.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_gpio_out_bit_replace(ui32BitNum, ui32Value) \
+ if ( ui32Value ) \
+ { \
+ AM_HAL_GPIO_WTS(ui32BitNum) = AM_HAL_GPIO_WTS_M(ui32BitNum); \
+ } \
+ else \
+ { \
+ AM_HAL_GPIO_WTC(ui32BitNum) = AM_HAL_GPIO_WTC_M(ui32BitNum); \
+ }
+
+//*****************************************************************************
+//
+//! @brief Toggle the output state of one GPIO.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function toggles the output state of one GPIO.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_gpio_out_bit_toggle(ui32BitNum) \
+ if ( 1 ) \
+ { \
+ AM_CRITICAL_BEGIN_ASM \
+ AM_HAL_GPIO_WT(ui32BitNum) ^= AM_HAL_GPIO_WT_M(ui32BitNum); \
+ AM_CRITICAL_END_ASM \
+ }
+
+//*****************************************************************************
+//
+//! @brief Sets the output enable for one GPIO.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function sets the output enable for one GPIO.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_gpio_out_enable_bit_set(ui32BitNum) \
+ AM_HAL_GPIO_ENS(ui32BitNum) = AM_HAL_GPIO_ENS_M(ui32BitNum)
+
+//*****************************************************************************
+//
+//! @brief Clears the output enable for one GPIO.
+//!
+//! @param ui32BitNum - GPIO number.
+//!
+//! This function clears the output enable for one GPIO.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_gpio_out_enable_bit_clear(ui32BitNum) \
+ AM_HAL_GPIO_ENC(ui32BitNum) = AM_HAL_GPIO_ENC_M(ui32BitNum)
+
+//*****************************************************************************
+//
+// Function pointer type for GPIO interrupt handlers.
+//
+//*****************************************************************************
+typedef void (*am_hal_gpio_handler_t)(void);
+
+//*****************************************************************************
+//
+// External function prototypes
+//
+//*****************************************************************************
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern uint32_t am_hal_gpio_pin_config_read(uint32_t ui32PinNumber);
+extern uint64_t am_hal_gpio_input_read(void);
+extern uint64_t am_hal_gpio_out_read(void);
+extern uint32_t am_hal_gpio_out_enable_bit_get(uint32_t ui32BitNum);
+extern uint64_t am_hal_gpio_out_enable_get(void);
+extern void am_hal_gpio_int_enable(uint64_t ui64InterruptMask);
+extern uint64_t am_hal_gpio_int_enable_get(void);
+extern void am_hal_gpio_int_disable(uint64_t ui64InterruptMask);
+extern void am_hal_gpio_int_clear(uint64_t ui64InterruptMask);
+extern void am_hal_gpio_int_set(uint64_t ui64InterruptMask);
+extern uint64_t am_hal_gpio_int_status_get(bool bEnabledOnly);
+extern void am_hal_gpio_int_service(uint64_t ui64Status);
+extern void am_hal_gpio_int_register(uint32_t ui32GPIONumber,
+ am_hal_gpio_handler_t pfnHandler);
+
+extern bool am_hal_gpio_int_polarity_bit_get(uint32_t ui32BitNum);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_GPIO_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.c b/bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.c
new file mode 100644
index 0000000000..603dd8c4ec
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.c
@@ -0,0 +1,757 @@
+//*****************************************************************************
+//
+// am_hal_i2c_bit_bang.c
+//! @file
+//!
+//! @brief I2C bit bang module.
+//!
+//! These functions implement the I2C bit bang utility
+//! It implements an I2C interface at close to 400 kHz
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "am_mcu_apollo.h"
+#include "am_util.h"
+#include "am_hal_i2c_bit_bang.h"
+
+// Max number of clock cycles to wait for clock stretch
+#define I2C_BB_MAX_CLOCK_STRETCH_WAIT 100
+
+#define I2C_BB_DESIRED_FREQ_HZ 400000
+
+#define I2C_BB_CYCLES_PER_DELAY_COUNT 3
+#define I2C_BB_ONE_BIT_TIME_IN_CYCLES (AM_HAL_CLKGEN_FREQ_MAX_HZ/I2C_BB_DESIRED_FREQ_HZ)
+#define I2C_BB_ONE_BIT_TIME_IN_DELAY_COUNT (I2C_BB_ONE_BIT_TIME_IN_CYCLES/I2C_BB_CYCLES_PER_DELAY_COUNT)
+
+// Number of loops (each worth 3 cycles) needed to delay for defined time
+// This is imprecise, as there is a setup time as well which is not accounted
+// for
+// One Bit time = 120 Cycles (400 kHz @ 48 MHz)
+#define HALF_BIT_TIME (I2C_BB_ONE_BIT_TIME_IN_DELAY_COUNT/2)
+#define QUARTER_BIT_TIME (I2C_BB_ONE_BIT_TIME_IN_DELAY_COUNT/4)
+#define ASM_DELAY am_hal_flash_delay
+
+// Empirically determined adjustments to account for the fact that there is a
+// variable time spent in actual processing as well, and hence we need not delay
+// for the full time. This processing time is variable based on exact processing
+// needed at various times, and will also vary based on compiler type and
+// optimization levels
+#define I2C_BB_TIMER_ADJUST 6 // Can not be more than QUARTER_BIT_TIME - 1
+#define I2C_BB_TIMER_HI_ADJUST 15 // Can not be more than HALF_BIT_TIME - 1
+#define I2C_BB_TIMER_LO_ADJUST 13 // Can not be more than HALF_BIT_TIME - 1
+
+// Wait till it is time to end the SCL Hi Period
+#define WAIT_I2C_CLOCK_HI_PERIOD() ASM_DELAY(HALF_BIT_TIME - I2C_BB_TIMER_HI_ADJUST)
+// Wait till it is time to end the SCL Lo Period
+#define WAIT_I2C_CLOCK_LOW_PERIOD() ASM_DELAY(HALF_BIT_TIME - I2C_BB_TIMER_LO_ADJUST)
+// Delay for Quarter Clock
+#define WAIT_FOR_QUARTER_I2C_CLOCK() ASM_DELAY(QUARTER_BIT_TIME - I2C_BB_TIMER_ADJUST)
+#define WRITE_SCL_LO() \
+ do { \
+ AM_REGVAL(am_hal_i2c_bit_bang_priv.sck_reg_clr_addr) = (am_hal_i2c_bit_bang_priv.sck_reg_val); \
+ } while(0)
+
+#define PULL_SCL_HI() \
+ do { \
+ AM_REGVAL(am_hal_i2c_bit_bang_priv.sck_reg_set_addr) = (am_hal_i2c_bit_bang_priv.sck_reg_val); \
+ } while(0)
+
+#define GET_SCL() (AM_REGVAL(am_hal_i2c_bit_bang_priv.sck_reg_read_addr) & (am_hal_i2c_bit_bang_priv.sck_reg_val))
+#define GET_SDA() (AM_REGVAL(am_hal_i2c_bit_bang_priv.sda_reg_read_addr) & (am_hal_i2c_bit_bang_priv.sda_reg_val))
+
+#define WRITE_SDA_LO() \
+ do { \
+ AM_REGVAL(am_hal_i2c_bit_bang_priv.sda_reg_clr_addr) = (am_hal_i2c_bit_bang_priv.sda_reg_val); \
+ } while(0)
+
+#define PULL_SDA_HI() \
+ do { \
+ AM_REGVAL(am_hal_i2c_bit_bang_priv.sda_reg_set_addr) = (am_hal_i2c_bit_bang_priv.sda_reg_val); \
+ } while(0)
+
+
+//*****************************************************************************
+//
+// I2C Bit Bang Private Data Structure
+//
+//*****************************************************************************
+typedef struct am_util_bit_bang_priv
+{
+ bool start_flag;
+ uint32_t sck_gpio_number;
+ uint32_t sda_gpio_number;
+ uint32_t sck_reg_set_addr;
+ uint32_t sck_reg_clr_addr;
+ uint32_t sck_reg_read_addr;
+ uint32_t sck_reg_val;
+ uint32_t sda_reg_set_addr;
+ uint32_t sda_reg_clr_addr;
+ uint32_t sda_reg_read_addr;
+ uint32_t sda_reg_val;
+} am_hal_i2c_bit_bang_priv_t;
+static am_hal_i2c_bit_bang_priv_t am_hal_i2c_bit_bang_priv;
+
+//
+// Wait for any stretched clock to go high
+// If it times out - return failure
+//
+static inline bool
+i2c_pull_and_wait_scl_hi(void)
+{
+ // Maximum time to wait for clock stretching
+ uint32_t maxLoop = 4*I2C_BB_MAX_CLOCK_STRETCH_WAIT + 1;
+ // Pull SCL High
+ PULL_SCL_HI();
+ // Poll for SCL to check for clock stretching
+ while (!GET_SCL())
+ {
+ if (--maxLoop == 0)
+ {
+ // timeout!
+ return true;
+ }
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+ }
+ return false;
+}
+
+//*****************************************************************************
+//
+//! @brief Initialize i2c bit bang private data structure
+//!
+//! @param sck_gpio_number is the GPIO # for the I2C SCK clock pin
+//! @param sda_gpio_number is the GPIO # for the I2C SDA data pin
+//!
+//! This function initializes the I2C bit bang utility's internal data struct.
+//!
+//! returns None.
+//
+//*****************************************************************************
+am_hal_i2c_bit_bang_enum_t
+am_hal_i2c_bit_bang_init(uint32_t sck_gpio_number,
+ uint32_t sda_gpio_number)
+{
+ int i;
+ //
+ // remember GPIO pin assignments for I2C bus signals
+ //
+ am_hal_i2c_bit_bang_priv.sck_gpio_number = sck_gpio_number;
+ am_hal_i2c_bit_bang_priv.sda_gpio_number = sda_gpio_number;
+
+ am_hal_i2c_bit_bang_priv.sck_reg_set_addr = AM_HAL_GPIO_WTS_REG(sck_gpio_number);
+ am_hal_i2c_bit_bang_priv.sck_reg_clr_addr = AM_HAL_GPIO_WTC_REG(sck_gpio_number);
+ am_hal_i2c_bit_bang_priv.sck_reg_read_addr = AM_HAL_GPIO_RD_REG(sck_gpio_number);
+ am_hal_i2c_bit_bang_priv.sck_reg_val = AM_HAL_GPIO_WTC_M(sck_gpio_number);
+ am_hal_i2c_bit_bang_priv.sda_reg_set_addr = AM_HAL_GPIO_WTS_REG(sda_gpio_number);
+ am_hal_i2c_bit_bang_priv.sda_reg_clr_addr = AM_HAL_GPIO_WTC_REG(sda_gpio_number);
+ am_hal_i2c_bit_bang_priv.sda_reg_read_addr = AM_HAL_GPIO_RD_REG(sda_gpio_number);
+ am_hal_i2c_bit_bang_priv.sda_reg_val = AM_HAL_GPIO_WTC_M(sda_gpio_number);
+
+ //
+ // Set SCK GPIO data bit high so we aren't pulling down the clock
+ //
+ am_hal_gpio_out_bit_set(sck_gpio_number);
+ //
+ // Set up SCK GPIO configuration bi-direction, input
+ //
+ am_hal_gpio_pin_config(sck_gpio_number, AM_HAL_PIN_OPENDRAIN);
+
+ //
+ // Set SDA GPIO data bit high so we aren't pulling down the data line
+ //
+ am_hal_gpio_out_bit_set(sda_gpio_number);
+ //
+ // Set up SDA GPIO configuration bi-direction, input
+ //
+ am_hal_gpio_pin_config(sda_gpio_number, AM_HAL_PIN_OPENDRAIN);
+
+ // Now make sure we have control of the clock line
+ //
+ // Wait for any stretched clock to go high. Return if still not high
+ //
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ if (!GET_SDA())
+ {
+ // If previous transaction did not finish - SDA may be pulled low for a Read.
+ // If so - need to flush out the data (max 8 bits) & NACK
+ for (i = 0; i < 9; i++)
+ {
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+ //
+ // Delay for 1/2 bit cell time to start the clock and let peer write on SDA
+ //
+ WAIT_I2C_CLOCK_LOW_PERIOD();
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ if (GET_SDA())
+ {
+ // Send START/STOP to clear the bus
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+ WRITE_SDA_LO();
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+ //
+ // Delay for 1/2 bit cell time to start the clock and let peer write on SDA
+ //
+ WAIT_I2C_CLOCK_LOW_PERIOD();
+ //
+ // Release the clock line
+ //
+ PULL_SCL_HI();
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+ PULL_SDA_HI();
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+ break;
+ }
+ }
+ if (i == 9)
+ {
+ // It is it still stuck after 9 clocks - something is wrong. Need to bail out
+ return AM_HAL_I2C_BIT_BANG_DATA_TIMEOUT;
+ }
+ }
+ return AM_HAL_I2C_BIT_BANG_SUCCESS;
+}
+
+//*****************************************************************************
+//
+//! @brief Receive one data byte from an I2C device
+//!
+//! This function handles sending one byte to a slave device
+//! bNack defines if we should send an ACK or NACK
+//!
+//! returns the byte received
+//
+//*****************************************************************************
+static inline am_hal_i2c_bit_bang_enum_t
+i2c_receive_byte(uint8_t *pRxByte, bool bNack)
+{
+ int i;
+ uint8_t data_byte = 0;
+
+ //
+ // Loop through receiving 8 bits
+ //
+ for (i = 0; i < 8; i++)
+ {
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+
+ //
+ // release the data line from from the previous ACK
+ //
+ PULL_SDA_HI();
+
+ //
+ // Delay for 1/2 bit cell time to start the clock and let peer write on SDA
+ //
+ WAIT_I2C_CLOCK_LOW_PERIOD();
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ //
+ // grab the data bit here
+ //
+ if ( GET_SDA() )
+ {
+ //
+ // set the bit in the data byte to be returned
+ //
+ data_byte |= (0x80 >> i);
+ }
+
+ //
+ // Delay for 1/2 bit cell time while clock is high
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+ }
+
+ *pRxByte = data_byte;
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+
+ //
+ // pull the data line down so we can ACK/NAK the byte we just received
+ //
+ if (bNack)
+ {
+ //
+ // Pull up on data line with clock low to indicate NAK
+ //
+ PULL_SDA_HI();
+ }
+ else
+ {
+ //
+ // Pull down on data line with clock low to indicate ACK
+ //
+ WRITE_SDA_LO();
+ }
+ //
+ // Delay for 1/2 bit cell time before sending ACK to device
+ //
+ WAIT_I2C_CLOCK_LOW_PERIOD();
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ //
+ // Delay for 1/2 bit cell time while clock is high to le peer sample the ACK/NAK
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+ //
+ // Give the received data byte back to them
+ //
+ return AM_HAL_I2C_BIT_BANG_SUCCESS;
+}
+
+//*****************************************************************************
+//
+//! @brief Send one data bytes to an I2C device
+//!
+//! @param one_byte the byte to send, could be address could be data
+//!
+//! This function handles sending one byte to a slave device
+//! Starts with 0 clock and runs till full cycle
+//!
+//! returns I2C BB ENUM
+//! {
+//! AM_HAL_I2C_BIT_BANG_SUCCESS,
+//! AM_HAL_I2C_BIT_BANG_ADDRESS_NAKED
+//! }
+//
+//*****************************************************************************
+static inline am_hal_i2c_bit_bang_enum_t
+i2c_send_byte(uint8_t one_byte)
+{
+ int i;
+ bool data_naked = false;
+
+ //
+ // Loop through sending 8 bits
+ //
+ for (i = 0; i < 8; i++)
+ {
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+
+ //
+ // output the next data bit
+ //
+ if ( one_byte & (0x80 >> i) )
+ {
+ PULL_SDA_HI();
+ }
+ else
+ {
+ WRITE_SDA_LO();
+ }
+
+ //
+ // Delay for 1/2 bit cell time to start the clock
+ //
+ WAIT_I2C_CLOCK_LOW_PERIOD();
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ //
+ // Delay for 1/2 bit cell time while clock is high
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+ }
+
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+
+ //
+ // Delay for 1/2 bit cell time to start the clock
+ //
+ WAIT_I2C_CLOCK_LOW_PERIOD();
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ //
+ // Grab the state of the ACK bit and return it
+ //
+ data_naked = GET_SDA();
+ //
+ // Delay for 1/2 bit cell time to complete the high period
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+ if ( data_naked )
+ {
+ return AM_HAL_I2C_BIT_BANG_DATA_NAKED;
+ }
+ else
+ {
+ return AM_HAL_I2C_BIT_BANG_SUCCESS;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Receive a string of data bytes from an I2C device
+//!
+//! @param address (only 8 bit I2C addresses are supported)
+//! LSB is I2C R/W
+//! @param number_of_bytes to transfer (# payload bytes)
+//! @param pData pointer to data buffer to receive payload
+//!
+//! This function handles receiving a payload from a slave device
+//!
+//! returns ENUM{AM_HAL_I2C_BIT_BANG_SUCCESS,AM_HAL_I2C_BIT_BANG_ADDRESS_NAKED}
+//
+//*****************************************************************************
+am_hal_i2c_bit_bang_enum_t
+am_hal_i2c_bit_bang_receive(uint8_t address, uint32_t number_of_bytes,
+ uint8_t *pData, uint8_t ui8Offset,
+ bool bUseOffset, bool bNoStop)
+{
+ uint32_t ui32I;
+ am_hal_i2c_bit_bang_enum_t status = AM_HAL_I2C_BIT_BANG_SUCCESS;
+
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ //
+ // Pull down on data line with clock high --> START CONDITION
+ //
+ WRITE_SDA_LO();
+
+ //
+ // Delay for 1/2 bit cell time to start the clock
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+
+ //
+ // send the address byte and wait for the ACK/NAK
+ //
+ status = i2c_send_byte(address);
+ if ( status != AM_HAL_I2C_BIT_BANG_SUCCESS )
+ {
+ if ( status == AM_HAL_I2C_BIT_BANG_DATA_NAKED)
+ {
+ return AM_HAL_I2C_BIT_BANG_ADDRESS_NAKED;
+ }
+ return status;
+ }
+
+ if ( bUseOffset )
+ {
+ status = i2c_send_byte(ui8Offset);
+ if ( status != AM_HAL_I2C_BIT_BANG_SUCCESS )
+ {
+ return status;
+ }
+ }
+
+ //
+ // receive the requested number of data bytes
+ //
+ for (ui32I = 0; ui32I < number_of_bytes - 1; ui32I++)
+ {
+ //
+ // receive the data bytes and send ACK for each one
+ //
+ status = i2c_receive_byte(pData, false);
+ if (status != AM_HAL_I2C_BIT_BANG_SUCCESS)
+ {
+ return status;
+ }
+ pData++;
+ }
+ // Send NAK for the last byte
+ status = i2c_receive_byte(pData, true);
+ if (status != AM_HAL_I2C_BIT_BANG_SUCCESS)
+ {
+ return status;
+ }
+
+ //********************
+ // Send stop condition
+ //********************
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+
+
+ if (!bNoStop)
+ {
+ //
+ // Pull down on data line with clock low
+ //
+ WRITE_SDA_LO();
+ }
+ else
+ {
+ //
+ // Release data line with clock low itself, as we are not sending STOP
+ //
+ PULL_SDA_HI();
+ }
+ //
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ //
+ // Delay for 1/2 bit cell time while clock is high
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+
+ if (!bNoStop)
+ {
+ //
+ // release data line with clock high --> STOP CONDITION
+ //
+ PULL_SDA_HI();
+ }
+
+ //
+ // message successfully received (how could we fail???)
+ //
+ return AM_HAL_I2C_BIT_BANG_SUCCESS;
+}
+
+//*****************************************************************************
+//
+//! @brief Send a string of data bytes to an I2C device
+//!
+//! @param address (only 8 bit I2C addresses are supported)
+//! LSB is I2C R/W
+//! @param number_of_bytes to transfer (# payload bytes)
+//! @param pData pointer to data buffer containing payload
+//!
+//! This function handles sending a payload to a slave device
+//!
+//! returns ENUM {AM_HAL_I2C_BIT_BANG_SUCCESS, AM_HAL_I2C_BIT_BANG_DATA_NAKED,
+//! AM_HAL_I2C_BIT_BANG_ADDRESS_NAKED}
+//
+//*****************************************************************************
+am_hal_i2c_bit_bang_enum_t
+am_hal_i2c_bit_bang_send(uint8_t address, uint32_t number_of_bytes,
+ uint8_t *pData, uint8_t ui8Offset,
+ bool bUseOffset, bool bNoStop)
+{
+ uint32_t ui32I;
+ am_hal_i2c_bit_bang_enum_t status;
+ bool data_naked = false;
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ //
+ // Pull down on data line with clock high --> START CONDITION
+ //
+ WRITE_SDA_LO();
+
+ //
+ // Delay for 1/2 bit cell time to start the clock
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+
+ //
+ // send the address byte and wait for the ACK/NAK
+ //
+ status = i2c_send_byte(address);
+ if ( status != AM_HAL_I2C_BIT_BANG_SUCCESS )
+ {
+ if ( status == AM_HAL_I2C_BIT_BANG_DATA_NAKED)
+ {
+ return AM_HAL_I2C_BIT_BANG_ADDRESS_NAKED;
+ }
+ return status;
+ }
+
+ if ( bUseOffset )
+ {
+ status = i2c_send_byte(ui8Offset);
+ if ( status != AM_HAL_I2C_BIT_BANG_SUCCESS )
+ {
+ return status;
+ }
+ }
+
+ //
+ // send the requested number of data bytes
+ //
+ for (ui32I = 0; ui32I < number_of_bytes; ui32I++)
+ {
+ //
+ // send out the data bytes while watching for premature NAK
+ //
+ status = i2c_send_byte(*pData++);
+ if (status != AM_HAL_I2C_BIT_BANG_SUCCESS)
+ {
+ if (status == AM_HAL_I2C_BIT_BANG_DATA_NAKED)
+ {
+ if (ui32I != (number_of_bytes-1))
+ {
+ data_naked = true;
+ // TODO - should we be sending the STOP bit in this case regardless of bNoStop?
+ break;
+ }
+ else
+ {
+ status = AM_HAL_I2C_BIT_BANG_SUCCESS;
+ }
+ }
+ else
+ {
+ return status;
+ }
+ }
+ }
+
+ //********************
+ // Send stop condition
+ //********************
+
+ //
+ // Pull down on clock line
+ //
+ WRITE_SCL_LO();
+
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+
+
+ if (!bNoStop)
+ {
+ //
+ // Pull down on data line with clock low
+ //
+ WRITE_SDA_LO();
+ }
+ else
+ {
+ //
+ // Release data line with clock low itself, as we are not sending STOP
+ //
+ PULL_SDA_HI();
+ }
+
+ //
+ // Delay for 1/4 bit cell time
+ //
+ WAIT_FOR_QUARTER_I2C_CLOCK();
+
+ if (i2c_pull_and_wait_scl_hi())
+ {
+ return AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT;
+ }
+ if (!bNoStop)
+ {
+ //
+ // release data line with clock high --> STOP CONDITION
+ //
+ PULL_SDA_HI();
+ }
+
+ //
+ // Delay for 1/2 bit cell time while clock is high
+ //
+ WAIT_I2C_CLOCK_HI_PERIOD();
+
+ if ( data_naked )
+ {
+ return AM_HAL_I2C_BIT_BANG_DATA_NAKED; // if it happens early
+ }
+
+ //
+ // message successfully sent
+ //
+ return AM_HAL_I2C_BIT_BANG_SUCCESS;
+}
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.h b/bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.h
new file mode 100644
index 0000000000..a9571edbe5
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_i2c_bit_bang.h
@@ -0,0 +1,100 @@
+//*****************************************************************************
+//
+// am_hal_i2c_bit_bang.h
+//! @file
+//!
+//! @brief I2C bit bang module.
+//!
+//! These functions implement the I2C bit bang utility
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_I2C_BIT_BANG_H
+#define AM_HAL_I2C_BIT_BANG_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Enumerated return constants
+//
+//*****************************************************************************
+typedef enum
+{
+ AM_HAL_I2C_BIT_BANG_SUCCESS = 0,
+ AM_HAL_I2C_BIT_BANG_ADDRESS_NAKED,
+ AM_HAL_I2C_BIT_BANG_DATA_NAKED,
+ AM_HAL_I2C_BIT_BANG_CLOCK_TIMEOUT,
+ AM_HAL_I2C_BIT_BANG_DATA_TIMEOUT,
+}am_hal_i2c_bit_bang_enum_t;
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern am_hal_i2c_bit_bang_enum_t am_hal_i2c_bit_bang_init(uint32_t sck_gpio_number,
+ uint32_t sda_gpio_number);
+
+extern am_hal_i2c_bit_bang_enum_t am_hal_i2c_bit_bang_send(uint8_t address,
+ uint32_t number_of_bytes,
+ uint8_t *pData,
+ uint8_t ui8Offset,
+ bool bUseOffset,
+ bool bNoStop);
+
+extern am_hal_i2c_bit_bang_enum_t am_hal_i2c_bit_bang_receive(uint8_t address,
+ uint32_t number_of_bytes,
+ uint8_t *pData,
+ uint8_t ui8Offset,
+ bool bUseOffset,
+ bool bNoStop);
+#ifdef __cplusplus
+}
+#endif
+
+#endif //AM_HAL_I2C_BIT_BANG_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.c b/bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.c
new file mode 100644
index 0000000000..2f93b09cfc
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.c
@@ -0,0 +1,407 @@
+//*****************************************************************************
+//
+// am_hal_interrupt.c
+//! @file
+//!
+//! @brief Helper functions supporting interrupts and NVIC operation.
+//!
+//! These functions may be used for NVIC-level interrupt configuration.
+//!
+//! @addtogroup interrupt2 Interrupt (ARM NVIC support functions)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Enable an interrupt.
+//!
+//! @param ui32Interrupt The ISR number of the interrupt to be enabled.
+//!
+//! This function enables an interrupt signal to the NVIC based on the provided
+//! ISR number.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_interrupt_enable(uint32_t ui32Interrupt)
+{
+ //
+ // Check to see what type of interrupt this is.
+ //
+ if ( ui32Interrupt > 15 )
+ {
+ //
+ // If this ISR number corresponds to a "normal" peripheral interrupt,
+ // enable it using the NVIC register.
+ //
+ AM_REG(NVIC, ISER0) = 0x1 << ((ui32Interrupt - 16) & 0x1F);
+ }
+ else
+ {
+ //
+ // If this is an ARM internal interrupt number, route it to the
+ // appropriate enable register.
+ //
+ switch(ui32Interrupt)
+ {
+ case AM_HAL_INTERRUPT_BUSFAULT:
+ AM_BFW(SYSCTRL, SHCSR, BUSFAULTENA, 1);
+ break;
+
+ case AM_HAL_INTERRUPT_USAGEFAULT:
+ AM_BFW(SYSCTRL, SHCSR, USAGEFAULTENA, 1);
+ break;
+
+ case AM_HAL_INTERRUPT_MPUFAULT:
+ AM_BFW(SYSCTRL, SHCSR, MEMFAULTENA, 1);
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Disable an interrupt.
+//!
+//! @param ui32Interrupt The ISR number of the interrupt to be disabled.
+//!
+//! This function disables an interrupt signal to the NVIC based on the
+//! provided ISR number.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_interrupt_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Check to see what type of interrupt this is.
+ //
+ if ( ui32Interrupt > 15 )
+ {
+ //
+ // If this ISR number corresponds to a "normal" peripheral interrupt,
+ // disable it using the NVIC register.
+ //
+ AM_REG(NVIC, ICER0) = 0x1 << ((ui32Interrupt - 16) & 0x1F);
+ }
+ else
+ {
+ //
+ // If this is an ARM internal interrupt number, route it to the
+ // appropriate enable register.
+ //
+ switch(ui32Interrupt)
+ {
+ case AM_HAL_INTERRUPT_BUSFAULT:
+ AM_BFW(SYSCTRL, SHCSR, BUSFAULTENA, 0);
+ break;
+
+ case AM_HAL_INTERRUPT_USAGEFAULT:
+ AM_BFW(SYSCTRL, SHCSR, USAGEFAULTENA, 0);
+ break;
+
+ case AM_HAL_INTERRUPT_MPUFAULT:
+ AM_BFW(SYSCTRL, SHCSR, MEMFAULTENA, 0);
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Set the priority of an interrupt vector.
+//!
+//! @param ui32Interrupt is the ISR number of the interrupt to change.
+//! @param ui32Priority is the new ISR priority value.
+//!
+//! This function changes the priority value in the NVIC for the given
+//! interrupt vector number.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_interrupt_priority_set(uint32_t ui32Interrupt, uint32_t ui32Priority)
+{
+ volatile uint32_t *pui32PriorityReg;
+ volatile uint32_t ui32OldPriority;
+ uint32_t ui32Shift;
+
+ //
+ // Find the correct priority register.
+ //
+ pui32PriorityReg = (volatile uint32_t *) AM_REG_NVIC_IPR0_O;
+ pui32PriorityReg += ((ui32Interrupt - 16) >> 2);
+
+ //
+ // Find the correct shift value.
+ //
+ ui32Shift = (((ui32Interrupt - 16) & 0x3) * 8);
+
+ //
+ // Mask out the old priority.
+ //
+ ui32OldPriority = *pui32PriorityReg;
+ ui32OldPriority &= ~(0xFF << ui32Shift);
+
+ //
+ // OR in the new priority.
+ //
+ *pui32PriorityReg |= (ui32Priority << ui32Shift);
+}
+
+//*****************************************************************************
+//
+//! @brief Set a pending interrupt bit in the NVIC (Software Interrupt)
+//!
+//! @param ui32Interrupt is the ISR number of the interrupt to change.
+//!
+//! This function sets the specified bit in the Interrupt Set Pending (ISPR0)
+//! register. For future MCUs there may be more than one ISPR.
+//!
+//! @return None
+//
+//*****************************************************************************
+void am_hal_interrupt_pend_set(uint32_t ui32Interrupt)
+{
+ //
+ // Check to see if the specified interrupt is valid for this MCU
+ //
+ if ( ui32Interrupt > 47 )
+ {
+ return;
+ }
+
+ //
+ // Check to see what type of interrupt this is.
+ //
+ if ( ui32Interrupt > 15 )
+ {
+ //
+ // If this ISR number corresponds to a "normal" peripheral interrupt,
+ // disable it using the NVIC register.
+ //
+ AM_REG(NVIC, ISPR0) = 0x1 << ((ui32Interrupt - 16) & 0x1F);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Clear a pending interrupt bit in the NVIC without servicing it
+//!
+//! @param ui32Interrupt is the ISR number of the interrupt to change.
+//!
+//! This function clears the specified bit in the Interrupt Clear Pending
+//! (ICPR0) register. For future MCUs there may be more than one ICPR. This
+//! function is useful immediately following a WFI before interrupts are
+//! re-enabled.
+//!
+//! @return None
+//
+//*****************************************************************************
+void am_hal_interrupt_pend_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Check to see if the specified interrupt is valid for this MCU
+ //
+ if ( ui32Interrupt > 47 )
+ {
+ return;
+ }
+
+ //
+ // Check to see what type of interrupt this is.
+ //
+ if ( ui32Interrupt > 15 )
+ {
+ //
+ // If this ISR number corresponds to a "normal" peripheral interrupt,
+ // disable it using the NVIC register.
+ //
+ AM_REG(NVIC, ICPR0) = 0x1 << ((ui32Interrupt - 16) & 0x1F);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Globally enable interrupt service routines
+//!
+//! This function allows interrupt signals from the NVIC to trigger ISR entry
+//! in the CPU. This function must be called if interrupts are to be serviced
+//! in software.
+//!
+//! @return 1 if interrupts were previously disabled, 0 otherwise.
+//
+//*****************************************************************************
+#if defined(__GNUC_STDC_INLINE__)
+uint32_t __attribute__((naked))
+am_hal_interrupt_master_enable(void)
+{
+ __asm(" mrs r0, PRIMASK");
+ __asm(" cpsie i");
+ __asm(" bx lr");
+}
+#elif defined(__ARMCC_VERSION)
+__asm uint32_t
+am_hal_interrupt_master_enable(void)
+{
+ mrs r0, PRIMASK
+ cpsie i
+ bx lr
+}
+#elif defined(__IAR_SYSTEMS_ICC__)
+#pragma diag_suppress = Pe940 // Suppress IAR compiler warning about missing
+ // return statement on a non-void function
+__stackless uint32_t
+am_hal_interrupt_master_enable(void)
+{
+ __asm(" mrs r0, PRIMASK");
+ __asm(" cpsie i");
+ __asm(" bx lr");
+}
+#pragma diag_default = Pe940 // Restore IAR compiler warning
+#endif
+
+//*****************************************************************************
+//
+//! @brief Globally disable interrupt service routines
+//!
+//! This function prevents interrupt signals from the NVIC from triggering ISR
+//! entry in the CPU. This will effectively stop incoming interrupt sources
+//! from triggering their corresponding ISRs.
+//!
+//! @note Any external interrupt signal that occurs while the master interrupt
+//! disable is active will still reach the "pending" state in the NVIC, but it
+//! will not be allowed to reach the "active" state or trigger the
+//! corresponding ISR. Instead, these interrupts are essentially "queued" until
+//! the next time the master interrupt enable instruction is executed. At that
+//! time, the interrupt handlers will be executed in order of decreasing
+//! priority.
+//!
+//! @return 1 if interrupts were previously disabled, 0 otherwise.
+//
+//*****************************************************************************
+#if defined(__GNUC_STDC_INLINE__)
+uint32_t __attribute__((naked))
+am_hal_interrupt_master_disable(void)
+{
+ __asm(" mrs r0, PRIMASK");
+ __asm(" cpsid i");
+ __asm(" bx lr");
+}
+#elif defined(__ARMCC_VERSION)
+__asm uint32_t
+am_hal_interrupt_master_disable(void)
+{
+ mrs r0, PRIMASK
+ cpsid i
+ bx lr
+}
+#elif defined(__IAR_SYSTEMS_ICC__)
+#pragma diag_suppress = Pe940 // Suppress IAR compiler warning about missing
+ // return statement on a non-void function
+__stackless uint32_t
+am_hal_interrupt_master_disable(void)
+{
+ __asm(" mrs r0, PRIMASK");
+ __asm(" cpsid i");
+ __asm(" bx lr");
+}
+#pragma diag_default = Pe940 // Restore IAR compiler warning
+#endif
+
+//*****************************************************************************
+//
+//! @brief Sets the master interrupt state based on the input.
+//!
+//! @param ui32InterruptState - Desired PRIMASK value.
+//!
+//! This function directly writes the PRIMASK register in the ARM core. A value
+//! of 1 will disable interrupts, while a value of zero will enable them.
+//!
+//! This function may be used along with am_hal_interrupt_master_disable() to
+//! implement a nesting critical section. To do this, call
+//! am_hal_interrupt_master_disable() to start the critical section, and save
+//! its return value. To complete the critical section, call
+//! am_hal_interrupt_master_set() using the saved return value as \e
+//! ui32InterruptState. This will safely restore PRIMASK to the value it
+//! contained just before the start of the critical section.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#if defined(__GNUC_STDC_INLINE__)
+void __attribute__((naked))
+am_hal_interrupt_master_set(uint32_t ui32InterruptState)
+{
+ __asm(" msr PRIMASK, r0");
+ __asm(" bx lr");
+}
+#elif defined(__ARMCC_VERSION)
+__asm void
+am_hal_interrupt_master_set(uint32_t ui32InterruptState)
+{
+ msr PRIMASK, r0
+ bx lr
+}
+#elif defined(__IAR_SYSTEMS_ICC__)
+#pragma diag_suppress = Pe940 // Suppress IAR compiler warning about missing
+ // return statement on a non-void function
+__stackless void
+am_hal_interrupt_master_set(uint32_t ui32InterruptState)
+{
+ __asm(" msr PRIMASK, r0");
+ __asm(" bx lr");
+}
+#pragma diag_default = Pe940 // Restore IAR compiler warning
+#endif
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.h b/bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.h
new file mode 100644
index 0000000000..a8523371eb
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_interrupt.h
@@ -0,0 +1,159 @@
+//*****************************************************************************
+//
+// am_hal_interrupt.h
+//! @file
+//!
+//! @brief Helper functions supporting interrupts and NVIC operation.
+//!
+//! These functions may be used for NVIC-level interrupt configuration.
+//!
+//! @addtogroup interrupt2 Interrupt (ARM NVIC support functions)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_INTERRUPT_H
+#define AM_HAL_INTERRUPT_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+//*****************************************************************************
+//
+//! @name ISR number macros.
+//! @brief ISR macros.
+//!
+//! These macros are used for all ui32Interrupt arguments in this module.
+//! @{
+//
+//*****************************************************************************
+//
+// Hardware interrupts
+//
+#define AM_HAL_INTERRUPT_RESET 1
+#define AM_HAL_INTERRUPT_NMI 2
+#define AM_HAL_INTERRUPT_HARDFAULT 3
+#define AM_HAL_INTERRUPT_MPUFAULT 4
+#define AM_HAL_INTERRUPT_BUSFAULT 5
+#define AM_HAL_INTERRUPT_USAGEFAULT 6
+
+#define AM_HAL_INTERRUPT_SVCALL 11
+#define AM_HAL_INTERRUPT_DEBUGMON 12
+#define AM_HAL_INTERRUPT_PENDSV 14
+#define AM_HAL_INTERRUPT_SYSTICK 15
+
+//
+// Begin IRQs
+//
+#define AM_HAL_INTERRUPT_BROWNOUT 16
+#define AM_HAL_INTERRUPT_WATCHDOG 17
+#define AM_HAL_INTERRUPT_CLKGEN 18
+#define AM_HAL_INTERRUPT_VCOMP 19
+#define AM_HAL_INTERRUPT_IOSLAVE 20
+#define AM_HAL_INTERRUPT_IOSACC 21
+#define AM_HAL_INTERRUPT_IOMASTER0 22
+#define AM_HAL_INTERRUPT_IOMASTER1 23
+#define AM_HAL_INTERRUPT_IOMASTER2 24
+#define AM_HAL_INTERRUPT_IOMASTER3 25
+#define AM_HAL_INTERRUPT_IOMASTER4 26
+#define AM_HAL_INTERRUPT_IOMASTER5 27
+#define AM_HAL_INTERRUPT_GPIO 28
+#define AM_HAL_INTERRUPT_CTIMER 29
+#define AM_HAL_INTERRUPT_UART0 30
+#define AM_HAL_INTERRUPT_UART1 31
+#define AM_HAL_INTERRUPT_UART (AM_HAL_INTERRUPT_UART0)
+#define AM_HAL_INTERRUPT_ADC 32
+#define AM_HAL_INTERRUPT_PDM 33
+#define AM_HAL_INTERRUPT_STIMER 34
+#define AM_HAL_INTERRUPT_STIMER_CMPR0 35
+#define AM_HAL_INTERRUPT_STIMER_CMPR1 36
+#define AM_HAL_INTERRUPT_STIMER_CMPR2 37
+#define AM_HAL_INTERRUPT_STIMER_CMPR3 38
+#define AM_HAL_INTERRUPT_STIMER_CMPR4 39
+#define AM_HAL_INTERRUPT_STIMER_CMPR5 40
+#define AM_HAL_INTERRUPT_STIMER_CMPR6 41
+#define AM_HAL_INTERRUPT_STIMER_CMPR7 42
+#define AM_HAL_INTERRUPT_FLASH 43
+
+#define AM_HAL_INTERRUPT_SOFTWARE0 44
+#define AM_HAL_INTERRUPT_SOFTWARE1 45
+#define AM_HAL_INTERRUPT_SOFTWARE2 46
+#define AM_HAL_INTERRUPT_SOFTWARE3 47
+//! @}
+
+//*****************************************************************************
+//
+//! @brief Interrupt priority
+//!
+//! This macro is made to be used with the \e am_hal_interrupt_priority_set()
+//! function. It converts a priority number to the format used by the ARM
+//! standard priority register, where only the top 3 bits are used.
+//!
+//! For example, AM_HAL_INTERRUPT_PRIORITY(1) yields a value of 0x20.
+//
+//*****************************************************************************
+#define AM_HAL_INTERRUPT_PRIORITY(n) (((uint32_t)(n) & 0x7) << 5)
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_interrupt_enable(uint32_t ui32Interrupt);
+extern void am_hal_interrupt_disable(uint32_t ui32Interrupt);
+extern void am_hal_interrupt_pend_set(uint32_t ui32Interrupt);
+extern void am_hal_interrupt_pend_clear(uint32_t ui32Interrupt);
+extern void am_hal_interrupt_priority_set(uint32_t ui32Interrupt,
+ uint32_t ui32Priority);
+extern uint32_t am_hal_interrupt_master_disable(void);
+extern uint32_t am_hal_interrupt_master_enable(void);
+extern void am_hal_interrupt_master_set(uint32_t ui32InterruptState);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_INTERRUPT_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_iom.c b/bsp/apollo2/libraries/drivers/hal/am_hal_iom.c
new file mode 100644
index 0000000000..8b85c32b6a
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_iom.c
@@ -0,0 +1,4426 @@
+//*****************************************************************************
+//
+// am_hal_iom.c
+//! @file
+//!
+//! @brief Functions for interfacing with the IO Master module
+//!
+//! @addtogroup iom2 IO Master (SPI/I2C)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+#include "am_util_delay.h"
+
+#ifdef __IAR_SYSTEMS_ICC__
+#define AM_INSTR_CLZ(n) __CLZ(n)
+#else
+#define AM_INSTR_CLZ(n) __builtin_clz(n)
+#endif
+
+//! ASSERT(1) or Correct(0) invalid IOM R/W Thresholds.
+#ifndef AM_ASSERT_INVALID_THRESHOLD
+#define AM_ASSERT_INVALID_THRESHOLD (1)
+#endif
+
+//*****************************************************************************
+//
+// Forcing optimizations
+//
+// These pragmas must be enabled if we intend to use the IOM4 workaround with a
+// delay higher than 18-bits in the first word.
+//
+//*****************************************************************************
+//#ifdef __IAR_SYSTEMS_ICC__
+//#pragma optimize=3 s
+//#endif
+//
+//#ifdef __ARMCC_VERSION
+//#pragma O3
+//#endif
+//
+//#ifdef __GNUC__
+//#pragma GCC optimize ("O3")
+//#endif
+
+//*****************************************************************************
+//
+// Forward declarations.
+//
+//*****************************************************************************
+static void iom_workaround_loop(uint32_t ui32PadRegVal,
+ volatile uint32_t *pui32PadReg,
+ bool bRising);
+static uint32_t
+internal_am_hal_iom_spi_cmd_construct(uint32_t ui32Operation,
+ uint32_t ui32ChipSelect,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+
+//*****************************************************************************
+//
+// IOM Buffer states.
+//
+//*****************************************************************************
+#define BUFFER_IDLE 0x0
+#define BUFFER_SENDING 0x1
+#define BUFFER_RECEIVING 0x2
+
+//*****************************************************************************
+//
+// Global state variables
+//
+//*****************************************************************************
+//
+// Save error status from ISR, particularly for use in I2C queue mode.
+//
+uint32_t g_iom_error_status = 0;
+
+//
+// Define a structure to map CE for IOM4 only.
+//
+typedef struct
+{
+ uint8_t channel; // CE channel for SPI
+ uint8_t pad; // GPIO Pad
+ uint8_t funcsel; // FNCSEL value
+} IOMPad_t;
+
+// Define the mapping between SPI CEn, Pads, and FNCSEL values for all IOMs.
+const IOMPad_t g_IOMPads[] =
+{
+ {0, 29, 6}, {0, 34, 6}, {1, 18, 4}, {1, 37, 5}, {2, 41, 6},
+ {3, 17, 4}, {3, 45, 4}, {4, 10, 6}, {4, 46, 6}, {5, 9, 4},
+ {5, 47, 6}, {6, 35, 4}, {7, 38, 6}
+};
+
+#define WORKAROUND_IOM 4
+#define WORKAROUND_IOM_MOSI_PIN 44
+#define WORKAROUND_IOM_MOSI_CFG AM_HAL_PIN_44_M4MOSI
+
+#define MAX_IOM_BITS 9
+#define IOM_OVERHEAD_FACTOR 2
+
+//*****************************************************************************
+//
+// Non-blocking buffer and buffer-management variables.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint32_t ui32State;
+ uint32_t *pui32Data;
+ uint32_t ui32BytesLeft;
+ uint32_t ui32Options;
+ void (*pfnCallback)(void);
+}
+am_hal_iom_nb_buffer;
+
+//
+// Global State to keep track if there is an ongoing transaction
+//
+volatile bool g_bIomBusy[AM_REG_IOMSTR_NUM_MODULES] = {0};
+
+am_hal_iom_nb_buffer g_psIOMBuffers[AM_REG_IOMSTR_NUM_MODULES];
+
+//*****************************************************************************
+//
+// Computed timeout.
+//
+// The IOM may not always respond to events (e.g., CMDCMP). This is a
+// timeout value in cycles to be used when waiting on status changes.
+//*****************************************************************************
+uint32_t ui32StatusTimeout[AM_REG_IOMSTR_NUM_MODULES];
+
+//*****************************************************************************
+//
+// Queue management variables.
+//
+//*****************************************************************************
+am_hal_queue_t g_psIOMQueue[AM_REG_IOMSTR_NUM_MODULES];
+
+//*****************************************************************************
+//
+// Default queue flush function
+//
+//*****************************************************************************
+am_hal_iom_queue_flush_t am_hal_iom_queue_flush = am_hal_iom_sleeping_queue_flush;
+
+//*****************************************************************************
+//
+// Power management structure.
+//
+//*****************************************************************************
+am_hal_iom_pwrsave_t am_hal_iom_pwrsave[AM_REG_IOMSTR_NUM_MODULES];
+
+
+//*****************************************************************************
+//
+// Static helper functions
+//
+//*****************************************************************************
+
+//*****************************************************************************
+// onebit()
+//*****************************************************************************
+//
+// A power of 2?
+// Return true if ui32Value has exactly 1 bit set, otherwise false.
+//
+static bool onebit(uint32_t ui32Value)
+{
+ return ui32Value && !(ui32Value & (ui32Value - 1));
+}
+
+//*****************************************************************************
+// compute_freq()
+//*****************************************************************************
+//
+// Compute the interface frequency based on the given parameters
+//
+static uint32_t compute_freq(uint32_t ui32HFRCfreqHz,
+ uint32_t ui32Fsel, uint32_t ui32Div3,
+ uint32_t ui32DivEn, uint32_t ui32TotPer)
+{
+ uint32_t ui32Denomfinal, ui32ClkFreq;
+
+ ui32Denomfinal = ((1 << (ui32Fsel - 1)) * (1 + ui32Div3 * 2) * (1 + ui32DivEn * (ui32TotPer)));
+ ui32ClkFreq = (ui32HFRCfreqHz) / ui32Denomfinal; // Compute the set frequency value
+ ui32ClkFreq += (((ui32HFRCfreqHz) % ui32Denomfinal) > (ui32Denomfinal / 2)) ? 1 : 0;
+
+ return ui32ClkFreq;
+}
+
+//*****************************************************************************
+// iom_calc_gpio()
+//
+// Calculate the IOM4 GPIO to assert.
+//
+//*****************************************************************************
+static uint32_t iom_calc_gpio(uint32_t ui32ChipSelect)
+{
+ uint32_t index;
+ uint8_t ui8PadRegVal, ui8FncSelVal;
+
+ //
+ // Figure out which GPIO we are using for the IOM
+ //
+ for ( index = 0; index < (sizeof(g_IOMPads) / sizeof(IOMPad_t)); index++ )
+ {
+ //
+ // Is this one of the CEn that we are using?
+ //
+ if ( g_IOMPads[index].channel == ui32ChipSelect )
+ {
+ //
+ // Get the PAD register value
+ //
+ ui8PadRegVal = ((AM_REGVAL(AM_HAL_GPIO_PADREG(g_IOMPads[index].pad))) &
+ AM_HAL_GPIO_PADREG_M(g_IOMPads[index].pad)) >>
+ AM_HAL_GPIO_PADREG_S(g_IOMPads[index].pad);
+
+ //
+ // Get the FNCSEL field value
+ //
+ ui8FncSelVal = (ui8PadRegVal & 0x38) >> 3;
+
+ //
+ // Is the FNCSEL filed for this pad set to the expected value?
+ //
+ if ( ui8FncSelVal == g_IOMPads[index].funcsel )
+ {
+ // This is the GPIO we need to use.
+ return g_IOMPads[index].pad;
+ }
+ }
+ }
+ return 0xDEADBEEF;
+}
+
+//*****************************************************************************
+//
+// Checks to see if this processor is a Rev B0 device.
+//
+// This is needed for the B0 IOM workaround.
+//
+//*****************************************************************************
+bool
+isRevB0(void)
+{
+ //
+ // Check to make sure the major rev is B and the minor rev is zero.
+ //
+ if ( (AM_REG(MCUCTRL, CHIPREV) & 0xFF) == AM_REG_MCUCTRL_CHIPREV_REVMAJ_B )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Returns the proper settings for the CLKCFG register.
+//!
+//! @param ui32FreqHz - The desired interface frequency in Hz.
+//! ui32Phase - SPI phase (0 or 1). Can affect duty cycle.
+//!
+//! Given a desired serial interface clock frequency, this function computes
+//! the appropriate settings for the various fields in the CLKCFG register
+//! and returns the 32-bit value that should be written to that register.
+//! The actual interface frequency may be slightly lower than the specified
+//! frequency, but the actual frequency is also returned.
+//!
+//! @note A couple of criteria that this algorithm follow are:
+//! 1. For power savings, choose the highest FSEL possible.
+//! 2. For best duty cycle, use DIV3 when possible rather than DIVEN.
+//!
+//! An example of #1 is that both of the following CLKCFGs would result
+//! in a frequency of 428,571 Hz: 0x0E071400 and 0x1C0E1300.
+//! The former is chosen by the algorithm because it results in FSEL=4
+//! while the latter is FSEL=3.
+//!
+//! An example of #2 is that both of the following CLKCFGs would result
+//! in a frequency of 2,000,000 Hz: 0x02011400 and 0x00000C00.
+//! The latter is chosen by the algorithm because it results in use of DIV3
+//! rather than DIVEN.
+//!
+//! @return An unsigned 64-bit value.
+//! The lower 32-bits represent the value to use to set CLKCFG.
+//! The upper 32-bits represent the actual frequency (in Hz) that will result
+//! from setting CLKCFG with the lower 32-bits.
+//!
+//! 0 (64 bits) = error. Note that the caller must check the entire 64 bits.
+//! It is not an error if only the low 32-bits are 0 (this is a valid value).
+//! But the entire 64 bits returning 0 is an error.
+//!
+//*****************************************************************************
+
+static
+uint64_t iom_get_interface_clock_cfg(uint32_t ui32FreqHz, uint32_t ui32Phase )
+{
+ uint32_t ui32Fsel, ui32Div3, ui32DivEn, ui32TotPer, ui32LowPer;
+ uint32_t ui32Denom, ui32v1, ui32Denomfinal, ui32ClkFreq, ui32ClkCfg;
+ uint32_t ui32HFRCfreqHz;
+ int32_t i32Div, i32N;
+
+ if ( ui32FreqHz == 0 )
+ {
+ return 0;
+ }
+
+ //
+ // Set the HFRC clock frequency.
+ //
+ ui32HFRCfreqHz = AM_HAL_CLKGEN_FREQ_MAX_HZ;
+
+ //
+ // Compute various parameters used for computing the optimal CLKCFG setting.
+ //
+ i32Div = (ui32HFRCfreqHz / ui32FreqHz) + ((ui32HFRCfreqHz % ui32FreqHz) ? 1 : 0); // Round up (ceiling)
+
+ //
+ // Compute N (count the number of LS zeros of Div) = ctz(Div) = log2(Div & (-Div))
+ //
+ i32N = 31 - AM_INSTR_CLZ((i32Div & (-i32Div)));
+
+ if ( i32N > 6 )
+ {
+ i32N = 6;
+ }
+
+ ui32Div3 = ( (ui32FreqHz < (ui32HFRCfreqHz / 16384)) ||
+ ( ((ui32FreqHz >= (ui32HFRCfreqHz / 3)) &&
+ (ui32FreqHz <= ((ui32HFRCfreqHz / 2) - 1)) ) ) ) ? 1 : 0;
+ ui32Denom = ( 1 << i32N ) * ( 1 + (ui32Div3 * 2) );
+ ui32TotPer = i32Div / ui32Denom;
+ ui32TotPer += (i32Div % ui32Denom) ? 1 : 0;
+ ui32v1 = 31 - AM_INSTR_CLZ(ui32TotPer); // v1 = log2(TotPer)
+ ui32Fsel = (ui32v1 > 7) ? ui32v1 + i32N - 7 : i32N;
+ ui32Fsel++;
+
+ if ( ui32Fsel > 7 )
+ {
+ //
+ // This is an error, can't go that low.
+ //
+ return 0;
+ }
+
+ if ( ui32v1 > 7 )
+ {
+ ui32DivEn = ui32TotPer; // Save TotPer for the round up calculation
+ ui32TotPer = ui32TotPer>>(ui32v1-7);
+ ui32TotPer += ((ui32DivEn) % (1 << (ui32v1 - 7))) ? 1 : 0;
+ }
+
+ ui32DivEn = ( (ui32FreqHz >= (ui32HFRCfreqHz / 4)) ||
+ ((1 << (ui32Fsel - 1)) == i32Div) ) ? 0 : 1;
+
+ if (ui32Phase == 1)
+ {
+ ui32LowPer = (ui32TotPer - 2) / 2; // Longer high phase
+ }
+ else
+ {
+ ui32LowPer = (ui32TotPer - 1) / 2; // Longer low phase
+ }
+
+ ui32ClkCfg = AM_REG_IOMSTR_CLKCFG_FSEL(ui32Fsel) |
+ AM_REG_IOMSTR_CLKCFG_DIV3(ui32Div3) |
+ AM_REG_IOMSTR_CLKCFG_DIVEN(ui32DivEn) |
+ AM_REG_IOMSTR_CLKCFG_LOWPER(ui32LowPer) |
+ AM_REG_IOMSTR_CLKCFG_TOTPER(ui32TotPer - 1);
+
+
+ //
+ // Now, compute the actual frequency, which will be returned.
+ //
+ ui32ClkFreq = compute_freq(ui32HFRCfreqHz, ui32Fsel, ui32Div3, ui32DivEn, ui32TotPer - 1);
+
+ //
+ // Determine if the actual frequency is a power of 2 (MHz).
+ //
+ if ( (ui32ClkFreq % 250000) == 0 )
+ {
+ //
+ // If the actual clock frequency is a power of 2 ranging from 250KHz up,
+ // we can simplify the CLKCFG value using DIV3 (which also results in a
+ // better duty cycle).
+ //
+ ui32Denomfinal = ui32ClkFreq / (uint32_t)250000;
+
+ if ( onebit(ui32Denomfinal) )
+ {
+ //
+ // These configurations can be simplified by using DIV3. Configs
+ // using DIV3 have a 50% duty cycle, while those from DIVEN will
+ // have a 66/33 duty cycle.
+ //
+ ui32TotPer = ui32LowPer = ui32DivEn = 0;
+ ui32Div3 = 1;
+
+ //
+ // Now, compute the return values.
+ //
+ ui32ClkFreq = compute_freq(ui32HFRCfreqHz, ui32Fsel, ui32Div3, ui32DivEn, ui32TotPer);
+
+ ui32ClkCfg = AM_REG_IOMSTR_CLKCFG_FSEL(ui32Fsel) |
+ AM_REG_IOMSTR_CLKCFG_DIV3(1) |
+ AM_REG_IOMSTR_CLKCFG_DIVEN(0) |
+ AM_REG_IOMSTR_CLKCFG_LOWPER(0) |
+ AM_REG_IOMSTR_CLKCFG_TOTPER(0);
+ }
+ }
+
+ return ( ((uint64_t)ui32ClkFreq) << 32) | (uint64_t)ui32ClkCfg;
+
+} //iom_get_interface_clock_cfg()
+
+
+//*****************************************************************************
+//
+//! @brief Enable the IOM in the power control block.
+//!
+//! This function enables the desigated IOM module in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_pwrctrl_enable(uint32_t ui32Module)
+{
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to enable an IOM module that doesn't exist.");
+
+ am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOM0 << ui32Module);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the IOM in the power control block.
+//!
+//! This function disables the desigated IOM module in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_pwrctrl_disable(uint32_t ui32Module)
+{
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to disable an IOM module that doesn't exist.");
+
+ am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_IOM0 << ui32Module);
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the IOM module
+//!
+//! @param ui32Module - The number of the IOM module to be enabled.
+//!
+//! This function enables the IOM module using the IFCEN bitfield in the
+//! IOMSTR_CFG register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_enable(uint32_t ui32Module)
+{
+ if ( ui32Module < AM_REG_IOMSTR_NUM_MODULES )
+ {
+ AM_REGn(IOMSTR, ui32Module, CFG) |= AM_REG_IOMSTR_CFG_IFCEN(1);
+ g_bIomBusy[ui32Module] = false;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the IOM module.
+//!
+//! @param ui32Module - The number of the IOM module to be disabled.
+//!
+//! This function disables the IOM module using the IFCEN bitfield in the
+//! IOMSTR_CFG register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_disable(uint32_t ui32Module)
+{
+ if ( ui32Module < AM_REG_IOMSTR_NUM_MODULES )
+ {
+ //
+ // Wait until the bus is idle.
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ //
+ // Disable the interface.
+ //
+ AM_REGn(IOMSTR, ui32Module, CFG) &= ~(AM_REG_IOMSTR_CFG_IFCEN(1));
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Enable power to the selected IOM module.
+//!
+//! @param ui32Module - Module number for the IOM to be turned on.
+//!
+//! This function enables the power gate to the selected IOM module. It is
+//! intended to be used along with am_hal_iom_power_off_save(). Used together,
+//! these functions allow the caller to power IOM modules off to save
+//! additional power without losing important configuration information.
+//!
+//! The am_hal_iom_power_off_save() function will save IOM configuration
+//! register information to SRAM before powering off the selected IOM module.
+//! This function will re-enable the IOM module, and restore those
+//! configuration settings from SRAM.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_power_on_restore(uint32_t ui32Module)
+{
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to enable an IOM module that doesn't exist.");
+
+ //
+ // Make sure this restore is a companion to a previous save call.
+ //
+ if ( am_hal_iom_pwrsave[ui32Module].bValid == 0 )
+ {
+ return;
+ }
+
+ //
+ // Enable power to the selected IOM.
+ //
+ am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOM0 << ui32Module);
+
+ //
+ // Restore the IOM configuration registers from the structure in SRAM.
+ //
+ AM_REGn(IOMSTR, ui32Module, FIFOTHR) = am_hal_iom_pwrsave[ui32Module].FIFOTHR;
+ AM_REGn(IOMSTR, ui32Module, CLKCFG) = am_hal_iom_pwrsave[ui32Module].CLKCFG;
+ AM_REGn(IOMSTR, ui32Module, CFG) = am_hal_iom_pwrsave[ui32Module].CFG;
+ AM_REGn(IOMSTR, ui32Module, INTEN) = am_hal_iom_pwrsave[ui32Module].INTEN;
+
+ //
+ // Indicates we have restored the configuration.
+ //
+ am_hal_iom_pwrsave[ui32Module].bValid = 0;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable power to the selected IOM module.
+//!
+//! @param ui32Module - Module number for the IOM to be turned off.
+//!
+//! This function disables the power gate to the selected IOM module. It is
+//! intended to be used along with am_hal_iom_power_on_restore(). Used together,
+//! these functions allow the caller to power IOM modules off to save
+//! additional power without losing important configuration information.
+//!
+//! The am_hal_iom_power_off_save() function will save IOM configuration
+//! register information to SRAM before powering off the selected IOM module.
+//! The am_hal_iom_power_on_restore() function will re-enable the IOM module
+//! and restore those configuration settings from SRAM.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_power_off_save(uint32_t ui32Module)
+{
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to disable an IOM module that doesn't exist.");
+
+ //
+ // Save the IOM configuration registers to the structure in SRAM.
+ //
+ am_hal_iom_pwrsave[ui32Module].FIFOTHR = AM_REGn(IOMSTR, ui32Module, FIFOTHR);
+ am_hal_iom_pwrsave[ui32Module].CLKCFG = AM_REGn(IOMSTR, ui32Module, CLKCFG);
+ am_hal_iom_pwrsave[ui32Module].CFG = AM_REGn(IOMSTR, ui32Module, CFG);
+ am_hal_iom_pwrsave[ui32Module].INTEN = AM_REGn(IOMSTR, ui32Module, INTEN);
+
+ //
+ // Indicates we have a valid saved configuration.
+ //
+ am_hal_iom_pwrsave[ui32Module].bValid = 1;
+
+ //
+ // Disable power to the selected IOM.
+ //
+ am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_IOM0 << ui32Module);
+}
+
+//
+//! Check and correct the IOM FIFO threshold.
+//
+#define MAX_RW_THRESHOLD (AM_HAL_IOM_MAX_FIFO_SIZE - 4)
+#define MIN_RW_THRESHOLD (4)
+#if (AM_ASSERT_INVALID_THRESHOLD == 0)
+static uint8_t check_iom_threshold(const uint8_t iom_threshold)
+{
+ uint8_t corrected_threshold = iom_threshold;
+
+ if ( corrected_threshold < MIN_RW_THRESHOLD )
+ {
+ corrected_threshold = MIN_RW_THRESHOLD;
+ }
+
+ if ( corrected_threshold > MAX_RW_THRESHOLD )
+ {
+ corrected_threshold = MAX_RW_THRESHOLD;
+ }
+
+ return corrected_threshold;
+}
+#endif
+
+//*****************************************************************************
+//
+//! @brief Sets module-wide configuration options for the IOM module.
+//!
+//! @param ui32Module - The instance number for the module to be configured
+//! (zero or one)
+//!
+//! @param psConfig - Pointer to an IOM configuration structure.
+//!
+//! This function is used to set the interface mode (SPI or I2C), clock
+//! frequency, SPI format (when relevant), and FIFO read/write interrupt
+//! thresholds for the IO master. For more information on specific
+//! configuration options, please see the documentation for the configuration
+//! structure.
+//!
+//! @note The IOM module should be disabled before configuring or
+//! re-configuring. This function will not re-enable the module when it
+//! completes. Call the am_hal_iom_enable function when the module is
+//! configured and ready to use.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_config(uint32_t ui32Module, const am_hal_iom_config_t *psConfig)
+{
+ uint32_t ui32Config, ui32ClkCfg;
+
+ //
+ // Start by checking the interface mode (I2C or SPI), and writing it to the
+ // configuration word.
+ //
+ ui32Config = psConfig->ui32InterfaceMode;
+
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ //
+ // Check the SPI format, and OR in the bits for SPHA (clock phase) and SPOL
+ // (polarity). These shouldn't have any effect in I2C mode, so it should be
+ // ok to write them without checking exactly which mode we're in.
+ //
+ if ( psConfig->bSPHA )
+ {
+ ui32Config |= AM_REG_IOMSTR_CFG_SPHA(1);
+ }
+
+ if ( psConfig->bSPOL )
+ {
+ ui32Config |= AM_REG_IOMSTR_CFG_SPOL(1);
+ }
+
+ // Set the STARTRD based on the interface speed
+ // For all I2C frequencies and SPI frequencies below 16 MHz, the STARTRD
+ // field should be set to 0 to minimize the potential of the IO transfer
+ // holding off a bus access to the FIFO. For SPI frequencies of 16 MHz
+ // or 24 MHz, the STARTRD field must be set to a value of 2 to insure
+ // enough time for the IO preread.
+ if ( psConfig->ui32ClockFrequency >= 16000000UL)
+ {
+ ui32Config |= AM_REG_IOMSTR_CFG_STARTRD(2);
+ }
+
+ //
+ // Write the resulting configuration word to the IO master CFG register for
+ // the module number we were provided.
+ //
+ AM_REGn(IOMSTR, ui32Module, CFG) = ui32Config;
+
+ //
+ // Write the FIFO write and read thresholds to the appropriate registers.
+ //
+#if (AM_ASSERT_INVALID_THRESHOLD == 1)
+ am_hal_debug_assert_msg(
+ (psConfig->ui8WriteThreshold <= MAX_RW_THRESHOLD), "IOM write threshold too big.");
+ am_hal_debug_assert_msg(
+ (psConfig->ui8ReadThreshold <= MAX_RW_THRESHOLD), "IOM read threshold too big.");
+ am_hal_debug_assert_msg(
+ (psConfig->ui8WriteThreshold >= MIN_RW_THRESHOLD), "IOM write threshold too small.");
+ am_hal_debug_assert_msg(
+ (psConfig->ui8ReadThreshold >= MIN_RW_THRESHOLD), "IOM read threshold too small.");
+
+ AM_REGn(IOMSTR, ui32Module, FIFOTHR) =
+ (AM_REG_IOMSTR_FIFOTHR_FIFOWTHR(psConfig->ui8WriteThreshold) |
+ AM_REG_IOMSTR_FIFOTHR_FIFORTHR(psConfig->ui8ReadThreshold));
+#elif (AM_ASSERT_INVALID_THRESHOLD == 0)
+ AM_REGn(IOMSTR, ui32Module, FIFOTHR) =
+ (AM_REG_IOMSTR_FIFOTHR_FIFOWTHR(check_iom_threshold(psConfig->ui8WriteThreshold)) |
+ AM_REG_IOMSTR_FIFOTHR_FIFORTHR(check_iom_threshold(psConfig->ui8ReadThreshold)));
+#else
+#error AM_ASSERT_INVALID_THRESHOLD must be 0 or 1.
+#endif
+
+ //
+ // An exception occurs in the LOWPER computation when setting an interface
+ // frequency (such as a divide by 5 frequency) which results in a 60/40
+ // duty cycle. The 60% cycle must occur in the appropriate half-period,
+ // as only one of the half-periods is active, depending on which phase
+ // is being selected.
+ // If SPHA=0 the low period must be 60%. If SPHA=1 high period must be 60%.
+ // Note that the predetermined frequency parameters use the formula
+ // lowper = (totper-1)/2, which results in a 60% low period.
+ //
+ ui32ClkCfg = iom_get_interface_clock_cfg(psConfig->ui32ClockFrequency,
+ psConfig->bSPHA );
+ if ( ui32ClkCfg )
+ {
+ AM_REGn(IOMSTR, ui32Module, CLKCFG) = (uint32_t)ui32ClkCfg;
+ }
+
+ //
+ // Compute the status timeout value.
+ //
+ ui32StatusTimeout[ui32Module] = MAX_IOM_BITS * AM_HAL_IOM_MAX_FIFO_SIZE *
+ IOM_OVERHEAD_FACTOR * (am_hal_clkgen_sysclk_get() / psConfig->ui32ClockFrequency);
+}
+
+//*****************************************************************************
+//
+//! @brief Returns the actual currently configured interface frequency in Hz.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_frequency_get(uint32_t ui32ClkCfg)
+{
+ uint32_t ui32Freq;
+
+ ui32Freq = compute_freq(AM_HAL_CLKGEN_FREQ_MAX_HZ,
+ (ui32ClkCfg & AM_REG_IOMSTR_CLKCFG_FSEL_M) >> AM_REG_IOMSTR_CLKCFG_FSEL_S,
+ (ui32ClkCfg & AM_REG_IOMSTR_CLKCFG_DIV3_M) >> AM_REG_IOMSTR_CLKCFG_DIV3_S,
+ (ui32ClkCfg & AM_REG_IOMSTR_CLKCFG_DIVEN_M) >> AM_REG_IOMSTR_CLKCFG_DIVEN_S,
+ (ui32ClkCfg & AM_REG_IOMSTR_CLKCFG_TOTPER_M)>> AM_REG_IOMSTR_CLKCFG_TOTPER_S);
+
+ return ui32Freq;
+}
+
+//*****************************************************************************
+//
+// Helper function for the B0 workaround.
+//
+//*****************************************************************************
+static uint32_t
+iom_get_workaround_fsel(uint32_t maxFreq)
+{
+ uint32_t ui32Freq, ui32Fsel;
+ uint32_t ui32ClkCfg = AM_REGn(IOMSTR, 4, CLKCFG);
+
+ //
+ // Starting with the current clock configuration parameters, find a value
+ // of FSEL that will bring our total frequency down to or below maxFreq.
+ //
+ for ( ui32Fsel = 1; ui32Fsel < 8; ui32Fsel++ )
+ {
+ ui32Freq = compute_freq(AM_HAL_CLKGEN_FREQ_MAX_HZ, ui32Fsel,
+ AM_BFX(IOMSTR, CLKCFG, DIV3, ui32ClkCfg),
+ AM_BFX(IOMSTR, CLKCFG, DIVEN, ui32ClkCfg),
+ AM_BFX(IOMSTR, CLKCFG, TOTPER, ui32ClkCfg));
+
+ if ( ui32Freq <= maxFreq && ui32Freq != 0 )
+ {
+ //
+ // Return the new FSEL
+ //
+ return ui32Fsel;
+ }
+ }
+
+ //
+ // Couldn't find an appropriate frequency. This should be impossible
+ // because there should always be a value of FSEL that brings the final IOM
+ // frequency below 500 KHz.
+ //
+ am_hal_debug_assert_msg(false, "Could find a valid frequency. Should never get here.");
+ return maxFreq;
+}
+
+// Separating this piece of code in separate function to keep the impact of
+// rest of the code to mimimal because of stack usage
+static void
+internal_iom_workaround_critical(uint32_t ui32Command,
+ volatile uint32_t *pui32CSPadreg,
+ uint32_t ui32CSPadregVal,
+ uint32_t ui32DelayTime,
+ uint32_t ui32ClkCfg,
+ uint32_t ui32LowClkCfg,
+ bool bRising)
+{
+ uint32_t ui32Critical = 0;
+ //
+ // Start a critical section.
+ //
+ ui32Critical = am_hal_interrupt_master_disable();
+
+ //
+ // Start the write on the bus.
+ //
+ AM_REGn(IOMSTR, WORKAROUND_IOM, CMD) = ui32Command;
+
+ //
+ // Slow down the clock, and run the workaround loop. The workaround
+ // loop runs an edge-detector on MOSI, and triggers a falling edge on
+ // chip-enable on the first bit of our real data.
+ //
+ ((void (*)(uint32_t)) 0x0800009d)(ui32DelayTime);
+ // Switch to Low Freq
+ AM_REGn(IOMSTR, WORKAROUND_IOM, CLKCFG) = ui32LowClkCfg;
+ iom_workaround_loop(ui32CSPadregVal, pui32CSPadreg, bRising);
+ //
+ // Restore the clock frequency and the normal MOSI pin function.
+ //
+ AM_REGn(IOMSTR, WORKAROUND_IOM, CLKCFG) = ui32ClkCfg;
+ am_hal_gpio_pin_config(WORKAROUND_IOM_MOSI_PIN, WORKAROUND_IOM_MOSI_CFG);
+
+ //
+ // End the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Critical);
+}
+
+
+//*****************************************************************************
+//
+//! @brief Workaround for an Apollo2 Rev B0 issue.
+//!
+//! @param ui32ChipSelect - Chip-select number for this transaction.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional SPI transfer options.
+//!
+//! Some Apollo2 Rev B0 devices have an issue where the first byte of a SPI
+//! write transaction can have some of its bits changed from ones to zeroes. In
+//! order to get around this issue, we artificially pad the SPI write data with
+//! additional bytes, and manually control the CS pin for the beginning of the
+//! SPI frame so that the receiving device will ignore the bytes of padding
+//! that we added.
+//!
+//! This function acts as a helper function to higher-level spi APIs. It
+//! performs the functions of am_hal_iom_fifo_write() and
+//! am_hal_iom_spi_cmd_run() to get a SPI write started on the bus, including
+//! all of the necessary workaround behavior.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_workaround_word_write(uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32TransferSize;
+ uint32_t ui32IOMGPIO = 0xDEADBEEF;
+ volatile uint32_t *pui32CSPadreg = 0;
+ uint32_t ui32CSPadregVal = 0;
+ uint32_t ui32ClkCfg = 0;
+ uint32_t ui32HiClkCfg, ui32LowClkCfg;
+ bool bRising = 0;
+ uint32_t ui32HiFreq = 0, ui32NormalFreq = 0;
+ uint32_t ui32DelayTime = 0;
+ uint32_t ui32LowFsel = 0;
+ uint32_t ui32HiFsel = 0;
+ uint32_t ui32FirstWord = 0;
+ uint32_t ui32MaxFifoSize = ((0 == AM_BFRn(IOMSTR, WORKAROUND_IOM, CFG, FULLDUP)) ?
+ AM_HAL_IOM_MAX_FIFO_SIZE : AM_HAL_IOM_MAX_FIFO_SIZE / 2);
+ uint32_t ui32Command;
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ // Note: This is a little shorter than usual, since the workaround
+ // consumes an extra byte at the beginning of the transfer.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes <= 4091, "SPI transfer too big.");
+
+ //
+ // Create a "dummy" word to add on to the beginning of the transfer
+ // that will guarantee a transition between the first word and the
+ // second on the bus.
+ //
+ // For raw transactions, this is straightforward. For transactions
+ // preceded by an offset, we'll add the offset in to the "dummy" word
+ // to preserve data alignment later.
+ //
+ // The workaround uses a critical section for precision
+ // To minimize the time in critical section, we raise the SPI frequency
+ // to the max possible for the initial preamble to be clocked out
+ // then we switch to a 'reasonably' slow frequency to be able to reliably
+ // catch the rising or falling edge by polling. Then we switch back to
+ // configured frequency
+ //
+
+ // We want to slow down the clock to help us count edges more
+ // accurately. Save it first, then slow it down. Also, we will
+ // pre-calculate a delay for when we need to restore the SPI settings.
+ //
+ ui32ClkCfg = AM_REGn(IOMSTR, WORKAROUND_IOM, CLKCFG);
+ // Get the largest speed we can configure within our rated speed of 16MHz
+ ui32HiFsel = iom_get_workaround_fsel(16000000);
+ ui32HiClkCfg = ((ui32ClkCfg & (~AM_REG_IOMSTR_CLKCFG_FSEL_M)) |
+ AM_BFV(IOMSTR, CLKCFG, FSEL, ui32HiFsel));
+ // Switch to Hi Freq
+ // Need to make sure we wait long enough for the hi clock to be effective
+ // Delay 2 cycles based on previous frequency
+ ui32NormalFreq = am_hal_iom_frequency_get(ui32ClkCfg);
+ AM_REGn(IOMSTR, WORKAROUND_IOM, CLKCFG) = ui32HiClkCfg;
+ ui32DelayTime = ((2 * AM_HAL_CLKGEN_FREQ_MAX_HZ) / (ui32NormalFreq * 3));
+ ((void (*)(uint32_t)) 0x0800009d)(ui32DelayTime);
+ //
+ // Remember what frequency we'll be running at.during Hi Phase
+ //
+ ui32HiFreq = am_hal_iom_frequency_get(ui32HiClkCfg);
+
+ //
+ // Validate return value to prevent DIVBY0 errors.
+ //
+ am_hal_debug_assert_msg(ui32HiFreq > 0, "Invalid Hi Frequency for IOM.");
+
+ // Get a reasonably slow speed (~1MHz) we can safely poll for the transition
+ ui32LowFsel = iom_get_workaround_fsel(1000000);
+ ui32LowClkCfg = ((ui32ClkCfg & (~AM_REG_IOMSTR_CLKCFG_FSEL_M)) |
+ AM_BFV(IOMSTR, CLKCFG, FSEL, ui32LowFsel));
+
+ if ( ui32Options & AM_HAL_IOM_RAW )
+ {
+ //
+ // The transition we care for is on 33rd bit.
+ // Prepare to delay 27 bits past the start of the transaction
+ // before getting into polling - to leave some
+ // margin for compiler related variations
+ //
+ ui32DelayTime = ((27 * AM_HAL_CLKGEN_FREQ_MAX_HZ) / (ui32HiFreq * 3));
+
+ if ( pui32Data[0] & 0x80 )
+ {
+ ui32FirstWord = 0x00000000;
+ bRising = true;
+ }
+ else
+ {
+ ui32FirstWord = 0xFFFFFF00;
+ bRising = false;
+ }
+ }
+ else
+ {
+ //
+ // The transition we care for is on 25th bit.
+ // Prepare to delay 19 bits past the start of the transaction
+ // before getting into polling - to leave some
+ // margin for compiler related variations
+ //
+ ui32DelayTime = ((19 * AM_HAL_CLKGEN_FREQ_MAX_HZ) / (ui32HiFreq * 3));
+ ui32FirstWord = ((ui32Options & 0xFF00) << 16);
+ if ( ui32FirstWord & 0x80000000 )
+ {
+ bRising = true;
+ }
+ else
+ {
+ ui32FirstWord |= 0x00FFFF00;
+ bRising = false;
+ }
+ }
+
+ //
+ // Now that weve taken care of the offset byte, we can run the
+ // transaction in RAW mode.
+ //
+ ui32Options |= AM_HAL_IOM_RAW;
+
+ ui32NumBytes += 4;
+
+ //
+ // Figure out how many bytes we can write to the FIFO immediately.
+ //
+ ui32TransferSize = (ui32NumBytes <= ui32MaxFifoSize ? ui32NumBytes :
+ ui32MaxFifoSize);
+
+ am_hal_iom_fifo_write(WORKAROUND_IOM, &ui32FirstWord, 4);
+
+ am_hal_iom_fifo_write(WORKAROUND_IOM, pui32Data, ui32TransferSize - 4);
+
+ //
+ // Calculate the GPIO to be controlled until the initial shift is
+ // complete. Make sure we get a valid value.
+ //
+ ui32IOMGPIO = iom_calc_gpio(ui32ChipSelect);
+ am_hal_debug_assert(0xDEADBEEF != ui32IOMGPIO);
+
+ //
+ // Save the locations and values of the CS pin configuration
+ // information.
+ //
+ pui32CSPadreg = (volatile uint32_t *)AM_HAL_GPIO_PADREG(ui32IOMGPIO);
+ ui32CSPadregVal = *pui32CSPadreg;
+
+ //
+ // Switch CS to a GPIO.
+ //
+ am_hal_gpio_out_bit_set(ui32IOMGPIO);
+ am_hal_gpio_pin_config(ui32IOMGPIO, AM_HAL_GPIO_OUTPUT);
+
+ //
+ // Enable the input buffer on MOSI.
+ //
+ am_hal_gpio_pin_config(WORKAROUND_IOM_MOSI_PIN, WORKAROUND_IOM_MOSI_CFG | AM_HAL_PIN_DIR_INPUT);
+
+ //
+ // Write the GPIO PADKEY register to allow the workaround loop to
+ // reconfigure chip enable.
+ //
+ AM_REGn(GPIO, 0, PADKEY) = AM_REG_GPIO_PADKEY_KEYVAL;
+ // Preconstruct the command - to save on calculations inside critical section
+ ui32Command = internal_am_hal_iom_spi_cmd_construct(AM_HAL_IOM_WRITE,
+ ui32ChipSelect, ui32NumBytes, ui32Options);
+ internal_iom_workaround_critical(ui32Command,
+ pui32CSPadreg, ui32CSPadregVal,
+ ui32DelayTime, ui32ClkCfg,
+ ui32LowClkCfg, bRising);
+
+ //
+ // Update the pointer and data counter.
+ //
+ ui32NumBytes -= ui32TransferSize;
+ pui32Data += (ui32TransferSize - 4) >> 2;
+}
+
+//*****************************************************************************
+//
+//! @brief Implement an iterative spin loop.
+//!
+//! @param ui32Iterations - Number of iterations to delay.
+//!
+//! Use this function to implement a CPU busy waiting spin. For Apollo, this
+//! delay can be used for timing purposes since for Apollo, each iteration will
+//! take 3 cycles.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#if defined(__GNUC_STDC_INLINE__)
+static void __attribute__((naked))
+iom_workaround_loop(uint32_t ui32PadRegVal, volatile uint32_t *pui32PadReg,
+ bool bRising)
+{
+ //
+ // Check to see if this is a "rising edge" or "falling edge" detector.
+ //
+ __asm(" cbz r2, falling_edge");
+
+ //
+ // Read GPIO pin 44, and loop until it's HIGH.
+ //
+ __asm("rising_edge:");
+ __asm(" ldr r2, =0x40010084");
+ __asm("rising_check_mosi:");
+ __asm(" ldr r3, [r2]");
+ __asm(" ands r3, r3, #0x1000");
+ __asm(" beq rising_check_mosi");
+
+ //
+ // Write the PADREG Value to the PADREG register.
+ //
+ __asm(" str r0, [r1]");
+ __asm(" bx lr");
+
+ //
+ // Read GPIO pin 44, and loop until it's LOW.
+ //
+ __asm("falling_edge:");
+ __asm(" ldr r2, =0x40010084");
+ __asm("falling_check_mosi:");
+ __asm(" ldr r3, [r2]");
+ __asm(" ands r3, r3, #0x1000");
+ __asm(" bne falling_check_mosi");
+
+ //
+ // Write the PADREG Value to the PADREG register.
+ //
+ __asm(" str r0, [r1]");
+ __asm(" bx lr");
+}
+#endif
+#ifdef keil
+__asm static void
+iom_workaround_loop(uint32_t ui32PadRegVal, volatile uint32_t *pui32PadReg,
+ bool bRising)
+{
+ //
+ // Check to see if this is a "rising edge" or "falling edge" detector.
+ //
+ cbz r2, falling_edge
+
+ //
+ // Read GPIO pin 44, and loop until it's HIGH.
+ //
+rising_edge
+ ldr r2, =0x40010084
+rising_check_mosi
+ ldr r3, [r2]
+ ands r3, r3, #0x1000
+ beq rising_check_mosi
+
+ //
+ // Write the PADREG Value to the PADREG register.
+ //
+ str r0, [r1]
+ bx lr
+
+ //
+ // Read GPIO pin 44, and loop until it's LOW.
+ //
+falling_edge
+ ldr r2, =0x40010084
+falling_check_mosi
+ ldr r3, [r2]
+ ands r3, r3, #0x1000
+ bne falling_check_mosi
+
+ //
+ // Write the PADREG Value to the PADREG register.
+ //
+ str r0, [r1]
+ bx lr
+ nop
+}
+#endif
+#ifdef iar
+static void
+iom_workaround_loop(uint32_t ui32PadRegVal, volatile uint32_t *pui32PadReg,
+ bool bRising)
+{
+ //
+ // Check to see if this is a "rising edge" or "falling edge" detector.
+ //
+ asm(
+ " cbz r2, falling_edge\n"
+
+ //
+ // Read GPIO pin 44, and loop until it's HIGH.
+ //
+ "rising_edge:\n"
+ " mov32 r2, #0x40010084\n"
+ "rising_check_mosi:\n"
+ " ldr r3, [r2]\n"
+ " ands r3, r3, #0x1000\n"
+ " beq rising_check_mosi\n"
+
+ //
+ // Write the PADREG Value to the PADREG register.
+ //
+ " str r0, [r1]\n"
+ " bx lr\n"
+
+ //
+ // Read GPIO pin 44, and loop until it's LOW.
+ //
+ "falling_edge:\n"
+ " mov32 r2, #0x40010084\n"
+ "falling_check_mosi:\n"
+ " ldr r3, [r2]\n"
+ " ands r3, r3, #0x1000\n"
+ " bne falling_check_mosi\n"
+
+ //
+ // Write the PADREG Value to the PADREG register.
+ //
+ " str r0, [r1]\n"
+ " bx lr"
+ );
+}
+#endif
+
+//*****************************************************************************
+//
+//! @brief Perform a simple write to the SPI interface.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32ChipSelect - Chip-select number for this transaction.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional SPI transfer options.
+//!
+//! This function performs SPI writes to a selected SPI device.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_spi_write(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ //
+ // Validate parameters
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to use an IOM module that doesn't exist.");
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Check to see if queues have been enabled. If they are, we'll actually
+ // switch to the queued interface.
+ //
+ if ( g_psIOMQueue[ui32Module].pui8Data != NULL )
+ {
+ //
+ // If the queue is on, go ahead and add this transaction to the queue.
+ //
+ am_hal_iom_queue_spi_write(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, 0);
+
+ //
+ // Wait until the transaction actually clears.
+ //
+ am_hal_iom_queue_flush(ui32Module);
+
+ //
+ // At this point, we've completed the transaction, and we can return.
+ //
+ return;
+ }
+ else
+ {
+ //
+ // Otherwise, we'll just do a polled transaction.
+ //
+ am_hal_iom_spi_write_nq(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Perform simple SPI read operations.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32ChipSelect - Chip-select number for this transaction.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional SPI transfer options.
+//!
+//! This function performs simple SPI read operations. The caller is
+//! responsible for ensuring that the receive buffer is large enough to hold
+//! the requested amount of data.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This function will pack the individual bytes from the physical interface
+//! into 32-bit words, which are then placed into the \e pui32Data array. Only
+//! the first \e ui32NumBytes bytes in this array will contain valid data.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_spi_read(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ //
+ // Validate parameters
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to use an IOM module that doesn't exist.");
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 4096, "SPI transfer too big.");
+
+ //
+ // Check to see if queues have been enabled. If they are, we'll actually
+ // switch to the queued interface.
+ //
+ if ( g_psIOMQueue[ui32Module].pui8Data != NULL )
+ {
+ //
+ // If the queue is on, go ahead and add this transaction to the queue.
+ //
+ am_hal_iom_queue_spi_read(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, 0);
+
+ //
+ // Wait until the transaction actually clears.
+ //
+ am_hal_iom_queue_flush(ui32Module);
+
+ //
+ // At this point, we've completed the transaction, and we can return.
+ //
+ return;
+ }
+ else
+ {
+ //
+ // Otherwise, just perform a polled transaction.
+ //
+ am_hal_iom_spi_read_nq(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Perform a simple write to the SPI interface (without queuing)
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32ChipSelect - Chip-select number for this transaction.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional SPI transfer options.
+//!
+//! This function performs SPI writes to a selected SPI device.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_spi_write_nq(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32TransferSize;
+ uint32_t ui32SpaceInFifo;
+ uint32_t ui32IntConfig;
+ uint32_t ui32MaxFifoSize;
+ uint32_t ui32Status = 1;
+
+ //
+ // Validate parameters
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to use an IOM module that doesn't exist.");
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 4096, "SPI transfer too big.");
+
+ ui32MaxFifoSize = ((0 == AM_BFRn(IOMSTR, ui32Module, CFG, FULLDUP)) ?
+ AM_HAL_IOM_MAX_FIFO_SIZE : AM_HAL_IOM_MAX_FIFO_SIZE / 2);
+ //
+ // Wait until any earlier transactions have completed.
+ //
+ am_hal_iom_poll_complete(ui32Module);
+ //
+ // Disable interrupts so that we don't get any undesired interrupts.
+ //
+ ui32IntConfig = AM_REGn(IOMSTR, ui32Module, INTEN);
+ AM_REGn(IOMSTR, ui32Module, INTEN) = 0;
+ // Clear CMDCMP status
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ //
+ // If we're on a B0 part, and we're using IOM4, our first byte coule be
+ // corrupted, so we need to send a dummy word with chip-select held high to
+ // get that first byte out of the way.
+ //
+ // That operation is tricky and detailed, so we'll call a function to do it
+ // for us.
+ //
+ if ( WORKAROUND_IOM == ui32Module && isRevB0() )
+ {
+ am_hal_iom_workaround_word_write(ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options);
+ //
+ // The workaround function is going to a partial transfer for us, but
+ // we have to keep our own data-tracking variables updated. Here, we're
+ // subtracting 4 bytes from the effective transfer size to account for
+ // the 4 bytes of "dummy" word that we sent instead of the actual data.
+ //
+ ui32TransferSize = (ui32NumBytes <= (ui32MaxFifoSize - 4) ? ui32NumBytes :
+ (ui32MaxFifoSize - 4));
+ }
+ else
+ {
+ //
+ // Figure out how many bytes we can write to the FIFO immediately.
+ //
+ ui32TransferSize = (ui32NumBytes <= ui32MaxFifoSize ? ui32NumBytes :
+ ui32MaxFifoSize);
+ //
+ // write our first word to the fifo.
+ //
+
+ am_hal_iom_fifo_write(ui32Module, pui32Data, ui32TransferSize);
+
+ //
+ // Start the write on the bus.
+ //
+ am_hal_iom_spi_cmd_run(AM_HAL_IOM_WRITE, ui32Module, ui32ChipSelect,
+ ui32NumBytes, ui32Options);
+ }
+
+ //
+ // Update the pointer and data counter.
+ //
+ ui32NumBytes -= ui32TransferSize;
+ pui32Data += ui32TransferSize >> 2;
+
+ //
+ // Keep looping until we're out of bytes to send or command complete (error).
+ //
+ while ( ui32NumBytes && !AM_BFRn(IOMSTR, ui32Module, INTSTAT, CMDCMP) )
+ {
+ //
+ // This will always return a multiple of four.
+ //
+ ui32SpaceInFifo = am_hal_iom_fifo_empty_slots(ui32Module);
+
+ if ( ui32NumBytes <= ui32SpaceInFifo )
+ {
+ //
+ // If the entire message will fit in the fifo, prepare to copy
+ // everything.
+ //
+ ui32TransferSize = ui32NumBytes;
+ }
+ else
+ {
+ //
+ // If only a portion of the message will fit in the fifo, prepare
+ // to copy the largest number of 4-byte blocks possible.
+ //
+ ui32TransferSize = ui32SpaceInFifo & ~(0x3);
+ }
+
+ //
+ // Write this chunk to the fifo.
+ //
+ am_hal_iom_fifo_write(ui32Module, pui32Data, ui32TransferSize);
+
+ //
+ // Update the data pointer and bytes-left count.
+ //
+ ui32NumBytes -= ui32TransferSize;
+ pui32Data += ui32TransferSize >> 2;
+ }
+
+ //
+ // Make sure CMDCMP was raised with standard timeout
+ //
+ ui32Status = am_util_wait_status_change(ui32StatusTimeout[ui32Module],
+ AM_REG_IOMSTRn(ui32Module) + AM_REG_IOMSTR_INTSTAT_O,
+ AM_REG_IOMSTR_INTEN_CMDCMP_M, AM_REG_IOMSTR_INTEN_CMDCMP_M);
+
+ //
+ // Re-enable IOM interrupts. Make sure CMDCMP is cleared
+ //
+ AM_REGn(IOMSTR, ui32Module, INTCLR) = (ui32IntConfig | AM_REG_IOMSTR_INTSTAT_CMDCMP_M);
+ AM_REGn(IOMSTR, ui32Module, INTEN) = ui32IntConfig;
+
+ am_hal_debug_assert_msg(ui32Status == 1,"IOM CMDCMP was not seen");
+
+ //
+ // Return the status (0 = timeout; 1 = success)
+ //
+ return ui32Status;
+
+}
+
+//*****************************************************************************
+//
+//! @brief Perform simple SPI read operations (without queuing).
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32ChipSelect - Chip-select number for this transaction.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional SPI transfer options.
+//!
+//! This function performs simple SPI read operations. The caller is
+//! responsible for ensuring that the receive buffer is large enough to hold
+//! the requested amount of data.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This function will pack the individual bytes from the physical interface
+//! into 32-bit words, which are then placed into the \e pui32Data array. Only
+//! the first \e ui32NumBytes bytes in this array will contain valid data.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_spi_read_nq(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32BytesInFifo;
+ uint32_t ui32IntConfig;
+ uint32_t bCmdCmp = false;
+ uint32_t ui32Status = 1;
+
+ //
+ // Validate parameters
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to use an IOM module that doesn't exist.");
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 4096, "SPI transfer too big.");
+
+ //
+ // Wait until the bus is idle, then start the requested READ transfer on
+ // the physical interface.
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ //
+ // Disable interrupts so that we don't get any undesired interrupts.
+ //
+ ui32IntConfig = AM_REGn(IOMSTR, ui32Module, INTEN);
+
+ //
+ // Disable IOM interrupts as we'll be polling
+ //
+ AM_REGn(IOMSTR, ui32Module, INTEN) = 0;
+
+ //
+ // Clear CMDCMP status
+ //
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ //
+ // If we're on a B0 part, and we're using IOM4, our first byte coule be
+ // corrupted, so we need to send a dummy word with chip-select held high to
+ // get that first byte out of the way. This is only true for spi reads with
+ // OFFSET values.
+ //
+ // That operation is tricky and detailed, so we'll call a function to do it
+ // for us.
+ //
+ if ( (WORKAROUND_IOM == ui32Module) && !(ui32Options & AM_HAL_IOM_RAW) &&
+ isRevB0() )
+ {
+ am_hal_iom_workaround_word_write(ui32ChipSelect, pui32Data, 0,
+ ui32Options | AM_HAL_IOM_CS_LOW);
+
+ //
+ // The workaround will send our offset for us, so we can run a RAW
+ // command after.
+ //
+ ui32Options |= AM_HAL_IOM_RAW;
+ //
+ // Wait for the dummy word to go out over the bus.
+ //
+ // Make sure the command complete has also been raised
+ ui32Status = am_util_wait_status_change(ui32StatusTimeout[ui32Module],
+ AM_REG_IOMSTRn(ui32Module) + AM_REG_IOMSTR_INTSTAT_O,
+ AM_REG_IOMSTR_INTEN_CMDCMP_M, AM_REG_IOMSTR_INTEN_CMDCMP_M);
+
+
+ // Clear CMDCMP status
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+ }
+
+ am_hal_iom_spi_cmd_run(AM_HAL_IOM_READ, ui32Module, ui32ChipSelect,
+ ui32NumBytes, ui32Options);
+
+ //
+ // Start a loop to catch the Rx data.
+ //
+ while ( ui32NumBytes )
+ {
+ ui32BytesInFifo = am_hal_iom_fifo_full_slots(ui32Module);
+
+ if ( ui32BytesInFifo >= ui32NumBytes )
+ {
+ //
+ // If the fifo contains our entire message, just copy the whole
+ // thing out.
+ //
+ am_hal_iom_fifo_read(ui32Module, pui32Data, ui32NumBytes);
+ ui32NumBytes = 0;
+ }
+ else if ( ui32BytesInFifo >= 4 )
+ {
+ //
+ // If the fifo has at least one 32-bit word in it, copy whole
+ // words out.
+ //
+ am_hal_iom_fifo_read(ui32Module, pui32Data, ui32BytesInFifo & ~0x3);
+ ui32NumBytes -= ui32BytesInFifo & ~0x3;
+ pui32Data += ui32BytesInFifo >> 2;
+ }
+ if ( bCmdCmp == true )
+ {
+ //
+ // No more data expected. Get out of the loop
+ //
+ break;
+ }
+
+ bCmdCmp = AM_BFRn(IOMSTR, ui32Module, INTSTAT, CMDCMP);
+ }
+
+ //
+ // Make sure CMDCMP was raised,
+ //
+ ui32Status = am_util_wait_status_change(ui32StatusTimeout[ui32Module],
+ AM_REG_IOMSTRn(ui32Module) + AM_REG_IOMSTR_INTSTAT_O,
+ AM_REG_IOMSTR_INTEN_CMDCMP_M, AM_REG_IOMSTR_INTEN_CMDCMP_M);
+
+ //
+ // Re-enable IOM interrupts. Make sure CMDCMP is cleared
+ //
+ AM_REGn(IOMSTR, ui32Module, INTCLR) = (ui32IntConfig | AM_REG_IOMSTR_INTSTAT_CMDCMP_M);
+ AM_REGn(IOMSTR, ui32Module, INTEN) = ui32IntConfig;
+
+ am_hal_debug_assert_msg(ui32Status == 1,"IOM CMDCMP was not seen");
+
+ //
+ // Return the status (0 = timeout; 1 = success)
+ //
+ return ui32Status;
+}
+
+//*****************************************************************************
+//
+//! @brief Perform a non-blocking write to the SPI interface.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32ChipSelect - Chip-select number for this transaction.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional SPI transfer options.
+//! @param pfnCallback - Function to call when the transaction completes.
+//!
+//! This function performs SPI writes to the selected SPI device.
+//!
+//! This function call is a non-blocking implementation. It will write as much
+//! data to the FIFO as possible immediately, store a pointer to the remaining
+//! data, start the transfer on the bus, and then immediately return. The
+//! caller will need to make sure that \e am_hal_iom_int_service() is called
+//! for IOM FIFO interrupt events and "command complete" interrupt events. The
+//! \e am_hal_iom_int_service() function will refill the FIFO as necessary and
+//! call the \e pfnCallback function when the transaction is finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_spi_write_nb(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback)
+{
+ uint32_t ui32TransferSize;
+ uint32_t ui32MaxFifoSize;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 4096, "SPI transfer too big.");
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ ui32MaxFifoSize = ((0 == AM_BFRn(IOMSTR, ui32Module, CFG, FULLDUP)) ?
+ AM_HAL_IOM_MAX_FIFO_SIZE : AM_HAL_IOM_MAX_FIFO_SIZE / 2);
+
+ //
+ // Wait until the bus is idle
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ //
+ // Need to mark IOM busy to avoid another transaction to be scheduled.
+ // This is to take care of a race condition in Queue mode, where the IDLE
+ // set is not a guarantee that the CMDCMP has been received
+ //
+ g_bIomBusy[ui32Module] = true;
+
+ //
+ // Clear CMDCMP status
+ //
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ //
+ // Check to see if we need to do the workaround.
+ //
+ if ( WORKAROUND_IOM == ui32Module && isRevB0() )
+ {
+ //
+ // Figure out how many bytes we can write to the FIFO immediately,
+ // accounting for the extra word from the workaround.
+ //
+ ui32TransferSize = (ui32NumBytes <= (ui32MaxFifoSize - 4) ? ui32NumBytes :
+ (ui32MaxFifoSize - 4));
+
+ //
+ // Prepare the global IOM buffer structure.
+ //
+ g_psIOMBuffers[ui32Module].ui32State = BUFFER_SENDING;
+ g_psIOMBuffers[ui32Module].pui32Data = pui32Data + (ui32TransferSize / 4);
+ g_psIOMBuffers[ui32Module].ui32BytesLeft = ui32NumBytes - ui32TransferSize;
+ g_psIOMBuffers[ui32Module].pfnCallback = pfnCallback;
+ g_psIOMBuffers[ui32Module].ui32Options = ui32Options;
+
+ //
+ // Start the write on the bus using the workaround. This includes both
+ // the command write and the first fifo write, so we won't need to do
+ // either of those things manually.
+ //
+ am_hal_iom_workaround_word_write(ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options);
+ }
+ else
+ {
+ //
+ // Figure out how many bytes we can write to the FIFO immediately.
+ //
+ ui32TransferSize = (ui32NumBytes <= ui32MaxFifoSize ? ui32NumBytes :
+ ui32MaxFifoSize);
+
+ if ( am_hal_iom_fifo_write(ui32Module, pui32Data, ui32TransferSize) > 0 )
+ {
+ //
+ // Prepare the global IOM buffer structure.
+ //
+ g_psIOMBuffers[ui32Module].ui32State = BUFFER_SENDING;
+ g_psIOMBuffers[ui32Module].pui32Data = pui32Data;
+ g_psIOMBuffers[ui32Module].ui32BytesLeft = ui32NumBytes;
+ g_psIOMBuffers[ui32Module].pfnCallback = pfnCallback;
+ g_psIOMBuffers[ui32Module].ui32Options = ui32Options;
+
+ //
+ // Update the pointer and the byte counter based on the portion of
+ // the transfer we just sent to the fifo.
+ //
+ g_psIOMBuffers[ui32Module].ui32BytesLeft -= ui32TransferSize;
+ g_psIOMBuffers[ui32Module].pui32Data += (ui32TransferSize / 4);
+
+ //
+ // Start the write on the bus.
+ //
+ am_hal_iom_spi_cmd_run(AM_HAL_IOM_WRITE, ui32Module, ui32ChipSelect,
+ ui32NumBytes, ui32Options);
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Perform a non-blocking SPI read.
+//!
+//! @param ui32Module - Module number for the IOM.
+//! @param ui32ChipSelect - Chip select number of the target device.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional SPI transfer options.
+//! @param pfnCallback - Function to call when the transaction completes.
+//!
+//! This function performs SPI reads to a selected SPI device.
+//!
+//! This function call is a non-blocking implementation. It will start the SPI
+//! transaction on the bus and store a pointer for the destination for the read
+//! data, but it will not wait for the SPI transaction to finish. The caller
+//! will need to make sure that \e am_hal_iom_int_service() is called for IOM
+//! FIFO interrupt events and "command complete" interrupt events. The \e
+//! am_hal_iom_int_service() function will empty the FIFO as necessary,
+//! transfer the data to the \e pui32Data buffer, and call the \e pfnCallback
+//! function when the transaction is finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This function will pack the individual bytes from the physical interface
+//! into 32-bit words, which are then placed into the \e pui32Data array. Only
+//! the first \e ui32NumBytes bytes in this array will contain valid data.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_spi_read_nb(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback)
+{
+ uint32_t ui32IntConfig;
+ uint32_t ui32Status = 1;
+
+ //
+ // Validate parameters
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_IOMSTR_NUM_MODULES,
+ "Trying to use an IOM module that doesn't exist.");
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 4096, "SPI transfer too big.");
+
+ //
+ // Wait until the bus is idle
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ //
+ // Need to mark IOM busy to avoid another transaction to be scheduled.
+ // This is to take care of a race condition in Queue mode, where the IDLE
+ // set is not a guarantee that the CMDCMP has been received
+ //
+
+ g_bIomBusy[ui32Module] = true;
+
+ //
+ // Clear CMDCMP status
+ //
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ //
+ // If we're on a B0 part, and we're using IOM4, our first byte coule be
+ // corrupted, so we need to send a dummy word with chip-select held high to
+ // get that first byte out of the way. This is only true for spi reads with
+ // OFFSET values.
+ //
+ // That operation is tricky and detailed, so we'll call a function to do it
+ // for us.
+ //
+ if ( (WORKAROUND_IOM == ui32Module) && !(ui32Options & AM_HAL_IOM_RAW) &&
+ isRevB0() )
+ {
+ //
+ // We might mess up the interrupt handler behavior if we allow this
+ // polled transaction to complete with interrupts enabled. We'll
+ // briefly turn them off here.
+ //
+ ui32IntConfig = AM_REGn(IOMSTR, 4, INTEN);
+ AM_REGn(IOMSTR, 4, INTEN) = 0;
+
+ am_hal_iom_workaround_word_write(ui32ChipSelect, pui32Data,
+ 0, ui32Options | AM_HAL_IOM_CS_LOW);
+
+ //
+ // The workaround will send our offset for us, so we can run a RAW
+ // command after.
+ //
+ ui32Options |= AM_HAL_IOM_RAW;
+
+ //
+ // Wait for the dummy word to go out over the bus.
+ //
+ // Make sure the command complete has also been raised
+ ui32Status = am_util_wait_status_change(ui32StatusTimeout[ui32Module],
+ AM_REG_IOMSTRn(ui32Module) + AM_REG_IOMSTR_INTSTAT_O,
+ AM_REG_IOMSTR_INTEN_CMDCMP_M, AM_REG_IOMSTR_INTEN_CMDCMP_M);
+
+ //
+ // Re-mark IOM as busy
+ //
+
+ g_bIomBusy[ui32Module] = true;
+
+ //
+ // Re-enable IOM interrupts. Make sure CMDCMP is cleared
+ //
+ AM_REGn(IOMSTR, 4, INTCLR) = (ui32IntConfig | AM_REG_IOMSTR_INTSTAT_CMDCMP_M);
+ AM_REGn(IOMSTR, 4, INTEN) = ui32IntConfig;
+ }
+
+ //
+ // Prepare the global IOM buffer structure.
+ //
+ g_psIOMBuffers[ui32Module].ui32State = BUFFER_RECEIVING;
+ g_psIOMBuffers[ui32Module].pui32Data = pui32Data;
+ g_psIOMBuffers[ui32Module].ui32BytesLeft = ui32NumBytes;
+ g_psIOMBuffers[ui32Module].pfnCallback = pfnCallback;
+ g_psIOMBuffers[ui32Module].ui32Options = ui32Options;
+
+ //
+ // Start the read transaction on the bus.
+ //
+ am_hal_iom_spi_cmd_run(AM_HAL_IOM_READ, ui32Module, ui32ChipSelect,
+ ui32NumBytes, ui32Options);
+
+ am_hal_debug_assert_msg(ui32Status == 1,"IOM CMDCMP was not seen");
+
+ return ui32Status;
+}
+
+static uint32_t
+internal_am_hal_iom_spi_cmd_construct(uint32_t ui32Operation,
+ uint32_t ui32ChipSelect,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32Command;
+ //
+ // Start building the command from the operation parameter.
+ //
+ ui32Command = ui32Operation;
+
+ //
+ // Set the transfer length (the length field is split, so this requires
+ // some swizzling).
+ //
+ ui32Command |= ((ui32NumBytes & 0xF00) << 15);
+ ui32Command |= (ui32NumBytes & 0xFF);
+
+ //
+ // Set the chip select number.
+ //
+ ui32Command |= ((ui32ChipSelect << 16) & 0x00070000);
+
+ //
+ // Finally, OR in the rest of the options. This mask should make sure that
+ // erroneous option values won't interfere with the other transfer
+ // parameters.
+ //
+ ui32Command |= ui32Options & 0x5C00FF00;
+ return ui32Command;
+}
+//*****************************************************************************
+//
+//! @brief Runs a SPI "command" through the IO master.
+//!
+//! @param ui32Operation - SPI action to be performed.
+//!
+//! @param psDevice - Structure containing information about the slave device.
+//!
+//! @param ui32NumBytes - Number of bytes to move (transmit or receive) with
+//! this command.
+//!
+//! @param ui32Options - Additional SPI options to apply to this command.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_spi_cmd_run(uint32_t ui32Operation, uint32_t ui32Module,
+ uint32_t ui32ChipSelect, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32Command;
+
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+ ui32Command = internal_am_hal_iom_spi_cmd_construct(ui32Operation,
+ ui32ChipSelect, ui32NumBytes, ui32Options);
+
+
+ //
+ // Write the complete command word to the IOM command register.
+ //
+ AM_REGn(IOMSTR, ui32Module, CMD) = ui32Command;
+}
+
+//*****************************************************************************
+//
+//! @brief Perform a simple write to the I2C interface (without queuing)
+//!
+//! @param ui32Module - Module number for the IOM.
+//! @param ui32BusAddress - I2C address of the target device.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional I2C transfer options.
+//!
+//! This function performs I2C writes to a selected I2C device.
+//!
+//! This function call is a blocking implementation. It will write as much
+//! data to the FIFO as possible immediately, and then refill the FIFO as data
+//! is transmiitted.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui32Data array.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_i2c_write_nq(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32TransferSize;
+ uint32_t ui32SpaceInFifo;
+ uint32_t ui32IntConfig;
+ uint32_t ui32MaxFifoSize;
+ uint32_t ui32Status = 1;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module > AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Redirect to the bit-bang interface if the module number matches the
+ // software I2C module.
+ //
+ if ( ui32Module == AM_HAL_IOM_I2CBB_MODULE )
+ {
+ if ( ui32Options & AM_HAL_IOM_RAW )
+ {
+ am_hal_i2c_bit_bang_send(ui32BusAddress << 1, ui32NumBytes,
+ (uint8_t *)pui32Data, 0, false,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+ else
+ {
+ am_hal_i2c_bit_bang_send(ui32BusAddress << 1, ui32NumBytes,
+ (uint8_t *)pui32Data,
+ ((ui32Options & 0xFF00) >> 8),
+ true,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+
+ //
+ // Return.
+ //
+ return 0;
+ }
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 256, "I2C transfer too big.");
+
+ ui32MaxFifoSize = ((0 == AM_BFRn(IOMSTR, ui32Module, CFG, FULLDUP)) ?
+ AM_HAL_IOM_MAX_FIFO_SIZE : AM_HAL_IOM_MAX_FIFO_SIZE / 2);
+
+ //
+ // Wait until any earlier transactions have completed.
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ //
+ // Disable interrupts so that we don't get any undesired interrupts.
+ //
+ ui32IntConfig = AM_REGn(IOMSTR, ui32Module, INTEN);
+ AM_REGn(IOMSTR, ui32Module, INTEN) = 0;
+
+ //
+ // Clear CMDCMP status
+ //
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ //
+ // Figure out how many bytes we can write to the FIFO immediately.
+ //
+ ui32TransferSize = (ui32NumBytes <= ui32MaxFifoSize ? ui32NumBytes :
+ ui32MaxFifoSize);
+
+ am_hal_iom_fifo_write(ui32Module, pui32Data, ui32TransferSize);
+
+ //
+ // Start the write on the bus.
+ //
+ am_hal_iom_i2c_cmd_run(AM_HAL_IOM_WRITE, ui32Module, ui32BusAddress,
+ ui32NumBytes, ui32Options);
+
+ //
+ // Update the pointer and data counter.
+ //
+ ui32NumBytes -= ui32TransferSize;
+ pui32Data += ui32TransferSize >> 2;
+
+ //
+ // Keep looping until we're out of bytes to send or command complete (error).
+ //
+ while ( ui32NumBytes && !AM_BFRn(IOMSTR, ui32Module, INTSTAT, CMDCMP) )
+ {
+ //
+ // This will always return a multiple of four.
+ //
+ ui32SpaceInFifo = am_hal_iom_fifo_empty_slots(ui32Module);
+
+ if ( ui32NumBytes <= ui32SpaceInFifo )
+ {
+ //
+ // If the entire message will fit in the fifo, prepare to copy
+ // everything.
+ //
+ ui32TransferSize = ui32NumBytes;
+ }
+ else
+ {
+ //
+ // If only a portion of the message will fit in the fifo, prepare
+ // to copy the largest number of 4-byte blocks possible.
+ //
+ ui32TransferSize = ui32SpaceInFifo;
+ }
+
+ //
+ // Write this chunk to the fifo.
+ //
+ am_hal_iom_fifo_write(ui32Module, pui32Data, ui32TransferSize);
+
+ //
+ // Update the data pointer and bytes-left count.
+ //
+ ui32NumBytes -= ui32TransferSize;
+ pui32Data += ui32TransferSize >> 2;
+ }
+
+ //
+ // Make sure CMDCMP was raised,
+ //
+ ui32Status = am_util_wait_status_change(ui32StatusTimeout[ui32Module],
+ AM_REG_IOMSTRn(ui32Module) + AM_REG_IOMSTR_INTSTAT_O,
+ AM_REG_IOMSTR_INTEN_CMDCMP_M, AM_REG_IOMSTR_INTEN_CMDCMP_M);
+
+ //
+ // Re-enable IOM interrupts. Make sure CMDCMP is cleared
+ //
+ AM_REGn(IOMSTR, ui32Module, INTCLR) = (ui32IntConfig | AM_REG_IOMSTR_INTSTAT_CMDCMP_M);
+ AM_REGn(IOMSTR, ui32Module, INTEN) = ui32IntConfig;
+
+ am_hal_debug_assert_msg(ui32Status == 1,"IOM CMDCMP was not seen");
+
+ //
+ // Return the status (0 = timeout; 1 = success)
+ //
+ return ui32Status;
+}
+
+//*****************************************************************************
+//
+//! @brief Perform simple I2C read operations (without queuing).
+//!
+//! @param ui32Module - Module number for the IOM.
+//! @param ui32BusAddress - I2C address of the target device.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional I2C transfer options.
+//!
+//! This function performs an I2C read to a selected I2C device.
+//!
+//! This function call is a blocking implementation. It will read as much
+//! data from the FIFO as possible immediately, and then re-read the FIFO as more
+//! data is available.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This function will pack the individual bytes from the physical interface
+//! into 32-bit words, which are then placed into the \e pui32Data array. Only
+//! the first \e ui32NumBytes bytes in this array will contain valid data.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_i2c_read_nq(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32BytesInFifo;
+ uint32_t ui32IntConfig;
+ uint32_t bCmdCmp = false;
+ uint32_t ui32Status = 1;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module > AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Redirect to the bit-bang interface if the module number matches the
+ // software I2C module.
+ //
+ if ( ui32Module == AM_HAL_IOM_I2CBB_MODULE )
+ {
+ if ( ui32Options & AM_HAL_IOM_RAW )
+ {
+ am_hal_i2c_bit_bang_receive((ui32BusAddress << 1) | 1, ui32NumBytes,
+ (uint8_t *)pui32Data, 0, false,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+ else
+ {
+ am_hal_i2c_bit_bang_receive((ui32BusAddress << 1) | 1, ui32NumBytes,
+ (uint8_t *)pui32Data,
+ ((ui32Options & 0xFF00) >> 8),
+ true,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+
+ //
+ // Return.
+ //
+ return 0;
+ }
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 256, "I2C transfer too big.");
+
+ //
+ // Wait until the bus is idle
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ //
+ // Disable interrupts so that we don't get any undesired interrupts.
+ //
+ ui32IntConfig = AM_REGn(IOMSTR, ui32Module, INTEN);
+ AM_REGn(IOMSTR, ui32Module, INTEN) = 0;
+
+ //
+ // Clear CMDCMP status
+ //
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ am_hal_iom_i2c_cmd_run(AM_HAL_IOM_READ, ui32Module, ui32BusAddress,
+ ui32NumBytes, ui32Options);
+
+ //
+ // Start a loop to catch the Rx data.
+ //
+ while ( ui32NumBytes )
+ {
+ ui32BytesInFifo = am_hal_iom_fifo_full_slots(ui32Module);
+
+ if ( ui32BytesInFifo >= ui32NumBytes )
+ {
+ //
+ // If the fifo contains our entire message, just copy the whole
+ // thing out.
+ //
+ am_hal_iom_fifo_read(ui32Module, pui32Data, ui32NumBytes);
+ ui32NumBytes = 0;
+ }
+ else if ( ui32BytesInFifo >= 4 )
+ {
+ //
+ // If the fifo has at least one 32-bit word in it, copy whole
+ // words out.
+ //
+ am_hal_iom_fifo_read(ui32Module, pui32Data, ui32BytesInFifo & ~0x3);
+
+ ui32NumBytes -= ui32BytesInFifo & ~0x3;
+ pui32Data += ui32BytesInFifo >> 2;
+ }
+
+ if ( bCmdCmp == true )
+ {
+ // No more data expected - exit out of loop
+ break;
+ }
+
+ bCmdCmp = AM_BFRn(IOMSTR, ui32Module, INTSTAT, CMDCMP);
+ }
+
+ //
+ // Make sure CMDCMP was raised,
+ //
+ ui32Status = am_util_wait_status_change(ui32StatusTimeout[ui32Module],
+ AM_REG_IOMSTRn(ui32Module) + AM_REG_IOMSTR_INTSTAT_O,
+ AM_REG_IOMSTR_INTEN_CMDCMP_M, AM_REG_IOMSTR_INTEN_CMDCMP_M);
+
+ //
+ // Re-enable IOM interrupts. Make sure CMDCMP is cleared
+ //
+ AM_REGn(IOMSTR, ui32Module, INTCLR) = (ui32IntConfig | AM_REG_IOMSTR_INTSTAT_CMDCMP_M);
+ AM_REGn(IOMSTR, ui32Module, INTEN) = ui32IntConfig;
+
+ am_hal_debug_assert_msg(ui32Status == 1,"IOM CMDCMP was not seen");
+
+ //
+ // Return the status (0 = timeout; 1 = success)
+ //
+ return ui32Status;
+}
+
+//*****************************************************************************
+//
+//! @brief Perform a simple write to the I2C interface.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32BusAddress - I2C bus address for this transaction.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional options
+//!
+//! Performs a write to the I2C interface using the provided parameters.
+//!
+//! See the "Command Options" section for parameters that may be ORed together
+//! and used in the \b ui32Options parameter.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_i2c_write(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module > AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Redirect to the bit-bang interface if the module number matches the
+ // software I2C module.
+ //
+ if ( ui32Module == AM_HAL_IOM_I2CBB_MODULE )
+ {
+ if ( ui32Options & AM_HAL_IOM_RAW )
+ {
+ am_hal_i2c_bit_bang_send(ui32BusAddress << 1, ui32NumBytes,
+ (uint8_t *)pui32Data, 0, false,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+ else
+ {
+ am_hal_i2c_bit_bang_send(ui32BusAddress << 1, ui32NumBytes,
+ (uint8_t *)pui32Data,
+ ((ui32Options & 0xFF00) >> 8),
+ true,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+
+ //
+ // Return.
+ //
+ return;
+ }
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 256, "I2C transfer too big.");
+
+ //
+ // Check to see if queues have been enabled. If they are, we'll actually
+ // switch to the queued interface.
+ //
+ if ( g_psIOMQueue[ui32Module].pui8Data != NULL )
+ {
+ //
+ // If the queue is on, go ahead and add this transaction to the queue.
+ //
+ am_hal_iom_queue_i2c_write(ui32Module, ui32BusAddress, pui32Data,
+ ui32NumBytes, ui32Options, 0);
+
+ //
+ // Wait until the transaction actually clears.
+ //
+ am_hal_iom_queue_flush(ui32Module);
+
+ //
+ // At this point, we've completed the transaction, and we can return.
+ //
+ return;
+ }
+ else
+ {
+ //
+ // Otherwise, we'll just do a polled transaction.
+ //
+ am_hal_iom_i2c_write_nq(ui32Module, ui32BusAddress, pui32Data,
+ ui32NumBytes, ui32Options);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Perform simple I2C read operations.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32BusAddress - I2C bus address for this transaction.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional I2C transfer options.
+//!
+//! This function performs simple I2C read operations. The caller is
+//! responsible for ensuring that the receive buffer is large enough to hold
+//! the requested amount of data. If \e bPolled is true, this function will
+//! block until all of the requested data has been received and placed in the
+//! user-supplied buffer. Otherwise, the function will execute the I2C read
+//! command and return immediately. The user-supplied buffer will be filled
+//! with the received I2C data as it comes in over the physical interface, and
+//! the "command complete" interrupt bit will become active once the entire
+//! message is available.
+//!
+//! See the "Command Options" section for parameters that may be ORed together
+//! and used in the \b ui32Options parameter.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This function will pack the individual bytes from the physical interface
+//! into 32-bit words, which are then placed into the \e pui32Data array. Only
+//! the first \e ui32NumBytes bytes in this array will contain valid data.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_i2c_read(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module > AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Redirect to the bit-bang interface if the module number matches the
+ // software I2C module.
+ //
+ if ( ui32Module == AM_HAL_IOM_I2CBB_MODULE )
+ {
+ if ( ui32Options & AM_HAL_IOM_RAW )
+ {
+ am_hal_i2c_bit_bang_receive((ui32BusAddress << 1) | 1, ui32NumBytes,
+ (uint8_t *)pui32Data, 0, false,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+ else
+ {
+ am_hal_i2c_bit_bang_receive((ui32BusAddress << 1) | 1, ui32NumBytes,
+ (uint8_t *)pui32Data,
+ ((ui32Options & 0xFF00) >> 8),
+ true,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+
+ //
+ // Return.
+ //
+ return;
+ }
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 256, "I2C transfer too big.");
+
+ //
+ // Check to see if queues have been enabled. If they are, we'll actually
+ // switch to the queued interface.
+ //
+ if ( g_psIOMQueue[ui32Module].pui8Data != NULL )
+ {
+ //
+ // If the queue is on, go ahead and add this transaction to the queue.
+ //
+ am_hal_iom_queue_i2c_read(ui32Module, ui32BusAddress, pui32Data,
+ ui32NumBytes, ui32Options, 0);
+
+ //
+ // Wait until the transaction actually clears.
+ //
+ am_hal_iom_queue_flush(ui32Module);
+
+ //
+ // At this point, we've completed the transaction, and we can return.
+ //
+ return;
+ }
+ else
+ {
+ //
+ // Otherwise, just perform a polled transaction.
+ //
+ am_hal_iom_i2c_read_nq(ui32Module, ui32BusAddress, pui32Data,
+ ui32NumBytes, ui32Options);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Perform a non-blocking write to the I2C interface.
+//!
+//! @param ui32Module - Module number for the IOM.
+//! @param ui32BusAddress - I2C address of the target device.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional I2C transfer options.
+//! @param pfnCallback - Function to call when the transaction completes.
+//!
+//! This function performs I2C writes to a selected I2C device.
+//!
+//! This function call is a non-blocking implementation. It will write as much
+//! data to the FIFO as possible immediately, store a pointer to the remaining
+//! data, start the transfer on the bus, and then immediately return. The
+//! caller will need to make sure that \e am_hal_iom_int_service() is called
+//! for IOM FIFO interrupt events and "command complete" interrupt events. The
+//! \e am_hal_iom_int_service() function will refill the FIFO as necessary and
+//! call the \e pfnCallback function when the transaction is finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui32Data array.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_i2c_write_nb(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback)
+{
+ uint32_t ui32TransferSize;
+ uint32_t ui32MaxFifoSize;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module > AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Redirect to the bit-bang interface if the module number matches the
+ // software I2C module.
+ //
+ if ( ui32Module == AM_HAL_IOM_I2CBB_MODULE )
+ {
+ if ( ui32Options & AM_HAL_IOM_RAW )
+ {
+ am_hal_i2c_bit_bang_send(ui32BusAddress << 1, ui32NumBytes,
+ (uint8_t *)pui32Data, 0, false,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+ else
+ {
+ am_hal_i2c_bit_bang_send(ui32BusAddress << 1, ui32NumBytes,
+ (uint8_t *)pui32Data,
+ ((ui32Options & 0xFF00) >> 8),
+ true,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+
+ //
+ // The I2C bit-bang interface is actually a blocking transfer, and it
+ // doesn't trigger the interrupt handler, so we have to call the
+ // callback function manually.
+ //
+ if ( pfnCallback )
+ {
+ pfnCallback();
+ }
+ //
+ // Return.
+ //
+ return;
+ }
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 256, "I2C transfer too big.");
+
+ ui32MaxFifoSize = ((0 == AM_BFRn(IOMSTR, ui32Module, CFG, FULLDUP)) ?
+ AM_HAL_IOM_MAX_FIFO_SIZE : AM_HAL_IOM_MAX_FIFO_SIZE / 2);
+
+ //
+ // Figure out how many bytes we can write to the FIFO immediately.
+ //
+ ui32TransferSize = (ui32NumBytes <= ui32MaxFifoSize ? ui32NumBytes :
+ ui32MaxFifoSize);
+
+ //
+ // Wait until any earlier transactions have completed, and then write our
+ // first word to the fifo.
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ // Need to mark IOM busy to avoid another transaction to be scheduled.
+ // This is to take care of a race condition in Queue mode, where the IDLE
+ // set is not a guarantee that the CMDCMP has been received
+ g_bIomBusy[ui32Module] = true;
+
+ //
+ // Clear CMDCMP status
+ //
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ if ( am_hal_iom_fifo_write(ui32Module, pui32Data, ui32TransferSize) > 0 )
+ {
+ //
+ // Prepare the global IOM buffer structure.
+ //
+ g_psIOMBuffers[ui32Module].ui32State = BUFFER_SENDING;
+ g_psIOMBuffers[ui32Module].pui32Data = pui32Data;
+ g_psIOMBuffers[ui32Module].ui32BytesLeft = ui32NumBytes;
+ g_psIOMBuffers[ui32Module].pfnCallback = pfnCallback;
+
+ //
+ // Update the pointer and the byte counter based on the portion of the
+ // transfer we just sent to the fifo.
+ //
+ g_psIOMBuffers[ui32Module].ui32BytesLeft -= ui32TransferSize;
+ g_psIOMBuffers[ui32Module].pui32Data += (ui32TransferSize / 4);
+
+ //
+ // Start the write on the bus.
+ //
+ am_hal_iom_i2c_cmd_run(AM_HAL_IOM_WRITE, ui32Module, ui32BusAddress,
+ ui32NumBytes, ui32Options);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Perform a non-blocking I2C read.
+//!
+//! @param ui32Module - Module number for the IOM.
+//! @param ui32ChipSelect - I2C address of the target device.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional I2C transfer options.
+//! @param pfnCallback - Function to call when the transaction completes.
+//!
+//! This function performs an I2C read to a selected I2C device.
+//!
+//! This function call is a non-blocking implementation. It will start the I2C
+//! transaction on the bus and store a pointer for the destination for the read
+//! data, but it will not wait for the I2C transaction to finish. The caller
+//! will need to make sure that \e am_hal_iom_int_service() is called for IOM
+//! FIFO interrupt events and "command complete" interrupt events. The \e
+//! am_hal_iom_int_service() function will empty the FIFO as necessary,
+//! transfer the data to the \e pui32Data buffer, and call the \e pfnCallback
+//! function when the transaction is finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This function will pack the individual bytes from the physical interface
+//! into 32-bit words, which are then placed into the \e pui32Data array. Only
+//! the first \e ui32NumBytes bytes in this array will contain valid data.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_i2c_read_nb(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module > AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Redirect to the bit-bang interface if the module number matches the
+ // software I2C module.
+ //
+ if ( ui32Module == AM_HAL_IOM_I2CBB_MODULE )
+ {
+ if ( ui32Options & AM_HAL_IOM_RAW )
+ {
+ am_hal_i2c_bit_bang_receive((ui32BusAddress << 1) | 1, ui32NumBytes,
+ (uint8_t *)pui32Data, 0, false,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+ else
+ {
+ am_hal_i2c_bit_bang_receive((ui32BusAddress << 1) | 1, ui32NumBytes,
+ (uint8_t *)pui32Data,
+ ((ui32Options & 0xFF00) >> 8),
+ true,
+ (ui32Options & AM_HAL_IOM_NO_STOP));
+ }
+
+ //
+ // The I2C bit-bang interface is actually a blocking transfer, and it
+ // doesn't trigger the interrupt handler, so we have to call the
+ // callback function manually.
+ //
+ if ( pfnCallback )
+ {
+ pfnCallback();
+ }
+
+ //
+ // Return.
+ //
+ return;
+ }
+
+ //
+ // Make sure the transfer isn't too long for the hardware to support.
+ //
+ am_hal_debug_assert_msg(ui32NumBytes < 256, "I2C transfer too big.");
+
+ //
+ // Wait until the bus is idle
+ //
+ am_hal_iom_poll_complete(ui32Module);
+
+ //
+ // Need to mark IOM busy to avoid another transaction to be scheduled.
+ // This is to take care of a race condition in Queue mode, where the IDLE
+ // set is not a guarantee that the CMDCMP has been received
+ //
+ g_bIomBusy[ui32Module] = true;
+
+ //
+ // Clear CMDCMP status
+ //
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, CMDCMP, 1);
+
+ //
+ // Prepare the global IOM buffer structure.
+ //
+ g_psIOMBuffers[ui32Module].ui32State = BUFFER_RECEIVING;
+ g_psIOMBuffers[ui32Module].pui32Data = pui32Data;
+ g_psIOMBuffers[ui32Module].ui32BytesLeft = ui32NumBytes;
+ g_psIOMBuffers[ui32Module].pfnCallback = pfnCallback;
+
+ //
+ // Start the read transaction on the bus.
+ //
+ am_hal_iom_i2c_cmd_run(AM_HAL_IOM_READ, ui32Module, ui32BusAddress,
+ ui32NumBytes, ui32Options);
+}
+
+//*****************************************************************************
+//
+//! @brief Runs a I2C "command" through the IO master.
+//!
+//! @param ui32Operation - I2C action to be performed. This should either be
+//! AM_HAL_IOM_WRITE or AM_HAL_IOM_READ.
+//! @param psDevice - Structure containing information about the slave device.
+//! @param ui32NumBytes - Number of bytes to move (transmit or receive) with
+//! this command.
+//! @param ui32Options - Additional I2C options to apply to this command.
+//!
+//! This function may be used along with am_hal_iom_fifo_write and
+//! am_hal_iom_fifo_read to perform more complex I2C reads and writes. This
+//! function
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_i2c_cmd_run(uint32_t ui32Operation, uint32_t ui32Module,
+ uint32_t ui32BusAddress, uint32_t ui32NumBytes,
+ uint32_t ui32Options)
+{
+ uint32_t ui32Command;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Start building the command from the operation parameter.
+ //
+ ui32Command = ui32Operation;
+
+ //
+ // Set the transfer length.
+ //
+ ui32Command |= (ui32NumBytes & 0xFF);
+
+ //
+ // Set the chip select number.
+ //
+ ui32Command |= ((ui32BusAddress << 16) & 0x03FF0000);
+
+ //
+ // Finally, OR in the rest of the options. This mask should make sure that
+ // erroneous option values won't interfere with the other transfer
+ // parameters.
+ //
+ ui32Command |= (ui32Options & 0x5C00FF00);
+
+ //
+ // Write the complete command word to the IOM command register.
+ //
+ AM_REGn(IOMSTR, ui32Module, CMD) = ui32Command;
+}
+
+//*****************************************************************************
+//
+//! @brief Sets the repeat count for the next IOM command.
+//!
+//! @param ui32Module is the IOM module number.
+//! @param ui32CmdCount is the number of times the next command should be
+//! executed.
+//!
+//! @note This function is not compatible with the am_hal_iom_spi_read/write()
+//! or am_hal_iom_i2c_read/write() functions. Instead, you will need to use the
+//! am_hal_iom_fifo_read/write() functions and the am_hal_iom_spi/i2c_cmd_run()
+//! functions.
+//!
+//! Example usage:
+//! @code
+//!
+//! //
+//! // Create a buffer and add 3 bytes of data to it.
+//! //
+//! am_hal_iom_buffer(3) psBuffer;
+//! psBuffer.bytes[0] = 's';
+//! psBuffer.bytes[1] = 'p';
+//! psBuffer.bytes[2] = 'i';
+//!
+//! //
+//! // Send three different bytes to the same SPI register on a remote device.
+//! //
+//! am_hal_iom_fifo_write(ui32Module, psBuffer.words, 3);
+//!
+//! am_hal_command_repeat_set(ui32Module, 3);
+//!
+//! am_hal_iom_spi_cmd_run(AM_HAL_IOM_WRITE, psDevice, 1,
+//! AM_HAL_IOM_OFFSET(0x5));
+//!
+//! //
+//! // The sequence "0x5, 's', 0x5, 'p', 0x5, 'i'" should be written to the SPI
+//! // bus.
+//! //
+//!
+//! @endcode
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_command_repeat_set(uint32_t ui32Module, uint32_t ui32CmdCount)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ AM_REGn(IOMSTR, ui32Module, CMDRPT) = ui32CmdCount;
+}
+
+//*****************************************************************************
+//
+//! @brief Writes data to the IOM FIFO.
+//!
+//! @param ui32Module - Selects the IOM module to use (zero or one).
+//! @param pui32Data - Pointer to an array of the data to be written.
+//! @param ui32NumBytes - Number of BYTES to copy into the FIFO.
+//!
+//! This function copies data from the array \e pui32Data into the IOM FIFO.
+//! This prepares the data to eventually be sent as SPI or I2C data by an IOM
+//! "command".
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//!
+//! @note This function may be used to write partial or complete SPI or I2C
+//! messages into the IOM FIFO. When writing partial messages to the FIFO, make
+//! sure that the number of bytes written is a multiple of four. Only the last
+//! 'part' of a message may consist of a number of bytes that is not a multiple
+//! of four. If this rule is not followed, the IOM will not be able to send
+//! these bytes correctly.
+//!
+//! @return Number of bytes actually written to the FIFO.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_fifo_write(uint32_t ui32Module, uint32_t *pui32Data,
+ uint32_t ui32NumBytes)
+{
+ uint32_t ui32Index;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ //
+ // Make sure we check the number of bytes we're writing to the FIFO.
+ //
+ am_hal_debug_assert_msg((am_hal_iom_fifo_empty_slots(ui32Module) >= ui32NumBytes),
+ "The fifo couldn't fit the requested number of bytes");
+
+ //
+ // Loop over the words in the array until we have the correct number of
+ // bytes.
+ //
+ for ( ui32Index = 0; (4 * ui32Index) < ui32NumBytes; ui32Index++ )
+ {
+ //
+ // Write the word to the FIFO.
+ //
+ AM_REGn(IOMSTR, ui32Module, FIFO) = pui32Data[ui32Index];
+ }
+
+ return ui32NumBytes;
+}
+
+//*****************************************************************************
+//
+//! @brief Reads data from the IOM FIFO.
+//!
+//! @param ui32Module - Selects the IOM module to use (zero or one).
+//! @param pui32Data - Pointer to an array where the FIFO data will be copied.
+//! @param ui32NumBytes - Number of bytes to copy into array.
+//!
+//! This function copies data from the IOM FIFO into the array \e pui32Data.
+//! This is how input data from SPI or I2C transactions may be retrieved.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This function will pack the individual bytes from the physical interface
+//! into 32-bit words, which are then placed into the \e pui32Data array. Only
+//! the first \e ui32NumBytes bytes in this array will contain valid data.
+//!
+//! @return Number of bytes read from the fifo.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_fifo_read(uint32_t ui32Module, uint32_t *pui32Data,
+ uint32_t ui32NumBytes)
+{
+ am_hal_iom_buffer(4) sTempBuffer;
+ uint32_t i, j, ui32NumWords, ui32Leftovers;
+ uint8_t *pui8Data;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ //
+ // Make sure we check the number of bytes we're reading from the FIFO.
+ //
+ am_hal_debug_assert_msg((am_hal_iom_fifo_full_slots(ui32Module) >= ui32NumBytes),
+ "The fifo doesn't contain the requested number of bytes.");
+
+ //
+ // Figure out how many whole words we're reading from the fifo, and how
+ // many bytes will be left over when we're done.
+ //
+ ui32NumWords = ui32NumBytes / 4;
+ ui32Leftovers = ui32NumBytes - (ui32NumWords * 4);
+
+ //
+ // Copy out as many full words as we can.
+ //
+ for ( i = 0; i < ui32NumWords; i++ )
+ {
+ //
+ // Copy data out of the FIFO, one word at a time.
+ //
+ pui32Data[i] = AM_REGn(IOMSTR, ui32Module, FIFO);
+ }
+
+ //
+ // If there were leftovers, we'll copy them carefully. Pull the last word
+ // from the fifo (there should only be one) into a temporary buffer. Also,
+ // create an 8-bit pointer to help us copy the remaining bytes one at a
+ // time.
+ //
+ // Note: If the data buffer we were given was truly a word pointer like the
+ // definition requests, we wouldn't need to do this. It's possible to call
+ // this function with a re-cast or packed pointer instead though. If that
+ // happens, we want to be careful not to overwrite any data that might be
+ // sitting just past the end of the destination array.
+ //
+ if ( ui32Leftovers )
+ {
+ sTempBuffer.words[0] = AM_REGn(IOMSTR, ui32Module, FIFO);
+ pui8Data = (uint8_t *) (&pui32Data[i]);
+
+ //
+ // If we had leftover bytes, copy them out one byte at a time.
+ //
+ for ( j = 0; j < ui32Leftovers; j++ )
+ {
+ pui8Data[j] = sTempBuffer.bytes[j];
+ }
+ }
+
+ return ui32NumBytes;
+}
+
+//*****************************************************************************
+//
+//! @brief Check amount of empty space in the IOM fifo.
+//!
+//! @param ui32Module - Module number of the IOM whose fifo should be checked.
+//!
+//! Returns the number of bytes that could be written to the IOM fifo without
+//! causing an overflow.
+//!
+//! @return Amount of space available in the fifo (in bytes).
+//
+//*****************************************************************************
+uint8_t
+am_hal_iom_fifo_empty_slots(uint32_t ui32Module)
+{
+ uint32_t ui32MaxFifoSize;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ ui32MaxFifoSize = ((0 == AM_BFRn(IOMSTR, ui32Module, CFG, FULLDUP)) ? AM_HAL_IOM_MAX_FIFO_SIZE : AM_HAL_IOM_MAX_FIFO_SIZE / 2);
+
+ //
+ // Calculate the FIFO Remaining from the FIFO size. This will be different
+ // depending on whether the IOM is configured for half-duplex or
+ // full-duplex.
+ //
+ return (ui32MaxFifoSize - AM_BFRn(IOMSTR, ui32Module, FIFOPTR, FIFOSIZ)) & (~0x3);
+}
+
+//*****************************************************************************
+//
+//! @brief Check to see how much data is in the IOM fifo.
+//!
+//! @param ui32Module - Module number of the IOM whose fifo should be checked.
+//!
+//! Returns the number of bytes of data that are currently in the IOM fifo.
+//!
+//! @return Number of bytes in the fifo.
+//
+//*****************************************************************************
+uint8_t
+am_hal_iom_fifo_full_slots(uint32_t ui32Module)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ return AM_BFRn(IOMSTR, ui32Module, FIFOPTR, FIFOSIZ);
+}
+
+//*****************************************************************************
+//
+//! @brief Wait for the current IOM command to complete.
+//!
+//! @param ui32Module - The module number of the IOM to use.
+//!
+//! This function polls until the IOM bus becomes idle.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_poll_complete(uint32_t ui32Module)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ //
+ // Poll on the IDLE bit in the status register.
+ //
+ while ( g_bIomBusy[ui32Module] );
+}
+
+//*****************************************************************************
+//
+//! @brief Returns the contents of the IOM status register.
+//!
+//! @param ui32Module IOM instance to check the status of.
+//!
+//! This function is just a wrapper around the IOM status register.
+//!
+//! @return 32-bit contents of IOM status register.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_status_get(uint32_t ui32Module)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ return AM_REGn(IOMSTR, ui32Module, STATUS);
+}
+
+//*****************************************************************************
+//
+//! @brief Returns current error state of the IOM.
+//!
+//! @param ui32Module IOM instance to check the status of.
+//!
+//! This function returns status indicating whether the IOM has incurred any
+//! errors or not.
+//!
+//! @return 0 if all is well.
+//! Otherwise error status as a bitmask of:
+//! AM_HAL_IOM_ERR_INVALID_MODULE
+//! AM_HAL_IOM_INT_ARB Another master initiated an operation
+//! simultaenously and the IOM lost. Or
+//! the IOM started an operation but found
+//! SDA already low.
+//! AM_HAL_IOM_INT_START A START from another master detected.
+//! SW must wait for STOP before continuing.
+//! AM_HAL_IOM_INT_ICMD Attempt to issue a CMD while another
+//! CMD was already in progress, or issue a
+//! non-zero-len write CMD with empty FIFO.
+//! AM_HAL_IOM_INT_IACC Attempt to read the FIFO on a write. Or
+//! an attempt to write the FIFO on a read.
+//! AM_HAL_IOM_INT_NAK Expected ACK from slave not received.
+//! AM_HAL_IOM_INT_FOVFL Attempt to write the FIFO while full
+//! (FIFOSIZ > 124).
+//! AM_HAL_IOM_INT_FUNDFL Attempt to read FIFO when empty (that is
+//! FIFOSIZ < 4).
+//! Note - see the datasheet text for full explanations of the INT errs.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_error_status_get(uint32_t ui32Module)
+{
+ uint32_t ui32intstat = 0;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ //
+ // AM_HAL_IOM_ERR_INVALID_MODULE is defined as an unused interrupt bit.
+ //
+ return AM_HAL_IOM_ERR_INVALID_MODULE;
+ }
+
+ if ( AM_REGn(IOMSTR, ui32Module, STATUS) & AM_REG_IOMSTR_STATUS_ERR_ERROR )
+ {
+ //
+ // The IOM is currently indicating an error condition.
+ // Let's figure out what is going on.
+ //
+ ui32intstat = AM_REGn(IOMSTR, ui32Module, INTSTAT);
+
+ //
+ // Filter out non-error bits.
+ //
+ ui32intstat &= AM_REG_IOMSTR_INTSTAT_ARB_M |
+ AM_REG_IOMSTR_INTSTAT_START_M |
+ AM_REG_IOMSTR_INTSTAT_ICMD_M |
+ AM_REG_IOMSTR_INTSTAT_IACC_M |
+ AM_REG_IOMSTR_INTSTAT_NAK_M |
+ AM_REG_IOMSTR_INTSTAT_FOVFL_M |
+ AM_REG_IOMSTR_INTSTAT_FUNDFL_M;
+ }
+
+ return ui32intstat;
+}
+
+//*****************************************************************************
+//
+//! @brief Service interrupts from the IOM.
+//!
+//! @param ui32Status is the IOM interrupt status as returned from
+//! am_hal_iom_int_status_get()
+//!
+//! This function performs the necessary operations to facilitate non-blocking
+//! IOM writes and reads.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_iom_int_service(uint32_t ui32Module, uint32_t ui32Status)
+{
+ am_hal_iom_nb_buffer *psBuffer;
+ uint32_t ui32NumBytes;
+ uint32_t ui32SpaceInFifo;
+ uint32_t thresh;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ //
+ // Find the buffer information for the chosen IOM module.
+ //
+ psBuffer = &g_psIOMBuffers[ui32Module];
+
+ //
+ // Figure out what type of interrupt this was.
+ //
+ if ( ui32Status & AM_HAL_IOM_INT_CMDCMP )
+ {
+ //
+ // Need to mark IOM Free
+ //
+ g_bIomBusy[ui32Module] = false;
+
+ //
+ // If we're not in the middle of a non-blocking call right now, there's
+ // nothing for this routine to do.
+ //
+ if ( psBuffer->ui32State == BUFFER_IDLE )
+ {
+ return;
+ }
+
+ //
+ // If a command just completed, we need to transfer all available data.
+ //
+ if ( psBuffer->ui32State == BUFFER_RECEIVING )
+ {
+ //
+ // If we were receiving, we need to copy any remaining data out of
+ // the IOM FIFO before calling the callback.
+ //
+ ui32NumBytes = am_hal_iom_fifo_full_slots(ui32Module);
+ am_hal_iom_fifo_read(ui32Module, psBuffer->pui32Data, ui32NumBytes);
+ }
+
+ //
+ // A command complete event also means that we've already transferred
+ // all of the data we need, so we can mark the data buffer as IDLE.
+ //
+ psBuffer->ui32State = BUFFER_IDLE;
+
+ //
+ // If we have a callback, call it now.
+ //
+ if ( psBuffer->pfnCallback )
+ {
+ psBuffer->pfnCallback();
+ }
+ }
+ else if ( ui32Status & AM_HAL_IOM_INT_THR )
+ {
+ //
+ // If we're not in the middle of a non-blocking call right now, there's
+ // nothing for this routine to do.
+ //
+ if ( psBuffer->ui32State == BUFFER_IDLE )
+ {
+ return;
+ }
+ //
+ // If we received a threshold event in the middle of a command, we need
+ // to transfer data.
+ //
+ if ( psBuffer->ui32State == BUFFER_SENDING )
+ {
+ thresh = AM_BFRn(IOMSTR, ui32Module, FIFOTHR, FIFOWTHR);
+ do
+ {
+ ui32SpaceInFifo = am_hal_iom_fifo_empty_slots(ui32Module);
+
+ //
+ // Figure out how much data we can send.
+ //
+ if ( psBuffer->ui32BytesLeft <= ui32SpaceInFifo )
+ {
+ //
+ // If the whole transfer will fit in the fifo, send it all.
+ //
+ ui32NumBytes = psBuffer->ui32BytesLeft;
+ }
+ else
+ {
+ //
+ // If the transfer won't fit in the fifo completely, send as
+ // much as we can (rounded down to a multiple of four bytes).
+ //
+ ui32NumBytes = ui32SpaceInFifo;
+ }
+
+ //
+ // Perform the transfer.
+ //
+ am_hal_iom_fifo_write(ui32Module, psBuffer->pui32Data, ui32NumBytes);
+
+ // Clear any spurious THR interrupt that might have got raised
+ // while we were adding data to FIFO
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, THR, 1);
+ //
+ // Update the pointer and the byte counter.
+ //
+ psBuffer->ui32BytesLeft -= ui32NumBytes;
+ psBuffer->pui32Data += (ui32NumBytes / 4);
+
+ if ( 0 == psBuffer->ui32BytesLeft )
+ {
+ //
+ // Done with this transaction
+ //
+ break;
+ }
+ } while ( am_hal_iom_fifo_full_slots(ui32Module) <= thresh );
+ }
+ else
+ {
+ thresh = AM_BFRn(IOMSTR, ui32Module, FIFOTHR, FIFORTHR);
+ while ( (ui32NumBytes = am_hal_iom_fifo_full_slots(ui32Module)) >= thresh )
+ {
+ //
+ // If we get here, we're in the middle of a read. Transfer as much
+ // data as possible out of the FIFO and into our buffer.
+ //
+ if ( ui32NumBytes == psBuffer->ui32BytesLeft )
+ {
+ //
+ // If the fifo contains our entire message, just copy the whole
+ // thing out.
+ //
+ am_hal_iom_fifo_read(ui32Module, psBuffer->pui32Data,
+ psBuffer->ui32BytesLeft);
+
+ break;
+ }
+ else if ( ui32NumBytes >= 4 )
+ {
+ //
+ // If the fifo has at least one 32-bit word in it, copy out the
+ // biggest block we can.
+ //
+ ui32NumBytes = (ui32NumBytes & (~0x3));
+
+ am_hal_iom_fifo_read(ui32Module, psBuffer->pui32Data, ui32NumBytes);
+
+ //
+ // Update the pointer and the byte counter.
+ //
+ psBuffer->ui32BytesLeft -= ui32NumBytes;
+ psBuffer->pui32Data += (ui32NumBytes / 4);
+
+ // Clear any spurious THR interrupt that might have got raised
+ // while we were reading the data from FIFO
+ AM_BFWn(IOMSTR, ui32Module, INTCLR, THR, 1);
+ }
+ }
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Initialize the IOM queue system.
+//!
+//! @param ui32Module - IOM module to be initialized for queue transfers.
+//! @param psQueueMemory - Memory to be used for queueing IOM transfers.
+//! @param ui32QueueMemSize - Size of the queue memory.
+//!
+//! This function prepares the selected IOM interface for use with the IOM
+//! queue system. The IOM queue system allows the caller to start multiple IOM
+//! transfers in a non-blocking way. In order to do this, the HAL requires some
+//! amount of memory dedicated to keeping track of IOM transactions before they
+//! can be sent to the hardware registers. This function tells the HAL what
+//! memory it should use for this purpose. For more information on the IOM
+//! queue interface, please see the documentation for
+//! am_hal_iom_queue_spi_write().
+//!
+//! @note This function only needs to be called once (per module), but it must
+//! be called before any other am_hal_iom_queue function.
+//!
+//! @note Each IOM module will need its own working space. If you intend to use
+//! the queueing mechanism with more than one IOM module, you will need to
+//! provide separate queue memory for each module.
+//!
+//! Example usage:
+//!
+//! @code
+//!
+//! //
+//! // Declare an array to be used for IOM queue transactions. This array will
+//! // be big enough to handle 32 IOM transactions.
+//! //
+//! am_hal_iom_queue_entry_t g_psQueueMemory[32];
+//!
+//! //
+//! // Attach the IOM0 queue system to the memory we just allocated.
+//! //
+//! am_hal_iom_queue_init(0, g_psQueueMemory, sizeof(g_psQueueMemory));
+//!
+//! @endcode
+//
+//*****************************************************************************
+void
+am_hal_iom_queue_init(uint32_t ui32Module, am_hal_iom_queue_entry_t *psQueueMemory,
+ uint32_t ui32QueueMemSize)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ am_hal_queue_init(&g_psIOMQueue[ui32Module], psQueueMemory,
+ sizeof(am_hal_iom_queue_entry_t), ui32QueueMemSize);
+}
+
+//*****************************************************************************
+//
+//! @brief Check to see how many transactions are in the queue.
+//!
+//! @param ui32Module Module number for the queue to check
+//!
+//! This function will check to see how many transactions are in the IOM queue
+//! for the selected IOM module.
+//!
+//! @return Number of transactions in the queue.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_queue_length_get(uint32_t ui32Module)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ return am_hal_queue_data_left(&g_psIOMQueue[ui32Module]);
+}
+
+//*****************************************************************************
+//
+//! @brief Executes the next operation in the IOM queue.
+//!
+//! @param ui32ModuleNum - Module number for the IOM to use.
+//!
+//! This function checks the IOM queue to see if there are any remaining
+//! transactions. If so, it will start the next available transaction in a
+//! non-blocking way.
+//!
+//! @note This function is called automatically by am_hal_iom_queue_service().
+//! You should not call this function standalone in a normal application.
+//
+//*****************************************************************************
+void
+am_hal_iom_queue_start_next_msg(uint32_t ui32Module)
+{
+ am_hal_iom_queue_entry_t sIOMTransaction = {0};
+
+ uint32_t ui32ChipSelect;
+ uint32_t *pui32Data;
+ uint32_t ui32NumBytes;
+ uint32_t ui32Options;
+ am_hal_iom_callback_t pfnCallback;
+
+ uint32_t ui32Critical;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ //
+ // Start a critical section.
+ //
+ ui32Critical = am_hal_interrupt_master_disable();
+
+ //
+ // Try to get the next IOM operation from the queue.
+ //
+ if ( am_hal_queue_item_get(&g_psIOMQueue[ui32Module], &sIOMTransaction, 1) )
+ {
+ //
+ // Read the operation parameters
+ //
+ ui32ChipSelect = sIOMTransaction.ui32ChipSelect;
+ pui32Data = sIOMTransaction.pui32Data;
+ ui32NumBytes = sIOMTransaction.ui32NumBytes;
+ ui32Options = sIOMTransaction.ui32Options;
+ pfnCallback = sIOMTransaction.pfnCallback;
+
+ //
+ // Figure out if this was a SPI or I2C write or read, and call the
+ // appropriate non-blocking function.
+ //
+ switch ( sIOMTransaction.ui32Operation )
+ {
+ case AM_HAL_IOM_QUEUE_SPI_WRITE:
+ am_hal_iom_spi_write_nb(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ break;
+
+ case AM_HAL_IOM_QUEUE_SPI_READ:
+ am_hal_iom_spi_read_nb(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ break;
+
+ case AM_HAL_IOM_QUEUE_I2C_WRITE:
+ am_hal_iom_i2c_write_nb(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ break;
+
+ case AM_HAL_IOM_QUEUE_I2C_READ:
+ am_hal_iom_i2c_read_nb(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ break;
+ }
+ }
+
+ //
+ // Exit the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Critical);
+}
+
+//*****************************************************************************
+//
+//! @brief Send a SPI frame using the IOM queue.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32ChipSelect - Chip-select number for this transaction.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional SPI transfer options.
+//!
+//! This function performs SPI writes to a selected SPI device.
+//!
+//! This function call is a queued implementation. It will write as much
+//! data to the FIFO as possible immediately, store a pointer to the remaining
+//! data, start the transfer on the bus, and then immediately return. If the
+//! FIFO is already in use, this function will save its arguments to the IOM
+//! queue and execute the transaction when the FIFO becomes available.
+//!
+//! The caller will need to make sure that \e am_hal_iom_queue_service() is
+//! called for IOM FIFO interrupt events and "command complete" interrupt
+//! events. The \e am_hal_iom_queue_service() function will refill the FIFO as
+//! necessary and call the \e pfnCallback function when the transaction is
+//! finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//
+//*****************************************************************************
+void
+am_hal_iom_queue_spi_write(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options, am_hal_iom_callback_t pfnCallback)
+{
+ uint32_t ui32Critical;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Start a critical section.
+ //
+ ui32Critical = am_hal_interrupt_master_disable();
+
+ //
+ // Check to see if we need to use the queue. If the IOM is idle, and
+ // there's nothing in the queue already, we can go ahead and start the
+ // transaction in the physical IOM. Need to check for the g_bIomBusy to
+ // avoid a race condition where IDLE is set - but the command complete
+ // for previous transaction has not been processed yet
+ //
+ if ( (g_bIomBusy[ui32Module] == false) &&
+ am_hal_queue_empty(&g_psIOMQueue[ui32Module]) )
+ {
+ //
+ // Send the packet.
+ //
+ am_hal_iom_spi_write_nb(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ }
+ else
+ {
+ //
+ // Otherwise, we'll build a transaction structure and add it to the queue.
+ //
+ am_hal_iom_queue_entry_t sIOMTransaction;
+
+ sIOMTransaction.ui32Operation = AM_HAL_IOM_QUEUE_SPI_WRITE;
+ sIOMTransaction.ui32Module = ui32Module;
+ sIOMTransaction.ui32ChipSelect = ui32ChipSelect;
+ sIOMTransaction.pui32Data = pui32Data;
+ sIOMTransaction.ui32NumBytes = ui32NumBytes;
+ sIOMTransaction.ui32Options = ui32Options;
+ sIOMTransaction.pfnCallback = pfnCallback;
+
+ //
+ // Make sure the item actually makes it into the queue
+ //
+ if ( am_hal_queue_item_add(&g_psIOMQueue[ui32Module], &sIOMTransaction, 1) == false )
+ {
+ //
+ // Didn't have enough memory.
+ //
+ am_hal_debug_assert_msg(0,
+ "The IOM queue is full. Allocate more"
+ "memory to the IOM queue, or allow it more"
+ "time to empty between transactions.");
+ }
+ }
+
+ //
+ // Exit the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Critical);
+}
+
+//*****************************************************************************
+//
+//! @brief Read a SPI frame using the IOM queue.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32ChipSelect - Chip select number for this transaction.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional SPI transfer options.
+//!
+//! This function performs SPI reads to a selected SPI device.
+//!
+//! This function call is a queued implementation. It will write as much
+//! data to the FIFO as possible immediately, store a pointer to the remaining
+//! data, start the transfer on the bus, and then immediately return. If the
+//! FIFO is already in use, this function will save its arguments to the IOM
+//! queue and execute the transaction when the FIFO becomes available.
+//!
+//! The caller will need to make sure that \e am_hal_iom_queue_service() is
+//! called for IOM FIFO interrupt events and "command complete" interrupt
+//! events. The \e am_hal_iom_queue_service() function will empty the FIFO as
+//! necessary and call the \e pfnCallback function when the transaction is
+//! finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//
+//*****************************************************************************
+void
+am_hal_iom_queue_spi_read(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options, am_hal_iom_callback_t pfnCallback)
+{
+ uint32_t ui32Critical;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ // Start a critical section.
+ //
+ ui32Critical = am_hal_interrupt_master_disable();
+
+ //
+ // Check to see if we need to use the queue. If the IOM is idle, and
+ // there's nothing in the queue already, we can go ahead and start the
+ // transaction in the physical IOM. Need to check for the g_bIomBusy to
+ // avoid a race condition where IDLE is set - but the command complete
+ // for previous transaction has not been processed yet
+ //
+ if ( (g_bIomBusy[ui32Module] == false) &&
+ am_hal_queue_empty(&g_psIOMQueue[ui32Module]) )
+ {
+ //
+ // Send the packet.
+ //
+ am_hal_iom_spi_read_nb(ui32Module, ui32ChipSelect, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ }
+ else
+ {
+ //
+ // Otherwise, we'll build a transaction structure and add it to the queue.
+ //
+ am_hal_iom_queue_entry_t sIOMTransaction;
+
+ sIOMTransaction.ui32Operation = AM_HAL_IOM_QUEUE_SPI_READ;
+ sIOMTransaction.ui32Module = ui32Module;
+ sIOMTransaction.ui32ChipSelect = ui32ChipSelect;
+ sIOMTransaction.pui32Data = pui32Data;
+ sIOMTransaction.ui32NumBytes = ui32NumBytes;
+ sIOMTransaction.ui32Options = ui32Options;
+ sIOMTransaction.pfnCallback = pfnCallback;
+
+ //
+ // Make sure the item actually makes it into the queue
+ //
+ if ( am_hal_queue_item_add(&g_psIOMQueue[ui32Module], &sIOMTransaction, 1) == false )
+ {
+ //
+ // Didn't have enough memory.
+ //
+ am_hal_debug_assert_msg(0,
+ "The IOM queue is full. Allocate more"
+ "memory to the IOM queue, or allow it more"
+ "time to empty between transactions.");
+ }
+ }
+
+ //
+ // Exit the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Critical);
+}
+
+//*****************************************************************************
+//
+//! @brief Send an I2C frame using the IOM queue.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32BusAddress - I2C address of the target device.
+//! @param pui32Data - Pointer to the bytes that will be sent.
+//! @param ui32NumBytes - Number of bytes to send.
+//! @param ui32Options - Additional I2C transfer options.
+//!
+//! This function performs I2C writes to a selected I2C device.
+//!
+//! This function call is a queued implementation. It will write as much
+//! data to the FIFO as possible immediately, store a pointer to the remaining
+//! data, start the transfer on the bus, and then immediately return. If the
+//! FIFO is already in use, this function will save its arguments to the IOM
+//! queue and execute the transaction when the FIFO becomes available.
+//!
+//! The caller will need to make sure that \e am_hal_iom_queue_service() is
+//! called for IOM FIFO interrupt events and "command complete" interrupt
+//! events. The \e am_hal_iom_queue_service() function will refill the FIFO as
+//! necessary and call the \e pfnCallback function when the transaction is
+//! finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//
+//*****************************************************************************
+void
+am_hal_iom_queue_i2c_write(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options, am_hal_iom_callback_t pfnCallback)
+{
+ uint32_t ui32Critical;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Start a critical section.
+ //
+ ui32Critical = am_hal_interrupt_master_disable();
+
+ //
+ // Check to see if we need to use the queue. If the IOM is idle, and
+ // there's nothing in the queue already, we can go ahead and start the
+ // transaction in the physical IOM. Need to check for the g_bIomBusy to
+ // avoid a race condition where IDLE is set - but the command complete
+ // for previous transaction has not been processed yet
+ //
+ if ( (g_bIomBusy[ui32Module] == false) &&
+ am_hal_queue_empty(&g_psIOMQueue[ui32Module]) )
+ {
+ //
+ // Send the packet.
+ //
+ am_hal_iom_i2c_write_nb(ui32Module, ui32BusAddress, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ }
+ else
+ {
+ //
+ // Otherwise, we'll build a transaction structure and add it to the queue.
+ //
+ am_hal_iom_queue_entry_t sIOMTransaction;
+
+ sIOMTransaction.ui32Operation = AM_HAL_IOM_QUEUE_I2C_WRITE;
+ sIOMTransaction.ui32Module = ui32Module;
+ sIOMTransaction.ui32ChipSelect = ui32BusAddress;
+ sIOMTransaction.pui32Data = pui32Data;
+ sIOMTransaction.ui32NumBytes = ui32NumBytes;
+ sIOMTransaction.ui32Options = ui32Options;
+ sIOMTransaction.pfnCallback = pfnCallback;
+
+ //
+ // Make sure the item actually makes it into the queue
+ //
+ if ( am_hal_queue_item_add(&g_psIOMQueue[ui32Module], &sIOMTransaction, 1) == false )
+ {
+ //
+ // Didn't have enough memory.
+ //
+ am_hal_debug_assert_msg(0,
+ "The IOM queue is full. Allocate more"
+ "memory to the IOM queue, or allow it more"
+ "time to empty between transactions.");
+ }
+ }
+
+ //
+ // Exit the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Critical);
+}
+
+//*****************************************************************************
+//
+//! @brief Read a I2C frame using the IOM queue.
+//!
+//! @param ui32Module - Module number for the IOM
+//! @param ui32BusAddress - I2C address of the target device.
+//! @param pui32Data - Pointer to the array where received bytes should go.
+//! @param ui32NumBytes - Number of bytes to read.
+//! @param ui32Options - Additional I2C transfer options.
+//!
+//! This function performs I2C reads to a selected I2C device.
+//!
+//! This function call is a queued implementation. It will write as much
+//! data to the FIFO as possible immediately, store a pointer to the remaining
+//! data, start the transfer on the bus, and then immediately return. If the
+//! FIFO is already in use, this function will save its arguments to the IOM
+//! queue and execute the transaction when the FIFO becomes available.
+//!
+//! The caller will need to make sure that \e am_hal_iom_queue_service() is
+//! called for IOM FIFO interrupt events and "command complete" interrupt
+//! events. The \e am_hal_iom_queue_service() function will empty the FIFO as
+//! necessary and call the \e pfnCallback function when the transaction is
+//! finished.
+//!
+//! @note The actual SPI and I2C interfaces operate in BYTES, not 32-bit words.
+//! This means that you will need to byte-pack the \e pui32Data array with the
+//! data you intend to send over the interface. One easy way to do this is to
+//! declare the array as a 32-bit integer array, but use an 8-bit pointer to
+//! put your actual data into the array. If there are not enough bytes in your
+//! desired message to completely fill the last 32-bit word, you may pad that
+//! last word with bytes of any value. The IOM hardware will only read the
+//! first \e ui32NumBytes in the \e pui8Data array.
+//
+//*****************************************************************************
+void
+am_hal_iom_queue_i2c_read(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options, am_hal_iom_callback_t pfnCallback)
+{
+ uint32_t ui32Critical;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+ am_hal_debug_assert_msg(ui32NumBytes > 0,
+ "Trying to do a 0 byte transaction");
+
+ //
+ // Start a critical section.
+ //
+ ui32Critical = am_hal_interrupt_master_disable();
+
+ //
+ // Check to see if we need to use the queue. If the IOM is idle, and
+ // there's nothing in the queue already, we can go ahead and start the
+ // transaction in the physical IOM. Need to check for the g_bIomBusy to
+ // avoid a race condition where IDLE is set - but the command complete
+ // for previous transaction has not been processed yet
+ //
+ if ( (g_bIomBusy[ui32Module] == false) &&
+ am_hal_queue_empty(&g_psIOMQueue[ui32Module]) )
+ {
+ //
+ // Send the packet.
+ //
+ am_hal_iom_i2c_read_nb(ui32Module, ui32BusAddress, pui32Data,
+ ui32NumBytes, ui32Options, pfnCallback);
+ }
+ else
+ {
+ //
+ // Otherwise, we'll build a transaction structure and add it to the queue.
+ //
+ am_hal_iom_queue_entry_t sIOMTransaction;
+
+ sIOMTransaction.ui32Operation = AM_HAL_IOM_QUEUE_I2C_READ;
+ sIOMTransaction.ui32Module = ui32Module;
+ sIOMTransaction.ui32ChipSelect = ui32BusAddress;
+ sIOMTransaction.pui32Data = pui32Data;
+ sIOMTransaction.ui32NumBytes = ui32NumBytes;
+ sIOMTransaction.ui32Options = ui32Options;
+ sIOMTransaction.pfnCallback = pfnCallback;
+
+ //
+ // Make sure the item actually makes it into the queue
+ //
+ if ( am_hal_queue_item_add(&g_psIOMQueue[ui32Module], &sIOMTransaction, 1) == false )
+ {
+ //
+ // Didn't have enough memory.
+ //
+ am_hal_debug_assert_msg(0, "The IOM queue is full. Allocate more"
+ "memory to the IOM queue, or allow it more"
+ "time to empty between transactions.");
+ }
+ }
+
+ //
+ // Exit the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Critical);
+}
+
+//*****************************************************************************
+//
+//! @brief "Block" until the queue of IOM transactions is over.
+//!
+//! @param ui32Module - Module number for the IOM.
+//!
+//! This function will sleep the core block until the queue for the selected
+//! IOM is empty. This is mainly useful for non-RTOS applications where the
+//! caller needs to know that a certain IOM transaction is complete before
+//! continuing with the main program flow.
+//!
+//! @note This function will put the core to sleep while it waits for the
+//! queued IOM transactions to complete. This will save power, in most
+//! situations, but it may not be the best option in all cases. \e Do \e not
+//! call this function from interrupt context (the core may not wake up again).
+//! \e Be \e careful using this function from an RTOS task (many RTOS
+//! implementations use hardware interrupts to switch contexts, and most RTOS
+//! implementations expect to control sleep behavior).
+//
+//*****************************************************************************
+void
+am_hal_iom_sleeping_queue_flush(uint32_t ui32Module)
+{
+ bool bWaiting = true;
+ uint32_t ui32Critical;
+
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ //
+ // Loop forever waiting for the IOM to be idle and the queue to be empty.
+ //
+ while ( bWaiting )
+ {
+ //
+ // Start a critical section.
+ //
+ ui32Critical = am_hal_interrupt_master_disable();
+
+ //
+ // Check the queue and the IOM itself.
+ //
+ if ( (g_bIomBusy[ui32Module] == false) &&
+ am_hal_queue_empty(&g_psIOMQueue[ui32Module]) )
+ {
+ //
+ // If the queue is empty and the IOM is idle, we can go ahead and
+ // return.
+ //
+ bWaiting = false;
+ }
+ else
+ {
+ //
+ // Otherwise, we should sleep until the interface is actually free.
+ //
+ am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_NORMAL);
+ }
+
+ //
+ // End the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Critical);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Service IOM transaction queue.
+//!
+//! @param ui32Module - Module number for the IOM to be used.
+//! @param ui32Status - Interrupt status bits for the IOM module being used.
+//!
+//! This function handles the operation of FIFOs and the IOM queue during
+//! queued IOM transactions. If you are using \e am_hal_iom_queue_spi_write()
+//! or similar functions, you will need to call this function in your interrupt
+//! handler.
+//!
+//! @note This interrupt service routine relies on the user to enable the IOM
+//! interrupts for FIFO threshold and CMD complete.
+//!
+//! Example:
+//!
+//! @code
+//! void
+//! am_iomaster0_isr(void)
+//! {
+//! uint32_t ui32Status;
+//!
+//! //
+//! // Check to see which interrupt caused us to enter the ISR.
+//! //
+//! ui32Status = am_hal_iom_int_status(0, true);
+//!
+//! //
+//! // Fill or empty the FIFO, and either continue the current operation or
+//! // start the next one in the queue. If there was a callback, it will be
+//! // called here.
+//! //
+//! am_hal_iom_queue_service(0, ui32Status);
+//!
+//! //
+//! // Clear the interrupts before leaving the ISR.
+//! //
+//! am_hal_iom_int_clear(ui32Status);
+//! }
+//! @endcode
+//!
+//! @return
+//
+//*****************************************************************************
+void
+am_hal_iom_queue_service(uint32_t ui32Module, uint32_t ui32Status)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ //
+ // Service the FIFOs in case this was a threshold interrupt.
+ //
+ am_hal_iom_int_service(ui32Module, ui32Status);
+
+ //
+ // If the last interrupt was a "command complete", then the IOM should be
+ // idle already or very soon. Make absolutely sure that the IOM is not in
+ // use, and then start the next transaction in the queue.
+ //
+ if ( ui32Status & AM_HAL_IOM_INT_CMDCMP )
+ {
+ if ( g_psIOMQueue[ui32Module].pui8Data != NULL )
+ {
+ am_hal_iom_queue_start_next_msg(ui32Module);
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Enable selected IOM Interrupts.
+//!
+//! @param ui32Module - Module number.
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_iom.h
+//!
+//! Use this function to enable the IOM interrupts.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_iom_int_enable(uint32_t ui32Module, uint32_t ui32Interrupt)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ AM_REGn(IOMSTR, ui32Module, INTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return the enabled IOM Interrupts.
+//!
+//! @param ui32Module - Module number.
+//!
+//! Use this function to return all enabled IOM interrupts.
+//!
+//! @return all enabled IOM interrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_int_enable_get(uint32_t ui32Module)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ return AM_REGn(IOMSTR, ui32Module, INTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable selected IOM Interrupts.
+//!
+//! @param ui32Module - Module number.
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_iom.h
+//!
+//! Use this function to disable the IOM interrupts.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_iom_int_disable(uint32_t ui32Module, uint32_t ui32Interrupt)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ AM_REGn(IOMSTR, ui32Module, INTEN) &= ~ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Clear selected IOM Interrupts.
+//!
+//! @param ui32Module - Module number.
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_iom.h
+//!
+//! Use this function to clear the IOM interrupts.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_iom_int_clear(uint32_t ui32Module, uint32_t ui32Interrupt)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ AM_REGn(IOMSTR, ui32Module, INTCLR) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Set selected IOM Interrupts.
+//!
+//! @param ui32Module - Module number.
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_iom.h
+//!
+//! Use this function to set the IOM interrupts.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_iom_int_set(uint32_t ui32Module, uint32_t ui32Interrupt)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return;
+ }
+
+ AM_REGn(IOMSTR, ui32Module, INTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return the IOM Interrupt status.
+//!
+//! @param ui32Module - Module number.
+//! @param bEnabledOnly - return only the enabled interrupts.
+//!
+//! Use this function to get the IOM interrupt status.
+//!
+//! @return interrupt status
+//
+//*****************************************************************************
+uint32_t
+am_hal_iom_int_status_get(uint32_t ui32Module, bool bEnabledOnly)
+{
+ //
+ // Validate parameters
+ //
+ if ( ui32Module >= AM_REG_IOMSTR_NUM_MODULES )
+ {
+ return 0;
+ }
+
+ if ( bEnabledOnly )
+ {
+ uint32_t u32RetVal = AM_REGn(IOMSTR, ui32Module, INTSTAT);
+ return u32RetVal & AM_REGn(IOMSTR, ui32Module, INTEN);
+ }
+ else
+ {
+ return AM_REGn(IOMSTR, ui32Module, INTSTAT);
+ }
+}
+
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_iom.h b/bsp/apollo2/libraries/drivers/hal/am_hal_iom.h
new file mode 100644
index 0000000000..e5a450f15c
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_iom.h
@@ -0,0 +1,559 @@
+//*****************************************************************************
+//
+// am_hal_iom.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the IO Master module
+//!
+//! @addtogroup iom2 IO Master (SPI/I2C)
+//! @ingroup apollo2hal
+//! @{
+
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#ifndef AM_HAL_IOM_H
+#define AM_HAL_IOM_H
+
+//*****************************************************************************
+//
+// Macro definitions
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! @name IOM Clock Frequencies
+//! @brief Macro definitions for common SPI and I2C clock frequencies.
+//!
+//! These macros may be used with the ui32ClockFrequency member of the
+//! am_hal_iom_config_t structure to set the clock frequency of the serial
+//! interfaces.
+//!
+//! This list of frequencies is not exhaustive by any means. If your desired
+//! frequency is not in this list, simply set ui32ClockFrequency to the
+//! desired frequency (in Hz) when calling am_hal_iom_config().
+//
+//*****************************************************************************
+#define AM_HAL_IOM_24MHZ 24000000
+#define AM_HAL_IOM_16MHZ 16000000
+#define AM_HAL_IOM_12MHZ 12000000
+#define AM_HAL_IOM_8MHZ 8000000
+#define AM_HAL_IOM_6MHZ 6000000
+#define AM_HAL_IOM_4MHZ 4000000
+#define AM_HAL_IOM_3MHZ 3000000
+#define AM_HAL_IOM_2MHZ 2000000
+#define AM_HAL_IOM_1_5MHZ 1500000
+#define AM_HAL_IOM_1MHZ 1000000
+#define AM_HAL_IOM_750KHZ 750000
+#define AM_HAL_IOM_500KHZ 500000
+#define AM_HAL_IOM_400KHZ 400000
+#define AM_HAL_IOM_375KHZ 375000
+#define AM_HAL_IOM_250KHZ 250000
+#define AM_HAL_IOM_125KHZ 125000
+#define AM_HAL_IOM_100KHZ 100000
+#define AM_HAL_IOM_50KHZ 50000
+#define AM_HAL_IOM_10KHZ 10000
+
+// Hardware FIFO Size
+#define AM_HAL_IOM_MAX_FIFO_SIZE 128
+
+//*****************************************************************************
+//
+//! @name IOM Physical Protocols
+//! @brief Macro Definitions for general IOM configuration.
+//!
+//! These macros may be used with the am_hal_iom_config_t structure to set the
+//! operating parameters of each serial IO master module. Choose SPIMODE to
+//! select the SPI interface, or I2CMODE to select the I2C interface.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOM_SPIMODE AM_REG_IOMSTR_CFG_IFCSEL(1)
+#define AM_HAL_IOM_I2CMODE AM_REG_IOMSTR_CFG_IFCSEL(0)
+//! @}
+
+//*****************************************************************************
+//
+//! @name IOM Operations
+//! @brief Macro definitions used for ui32Operation parameters.
+//!
+//! These macros may be used to specify which action an IOM command will
+//! execute. The 'OFFSET' operations will cause the IOM hardware to transmit the
+//! provided 1-byte 'offset' before executing the rest of the command.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOM_WRITE 0x00000000
+#define AM_HAL_IOM_READ 0x80000000
+//! @}
+
+//*****************************************************************************
+//
+//! @name Command Options
+//! @brief Macro definitions used for ui32Options parameters.
+//!
+//! These macros are all related to SPI or I2C command words. They can be used
+//! to set specific options on a per-transaction basis.
+//!
+//! - CS_LOW - Do not raise the CS signal at the end of this SPI command.
+//! - NO_STOP - Do not release the I2C bus with a STOP bit after this command.
+//! - LSB_FIRST - Reverse the payload bits of this command.
+//! - 10BIT_ADDRESS - (I2C only) use a 10-bit I2C address protocol.
+//! - RAW - Don't use an offset byte.
+//! - OFFSET() - Send this 1-byte offset as the first byte of the transaction.
+//! This can be used to access "registers" in external I2C devices, or add a
+//! 1-byte write to the beginning of a SPI write or read command. See
+//! "normal mode" operation in the I2C/SPI Master section of the datasheet
+//! for more information on this parameter.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOM_CS_LOW 0x10000000
+#define AM_HAL_IOM_NO_STOP 0x10000000
+#define AM_HAL_IOM_LSB_FIRST 0x08000000
+#define AM_HAL_IOM_10BIT_ADDRESS 0x04000000
+#define AM_HAL_IOM_RAW 0x40000000
+#define AM_HAL_IOM_OFFSET(n) (((n) << 8) & 0x0000FF00)
+//! @}
+
+//*****************************************************************************
+//
+//! @name IOM Interrupts
+//! @brief Macro definitions for IOM interrupt status bits.
+//!
+//! These macros correspond to the bits in the IOM interrupt status register.
+//! They may be used with any of the \e am_hal_iom_int_x() functions.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOM_INT_ARB AM_REG_IOMSTR_INTEN_ARB_M
+#define AM_HAL_IOM_INT_STOP AM_REG_IOMSTR_INTEN_STOP_M
+#define AM_HAL_IOM_INT_START AM_REG_IOMSTR_INTEN_START_M
+#define AM_HAL_IOM_INT_ICMD AM_REG_IOMSTR_INTEN_ICMD_M
+#define AM_HAL_IOM_INT_IACC AM_REG_IOMSTR_INTEN_IACC_M
+#define AM_HAL_IOM_INT_WTLEN AM_REG_IOMSTR_INTEN_WTLEN_M
+#define AM_HAL_IOM_INT_NAK AM_REG_IOMSTR_INTEN_NAK_M
+#define AM_HAL_IOM_INT_FOVFL AM_REG_IOMSTR_INTEN_FOVFL_M
+#define AM_HAL_IOM_INT_FUNDFL AM_REG_IOMSTR_INTEN_FUNDFL_M
+#define AM_HAL_IOM_INT_THR AM_REG_IOMSTR_INTEN_THR_M
+#define AM_HAL_IOM_INT_CMDCMP AM_REG_IOMSTR_INTEN_CMDCMP_M
+//! @}
+
+//*****************************************************************************
+//
+//! @name IOM function errors
+//! @brief Return values for IOM HAL function errors, such as with the function
+//! am_hal_iom_error_status_get().
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOM_ERR_INVALID_MODULE (1 << 30)
+//! @}
+
+//*****************************************************************************
+//
+//! @name Software IOM modules
+//! @brief Macro definitions for using the software I2C interface.
+//!
+//! Use this macro as the module number for standard IOM functions to emulate
+//! them using the bit-banged i2c interface.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOM_I2CBB_MODULE AM_REG_IOMSTR_NUM_MODULES
+//! @}
+
+//*****************************************************************************
+//
+//! @brief Union type for a word-aligned, byte-addressable array.
+//!
+//! This is a convenience macro that may be used to define byte-addressable
+//! arrays with 32-bit alignment. This allows the programmer to define SPI or
+//! I2C transactions as a series of 8-bit values, but also write them to the
+//! IOM FIFO efficiently as a series of 32-bit values.
+//!
+//! Example usage:
+//!
+//! @code
+//! //
+//! // Declare a buffer array with at least 3-bytes worth of space.
+//! //
+//! am_hal_iom_buffer(3) sBuffer;
+//!
+//! //
+//! // Populate the buffer with a 3-byte command.
+//! //
+//! sBuffer.bytes[0] = 's';
+//! sBuffer.bytes[1] = 'p';
+//! sBuffer.bytes[2] = 'i';
+//!
+//! //
+//! // Send the buffer over the spi interface.
+//! //
+//! am_hal_iom_spi_write(psDevice, sBuffer.words, 3, 0);
+//!
+//! @endcode
+//
+//*****************************************************************************
+#define am_hal_iom_buffer(A) \
+ union \
+ { \
+ uint32_t words[(A + 3) >> 2]; \
+ uint8_t bytes[A]; \
+ }
+
+//*****************************************************************************
+//
+//! @brief Configuration structure for the IO master module.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! @brief Selects the physical protocol for the IO master module. Choose
+ //! either AM_HAL_IOM_SPIMODE or AM_HAL_IOM_I2CMODE.
+ //
+ uint32_t ui32InterfaceMode;
+
+ //
+ //! @brief Selects the output clock frequency for SPI or I2C mode. Choose
+ //! one of the AM_HAL_IOM_nMHZ or AM_HAL_IOM_nKHZ macros.
+ //
+ uint32_t ui32ClockFrequency;
+
+ //
+ //! Select the SPI clock phase (unused in I2C mode).
+ //
+ bool bSPHA;
+
+ //
+ //! Select the SPI clock polarity (unused in I2C mode).
+ //
+ bool bSPOL;
+
+ //
+ //! @brief Select the FIFO write threshold.
+ //!
+ //! The IOM controller will generate a processor interrupt when the number
+ //! of entries in the FIFO goes *below* this number.
+ //
+ uint8_t ui8WriteThreshold;
+
+ //
+ //! @brief Select the FIFO read threshold.
+ //!
+ //! The IOM controller will generate a processor interrupt when the number
+ //! of entries in the FIFO grows *larger* than this number.
+ //
+ uint8_t ui8ReadThreshold;
+
+}
+am_hal_iom_config_t;
+
+//*****************************************************************************
+//
+//! Configuration structure for an individual SPI device.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! IOM module to use for communicating with this device.
+ //
+ uint32_t ui32Module;
+
+ //
+ //! Chip select signal that should be used for this device.
+ //
+ uint32_t ui32ChipSelect;
+
+ //
+ //! Additional options that will ALWAYS be ORed into the command word.
+ //
+ uint32_t ui32Options;
+}
+am_hal_iom_spi_device_t;
+
+//*****************************************************************************
+//
+//! Configuration structure for an individual I2C device.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! IOM module to use for communicating with this device.
+ //
+ uint32_t ui32Module;
+
+ //
+ //! I2C address associated with this device.
+ //
+ uint32_t ui32BusAddress;
+
+ //
+ //! Additional options that will ALWAYS be ORed into the command word.
+ //
+ uint32_t ui32Options;
+}
+am_hal_iom_i2c_device_t;
+
+//*****************************************************************************
+//
+// Typedef for non-blocking function callbacks.
+//
+//*****************************************************************************
+typedef void (*am_hal_iom_callback_t)(void);
+
+//*****************************************************************************
+//
+// Typedef for a function that waits until the IOM queue is empty.
+//
+//*****************************************************************************
+typedef void (*am_hal_iom_queue_flush_t)(uint32_t);
+
+extern am_hal_iom_queue_flush_t am_hal_iom_queue_flush;
+
+
+//*****************************************************************************
+//
+// Operations
+//
+//*****************************************************************************
+#define AM_HAL_IOM_QUEUE_SPI_WRITE 0
+#define AM_HAL_IOM_QUEUE_SPI_READ 1
+#define AM_HAL_IOM_QUEUE_I2C_WRITE 2
+#define AM_HAL_IOM_QUEUE_I2C_READ 3
+
+//*****************************************************************************
+//
+// Structure to hold IOM operations.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint32_t ui32Operation;
+ uint32_t ui32Module;
+ uint32_t ui32ChipSelect;
+ uint32_t *pui32Data;
+ uint32_t ui32NumBytes;
+ uint32_t ui32Options;
+ am_hal_iom_callback_t pfnCallback;
+}
+am_hal_iom_queue_entry_t;
+
+//*****************************************************************************
+//
+// Structure to hold IOM configuration during module power-down.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint32_t FIFOTHR;
+ uint32_t CLKCFG;
+ uint32_t CFG;
+ uint32_t INTEN;
+ uint32_t bValid;
+}
+am_hal_iom_pwrsave_t;
+
+//*****************************************************************************
+//
+// Global variables
+//
+//*****************************************************************************
+extern am_hal_iom_pwrsave_t am_hal_iom_pwrsave[AM_REG_IOMSTR_NUM_MODULES];
+extern uint32_t g_iom_error_status;
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_iom_pwrctrl_enable(uint32_t ui32Module);
+extern void am_hal_iom_pwrctrl_disable(uint32_t ui32Module);
+extern void am_hal_iom_power_on_restore(uint32_t ui32Module);
+extern void am_hal_iom_power_off_save(uint32_t ui32Module);
+extern void am_hal_iom_config(uint32_t ui32Module,
+ const am_hal_iom_config_t *psConfig);
+extern uint32_t am_hal_iom_frequency_get(uint32_t ui32Module);
+extern void am_hal_iom_enable(uint32_t ui32Module);
+extern void am_hal_iom_disable(uint32_t ui32Module);
+extern void am_hal_iom_spi_write(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern void am_hal_iom_spi_read(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern uint32_t am_hal_iom_spi_write_nq(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern uint32_t am_hal_iom_spi_read_nq(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern void am_hal_iom_spi_write_nb(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern uint32_t am_hal_iom_spi_read_nb(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern void am_hal_iom_spi_cmd_run(uint32_t ui32Operation,
+ uint32_t ui32Module,
+ uint32_t ui32ChipSelect,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern void am_hal_iom_i2c_write(uint32_t ui32Module,
+ uint32_t ui32BusAddress,
+ uint32_t *pui32Data,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern void am_hal_iom_i2c_read(uint32_t ui32Module,
+ uint32_t ui32BusAddress,
+ uint32_t *pui32Data,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern uint32_t am_hal_iom_i2c_write_nq(uint32_t ui32Module,
+ uint32_t ui32BusAddress,
+ uint32_t *pui32Data,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern uint32_t am_hal_iom_i2c_read_nq(uint32_t ui32Module,
+ uint32_t ui32BusAddress,
+ uint32_t *pui32Data,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern void am_hal_iom_i2c_write_nb(uint32_t ui32Module,
+ uint32_t ui32BusAddress,
+ uint32_t *pui32Data,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern void am_hal_iom_i2c_read_nb(uint32_t ui32Module,
+ uint32_t ui32BusAddress,
+ uint32_t *pui32Data,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern void am_hal_iom_i2c_cmd_run(uint32_t ui32Operation,
+ uint32_t ui32Module,
+ uint32_t ui32BusAddress,
+ uint32_t ui32NumBytes,
+ uint32_t ui32Options);
+extern void am_hal_iom_command_repeat_set(uint32_t ui32Module,
+ uint32_t ui32CmdCount);
+extern uint32_t am_hal_iom_status_get(uint32_t ui32Module);
+extern uint32_t am_hal_iom_error_status_get(uint32_t ui32Module);
+extern uint32_t am_hal_iom_fifo_write(uint32_t ui32Module, uint32_t *pui32Data,
+ uint32_t ui32NumBytes);
+extern uint32_t am_hal_iom_fifo_read(uint32_t ui32Module, uint32_t *pui32Data,
+ uint32_t ui32NumBytes);
+extern uint8_t am_hal_iom_fifo_empty_slots(uint32_t ui32Module);
+extern uint8_t am_hal_iom_fifo_full_slots(uint32_t ui32Module);
+extern void am_hal_iom_poll_complete(uint32_t ui32Module);
+extern void am_hal_iom_int_service(uint32_t ui32Module, uint32_t ui32Status);
+extern void am_hal_iom_int_enable(uint32_t ui32Module, uint32_t ui32Interrupt);
+extern uint32_t am_hal_iom_int_enable_get(uint32_t ui32Module);
+extern void am_hal_iom_int_disable(uint32_t ui32Module, uint32_t ui32Interrupt);
+extern void am_hal_iom_int_clear(uint32_t ui32Module, uint32_t ui32Interrupt);
+extern void am_hal_iom_int_set(uint32_t ui32Module, uint32_t ui32Interrupt);
+extern uint32_t am_hal_iom_int_status_get(uint32_t ui32Module, bool bEnabledOnly);
+extern void am_hal_iom_queue_init(uint32_t ui32ModuleNum,
+ am_hal_iom_queue_entry_t *psQueueMemory,
+ uint32_t ui32QueueMemSize);
+extern uint32_t am_hal_iom_queue_length_get(uint32_t ui32Module);
+extern void am_hal_iom_sleeping_queue_flush(uint32_t ui32Module);
+extern void am_hal_iom_queue_spi_write(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern void am_hal_iom_queue_spi_read(uint32_t ui32Module, uint32_t ui32ChipSelect,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern void am_hal_iom_queue_i2c_write(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern void am_hal_iom_queue_i2c_read(uint32_t ui32Module, uint32_t ui32BusAddress,
+ uint32_t *pui32Data, uint32_t ui32NumBytes,
+ uint32_t ui32Options,
+ am_hal_iom_callback_t pfnCallback);
+extern void am_hal_iom_queue_start_next_msg(uint32_t ui32Module);
+extern void am_hal_iom_queue_service(uint32_t ui32Module, uint32_t ui32Status);
+
+//*****************************************************************************
+//
+// Helper functions.
+//
+//*****************************************************************************
+#define AM_IOMASTER_ISR_QUEUE(x) \
+void am_iomaster##x##_isr(void) \
+{ \
+ uint32_t ui32IntStatus; \
+ g_iom_error_status = am_hal_iom_error_status_get(x); \
+ ui32IntStatus = am_hal_iom_int_status_get(x, false); \
+ am_hal_iom_int_clear(x, ui32IntStatus); \
+ am_hal_iom_queue_service(x, ui32IntStatus); \
+}
+
+#define AM_IOMASTER_ISR_NB(x) \
+void am_iomaster##x##_isr(void) \
+{ \
+ uint32_t ui32IntStatus; \
+ g_iom_error_status = am_hal_iom_error_status_get(x); \
+ ui32IntStatus = am_hal_iom_int_status_get(x, false); \
+ am_hal_iom_int_clear(x, ui32IntStatus); \
+ am_hal_iom_int_service(x, ui32IntStatus); \
+}
+
+#endif // AM_HAL_IOM_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_ios.c b/bsp/apollo2/libraries/drivers/hal/am_hal_ios.c
new file mode 100644
index 0000000000..0f34aa6efb
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_ios.c
@@ -0,0 +1,1303 @@
+//*****************************************************************************
+//
+// am_hal_ios.c
+//! @file
+//!
+//! @brief Functions for interfacing with the IO Slave module
+//!
+//! @addtogroup ios2 IO Slave (SPI/I2C)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// SRAM Buffer structure
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t *pui8Data;
+ volatile uint32_t ui32WriteIndex;
+ volatile uint32_t ui32ReadIndex;
+ volatile uint32_t ui32Length;
+ uint32_t ui32Capacity;
+}
+am_hal_ios_buffer_t;
+
+am_hal_ios_buffer_t g_sSRAMBuffer;
+
+//*****************************************************************************
+//
+// Forward declarations of static funcitons.
+//
+//*****************************************************************************
+static void am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer,
+ void *pvArray, uint32_t ui32Bytes);
+
+static void fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes);
+
+//*****************************************************************************
+//
+// Function-like macros.
+//
+//*****************************************************************************
+#define am_hal_ios_buffer_empty(psBuffer) \
+ ((psBuffer)->ui32Length == 0)
+
+#define am_hal_ios_buffer_full(psBuffer) \
+ ((psBuffer)->ui32Length == (psBuffer)->ui32Capacity)
+
+#define am_hal_ios_buffer_data_left(psBuffer) \
+ ((psBuffer)->ui32Length)
+
+//*****************************************************************************
+//
+// Global Variables
+//
+//*****************************************************************************
+volatile uint8_t * const am_hal_ios_pui8LRAM = (uint8_t *)REG_IOSLAVE_BASEADDR;
+uint8_t *g_pui8FIFOBase = (uint8_t *) REG_IOSLAVE_BASEADDR;
+uint8_t *g_pui8FIFOEnd = (uint8_t *) REG_IOSLAVE_BASEADDR;
+uint8_t *g_pui8FIFOPtr = (uint8_t *) REG_IOSLAVE_BASEADDR;
+uint8_t g_ui32HwFifoSize = 0;
+uint32_t g_ui32FifoBaseOffset = 0;
+
+//*****************************************************************************
+//
+//! @brief Enable the IOS in the power control block.
+//!
+//! This function enables the IOS module in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_pwrctrl_enable(void)
+{
+ am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOS);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the IOS in the power control block.
+//!
+//! This function disables the IOS module in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_pwrctrl_disable(void)
+{
+ am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_IOS);
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the IOS module
+//!
+//! This function enables the IOSLAVE module using the IFCEN bitfield in the
+//! IOSLAVE_CFG register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_enable(uint32_t ui32Module)
+{
+ AM_REGn(IOSLAVE, ui32Module, CFG) |= AM_REG_IOSLAVE_CFG_IFCEN(1);
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the IOSLAVE module.
+//!
+//! This function disables the IOSLAVE module using the IFCEN bitfield in the
+//! IOSLAVE_CFG register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_disable(uint32_t ui32Module)
+{
+ AM_REGn(IOSLAVE, ui32Module, CFG) &= ~(AM_REG_IOSLAVE_CFG_IFCEN(1));
+}
+
+//*****************************************************************************
+//
+//! @brief Configure the IOS module.
+//!
+//! This function reads the an \e am_hal_ios_config_t structure and uses it to
+//! set up the IO Slave module. Please see the information on the configuration
+//! structure for more information on the parameters that may be set by this
+//! function.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_config(am_hal_ios_config_t *psConfig)
+{
+ uint32_t ui32LRAMConfig;
+
+ am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOS);
+
+ //
+ // Record the FIFO parameters for later use.
+ //
+ g_pui8FIFOBase = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32FIFOBase);
+ g_pui8FIFOEnd = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32RAMBase);
+ g_ui32HwFifoSize = g_pui8FIFOEnd - g_pui8FIFOBase;
+ g_ui32FifoBaseOffset = psConfig->ui32FIFOBase;
+
+ //
+ // Caluclate the value for the IO Slave FIFO configuration register.
+ //
+ ui32LRAMConfig = AM_REG_IOSLAVE_FIFOCFG_ROBASE(psConfig->ui32ROBase >> 3);
+ ui32LRAMConfig |= AM_REG_IOSLAVE_FIFOCFG_FIFOBASE(psConfig->ui32FIFOBase >> 3);
+ ui32LRAMConfig |= AM_REG_IOSLAVE_FIFOCFG_FIFOMAX(psConfig->ui32RAMBase >> 3);
+
+ //
+ // Just in case, disable the IOS
+ //
+ am_hal_ios_disable(0);
+
+ //
+ // Write the configuration register with the user's selected interface
+ // characteristics.
+ //
+ AM_REG(IOSLAVE, CFG) = psConfig->ui32InterfaceSelect;
+
+ //
+ // Write the FIFO configuration register to set the memory map for the LRAM.
+ //
+ AM_REG(IOSLAVE, FIFOCFG) = ui32LRAMConfig;
+
+ //
+ // Enable the IOS. The following configuration options can't be set while
+ // the IOS is disabled.
+ //
+ am_hal_ios_enable(0);
+
+ //
+ // Initialize the FIFO pointer to the beginning of the FIFO section.
+ //
+ am_hal_ios_fifo_ptr_set(psConfig->ui32FIFOBase);
+
+ //
+ // Write the FIFO threshold register.
+ //
+ AM_REG(IOSLAVE, FIFOTHR) = psConfig->ui32FIFOThreshold;
+}
+
+//*****************************************************************************
+//
+//! @brief Set bits in the HOST side IOINTCTL register.
+//!
+//! This function may be used to set an interrupt bit to the host.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_host_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Set a bit that will cause an interrupt to the host.
+ //
+ AM_REG(IOSLAVE, IOINTCTL) = AM_REG_IOSLAVE_IOINTCTL_IOINTSET(ui32Interrupt);
+}
+
+//*****************************************************************************
+//
+//! @brief Clear bits in the HOST side IOINTCTL register.
+//!
+//! This function may be used to clear an interrupt bit to the host.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_host_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Clear bits that will cause an interrupt to the host.
+ //
+ AM_REG(IOSLAVE, IOINTCTL) = AM_REG_IOSLAVE_IOINTCTL_IOINTCLR(ui32Interrupt);
+}
+
+//*****************************************************************************
+//
+//! @brief Get the bits in the HOST side IOINTCTL register.
+//!
+//! This function may be used to read the host side interrupt bits.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_host_int_get(void)
+{
+ //
+ // return the value of the bits that will cause an interrupt to the host.
+ //
+ return AM_BFR(IOSLAVE, IOINTCTL, IOINT);
+}
+
+//*****************************************************************************
+//
+//! @brief Get the enable bits in the HOST side IOINTCTL register.
+//!
+//! This function may be used to read the host side interrupt bits.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_host_int_enable_get(void)
+{
+ //
+ // return the value of the bits that will cause an interrupt to the host.
+ //
+ return AM_BFR(IOSLAVE, IOINTCTL, IOINTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable an IOS Access Interrupt.
+//!
+//! This function may be used to enable an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_access_int_enable(uint32_t ui32Interrupt)
+{
+ //
+ // OR the desired interrupt into the enable register.
+ //
+ AM_REG(IOSLAVE, REGACCINTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return all enabled IOS Access Interrupts.
+//!
+//! This function may be used to return all enabled IOS Access interrupts.
+//!
+//! @return the enabled interrrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_access_int_enable_get(void)
+{
+ //
+ // Return the enabled interrupts.
+ //
+ return AM_REG(IOSLAVE, REGACCINTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable an IOS Access Interrupt.
+//!
+//! This function may be used to disable an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_access_int_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Clear the desired bit from the interrupt enable register.
+ //
+ AM_REG(IOSLAVE, REGACCINTEN) &= ~(ui32Interrupt);
+}
+
+//*****************************************************************************
+//
+//! @brief Clear an IOS Access Interrupt.
+//!
+//! This function may be used to clear an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_access_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Use the interrupt clear register to deactivate the chosen interrupt.
+ //
+ AM_REG(IOSLAVE, REGACCINTCLR) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Set an IOS Access Interrupt.
+//!
+//! This function may be used to set an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_access_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Use the interrupt set register to activate the chosen interrupt.
+ //
+ AM_REG(IOSLAVE, REGACCINTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Check the status of an IOS Access Interrupt.
+//!
+//! @param bEnabledOnly - return only the enabled interrupt status.
+//!
+//! This function may be used to return the enabled interrupt status.
+//!
+//! @return the enabled interrupt status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_access_int_status_get(bool bEnabledOnly)
+{
+ if ( bEnabledOnly )
+ {
+ uint32_t u32RetVal = AM_REG(IOSLAVE, REGACCINTSTAT);
+ return u32RetVal & AM_REG(IOSLAVE, REGACCINTEN);
+
+ }
+ else
+ {
+ return AM_REG(IOSLAVE, REGACCINTSTAT);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Enable an IOS Interrupt.
+//!
+//! @param ui32Interrupt - desired interrupts.
+//!
+//! This function may be used to enable an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_int_enable(uint32_t ui32Interrupt)
+{
+ //
+ // OR the desired interrupt into the enable register.
+ //
+ AM_REG(IOSLAVE, INTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return all enabled IOS Interrupts.
+//!
+//! This function may be used to return all enabled IOS interrupts.
+//!
+//! @return the enabled interrrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_int_enable_get(void)
+{
+ //
+ // Return the enabled interrupts.
+ //
+ return AM_REG(IOSLAVE, INTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable an IOS Interrupt.
+//!
+//! @param ui32Interrupt - desired interrupts.
+//!
+//! This function may be used to disable an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_int_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Clear the desired bit from the interrupt enable register.
+ //
+ AM_REG(IOSLAVE, INTEN) &= ~(ui32Interrupt);
+}
+
+//*****************************************************************************
+//
+//! @brief Clear an IOS Interrupt.
+//!
+//! @param ui32Interrupt - desired interrupts.
+//!
+//! This function may be used to clear an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Use the interrupt clear register to deactivate the chosen interrupt.
+ //
+ AM_REG(IOSLAVE, INTCLR) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Set an IOS Interrupt.
+//!
+//! @param ui32Interrupt - desired interrupts.
+//!
+//! This function may be used to set an interrupt to the NVIC.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Use the interrupt clear register to deactivate the chosen interrupt.
+ //
+ AM_REG(IOSLAVE, INTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Write to the LRAM.
+//!
+//! @param ui32Offset - offset into the LRAM to write.
+//! @param ui8Value - value to be written.
+//!
+//! This function writes ui8Value to offset ui32Offset inside the LRAM.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_lram_write(uint32_t ui32Offset, uint8_t ui8Value)
+{
+ //
+ // Write the LRAM.
+ //
+ am_hal_ios_pui8LRAM[ui32Offset] = ui8Value;
+}
+
+//*****************************************************************************
+//
+//! @brief Read from the LRAM.
+//!
+//! @param ui32Offset - offset into the LRAM to read.
+//!
+//! This function read from offset ui32Offset inside the LRAM.
+//!
+//! @return the value at ui32Offset.
+//
+//*****************************************************************************
+uint8_t
+am_hal_ios_lram_read(uint32_t ui32Offset)
+{
+ //
+ // Read the LRAM.
+ //
+ return am_hal_ios_pui8LRAM[ui32Offset];
+}
+
+//*****************************************************************************
+//
+//! @brief Check the status of an IOS Interrupt.
+//!
+//! @param bEnabledOnly - return only the enabled interrupt status.
+//!
+//! This function may be used to return the enabled interrupt status.
+//!
+//! @return the enabled interrupt status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_int_status_get(bool bEnabledOnly)
+{
+ if ( bEnabledOnly )
+ {
+ uint32_t u32RetVal = AM_REG(IOSLAVE, INTSTAT);
+ return u32RetVal & AM_REG(IOSLAVE, INTEN);
+
+ }
+ else
+ {
+ return AM_REG(IOSLAVE, INTSTAT);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Check the amount of space used in the FIFO
+//!
+//! This function returns the available data in the overall FIFO yet to be
+//! read by the host. This takes into account the SRAM buffer and hardware FIFO
+//!
+//! @return Bytes used in the Overall FIFO.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_fifo_space_used(void)
+{
+ uint32_t ui32Val;
+ uint32_t ui32Primask;
+ //
+ // Start a critical section for thread safety.
+ //
+ ui32Primask = am_hal_interrupt_master_disable();
+ ui32Val = g_sSRAMBuffer.ui32Length;
+ ui32Val += AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
+ //
+ // End the critical section
+ //
+ am_hal_interrupt_master_set(ui32Primask);
+ return ui32Val;
+}
+
+
+
+//*****************************************************************************
+//
+//! @brief Check the amount of space left in the FIFO
+//!
+//! This function returns the available space in the overall FIFO to accept
+//! new data. This takes into account the SRAM buffer and hardware FIFO
+//!
+//! @return Bytes left in the Overall FIFO.
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_fifo_space_left(void)
+{
+ uint32_t ui32Val;
+ uint32_t ui32Primask;
+ //
+ // Start a critical section for thread safety.
+ //
+ ui32Primask = am_hal_interrupt_master_disable();
+ //
+ // We waste one byte in HW FIFO
+ //
+ ui32Val = g_sSRAMBuffer.ui32Capacity + g_ui32HwFifoSize - 1;
+ ui32Val -= g_sSRAMBuffer.ui32Length;
+ ui32Val -= AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
+ //
+ // End the critical section
+ //
+ am_hal_interrupt_master_set(ui32Primask);
+ return ui32Val;
+}
+
+//*****************************************************************************
+//
+//! @brief Check the amount of space left in the hardware FIFO
+//!
+//! This function reads the IOSLAVE FIFOPTR register and determines the amount
+//! of space left in the IOS LRAM FIFO.
+//!
+//! @return Bytes left in the IOS FIFO.
+//
+//*****************************************************************************
+static uint32_t
+fifo_space_left(void)
+{
+ //
+ // We waste one byte in HW FIFO
+ //
+ return ((uint32_t)g_ui32HwFifoSize- AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ) - 1);
+}
+
+//*****************************************************************************
+//
+// Helper function for managing IOS FIFO writes.
+//
+//*****************************************************************************
+static void
+fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes)
+{
+ uint8_t *pFifoPtr = g_pui8FIFOPtr;
+ uint8_t *pFifoBase = g_pui8FIFOBase;
+ uint8_t *pFifoEnd = g_pui8FIFOEnd;
+ while ( ui32NumBytes )
+ {
+ //
+ // Write the data to the FIFO
+ //
+ *pFifoPtr++ = *pui8Data++;
+ ui32NumBytes--;
+
+ //
+ // Make sure to wrap the FIFO pointer if necessary.
+ //
+ if ( pFifoPtr == pFifoEnd )
+ {
+ pFifoPtr = pFifoBase;
+ }
+ }
+ g_pui8FIFOPtr = pFifoPtr;
+}
+
+//
+// Assembly code below assumes 8bit FIFOSIZ field aligned at a byte boundary
+//
+#if (((AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S) != 0xFF) \
+ || (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S & 0x3))
+#error "FIFOSIZ not 8bit value aligned at byte offset"
+#endif
+
+//
+// Byte offset of FIFOSIZ field in FIFOPTR register
+//
+#define BYTEOFFSET_FIFOSIZE (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S >> 3)
+
+//*****************************************************************************
+//
+// Helper function in assembly for implementing the ReSync
+//
+//*****************************************************************************
+#if defined(__GNUC_STDC_INLINE__)
+#if (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S != 8)
+#error "AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S not 8"
+#endif
+__attribute__((naked))
+static void
+internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
+{
+ __asm
+ (
+ " push {r3,r4}\n\t" // Save r3, r4 - used by this function
+ "__internal_resync_fifoSize_loop:\n\t"
+ " ldr r4, [r2]\n\t" // Load FIFOPTR register in r4
+ " ubfx r3, r4, #8, #8\n\t" // Extract hwFifoSize to r3
+ " uxtb r4, r4\n\t" // Extract rdOffset in r4
+ " subs r4, r0, r4\n\t" // fifoSize in r4 = wrOffset - rdOffset
+ " it cc\n\t" // if (wrOffset < rdOffset)
+ " addcc r4, r4, r1\n\t" // fifoSize = maxFifoSize - (rdOffset - wrOffset)
+ " cmp r3, r4\n\t" // (hwFifoSize != fifoSize)
+ " beq __internal_resync_fifosize_done\n\t"
+ " strb r4, [r2, #1]\n\t" // Overwrite FIFOSIZ value with fifoSize
+ " b __internal_resync_fifoSize_loop\n\t" // Repeat the check
+ "__internal_resync_fifosize_done:\n\t"
+ " pop {r3,r4}\n\t" // Restore registers
+ " bx lr\n\t"
+ );
+}
+
+#elif defined(__ARMCC_VERSION)
+__asm static void
+internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
+{
+ push {r3, r4} // Save r3, r4 - used by this function
+internal_resync_fifoSize_loop
+ ldr r4, [r2] // Load FIFOPTR register in r4
+ ubfx r3, r4, #AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S, #8 // Extract hwFifoSize to r3
+ uxtb r4, r4 // Extract rdOffset in r4
+ subs r4, r0, r4 // fifoSize in r4 = wrOffset - rdOffset
+ it cc // if (wrOffset < rdOffset),
+ addcc r4, r4, r1 // fifoSize = maxFifoSize - (rdOffset - wrOffset)
+ cmp r3, r4 // (hwFifoSize != fifoSize)
+ beq internal_resync_fifosize_done
+ strb r4, [r2, #1] // Overwrite FIFOSIZ value with fifoSize
+ b internal_resync_fifoSize_loop // Repeat the check
+internal_resync_fifosize_done
+ pop {r3, r4} // Restore registers
+ bx lr
+}
+
+#elif defined(__IAR_SYSTEMS_ICC__)
+#if (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S != 8)
+#error "AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S not 8"
+#endif
+__stackless static void
+internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
+{
+ __asm volatile (
+ " push {r3,r4}\n" // Save r3, r4 - used by this function
+ "__internal_resync_fifoSize_loop:\n"
+ " ldr r4, [r2]\n" // Load FIFOPTR register in r4
+ " ubfx r3, r4, #8, #8\n" // Extract hwFifoSize to r3
+ " uxtb r4, r4\n" // Extract rdOffset in r4
+ " subs r4, r0, r4\n" // fifoSize in r4 = wrOffset - rdOffset
+ " it cc\n"
+ " addcc r4, r4, r1\n" // fifoSize = maxFifoSize - (rdOffset - wrOffset)
+ " cmp r3, r4\n" // (fifoSize != hwFifoSize)
+ " beq __internal_resync_fifosize_done\n"
+ " strb r4, [r2, #1]\n" // Overwrite FIFOSIZ value with fifoSize
+ " b __internal_resync_fifoSize_loop\n" // Repeat the check
+ "__internal_resync_fifosize_done:\n"
+ " pop {r3,r4}\n" // Restore registers
+ " bx lr\n"
+ );
+}
+
+#else
+static void
+internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
+{
+ uint32_t fifoSize;
+ uint32_t hwFifoPtrReg;
+ uint32_t rdOffset;
+ uint32_t hwFifoSize;
+
+ hwFifoPtrReg = AM_REGVAL(hwFifoPtrRegAddr);
+ rdOffset = ((hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_S);
+ hwFifoSize = (hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S;
+ // By wasting one byte in hardware FIFO, we're guaranteed that fifoSize does not need special handling for FULL FIFO case
+ fifoSize = ((wrOffset >= rdOffset) ? (wrOffset - rdOffset) : (maxFifoSize - (rdOffset - wrOffset)));
+ while ( fifoSize != hwFifoSize )
+ {
+ // Overwite correct FIFOSIZ
+ // Need to do a Byte Write to make sure the FIFOPTR is not overwritten
+ *((uint8_t *)(hwFifoPtrRegAddr + BYTEOFFSET_FIFOSIZE)) = fifoSize;
+ // Read back the register and check for consistency
+ hwFifoPtrReg = AM_REGVAL(hwFifoPtrRegAddr);
+ rdOffset = ((hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_S);
+ hwFifoSize = (hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S;
+ // By wasting one byte in hardware FIFO, we're guaranteed that fifoSize does not need special handling for FULL FIFO case
+ fifoSize = ((wrOffset >= rdOffset) ? (wrOffset - rdOffset) : (hwFifoSize - (rdOffset - wrOffset)));
+ }
+}
+#endif
+
+//
+// Address of the FIFOPTR register
+//
+#define AM_REG_IOS_FIFOPTR (REG_IOSLAVE_BASEADDR + AM_REG_IOSLAVE_FIFOPTR_O)
+
+// When the FIFO is being replenished by the SW, at the same time as host is
+// reading from it, there is a possible race condition, where the hardware decrement
+// of FIFOSIZ as a result of read gets overwritten by hardware increment due to
+// write.
+// This function re-sync's the FIFOSIZ to ensure such errors do not accumulate
+void
+resync_fifoSize(void)
+{
+ uint32_t ui32Primask;
+ uint32_t wrOffset = (uint32_t)g_pui8FIFOPtr - (uint32_t)am_hal_ios_pui8LRAM;
+ //
+ // Start a critical section for thread safety.
+ //
+ ui32Primask = am_hal_interrupt_master_disable();
+ internal_resync_fifoSize(wrOffset, g_ui32HwFifoSize, AM_REG_IOS_FIFOPTR);
+ // Clear interrupts for IOS which could be spuriously triggered
+ AM_REG(IOSLAVE, REGACCINTCLR) = (AM_HAL_IOS_INT_FSIZE | AM_HAL_IOS_INT_FOVFL | AM_HAL_IOS_INT_FUNDFL);
+ //
+ // End the critical section
+ //
+ am_hal_interrupt_master_set(ui32Primask);
+ return;
+}
+
+//*****************************************************************************
+//
+//! @brief Transfer any available data from the IOS SRAM buffer to the FIFO.
+//!
+//! This function is meant to be called from an interrupt handler for the
+//! ioslave module. It checks the IOS FIFO interrupt status for a threshold
+//! event, and transfers data from an SRAM buffer into the IOS FIFO.
+//!
+//! @param ui32Status should be set to the ios interrupt status at the time of
+//! ISR entry.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_fifo_service(uint32_t ui32Status)
+{
+ uint32_t thresh;
+ uint32_t freeSpace, usedSpace, chunk1, chunk2, ui32WriteIndex;
+
+ //
+ // Check for FIFO size interrupts.
+ //
+ if ( ui32Status & AM_HAL_IOS_INT_FSIZE )
+ {
+ thresh = AM_BFR(IOSLAVE, FIFOTHR, FIFOTHR);
+
+ //
+ // While the FIFO is at or below threshold Add more data
+ // If Fifo level is above threshold, we're guaranteed an FSIZ interrupt
+ //
+ while ( g_sSRAMBuffer.ui32Length &&
+ ((usedSpace = AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ)) <= thresh) )
+ {
+ //
+ // So, we do have some data in SRAM which needs to be moved to FIFO.
+ // A chunk of data is a continguous set of bytes in SRAM that can be
+ // written to FIFO. Determine the chunks of data from SRAM that can
+ // be written. Up to two chunks possible
+ //
+ ui32WriteIndex = g_sSRAMBuffer.ui32WriteIndex;
+ chunk1 = ((ui32WriteIndex > (uint32_t)g_sSRAMBuffer.ui32ReadIndex) ? \
+ (ui32WriteIndex - (uint32_t)g_sSRAMBuffer.ui32ReadIndex) : \
+ (g_sSRAMBuffer.ui32Capacity - (uint32_t)g_sSRAMBuffer.ui32ReadIndex));
+ chunk2 = g_sSRAMBuffer.ui32Length - chunk1;
+ // We waste one byte in HW FIFO
+ freeSpace = g_ui32HwFifoSize - usedSpace - 1;
+ // Write data in chunks
+ // Determine the chunks of data from SRAM that can be written
+ if ( chunk1 > freeSpace )
+ {
+ fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
+ //
+ // Advance the read index, wrapping if needed.
+ //
+ g_sSRAMBuffer.ui32ReadIndex += freeSpace;
+ // No need to check for wrap as we wrote less than chunk1
+ //
+ // Adjust the length value to reflect the change.
+ //
+ g_sSRAMBuffer.ui32Length -= freeSpace;
+ }
+ else
+ {
+ fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk1);
+
+ //
+ // Update the read index - wrapping as needed
+ //
+ g_sSRAMBuffer.ui32ReadIndex += chunk1;
+ g_sSRAMBuffer.ui32ReadIndex %= g_sSRAMBuffer.ui32Capacity;
+ //
+ // Adjust the length value to reflect the change.
+ //
+ g_sSRAMBuffer.ui32Length -= chunk1;
+ freeSpace -= chunk1;
+
+ if ( freeSpace && chunk2 )
+ {
+ if ( chunk2 > freeSpace )
+ {
+ fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
+
+ //
+ // Advance the read index, wrapping if needed.
+ //
+ g_sSRAMBuffer.ui32ReadIndex += freeSpace;
+
+ // No need to check for wrap in chunk2
+ //
+ // Adjust the length value to reflect the change.
+ //
+ g_sSRAMBuffer.ui32Length -= freeSpace;
+ }
+ else
+ {
+ fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk2);
+ //
+ // Advance the read index, wrapping if needed.
+ //
+ g_sSRAMBuffer.ui32ReadIndex += chunk2;
+
+ // No need to check for wrap in chunk2
+ //
+ // Adjust the length value to reflect the change.
+ //
+ g_sSRAMBuffer.ui32Length -= chunk2;
+ }
+ }
+ }
+ resync_fifoSize();
+
+ //
+ // Need to retake the FIFO space, after Threshold interrupt has been reenabled
+ // Clear any spurious FSIZE interrupt that might have got raised
+ //
+ AM_BFW(IOSLAVE, INTCLR, FSIZE, 1);
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Writes the specified number of bytes to the IOS fifo.
+//!
+//! @param pui8Data is a pointer to the data to be written to the fifo.
+//! @param ui32NumBytes is the number of bytes to send.
+//!
+//! This function will write data from the caller-provided array to the IOS
+//! LRAM FIFO. If there is no space in the LRAM FIFO, the data will be copied
+//! to a temporary SRAM buffer instead.
+//!
+//! The maximum message size for the IO Slave is 1023 bytes.
+//!
+//! @note In order for SRAM copy operations in the function to work correctly,
+//! the \e am_hal_ios_buffer_service() function must be called in the ISR for
+//! the ioslave module.
+//!
+//! @return Number of bytes written (could be less than ui32NumBytes, if not enough space)
+//
+//*****************************************************************************
+uint32_t
+am_hal_ios_fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes)
+{
+ uint32_t ui32FIFOSpace;
+ uint32_t ui32SRAMSpace;
+ uint32_t ui32SRAMLength;
+ uint32_t ui32Primask;
+ uint32_t totalBytes = ui32NumBytes;
+
+ //
+ // This operation will only work properly if an SRAM buffer has been
+ // allocated. Make sure that am_hal_ios_fifo_buffer_init() has been called,
+ // and the buffer pointer looks valid.
+ //
+ am_hal_debug_assert(g_sSRAMBuffer.pui8Data != 0);
+
+ if ( ui32NumBytes == 0 )
+ {
+ return 0;
+ }
+
+ //
+ // Start a critical section for thread safety.
+ //
+ ui32Primask = am_hal_interrupt_master_disable();
+
+ ui32SRAMLength = g_sSRAMBuffer.ui32Length;
+ //
+ // End the critical section
+ //
+ am_hal_interrupt_master_set(ui32Primask);
+
+ //
+ // If the SRAM buffer is empty, we should just write directly to the FIFO.
+ //
+ if ( ui32SRAMLength == 0 )
+ {
+ ui32FIFOSpace = fifo_space_left();
+
+ //
+ // If the whole message fits, send it now.
+ //
+ if ( ui32NumBytes <= ui32FIFOSpace )
+ {
+ fifo_write(pui8Data, ui32NumBytes);
+ ui32NumBytes = 0;
+ }
+ else
+ {
+ fifo_write(pui8Data, ui32FIFOSpace);
+ ui32NumBytes -= ui32FIFOSpace;
+ pui8Data += ui32FIFOSpace;
+ };
+ resync_fifoSize();
+ }
+
+ //
+ // If there's still data, write it to the SRAM buffer.
+ //
+ if ( ui32NumBytes )
+ {
+ uint32_t idx, writeIdx, capacity, fifoSize;
+ ui32SRAMSpace = g_sSRAMBuffer.ui32Capacity - ui32SRAMLength;
+
+ writeIdx = g_sSRAMBuffer.ui32WriteIndex;
+ capacity = g_sSRAMBuffer.ui32Capacity;
+ //
+ // Make sure that the data will fit inside the SRAM buffer.
+ //
+ if ( ui32SRAMSpace > ui32NumBytes )
+ {
+ ui32SRAMSpace = ui32NumBytes;
+ }
+
+ //
+ // If the data will fit, write it to the SRAM buffer.
+ //
+ for ( idx = 0; idx < ui32SRAMSpace; idx++ )
+ {
+ g_sSRAMBuffer.pui8Data[(idx + writeIdx) % capacity] = pui8Data[idx];
+ }
+
+ ui32NumBytes -= idx;
+ //
+ // Start a critical section for thread safety before updating length & wrIdx.
+ //
+ ui32Primask = am_hal_interrupt_master_disable();
+ //
+ // Advance the write index, making sure to wrap if necessary.
+ //
+ g_sSRAMBuffer.ui32WriteIndex = (idx + writeIdx) % capacity;
+
+ //
+ // Update the length value appropriately.
+ //
+ g_sSRAMBuffer.ui32Length += idx;
+ //
+ // End the critical section
+ //
+ am_hal_interrupt_master_set(ui32Primask);
+
+ // It is possible that there is a race condition that the FIFO level has
+ // gone below the threshold by the time we set the wrIdx above, and hence
+ // we may never get the threshold interrupt to serve the SRAM data we
+ // just wrote
+
+ // If that is the case, explicitly generate the FSIZE interrupt from here
+ fifoSize = AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
+ if ( fifoSize <= AM_BFR(IOSLAVE, FIFOTHR, FIFOTHR) )
+ {
+ AM_BFW(IOSLAVE, INTSET, FSIZE, 1);
+ }
+ }
+
+ return (totalBytes - ui32NumBytes);
+}
+
+//*****************************************************************************
+//
+//! @brief Writes the specified number of bytes to the IOS fifo simply.
+//!
+//! @param pui8Data is a pointer to the data to be written to the fifo.
+//! @param ui32NumBytes is the number of bytes to send.
+//!
+//! This function will write data from the caller-provided array to the IOS
+//! LRAM FIFO. This simple routine does not use SRAM buffering for large
+//! messages.
+//!
+//! The maximum message size for the IO Slave is 128 bytes.
+//!
+//! @note Do note call the \e am_hal_ios_buffer_service() function in the ISR for
+//! the ioslave module.
+//!
+//! @return
+//
+//*****************************************************************************
+void
+am_hal_ios_fifo_write_simple(uint8_t *pui8Data, uint32_t ui32NumBytes)
+{
+ uint32_t ui32FIFOSpace;
+
+ //
+ // Check the FIFO and the SRAM buffer to see where we have space.
+ //
+ ui32FIFOSpace = fifo_space_left();
+
+ //
+ // If the whole message fits, send it now.
+ //
+ if ( ui32NumBytes <= ui32FIFOSpace )
+ {
+ fifo_write(pui8Data, ui32NumBytes);
+ }
+ else
+ {
+ //
+ // The message didn't fit. Try using am_hal_ios_fifo_write() instead.
+ //
+ am_hal_debug_assert_msg(0, "The requested IOS transfer didn't fit in"
+ "the LRAM FIFO. Try using am_hal_ios_fifo_write().");
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Sets the IOS FIFO pointer to the specified LRAM offset.
+//!
+//! @param ui32Offset is LRAM offset to set the FIFO pointer to.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_fifo_ptr_set(uint32_t ui32Offset)
+{
+ uint32_t ui32Primask;
+
+ //
+ // Start a critical section for thread safety.
+ //
+ ui32Primask = am_hal_interrupt_master_disable();
+
+ //
+ // Set the FIFO Update bit.
+ //
+ AM_REG(IOSLAVE, FUPD) = 0x1;
+
+ //
+ // Change the FIFO offset.
+ //
+ AM_REG(IOSLAVE, FIFOPTR) = ui32Offset;
+
+ //
+ // Clear the FIFO update bit.
+ //
+ AM_REG(IOSLAVE, FUPD) = 0x0;
+
+ //
+ // Set the global FIFO-pointer tracking variable.
+ //
+ g_pui8FIFOPtr = (uint8_t *) (REG_IOSLAVE_BASEADDR + ui32Offset);
+
+ //
+ // End the critical section.
+ //
+ am_hal_interrupt_master_set(ui32Primask);
+}
+
+//*****************************************************************************
+//
+// Initialize an SRAM buffer for use with the IO Slave.
+//
+//*****************************************************************************
+static void
+am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer, void *pvArray,
+ uint32_t ui32Bytes)
+{
+ psBuffer->ui32WriteIndex = 0;
+ psBuffer->ui32ReadIndex = 0;
+ psBuffer->ui32Length = 0;
+ psBuffer->ui32Capacity = ui32Bytes;
+ psBuffer->pui8Data = (uint8_t *)pvArray;
+}
+
+//*****************************************************************************
+//
+//! @brief Poll for all host side read activity to complete.
+//!
+//! Poll for all host side read activity to complete. Use this before
+//! calling am_hal_ios_fifo_write_simple().
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_read_poll_complete(void)
+{
+ while ( AM_REG(IOSLAVE, FUPD) & AM_REG_IOSLAVE_FUPD_IOREAD_M );
+}
+
+//*****************************************************************************
+//
+//! @brief Initializes an SRAM buffer for the IOS FIFO.
+//!
+//! @param pui8Buffer is the SRAM buffer that will be used for IOS fifo data.
+//! @param ui32BufferSize is the size of the SRAM buffer.
+//!
+//! This function provides the IOS HAL functions with working memory for
+//! managing outgoing IOS FIFO transactions. It needs to be called at least
+//! once before am_hal_ios_fifo_write() may be used.
+//!
+//! The recommended buffer size for the IOS FIFO is 1024 bytes.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_fifo_buffer_init(uint8_t *pui8Buffer, uint32_t ui32NumBytes)
+{
+ //
+ // Initialize the global SRAM buffer
+ // Total size, which is SRAM Buffer plus the hardware FIFO needs to be
+ // limited to 1023
+ //
+ if ( ui32NumBytes > (1023 - g_ui32HwFifoSize + 1) )
+ {
+ ui32NumBytes = (1023 - g_ui32HwFifoSize + 1);
+ }
+
+ am_hal_ios_buffer_init(&g_sSRAMBuffer, pui8Buffer, ui32NumBytes);
+
+ //
+ // Clear the FIFO State
+ //
+ AM_BFW(IOSLAVE, FIFOCTR, FIFOCTR, 0x0);
+ AM_BFW(IOSLAVE, FIFOPTR, FIFOSIZ, 0x0);
+
+ am_hal_ios_fifo_ptr_set(g_ui32FifoBaseOffset);
+}
+
+//*****************************************************************************
+//
+//! @brief Update the FIFOCTR to inform host of available data to read.
+//!
+//! This function allows the application to indicate to HAL when it is safe to
+//! update the FIFOCTR.
+//!
+//! Application needs to implement some sort of
+//! synchronization with the host to make sure host is not reading FIFOCTR while
+//! it is being updated by the MCU, since the FIFOCTR read over
+//! IO is not an atomic operation.
+//!
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_ios_update_fifoctr(void)
+{
+ uint32_t ui32Val;
+ // Determine the available data
+ ui32Val = am_hal_ios_fifo_space_used();
+ // Update FIFOCTR
+ AM_BFW(IOSLAVE, FIFOCTR, FIFOCTR, ui32Val);
+ return;
+}
+
+//*****************************************************************************
+//
+// End the doxygen group
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_ios.h b/bsp/apollo2/libraries/drivers/hal/am_hal_ios.h
new file mode 100644
index 0000000000..b166c9c6e5
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_ios.h
@@ -0,0 +1,362 @@
+//*****************************************************************************
+//
+// am_hal_ios.h
+//! @file
+//!
+//! @brief Functions for interfacing with the IO Slave module
+//!
+//! @addtogroup ios2 IO Slave (SPI/I2C)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_IOS_H
+#define AM_HAL_IOS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! @name Interface Configuration
+//! @brief Macro definitions for configuring the physical interface of the IO
+//! Slave
+//!
+//! These macros may be used with the am_hal_ios_config_t structure to set the
+//! physical parameters of the SPI/I2C slave module.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOS_USE_SPI AM_REG_IOSLAVE_CFG_IFCSEL_SPI
+#define AM_HAL_IOS_SPIMODE_0 AM_REG_IOSLAVE_CFG_SPOL_SPI_MODES_0_3
+#define AM_HAL_IOS_SPIMODE_1 AM_REG_IOSLAVE_CFG_SPOL_SPI_MODES_1_2
+#define AM_HAL_IOS_SPIMODE_2 AM_REG_IOSLAVE_CFG_SPOL_SPI_MODES_1_2
+#define AM_HAL_IOS_SPIMODE_3 AM_REG_IOSLAVE_CFG_SPOL_SPI_MODES_0_3
+
+#define AM_HAL_IOS_USE_I2C AM_REG_IOSLAVE_CFG_IFCSEL_I2C
+#define AM_HAL_IOS_I2C_ADDRESS(n) AM_REG_IOSLAVE_CFG_I2CADDR(n)
+
+#define AM_HAL_IOS_LSB_FIRST AM_REG_IOSLAVE_CFG_LSB(1)
+//! @}
+
+//*****************************************************************************
+//
+//! @name Register Access Interrupts
+//! @brief Macro definitions for register access interrupts.
+//!
+//! These macros may be used with any of the
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOS_ACCESS_INT_00 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 31)
+#define AM_HAL_IOS_ACCESS_INT_01 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 30)
+#define AM_HAL_IOS_ACCESS_INT_02 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 29)
+#define AM_HAL_IOS_ACCESS_INT_03 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 28)
+#define AM_HAL_IOS_ACCESS_INT_04 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 27)
+#define AM_HAL_IOS_ACCESS_INT_05 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 26)
+#define AM_HAL_IOS_ACCESS_INT_06 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 25)
+#define AM_HAL_IOS_ACCESS_INT_07 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 24)
+#define AM_HAL_IOS_ACCESS_INT_08 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 23)
+#define AM_HAL_IOS_ACCESS_INT_09 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 22)
+#define AM_HAL_IOS_ACCESS_INT_0A AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 21)
+#define AM_HAL_IOS_ACCESS_INT_0B AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 20)
+#define AM_HAL_IOS_ACCESS_INT_0C AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 19)
+#define AM_HAL_IOS_ACCESS_INT_0D AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 18)
+#define AM_HAL_IOS_ACCESS_INT_0E AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 17)
+#define AM_HAL_IOS_ACCESS_INT_0F AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 16)
+#define AM_HAL_IOS_ACCESS_INT_13 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 15)
+#define AM_HAL_IOS_ACCESS_INT_17 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 14)
+#define AM_HAL_IOS_ACCESS_INT_1B AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 13)
+#define AM_HAL_IOS_ACCESS_INT_1F AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 12)
+#define AM_HAL_IOS_ACCESS_INT_23 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 11)
+#define AM_HAL_IOS_ACCESS_INT_27 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 10)
+#define AM_HAL_IOS_ACCESS_INT_2B AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 9)
+#define AM_HAL_IOS_ACCESS_INT_2F AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 8)
+#define AM_HAL_IOS_ACCESS_INT_33 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 7)
+#define AM_HAL_IOS_ACCESS_INT_37 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 6)
+#define AM_HAL_IOS_ACCESS_INT_3B AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 5)
+#define AM_HAL_IOS_ACCESS_INT_3F AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 4)
+#define AM_HAL_IOS_ACCESS_INT_43 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 3)
+#define AM_HAL_IOS_ACCESS_INT_47 AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 2)
+#define AM_HAL_IOS_ACCESS_INT_4B AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 1)
+#define AM_HAL_IOS_ACCESS_INT_4F AM_REG_IOSLAVE_REGACCINTEN_REGACC((uint32_t)1 << 0)
+#define AM_HAL_IOS_ACCESS_INT_ALL 0xFFFFFFFF
+//! @}
+
+//*****************************************************************************
+//
+//! @name I/O Slave Interrupts
+//! @brief Macro definitions for I/O slave (IOS) interrupts.
+//!
+//! These macros may be used with any of the
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOS_INT_FSIZE AM_REG_IOSLAVE_INTEN_FSIZE_M
+#define AM_HAL_IOS_INT_FOVFL AM_REG_IOSLAVE_INTEN_FOVFL_M
+#define AM_HAL_IOS_INT_FUNDFL AM_REG_IOSLAVE_INTEN_FUNDFL_M
+#define AM_HAL_IOS_INT_FRDERR AM_REG_IOSLAVE_INTEN_FRDERR_M
+#define AM_HAL_IOS_INT_GENAD AM_REG_IOSLAVE_INTEN_GENAD_M
+#define AM_HAL_IOS_INT_IOINTW AM_REG_IOSLAVE_INTEN_IOINTW_M
+#define AM_HAL_IOS_INT_XCMPWR AM_REG_IOSLAVE_INTEN_XCMPWR_M
+#define AM_HAL_IOS_INT_XCMPWF AM_REG_IOSLAVE_INTEN_XCMPWF_M
+#define AM_HAL_IOS_INT_XCMPRR AM_REG_IOSLAVE_INTEN_XCMPRR_M
+#define AM_HAL_IOS_INT_XCMPRF AM_REG_IOSLAVE_INTEN_XCMPRF_M
+#define AM_HAL_IOS_INT_ALL 0xFFFFFFFF
+//! @}
+
+//*****************************************************************************
+//
+//! @name I/O Slave Interrupts triggers
+//! @brief Macro definitions for I/O slave (IOS) interrupts.
+//!
+//! These macros may be used with am_hal_ios_int_set and am_hal_ios_int_clear
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_IOS_IOINTCTL_INT0 (0x01)
+#define AM_HAL_IOS_IOINTCTL_INT1 (0x02)
+#define AM_HAL_IOS_IOINTCTL_INT2 (0x04)
+#define AM_HAL_IOS_IOINTCTL_INT3 (0x08)
+#define AM_HAL_IOS_IOINTCTL_INT4 (0x10)
+#define AM_HAL_IOS_IOINTCTL_INT5 (0x20)
+//! @}
+
+//*****************************************************************************
+//
+// External variable definitions
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! @brief LRAM pointer
+//!
+//! Pointer to the base of the IO Slave LRAM.
+//
+//*****************************************************************************
+extern volatile uint8_t * const am_hal_ios_pui8LRAM;
+
+//*****************************************************************************
+//
+//! @brief Configuration structure for the IO slave module.
+//!
+//! This structure may be used along with the am_hal_ios_config() function to
+//! select key parameters of the IO Slave module. See the descriptions of each
+//! parameter within this structure for more information on what they control.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! Interface Selection
+ //!
+ //! This word selects the physical behavior of the IO Slave port. For SPI
+ //! mode, this word should be the logical OR of one or more of the
+ //! following:
+ //!
+ //! AM_HAL_IOS_USE_SPI
+ //! AM_HAL_IOS_SPIMODE_0
+ //! AM_HAL_IOS_SPIMODE_1
+ //! AM_HAL_IOS_SPIMODE_2
+ //! AM_HAL_IOS_SPIMODE_3
+ //!
+ //! For I2C mode, use the logical OR of one or more of these values instead
+ //! (where n is the 7 or 10-bit I2C address to use):
+ //!
+ //! AM_HAL_IOS_USE_I2C
+ //! AM_HAL_IOS_I2C_ADDRESS(n)
+ //!
+ //! Also, in any mode, you may OR in this value to reverse the order of
+ //! incoming data bits.
+ //!
+ //! AM_HAL_IOS_LSB_FIRST
+ //
+ uint32_t ui32InterfaceSelect;
+
+ //
+ //! Read-Only section
+ //!
+ //! The IO Slave LRAM is split into three main sections. The first section
+ //! is a "Direct Write" section, which may be accessed for reads or write
+ //! either directly through the Apollo CPU, or over the SPI/I2C bus. The
+ //! "Direct Write" section always begins at LRAM offset 0x0. At the end of
+ //! the normal "Direct Write" space, there is a "Read Only" space, which is
+ //! read/write accessible to the Apollo CPU, but read-only over the I2C/SPI
+ //! Bus. This word selects the base address of this "Read Only" space.
+ //!
+ //! This value may be set to any multiple of 8 between 0x0 and 0x78,
+ //! inclusive. For the configuration to be valid, \e ui32ROBase must also
+ //! be less than or equal to \e ui32FIFOBase
+ //!
+ //! @note The address given here is in units of BYTES. Since the location
+ //! of the "Read Only" space may only be set in 8-byte increments, this
+ //! value must be a multiple of 8.
+ //!
+ //! For the avoidance of doubt this means 0x80 is 128 bytes. These functions
+ //! will shift right by 8 internally.
+ //
+ uint32_t ui32ROBase;
+
+ //
+ //! FIFO section
+ //!
+ //! After the "Direct Access" and "Read Only" sections is a section of LRAM
+ //! allocated to a FIFO. This section is accessible by the Apollo CPU
+ //! through the FIFO control registers, and accessible on the SPI/I2C bus
+ //! through the 0x7F address. This word selects the base address of the
+ //! FIFO space. The FIFO will extend from the address specified here to the
+ //! address specified in \e ui32RAMBase.
+ //!
+ //! This value may be set to any multiple of 8 between 0x0 and 0x78,
+ //! inclusive. For the configuration to be valid, \e ui32FIFOBase must also
+ //! be greater than or equal to \e ui32ROBase.
+ //!
+ //! @note The address given here is in units of BYTES. Since the location
+ //! of the "FIFO" space may only be set in 8-byte increments, this value
+ //! must be a multiple of 8.
+ //!
+ //! For the avoidance of doubt this means 0x80 is 128 bytes. These functions
+ //! will shift right by 8 internally.
+ //
+ uint32_t ui32FIFOBase;
+
+ //
+ //! RAM section
+ //!
+ //! At the end of the IOS LRAM, the user may allocate a "RAM" space that
+ //! can only be accessed by the Apollo CPU. This space will not interact
+ //! with the SPI/I2C bus at all, and may be used as general-purpose memory.
+ //! Unlike normal SRAM, this section of LRAM will retain its state through
+ //! Deep Sleep, so it may be used as a data retention space for
+ //! ultra-low-power applications.
+ //!
+ //! This value may be set to any multiple of 8 between 0x0 and 0x100,
+ //! inclusive. For the configuration to be valid, \e ui32RAMBase must also
+ //! be greater than or equal to \e ui32FIFOBase.
+ //!
+ //! @note The address given here is in units of BYTES. Since the location
+ //! of the "FIFO" space may only be set in 8-byte increments, this value
+ //! must be a multiple of 8.
+ //!
+ //! For the avoidance of doubt this means 0x80 is 128 bytes. These functions
+ //! will shift right by 8 internally.
+ //
+ uint32_t ui32RAMBase;
+
+ //
+ //! FIFO threshold
+ //!
+ //! The IO Slave module will trigger an interrupt when the number of
+ //! entries in the FIFO drops below this number of bytes.
+ //
+ uint32_t ui32FIFOThreshold;
+
+ //
+ // Pointer to an SRAM
+ //
+ uint8_t *pui8SRAMBuffer;
+}
+am_hal_ios_config_t;
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_ios_enable(uint32_t ui32Module);
+extern void am_hal_ios_disable(uint32_t ui32Module);
+
+// these interrupts drive the HOST side IOS interrupt pins
+extern void am_hal_ios_host_int_set(uint32_t ui32Interrupt);
+extern void am_hal_ios_host_int_clear(uint32_t ui32Interrupt);
+extern uint32_t am_hal_ios_host_int_get(void);
+extern uint32_t am_hal_ios_host_int_enable_get(void);
+
+extern void am_hal_ios_lram_write(uint32_t ui32Offset, uint8_t ui8Value);
+extern uint8_t am_hal_ios_lram_read(uint32_t ui32Offset);
+
+// the following interrupts go back to the NVIC
+extern void am_hal_ios_config(am_hal_ios_config_t *psConfig);
+extern void am_hal_ios_access_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_ios_access_int_enable_get(void);
+extern void am_hal_ios_access_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_ios_access_int_clear(uint32_t ui32Interrupt);
+extern void am_hal_ios_access_int_set(uint32_t ui32Interrupt);
+extern uint32_t am_hal_ios_access_int_status_get(bool bEnabledOnly);
+extern void am_hal_ios_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_ios_int_enable_get(void);
+extern void am_hal_ios_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_ios_int_clear(uint32_t ui32Interrupt);
+extern void am_hal_ios_int_set(uint32_t ui32Interrupt);
+extern uint32_t am_hal_ios_int_status_get(bool bEnabledOnly);
+
+extern void am_hal_ios_fifo_buffer_init(uint8_t *pui8Buffer, uint32_t ui32NumBytes);
+extern uint32_t am_hal_ios_fifo_space_left(void);
+extern uint32_t am_hal_ios_fifo_space_used(void);
+extern void am_hal_ios_fifo_service(uint32_t ui32Status);
+// Returns the number of bytes actually written
+extern uint32_t am_hal_ios_fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes);
+extern void am_hal_ios_fifo_write_simple(uint8_t *pui8Data,
+ uint32_t ui32NumBytes);
+extern void am_hal_ios_fifo_ptr_set(uint32_t ui32Offset);
+extern void am_hal_ios_update_fifoctr(void);
+
+extern void am_hal_ios_read_poll_complete(void);
+extern void am_hal_ios_pwrctrl_enable(void);
+extern void am_hal_ios_pwrctrl_disable(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_IOS_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_itm.c b/bsp/apollo2/libraries/drivers/hal/am_hal_itm.c
new file mode 100644
index 0000000000..0f57c0d417
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_itm.c
@@ -0,0 +1,453 @@
+//*****************************************************************************
+//
+// am_hal_itm.c
+//! @file
+//!
+//! @brief Functions for operating the instrumentation trace macrocell
+//!
+//! @addtogroup itm2 Instrumentation Trace Macrocell (ITM)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Global Variables
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! @brief Delays for a desired amount of microseconds.
+//!
+//! @note - This function is based on the similar function in am_util_delay.c,
+//! please see that module for implementation details. It was necessary to
+//! duplicate it here to avoid having to update every example to include the
+//! am_util_delay.c module in its build.
+//!
+//! @returns None
+//
+//*****************************************************************************
+void
+am_hal_itm_delay_us(uint32_t ui32MicroSeconds)
+{
+ uint32_t ui32Iterations = ui32MicroSeconds *
+ (am_hal_clkgen_sysclk_get() / 3000000);
+
+ //
+ // Call the BOOTROM cycle delay function
+ //
+ am_hal_flash_delay(ui32Iterations);
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the ITM
+//!
+//! This function enables the ARM ITM by setting the TRCENA bit in the DEMCR
+//! register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_enable(void)
+{
+ if (g_ui32HALflags & AM_HAL_FLAGS_ITMSKIPENABLEDISABLE_M)
+ {
+ return;
+ }
+
+ //
+ // To be able to access ITM registers, set the Trace Enable bit
+ // in the Debug Exception and Monitor Control Register (DEMCR).
+ //
+ AM_REG(SYSCTRL, DEMCR) |= AM_REG_SYSCTRL_DEMCR_TRCENA(1);
+ while ( !(AM_REG(SYSCTRL, DEMCR) & AM_REG_SYSCTRL_DEMCR_TRCENA(1)) );
+
+ //
+ // Write the key to the ITM Lock Access register to unlock the ITM_TCR.
+ //
+ AM_REGVAL(AM_REG_ITM_LOCKAREG_O) = AM_REG_ITM_LOCKAREG_KEYVAL;
+
+ //
+ // Set the enable bits in the ITM trace enable register, and the ITM
+ // control registers to enable trace data output.
+ //
+ AM_REGVAL(AM_REG_ITM_TPR_O) = 0x0000000f;
+ AM_REGVAL(AM_REG_ITM_TER_O) = 0xffffffff;
+
+ //
+ // Write to the ITM control and status register (don't enable yet).
+ //
+ AM_REGVAL(AM_REG_ITM_TCR_O) =
+ AM_WRITE_SM(AM_REG_ITM_TCR_ATB_ID, 0x15) |
+ AM_WRITE_SM(AM_REG_ITM_TCR_TS_FREQ, 1) |
+ AM_WRITE_SM(AM_REG_ITM_TCR_TS_PRESCALE, 1) |
+ AM_WRITE_SM(AM_REG_ITM_TCR_SWV_ENABLE, 1) |
+ AM_WRITE_SM(AM_REG_ITM_TCR_DWT_ENABLE, 0) |
+ AM_WRITE_SM(AM_REG_ITM_TCR_SYNC_ENABLE, 0) |
+ AM_WRITE_SM(AM_REG_ITM_TCR_TS_ENABLE, 0) |
+ AM_WRITE_SM(AM_REG_ITM_TCR_ITM_ENABLE, 1);
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the ITM
+//!
+//! This function completely disables the ARM ITM by resetting the TRCENA bit
+//! in the DEMCR register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_disable(void)
+{
+
+ if (g_ui32HALflags & AM_HAL_FLAGS_ITMSKIPENABLEDISABLE_M)
+ {
+ return;
+ }
+
+ //
+ // Make sure the ITM_TCR is unlocked.
+ //
+ AM_REGVAL(AM_REG_ITM_LOCKAREG_O) = AM_REG_ITM_LOCKAREG_KEYVAL;
+
+ //
+ // Make sure the ITM/TPIU is not busy.
+ //
+ while ( AM_REG(ITM, TCR) & AM_REG_ITM_TCR_BUSY(1) );
+
+ //
+ // Disable the ITM.
+ //
+ for (int ix = 0; ix < 100; ix++)
+ {
+ AM_REG(ITM, TCR) &= ~AM_REG_ITM_TCR_ITM_ENABLE(1);
+ while ( AM_REG(ITM, TCR) & (AM_REG_ITM_TCR_ITM_ENABLE(1) | AM_REG_ITM_TCR_BUSY(1)) );
+ }
+
+ //
+ // Reset the TRCENA bit in the DEMCR register, which should disable the ITM
+ // for operation.
+ //
+ AM_REG(SYSCTRL, DEMCR) &= ~AM_REG_SYSCTRL_DEMCR_TRCENA(1);
+
+ //
+ // Disable the TPIU clock source in MCU control.
+ //
+ AM_REG(MCUCTRL, TPIUCTRL) = AM_REG_MCUCTRL_TPIUCTRL_CLKSEL_0MHz |
+ AM_REG_MCUCTRL_TPIUCTRL_ENABLE_DIS;
+}
+
+//*****************************************************************************
+//
+//! @brief Checks if itm is busy and provides a delay to flush the fifo
+//!
+//! This function disables the ARM ITM by resetting the TRCENA bit in the DEMCR
+//! register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_not_busy(void)
+{
+ //
+ // Make sure the ITM/TPIU is not busy.
+ //
+ while (AM_REG(ITM, TCR) & AM_REG_ITM_TCR_BUSY(1));
+
+ //
+ // wait for 50us for the data to flush out
+ //
+ am_hal_itm_delay_us(50);
+}
+
+//*****************************************************************************
+//
+//! @brief Enables tracing on a given set of ITM ports
+//!
+//! @param ui8portNum - Set ports to be enabled
+//!
+//! Enables tracing on the ports referred to by \e ui8portNum by writing the
+//! associated bit in the Trace Privilege Register in the ITM. The value for
+//! ui8portNum should be the logical OR one or more of the following values:
+//!
+//! \e ITM_PRIVMASK_0_7 - enable ports 0 through 7
+//! \e ITM_PRIVMASK_8_15 - enable ports 8 through 15
+//! \e ITM_PRIVMASK_16_23 - enable ports 16 through 23
+//! \e ITM_PRIVMASK_24_31 - enable ports 24 through 31
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_trace_port_enable(uint8_t ui8portNum)
+{
+ AM_REGVAL(AM_REG_ITM_TPR_O) |= (0x00000001 << (ui8portNum>>3));
+}
+
+//*****************************************************************************
+//
+//! @brief Disable tracing on the given ITM stimulus port.
+//!
+//! @param ui8portNum
+//!
+//! Disables tracing on the ports referred to by \e ui8portNum by writing the
+//! associated bit in the Trace Privilege Register in the ITM. The value for
+//! ui8portNum should be the logical OR one or more of the following values:
+//!
+//! \e ITM_PRIVMASK_0_7 - disable ports 0 through 7
+//! \e ITM_PRIVMASK_8_15 - disable ports 8 through 15
+//! \e ITM_PRIVMASK_16_23 - disable ports 16 through 23
+//! \e ITM_PRIVMASK_24_31 - disable ports 24 through 31
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_trace_port_disable(uint8_t ui8portNum)
+{
+ AM_REGVAL(AM_REG_ITM_TPR_O) &= ~(0x00000001 << (ui8portNum >> 3));
+}
+
+//*****************************************************************************
+//
+//! @brief Poll the given ITM stimulus register until not busy.
+//!
+//! @param ui32StimReg - stimulus register
+//!
+//! @return true if not busy, false if busy (timed out or other error).
+//
+//*****************************************************************************
+bool
+am_hal_itm_stimulus_not_busy(uint32_t ui32StimReg)
+{
+ uint32_t ui32StimAddr = (AM_REG_ITM_STIM0_O + (4 * ui32StimReg));
+
+ //
+ // Busy waiting until it is available, non-zero means ready.
+ //
+ while (!AM_REGVAL(ui32StimAddr));
+
+ return true;
+}
+
+//*****************************************************************************
+//
+//! @brief Writes a 32-bit value to the given ITM stimulus register.
+//!
+//! @param ui32StimReg - stimulus register
+//! @param ui32Value - value to be written.
+//!
+//! Write a word to the desired stimulus register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_stimulus_reg_word_write(uint32_t ui32StimReg, uint32_t ui32Value)
+{
+ uint32_t ui32StimAddr;
+
+ ui32StimAddr = (AM_REG_ITM_STIM0_O + (4 * ui32StimReg));
+
+ //
+ // Busy waiting until it is available, non-zero means ready
+ //
+ while (!AM_REGVAL(ui32StimAddr));
+
+ //
+ // Write the register.
+ //
+ AM_REGVAL(ui32StimAddr) = ui32Value;
+}
+
+//*****************************************************************************
+//
+//! @brief Writes a short to the given ITM stimulus register.
+//!
+//! @param ui32StimReg - stimulus register
+//! @param ui16Value - short to be written.
+//!
+//! Write a short to the desired stimulus register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_stimulus_reg_short_write(uint32_t ui32StimReg, uint16_t ui16Value)
+{
+ uint32_t ui32StimAddr;
+
+ ui32StimAddr = (AM_REG_ITM_STIM0_O + (4 * ui32StimReg));
+
+ //
+ // Busy waiting until it is available non-zero means ready
+ //
+ while (!AM_REGVAL(ui32StimAddr));
+
+ //
+ // Write the register.
+ //
+ *((volatile uint16_t *) ui32StimAddr) = ui16Value;
+}
+
+//*****************************************************************************
+//
+//! @brief Writes a byte to the given ITM stimulus register.
+//!
+//! @param ui32StimReg - stimulus register
+//! @param ui8Value - byte to be written.
+//!
+//! Write a byte to the desired stimulus register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_stimulus_reg_byte_write(uint32_t ui32StimReg, uint8_t ui8Value)
+{
+ uint32_t ui32StimAddr;
+
+ ui32StimAddr = (AM_REG_ITM_STIM0_O + (4 * ui32StimReg));
+
+ //
+ // Busy waiting until it is available (non-zero means ready)
+ //
+ while (!AM_REGVAL(ui32StimAddr));
+
+ //
+ // Write the register.
+ //
+ *((volatile uint8_t *) ui32StimAddr) = ui8Value;
+}
+
+//*****************************************************************************
+//
+//! @brief Sends a Sync Packet.
+//!
+//! Sends a sync packet. This can be useful for external software should it
+//! become out of sync with the ITM stream.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_sync_send(void)
+{
+ //
+ // Write the register.
+ //
+ am_hal_itm_stimulus_reg_word_write(AM_HAL_ITM_SYNC_REG,
+ AM_HAL_ITM_SYNC_VAL);
+}
+
+//*****************************************************************************
+//
+//! @brief Poll the print stimulus registers until not busy.
+//!
+//! @return true if not busy, false if busy (timed out or other error).
+//
+//*****************************************************************************
+bool
+am_hal_itm_print_not_busy(void)
+{
+ //
+ // Poll stimulus register allocated for printing.
+ //
+ am_hal_itm_stimulus_not_busy(0);
+
+
+ return true;
+}
+
+//*****************************************************************************
+//
+//! @brief Prints a char string out of the ITM.
+//!
+//! @param pcString pointer to the character sting
+//!
+//! This function prints a sting out of the ITM.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_itm_print(char *pcString)
+{
+ uint32_t ui32Length = 0;
+
+ //
+ // Determine the length of the string.
+ //
+ while (*(pcString + ui32Length))
+ {
+ ui32Length++;
+ }
+
+ //
+ // If there is no longer a word left, empty out the remaining characters.
+ //
+ while (ui32Length)
+ {
+ //
+ // Print string out the ITM.
+ //
+ am_hal_itm_stimulus_reg_byte_write(0, (uint8_t)*pcString++);
+
+ //
+ // Subtract from length.
+ //
+ ui32Length--;
+ }
+}
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_itm.h b/bsp/apollo2/libraries/drivers/hal/am_hal_itm.h
new file mode 100644
index 0000000000..e747b0ab65
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_itm.h
@@ -0,0 +1,107 @@
+//*****************************************************************************
+//
+// am_hal_itm.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the ARM ITM.
+//!
+//! @addtogroup itm2 Instrumentation Trace Macrocell (ITM)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#ifndef AM_HAL_ITM_H
+#define AM_HAL_ITM_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Sync Packet Defines
+//
+//*****************************************************************************
+#define AM_HAL_ITM_SYNC_REG 23
+#define AM_HAL_ITM_SYNC_VAL 0xF8F8F8F8
+
+//*****************************************************************************
+//
+// PrintF Setup
+//
+//*****************************************************************************
+#define AM_HAL_ITM_PRINT_NUM_BYTES 1
+#define AM_HAL_ITM_PRINT_NUM_REGS 1
+extern uint32_t am_hal_itm_print_registers[AM_HAL_ITM_PRINT_NUM_REGS];
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_itm_delay_us(uint32_t ui32MicroSeconds);
+extern void am_hal_itm_enable(void);
+extern void am_hal_itm_disable(void);
+extern void am_hal_itm_not_busy(void);
+extern void am_hal_itm_sync_send(void);
+extern void am_hal_itm_trace_port_enable(uint8_t ui8portNum);
+extern void am_hal_itm_trace_port_disable(uint8_t ui8portNum);
+extern bool am_hal_itm_stimulus_not_busy(uint32_t ui32StimReg);
+extern void am_hal_itm_stimulus_reg_word_write(uint32_t ui32StimReg,
+ uint32_t ui32Value);
+extern void am_hal_itm_stimulus_reg_short_write(uint32_t ui32StimReg,
+ uint16_t ui16Value);
+extern void am_hal_itm_stimulus_reg_byte_write(uint32_t ui32StimReg,
+ uint8_t ui8Value);
+extern bool am_hal_itm_print_not_busy(void);
+extern void am_hal_itm_print(char *pcString);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_ITM_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.c b/bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.c
new file mode 100644
index 0000000000..f7b60e3c1a
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.c
@@ -0,0 +1,292 @@
+//*****************************************************************************
+//
+// am_hal_mcuctrl.c
+//! @file
+//!
+//! @brief Functions for interfacing with the MCUCTRL.
+//!
+//! @addtogroup mcuctrl2 MCU Control (MCUCTRL)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+#define LDO_TRIM_REG_ADDR (0x50023004)
+#define BUCK_TRIM_REG_ADDR (0x50023000)
+
+//*****************************************************************************
+//
+// Global Variables.
+//
+//*****************************************************************************
+//
+// Define the flash sizes from CHIP_INFO.
+//
+const uint32_t g_am_hal_mcuctrl_flash_size[16] =
+{
+ 16 * 1024, /* 0x0 0x00004000 16 KB */
+ 32 * 1024, /* 0x1 0x00008000 32 KB */
+ 64 * 1024, /* 0x2 0x00010000 64 KB */
+ 128 * 1024, /* 0x3 0x00020000 128 KB */
+ 256 * 1024, /* 0x4 0x00040000 256 KB */
+ 512 * 1024, /* 0x5 0x00080000 512 KB */
+ 1 * 1024 * 1024, /* 0x6 0x00100000 1 MB */
+ 2 * 1024 * 1024, /* 0x7 0x00200000 2 MB */
+ 4 * 1024 * 1024, /* 0x8 0x00400000 4 MB */
+ 8 * 1024 * 1024, /* 0x9 0x00800000 8 MB */
+ 16 * 1024 * 1024, /* 0xA 0x01000000 16 MB */
+ 32 * 1024 * 1024, /* 0xB 0x02000000 32 MB */
+ 64 * 1024 * 1024, /* 0xC 0x04000000 64 MB */
+ 128 * 1024 * 1024, /* 0xD 0x08000000 128 MB */
+ 256 * 1024 * 1024, /* 0xE 0x10000000 256 MB */
+ 512 * 1024 * 1024 /* 0xF 0x20000000 512 MB */
+};
+
+//
+// Define the SRAM sizes from CHIP_INFO.
+// For Apollo2, the SRAM sizes are defined exactly the same as the flash sizes.
+//
+#define g_am_hal_mcuctrl_sram_size g_am_hal_mcuctrl_flash_size
+
+//*****************************************************************************
+//
+//! @brief Gets all relevant device information.
+//!
+//! @param psDevice is a pointer to a structure that will be used to store all
+//! device info.
+//!
+//! This function gets the device part number, chip IDs, and revision and
+//! stores them in the passed structure.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_mcuctrl_device_info_get(am_hal_mcuctrl_device_t *psDevice)
+{
+ //
+ // Read the Part Number.
+ //
+ psDevice->ui32ChipPN = AM_REG(MCUCTRL, CHIP_INFO);
+
+ //
+ // Read the Chip ID0.
+ //
+ psDevice->ui32ChipID0 = AM_REG(MCUCTRL, CHIPID0);
+
+ //
+ // Read the Chip ID1.
+ //
+ psDevice->ui32ChipID1 = AM_REG(MCUCTRL, CHIPID1);
+
+ //
+ // Read the Chip Revision.
+ //
+ psDevice->ui32ChipRev = AM_REG(MCUCTRL, CHIPREV);
+
+ //
+ // Read the Part Number.
+ //
+ psDevice->ui32ChipPN = AM_REG(MCUCTRL, CHIP_INFO);
+
+ //
+ // Read the Chip ID0.
+ //
+ psDevice->ui32ChipID0 = AM_REG(MCUCTRL, CHIPID0);
+
+ //
+ // Read the Chip ID1.
+ //
+ psDevice->ui32ChipID1 = AM_REG(MCUCTRL, CHIPID1);
+
+ //
+ // Read the Chip Revision.
+ //
+ psDevice->ui32ChipRev = AM_REG(MCUCTRL, CHIPREV);
+
+ //
+ // Read the Chip VENDOR ID.
+ //
+ psDevice->ui32VendorID = AM_REG(MCUCTRL, VENDORID);
+
+ //
+ // Qualified from Part Number.
+ //
+ psDevice->ui32Qualified =
+ (psDevice->ui32ChipPN & AM_HAL_MCUCTRL_CHIP_INFO_QUAL_M) >>
+ AM_HAL_MCUCTRL_CHIP_INFO_QUAL_S;
+
+ //
+ // Flash size from Part Number.
+ //
+ psDevice->ui32FlashSize =
+ g_am_hal_mcuctrl_flash_size[
+ (psDevice->ui32ChipPN & AM_HAL_MCUCTRL_CHIP_INFO_FLASH_SIZE_M) >>
+ AM_HAL_MCUCTRL_CHIP_INFO_FLASH_SIZE_S];
+
+ //
+ // SRAM size from Part Number.
+ //
+ psDevice->ui32SRAMSize =
+ g_am_hal_mcuctrl_flash_size[
+ (psDevice->ui32ChipPN & AM_HAL_MCUCTRL_CHIP_INFO_SRAM_SIZE_M) >>
+ AM_HAL_MCUCTRL_CHIP_INFO_SRAM_SIZE_S];
+
+ //
+ // Now, let's look at the JEDEC info.
+ // The full partnumber is 12 bits total, but is scattered across 2 registers.
+ // Bits [11:8] are 0xE.
+ // Bits [7:4] are 0xE for Apollo, 0xD for Apollo2.
+ // Bits [3:0] are defined differently for Apollo and Apollo2.
+ // For Apollo, the low nibble is 0x0.
+ // For Apollo2, the low nibble indicates flash and SRAM size.
+ //
+ psDevice->ui32JedecPN = (AM_BFR(JEDEC, PID0, PNL8) << 0);
+ psDevice->ui32JedecPN |= (AM_BFR(JEDEC, PID1, PNH4) << 8);
+
+ //
+ // JEPID is the JEP-106 Manufacturer ID Code, which is assigned to Ambiq as
+ // 0x1B, with parity bit is 0x9B. It is 8 bits located across 2 registers.
+ //
+ psDevice->ui32JedecJEPID = (AM_BFR(JEDEC, PID1, JEPIDL) << 0);
+ psDevice->ui32JedecJEPID |= (AM_BFR(JEDEC, PID2, JEPIDH) << 4);
+
+ //
+ // CHIPREV is 8 bits located across 2 registers.
+ //
+ psDevice->ui32JedecCHIPREV = (AM_BFR(JEDEC, PID2, CHIPREVH4) << 4);
+ psDevice->ui32JedecCHIPREV |= (AM_BFR(JEDEC, PID3, CHIPREVL4) << 0);
+
+ //
+ // Let's get the Coresight ID (32-bits across 4 registers)
+ // For Apollo and Apollo2, it's expected to be 0xB105100D.
+ //
+ psDevice->ui32JedecCID = (AM_BFR(JEDEC, CID3, CID) << 24);
+ psDevice->ui32JedecCID |= (AM_BFR(JEDEC, CID2, CID) << 16);
+ psDevice->ui32JedecCID |= (AM_BFR(JEDEC, CID1, CID) << 8);
+ psDevice->ui32JedecCID |= (AM_BFR(JEDEC, CID0, CID) << 0);
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the fault capture registers.
+//!
+//! This function enables the DCODEFAULTADDR and ICODEFAULTADDR registers.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_mcuctrl_fault_capture_enable(void)
+{
+ //
+ // Enable the Fault Capture registers.
+ //
+ AM_BFW(MCUCTRL, FAULTCAPTUREEN, ENABLE, 1);
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the fault capture registers.
+//!
+//! This function disables the DCODEFAULTADDR and ICODEFAULTADDR registers.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_mcuctrl_fault_capture_disable(void)
+{
+ //
+ // Disable the Fault Capture registers.
+ //
+ AM_BFW(MCUCTRL, FAULTCAPTUREEN, ENABLE, 0);
+}
+
+//*****************************************************************************
+//
+//! @brief Gets the fault status and capture registers.
+//!
+//! @param psFault is a pointer to a structure that will be used to store all
+//! fault info.
+//!
+//! This function gets the status of the ICODE, DCODE, and SYS bus faults and
+//! the addresses associated with the fault.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_mcuctrl_fault_status(am_hal_mcuctrl_fault_t *psFault)
+{
+ uint32_t ui32FaultStat;
+
+ //
+ // Read the Fault Status Register.
+ //
+ ui32FaultStat = AM_REG(MCUCTRL, FAULTSTATUS);
+ psFault->bICODE = (ui32FaultStat & AM_REG_MCUCTRL_FAULTSTATUS_ICODE_M);
+ psFault->bDCODE = (ui32FaultStat & AM_REG_MCUCTRL_FAULTSTATUS_DCODE_M);
+ psFault->bSYS = (ui32FaultStat & AM_REG_MCUCTRL_FAULTSTATUS_SYS_M);
+
+ //
+ // Read the DCODE fault capture address register.
+ //
+ psFault->ui32DCODE = AM_REG(MCUCTRL, DCODEFAULTADDR);
+
+ //
+ // Read the ICODE fault capture address register.
+ //
+ psFault->ui32ICODE |= AM_REG(MCUCTRL, ICODEFAULTADDR);
+
+ //
+ // Read the ICODE fault capture address register.
+ //
+ psFault->ui32SYS |= AM_REG(MCUCTRL, SYSFAULTADDR);
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.h b/bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.h
new file mode 100644
index 0000000000..6811006fd6
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_mcuctrl.h
@@ -0,0 +1,212 @@
+//*****************************************************************************
+//
+// am_hal_mcuctrl.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the MCUCTRL.
+//!
+//! @addtogroup mcuctrl2 MCU Control (MCUCTRL)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_MCUCTRL_H
+#define AM_HAL_MCUCTRL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//
+// Deprecate the am_hal_mcuctrl_bucks_enable() and disable() functions.
+// This functionality is now handled in pwrctrl.
+//
+#define am_hal_mcuctrl_bucks_enable am_hal_pwrctrl_bucks_enable
+#define am_hal_mcuctrl_bucks_disable am_hal_pwrctrl_bucks_disable
+
+
+//*****************************************************************************
+//
+// Define CHIP_INFO fields, which for Apollo2 are not defined in the register
+// definitions.
+//
+//*****************************************************************************
+#define AM_HAL_MCUCTRL_CHIP_INFO_CLASS_M 0xFF000000
+#define AM_HAL_MCUCTRL_CHIP_INFO_CLASS_S 24
+#define AM_HAL_MCUCTRL_CHIP_INFO_FLASH_SIZE_M 0x00F00000
+#define AM_HAL_MCUCTRL_CHIP_INFO_FLASH_SIZE_S 20
+#define AM_HAL_MCUCTRL_CHIP_INFO_SRAM_SIZE_M 0x000F0000
+#define AM_HAL_MCUCTRL_CHIP_INFO_SRAM_SIZE_S 16
+#define AM_HAL_MCUCTRL_CHIP_INFO_REV_M 0x0000FF00
+#define AM_HAL_MCUCTRL_CHIP_INFO_REV_S 8
+#define AM_HAL_MCUCTRL_CHIP_INFO_PKG_M 0x000000C0
+#define AM_HAL_MCUCTRL_CHIP_INFO_PKG_S 6
+#define AM_HAL_MCUCTRL_CHIP_INFO_PINS_M 0x00000038
+#define AM_HAL_MCUCTRL_CHIP_INFO_PINS_S 3
+#define AM_HAL_MCUCTRL_CHIP_INFO_TEMP_M 0x00000006
+#define AM_HAL_MCUCTRL_CHIP_INFO_TEMP_S 1
+#define AM_HAL_MCUCTRL_CHIP_INFO_QUAL_M 0x00000001
+#define AM_HAL_MCUCTRL_CHIP_INFO_QUAL_S 0
+
+//*****************************************************************************
+//
+// Apollo Number Decode.
+//
+//*****************************************************************************
+extern const uint32_t g_am_hal_mcuctrl_flash_size[];
+extern const uint32_t g_am_hal_mcuctrl_sram_size[];
+
+//*****************************************************************************
+//
+//! MCUCTRL device structure
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! Device part number. (BCD format)
+ //
+ uint32_t ui32ChipPN;
+
+ //
+ //! Unique Chip ID 0.
+ //
+ uint32_t ui32ChipID0;
+
+ //
+ //! Unique Chip ID 1.
+ //
+ uint32_t ui32ChipID1;
+
+ //
+ //! Chip Revision.
+ //
+ uint32_t ui32ChipRev;
+
+ //
+ //! Vendor ID.
+ //
+ uint32_t ui32VendorID;
+
+ //
+ //! Qualified chip.
+ //
+ uint32_t ui32Qualified;
+
+ //
+ //! Flash Size.
+ //
+ uint32_t ui32FlashSize;
+
+ //
+ //! SRAM Size.
+ //
+ uint32_t ui32SRAMSize;
+
+ //
+ // JEDEC chip info
+ //
+ uint32_t ui32JedecPN;
+ uint32_t ui32JedecJEPID;
+ uint32_t ui32JedecCHIPREV;
+ uint32_t ui32JedecCID;
+}
+am_hal_mcuctrl_device_t;
+
+//*****************************************************************************
+//
+//! MCUCTRL fault structure
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! ICODE bus fault occurred.
+ //
+ bool bICODE;
+
+ //
+ //! ICODE bus fault address.
+ //
+ uint32_t ui32ICODE;
+
+ //
+ //! DCODE bus fault occurred.
+ //
+ bool bDCODE;
+
+ //
+ //! DCODE bus fault address.
+ //
+ uint32_t ui32DCODE;
+
+ //
+ //! SYS bus fault occurred.
+ //
+ bool bSYS;
+
+ //
+ //! SYS bus fault address.
+ //
+ uint32_t ui32SYS;
+}
+am_hal_mcuctrl_fault_t;
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_mcuctrl_device_info_get(am_hal_mcuctrl_device_t *psDevice);
+extern void am_hal_mcuctrl_fault_capture_enable(void);
+extern void am_hal_mcuctrl_fault_capture_disable(void);
+extern void am_hal_mcuctrl_fault_status(am_hal_mcuctrl_fault_t *psFault);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_MCUCTRL_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_otp.c b/bsp/apollo2/libraries/drivers/hal/am_hal_otp.c
new file mode 100644
index 0000000000..67d08448da
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_otp.c
@@ -0,0 +1,173 @@
+//*****************************************************************************
+//
+// am_hal_otp.c
+//! @file
+//!
+//! @brief Functions for handling the OTP interface.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#include "am_mcu_apollo.h"
+#include "am_hal_flash.h"
+
+//*****************************************************************************
+//
+//! THIS FUNCTION IS DEPRECATED!
+//! Use the respective HAL flash function instead.
+//!
+// @brief Check if debugger is currently locked out.
+//
+// @param None.
+//
+// Determine if the debugger is already locked out.
+//
+// @return non-zero if debugger is currently locked out.
+// Specifically:
+// 0 = debugger is not locked out.
+// 1 = debugger is locked out.
+//
+//*****************************************************************************
+int
+am_hal_otp_is_debugger_lockedout(void)
+{
+ return am_hal_flash_debugger_disable_check();
+}
+
+//*****************************************************************************
+//
+//! THIS FUNCTION IS DEPRECATED!
+//! Use the respective HAL flash function instead.
+//!
+// @brief Lock out debugger access.
+//
+// @param None.
+//
+// This function locks out access by a debugger.
+//
+// @return 0 if lockout was successful or if lockout was already enabled.
+//
+//*****************************************************************************
+int
+am_hal_otp_debugger_lockout(void)
+{
+ return am_hal_flash_debugger_disable();
+}
+
+//*****************************************************************************
+//
+//! THIS FUNCTION IS DEPRECATED!
+//! Use the respective HAL flash function instead.
+//!
+// @brief Lock out SRAM access.
+//
+// @param None.
+//
+// This function locks out access by a debugger to SRAM.
+//
+// @return 0 if lockout was successful or if lockout was already enabled.
+// Low byte=0xff, byte 1 contains current value of lockout.
+// Else, return value from HAL programming function.
+//
+//*****************************************************************************
+int
+am_hal_otp_sram_lockout(void)
+{
+ return am_hal_flash_wipe_sram_enable();
+}
+
+//*****************************************************************************
+//
+//! THIS FUNCTION IS DEPRECATED!
+//! Use the respective HAL flash function instead.
+//!
+// @brief Set copy (read) protection.
+//
+// @param @u32BegAddr The beginning address to be copy protected.
+// @u32EndAddr The ending address to be copy protected.
+//
+// @note For Apollo, the u32BegAddr parameter should be on a 16KB boundary, and
+// the u32EndAddr parameter should be on a (16KB-1) boundary. Otherwise
+// both parameters will be truncated/expanded to do so.
+// For example, if u32BegAddr=0x1000 and u32EndAddr=0xC200, the actual
+// range that protected is: 0x0 - 0xFFFF.
+//
+// This function enables copy protection on a given flash address range.
+//
+// @return 0 if copy protection was successfully enabled.
+//
+//*****************************************************************************
+int
+am_hal_otp_set_copy_protection(uint32_t u32BegAddr, uint32_t u32EndAddr)
+{
+ return am_hal_flash_copy_protect_set((uint32_t*)u32BegAddr,
+ (uint32_t*)u32EndAddr);
+}
+
+//*****************************************************************************
+//
+//! THIS FUNCTION IS DEPRECATED!
+//! Use the respective HAL flash function instead.
+//!
+// @brief Set write protection.
+//
+// @param @u32BegAddr The beginning address to be write protected.
+// @u32EndAddr The ending address to be write protected.
+//
+// @note For Apollo, the u32BegAddr parameter should be on a 16KB boundary, and
+// the u32EndAddr parameter should be on a (16KB-1) boundary. Otherwise
+// both parameters will be truncated/expanded to do so.
+// For example, if u32BegAddr=0x1000 and u32EndAddr=0xC200, the actual
+// range that protected is: 0x0 - 0xFFFF.
+//
+// This function enables write protection on a given flash address range.
+//
+// @return 0 if write protection was successfully enabled.
+//
+//*****************************************************************************
+int
+am_hal_otp_set_write_protection(uint32_t u32BegAddr, uint32_t u32EndAddr)
+{
+ return am_hal_flash_write_protect_set((uint32_t*)u32BegAddr,
+ (uint32_t*)u32EndAddr);
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_otp.h b/bsp/apollo2/libraries/drivers/hal/am_hal_otp.h
new file mode 100644
index 0000000000..d938e916fb
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_otp.h
@@ -0,0 +1,108 @@
+//*****************************************************************************
+//
+// am_hal_otp.h
+//! @file
+//!
+//! @brief Functions for handling the OTP interface.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_OTP_H
+#define AM_HAL_OTP_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Define some OTP values and macros.
+//
+//*****************************************************************************
+#define AM_HAL_OTP_SIG0 0x00
+#define AM_HAL_OTP_SIG1 0x04
+#define AM_HAL_OTP_SIG2 0x08
+#define AM_HAL_OTP_SIG3 0x0C
+
+#define AM_HAL_OTP_DBGR_O 0x10
+#define AM_HAL_OTP_WRITPROT0_O 0x20
+#define AM_HAL_OTP_WRITPROT1_O 0x24
+#define AM_HAL_OTP_COPYPROT0_O 0x30
+#define AM_HAL_OTP_COPYPROT1_O 0x34
+
+#define AM_HAL_OTP_ADDR 0x50020000
+#define AM_HAL_OTP_DBGRPROT_ADDR (AM_HAL_OTP_ADDR + AM_HAL_OTP_DBGR_O)
+#define AM_HAL_OTP_WRITPROT_ADDR (AM_HAL_OTP_ADDR + AM_HAL_OTP_WRITPROT0_O)
+#define AM_HAL_OTP_COPYPROT_ADDR (AM_HAL_OTP_ADDR + AM_HAL_OTP_COPYPROT0_O)
+
+#define AM_HAL_OTP_CHUNKSIZE (16*1024)
+
+//
+// Debugger port lockout macros.
+//
+#define AM_OTP_DBGR_LOCKOUT_S (0)
+#define AM_OTP_DBGR_LOCKOUT_M (0x1 << AM_OTP_DBGR_LOCKOUT_S)
+#define AM_OTP_STRM_LOCKOUT_S (1)
+#define AM_OTP_STRM_LOCKOUT_M (0x1 << AM_OTP_STRM_LOCKOUT_S)
+#define AM_OTP_SRAM_LOCKOUT_S (2)
+#define AM_OTP_SRAM_LOCKOUT_M (0x1 << AM_OTP_SRAM_LOCKOUT_S)
+
+//*****************************************************************************
+//
+// Function prototypes
+//
+//*****************************************************************************
+extern int am_hal_otp_is_debugger_lockedout(void);
+extern int am_hal_otp_debugger_lockout(void);
+extern int am_hal_otp_sram_lockout(void);
+extern int am_hal_otp_set_copy_protection(uint32_t u32BegAddr, uint32_t u32EndAddr);
+extern int am_hal_otp_set_write_protection(uint32_t u32BegAddr, uint32_t u32EndAddr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_OTP_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_pdm.c b/bsp/apollo2/libraries/drivers/hal/am_hal_pdm.c
new file mode 100644
index 0000000000..45acfab995
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_pdm.c
@@ -0,0 +1,158 @@
+//*****************************************************************************
+//
+// am_hal_pdm.c
+//! @file
+//!
+//! @brief Functions for interfacing with Pulse Density Modulation (PDM).
+//!
+//! @addtogroup pdm2 DMEMS Microphon3 (PDM)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Configure the PDM module.
+//!
+//! This function reads the an \e am_hal_pdm_config_t structure and uses it to
+//! set up the PDM module.
+//!
+//! Please see the information on the am_hal_pdm_config_t configuration
+//! structure, found in am_hal_pdm.h, for more information on the parameters
+//! that may be set by this function.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_pdm_config(am_hal_pdm_config_t *psConfig)
+{
+ //
+ // setup the PDM PCFG register
+ //
+ AM_REG(PDM, PCFG) = psConfig->ui32PDMConfigReg;
+
+ //
+ // setup the PDM VCFG register
+ //
+ AM_REG(PDM, VCFG) = psConfig->ui32VoiceConfigReg;
+
+ //
+ // setup the PDM FIFO Threshold register
+ //
+ AM_REG(PDM, FTHR) = psConfig->ui32FIFOThreshold;
+
+ //
+ // Flush the FIFO for good measure.
+ //
+ am_hal_pdm_fifo_flush();
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the PDM module.
+//!
+//! This function enables the PDM module in the mode previously defined by
+//! am_hal_pdm_config().
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_pdm_enable(void)
+{
+ AM_REG(PDM, PCFG) |= AM_REG_PDM_PCFG_PDMCORE_EN;
+ AM_REG(PDM, VCFG) |= ( AM_REG_PDM_VCFG_IOCLKEN_EN |
+ AM_REG_PDM_VCFG_PDMCLK_EN |
+ AM_REG_PDM_VCFG_RSTB_NORM );
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the PDM module.
+//!
+//! This function disables the PDM module.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_pdm_disable(void)
+{
+ AM_REG(PDM, PCFG) &= ~ AM_REG_PDM_PCFG_PDMCORE_EN;
+ AM_REG(PDM, VCFG) &= ~ ( AM_REG_PDM_VCFG_IOCLKEN_EN |
+ AM_REG_PDM_VCFG_PDMCLK_EN |
+ AM_REG_PDM_VCFG_RSTB_NORM );
+}
+
+//*****************************************************************************
+//
+//! @brief Return the PDM Interrupt status.
+//!
+//! @param bEnabledOnly - return only the enabled interrupts.
+//!
+//! Use this function to get the PDM interrupt status.
+//!
+//! @return intrrupt status
+//
+//*****************************************************************************
+uint32_t
+am_hal_pdm_int_status_get(bool bEnabledOnly)
+{
+ if ( bEnabledOnly )
+ {
+ uint32_t u32RetVal = AM_REG(PDM, INTSTAT);
+ return u32RetVal & AM_REG(PDM, INTEN);
+ }
+ else
+ {
+ return AM_REG(PDM, INTSTAT);
+ }
+}
+
+//*****************************************************************************
+//
+// End the doxygen group
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_pdm.h b/bsp/apollo2/libraries/drivers/hal/am_hal_pdm.h
new file mode 100644
index 0000000000..a6e23d2698
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_pdm.h
@@ -0,0 +1,665 @@
+//*****************************************************************************
+//
+// am_hal_pdm.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the PDM module
+//!
+//! @addtogroup pdm2 Pulse Density Modulation (PDM) Input Module.
+//! @ingroup apollo2hal
+//! @{
+
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#ifndef AM_HAL_PDM_H
+#define AM_HAL_PDM_H
+
+//*****************************************************************************
+//
+// Macro definitions
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! @name PDM Left Right Swap Control
+//! @brief Macro definitions for the PDM LRSWAP bit field
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! left right swap bit.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_LRSWAP_ENABLE \
+ AM_REG_PDM_PCFG_LRSWAP_EN
+#define AM_HAL_PDM_PCFG_LRSWAP_DISABLE \
+ AM_REG_PDM_PCFG_LRSWAP_NOSWAP
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Right Gain Setting
+//! @brief Macro definitions for the PDM Right Gain Setting.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! right gain value.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M15DB AM_REG_PDM_PCFG_PGARIGHT_M15DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M300DB AM_REG_PDM_PCFG_PGARIGHT_M300DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M45DB AM_REG_PDM_PCFG_PGARIGHT_M45DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M60DB AM_REG_PDM_PCFG_PGARIGHT_M60DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M75DB AM_REG_PDM_PCFG_PGARIGHT_M75DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M90DB AM_REG_PDM_PCFG_PGARIGHT_M90DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M105DB AM_REG_PDM_PCFG_PGARIGHT_M105DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_M120DB AM_REG_PDM_PCFG_PGARIGHT_M120DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_P105DB AM_REG_PDM_PCFG_PGARIGHT_P105DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_P90DB AM_REG_PDM_PCFG_PGARIGHT_P90DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_P75DB AM_REG_PDM_PCFG_PGARIGHT_P75DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_P60DB AM_REG_PDM_PCFG_PGARIGHT_P60DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_P45DB AM_REG_PDM_PCFG_PGARIGHT_P45DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_P300DB AM_REG_PDM_PCFG_PGARIGHT_P300DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_P15DB AM_REG_PDM_PCFG_PGARIGHT_P15DB
+#define AM_HAL_PDM_PCFG_RIGHT_PGA_0DB AM_REG_PDM_PCFG_PGARIGHT_0DB
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Left Gain Setting
+//! @brief Macro definitions for the PDM Left Gain Setting.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! left gain value.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M15DB AM_REG_PDM_PCFG_PGALEFT_M15DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M300DB AM_REG_PDM_PCFG_PGALEFT_M300DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M45DB AM_REG_PDM_PCFG_PGALEFT_M45DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M60DB AM_REG_PDM_PCFG_PGALEFT_M60DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M75DB AM_REG_PDM_PCFG_PGALEFT_M75DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M90DB AM_REG_PDM_PCFG_PGALEFT_M90DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M105DB AM_REG_PDM_PCFG_PGALEFT_M105DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_M120DB AM_REG_PDM_PCFG_PGALEFT_M120DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_P105DB AM_REG_PDM_PCFG_PGALEFT_P105DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_P90DB AM_REG_PDM_PCFG_PGALEFT_P90DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_P75DB AM_REG_PDM_PCFG_PGALEFT_P75DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_P60DB AM_REG_PDM_PCFG_PGALEFT_P60DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_P45DB AM_REG_PDM_PCFG_PGALEFT_P45DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_P300DB AM_REG_PDM_PCFG_PGALEFT_P300DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_P15DB AM_REG_PDM_PCFG_PGALEFT_P15DB
+#define AM_HAL_PDM_PCFG_LEFT_PGA_0DB AM_REG_PDM_PCFG_PGALEFT_0DB
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Configuration MCLK Divider
+//! @brief Macro definitions for the PDM MCLK Divider
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! sinc decimation rate relative to the PDM sample clock (OSR).
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_MCLKDIV_DIV1 AM_REG_PDM_PCFG_MCLKDIV_MCKDIV1
+#define AM_HAL_PDM_PCFG_MCLKDIV_DIV2 AM_REG_PDM_PCFG_MCLKDIV_MCKDIV2
+#define AM_HAL_PDM_PCFG_MCLKDIV_DIV3 AM_REG_PDM_PCFG_MCLKDIV_MCKDIV3
+#define AM_HAL_PDM_PCFG_MCLKDIV_DIV4 AM_REG_PDM_PCFG_MCLKDIV_MCKDIV4
+
+#define AM_HAL_PDM_PCFG_MCLKDIV(DIV) AM_REG_PDM_PCFG_MCLKDIV(DIV)
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Configuration SINC Decimation Rate
+//! @brief Macro definitions for the PDM SINC decimation rate
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! sinc decimation rate relative to the PDM sample clock (OSR).
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_SINC_RATE(OSR) \
+ AM_REG_PDM_PCFG_SINCRATE(OSR)
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Configuration High Pass Filter Enable
+//! @brief Macro definitions for the PDM ADCHPD
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! the high pass filter.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_ADCHPD_ENABLE AM_REG_PDM_PCFG_ADCHPD_EN
+#define AM_HAL_PDM_PCFG_ADCHPD_DISABLE AM_REG_PDM_PCFG_ADCHPD_DIS
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Configuration HPCUTOFF
+//! @brief Macro definitions for the PDM High Pass Filter Cutoff Selector.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! high pass filter cutoff frequency. Valid range is 0 to 7.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_HPCUTOFF(HPSEL) \
+ AM_REG_PDM_PCFG_HPCUTOFF(HPSEL)
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Configuration Gain Set Change Clock Delay
+//! @brief Macro definitions for the PDM clock delay for gain set changes.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! number of clocks for spreading gain setting changes. Valid range is 0 to 7.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_CYCLES(CLOCKS) \
+ AM_REG_PDM_PCFG_CYCLES(CLOCKS)
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Configuration SOFTMUTE enable/disable.
+//! @brief Macro definitions for the PDM PCFG register mute controls.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! or disable the SOFTMUTE option.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_SOFTMUTE_ENABLE AM_REG_PDM_PCFG_SOFTMUTE_EN
+#define AM_HAL_PDM_PCFG_SOFTMUTE_DISABLE AM_REG_PDM_PCFG_SOFTMUTE_DIS
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Configuration PDM Core enable/disable.
+//! @brief Macro definitions for the PDM PCFG register filter engine enable.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! or disable the PDM filter engine core.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_PCFG_PDMCORE_ENABLE AM_REG_PDM_PCFG_PDMCORE_EN
+#define AM_HAL_PDM_PCFG_PDMCORE_DISABLE AM_REG_PDM_PCFG_PDMCORE_DIS
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Clock Frequencies
+//! @brief Macro definitions for the PDM clock (from clkgen) frequencies.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! source clock frequency of the PDM interface.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_IOCLK_12MHZ \
+ (AM_REG_PDM_VCFG_PDMCLKSEL_12MHz | AM_REG_PDM_VCFG_IOCLKEN_EN)
+#define AM_HAL_PDM_IOCLK_6MHZ \
+ (AM_REG_PDM_VCFG_PDMCLKSEL_6MHz | AM_REG_PDM_VCFG_IOCLKEN_EN)
+#define AM_HAL_PDM_IOCLK_3MHZ \
+ (AM_REG_PDM_VCFG_PDMCLKSEL_3MHz | AM_REG_PDM_VCFG_IOCLKEN_EN)
+#define AM_HAL_PDM_IOCLK_1_5MHZ \
+ (AM_REG_PDM_VCFG_PDMCLKSEL_1_5MHz | AM_REG_PDM_VCFG_IOCLKEN_EN)
+#define AM_HAL_PDM_IOCLK_750KHZ \
+ (AM_REG_PDM_VCFG_PDMCLKSEL_750KHz | AM_REG_PDM_VCFG_IOCLKEN_EN)
+#define AM_HAL_PDM_IOCLK_375KHZ \
+ (AM_REG_PDM_VCFG_PDMCLKSEL_375KHz | AM_REG_PDM_VCFG_IOCLKEN_EN)
+#define AM_HAL_PDM_IOCLK_187KHZ \
+ (AM_REG_PDM_VCFG_PDMCLKSEL_187KHz | AM_REG_PDM_VCFG_IOCLKEN_EN)
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Voice Configuration RSTB
+//! @brief Reset the IP core.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_RSTB_RESET AM_REG_PDM_VCFG_RSTB_RESET
+#define AM_HAL_PDM_VCFG_RSTB_NORMAL AM_REG_PDM_VCFG_RSTB_NORM
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Voice Configuration PDM Clock Enable/Disable
+//! @brief Macro definitions for the PDM VCFG register PDMCLKEN.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! or disable the PDM clock output to the pad mux and from there to the world.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_PDMCLK_ENABLE AM_REG_PDM_VCFG_PDMCLK_EN
+#define AM_HAL_PDM_VCFG_PDMCLK_DISABLE AM_REG_PDM_VCFG_PDMCLK_DIS
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Voice Configuration I2S Mode Enable/Disable
+//! @brief Macro definitions for the PDM VCFG register I2SMODE.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! or disable the PDM clock output to the pad mux and from there to the world.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_I2SMODE_ENABLE AM_REG_PDM_VCFG_I2SMODE_EN
+#define AM_HAL_PDM_VCFG_I2SMODE_DISABLE AM_REG_PDM_VCFG_I2SMODE_DIS
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Voice Configuration BCLK Inversion Enable/Disable
+//! @brief Macro definitions for the PDM VCFG register BCLKINV.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! or disable the PDM clock output to the pad mux and from there to the world.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_BCLKINV_ENABLE AM_REG_PDM_VCFG_BCLKINV_INV
+#define AM_HAL_PDM_VCFG_BCLKINV_DISABLE AM_REG_PDM_VCFG_BCLKINV_NORM
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Voice Configuration DMICDEL Enable/Disable
+//! @brief Macro definitions for the PDM VCFG register Digital Mic Delay.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! or disable the PDM digital microphone clock delay.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_DMICDEL_1CYC AM_REG_PDM_VCFG_DMICKDEL_1CYC
+#define AM_HAL_PDM_VCFG_DMICDEL_0CYC AM_REG_PDM_VCFG_DMICKDEL_0CYC
+#define AM_HAL_PDM_VCFG_DMICDEL_ENABLE AM_REG_PDM_VCFG_DMICKDEL_1CYC
+#define AM_HAL_PDM_VCFG_DMICDEL_DISABLE AM_REG_PDM_VCFG_DMICKDEL_0CYC
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Voice Configuration Select Apps Processor (AP) versus Internal
+//! @brief Macro definitions for the PDM VCFG register Digital Mic Delay.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to select
+//! the Application Processor (I2S slave) mode or the Internal FIFO interface
+//! to the Apollo Cortex M4.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_SELAP_I2S AM_REG_PDM_VCFG_SELAP_I2S
+#define AM_HAL_PDM_VCFG_SELAP_INTERNAL AM_REG_PDM_VCFG_SELAP_INTERNAL
+#define AM_HAL_PDM_VCFG_SELAP_AP_I2S AM_REG_PDM_VCFG_SELAP_I2S
+#define AM_HAL_PDM_VCFG_SELAP_CM4_FIFO AM_REG_PDM_VCFG_SELAP_INTERNAL
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Voice Configuration PACK Enable/Disable
+//! @brief Macro definitions for the PDM VCFG register sample packing mode.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to enable
+//! or disable the PDM sample packing mode. This mode puts two 16-bit samples
+//! per 32-bit FIFO word. The following packed modes are available:
+//!
+//! mono left: LEFT_NEW, LEFT_OLD
+//! mono right: RIGHT_NEW,RIGHT_OLD
+//! stereo right: LEFT, RIGHT
+//! stereo right(LRSWAP): RIGHT, LEFT
+//!
+//!
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_PACK_ENABLE AM_REG_PDM_VCFG_PCMPACK_EN
+#define AM_HAL_PDM_VCFG_PACK_DISABLE AM_REG_PDM_VCFG_PCMPACK_DIS
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Channel Selects
+//! @brief Macro definitions for the PDM Channel Selection.
+//!
+//! These macros may be used with the am_hal_pdm_config_t structure to set the
+//! channel selection for the PDM interface.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_VCFG_CHANNEL_LEFT AM_REG_PDM_VCFG_CHSET_LEFT
+#define AM_HAL_PDM_VCFG_CHANNEL_RIGHT AM_REG_PDM_VCFG_CHSET_RIGHT
+#define AM_HAL_PDM_VCFG_CHANNEL_STEREO AM_REG_PDM_VCFG_CHSET_STEREO
+//! @}
+
+//*****************************************************************************
+//
+//! @name PDM Interrupts
+//! @brief Macro definitions for the PDM interrupt status bits.
+//!
+//! These macros correspond to the bits in the PDM interrupt status register.
+//! They may be used for any of the am_hal_pdm_int_x() functions.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_PDM_INT_UNDFL AM_REG_PDM_INTEN_UNDFL_M
+#define AM_HAL_PDM_INT_OVF AM_REG_PDM_INTEN_OVF_M
+#define AM_HAL_PDM_INT_FIFO AM_REG_PDM_INTEN_THR_M
+//! @}
+
+//*****************************************************************************
+//
+//! @brief Configuration structure for the PDM module.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! @brief Set the PDM configuration reg with the values in this member.
+ //! Choose from AM_HAL_PDM_PCFG macros.
+ //! AM_HAL_PDM_PCFG_LRSWAP_xxx
+ //! AM_HAL_PDM_PCFG_RIGHT_PGA_xxx
+ //! AM_HAL_PDM_PCFG_LEFT_PGA_xxx
+ //! AM_HAL_PDM_PCFG_MCLKDIV_xxx
+ //! AM_HAL_PDM_PCFG_SINC_RATE()
+ //! AM_HAL_PDM_PCFG_ADCHPD_xxx
+ //! AM_HAL_PDM_PCFG_HPCUTOFF()
+ //! AM_HAL_PDM_PCFG_CYCLES()
+ //! AM_HAL_PDM_PCFG_SOFTMUTE_xxx
+ //! * AM_HAL_PDM_PCFG_PDMCORE_EN
+ //! AM_HAL_PDM_PCFG_PDMCORE_DISABLE
+ //
+ uint32_t ui32PDMConfigReg;
+
+ //
+ //! @brief Set the Voice Configuration reg with the values in this member.
+ //! Choose from AM_HAL_PDM_VCFG macros.
+ //! AM_HAL_PDM_IOCLK_xxx (also sets AM_REG_PDM_VCFG_IOCLKEN_EN)
+ //! * AM_REG_PDM_VCFG_IOCLKEN_EN
+ //! * AM_HAL_PDM_VCFG_RSTB_RESET
+ //! AM_HAL_PDM_VCFG_RSTB_NORMAL
+ //! * AM_HAL_PDM_VCFG_PDMCLK_EN
+ //! AM_HAL_PDM_VCFG_PDMCLK_DIS
+ //! AM_HAL_PDM_VCFG_I2SMODE_xxx
+ //! AM_HAL_PDM_VCFG_BCLKINV_xxx
+ //! AM_HAL_PDM_VCFG_DMICDEL_xxx
+ //! AM_HAL_PDM_VCFG_SELAP_xxx
+ //! AM_HAL_PDM_VCFG_PACK_xxx
+ //! AM_HAL_PDM_VCFG_CHANNEL_xxx
+ //!
+ //! * = These bits are set or cleared by the HAL PDM functions
+ //! am_hal_pdm_enable() or am_hal_pdm_disable().
+ //
+ uint32_t ui32VoiceConfigReg;
+
+ //
+ //! @brief Select the FIFO PCM sample threshold.
+ //!
+ //! The PDM controller will generate a processor interrupt when the number
+ //! of entries in the FIFO goes *above* this number.
+ //
+ uint32_t ui32FIFOThreshold;
+} am_hal_pdm_config_t;
+
+//*****************************************************************************
+//
+// Define function-like macros.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! @brief Read the FIFO depth information as an in-line macro
+//
+//*****************************************************************************
+#define am_hal_pdm_fifo_depth_read() (AM_REG(PDM, FR))
+
+//*****************************************************************************
+//
+//! @brief Read the FIFO READ DATA as an in-line macro
+//
+//*****************************************************************************
+#define am_hal_pdm_fifo_data_read() (AM_REG(PDM, FRD))
+
+//*****************************************************************************
+//
+//! @brief Flush the FIFO as an in-line macro
+//
+//*****************************************************************************
+#define am_hal_pdm_fifo_flush() (AM_REG(PDM, FLUSH) = 0)
+
+//*****************************************************************************
+//
+//! @brief Set the PDM Configuration (PCFG) Register
+//!
+//! This function sets the PDM configuration register
+//
+//*****************************************************************************
+#define am_hal_pdm_pcfg_set(Value) (AM_REG(PDM, PCFG) = Value)
+
+//*****************************************************************************
+//
+//! @brief Get the PCFG register value from PDM module.
+//
+//*****************************************************************************
+#define am_hal_pdm_pcfg_get() (AM_REG(PDM, PCFG))
+
+//*****************************************************************************
+//
+//! @brief Set the Voice Configuration (VCFG) Register
+//
+//*****************************************************************************
+#define am_hal_pdm_vcfg_set(Value) (AM_REG(PDM, VCFG) = Value)
+
+//*****************************************************************************
+//
+//! @brief Get the VCFG register value from PDM module.
+//
+//*****************************************************************************
+#define am_hal_pdm_vcfg_get() (AM_REG(PDM, VCFG))
+
+//*****************************************************************************
+//
+//! @brief Set the FIFO Threshold
+//
+//*****************************************************************************
+#define am_hal_pdm_thresh_set(thresh) (AM_REG(PDM, FTHR) = thresh)
+
+//*****************************************************************************
+//
+//! @brief Get the FIFO Threshold register value from PDM module.
+//
+//*****************************************************************************
+#define am_hal_pdm_thresh_get() (AM_REG(PDM, FTHR))
+
+//*****************************************************************************
+//
+//! @brief Set the left microphone PGA gain.
+//!
+//*****************************************************************************
+#define am_hal_pdm_left_gain_set(gain) (AM_BFW(PDM, PCFG, PGALEFT, gain))
+
+//*****************************************************************************
+//
+//! @brief Set the right microphone PGA gain.
+//
+//*****************************************************************************
+#define am_hal_pdm_right_gain_set(gain) (AM_BFW(PDM, PCFG, PGARIGHT, gain))
+
+//*****************************************************************************
+//
+//! @brief Get the left microphone PGA gain value.
+//
+//*****************************************************************************
+#define am_hal_pdm_left_gain_get() (AM_BFR(PDM, PCFG, PGALEFT))
+
+//*****************************************************************************
+//
+//! @brief Get the right microphone PGA gain value.
+//
+//*****************************************************************************
+#define am_hal_pdm_right_gain_get() (AM_BFR(PDM, PCFG, PGARIGHT))
+
+//*****************************************************************************
+//
+//! @brief Enable the Soft Mute functionality.
+//
+//*****************************************************************************
+#define am_hal_pdm_soft_mute_enable() (AM_BFWe(PDM, PCFG, SOFTMUTE, EN))
+
+//*****************************************************************************
+//
+//! @brief Disable the Soft Mute functionality.
+//
+//*****************************************************************************
+#define am_hal_pdm_soft_mute_disable() (AM_BFWe(PDM, PCFG, SOFTMUTE, DIS))
+
+//*****************************************************************************
+//
+//! @brief Enable selected PDM Interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_pdm.h\n
+//! AM_HAL_PDM_INT_UNDFL\n
+//! AM_HAL_PDM_INT_OVF\n
+//! AM_HAL_PDM_INT_FIFO\n
+//
+//*****************************************************************************
+#define am_hal_pdm_int_enable(intrpt) (AM_REG(PDM, INTEN) |= intrpt)
+
+//*****************************************************************************
+//
+//! @brief Return the enabled PDM Interrupts.
+//!
+//! Use this function to return all enabled PDM interrupts.
+//!
+//! @return all enabled PDM interrupts as a mask.\n
+//! AM_HAL_PDM_INT_UNDFL\n
+//! AM_HAL_PDM_INT_OVF\n
+//! AM_HAL_PDM_INT_FIFO\n
+//
+//*****************************************************************************
+#define am_hal_pdm_int_enable_get() (AM_REG(PDM, INTEN))
+
+//*****************************************************************************
+//
+//! @brief Disable selected PDM Interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_pdm.h\n
+//! AM_HAL_PDM_INT_UNDFL\n
+//! AM_HAL_PDM_INT_OVF\n
+//! AM_HAL_PDM_INT_FIFO\n
+//
+//*****************************************************************************
+#define am_hal_pdm_int_disable(intrpt) (AM_REG(PDM, INTEN) &= ~intrpt)
+
+//*****************************************************************************
+//
+//! @brief Clear selected PDM Interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_pdm.h\n
+//! AM_HAL_PDM_INT_UNDFL\n
+//! AM_HAL_PDM_INT_OVF\n
+//! AM_HAL_PDM_INT_FIFO\n
+//
+//*****************************************************************************
+#define am_hal_pdm_int_clear(intrpt) (AM_REG(PDM, INTCLR) = intrpt)
+
+//*****************************************************************************
+//
+//! @brief Set selected PDM Interrupts.
+//!
+//! Use this function to set the PDM interrupts.
+//!
+//! @param ui32Interrupt - Use the macro bit fields provided in am_hal_pdm.h\n
+//! AM_HAL_PDM_INT_UNDFL\n
+//! AM_HAL_PDM_INT_OVF\n
+//! AM_HAL_PDM_INT_FIFO\n
+//
+//*****************************************************************************
+#define am_hal_pdm_int_set(intrpt) (AM_REG(PDM, INTSET) = intrpt)
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_pdm_config(am_hal_pdm_config_t * cfg);
+extern void am_hal_pdm_enable(void);
+extern void am_hal_pdm_disable(void);
+
+extern uint32_t am_hal_pdm_int_status_get(bool bEnabledOnly);
+
+#endif // AM_HAL_PDM_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_pin.h b/bsp/apollo2/libraries/drivers/hal/am_hal_pin.h
new file mode 100644
index 0000000000..8a1068f882
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_pin.h
@@ -0,0 +1,557 @@
+//*****************************************************************************
+//
+// am_hal_pin.h
+//! @file
+//! @brief Macros for configuring specific pins.
+//!
+//! @addtogroup pin2 PIN definitions for Apollo2.
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#ifndef AM_HAL_PIN_H
+#define AM_HAL_PIN_H
+
+//*****************************************************************************
+//
+// Pin definition helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_PIN_DIR_INPUT (AM_HAL_GPIO_INPEN)
+#define AM_HAL_PIN_DIR_OUTPUT (AM_HAL_GPIO_OUT_PUSHPULL)
+#define AM_HAL_PIN_DIR_OPENDRAIN (AM_HAL_GPIO_OUT_OPENDRAIN | AM_HAL_GPIO_INPEN)
+#define AM_HAL_PIN_DIR_3STATE (AM_HAL_GPIO_OUT_3STATE)
+
+//*****************************************************************************
+//
+// Pin definition helper macros.
+//
+//*****************************************************************************
+#define AM_HAL_PIN_DISABLE (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_INPUT (AM_HAL_GPIO_FUNC(3) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_OUTPUT (AM_HAL_GPIO_FUNC(3) | AM_HAL_PIN_DIR_OUTPUT)
+#define AM_HAL_PIN_OPENDRAIN (AM_HAL_GPIO_FUNC(3) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_3STATE (AM_HAL_GPIO_FUNC(3) | AM_HAL_PIN_DIR_3STATE)
+
+//*****************************************************************************
+//
+// Pin definition macros.
+//
+//*****************************************************************************
+#define AM_HAL_PIN_0_SLSCL (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_0_SLSCK (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_0_CLKOUT (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_0_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_0_MxSCKLB (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_0_M2SCK (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_0_MxSCLLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_0_M2SCL (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_OPENDRAIN)
+
+#define AM_HAL_PIN_1_SLSDA (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_1_SLMISO (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_1_UART0TX (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_1_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_1_MxMISOLB (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_1_M2MISO (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_1_MxSDALB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_1_M2SDA (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_OPENDRAIN)
+
+#define AM_HAL_PIN_2_SLWIR3 (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_3STATE)
+#define AM_HAL_PIN_2_SLMOSI (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_2_UART0RX (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_2_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_2_MxMOSILB (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_2_M2MOSI (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_2_MxWIR3LB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_2_M2WIR3 (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_3STATE)
+
+#define AM_HAL_PIN_3_UART0RTS (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_3_SLnCE (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_3_M1nCE4 (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_3_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_3_MxnCELB (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_3_M2nCE0 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_3_TRIG1 (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_3_I2S_WCLK (AM_HAL_GPIO_FUNC(7))
+#define AM_HAL_PIN_3_PSOURCE (AM_HAL_GPIO_FUNC(3) | AM_HAL_PIN_DIR_OUTPUT | AM_HAL_GPIO_POWER)
+
+#define AM_HAL_PIN_4_UART0CTS (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_4_SLINT (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_4_M0nCE5 (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_4_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_4_SLINTGP (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_4_M2nCE5 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_4_CLKOUT (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_4_32KHZ_XT (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_5_M0SCL (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_5_M0SCK (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_5_UART0RTS (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_5_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_5_M0SCKLB (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_5_EXTHFA (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_5_M0SCLLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_5_M1nCE2 (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_6_M0SDA (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_6_M0MISO (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_6_UART0CTS (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_6_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_6_SLMISOLB (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_6_M1nCE0 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_6_SLSDALB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_6_I2S_DAT (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_7_M0WIR3 (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_3STATE)
+#define AM_HAL_PIN_7_M0MOSI (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_7_CLKOUT (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_7_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_7_TRIG0 (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_7_UART0TX (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_7_SLWIR3LB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_7_M1nCE1 (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_8_M1SCL (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_8_M1SCK (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_8_M0nCE4 (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_8_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_8_M2nCE4 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_8_M1SCKLB (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_8_UART1TX (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_8_M1SCLLB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_9_M1SDA (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_9_M1MISO (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_9_M0nCE5 (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_9_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_9_M4nCE5 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_9_SLMISOLB (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_9_UART1RX (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_9_SLSDALB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_10_M1WIR3 (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_3STATE)
+#define AM_HAL_PIN_10_M1MOSI (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_10_M0nCE6 (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_10_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_10_M2nCE6 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_10_UART1RTS (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_10_M4nCE4 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_10_SLWIR3LB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_11_ADCSE2 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_11_M0nCE0 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_11_CLKOUT (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_11_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_11_M2nCE7 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_11_UART1CTS (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_11_UART0RX (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_11_PDM_DATA (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_11_PSINK (AM_HAL_GPIO_FUNC(3))
+
+#define AM_HAL_PIN_12_ADCD0NSE9 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_12_M1nCE0 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_12_TCTA0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_12_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_12_CLKOUT (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_12_PDM_CLK (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_12_UART0CTS (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_12_UART1TX (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_13_ADCD0PSE8 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_13_M1nCE1 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_13_TCTB0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_13_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_13_M2nCE3 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_13_EXTHFB (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_13_UART0RTS (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_13_UART1RX (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_INPUT)
+
+#define AM_HAL_PIN_14_ADCD1P (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_14_M1nCE2 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_14_UART1TX (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_14_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_14_M2nCE1 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_14_EXTHFS (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_14_SWDCK (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_14_32KHZ_XT (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_15_ADCD1N (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_15_M1nCE3 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_15_UART1RX (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_15_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_15_M2nCE2 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_15_EXTXT (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_15_SWDIO (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_15_SWO (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_16_ADCSE0 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_16_M0nCE4 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_16_TRIG0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_16_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_16_M2nCE3 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_16_CMPIN0 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_16_UART0TX (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_16_UART1RTS (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_17_CMPRF1 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_17_M0nCE1 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_17_TRIG1 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_17_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_17_M4nCE3 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_17_EXTLF (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_17_UART0RX (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_17_UART1CTS (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_INPUT)
+
+#define AM_HAL_PIN_18_CMPIN1 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_18_M0nCE2 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_18_TCTA1 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_18_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_18_M4nCE1 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_18_ANATEST2 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_18_UART1TX (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_18_32KHZ_XT (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_19_CMPRF0 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_19_M0nCE3 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_19_TCTB1 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_19_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_19_TCTA1 (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_19_ANATEST1 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_19_UART1RX (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_19_I2S_BCLK (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_20_SWDCK (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_20_M1nCE5 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_20_TCTA2 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_20_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_20_UART0TX (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_20_UART1TX (AM_HAL_GPIO_FUNC(5))
+
+#define AM_HAL_PIN_21_SWDIO (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_21_M1nCE6 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_21_TCTB2 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_21_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_21_UART0RX (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_21_UART1RX (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+
+#define AM_HAL_PIN_22_UART0TX (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_22_M1nCE7 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_22_TCTA3 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_22_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_22_PDM_CLK (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_22_TCTB1 (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_22_SWO (AM_HAL_GPIO_FUNC(7))
+#define AM_HAL_PIN_22_PSOURCE (AM_HAL_GPIO_FUNC(3) | AM_HAL_PIN_DIR_OUTPUT | AM_HAL_GPIO_POWER)
+
+#define AM_HAL_PIN_23_UART0RX (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_23_M0nCE0 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_23_TCTB3 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_23_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_23_PDM_DATA (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_23_CMPOUT (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_23_TCTB1 (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_24_M2nCE1 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_24_M0nCE1 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_24_CLKOUT (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_24_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_24_M5nCE0 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_24_TCTA1 (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_24_I2S_BCLK (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_24_SWO (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_25_EXTXT (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_25_M0nCE2 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_25_TCTA0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_25_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_25_M2SDA (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_25_M2MISO (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_25_SLMISOLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_25_SLSDALB (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#define AM_HAL_PIN_26_EXTLF (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_26_M0nCE3 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_26_TCTB0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_26_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_26_M2nCE0 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_26_TCTA1 (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_26_M5nCE1 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_26_M3nCE0 (AM_HAL_GPIO_FUNC(7))
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_27_EXTHF (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_27_M1nCE4 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_27_TCTA1 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_27_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_27_M2SCL (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_27_M2SCK (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_27_M2SCKLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_27_M2SCLLB (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#define AM_HAL_PIN_28_I2S_WCLK (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_28_M1nCE5 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_28_TCTB1 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_28_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_28_M2WIR3 (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_3STATE)
+#define AM_HAL_PIN_28_M2MOSI (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_28_M5nCE3 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_28_SLWIR3LB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_29_ADCSE1 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_29_M1nCE6 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_29_TCTA2 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_29_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_29_UART0CTS (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_29_UART1CTS (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_29_M4nCE0 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_29_PDM_DATA (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_INPUT)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_30_M1nCE7 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_30_TCTB2 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_30_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_30_UART0TX (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_30_UART1RTS (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_30_SWO (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_30_I2S_DAT (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_31_ADCSE3 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_31_M0nCE4 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_31_TCTA3 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_31_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_31_UART0RX (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_31_TCTB1 (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_32_ADCSE4 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_32_M0nCE5 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_32_TCTB3 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_32_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_32_TCTB1 (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_33_ADCSE5 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_33_M0nCE6 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_33_32KHZ_XT (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_33_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_33_M3nCE7 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_33_TCTB1 (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_33_SWO (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_34_ADCSE6 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_34_M0nCE7 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_34_M2nCE3 (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_34_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_34_CMPRF2 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_34_M3nCE1 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_34_M4nCE0 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_34_M5nCE2 (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_35_ADCSE7 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_35_M1nCE0 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_35_UART1TX (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_35_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_35_M4nCE6 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_35_TCTA1 (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_35_UART0RTS (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_35_M3nCE2 (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_36_TRIG1 (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_36_M1nCE1 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_36_UART1RX (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_36_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_36_32KHZ_XT (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_36_M2nCE0 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_36_UART0CTS (AM_HAL_GPIO_FUNC(6) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_36_M3nCE3 (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_37_TRIG2 (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_37_M1nCE2 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_37_UART0RTS (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_37_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_37_M3nCE4 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_37_M4nCE1 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_37_PDM_CLK (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_37_TCTA1 (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_INPUT)
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_38_TRIG3 (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_38_M1nCE3 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_38_UART0CTS (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_38_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_38_M3WIR3 (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_3STATE)
+#define AM_HAL_PIN_38_M3MOSI (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_38_M4nCE7 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_38_SLWIR3LB (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#define AM_HAL_PIN_39_UART0TX (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_39_UART1TX (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_39_CLKOUT (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_39_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_39_M4SCL (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_39_M4SCK (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_39_M4SCKLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_39_M4SCLLB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_40_UART0RX (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_40_UART1RX (AM_HAL_GPIO_FUNC(1) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_40_TRIG0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_40_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_40_M4SDA (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_40_M4MISO (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_40_SLMISOLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_40_SLSDALB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_41_M2nCE1 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_41_CLKOUT (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_41_SWO (AM_HAL_GPIO_FUNC(2))
+#define AM_HAL_PIN_41_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_41_M3nCE5 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_41_M5nCE7 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_41_M4nCE2 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_41_UART0RTS (AM_HAL_GPIO_FUNC(7))
+#define AM_HAL_PIN_41_PSOURCE (AM_HAL_GPIO_FUNC(3) | AM_HAL_PIN_DIR_OUTPUT | AM_HAL_GPIO_POWER)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_42_M2nCE2 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_42_M0nCE0 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_42_TCTA0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_42_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_42_M3SCL (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_42_M3SCK (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_42_M3SCKLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_42_M3SCLLB (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_43_M2nCE4 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_43_M0nCE1 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_43_TCTB0 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_43_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_43_M3SDA (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_43_M3MISO (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_43_SLMISOLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_43_SLSDALB (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#define AM_HAL_PIN_44_UART1RTS (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_44_M0nCE2 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_44_TCTA1 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_44_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_44_M4WIR3 (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_3STATE)
+#define AM_HAL_PIN_44_M4MOSI (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_44_M5nCE6 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_44_SLWIR3LB (AM_HAL_GPIO_FUNC(7))
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_45_UART1CTS (AM_HAL_GPIO_FUNC(0) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_45_M0nCE3 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_45_TCTB1 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_45_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_45_M4nCE3 (AM_HAL_GPIO_FUNC(4))
+#define AM_HAL_PIN_45_M3nCE6 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_45_M5nCE5 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_45_TCTA1 (AM_HAL_GPIO_FUNC(7) | AM_HAL_PIN_DIR_INPUT)
+#endif // defined (AM_PACKAGE_BGA)
+
+#if defined (AM_PACKAGE_BGA)
+#define AM_HAL_PIN_46_32KHZ_XT (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_46_M0nCE4 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_46_TCTA2 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_46_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_46_TCTA1 (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_46_M5nCE4 (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_46_M4nCE4 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_46_SWO (AM_HAL_GPIO_FUNC(7))
+#endif // defined (AM_PACKAGE_BGA)
+
+#define AM_HAL_PIN_47_M2nCE5 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_47_M0nCE5 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_47_TCTB2 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_47_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_47_M5WIR3 (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_3STATE)
+#define AM_HAL_PIN_47_M5MOSI (AM_HAL_GPIO_FUNC(5))
+#define AM_HAL_PIN_47_M4nCE5 (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_47_SLWIR3LB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_48_M2nCE6 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_48_M0nCE6 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_48_TCTA3 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_48_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_48_M5SCL (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_48_M5SCK (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_48_M5SCKLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_48_M5SCLLB (AM_HAL_GPIO_FUNC(7))
+
+#define AM_HAL_PIN_49_M2nCE7 (AM_HAL_GPIO_FUNC(0))
+#define AM_HAL_PIN_49_M0nCE7 (AM_HAL_GPIO_FUNC(1))
+#define AM_HAL_PIN_49_TCTB3 (AM_HAL_GPIO_FUNC(2) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_49_GPIO (AM_HAL_GPIO_FUNC(3))
+#define AM_HAL_PIN_49_M5SDA (AM_HAL_GPIO_FUNC(4) | AM_HAL_PIN_DIR_OPENDRAIN)
+#define AM_HAL_PIN_49_M5MISO (AM_HAL_GPIO_FUNC(5) | AM_HAL_PIN_DIR_INPUT)
+#define AM_HAL_PIN_49_SLMISOLB (AM_HAL_GPIO_FUNC(6))
+#define AM_HAL_PIN_49_SLSDALB (AM_HAL_GPIO_FUNC(7))
+
+#endif // AM_HAL_PIN_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.c b/bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.c
new file mode 100644
index 0000000000..cc91eeb159
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.c
@@ -0,0 +1,558 @@
+//*****************************************************************************
+//
+// am_hal_pwrctrl.c
+//! @file
+//!
+//! @brief Functions for enabling and disabling power domains.
+//!
+//! @addtogroup pwrctrl2 Power Control
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// ONE_BIT - true iff value has exactly 1 bit set.
+//
+//*****************************************************************************
+#define ONE_BIT(ui32Value) (ui32Value && !(ui32Value & (ui32Value - 1)))
+
+//*****************************************************************************
+//
+// Determine if this is an Apollo2 revision that requires additional handling
+// of the BUCK to LDO transition when only the ADC is in use and going to
+// deepsleep.
+//
+//*****************************************************************************
+static bool
+isRev_ADC(void)
+{
+ return AM_BFM(MCUCTRL, CHIPREV, REVMAJ) == AM_REG_MCUCTRL_CHIPREV_REVMAJ_B ?
+ true : false;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable power for a peripheral.
+//!
+//! @param ui32Peripheral - The peripheral to enable
+//!
+//! This function directly enables or disables power for the chosen peripheral.
+//!
+//! @note Unpowered peripherals may lose their configuration information. This
+//! function does not save or restore peripheral configuration registers.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_pwrctrl_periph_enable(uint32_t ui32Peripheral)
+{
+
+ am_hal_debug_assert_msg(ONE_BIT(ui32Peripheral),
+ "Cannot enable more than one peripheral at a time.");
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Enable power control for the given device.
+ //
+ AM_REG(PWRCTRL, DEVICEEN) |= ui32Peripheral;
+
+ //
+ // End Critical Section.
+ //
+ AM_CRITICAL_END_ASM
+
+ //
+ // Wait for the power to stablize. Using a simple delay loop is more
+ // power efficient than a polling loop.
+ //
+ am_hal_flash_delay(AM_HAL_PWRCTRL_DEVICEEN_DELAYCYCLES / 3);
+
+ //
+ // Quick check to guarantee we're good (should never be more than 1 read).
+ //
+ POLL_PWRSTATUS(ui32Peripheral);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable power for a peripheral.
+//!
+//! @param ui32Peripheral - The peripheral to disable
+//!
+//! This function directly disables or disables power for the chosen peripheral.
+//!
+//! @note Unpowered peripherals may lose their configuration information. This
+//! function does not save or restore peripheral configuration registers.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_pwrctrl_periph_disable(uint32_t ui32Peripheral)
+{
+
+ am_hal_debug_assert_msg(ONE_BIT(ui32Peripheral),
+ "Cannot enable more than one peripheral at a time.");
+
+ //
+ // Begin critical section.
+ //
+ AM_CRITICAL_BEGIN_ASM
+
+ //
+ // Disable power control for the given device.
+ //
+ AM_REG(PWRCTRL, DEVICEEN) &= ~ui32Peripheral;
+
+ //
+ // End critical section.
+ //
+ AM_CRITICAL_END_ASM
+
+ //
+ // Wait for the power to stablize
+ //
+ am_hal_flash_delay(AM_HAL_PWRCTRL_DEVICEDIS_DELAYCYCLES / 3);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable and disable power for memory devices (SRAM, flash, cache).
+//!
+//! @param ui32MemEn - The memory and amount to be enabled.
+//! Must be one of the following:
+//! AM_HAL_PWRCTRL_MEMEN_CACHE
+//! AM_HAL_PWRCTRL_MEMEN_CACHE_DIS
+//! AM_HAL_PWRCTRL_MEMEN_FLASH512K
+//! AM_HAL_PWRCTRL_MEMEN_FLASH1M
+//! AM_HAL_PWRCTRL_MEMEN_SRAM8K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM16K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM24K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM32K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM64K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM96K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM128K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM160K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM192K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM224K
+//! AM_HAL_PWRCTRL_MEMEN_SRAM256K
+//! AM_HAL_PWRCTRL_MEMEN_ALL (the default, power-up state)
+//!
+//! This function enables/disables power to provide only the given amount of
+//! the type of memory specified.
+//!
+//! Only the type of memory specified is affected. Therefore separate calls
+//! are required to affect power settings for FLASH, SRAM, or CACHE.
+//!
+//! Settings for zero SRAM or FLASH are not provided as device behavior under
+//! either of those conditions is undefined.
+//!
+//! @note Unpowered memory devices may lose their configuration information.
+//! This function does not save or restore peripheral configuration registers.
+//!
+//! @return None.
+//
+//*****************************************************************************
+bool
+am_hal_pwrctrl_memory_enable(uint32_t ui32MemEn)
+{
+ uint32_t ui32MemEnMask, ui32MemDisMask;
+ uint32_t ui32PwrStatEnMask, ui32PwrStatDisMask;
+ int32_t i32TOcnt;
+
+ if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_FLASH512K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_FLASH0_EN;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_FLASH1_EN;
+ ui32PwrStatEnMask = AM_REG_PWRCTRL_PWRONSTATUS_PD_FLAM0_M;
+ ui32PwrStatDisMask = AM_REG_PWRCTRL_PWRONSTATUS_PD_FLAM1_M;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_FLASH1M )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_FLASH0_EN |
+ AM_REG_PWRCTRL_MEMEN_FLASH1_EN;
+ ui32MemDisMask = 0;
+ ui32PwrStatEnMask = AM_REG_PWRCTRL_PWRONSTATUS_PD_FLAM0_M |
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_FLAM1_M;
+ ui32PwrStatDisMask = 0;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM8K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM8K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM8K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_8K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_8K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM16K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM16K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM16K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_16K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_16K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM24K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP0_SRAM0 |
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP0_SRAM1 |
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP0_SRAM2;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~(AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP0_SRAM0 |
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP0_SRAM1 |
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP0_SRAM2);
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_24K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_24K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM32K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM32K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM32K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_32K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_32K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM64K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM64K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM64K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_64K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_64K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM96K )
+ {
+ ui32MemEnMask = AM_HAL_PWRCTRL_MEMEN_SRAM96K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_HAL_PWRCTRL_MEMEN_SRAM96K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_96K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_96K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM128K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM128K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM128K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_128K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_128K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM160K )
+ {
+ ui32MemEnMask = AM_HAL_PWRCTRL_MEMEN_SRAM160K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_HAL_PWRCTRL_MEMEN_SRAM160K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_160K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_160K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM192K )
+ {
+ ui32MemEnMask = AM_HAL_PWRCTRL_MEMEN_SRAM192K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_HAL_PWRCTRL_MEMEN_SRAM192K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_192K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_192K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM224K )
+ {
+ ui32MemEnMask = AM_HAL_PWRCTRL_MEMEN_SRAM224K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_HAL_PWRCTRL_MEMEN_SRAM224K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_224K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_224K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_SRAM256K )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM256K;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL &
+ ~AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM256K;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_256K;
+ ui32PwrStatDisMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL &
+ ~AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_256K;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_CACHE )
+ {
+ ui32MemEnMask = AM_REG_PWRCTRL_MEMEN_CACHEB0_EN |
+ AM_REG_PWRCTRL_MEMEN_CACHEB2_EN;
+ ui32MemDisMask = 0;
+ ui32PwrStatEnMask = AM_REG_PWRCTRL_PWRONSTATUS_PD_CACHEB2_M |
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_CACHEB0_M;
+ ui32PwrStatDisMask = 0;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_CACHE_DIS )
+ {
+ ui32MemEnMask = 0;
+ ui32MemDisMask = AM_REG_PWRCTRL_MEMEN_CACHEB0_EN |
+ AM_REG_PWRCTRL_MEMEN_CACHEB2_EN;
+ ui32PwrStatEnMask = 0;
+ ui32PwrStatDisMask = AM_REG_PWRCTRL_PWRONSTATUS_PD_CACHEB2_M |
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_CACHEB0_M;
+ }
+ else if ( ui32MemEn == AM_HAL_PWRCTRL_MEMEN_ALL )
+ {
+ ui32MemEnMask = AM_HAL_PWRCTRL_MEMEN_ALL;
+ ui32MemDisMask = 0;
+ ui32PwrStatEnMask = AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL;
+ ui32PwrStatDisMask = 0;
+ }
+ else
+ {
+ return false;
+ }
+
+ //
+ // Disable unneeded memory. If nothing to be disabled, skip to save time.
+ //
+ // Note that a deliberate disable step using a disable mask is taken here
+ // for 2 reasons: 1) To only affect the specified type of memory, and 2)
+ // To avoid inadvertently disabling any memory currently being depended on.
+ //
+ if ( ui32MemDisMask != 0 )
+ {
+ AM_REG(PWRCTRL, MEMEN) &= ~ui32MemDisMask;
+ }
+
+ //
+ // Enable the required memory.
+ //
+ if ( ui32MemEnMask != 0 )
+ {
+ AM_REG(PWRCTRL, MEMEN) |= ui32MemEnMask;
+ }
+
+ //
+ // Wait for the power to be turned on.
+ // Apollo2 note - these loops typically end up taking 1 iteration.
+ //
+ i32TOcnt = 200;
+ if ( ui32PwrStatDisMask )
+ {
+ while ( --i32TOcnt &&
+ ( AM_REG(PWRCTRL, PWRONSTATUS) & ui32PwrStatDisMask ) );
+ }
+
+ if ( i32TOcnt <= 0 )
+ {
+ return false;
+ }
+
+ i32TOcnt = 200;
+ if ( ui32PwrStatEnMask )
+ {
+ while ( --i32TOcnt &&
+ (( AM_REG(PWRCTRL, PWRONSTATUS) & ui32PwrStatEnMask )
+ != ui32PwrStatEnMask) );
+ }
+ if ( i32TOcnt <= 0 )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//*****************************************************************************
+//
+//! @brief Initialize the core and memory buck converters.
+//!
+//! This function is intended to be used for first time core and memory buck
+//! converters initialization.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_pwrctrl_bucks_init(void)
+{
+ am_hal_pwrctrl_bucks_enable();
+
+ while ( ( AM_REG(PWRCTRL, POWERSTATUS) &
+ ( AM_REG_PWRCTRL_POWERSTATUS_COREBUCKON_M |
+ AM_REG_PWRCTRL_POWERSTATUS_MEMBUCKON_M ) ) !=
+ ( AM_REG_PWRCTRL_POWERSTATUS_COREBUCKON_M |
+ AM_REG_PWRCTRL_POWERSTATUS_MEMBUCKON_M ) );
+
+ //
+ // Additional delay to make sure BUCKs are initialized.
+ //
+ am_hal_flash_delay(200 / 3);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the core and memory buck converters.
+//!
+//! This function enables the core and memory buck converters.
+//!
+//! @return None
+//
+//*****************************************************************************
+#define LDO_TRIM_REG_ADDR (0x50023004)
+#define BUCK_TRIM_REG_ADDR (0x50023000)
+
+void
+am_hal_pwrctrl_bucks_enable(void)
+{
+ //
+ // Check to see if the bucks are already on. If so, we can just return.
+ //
+ if ( AM_BFR(PWRCTRL, POWERSTATUS, COREBUCKON) &&
+ AM_BFR(PWRCTRL, POWERSTATUS, MEMBUCKON) )
+ {
+ return;
+ }
+
+ //
+ // Enable BUCK power up
+ //
+ AM_BFW(PWRCTRL, SUPPLYSRC, COREBUCKEN, 1);
+ AM_BFW(PWRCTRL, SUPPLYSRC, MEMBUCKEN, 1);
+
+ //
+ // Make sure bucks are ready.
+ //
+ while ( ( AM_REG(PWRCTRL, POWERSTATUS) &
+ ( AM_REG_PWRCTRL_POWERSTATUS_COREBUCKON_M |
+ AM_REG_PWRCTRL_POWERSTATUS_MEMBUCKON_M ) ) !=
+ ( AM_REG_PWRCTRL_POWERSTATUS_COREBUCKON_M |
+ AM_REG_PWRCTRL_POWERSTATUS_MEMBUCKON_M ) );
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the core and memory buck converters.
+//!
+//! This function disables the core and memory buck converters.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_pwrctrl_bucks_disable(void)
+{
+ //
+ // Check to see if the bucks are already off. If so, we can just return.
+ //
+ if ( AM_BFR(PWRCTRL, POWERSTATUS, COREBUCKON) == 0 &&
+ AM_BFR(PWRCTRL, POWERSTATUS, MEMBUCKON) == 0)
+ {
+ return;
+ }
+
+ //
+ // Handle the special case if only the ADC is powered.
+ //
+ if ( isRev_ADC() &&
+ (AM_REG(PWRCTRL, DEVICEEN) == AM_REG_PWRCTRL_DEVICEEN_ADC_EN) )
+ {
+ //
+ // Set SUPPLYSRC to handle this case
+ //
+ AM_REG(PWRCTRL, SUPPLYSRC) &=
+ (AM_REG_PWRCTRL_SUPPLYSRC_SWITCH_LDO_IN_SLEEP_EN |
+ AM_REG_PWRCTRL_SUPPLYSRC_MEMBUCKEN_EN);
+ }
+ else
+ {
+ //
+ // Power them down
+ //
+ AM_BFW(PWRCTRL, SUPPLYSRC, COREBUCKEN, 0);
+ AM_BFW(PWRCTRL, SUPPLYSRC, MEMBUCKEN, 0);
+ }
+
+ //
+ // Wait until BUCKs are disabled.
+ //
+ am_hal_flash_delay(AM_HAL_PWRCTRL_BUCKDIS_DELAYCYCLES / 3);
+}
+
+//*****************************************************************************
+//
+//! @brief Misc low power initializations.
+//!
+//! This function performs low power initializations that aren't specifically
+//! handled elsewhere.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_pwrctrl_low_power_init(void)
+{
+ //
+ // For lowest power, we enable clock gating for all SRAM configuration.
+ //
+ AM_REG(PWRCTRL, SRAMCTRL) |=
+ AM_REG_PWRCTRL_SRAMCTRL_SRAM_MASTER_CLKGATE_EN |
+ AM_REG_PWRCTRL_SRAMCTRL_SRAM_CLKGATE_EN |
+ AM_REG_PWRCTRL_SRAMCTRL_SRAM_LIGHT_SLEEP_DIS;
+
+ //
+ // For lowest deep sleep power, make sure we stay in BUCK mode.
+ //
+ AM_REG(PWRCTRL, SUPPLYSRC) &=
+ ~AM_REG_PWRCTRL_SUPPLYSRC_SWITCH_LDO_IN_SLEEP_M;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.h b/bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.h
new file mode 100644
index 0000000000..bc9adabf84
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_pwrctrl.h
@@ -0,0 +1,342 @@
+//*****************************************************************************
+//
+// am_hal_pwrctrl.h
+//! @file
+//!
+//! @brief Functions for enabling and disabling power domains.
+//!
+//! @addtogroup pwrctrl2 Power Control
+//! @ingroup apollo2hal
+//! @{
+
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#ifndef AM_HAL_PWRCTRL_H
+#define AM_HAL_PWRCTRL_H
+
+//*****************************************************************************
+//
+// Peripheral enable bits for am_hal_pwrctrl_periph_enable/disable()
+//
+//*****************************************************************************
+#define AM_HAL_PWRCTRL_ADC AM_REG_PWRCTRL_DEVICEEN_ADC_EN
+#define AM_HAL_PWRCTRL_IOM0 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER0_EN
+#define AM_HAL_PWRCTRL_IOM1 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER1_EN
+#define AM_HAL_PWRCTRL_IOM2 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER2_EN
+#define AM_HAL_PWRCTRL_IOM3 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER3_EN
+#define AM_HAL_PWRCTRL_IOM4 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER4_EN
+#define AM_HAL_PWRCTRL_IOM5 AM_REG_PWRCTRL_DEVICEEN_IO_MASTER5_EN
+#define AM_HAL_PWRCTRL_IOS AM_REG_PWRCTRL_DEVICEEN_IO_SLAVE_EN
+#define AM_HAL_PWRCTRL_PDM AM_REG_PWRCTRL_DEVICEEN_PDM_EN
+#define AM_HAL_PWRCTRL_UART0 AM_REG_PWRCTRL_DEVICEEN_UART0_EN
+#define AM_HAL_PWRCTRL_UART1 AM_REG_PWRCTRL_DEVICEEN_UART1_EN
+
+//*****************************************************************************
+//
+// Macro to set the appropriate IOM peripheral when using
+// am_hal_pwrctrl_periph_enable()/disable().
+// For Apollo2, the module argument must resolve to be a value from 0-5.
+//
+//*****************************************************************************
+#define AM_HAL_PWRCTRL_IOM(module) \
+ (AM_REG_PWRCTRL_DEVICEEN_IO_MASTER0_EN << module)
+
+//*****************************************************************************
+//
+// Macro to set the appropriate UART peripheral when using
+// am_hal_pwrctrl_periph_enable()/disable().
+// For Apollo2, the module argument must resolve to be a value from 0-1.
+//
+//*****************************************************************************
+#define AM_HAL_PWRCTRL_UART(module) \
+ (AM_REG_PWRCTRL_DEVICEEN_UART0_EN << module)
+
+
+//*****************************************************************************
+//
+// Memory enable values for am_hal_pwrctrl_memory_enable()
+//
+//*****************************************************************************
+#define AM_HAL_PWRCTRL_MEMEN_SRAM8K AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM8K
+#define AM_HAL_PWRCTRL_MEMEN_SRAM16K AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM16K
+#define AM_HAL_PWRCTRL_MEMEN_SRAM24K (AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM16K | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP0_SRAM2)
+#define AM_HAL_PWRCTRL_MEMEN_SRAM32K AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM32K
+#define AM_HAL_PWRCTRL_MEMEN_SRAM64K AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM64K
+#define AM_HAL_PWRCTRL_MEMEN_SRAM96K \
+ (AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM64K | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP2)
+#define AM_HAL_PWRCTRL_MEMEN_SRAM128K AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM128K
+#define AM_HAL_PWRCTRL_MEMEN_SRAM160K \
+ (AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM128K | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP4)
+#define AM_HAL_PWRCTRL_MEMEN_SRAM192K \
+ (AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM128K | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP4 | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP5)
+#define AM_HAL_PWRCTRL_MEMEN_SRAM224K \
+ (AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM128K | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP4 | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP5 | \
+ AM_REG_PWRCTRL_MEMEN_SRAMEN_GROUP6)
+#define AM_HAL_PWRCTRL_MEMEN_SRAM256K AM_REG_PWRCTRL_MEMEN_SRAMEN_SRAM256K
+
+#define AM_HAL_PWRCTRL_MEMEN_FLASH512K AM_REG_PWRCTRL_MEMEN_FLASH0_EN
+#define AM_HAL_PWRCTRL_MEMEN_FLASH1M \
+ (AM_REG_PWRCTRL_MEMEN_FLASH0_EN | \
+ AM_REG_PWRCTRL_MEMEN_FLASH1_EN)
+#define AM_HAL_PWRCTRL_MEMEN_CACHE \
+ (AM_REG_PWRCTRL_MEMEN_CACHEB0_EN | \
+ AM_REG_PWRCTRL_MEMEN_CACHEB2_EN)
+#define AM_HAL_PWRCTRL_MEMEN_CACHE_DIS \
+ ~(AM_REG_PWRCTRL_MEMEN_CACHEB0_EN | \
+ AM_REG_PWRCTRL_MEMEN_CACHEB2_EN)
+
+//
+// Power up all available memory devices (this is the default power up state)
+//
+#define AM_HAL_PWRCTRL_MEMEN_ALL \
+ (AM_REG_PWRCTRL_MEMEN_SRAMEN_ALL | \
+ AM_REG_PWRCTRL_MEMEN_FLASH0_EN | \
+ AM_REG_PWRCTRL_MEMEN_FLASH1_EN | \
+ AM_REG_PWRCTRL_MEMEN_CACHEB0_EN | \
+ AM_REG_PWRCTRL_MEMEN_CACHEB2_EN)
+
+//*****************************************************************************
+//
+// Peripheral power enable and disable delays
+// The delay counts are based on an internal clock that runs at half of
+// HFRC. Therefore, we need to double the delay cycles.
+//
+//*****************************************************************************
+#define AM_HAL_PWRCTRL_DEVICEEN_DELAYCYCLES (22 * 2)
+#define AM_HAL_PWRCTRL_DEVICEDIS_DELAYCYCLES (22 * 2)
+
+//
+// Use the following only when enabling after sleep (not during initialization).
+//
+#define AM_HAL_PWRCTRL_BUCKEN_DELAYCYCLES (0 * 2)
+#define AM_HAL_PWRCTRL_BUCKDIS_DELAYCYCLES (15 * 2)
+
+//*****************************************************************************
+//
+// Peripheral PWRONSTATUS groupings.
+//
+//*****************************************************************************
+//
+// Group DEVICEEN bits (per PWRONSTATUS groupings).
+//
+#define AM_HAL_PWRCTRL_DEVICEEN_IOM_0_2 \
+ (AM_REG_PWRCTRL_DEVICEEN_IO_MASTER0_EN | \
+ AM_REG_PWRCTRL_DEVICEEN_IO_MASTER1_EN | \
+ AM_REG_PWRCTRL_DEVICEEN_IO_MASTER2_EN )
+
+#define AM_HAL_PWRCTRL_DEVICEEN_IOM_3_5 \
+ (AM_REG_PWRCTRL_DEVICEEN_IO_MASTER3_EN | \
+ AM_REG_PWRCTRL_DEVICEEN_IO_MASTER4_EN | \
+ AM_REG_PWRCTRL_DEVICEEN_IO_MASTER5_EN )
+
+#define AM_HAL_PWRCTRL_DEVICEEN_IOS_UARTS \
+ (AM_REG_PWRCTRL_DEVICEEN_UART0_EN | \
+ AM_REG_PWRCTRL_DEVICEEN_UART1_EN | \
+ AM_REG_PWRCTRL_DEVICEEN_IO_SLAVE_EN )
+
+#define AM_HAL_PWRCTRL_DEVICEEN_ADC AM_REG_PWRCTRL_DEVICEEN_ADC_EN
+#define AM_HAL_PWRCTRL_DEVICEEN_PDM AM_REG_PWRCTRL_DEVICEEN_PDM_EN
+
+//
+// Map PWRONSTATUS bits to peripheral groupings.
+//
+#define AM_HAL_PWRCTRL_PWRONSTATUS_IOS_UARTS AM_REG_PWRCTRL_PWRONSTATUS_PDA_M
+#define AM_HAL_PWRCTRL_PWRONSTATUS_IOM_3_5 AM_REG_PWRCTRL_PWRONSTATUS_PDC_M
+#define AM_HAL_PWRCTRL_PWRONSTATUS_IOM_0_2 AM_REG_PWRCTRL_PWRONSTATUS_PDB_M
+#define AM_HAL_PWRCTRL_PWRONSTATUS_ADC AM_REG_PWRCTRL_PWRONSTATUS_PDADC_M
+#define AM_HAL_PWRCTRL_PWRONSTATUS_PDM AM_REG_PWRCTRL_PWRONSTATUS_PD_PDM_M
+
+#define POLL_PWRSTATUS(ui32Peripheral) \
+ if ( 1 ) \
+ { \
+ uint32_t ui32PwrOnStat; \
+ if ( ui32Peripheral & AM_HAL_PWRCTRL_DEVICEEN_IOM_0_2 ) \
+ { \
+ ui32PwrOnStat = AM_HAL_PWRCTRL_PWRONSTATUS_IOM_0_2; \
+ } \
+ else if ( ui32Peripheral & AM_HAL_PWRCTRL_DEVICEEN_IOM_3_5 ) \
+ { \
+ ui32PwrOnStat = AM_HAL_PWRCTRL_PWRONSTATUS_IOM_3_5; \
+ } \
+ else if ( ui32Peripheral & AM_HAL_PWRCTRL_DEVICEEN_IOS_UARTS ) \
+ { \
+ ui32PwrOnStat = AM_HAL_PWRCTRL_PWRONSTATUS_IOS_UARTS; \
+ } \
+ else if ( ui32Peripheral & AM_HAL_PWRCTRL_DEVICEEN_ADC ) \
+ { \
+ ui32PwrOnStat = AM_HAL_PWRCTRL_PWRONSTATUS_ADC; \
+ } \
+ else if ( ui32Peripheral & AM_HAL_PWRCTRL_DEVICEEN_PDM ) \
+ { \
+ ui32PwrOnStat = AM_HAL_PWRCTRL_PWRONSTATUS_PDM; \
+ } \
+ else \
+ { \
+ ui32PwrOnStat = 0xFFFFFFFF; \
+ } \
+ \
+ /* */ \
+ /* Wait for the power control setting to take effect. */ \
+ /* */ \
+ while ( !(AM_REG(PWRCTRL, PWRONSTATUS) & ui32PwrOnStat) ); \
+ }
+
+//*****************************************************************************
+//
+// Memory PWRONSTATUS enable values for am_hal_pwrctrl_memory_enable()
+//
+//*****************************************************************************
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_8K \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_16K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_24K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_32K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_64K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP1_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_96K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP2_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP1_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_128K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP3_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP2_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP1_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_160K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP4_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP3_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP2_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP1_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_192K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP5_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP4_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP3_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP2_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP1_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_224K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP6_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP5_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP4_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP3_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP2_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP1_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_256K \
+ (AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP7_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP6_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP5_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP4_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP3_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP2_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP1_SRAM_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM3_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM2_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM1_M | \
+ AM_REG_PWRCTRL_PWRONSTATUS_PD_GRP0_SRAM0_M)
+
+#define AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_ALL \
+ AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_256K
+
+//*****************************************************************************
+//
+// Function prototypes
+//
+//*****************************************************************************
+extern void am_hal_pwrctrl_periph_enable(uint32_t ui32Peripheral);
+extern void am_hal_pwrctrl_periph_disable(uint32_t ui32Peripheral);
+extern bool am_hal_pwrctrl_memory_enable(uint32_t ui32MemEn);
+extern void am_hal_pwrctrl_bucks_init(void);
+extern void am_hal_pwrctrl_bucks_enable(void);
+extern void am_hal_pwrctrl_bucks_disable(void);
+extern void am_hal_pwrctrl_low_power_init(void);
+
+#endif // AM_HAL_PWRCTRL_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_queue.c b/bsp/apollo2/libraries/drivers/hal/am_hal_queue.c
new file mode 100644
index 0000000000..66a9846c29
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_queue.c
@@ -0,0 +1,286 @@
+//*****************************************************************************
+//
+// am_hal_queue.c
+//! @file
+//!
+//! @brief Functions for implementing a queue system.
+//!
+//! @addtogroup Miscellaneous2 Software Features (MISC)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Initializes a queue.
+//!
+//! @param psQueue - Pointer to a queue structure.
+//! @param pvData - Pointer to a memory location to be used for data storage.
+//! @param ui32ItemSize - Number of bytes per item in the queue.
+//! @param ui32ArraySize - Number of bytes in the data array.
+//!
+//! This function initializes the members of a queue structure and attaches it
+//! to an array of memory that it can use for storage. This function should be
+//! called before the queue is used.
+//!
+//! In this example, we are creating a queue that can hold 1024 32-bit
+//! integers. The integers themselves will be stored in the array named
+//! pui32WorkingSpace, while information about the queue itself will be stored
+//! in sDataQueue.
+//!
+//! @note The caller should not modify any of the members of am_hal_queue_t
+//! structures. The queue API will handle these members in a thread-safe way.
+//!
+//! @note The queue will remember what size data is in it. Other queue API
+//! functions will perform transfers in units of "items" where one "item" is
+//! the number of bytes you specify in the \e ui32ItemSize argument upon
+//! initialization.
+//!
+//! Example usage:
+//!
+//! @code
+//!
+//! //
+//! // Declare a queue structure and an array of bytes we can use to store
+//! // data.
+//! //
+//! am_hal_queue_t sDataQueue;
+//! uint32_t pui32WorkingSpace[1024];
+//!
+//! //
+//! // Attach the queue structure to the working memory.
+//! //
+//! am_hal_queue_init(&sDataQueue, pui8WorkingSpace, sizeof(uint32_t)
+//! sizeof(pui32WorkingSpace));
+//!
+//! @endcode
+//!
+//! The am_hal_queue_from_array macro is a convenient shorthand for this
+//! operation. The code below does the same thing as the code above.
+//!
+//! @code
+//!
+//! //
+//! // Declare a queue structure and an array of bytes we can use to store
+//! // data.
+//! //
+//! am_hal_queue_t sDataQueue;
+//! uint32_t pui32WorkingSpace[1024];
+//!
+//! //
+//! // Attach the queue structure to the working memory.
+//! //
+//! am_hal_queue_from_array(&sDataQueue, pui8WorkingSpace);
+//!
+//! @endcode
+//
+//*****************************************************************************
+void
+am_hal_queue_init(am_hal_queue_t *psQueue, void *pvData, uint32_t ui32ItemSize,
+ uint32_t ui32ArraySize)
+{
+ psQueue->ui32WriteIndex = 0;
+ psQueue->ui32ReadIndex = 0;
+ psQueue->ui32Length = 0;
+ psQueue->ui32Capacity = ui32ArraySize;
+ psQueue->ui32ItemSize = ui32ItemSize;
+ psQueue->pui8Data = (uint8_t *) pvData;
+}
+
+//*****************************************************************************
+//
+//! @brief Adds an item to the Queue
+//!
+//! @param psQueue - Pointer to a queue structure.
+//! @param pvSource - Pointer to the data to be added.
+//! @param ui32NumItems - Number of items to be added.
+//!
+//! This function will copy the data pointed to by pvSource into the queue. The
+//! \e ui32NumItems term specifies the number of items to be copied from \e
+//! pvSource. The size of an "item" depends on how the queue was initialized.
+//! Please see am_hal_queue_init() for more information on this.
+//!
+//! @return true if the add operation was successful, or false if the queue
+//! didn't have enough space.
+//
+//*****************************************************************************
+bool
+am_hal_queue_item_add(am_hal_queue_t *psQueue, const void *pvSource, uint32_t ui32NumItems)
+{
+ uint32_t i;
+ uint8_t *pui8Source;
+ uint32_t ui32Bytes = ui32NumItems * psQueue->ui32ItemSize;
+ bool bSuccess = false;
+ uint32_t ui32Primask;
+
+ pui8Source = (uint8_t *) pvSource;
+
+ ui32Primask = am_hal_interrupt_master_disable();
+
+ //
+ // Check to make sure that the buffer isn't already full
+ //
+ if ( am_hal_queue_space_left(psQueue) >= ui32Bytes )
+ {
+ //
+ // Loop over the bytes in the source array.
+ //
+ for ( i = 0; i < ui32Bytes; i++ )
+ {
+ //
+ // Write the value to the buffer.
+ //
+ psQueue->pui8Data[psQueue->ui32WriteIndex] = pui8Source[i];
+
+ //
+ // Advance the write index, making sure to wrap if necessary.
+ //
+ psQueue->ui32WriteIndex = ((psQueue->ui32WriteIndex + 1) %
+ psQueue->ui32Capacity);
+ }
+
+ //
+ // Update the length value appropriately.
+ //
+ psQueue->ui32Length += ui32Bytes;
+
+ //
+ // Report a success.
+ //
+ bSuccess = true;
+ }
+ else
+ {
+ //
+ // The buffer can't fit the amount of data requested. Return a
+ // failure.
+ //
+ bSuccess = false;
+ }
+
+ am_hal_interrupt_master_set(ui32Primask);
+
+ return bSuccess;
+}
+
+//*****************************************************************************
+//
+//! @brief Removes an item from the Queue
+//!
+//! @param psQueue - Pointer to a queue structure.
+//! @param pvDest - Pointer to the data to be added.
+//! @param ui32NumItems - Number of items to be added.
+//!
+//! This function will copy the data from the queue into the memory pointed to
+//! by pvDest. The \e ui32NumItems term specifies the number of items to be
+//! copied from the queue. The size of an "item" depends on how the queue was
+//! initialized. Please see am_hal_queue_init() for more information on this.
+//!
+//! @return true if we were able to pull the requested number of items from the
+//! queue, or false if the queue didn't have that many items to pull.
+//
+//*****************************************************************************
+bool
+am_hal_queue_item_get(am_hal_queue_t *psQueue, void *pvDest, uint32_t ui32NumItems)
+{
+ uint32_t i;
+ uint8_t *pui8Dest;
+ uint32_t ui32Bytes = ui32NumItems * psQueue->ui32ItemSize;
+ bool bSuccess = false;
+ uint32_t ui32Primask;
+
+ pui8Dest = (uint8_t *) pvDest;
+
+ ui32Primask = am_hal_interrupt_master_disable();
+
+ //
+ // Check to make sure that the buffer isn't empty
+ //
+ if ( am_hal_queue_data_left(psQueue) >= ui32Bytes )
+ {
+ //
+ // Loop over the bytes in the destination array.
+ //
+ for ( i = 0; i < ui32Bytes; i++ )
+ {
+ //
+ // Grab the next value from the buffer.
+ //
+ pui8Dest[i] = psQueue->pui8Data[psQueue->ui32ReadIndex];
+
+ //
+ // Advance the read index, wrapping if needed.
+ //
+ psQueue->ui32ReadIndex = ((psQueue->ui32ReadIndex + 1) %
+ psQueue->ui32Capacity);
+ }
+
+ //
+ // Adjust the length value to reflect the change.
+ //
+ psQueue->ui32Length -= ui32Bytes;
+
+ //
+ // Report a success.
+ //
+ bSuccess = true;
+ }
+ else
+ {
+ //
+ // If the buffer didn't have enough data, just return false.
+ //
+ bSuccess = false;
+ }
+
+ am_hal_interrupt_master_set(ui32Primask);
+
+ return bSuccess;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_queue.h b/bsp/apollo2/libraries/drivers/hal/am_hal_queue.h
new file mode 100644
index 0000000000..11e8ace90a
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_queue.h
@@ -0,0 +1,123 @@
+//*****************************************************************************
+//
+// am_hal_queue.h
+//! @file
+//!
+//! @brief Functions for implementing a queue system.
+//!
+//! @addtogroup Miscellaneous2 Software Features (MISC)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_QUEUE_H
+#define AM_HAL_QUEUE_H
+
+//*****************************************************************************
+//
+//! @brief A data structure that will operate as a queue.
+//!
+//! This data structure holds information necessary for operating a thread-safe
+//! queue. When declaring a structure of type am_hal_queue_t, you will also need
+//! to provide some working memory for the queue to use. For more information on
+//! setting up and using the am_hal_queue_t structure, please see the
+//! documentation for am_hal_queue_init().
+//
+//*****************************************************************************
+typedef struct
+{
+ uint32_t ui32WriteIndex;
+ uint32_t ui32ReadIndex;
+ uint32_t ui32Length;
+ uint32_t ui32Capacity;
+ uint32_t ui32ItemSize;
+ uint8_t *pui8Data;
+}
+am_hal_queue_t;
+
+//*****************************************************************************
+//
+// Function-like macros.
+//
+//*****************************************************************************
+#define am_hal_queue_empty(psQueue) \
+ ((psQueue)->ui32Length == 0)
+
+#define am_hal_queue_full(psQueue) \
+ ((psQueue)->ui32Length == (psQueue)->ui32Capacity)
+
+#define am_hal_queue_space_left(psQueue) \
+ ((psQueue)->ui32Capacity - (psQueue)->ui32Length)
+
+#define am_hal_queue_data_left(psQueue) \
+ ((psQueue)->ui32Length)
+
+//*****************************************************************************
+//
+// Use this to make sure you get the size parameters right.
+//
+//*****************************************************************************
+#define am_hal_queue_from_array(queue, array) \
+ am_hal_queue_init((queue), (array), sizeof((array)[0]), sizeof(array))
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// External function definitions.
+//
+//*****************************************************************************
+extern void am_hal_queue_init(am_hal_queue_t *psQueue, void *pvData, uint32_t ui32ItemSize, uint32_t ui32ArraySize);
+extern bool am_hal_queue_item_add(am_hal_queue_t *psQueue, const void *pvSource, uint32_t ui32NumItems);
+extern bool am_hal_queue_item_get(am_hal_queue_t *psQueue, void *pvDest, uint32_t ui32NumItems);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_QUEUE_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_reset.c b/bsp/apollo2/libraries/drivers/hal/am_hal_reset.c
new file mode 100644
index 0000000000..86d5cf10b7
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_reset.c
@@ -0,0 +1,160 @@
+//*****************************************************************************
+//
+// am_hal_reset.c
+//! @file
+//!
+//! @brief Hardware abstraction layer for the Reset Generator module.
+//!
+//! @addtogroup rstgen2 Reset Generator (RSTGEN)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Configure the Reset Generator.
+//!
+//! @param ui32Config - Or together the supplied macros to enable
+//! configurations to obtain the desired reset generator settings.
+//!
+//! This function will set the reset generator's configuration register based on
+//! the user's desired settings listed in the supplied arugment.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_reset_init(uint32_t ui32Config)
+{
+ //
+ // Write the configuration to the reset generator
+ //
+ AM_REG(RSTGEN, CFG) = ui32Config;
+}
+
+//*****************************************************************************
+//
+//! @brief Issue a POR (Apollo's last stage interrupt).
+//!
+//! This function will issue a POR reset.
+//! The Apollo chip has numerous stages of reset. POR is the last and is also
+//! the reset invoked by the chip's reset pin, the watchdog timer, the AIRCR
+//! reset, and the SWD debugger requested interrupt.
+//!
+//! The Debug Access Port in the M4 is not cleared by this reset.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void am_hal_reset_por(void)
+{
+ //
+ // Write the POR key to the software POR register.
+ //
+ AM_REG(RSTGEN, SWPOR) =
+ AM_REG_RSTGEN_SWPOR_SWPORKEY(AM_REG_RSTGEN_SWPOR_SWPORKEY_KEYVALUE);
+}
+
+//*****************************************************************************
+//
+//! @brief Issue a POI (Apollo's second stage interrupt).
+//!
+//! This function will issue a POI reset.
+//! The Apollo chip has numerous stages of reset. POI is the second stage.
+//! A few modules are reset by POI that are not reset by POR, notably POI
+//! causes the shadow registers to be reloaded from the OTP. A full power
+//! cycle or POI should be used after writing new flash, debug or SRAM
+//! protection bits into the OTP for these protections to take effect.
+//!
+//! The Debug Access Port in the M4 is not cleared by this reset.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void am_hal_reset_poi(void)
+{
+ //
+ // Write the POI key to the software POI register.
+ //
+ AM_REG(RSTGEN, SWPOI) =
+ AM_REG_RSTGEN_SWPOI_SWPOIKEY(AM_REG_RSTGEN_SWPOI_SWPOIKEY_KEYVALUE);
+}
+
+//*****************************************************************************
+//
+//! @brief Retrieve the status bits from the reset generator.
+//!
+//! This function will get the status bits from the reset generator.
+//! These bits are sticky and show the accumulation of reset types that the
+//! Apollo chip has experienced since power on. One should clear these out
+//! after reading them.
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t am_hal_reset_status_get(void)
+{
+ //
+ // Retrieve the reset generator status bits
+ //
+ return AM_REG(RSTGEN, STAT);
+}
+
+//*****************************************************************************
+//
+//! @brief Clear ALL of the status bits in the reset generator.
+//!
+//! This function will clear all status bits in the reset generator status.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void am_hal_reset_status_clear(void)
+{
+ AM_REG(RSTGEN, CLRSTAT) = AM_REG_RSTGEN_CLRSTAT_CLRSTAT(1);
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_reset.h b/bsp/apollo2/libraries/drivers/hal/am_hal_reset.h
new file mode 100644
index 0000000000..a3273dad10
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_reset.h
@@ -0,0 +1,119 @@
+//*****************************************************************************
+//
+// am_hal_reset.h
+//! @file
+//!
+//! @brief Hardware abstraction layer for the Reset Generator module.
+//!
+//! @addtogroup wdt2 Watchdog Timer (RSTGEN)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_RSTGEN_H
+#define AM_HAL_RSTGEN_H
+
+//*****************************************************************************
+//
+//! @name Reset Generator Configuration
+//! @brief These macros may be used to set the reset generator's configuration.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_RESET_CFG_WDT_RESET_ENABLE (AM_REG_RSTGEN_CFG_WDREN(1))
+// Brown out high (2.1v) reset enable.
+#define AM_HAL_RESET_CFG_BOD_HIGH_RESET_ENABLE (AM_REG_RSTGEN_CFG_BODHREN(1))
+//! @}
+
+//*****************************************************************************
+//
+//! @name Reset Generator Status Bit Masks
+//! @brief These macros may be used to determine which type(s) of resets have
+//! been seen.
+//! @{
+//
+//*****************************************************************************
+// Reset was initiated by a Watchdog Timer Reset.
+#define AM_HAL_RESET_STAT_WDT (AM_REG_RSTGEN_STAT_WDRSTAT_M)
+
+// Reset was a initiated by Debugger Reset.
+#define AM_HAL_RESET_STAT_DEBUG (AM_REG_RSTGEN_STAT_DBGRSTAT_M)
+
+// Reset was a initiated by Software POI Reset.
+#define AM_HAL_RESET_STAT_POI (AM_REG_RSTGEN_STAT_POIRSTAT_M)
+
+// Reset was a initiated by Software POR or AIRCR Reset.
+#define AM_HAL_RESET_STAT_SOFTWARE (AM_REG_RSTGEN_STAT_SWRSTAT_M)
+
+// Reset was initiated by a Brown-Out Reset.
+#define AM_HAL_RESET_STAT_BOD (AM_REG_RSTGEN_STAT_BORSTAT_M)
+
+// Reset was initiated by a Power Cycle
+#define AM_HAL_RESET_STAT_POWER_CYCLE (AM_REG_RSTGEN_STAT_PORSTAT_M)
+
+// Reset was initiated by an External Reset.
+#define AM_HAL_RESET_STAT_EXTERNAL (AM_REG_RSTGEN_STAT_EXRSTAT_M)
+//! @}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_reset_init(uint32_t ui32Config);
+extern void am_hal_reset_por(void);
+extern void am_hal_reset_poi(void);
+extern uint32_t am_hal_reset_status_get(void);
+extern void am_hal_reset_status_clear(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_RSTGEN_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_rtc.c b/bsp/apollo2/libraries/drivers/hal/am_hal_rtc.c
new file mode 100644
index 0000000000..4630d5a117
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_rtc.c
@@ -0,0 +1,678 @@
+//*****************************************************************************
+//
+// am_hal_rtc.c
+//! @file
+//!
+//! @brief Functions for interfacing with the Real-Time Clock (RTC).
+//!
+//! @addtogroup rtc2 Real-Time Clock (RTC)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Converts a Binary Coded Decimal (BCD) byte to its Decimal form.
+//
+//*****************************************************************************
+static uint8_t
+bcd_to_dec(uint8_t ui8BCDByte)
+{
+ return (((ui8BCDByte & 0xF0) >> 4) * 10) + (ui8BCDByte & 0x0F);
+}
+
+//*****************************************************************************
+//
+// Converts a Decimal byte to its Binary Coded Decimal (BCD) form.
+//
+//*****************************************************************************
+static uint8_t
+dec_to_bcd(uint8_t ui8DecimalByte)
+{
+ return (((ui8DecimalByte / 10) << 4) | (ui8DecimalByte % 10));
+}
+
+//*****************************************************************************
+//
+//! @brief Selects the clock source for the RTC.
+//!
+//! @param ui32OSC the clock source for the RTC.
+//!
+//! This function selects the clock source for the RTC.
+//!
+//! Valid values for ui32OSC are:
+//!
+//! AM_HAL_RTC_OSC_LFRC
+//! AM_HAL_RTC_OSC_XT
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_rtc_osc_select(uint32_t ui32OSC)
+{
+ //
+ // Set XT if flag is set.
+ // Otherwise configure for LFRC.
+ //
+ if (ui32OSC)
+ {
+ AM_REG(CLKGEN, OCTRL) |= AM_REG_CLKGEN_OCTRL_OSEL_M;
+ }
+ else
+ {
+ AM_REG(CLKGEN, OCTRL) &= ~AM_REG_CLKGEN_OCTRL_OSEL_M;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Enable/Start the RTC oscillator.
+//!
+//! Starts the RTC oscillator.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_osc_enable(void)
+{
+ //
+ // Start the RTC Oscillator.
+ //
+ AM_REG(RTC, RTCCTL) &= ~AM_REG_RTC_RTCCTL_RSTOP(1);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable/Stop the RTC oscillator.
+//!
+//! Stops the RTC oscillator.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_osc_disable(void)
+{
+ //
+ // Stop the RTC Oscillator.
+ //
+ AM_REG(RTC, RTCCTL) |= AM_REG_RTC_RTCCTL_RSTOP(1);
+}
+
+//*****************************************************************************
+//
+//! @brief Configures the RTC for 12 or 24 hour time keeping.
+//!
+//! @param b12Hour - A 'true' configures the RTC for 12 hour time keeping.
+//!
+//! Configures the RTC for 12 (true) or 24 (false) hour time keeping.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_time_12hour(bool b12Hour)
+{
+ //
+ // Set the 12/24 hour bit.
+ //
+ AM_REG(RTC, RTCCTL) |= AM_REG_RTC_RTCCTL_HR1224(b12Hour);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable selected RTC interrupts.
+//!
+//! @param ui32Interrupt - desired interrupts
+//!
+//! Enables the RTC interrupts.
+//!
+//! ui32Interrupt should be an OR of the following:
+//!
+//! AM_HAL_RTC_INT_ALM
+//! AM_HAL_RTC_INT_OF
+//! AM_HAL_RTC_INT_ACC
+//! AM_HAL_RTC_INT_ACF
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_int_enable(uint32_t ui32Interrupt)
+{
+ //
+ // Enable the interrupts.
+ //
+ AM_REG(RTC, INTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return the enabled RTC interrupts.
+//!
+//! Returns the enabled RTC interrupts.
+//!
+//! @return enabled RTC interrupts. Return is a logical or of:
+//!
+//! AM_HAL_RTC_INT_ALM
+//! AM_HAL_RTC_INT_OF
+//! AM_HAL_RTC_INT_ACC
+//! AM_HAL_RTC_INT_ACF
+//
+//*****************************************************************************
+uint32_t
+am_hal_rtc_int_enable_get(void)
+{
+ //
+ // Read the RTC interrupt enable register, and return its contents.
+ //
+ return AM_REG(RTC, INTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable selected RTC interrupts.
+//!
+//! @param ui32Interrupt - desired interrupts
+//!
+//! Disables the RTC interrupts.
+//!
+//! ui32Interrupt should be an OR of the following:
+//!
+//! AM_HAL_RTC_INT_ALM
+//! AM_HAL_RTC_INT_OF
+//! AM_HAL_RTC_INT_ACC
+//! AM_HAL_RTC_INT_ACF
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_int_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Disable the interrupts.
+ //
+ AM_REG(RTC, INTEN) &= ~ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Sets the selected RTC interrupts.
+//!
+//! @param ui32Interrupt - desired interrupts
+//!
+//! Sets the RTC interrupts causing them to immediately trigger.
+//!
+//! ui32Interrupt should be an OR of the following:
+//!
+//! AM_HAL_RTC_INT_ALM
+//! AM_HAL_RTC_INT_OF
+//! AM_HAL_RTC_INT_ACC
+//! AM_HAL_RTC_INT_ACF
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Set the interrupts.
+ //
+ AM_REG(RTC, INTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Clear selected RTC interrupts.
+//!
+//! @param ui32Interrupt - desired interrupts
+//!
+//! Clears the RTC interrupts.
+//!
+//! ui32Interrupt should be an OR of the following:
+//!
+//! AM_HAL_RTC_INT_ALM
+//! AM_HAL_RTC_INT_OF
+//! AM_HAL_RTC_INT_ACC
+//! AM_HAL_RTC_INT_ACF
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Clear the interrupts.
+ //
+ AM_REG(RTC, INTCLR) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Returns the RTC interrupt status.
+//!
+//! @param bEnabledOnly - return the status of only the enabled interrupts.
+//!
+//! Returns the RTC interrupt status.
+//!
+//! @return Bitwise representation of the current interrupt status.
+//!
+//! The return value will be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_RTC_INT_ALM
+//! AM_HAL_RTC_INT_OF
+//! AM_HAL_RTC_INT_ACC
+//! AM_HAL_RTC_INT_ACF
+//
+//*****************************************************************************
+uint32_t
+am_hal_rtc_int_status_get(bool bEnabledOnly)
+{
+ //
+ // Get the interrupt status.
+ //
+ if (bEnabledOnly)
+ {
+ uint32_t u32RetVal;
+ u32RetVal = AM_REG(RTC, INTSTAT);
+ u32RetVal &= AM_REG(RTC, INTEN);
+ return u32RetVal &
+ (AM_HAL_RTC_INT_ALM | AM_HAL_RTC_INT_OF |
+ AM_HAL_RTC_INT_ACC | AM_HAL_RTC_INT_ACF);
+ }
+ else
+ {
+ return (AM_REG(RTC, INTSTAT) & (AM_HAL_RTC_INT_ALM |
+ AM_HAL_RTC_INT_OF |
+ AM_HAL_RTC_INT_ACC |
+ AM_HAL_RTC_INT_ACF));
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Set the Real Time Clock counter registers.
+//!
+//! @param *pTime - A pointer to the time structure.
+//!
+//! Sets the RTC counter registers to the supplied values.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_time_set(am_hal_rtc_time_t *pTime)
+{
+ //
+ // Enable writing to the counters.
+ //
+ AM_REG(RTC, RTCCTL) |= AM_REG_RTC_RTCCTL_WRTC(1);
+
+ //
+ // Write the RTCLOW register.
+ //
+ AM_REG(RTC, CTRLOW) =
+ AM_REG_RTC_CTRLOW_CTRHR(dec_to_bcd(pTime->ui32Hour)) |
+ AM_REG_RTC_CTRLOW_CTRMIN(dec_to_bcd(pTime->ui32Minute)) |
+ AM_REG_RTC_CTRLOW_CTRSEC(dec_to_bcd(pTime->ui32Second)) |
+ AM_REG_RTC_CTRLOW_CTR100(dec_to_bcd(pTime->ui32Hundredths));
+
+ //
+ // Write the RTCUP register.
+ //
+ AM_REG(RTC, CTRUP) =
+ AM_REG_RTC_CTRUP_CEB((pTime->ui32CenturyEnable)) |
+ AM_REG_RTC_CTRUP_CB((pTime->ui32Century)) |
+ AM_REG_RTC_CTRUP_CTRWKDY((pTime->ui32Weekday)) |
+ AM_REG_RTC_CTRUP_CTRYR(dec_to_bcd((pTime->ui32Year))) |
+ AM_REG_RTC_CTRUP_CTRMO(dec_to_bcd((pTime->ui32Month))) |
+ AM_REG_RTC_CTRUP_CTRDATE(dec_to_bcd((pTime->ui32DayOfMonth)));
+
+ //
+ // Disable writing to the counters.
+ //
+ AM_REG(RTC, RTCCTL) |= AM_REG_RTC_RTCCTL_WRTC(0);
+}
+
+//*****************************************************************************
+//
+//! @brief Get the Real Time Clock current time.
+//!
+//! @param *pTime - A pointer to the time structure to store the current time.
+//!
+//! Gets the RTC's current time
+//!
+//! @return 0 for success and 1 for error.
+//
+//*****************************************************************************
+uint32_t
+am_hal_rtc_time_get(am_hal_rtc_time_t *pTime)
+{
+ uint32_t ui32RTCLow, ui32RTCUp, ui32Value;
+
+ //
+ // Read the upper and lower RTC registers.
+ //
+ ui32RTCLow = AM_REG(RTC, CTRLOW);
+ ui32RTCUp = AM_REG(RTC, CTRUP);
+
+ //
+ // Break out the lower word.
+ //
+ ui32Value =
+ ((ui32RTCLow & AM_REG_RTC_CTRLOW_CTRHR_M) >> AM_REG_RTC_CTRLOW_CTRHR_S);
+ pTime->ui32Hour = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32RTCLow & AM_REG_RTC_CTRLOW_CTRMIN_M) >> AM_REG_RTC_CTRLOW_CTRMIN_S);
+ pTime->ui32Minute = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32RTCLow & AM_REG_RTC_CTRLOW_CTRSEC_M) >> AM_REG_RTC_CTRLOW_CTRSEC_S);
+ pTime->ui32Second = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32RTCLow & AM_REG_RTC_CTRLOW_CTR100_M) >> AM_REG_RTC_CTRLOW_CTR100_S);
+ pTime->ui32Hundredths = bcd_to_dec(ui32Value);
+
+ //
+ // Break out the upper word.
+ //
+ pTime->ui32ReadError =
+ ((ui32RTCUp & AM_REG_RTC_CTRUP_CTERR_M) >> AM_REG_RTC_CTRUP_CTERR_S);
+
+ pTime->ui32CenturyEnable =
+ ((ui32RTCUp & AM_REG_RTC_CTRUP_CEB_M) >> AM_REG_RTC_CTRUP_CEB_S);
+
+ pTime->ui32Century =
+ ((ui32RTCUp & AM_REG_RTC_CTRUP_CB_M) >> AM_REG_RTC_CTRUP_CB_S);
+
+ ui32Value =
+ ((ui32RTCUp & AM_REG_RTC_CTRUP_CTRWKDY_M) >> AM_REG_RTC_CTRUP_CTRWKDY_S);
+ pTime->ui32Weekday = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32RTCUp & AM_REG_RTC_CTRUP_CTRYR_M) >> AM_REG_RTC_CTRUP_CTRYR_S);
+ pTime->ui32Year = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32RTCUp & AM_REG_RTC_CTRUP_CTRMO_M) >> AM_REG_RTC_CTRUP_CTRMO_S);
+ pTime->ui32Month = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32RTCUp & AM_REG_RTC_CTRUP_CTRDATE_M) >> AM_REG_RTC_CTRUP_CTRDATE_S);
+ pTime->ui32DayOfMonth = bcd_to_dec(ui32Value);
+
+ //
+ // Was there a read error?
+ //
+ if (pTime->ui32ReadError)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Sets the alarm repeat interval.
+//!
+//! @param ui32RepeatInterval the desired repeat interval.
+//!
+//! Sets the alarm repeat interval.
+//!
+//! Valid values for ui32RepeatInterval:
+//!
+//! AM_HAL_RTC_ALM_RPT_DIS
+//! AM_HAL_RTC_ALM_RPT_YR
+//! AM_HAL_RTC_ALM_RPT_MTH
+//! AM_HAL_RTC_ALM_RPT_WK
+//! AM_HAL_RTC_ALM_RPT_DAY
+//! AM_HAL_RTC_ALM_RPT_HR
+//! AM_HAL_RTC_ALM_RPT_MIN
+//! AM_HAL_RTC_ALM_RPT_SEC
+//! AM_HAL_RTC_ALM_RPT_10TH
+//! AM_HAL_RTC_ALM_RPT_100TH
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_alarm_interval_set(uint32_t ui32RepeatInterval)
+{
+ uint32_t ui32RptInt, ui32Alm100, ui32Value;
+
+ switch(ui32RepeatInterval)
+ {
+ //
+ // If repeat every 10th set RPT and ALM100 field accordinly
+ //
+ case AM_HAL_RTC_ALM_RPT_10TH:
+ ui32RptInt = AM_HAL_RTC_ALM_RPT_SEC;
+ ui32Alm100 = AM_HAL_RTC_ALM100_10TH;
+ break;
+ //
+ // If repeat every 100th set RPT and ALM100 field accordinly
+ //
+ case AM_HAL_RTC_ALM_RPT_100TH:
+ ui32RptInt = AM_HAL_RTC_ALM_RPT_SEC;
+ ui32Alm100 = AM_HAL_RTC_ALM100_100TH;
+ break;
+ //
+ // Otherwise set RPT as value passed. ALM100 values need to be 0xnn
+ // in this setting where n = 0-9.
+ //
+ default:
+ //
+ // Get the current value of the ALM100 field.
+ //
+ ui32Value = AM_BFR(RTC, ALMLOW, ALM100);
+
+ //
+ // If ALM100 was previous EVERY_10TH or EVERY_100TH reset to zero
+ // otherwise keep previous setting.
+ //
+ ui32Alm100 = ui32Value >= 0xF0 ? 0 : ui32Value;
+
+ //
+ // Set RPT value to value passed.
+ //
+ ui32RptInt = ui32RepeatInterval;
+ break;
+ }
+
+ //
+ // Write the interval to the register.
+ //
+ AM_BFW(RTC, RTCCTL, RPT, ui32RptInt);
+
+ //
+ // Write the Alarm 100 bits in the ALM100 register.
+ //
+ AM_BFW(RTC, ALMLOW, ALM100, ui32Alm100);
+}
+
+//*****************************************************************************
+//
+//! @brief Sets the RTC's Alarm.
+//!
+//! @param *pTime - A pointer to the time structure.
+//! @param ui32RepeatInterval - the desired alarm repeat interval.
+//!
+//! Set the Real Time Clock Alarm Parameters.
+//!
+//! Valid values for ui32RepeatInterval:
+//!
+//! AM_HAL_RTC_ALM_RPT_DIS
+//! AM_HAL_RTC_ALM_RPT_YR
+//! AM_HAL_RTC_ALM_RPT_MTH
+//! AM_HAL_RTC_ALM_RPT_WK
+//! AM_HAL_RTC_ALM_RPT_DAY
+//! AM_HAL_RTC_ALM_RPT_HR
+//! AM_HAL_RTC_ALM_RPT_MIN
+//! AM_HAL_RTC_ALM_RPT_SEC
+//! AM_HAL_RTC_ALM_RPT_10TH
+//! AM_HAL_RTC_ALM_RPT_EVERY_100TH
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_alarm_set(am_hal_rtc_time_t *pTime, uint32_t ui32RepeatInterval)
+{
+ uint8_t ui8Value = 0;
+
+ //
+ // Write the interval to the register.
+ //
+ AM_REG(RTC, RTCCTL) |=
+ AM_REG_RTC_RTCCTL_RPT(ui32RepeatInterval > 0x7 ? 0x7 : ui32RepeatInterval);
+
+ //
+ // Check if the interval is 10th or every 100th and track it in ui8Value.
+ //
+ if (ui32RepeatInterval == AM_HAL_RTC_ALM_RPT_10TH)
+ {
+ ui8Value = 0xF0;
+ }
+ else if (ui32RepeatInterval == AM_HAL_RTC_ALM_RPT_100TH)
+ {
+ ui8Value = 0xFF;
+ }
+
+ //
+ // Write the ALMUP register.
+ //
+ AM_REG(RTC, ALMUP) =
+ AM_REG_RTC_ALMUP_ALMWKDY((pTime->ui32Weekday)) |
+ AM_REG_RTC_ALMUP_ALMMO(dec_to_bcd((pTime->ui32Month))) |
+ AM_REG_RTC_ALMUP_ALMDATE(dec_to_bcd((pTime->ui32DayOfMonth)));
+
+ //
+ // Write the ALMLOW register.
+ //
+ AM_REG(RTC, ALMLOW) =
+ AM_REG_RTC_ALMLOW_ALMHR(dec_to_bcd(pTime->ui32Hour)) |
+ AM_REG_RTC_ALMLOW_ALMMIN(dec_to_bcd(pTime->ui32Minute)) |
+ AM_REG_RTC_ALMLOW_ALMSEC(dec_to_bcd(pTime->ui32Second)) |
+ AM_REG_RTC_ALMLOW_ALM100(dec_to_bcd(pTime->ui32Hundredths) | ui8Value);
+}
+
+//*****************************************************************************
+//
+//! @brief Get the Real Time Clock Alarm Parameters
+//!
+//! @param *pTime - A pointer to the time structure to store the current alarm.
+//!
+//! Gets the RTC's Alarm time
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_rtc_alarm_get(am_hal_rtc_time_t *pTime)
+{
+ uint32_t ui32ALMLow, ui32ALMUp, ui32Value;
+
+ //
+ // Read the upper and lower RTC registers.
+ //
+ ui32ALMLow = AM_REG(RTC, ALMLOW);
+ ui32ALMUp = AM_REG(RTC, ALMUP);
+
+ //
+ // Break out the lower word.
+ //
+ ui32Value =
+ ((ui32ALMLow & AM_REG_RTC_ALMLOW_ALMHR_M) >> AM_REG_RTC_ALMLOW_ALMHR_S);
+ pTime->ui32Hour = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32ALMLow & AM_REG_RTC_ALMLOW_ALMMIN_M) >> AM_REG_RTC_ALMLOW_ALMMIN_S);
+ pTime->ui32Minute = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32ALMLow & AM_REG_RTC_ALMLOW_ALMSEC_M) >> AM_REG_RTC_ALMLOW_ALMSEC_S);
+ pTime->ui32Second = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32ALMLow & AM_REG_RTC_ALMLOW_ALM100_M) >> AM_REG_RTC_ALMLOW_ALM100_S);
+ pTime->ui32Hundredths = bcd_to_dec(ui32Value);
+
+ //
+ // Break out the upper word.
+ //
+ pTime->ui32ReadError = 0;
+ pTime->ui32CenturyEnable = 0;
+ pTime->ui32Century = 0;
+
+ ui32Value =
+ ((ui32ALMUp & AM_REG_RTC_ALMUP_ALMWKDY_M) >> AM_REG_RTC_ALMUP_ALMWKDY_S);
+ pTime->ui32Weekday = bcd_to_dec(ui32Value);
+
+ pTime->ui32Year = 0;
+
+ ui32Value =
+ ((ui32ALMUp & AM_REG_RTC_ALMUP_ALMMO_M) >> AM_REG_RTC_ALMUP_ALMMO_S);
+ pTime->ui32Month = bcd_to_dec(ui32Value);
+
+ ui32Value =
+ ((ui32ALMUp & AM_REG_RTC_ALMUP_ALMDATE_M) >> AM_REG_RTC_ALMUP_ALMDATE_S);
+ pTime->ui32DayOfMonth = bcd_to_dec(ui32Value);
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_rtc.h b/bsp/apollo2/libraries/drivers/hal/am_hal_rtc.h
new file mode 100644
index 0000000000..9304a6c67f
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_rtc.h
@@ -0,0 +1,185 @@
+//*****************************************************************************
+//
+// am_hal_rtc.h
+//! @file
+//!
+//! @brief Functions for interfacing and accessing the Real-Time Clock (RTC).
+//!
+//! @addtogroup rtc2 Real-Time Clock (RTC)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_RTC_H
+#define AM_HAL_RTC_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! @name OSC Start and Stop
+//! @brief OSC Start and Stop defines.
+//!
+//! OSC Start and Stop defines to be used with \e am_hal_clkgen_osc_x().
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_RTC_OSC_LFRC 0x1
+#define AM_HAL_RTC_OSC_XT 0x0
+//! @}
+
+//*****************************************************************************
+//
+//! @name RTC Interrupts
+//! @brief Macro definitions for RTC interrupt status bits.
+//!
+//! These macros correspond to the bits in the RTC interrupt status register.
+//! They may be used with any of the \e am_hal_rtc_int_x() functions.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_RTC_INT_ALM AM_REG_RTC_INTEN_ALM_M
+#define AM_HAL_RTC_INT_OF AM_REG_RTC_INTEN_OF_M
+#define AM_HAL_RTC_INT_ACC AM_REG_RTC_INTEN_ACC_M
+#define AM_HAL_RTC_INT_ACF AM_REG_RTC_INTEN_ACF_M
+//! @}
+
+//*****************************************************************************
+//
+//! @name RTC Alarm Repeat Interval.
+//! @brief Macro definitions for the RTC alarm repeat interval.
+//!
+//! These macros correspond to the RPT bits in the RTCCTL register.
+//! They may be used with the \e am_hal_rtc_alarm_interval_set() function.
+//!
+//! Note: AM_HAL_RTC_ALM_RPT_10TH and AM_HAL_RTC_ALM_RPT_100TH do not
+//! correspond to the RPT bits but are used in conjunction with setting the
+//! ALM100 bits in the ALMLOW register.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_RTC_ALM_RPT_DIS 0x0
+#define AM_HAL_RTC_ALM_RPT_YR 0x1
+#define AM_HAL_RTC_ALM_RPT_MTH 0x2
+#define AM_HAL_RTC_ALM_RPT_WK 0x3
+#define AM_HAL_RTC_ALM_RPT_DAY 0x4
+#define AM_HAL_RTC_ALM_RPT_HR 0x5
+#define AM_HAL_RTC_ALM_RPT_MIN 0x6
+#define AM_HAL_RTC_ALM_RPT_SEC 0x7
+#define AM_HAL_RTC_ALM_RPT_10TH 0x8
+#define AM_HAL_RTC_ALM_RPT_100TH 0x9
+//! @}
+
+//*****************************************************************************
+//
+//! @name RTC Alarm 100 Interval.
+//! @brief Macro definitions for the RTC alarm ms intervals.
+//!
+//! These macros are used inside the #am_hal_rtc_alarm_interval_set function
+//! when 10ms and 100ms repeated alarm intervals are desired.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_RTC_ALM100_DEFAULT 0x00
+#define AM_HAL_RTC_ALM100_10TH 0xF0
+#define AM_HAL_RTC_ALM100_100TH 0xFF
+//! @}
+
+//*****************************************************************************
+//
+//! @brief The basic time structure used by the HAL for RTC interaction.
+//!
+//! All values are positive whole numbers. The HAL routines convert back and
+//! forth to BCD.
+//
+//*****************************************************************************
+typedef struct am_hal_rtc_time_struct
+{
+ uint32_t ui32ReadError;
+ uint32_t ui32CenturyEnable;
+ uint32_t ui32Weekday;
+ uint32_t ui32Century;
+ uint32_t ui32Year;
+ uint32_t ui32Month;
+ uint32_t ui32DayOfMonth;
+ uint32_t ui32Hour;
+ uint32_t ui32Minute;
+ uint32_t ui32Second;
+ uint32_t ui32Hundredths;
+}am_hal_rtc_time_t;
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_rtc_osc_select(uint32_t ui32OSC);
+extern void am_hal_rtc_osc_enable(void);
+extern void am_hal_rtc_osc_disable(void);
+extern void am_hal_rtc_time_12hour(bool b12Hour);
+extern void am_hal_rtc_time_set(am_hal_rtc_time_t *pTime);
+extern uint32_t am_hal_rtc_time_get(am_hal_rtc_time_t *pTime);
+extern void am_hal_rtc_alarm_interval_set(uint32_t ui32RepeatInterval);
+extern void am_hal_rtc_alarm_set(am_hal_rtc_time_t *pTime,
+ uint32_t ui32RepeatInterval);
+extern void am_hal_rtc_alarm_get(am_hal_rtc_time_t *pTime);
+extern void am_hal_rtc_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_rtc_int_enable_get(void);
+extern void am_hal_rtc_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_rtc_int_clear(uint32_t ui32Interrupt);
+extern void am_hal_rtc_int_set(uint32_t ui32Interrupt);
+extern uint32_t am_hal_rtc_int_status_get(bool bEnabledOnly);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_RTC_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_stimer.c b/bsp/apollo2/libraries/drivers/hal/am_hal_stimer.c
new file mode 100644
index 0000000000..0cdd706c9e
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_stimer.c
@@ -0,0 +1,525 @@
+//*****************************************************************************
+//
+// am_hal_stimer.c
+//! @file
+//!
+//! @brief Functions for interfacing with the system timer (STIMER).
+//!
+//! @addtogroup stimer2 System Timer (STIMER)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Set up the stimer.
+//!
+//! @param ui32STimerConfig is the value to load into the configuration reg.
+//!
+//! This function should be used to perform the initial set-up of the
+//! stimer.
+//!
+//! @return The 32-bit current config of the STimer Config register
+//
+//*****************************************************************************
+uint32_t
+am_hal_stimer_config(uint32_t ui32STimerConfig)
+{
+ uint32_t ui32CurrVal;
+
+ //
+ // Read the current config
+ //
+ ui32CurrVal = AM_REG(CTIMER, STCFG);
+
+ //
+ // Write our configuration value.
+ //
+ AM_REG(CTIMER, STCFG) = ui32STimerConfig;
+
+ //
+ // If all of the clock sources are not HFRC, disable LDO when sleeping if timers are enabled.
+ //
+ if ( (AM_BFR(CTIMER, STCFG, CLKSEL) == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV16) ||
+ (AM_BFR(CTIMER, STCFG, CLKSEL) == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV256) )
+ {
+ AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 0);
+ }
+ else
+ {
+ AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 1);
+ }
+ return ui32CurrVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Get the current stimer value.
+//!
+//! This function can be used to read, uninvasively, the value in the stimer.
+//!
+//! @return The 32-bit value from the STimer counter register.
+//
+//*****************************************************************************
+uint32_t
+am_hal_stimer_counter_get(void)
+{
+ return AM_REG(CTIMER, STTMR);
+}
+
+//*****************************************************************************
+//
+//! @brief Clear the stimer counter.
+//!
+//! This function clears the STimer Counter and leaves the stimer running.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_stimer_counter_clear(void)
+{
+ //
+ // Set the clear bit
+ //
+ AM_REG(CTIMER, STCFG) |= AM_REG_CTIMER_STCFG_CLEAR_M;
+
+ //
+ // Reset the clear bit
+ //
+ AM_REG(CTIMER, STCFG) &= ~AM_REG_CTIMER_STCFG_CLEAR_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Set the compare value.
+//!
+//! @param ui32CmprInstance is the compare register instance number (0-7).
+//! @param ui32Delta is the value to add to the STimer counter and load into
+//! the comparator register.
+//!
+//! NOTE: There is no way to set an absolute value into a comparator register.
+//! Only deltas added to the STimer counter can be written to the compare
+//! registers.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_stimer_compare_delta_set(uint32_t ui32CmprInstance, uint32_t ui32Delta)
+{
+ if ( ui32CmprInstance > 7 )
+ {
+ return;
+ }
+
+ AM_REGVAL(AM_REG_STIMER_COMPARE(0, ui32CmprInstance)) = ui32Delta;
+}
+
+//*****************************************************************************
+//
+//! @brief Get the current stimer compare register value.
+//!
+//! @param ui32CmprInstance is the compare register instance number (0-7).
+//!
+//! This function can be used to read the value in an stimer compare register.
+//!
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t
+am_hal_stimer_compare_get(uint32_t ui32CmprInstance)
+{
+ if ( ui32CmprInstance > 7 )
+ {
+ return 0;
+ }
+
+ return AM_REGVAL(AM_REG_STIMER_COMPARE(0, ui32CmprInstance));
+}
+
+//*****************************************************************************
+//
+//! @brief Start capturing data with the specified capture register.
+//!
+//! @param ui32CaptureNum is the Capture Register Number to read (0-3).
+//! ui32GPIONumber is the pin number.
+//! bPolarity: false (0) = Capture on low to high transition.
+//! true (1) = Capture on high to low transition.
+//!
+//! Use this function to start capturing.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_stimer_capture_start(uint32_t ui32CaptureNum,
+ uint32_t ui32GPIONumber,
+ bool bPolarity)
+{
+ uint32_t ui32CapCtrl;
+
+ if ( ui32GPIONumber > (AM_HAL_GPIO_MAX_PADS-1) )
+ {
+ return;
+ }
+
+ //
+ // Set the polarity and pin selection in the GPIO block.
+ //
+ switch (ui32CaptureNum)
+ {
+ case 0:
+ AM_BFW(GPIO, STMRCAP, STPOL0, bPolarity);
+ AM_BFW(GPIO, STMRCAP, STSEL0, ui32GPIONumber);
+ ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_A_M;
+ break;
+ case 1:
+ AM_BFW(GPIO, STMRCAP, STPOL1, bPolarity);
+ AM_BFW(GPIO, STMRCAP, STSEL1, ui32GPIONumber);
+ ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_B_M;
+ break;
+ case 2:
+ AM_BFW(GPIO, STMRCAP, STPOL2, bPolarity);
+ AM_BFW(GPIO, STMRCAP, STSEL2, ui32GPIONumber);
+ ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_C_M;
+ break;
+ case 3:
+ AM_BFW(GPIO, STMRCAP, STPOL3, bPolarity);
+ AM_BFW(GPIO, STMRCAP, STSEL3, ui32GPIONumber);
+ ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_D_M;
+ break;
+ default:
+ return; // error concealment.
+ }
+
+ //
+ // Enable it in the CTIMER Block
+ //
+ AM_REG(CTIMER, CAPTURE_CONTROL) |= ui32CapCtrl;
+}
+
+//*****************************************************************************
+//
+//! @brief Start capturing data with the specified capture register.
+//!
+//! @param ui32CaptureNum is the Capture Register Number to read.
+//!
+//! Use this function to start capturing.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void am_hal_stimer_capture_stop(uint32_t ui32CaptureNum)
+{
+ //
+ // Disable it in the CTIMER block.
+ //
+ AM_REG(CTIMER, CAPTURE_CONTROL) &=
+ ~(AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_A_M <<
+ ((AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_B_S -
+ AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_A_S) * ui32CaptureNum));
+}
+
+//*****************************************************************************
+//
+//! @brief Get the current stimer capture register value.
+//!
+//! @param ui32CaptureNum is the Capture Register Number to read.
+//!
+//! This function can be used to read the value in an stimer capture register.
+//!
+//!
+//! @return None.
+//
+//*****************************************************************************
+uint32_t am_hal_stimer_capture_get(uint32_t ui32CaptureNum)
+{
+ if ( ui32CaptureNum > 7 )
+ {
+ return 0;
+ }
+
+ return AM_REGVAL(AM_REG_STIMER_CAPTURE(0, ui32CaptureNum));
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the selected system timer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will enable the selected interrupts in the STIMER interrupt
+//! enable register. In order to receive an interrupt from an stimer component,
+//! you will need to enable the interrupt for that component in this main
+//! register, as well as in the stimer configuration register (accessible though
+//! am_hal_stimer_config()), and in the NVIC.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_STIMER_INT_COMPAREA
+//! AM_HAL_STIMER_INT_COMPAREB
+//! AM_HAL_STIMER_INT_COMPAREC
+//! AM_HAL_STIMER_INT_COMPARED
+//! AM_HAL_STIMER_INT_COMPAREE
+//! AM_HAL_STIMER_INT_COMPAREF
+//! AM_HAL_STIMER_INT_COMPAREG
+//! AM_HAL_STIMER_INT_COMPAREH
+//!
+//! AM_HAL_STIMER_INT_OVERFLOW
+//!
+//! AM_HAL_STIMER_INT_CAPTUREA
+//! AM_HAL_STIMER_INT_CAPTUREB
+//! AM_HAL_STIMER_INT_CAPTUREC
+//! AM_HAL_STIMER_INT_CAPTURED
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_stimer_int_enable(uint32_t ui32Interrupt)
+{
+ //
+ // Enable the interrupt at the module level.
+ //
+ AM_REGn(CTIMER, 0, STMINTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return the enabled stimer interrupts.
+//!
+//! This function will return all enabled interrupts in the STIMER
+//! interrupt enable register.
+//!
+//! @return return enabled interrupts. This will be a logical or of:
+//!
+//! AM_HAL_STIMER_INT_COMPAREA
+//! AM_HAL_STIMER_INT_COMPAREB
+//! AM_HAL_STIMER_INT_COMPAREC
+//! AM_HAL_STIMER_INT_COMPARED
+//! AM_HAL_STIMER_INT_COMPAREE
+//! AM_HAL_STIMER_INT_COMPAREF
+//! AM_HAL_STIMER_INT_COMPAREG
+//! AM_HAL_STIMER_INT_COMPAREH
+//!
+//! AM_HAL_STIMER_INT_OVERFLOW
+//!
+//! AM_HAL_STIMER_INT_CAPTUREA
+//! AM_HAL_STIMER_INT_CAPTUREB
+//! AM_HAL_STIMER_INT_CAPTUREC
+//! AM_HAL_STIMER_INT_CAPTURED
+//!
+//! @return Return the enabled timer interrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_stimer_int_enable_get(void)
+{
+ //
+ // Return enabled interrupts.
+ //
+ return AM_REGn(CTIMER, 0, STMINTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the selected stimer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will disable the selected interrupts in the STIMER
+//! interrupt register.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_STIMER_INT_COMPAREA
+//! AM_HAL_STIMER_INT_COMPAREB
+//! AM_HAL_STIMER_INT_COMPAREC
+//! AM_HAL_STIMER_INT_COMPARED
+//! AM_HAL_STIMER_INT_COMPAREE
+//! AM_HAL_STIMER_INT_COMPAREF
+//! AM_HAL_STIMER_INT_COMPAREG
+//! AM_HAL_STIMER_INT_COMPAREH
+//!
+//! AM_HAL_STIMER_INT_OVERFLOW
+//!
+//! AM_HAL_STIMER_INT_CAPTUREA
+//! AM_HAL_STIMER_INT_CAPTUREB
+//! AM_HAL_STIMER_INT_CAPTUREC
+//! AM_HAL_STIMER_INT_CAPTURED
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_stimer_int_disable(uint32_t ui32Interrupt)
+{
+ //
+ // Disable the interrupt at the module level.
+ //
+ AM_REGn(CTIMER, 0, STMINTEN) &= ~ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Sets the selected stimer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will set the selected interrupts in the STIMER
+//! interrupt register.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_STIMER_INT_COMPAREA
+//! AM_HAL_STIMER_INT_COMPAREB
+//! AM_HAL_STIMER_INT_COMPAREC
+//! AM_HAL_STIMER_INT_COMPARED
+//! AM_HAL_STIMER_INT_COMPAREE
+//! AM_HAL_STIMER_INT_COMPAREF
+//! AM_HAL_STIMER_INT_COMPAREG
+//! AM_HAL_STIMER_INT_COMPAREH
+//!
+//! AM_HAL_STIMER_INT_OVERFLOW
+//!
+//! AM_HAL_STIMER_INT_CAPTUREA
+//! AM_HAL_STIMER_INT_CAPTUREB
+//! AM_HAL_STIMER_INT_CAPTUREC
+//! AM_HAL_STIMER_INT_CAPTURED
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_stimer_int_set(uint32_t ui32Interrupt)
+{
+ //
+ // Set the interrupts.
+ //
+ AM_REGn(CTIMER, 0, STMINTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Clears the selected stimer interrupt.
+//!
+//! @param ui32Interrupt is the interrupt to be used.
+//!
+//! This function will clear the selected interrupts in the STIMER
+//! interrupt register.
+//!
+//! ui32Interrupt should be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_STIMER_INT_COMPAREA
+//! AM_HAL_STIMER_INT_COMPAREB
+//! AM_HAL_STIMER_INT_COMPAREC
+//! AM_HAL_STIMER_INT_COMPARED
+//! AM_HAL_STIMER_INT_COMPAREE
+//! AM_HAL_STIMER_INT_COMPAREF
+//! AM_HAL_STIMER_INT_COMPAREG
+//! AM_HAL_STIMER_INT_COMPAREH
+//!
+//! AM_HAL_STIMER_INT_OVERFLOW
+//!
+//! AM_HAL_STIMER_INT_CAPTUREA
+//! AM_HAL_STIMER_INT_CAPTUREB
+//! AM_HAL_STIMER_INT_CAPTUREC
+//! AM_HAL_STIMER_INT_CAPTURED
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_stimer_int_clear(uint32_t ui32Interrupt)
+{
+ //
+ // Disable the interrupt at the module level.
+ //
+ AM_REGn(CTIMER, 0, STMINTCLR) = ui32Interrupt;
+}
+
+
+//*****************************************************************************
+//
+//! @brief Returns either the enabled or raw stimer interrupt status.
+//!
+//! This function will return the stimer interrupt status.
+//!
+//! @bEnabledOnly if true returns the status of the enabled interrupts
+//! only.
+//!
+//! The return value will be the logical OR of one or more of the following
+//! values:
+//!
+//!
+//! @return Returns the stimer interrupt status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_stimer_int_status_get(bool bEnabledOnly)
+{
+ //
+ // Return the desired status.
+ //
+ uint32_t ui32RetVal = AM_REGn(CTIMER, 0, STMINTSTAT);
+
+ if ( bEnabledOnly )
+ {
+ ui32RetVal &= AM_REGn(CTIMER, 0, STMINTEN);
+ }
+
+ return ui32RetVal;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_stimer.h b/bsp/apollo2/libraries/drivers/hal/am_hal_stimer.h
new file mode 100644
index 0000000000..bd4b09feae
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_stimer.h
@@ -0,0 +1,242 @@
+//*****************************************************************************
+//
+// am_hal_stimer.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the STIMER.
+//!
+//! @addtogroup stimer2 Counter/Timer (STIMER)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_STIMER_H
+#define AM_HAL_STIMER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//
+// Compute address of a given COMPARE or CAPTURE register.
+// Note - For Apollo2, the parameter n should be 0 (as only 1 stimer module
+// exists) and the parameter r should be 0-7 (compare) or 0-3 (capture).
+//
+#define AM_REG_STIMER_COMPARE(n, r) (AM_REG_CTIMERn(n) + \
+ AM_REG_CTIMER_SCMPR0_O + (r * 4))
+
+#define AM_REG_STIMER_CAPTURE(n, r) (AM_REG_CTIMERn(n) + \
+ AM_REG_CTIMER_SCAPT0_O + (r * 4))
+
+//*****************************************************************************
+//
+//! @name Interrupt Status Bits
+//! @brief Interrupt Status Bits for enable/disble use
+//!
+//! These macros may be used to set and clear interrupt bits
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_STIMER_INT_COMPAREA AM_REG_CTIMER_STMINTSTAT_COMPAREA_M
+#define AM_HAL_STIMER_INT_COMPAREB AM_REG_CTIMER_STMINTSTAT_COMPAREB_M
+#define AM_HAL_STIMER_INT_COMPAREC AM_REG_CTIMER_STMINTSTAT_COMPAREC_M
+#define AM_HAL_STIMER_INT_COMPARED AM_REG_CTIMER_STMINTSTAT_COMPARED_M
+#define AM_HAL_STIMER_INT_COMPAREE AM_REG_CTIMER_STMINTSTAT_COMPAREE_M
+#define AM_HAL_STIMER_INT_COMPAREF AM_REG_CTIMER_STMINTSTAT_COMPAREF_M
+#define AM_HAL_STIMER_INT_COMPAREG AM_REG_CTIMER_STMINTSTAT_COMPAREG_M
+#define AM_HAL_STIMER_INT_COMPAREH AM_REG_CTIMER_STMINTSTAT_COMPAREH_M
+
+#define AM_HAL_STIMER_INT_OVERFLOW AM_REG_CTIMER_STMINTSTAT_OVERFLOW_M
+
+#define AM_HAL_STIMER_INT_CAPTUREA AM_REG_CTIMER_STMINTSTAT_CAPTUREA_M
+#define AM_HAL_STIMER_INT_CAPTUREB AM_REG_CTIMER_STMINTSTAT_CAPTUREB_M
+#define AM_HAL_STIMER_INT_CAPTUREC AM_REG_CTIMER_STMINTSTAT_CAPTUREC_M
+#define AM_HAL_STIMER_INT_CAPTURED AM_REG_CTIMER_STMINTSTAT_CAPTURED_M
+
+//! @}
+
+
+
+//*****************************************************************************
+//
+//! @name STimer Configuration Bits
+//! @brief Interrupt Status Bits for enable/disble use
+//!
+//! These macros may be used to set and clear interrupt bits
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_STIMER_CFG_THAW \
+ AM_REG_CTIMER_STCFG_FREEZE_THAW
+#define AM_HAL_STIMER_CFG_FREEZE \
+ AM_REG_CTIMER_STCFG_FREEZE_FREEZE
+#define AM_HAL_STIMER_CFG_RUN \
+ AM_REG_CTIMER_STCFG_CLEAR_RUN
+#define AM_HAL_STIMER_CFG_CLEAR \
+ AM_REG_CTIMER_STCFG_CLEAR_CLEAR
+#define AM_HAL_STIMER_CFG_COMPARE_A_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_A_EN_ENABLE
+#define AM_HAL_STIMER_CFG_COMPARE_B_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_B_EN_ENABLE
+#define AM_HAL_STIMER_CFG_COMPARE_C_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_C_EN_ENABLE
+#define AM_HAL_STIMER_CFG_COMPARE_D_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_D_EN_ENABLE
+#define AM_HAL_STIMER_CFG_COMPARE_E_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_E_EN_ENABLE
+#define AM_HAL_STIMER_CFG_COMPARE_F_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_F_EN_ENABLE
+#define AM_HAL_STIMER_CFG_COMPARE_G_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_G_EN_ENABLE
+#define AM_HAL_STIMER_CFG_COMPARE_H_ENABLE \
+ AM_REG_CTIMER_STCFG_COMPARE_H_EN_ENABLE
+
+//! @}
+
+//*****************************************************************************
+//
+//! @name Clock Configuration options
+//! @brief STimer Configuration register options.
+//!
+//! These options are to be used with the am_hal_stimer_config() function.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_STIMER_NO_CLK \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_NOCLK)
+#define AM_HAL_STIMER_HFRC_3MHZ \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV16)
+#define AM_HAL_STIMER_HFRC_187_5KHZ \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV256)
+#define AM_HAL_STIMER_XTAL_32KHZ \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_XTAL_DIV1)
+#define AM_HAL_STIMER_XTAL_16KHZ \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_XTAL_DIV2)
+#define AM_HAL_STIMER_XTAL_1KHZ \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_XTAL_DIV32)
+#define AM_HAL_STIMER_LFRC_1KHZ \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_LFRC_DIV1)
+#define AM_HAL_STIMER_HFRC_CTIMER0A \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_CTIMER0A)
+#define AM_HAL_STIMER_HFRC_CTIMER0B \
+ AM_REG_CTIMER_STCFG_CLKSEL(AM_REG_CTIMER_STCFG_CLKSEL_CTIMER0B)
+//! @}
+
+
+
+//*****************************************************************************
+//
+//! @name Capture Control Register options.
+//! @brief Configuration options for capture control register.
+//!
+//! These options are to be used with the am_hal_stimer_capture_control_set
+//! function.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_STIMER_CAPTURE_A_ENABLE \
+ AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_A_ENABLE
+#define AM_HAL_STIMER_CAPTURE_B_ENABLE \
+ AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_B_ENABLE
+#define AM_HAL_STIMER_CAPTURE_C_ENABLE \
+ AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_C_ENABLE
+#define AM_HAL_STIMER_CAPTURE_D_ENABLE \
+ AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_D_ENABLE
+
+//! @}
+
+
+//*****************************************************************************
+//
+//
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Stimer configuration structure
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! Configuration options for the STIMER
+ //
+ uint32_t ui32STimerConfig;
+}
+am_hal_stimer_config_t;
+
+
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern uint32_t am_hal_stimer_config(uint32_t ui32STimerConfig);
+extern uint32_t am_hal_stimer_counter_get(void);
+extern void am_hal_stimer_counter_clear(void);
+extern void am_hal_stimer_compare_delta_set(uint32_t ui32CmprInstance,
+ uint32_t ui32Delta);
+extern uint32_t am_hal_stimer_compare_get(uint32_t ui32CmprInstance);
+extern void am_hal_stimer_capture_start(uint32_t ui32CaptureNum,
+ uint32_t ui32GPIONumber,
+ bool bPolarity);
+extern void am_hal_stimer_capture_stop(uint32_t ui32CaptureNum);
+extern uint32_t am_hal_stimer_capture_get(uint32_t ui32CaptureNum);
+extern void am_hal_stimer_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_stimer_int_enable_get(void);
+extern void am_hal_stimer_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_stimer_int_set(uint32_t ui32Interrupt);
+extern void am_hal_stimer_int_clear(uint32_t ui32Interrupt);
+extern uint32_t am_hal_stimer_int_status_get(bool bEnabledOnly);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_STIMER_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.c b/bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.c
new file mode 100644
index 0000000000..50e0b67915
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.c
@@ -0,0 +1,851 @@
+//*****************************************************************************
+//
+// am_hal_sysctrl.c
+//! @file
+//!
+//! @brief Functions for interfacing with the M4F system control registers
+//!
+//! @addtogroup sysctrl2 System Control (SYSCTRL)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 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 is already powered up, we don't need to do the
+ // ZX workaround because in this case the bucks remain in active mode.
+ //
+ ui32SupplySrc = AM_REG(PWRCTRL, DEVICEEN);
+
+ g_buckZX_chk |= ( ui32SupplySrc &
+ (AM_REG_PWRCTRL_DEVICEEN_PDM_M |
+ AM_REG_PWRCTRL_DEVICEEN_UART1_M |
+ AM_REG_PWRCTRL_DEVICEEN_UART0_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_ASM
+
+ //
+ // 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_ASM
+}
+
+//*****************************************************************************
+//
+//! @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();
+ }
+
+ //
+ // Execute the sleep instruction.
+ //
+ AM_ASM_WFI;
+
+ //
+ // 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);
+
+ //
+ // Go to sleep.
+ //
+ AM_ASM_WFI;
+ }
+
+ //
+ // 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 This function should be called before the floating-point module is
+//! used in interrupt-driven code. If it is not called, the core will not have
+//! any way to save context information for floating-point variables on
+//! exception entry.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_sysctrl_fpu_stacking_enable(bool bLazy)
+{
+ if ( bLazy )
+ {
+ //
+ // Enable automatic saving of FPU registers on exception entry, using lazy
+ // context saving.
+ //
+ AM_REG(SYSCTRL, FPCCR) |= (AM_REG_SYSCTRL_FPCCR_ASPEN(0x1) |
+ AM_REG_SYSCTRL_FPCCR_LSPEN(0x1));
+ }
+ else
+ {
+ //
+ // Enable automatic saving of FPU registers on exception entry.
+ //
+ AM_REG(SYSCTRL, FPCCR) |= AM_REG_SYSCTRL_FPCCR_ASPEN(0x1);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Disable FPU register stacking on exception entry.
+//!
+//! This function disables all stacking of floating point registers for
+//! interrupt handlers.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_sysctrl_fpu_stacking_disable(void)
+{
+ //
+ // Enable automatic saving of FPU registers on exception entry, using lazy
+ // context saving.
+ //
+ AM_REG(SYSCTRL, FPCCR) &= ~(AM_REG_SYSCTRL_FPCCR_ASPEN(0x1) |
+ AM_REG_SYSCTRL_FPCCR_LSPEN(0x1));
+}
+
+//*****************************************************************************
+//
+//! @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)
+{
+ volatile uint32_t ui32BuckTimer = g_ui32BuckTimer - 1;
+
+ //
+ // 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_ASM
+
+ //
+ // 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_ASM
+}
+
+//*****************************************************************************
+//
+// 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)
+{
+ volatile uint32_t ui32BuckTimer = g_ui32BuckTimer - 1;
+
+ //
+ // 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_ASM
+
+ //
+ // 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_ASM
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.h b/bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.h
new file mode 100644
index 0000000000..34c72b4173
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_sysctrl.h
@@ -0,0 +1,119 @@
+//*****************************************************************************
+//
+//! am_hal_sysctrl.h
+//! @file
+//!
+//! @brief Functions for interfacing with the M4F system control registers
+//!
+//! @addtogroup sysctrl2 System Control (SYSCTRL)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_SYSCTRL_H
+#define AM_HAL_SYSCTRL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Definitions for sleep mode parameter
+//
+//*****************************************************************************
+#define AM_HAL_SYSCTRL_SLEEP_DEEP true
+#define AM_HAL_SYSCTRL_SLEEP_NORMAL false
+
+//*****************************************************************************
+//
+// Parameters for am_hal_sysctrl_buck_ctimer_isr_init()
+//
+//*****************************************************************************
+//
+// Define the maximum valid timer number
+//
+#define BUCK_TIMER_MAX (AM_HAL_CTIMER_TIMERS_NUM - 1)
+
+//
+// Define the valid timer numbers
+//
+#define AM_HAL_SYSCTRL_BUCK_CTIMER_TIMER0 0
+#define AM_HAL_SYSCTRL_BUCK_CTIMER_TIMER1 1
+#define AM_HAL_SYSCTRL_BUCK_CTIMER_TIMER2 2
+#define AM_HAL_SYSCTRL_BUCK_CTIMER_TIMER3 3
+
+//
+// The following is an invalid timer number. If used, it is the caller telling
+// the HAL to use the "Hard Option", which applies a constant value to the zero
+// cross. The applied value is more noise immune, if less energy efficent.
+//
+#define AM_HAL_SYSCTRL_BUCK_CTIMER_ZX_CONSTANT 0x01000000 // No timer, apply a constant value
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_sysctrl_sleep(bool bSleepDeep);
+extern void am_hal_sysctrl_fpu_enable(void);
+extern void am_hal_sysctrl_fpu_disable(void);
+extern void am_hal_sysctrl_fpu_stacking_enable(bool bLazy);
+extern void am_hal_sysctrl_fpu_stacking_disable(void);
+extern void am_hal_sysctrl_aircr_reset(void);
+
+//
+// Apollo2 zero-cross buck/ctimer related functions
+//
+extern uint32_t am_hal_sysctrl_buck_ctimer_isr_init(uint32_t ui32BuckTimerNumber);
+extern bool am_hal_sysctrl_buck_update_complete(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_SYSCTRL_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_systick.c b/bsp/apollo2/libraries/drivers/hal/am_hal_systick.c
new file mode 100644
index 0000000000..3654910495
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_systick.c
@@ -0,0 +1,453 @@
+//*****************************************************************************
+//
+// am_hal_systick.c
+//! @file
+//!
+//! @brief Functions for interfacing with the SYSTICK
+//!
+//! @addtogroup systick2 System Timer (SYSTICK)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+
+//*****************************************************************************
+//
+// Macro definitions
+//
+//*****************************************************************************
+#define SYSTICK_MAX_TICKS ((1 << 24)-1)
+#define MAX_U32 (0xffffffff)
+
+//*****************************************************************************
+//
+//! @brief Start the SYSTICK.
+//!
+//! This function starts the systick timer.
+//!
+//! @note This timer does not run in deep-sleep mode as it runs from the core
+//! clock, which is gated in deep-sleep. If a timer is needed in deep-sleep use
+//! one of the ctimers instead. Also to note is this timer will consume higher
+//! power than the ctimers.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_systick_start(void)
+{
+ //
+ // Start the systick timer.
+ //
+ AM_REG(SYSTICK, SYSTCSR) |= AM_REG_SYSTICK_SYSTCSR_ENABLE_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Stop the SYSTICK.
+//!
+//! This function stops the systick timer.
+//!
+//! @note This timer does not run in deep-sleep mode as it runs from the core
+//! clock, which is gated in deep-sleep. If a timer is needed in deep-sleep use
+//! one of the ctimers instead. Also to note is this timer will consume higher
+//! power than the ctimers.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_systick_stop(void)
+{
+ //
+ // Stop the systick timer.
+ //
+ AM_REG(SYSTICK, SYSTCSR) &= ~AM_REG_SYSTICK_SYSTCSR_ENABLE_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the interrupt in the SYSTICK.
+//!
+//! This function enables the interupt in the systick timer.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_systick_int_enable(void)
+{
+ //
+ // Enable the systick timer interrupt.
+ //
+ AM_REG(SYSTICK, SYSTCSR) |= AM_REG_SYSTICK_SYSTCSR_TICKINT_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the interrupt in the SYSTICK.
+//!
+//! This function disables the interupt in the systick timer.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_systick_int_disable(void)
+{
+ //
+ // Disable the systick timer interrupt.
+ //
+ AM_REG(SYSTICK, SYSTCSR) &= ~AM_REG_SYSTICK_SYSTCSR_TICKINT_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Reads the interrupt status.
+//!
+//! This function reads the interrupt status in the systick timer.
+//!
+//! @return the interrupt status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_systick_int_status_get(void)
+{
+ //
+ // Return the systick timer interrupt status.
+ //
+ return AM_REG(SYSTICK, SYSTCSR) & AM_REG_SYSTICK_SYSTCSR_COUNTFLAG_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Reset the interrupt in the SYSTICK.
+//!
+//! This function resets the systick timer by clearing out the configuration
+//! register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_systick_reset(void)
+{
+ //
+ // Reset the systick timer interrupt.
+ //
+ AM_REG(SYSTICK, SYSTCSR) = 0x0;
+}
+
+//*****************************************************************************
+//
+//! @brief Load the value into the SYSTICK.
+//!
+//! @param ui32LoadVal the desired load value for the systick. Maximum value is
+//! 0x00FF.FFFF.
+//!
+//! This function loads the desired value into the systick timer.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_systick_load(uint32_t ui32LoadVal)
+{
+ //
+ // Write the reload register.
+ //
+ AM_REG(SYSTICK, SYSTRVR) = ui32LoadVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Get the current count value in the SYSTICK.
+//!
+//! This function gets the current count value in the systick timer.
+//!
+//! @return Current count value.
+//
+//*****************************************************************************
+uint32_t
+am_hal_systick_count(void)
+{
+ //
+ // Return the current systick timer count value.
+ //
+ return AM_REG(SYSTICK, SYSTCVR);
+}
+
+//*****************************************************************************
+//
+//! @brief Wait the specified number of ticks.
+//!
+//! This function delays for the given number of SysTick ticks.
+//!
+//! @note If the SysTick timer is being used elsewhere, it will be corrupted
+//! by calling this function.
+//!
+//! @return 0 if successful.
+//
+//*****************************************************************************
+uint32_t
+am_hal_systick_wait_ticks(uint32_t u32Ticks)
+{
+
+ if ( u32Ticks == 0 )
+ {
+ u32Ticks++; // Make sure we get the COUNTFLAG
+ }
+
+ //
+ // The proper SysTick initialization sequence is: (p 4-36 of the M4 UG).
+ // 1. Program reload value
+ // 2. Clear current value
+ // 3. Program CSR
+ //
+ // Set the reload value to the required number of ticks.
+ //
+ AM_REG(SYSTICK, SYSTRVR) = u32Ticks;
+
+ //
+ // Clear the current count.
+ //
+ AM_REG(SYSTICK, SYSTCVR) = 0x0;
+
+ //
+ // Set to use the processor clock, but don't cause an exception (we'll poll).
+ //
+ AM_REG(SYSTICK, SYSTCSR) = AM_REG_SYSTICK_SYSTCSR_ENABLE_M;
+
+ //
+ // Poll till done
+ //
+ while ( !(AM_REG(SYSTICK, SYSTCSR) & AM_REG_SYSTICK_SYSTCSR_COUNTFLAG_M) );
+
+ //
+ // And disable systick before exiting.
+ //
+ AM_REG(SYSTICK, SYSTCSR) = 0;
+
+ return 0;
+}
+
+//*****************************************************************************
+//
+//! @brief Delay the specified number of microseconds.
+//!
+//! This function will use the SysTick timer to delay until the specified
+//! number of microseconds have elapsed. It uses the processor clocks and
+//! takes into account the current CORESEL setting.
+//!
+//! @note If the SysTick timer is being used elsewhere, it will be corrupted
+//! by calling this function.
+//!
+//! @return Total number of SysTick ticks delayed.
+//
+//*****************************************************************************
+uint32_t
+am_hal_systick_delay_us(uint32_t u32NumUs)
+{
+ uint32_t u32ClkFreq, u32nLoops, u32Ticks, uRet;
+ uint32_t u32CoreSel = AM_BFR(CLKGEN, CCTRL, CORESEL);
+
+ u32nLoops = 1;
+ switch (u32CoreSel)
+ {
+ //
+ // We need to compute the required number of ticks. To do so and to
+ // minimize divide operations, we'll use the following equation:
+ // u32Ticks = (u32NumUs * HFCR_EXACT)/1000000
+ // = (u32NumUs * (HFCR_EXACT * 1024)/1000000) / 1024
+ // The values for the variable u32ClkFreq are computed as follows:
+ // u32ClkFreq = (24390200 * 1024) / ((clksel+1)*1000000);
+ // (and we'll do the remaining divide by 1024, using a shift, later).
+ //
+ case 0:
+ u32ClkFreq = 24975;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 24975)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 24975)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 24975) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ case 1:
+ u32ClkFreq = 12487;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 12487)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 12487)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 12487) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ case 2:
+ u32ClkFreq = 8325;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 8325)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 8325)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 8325) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ case 3:
+ u32ClkFreq = 6243;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 6243)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 6243)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 6243) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ case 4:
+ u32ClkFreq = 4995;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 4995)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 4995)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 4995) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ case 5:
+ u32ClkFreq = 4162;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 4162)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 4162)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 4162) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ case 6:
+ u32ClkFreq = 3567;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 3567)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 3567)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 3567) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ case 7:
+ u32ClkFreq = 3121;
+ if ( u32NumUs > ((SYSTICK_MAX_TICKS / 3121)*1024) )
+ {
+ u32nLoops = (u32NumUs / ((SYSTICK_MAX_TICKS / 3121)*1024)) + 1;
+ u32NumUs /= u32nLoops;
+ }
+ if ( u32NumUs > (MAX_U32 / 3121) )
+ {
+ u32Ticks = (u32NumUs >> 10) * u32ClkFreq;
+ }
+ else
+ {
+ u32Ticks = (u32NumUs * u32ClkFreq) >> 10;
+ }
+ break;
+ default:
+ u32Ticks = 1;
+ break;
+ } // switch()
+
+ uRet = u32Ticks * u32nLoops;
+ while ( u32nLoops-- )
+ {
+ am_hal_systick_wait_ticks(u32Ticks);
+ }
+
+ return uRet;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_systick.h b/bsp/apollo2/libraries/drivers/hal/am_hal_systick.h
new file mode 100644
index 0000000000..bd5e576938
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_systick.h
@@ -0,0 +1,83 @@
+//*****************************************************************************
+//
+// am_hal_systick.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the SYSTICK.
+//!
+//! @addtogroup systick2 System Timer (SYSTICK)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_SYSTICK_H
+#define AM_HAL_SYSTICK_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_systick_start(void);
+extern void am_hal_systick_stop(void);
+extern void am_hal_systick_int_enable(void);
+extern void am_hal_systick_int_disable(void);
+extern uint32_t am_hal_systick_int_status_get(void);
+extern void am_hal_systick_reset(void);
+extern void am_hal_systick_load(uint32_t ui32LoadVal);
+extern uint32_t am_hal_systick_count(void);
+extern uint32_t am_hal_systick_wait_ticks(uint32_t u32Ticks);
+extern uint32_t am_hal_systick_delay_us(uint32_t u32NumUs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_SYSTICK_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.c b/bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.c
new file mode 100644
index 0000000000..722f22fa13
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.c
@@ -0,0 +1,381 @@
+//*****************************************************************************
+//
+// am_hal_tpiu.c
+//! @file
+//!
+//! @brief Support functions for the ARM TPIU module
+//!
+//! Provides support functions for configuring the ARM TPIU module
+//!
+//! @addtogroup tpiu2 Trace Port Interface Unit (TPIU)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Enable the clock to the TPIU module.
+//!
+//! This function enables the clock to the TPIU module.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_tpiu_clock_enable(void)
+{
+ //
+ // Enable the TPIU clock
+ //
+ AM_REG(MCUCTRL, TPIUCTRL) |= AM_REG_MCUCTRL_TPIUCTRL_ENABLE_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the clock to the TPIU module.
+//!
+//! This function disables the clock to the TPIU module.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_tpiu_clock_disable(void)
+{
+ //
+ // Disable the TPIU clock
+ //
+ AM_REG(MCUCTRL, TPIUCTRL) &= ~AM_REG_MCUCTRL_TPIUCTRL_ENABLE_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Set the output port width of the TPIU
+//!
+//! @param ui32PortWidth - The desired port width (in bits)
+//!
+//! This function uses the TPIU_CSPSR register to set the desired output port
+//! width of the TPIU.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_tpiu_port_width_set(uint32_t ui32PortWidth)
+{
+ AM_REG(TPIU, CSPSR) = 1 << (ui32PortWidth - 1);
+}
+
+//*****************************************************************************
+//
+//! @brief Read the supported_output port width of the TPIU
+//!
+//! This function uses the \e TPIU_SSPSR register to set the supported output
+//! port widths of the TPIU.
+//!
+//! @return Current width of the TPIU output port
+//
+//*****************************************************************************
+uint32_t
+am_hal_tpiu_supported_port_width_get(void)
+{
+ uint32_t i, ui32WidthValue;
+
+ //
+ // Read the supported width register.
+ //
+ ui32WidthValue = AM_REG(TPIU, SSPSR);
+
+ //
+ // The register value is encoded in a one-hot format, so the position of
+ // the single set bit determines the actual width of the port.
+ //
+ for (i = 1; i < 32; i++)
+ {
+ //
+ // Check each bit for a '1'. When we find it, our current loop index
+ // will be equal to the port width.
+ //
+ if (ui32WidthValue == (0x1 << (i - 1)))
+ {
+ return i;
+ }
+ }
+
+ //
+ // We should never get here, but if we do, just return the smallest
+ // possible value for a supported trace port width.
+ //
+ return 1;
+}
+
+//*****************************************************************************
+//
+//! @brief Read the output port width of the TPIU
+//!
+//! This function uses the \e TPIU_CSPSR register to set the desired output
+//! port width of the TPIU.
+//!
+//! @return Current width of the TPIU output port
+//
+//*****************************************************************************
+uint32_t
+am_hal_tpiu_port_width_get(void)
+{
+ uint32_t ui32Temp;
+ uint32_t ui32Width;
+
+ ui32Width = 1;
+ ui32Temp = AM_REG(TPIU, CSPSR);
+
+ while ( !(ui32Temp & 1) )
+ {
+ ui32Temp = ui32Temp >> 1;
+ ui32Width++;
+
+ if (ui32Width > 32)
+ {
+ ui32Width = 0;
+ break;
+ }
+ }
+
+ //
+ // Current width of the TPIU output port.
+ //
+ return ui32Width;
+}
+
+//*****************************************************************************
+//
+//! @brief Configure the TPIU based on the values in the configuration struct.
+//!
+//! @param psConfig - pointer to an am_hal_tpiu_config_t structure containing
+//! the desired configuration information.
+//!
+//! This function reads the provided configuration structure, and sets the
+//! relevant TPIU registers to achieve the desired configuration.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_tpiu_configure(am_hal_tpiu_config_t *psConfig)
+{
+ //
+ // Set the clock freq in the MCUCTRL register.
+ //
+ AM_REG(MCUCTRL, TPIUCTRL) |= psConfig->ui32TraceClkIn;
+
+ //
+ // Set the desired protocol.
+ //
+ AM_REG(TPIU, SPPR) = psConfig->ui32PinProtocol;
+
+ //
+ // Set the parallel port width. This may be redundant if the user has
+ // selected a serial protocol, but we'll set it anyway.
+ //
+ AM_REG(TPIU, CSPSR) = (1 << (psConfig->ui32ParallelPortSize - 1));
+
+ //
+ // Set the clock prescaler.
+ //
+ AM_REG(TPIU, ACPR) = psConfig->ui32ClockPrescaler;
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the TPIU
+//!
+//! This function enables the ARM TPIU by setting the TPIU registers and then
+//! enabling the TPIU clock source in MCU control register.
+//!
+//! @param psConfig - structure for configuration.
+//! If ui32SetItmBaud, the other structure members are used to set the
+//! TPIU configuration.
+//! But for simplicity, ui32SetItmBaud can be set to one of the
+//! following, in which case all other structure members are ignored.
+//! In this case, the given BAUD rate is based on a div-by-8 HFRC clock.
+//! AM_HAL_TPIU_BAUD_57600
+//! AM_HAL_TPIU_BAUD_115200
+//! AM_HAL_TPIU_BAUD_230400
+//! AM_HAL_TPIU_BAUD_460800
+//! AM_HAL_TPIU_BAUD_500000
+//! AM_HAL_TPIU_BAUD_1M
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_tpiu_enable(am_hal_tpiu_config_t *psConfig)
+{
+ uint32_t ui32HFRC, ui32SWOscaler, ui32ITMbitrate;
+
+ ui32ITMbitrate = psConfig->ui32SetItmBaud;
+
+ //
+ // TPIU formatter & flush control register.
+ //
+ AM_REG(TPIU, FFCR) = 0;
+
+ if ( ui32ITMbitrate )
+ {
+ //
+ // Set the Current Parallel Port Size (note - only 1 bit can be set).
+ //
+ AM_REG(TPIU, CSPSR) = AM_REG_TPIU_CSPSR_CWIDTH_1BIT;
+
+ //
+ // Use some default assumptions to set the ITM frequency.
+ //
+ if ( (ui32ITMbitrate < AM_HAL_TPIU_BAUD_57600 ) ||
+ (ui32ITMbitrate > AM_HAL_TPIU_BAUD_2M ) )
+ {
+ ui32ITMbitrate = AM_HAL_TPIU_BAUD_DEFAULT;
+ }
+
+ //
+ // Get the current HFRC frequency.
+ //
+ ui32HFRC = am_hal_clkgen_sysclk_get();
+
+ //
+ // Compute the SWO scaler value.
+ //
+ if ( ui32HFRC != 0xFFFFFFFF )
+ {
+ ui32SWOscaler = ((ui32HFRC / 8) / ui32ITMbitrate) - 1;
+ }
+ else
+ {
+ ui32SWOscaler = ( (AM_HAL_CLKGEN_FREQ_MAX_HZ / 8) /
+ AM_HAL_TPIU_BAUD_DEFAULT ) - 1;
+ }
+
+ //
+ // Set the scaler value.
+ //
+ AM_REG(TPIU, ACPR) = AM_REG_TPIU_ACPR_SWOSCALER(ui32SWOscaler);
+
+ //
+ // Set for UART mode
+ //
+ AM_REG(TPIU, SPPR) = AM_REG_TPIU_SPPR_TXMODE_UART;
+
+ //
+ // Make sure we are not in test mode (important for proper deep sleep
+ // operation).
+ //
+ AM_REG(TPIU, ITCTRL) = AM_REG_TPIU_ITCTRL_MODE_NORMAL;
+
+ //
+ // Enable the TPIU clock source in MCU control.
+ // Set TPIU clock for HFRC/8 (6 or 3 MHz) operation.
+ //
+ AM_REGn(MCUCTRL, 0, TPIUCTRL) =
+ AM_REG_MCUCTRL_TPIUCTRL_CLKSEL_HFRC_DIV_8 |
+ AM_REG_MCUCTRL_TPIUCTRL_ENABLE_EN;
+ }
+ else
+ {
+ //
+ // Set the configuration according to the structure values.
+ //
+
+ //
+ // Set the Asynchronous Clock Prescaler Register.
+ //
+ AM_REG(TPIU, ACPR) = psConfig->ui32ClockPrescaler;
+
+ //
+ // Set the Selected Pin Protocol Register.
+ // e.g. AM_REG_TPIU_SPPR_TXMODE_UART
+ //
+ AM_REG(TPIU, SPPR) = psConfig->ui32PinProtocol;
+
+ //
+ // Set the Current Parallel Port Size (note - only 1 bit can be set).
+ // This may be redundant if the user has selected a serial protocol,
+ // but we'll set it anyway.
+ //
+ AM_REG(TPIU, CSPSR) = (1 << (psConfig->ui32ParallelPortSize - 1));
+
+ //
+ // Set the clock freq in the MCUCTRL register.
+ //
+ AM_REG(MCUCTRL, TPIUCTRL) |= psConfig->ui32TraceClkIn;
+ }
+
+ //
+ // Wait for 50us for the data to flush out.
+ //
+ am_hal_itm_delay_us(50);
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the TPIU
+//!
+//! This function disables the ARM TPIU by disabling the TPIU clock source
+//! in MCU control register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_tpiu_disable(void)
+{
+ //
+ // Disable the TPIU clock source in MCU control.
+ //
+ AM_REG(MCUCTRL, TPIUCTRL) = AM_REG_MCUCTRL_TPIUCTRL_CLKSEL_0MHz |
+ AM_REG_MCUCTRL_TPIUCTRL_ENABLE_DIS;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.h b/bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.h
new file mode 100644
index 0000000000..9739034a18
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_tpiu.h
@@ -0,0 +1,193 @@
+//*****************************************************************************
+//
+// am_hal_tpiu.h
+//! @file
+//!
+//! @brief Definitions and structures for working with the TPIU.
+//!
+//! @addtogroup tpiu2 Trace Port Interface Unit (TPIU)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_TPIU_H
+#define AM_HAL_TPIU_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// TPIU bit rate defines.
+//
+//*****************************************************************************
+#define AM_HAL_TPIU_BAUD_57600 (115200 / 2)
+#define AM_HAL_TPIU_BAUD_115200 (115200 * 1)
+#define AM_HAL_TPIU_BAUD_230400 (115200 * 2)
+#define AM_HAL_TPIU_BAUD_460800 (115200 * 4)
+#define AM_HAL_TPIU_BAUD_500000 (1000000 / 2)
+#define AM_HAL_TPIU_BAUD_1M (1000000 * 1)
+#define AM_HAL_TPIU_BAUD_2M (1000000 * 2)
+#define AM_HAL_TPIU_BAUD_DEFAULT (AM_HAL_TPIU_BAUD_1M)
+
+//*****************************************************************************
+//
+// TPIU register defines.
+//
+//*****************************************************************************
+#define AM_HAL_TPIU_SSPSR 0xE0040000 //! Supported Parallel Port Sizes
+#define AM_HAL_TPIU_CSPSR 0xE0040004 //! Current Parallel Port Size
+#define AM_HAL_TPIU_ACPR 0xE0040010 //! Asynchronous Clock Prescaler
+#define AM_HAL_TPIU_SPPR 0xE00400F0 //! Selected Pin Protocol
+#define AM_HAL_TPIU_TYPE 0xE0040FC8 //! TPIU Type
+
+//*****************************************************************************
+//
+// TPIU ACPR defines.
+//
+//*****************************************************************************
+#define AM_HAL_TPIU_ACPR_SWOSCALER_M 0x0000FFFF //! SWO baud rate prescalar
+
+//*****************************************************************************
+//
+// TPIU_SPPR TXMODE defines.
+//
+//*****************************************************************************
+#define AM_HAL_TPIU_SPPR_PARALLEL 0x00000000
+#define AM_HAL_TPIU_SPPR_MANCHESTER 0x00000001
+#define AM_HAL_TPIU_SPPR_NRZ 0x00000002
+
+//*****************************************************************************
+//
+// TPIU Type defines
+//
+//*****************************************************************************
+#define AM_HAL_TPIU_TYPE_NRZVALID 0x00000800
+#define AM_HAL_TPIU_TYPE_MANCVALID 0x00000400
+#define AM_HAL_TPIU_TYPE_PTINVALID 0x00000200
+#define AM_HAL_TPIU_TYPE_FIFOSZ_M 0x000001C0
+
+//*****************************************************************************
+//
+// TPIU Clock defines
+//
+//*****************************************************************************
+#define AM_HAL_TPIU_TRACECLKIN_6MHZ AM_REG_MCUCTRL_TPIUCTRL_TPIUCLKSEL(0)
+#define AM_HAL_TPIU_TRACECLKIN_3MHZ AM_REG_MCUCTRL_TPIUCTRL_TPIUCLKSEL(1)
+#define AM_HAL_TPIU_TRACECLKIN_1_5MHZ AM_REG_MCUCTRL_TPIUCTRL_TPIUCLKSEL(2)
+#define AM_HAL_TPIU_TRACECLKIN_750KHZ AM_REG_MCUCTRL_TPIUCTRL_TPIUCLKSEL(3)
+
+//*****************************************************************************
+//
+//! @brief Structure used for configuring the TPIU
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ // If ui32SetItmBaud is non-zero, the ITM frequency is set to the given
+ // frequency, and is based on a divide-by-8 HFRC TPIU clock.
+ // If zero, other structure members are used to set the TPIU configuration.
+ //
+ uint32_t ui32SetItmBaud;
+
+ //
+ //! MCU Control TRACECLKIN clock freq.
+ //!
+ //! Valid values for ui32TraceClkIn are:
+ //!
+ //! AM_HAL_TPIU_TRACECLKIN_6MHZ
+ //! AM_HAL_TPIU_TRACECLKIN_3MHZ
+ //! AM_HAL_TPIU_TRACECLKIN_1_5MHZ
+ //! AM_HAL_TPIU_TRACECLKIN_750KHZ
+ //
+ uint32_t ui32TraceClkIn;
+
+ //
+ //! Protocol to use for the TPIU
+ //!
+ //! Valid values for ui32PinProtocol are:
+ //!
+ //! AM_HAL_TPIU_SPPR_PARALLEL
+ //! AM_HAL_TPIU_SPPR_MANCHESTER
+ //! AM_HAL_TPIU_SPPR_NRZ
+ //
+ uint32_t ui32PinProtocol;
+
+ //
+ //! Desired width of the TPIU parallel port
+ //
+ uint32_t ui32ParallelPortSize;
+
+ //
+ //! Desired Clock prescaler value
+ //
+ uint32_t ui32ClockPrescaler;
+}
+am_hal_tpiu_config_t;
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_tpiu_clock_enable(void);
+extern void am_hal_tpiu_clock_disable(void);
+extern void am_hal_tpiu_port_width_set(uint32_t ui32PortWidth);
+extern uint32_t am_hal_tpiu_supported_port_width_get(void);
+extern uint32_t am_hal_tpiu_port_width_get(void);
+extern void am_hal_tpiu_configure(am_hal_tpiu_config_t *psConfig);
+extern void am_hal_tpiu_enable(am_hal_tpiu_config_t *psConfig);
+extern void am_hal_tpiu_disable(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_TPIU_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_ttp.c b/bsp/apollo2/libraries/drivers/hal/am_hal_ttp.c
new file mode 100644
index 0000000000..77bde67b87
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_ttp.c
@@ -0,0 +1,205 @@
+//*****************************************************************************
+//
+// am_hal_ttp.c
+//! @file
+//!
+//! @brief Functions for handling the "two time program" interface.
+//!
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#include "am_mcu_apollo.h"
+#include "am_hal_ttp.h"
+
+//*****************************************************************************
+//
+// Local constants
+//
+//*****************************************************************************
+#define TTP_ADDR 0x50020000
+
+//*****************************************************************************
+//
+// Local prototypes
+//
+//*****************************************************************************
+#if !defined(__GNUC__)
+void __breakpoint(int val);
+#endif
+
+//*****************************************************************************
+//
+// A function to verify that the TTP was saved and/or restored properly.
+//
+//*****************************************************************************
+int
+verifyTTPSaved(uint32_t *pSaveArray, int iNumWords)
+{
+ int ix, iErrCnt = 0;
+ uint32_t *pDataSpace = (uint32_t*)TTP_ADDR;
+
+ for (ix = 0; ix<iNumWords; ix++)
+ {
+ if ( *pSaveArray != am_hal_flash_load_ui32((uint32_t)pDataSpace) )
+ {
+ iErrCnt++;
+ }
+ pSaveArray++;
+ pDataSpace++;
+ }
+
+ //
+ // Hopefully returning 0.
+ //
+ return iErrCnt;
+}
+
+//*****************************************************************************
+//
+//! @brief TTP unlock.
+//!
+//! @param ui32Keyval - The key value to unlock the interface.
+//! @param pui8_1024Bytes - A pointer to a 1024 bytes array, used for
+//! temporary data storage.
+//! WARNING This area must be 32-bit aligned and at
+//! least 1024 bytes long.
+//!
+//! This function is used to unlock the TTP ability.
+//!
+//! @return None.
+//
+//*****************************************************************************
+int
+am_hal_ttp_unlock(uint32_t ui32Keyval, uint8_t *pui8_1024Bytes)
+{
+ int iErrCnt = 0;
+ int ix, iRet;
+ int iNumWords = 1024 / 4;
+ uint32_t *pSaveArray, *pDataSpace;
+ int (*pTTPClear)(uint32_t, uint32_t) = (int (*)(uint32_t, uint32_t))0x080002EF;
+ int (*pTTPSet)(uint32_t, uint32_t, uint32_t*, uint32_t, uint32_t) =
+ (int (*)(uint32_t, uint32_t, uint32_t*, uint32_t, uint32_t))0x080006FF;
+
+ //
+ // Save off the data.
+ //
+ pSaveArray = (uint32_t*)pui8_1024Bytes;
+ pDataSpace = (uint32_t*)TTP_ADDR;
+ for (ix = 0; ix < iNumWords; ix++)
+ {
+ *pSaveArray = am_hal_flash_load_ui32((uint32_t)pDataSpace);
+ pSaveArray++;
+ pDataSpace++;
+ }
+
+ //
+ // Before proceeding, make sure that we captured the data correctly.
+ //
+ iErrCnt += verifyTTPSaved((uint32_t*)pui8_1024Bytes, iNumWords);
+ if ( iErrCnt )
+ {
+ return 0x10000001;
+ }
+
+ //
+ // Erase the TTP area.
+ //
+ iRet = (*pTTPClear)(0, ui32Keyval);
+ if ( iRet != 0 )
+ {
+ iErrCnt++;
+ return 0x10000002;
+ }
+
+ //
+ // The point of no return! The TTP space is successfully erased.
+ // Let's make sure.
+ //
+ pDataSpace = (uint32_t*)TTP_ADDR;
+ for (ix = 0; ix < iNumWords; ix++)
+ {
+ if ( am_hal_flash_load_ui32((uint32_t)pDataSpace) != 0xffffffff )
+ {
+ iErrCnt++;
+ }
+ pDataSpace++;
+ }
+
+ if ( iErrCnt )
+ {
+ return 0x10000003;
+ }
+
+ //
+ // Restore the TTP block from the saved data.
+ //
+ iRet = (*pTTPSet)(ui32Keyval, 0, (uint32_t*)pui8_1024Bytes, 0, iNumWords);
+ if ( iRet != 0 )
+ {
+ iErrCnt++;
+ return 0x10000004;
+ }
+
+ //
+ // Now, check the restored INFO data.
+ //
+ iRet = verifyTTPSaved((uint32_t*)pui8_1024Bytes, iNumWords);
+ if ( iRet )
+ {
+ iErrCnt++;
+ return 0x10000005;
+ }
+ else
+ {
+ //
+ // All good. The device was successfully recovered.
+ //
+ }
+
+
+ //
+ // Return with error count (hopefully 0).
+ //
+ return iErrCnt;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_ttp.h b/bsp/apollo2/libraries/drivers/hal/am_hal_ttp.h
new file mode 100644
index 0000000000..b254c957a7
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_ttp.h
@@ -0,0 +1,72 @@
+//*****************************************************************************
+//
+// am_hal_ttp.h
+//! @file
+//!
+//! @brief Functions for handling the "two time program" interface.
+//!
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_TTP_H
+#define AM_HAL_TTP_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// Function prototypes
+//
+//*****************************************************************************
+extern int am_hal_ttp_unlock(uint32_t ui32Keyval, uint8_t *pui8_1024Bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_TTP_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_uart.c b/bsp/apollo2/libraries/drivers/hal/am_hal_uart.c
new file mode 100644
index 0000000000..1a7e5aca31
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_uart.c
@@ -0,0 +1,1160 @@
+//*****************************************************************************
+//
+// am_hal_uart.c
+//! @file
+//!
+//! @brief Functions for interfacing with the UART.
+//!
+//! @addtogroup uart2 UART
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Transmit and receive queue pointers for each UART module.
+//
+//*****************************************************************************
+am_hal_queue_t g_psTxQueue[AM_REG_UART_NUM_MODULES];
+am_hal_queue_t g_psRxQueue[AM_REG_UART_NUM_MODULES];
+
+//*****************************************************************************
+//
+// Power tracking structure
+//
+//*****************************************************************************
+am_hal_uart_pwrsave_t am_hal_uart_pwrsave[AM_REG_UART_NUM_MODULES];
+
+//*****************************************************************************
+//
+// Set Baud Rate based on the UART clock frequency.
+//
+//*****************************************************************************
+
+#define BAUDCLK (32)
+
+static void
+config_baudrate(uint32_t ui32Module, uint32_t ui32Baudrate, uint32_t ui32UartClkFreq)
+{
+ uint64_t ui64FractionDivisorLong;
+ uint64_t ui64IntermediateLong;
+ uint32_t ui32IntegerDivisor;
+ uint32_t ui32FractionDivisor;
+ uint32_t ui32BaudClk;
+
+ //
+ // Calculate register values.
+ //
+ ui32BaudClk = BAUDCLK * ui32Baudrate;
+ ui32IntegerDivisor = (uint32_t)(ui32UartClkFreq / ui32BaudClk);
+ ui64IntermediateLong = (ui32UartClkFreq * 64) / ui32BaudClk;
+ ui64FractionDivisorLong = ui64IntermediateLong - (ui32IntegerDivisor * 64);
+ ui32FractionDivisor = (uint32_t)ui64FractionDivisorLong;
+
+ //
+ // Check the result.
+ //
+ am_hal_debug_assert_msg(ui32IntegerDivisor > 0, "Integer divisor MUST be greater than or equal to 1.");
+
+ //
+ // Write the UART regs.
+ //
+ AM_REGn(UART, ui32Module, IBRD) = ui32IntegerDivisor;
+ AM_REGn(UART, ui32Module, IBRD) = ui32IntegerDivisor;
+ AM_REGn(UART, ui32Module, FBRD) = ui32FractionDivisor;
+}
+
+//*****************************************************************************
+//
+//! @brief Set up the UART.
+//!
+//! @param psConfig pointer to a structure that holds the settings for the UART.
+//! @param ui32UartclkFreq is clock frequency that the UART is running at.
+//!
+//! This function should be used to perform the initial set-up of the UART.
+//!
+//! @return none.
+//
+//*****************************************************************************
+void
+am_hal_uart_config(uint32_t ui32Module, am_hal_uart_config_t *psConfig)
+
+{
+ uint32_t ui32ConfigVal = 0;
+
+ //
+ // Configure the Baudrate.
+ //
+ config_baudrate(ui32Module, psConfig->ui32BaudRate, am_hal_clkgen_sysclk_get());
+
+ //
+ // OR in the Data bits.
+ //
+ ui32ConfigVal |= psConfig->ui32DataBits;
+
+ //
+ // OR in the Two Stop bit if used.
+ //
+ ui32ConfigVal |= psConfig->bTwoStopBits ? AM_REG_UART_LCRH_STP2_M : 0;
+
+ //
+ // OR in the Parity.
+ //
+ ui32ConfigVal |= psConfig->ui32Parity;
+
+ //
+ // Write config to Line control register.
+ //
+ AM_REGn(UART, ui32Module, LCRH) |= ui32ConfigVal;
+
+ //
+ // Write the flow control settings to the control register.
+ //
+ AM_REGn(UART, ui32Module, CR) |= psConfig->ui32FlowCtrl;
+
+ //
+ // Set the clock select field for 24MHz from the HFRC
+ //
+ AM_REGn(UART, ui32Module, CR) |= AM_REG_UART_CR_CLKSEL_24MHZ;
+}
+
+//*****************************************************************************
+//
+//! @brief Gets the status.
+//!
+//! This function returns the current status.
+//!
+//! @return current status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_uart_status_get(uint32_t ui32Module)
+{
+ //
+ // Read and return the Status.
+ //
+ return AM_REGn(UART, ui32Module, RSR);
+}
+
+//*****************************************************************************
+//
+//! @brief Gets the interrupt status.
+//!
+//! @param bEnabledOnly - If true returns the enabled interrupt status.
+//!
+//! This function returns the masked or raw interrupt status.
+//!
+//! @return Bitwise representation of the current interrupt status.
+//!
+//! The return value will be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_UART_INT_OVER_RUN
+//! AM_HAL_UART_INT_BREAK_ERR
+//! AM_HAL_UART_INT_PARITY_ERR
+//! AM_HAL_UART_INT_FRAME_ERR
+//! AM_HAL_UART_INT_RX_TMOUT
+//! AM_HAL_UART_INT_TX
+//! AM_REG_UART_IER_TXIM_M
+//! AM_HAL_UART_INT_RX
+//! AM_HAL_UART_INT_DSRM
+//! AM_HAL_UART_INT_DCDM
+//! AM_HAL_UART_INT_CTSM
+//! AM_HAL_UART_INT_RIM
+//
+//*****************************************************************************
+uint32_t
+am_hal_uart_int_status_get(uint32_t ui32Module, bool bEnabledOnly)
+{
+ if (bEnabledOnly)
+ {
+ //
+ // Read and return the Masked Interrupt Status.
+ //
+ return AM_REGn(UART, ui32Module, MIS);
+ }
+ else
+ {
+ //
+ // Read and return the Raw Interrupt Status.
+ //
+ return AM_REGn(UART, ui32Module, IES);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Clears the desired interrupts.
+//!
+//! @param ui32Interrupt - Interrupt bits to clear.
+//!
+//! This function clears the desired interrupts.
+//!
+//! ui32Interrupt should be a logical or of the following:
+//!
+//! AM_HAL_UART_INT_OVER_RUN
+//! AM_HAL_UART_INT_BREAK_ERR
+//! AM_HAL_UART_INT_PARITY_ERR
+//! AM_HAL_UART_INT_FRAME_ERR
+//! AM_HAL_UART_INT_RX_TMOUT
+//! AM_HAL_UART_INT_TX
+//! AM_REG_UART_IER_TXIM_M
+//! AM_HAL_UART_INT_RX
+//! AM_HAL_UART_INT_DSRM
+//! AM_HAL_UART_INT_DCDM
+//! AM_HAL_UART_INT_CTSM
+//! AM_HAL_UART_INT_RIM
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_int_clear(uint32_t ui32Module, uint32_t ui32Interrupt)
+{
+ //
+ // Clear the bits.
+ //
+ AM_REGn(UART, ui32Module, IEC) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Disables the desired interrupts.
+//!
+//! @param ui32Interrupt - Interrupt bits to disable.
+//!
+//! This function disables the desired interrupts.
+//!
+//! ui32Interrupt should be a logical or of the following:
+//!
+//! AM_HAL_UART_INT_OVER_RUN
+//! AM_HAL_UART_INT_BREAK_ERR
+//! AM_HAL_UART_INT_PARITY_ERR
+//! AM_HAL_UART_INT_FRAME_ERR
+//! AM_HAL_UART_INT_RX_TMOUT
+//! AM_HAL_UART_INT_TX
+//! AM_REG_UART_IER_TXIM_M
+//! AM_HAL_UART_INT_RX
+//! AM_HAL_UART_INT_DSRM
+//! AM_HAL_UART_INT_DCDM
+//! AM_HAL_UART_INT_CTSM
+//! AM_HAL_UART_INT_RIM
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_int_disable(uint32_t ui32Module, uint32_t ui32Interrupt)
+{
+ //
+ // Disable the bits.
+ //
+ AM_REGn(UART, ui32Module, IER) &= ~ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Enables the desired interrupts.
+//!
+//! @param ui32Interrupt - Interrupt bits to enable.
+//!
+//! This function enables the desired interrupts.
+//!
+//! ui32Interrupt should be a logical or of the following:
+//!
+//! AM_HAL_UART_INT_OVER_RUN
+//! AM_HAL_UART_INT_BREAK_ERR
+//! AM_HAL_UART_INT_PARITY_ERR
+//! AM_HAL_UART_INT_FRAME_ERR
+//! AM_HAL_UART_INT_RX_TMOUT
+//! AM_HAL_UART_INT_TX
+//! AM_REG_UART_IER_TXIM_M
+//! AM_HAL_UART_INT_RX
+//! AM_HAL_UART_INT_DSRM
+//! AM_HAL_UART_INT_DCDM
+//! AM_HAL_UART_INT_CTSM
+//! AM_HAL_UART_INT_RIM
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_int_enable(uint32_t ui32Module, uint32_t ui32Interrupt)
+{
+ //
+ // Enable the interrupts.
+ //
+ AM_REGn(UART, ui32Module, IER) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Returns the enabled interrupts.
+//!
+//! This function return the enabled interrupts.
+//!
+//! @return the enabled interrupts. This will be a logical or of the following:
+//!
+//! AM_HAL_UART_INT_OVER_RUN
+//! AM_HAL_UART_INT_BREAK_ERR
+//! AM_HAL_UART_INT_PARITY_ERR
+//! AM_HAL_UART_INT_FRAME_ERR
+//! AM_HAL_UART_INT_RX_TMOUT
+//! AM_HAL_UART_INT_TX
+//! AM_REG_UART_IER_TXIM_M
+//! AM_HAL_UART_INT_RX
+//! AM_HAL_UART_INT_DSRM
+//! AM_HAL_UART_INT_DCDM
+//! AM_HAL_UART_INT_CTSM
+//! AM_HAL_UART_INT_RIM
+//!
+//! @return Returns the enabled interrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_uart_int_enable_get(uint32_t ui32Module)
+{
+ //
+ // Return the enabled interrupts.
+ //
+ return AM_REGn(UART, ui32Module, IER);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the UART, RX, and TX.
+//!
+//! This function enables the UART, RX, and TX.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_enable(uint32_t ui32Module)
+{
+ //
+ // Enable the UART, RX, and TX.
+ //
+ AM_REGan_SET(UART, ui32Module, CR, (AM_REG_UART_CR_UARTEN_M |
+ AM_REG_UART_CR_RXE_M |
+ AM_REG_UART_CR_TXE_M) );
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the UART, RX, and TX.
+//!
+//! This function disables the UART, RX, and TX.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_disable(uint32_t ui32Module)
+{
+ //
+ // Disable the UART.
+ //
+ AM_REGan_CLR(UART, ui32Module, CR, (AM_REG_UART_CR_UARTEN_M |
+ AM_REG_UART_CR_RXE_M |
+ AM_REG_UART_CR_TXE_M) );
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the UART in the power control block.
+//!
+//! This function enables the UART device in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_pwrctrl_enable(uint32_t ui32Module)
+{
+ //
+ // Check to make sure we're acting on a real UART module.
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
+ "Trying to disable a UART module that doesn't exist");
+
+ am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_UART0 << ui32Module);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the UART in the power control block.
+//!
+//! This function disables the UART device in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_pwrctrl_disable(uint32_t ui32Module)
+{
+ //
+ // Check to make sure we're acting on a real UART module.
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
+ "Trying to disable a UART module that doesn't exist");
+
+ am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_UART0 << ui32Module);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the UART in the power control block.
+//!
+//! This function enables the UART device in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_power_on_restore(uint32_t ui32Module)
+{
+ //
+ // Check to make sure we're acting on a real UART module.
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
+ "Trying to enable a UART module that doesn't exist");
+
+ //
+ // Make sure this restore is a companion to a previous save call.
+ //
+ if ( am_hal_uart_pwrsave[ui32Module].bValid == 0 )
+ {
+ return;
+ }
+
+ //
+ // Enable power to the selected UART
+ //
+ am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_UART0 << ui32Module);
+
+ //
+ // Restore the clock settings
+ //
+ am_hal_clkgen_uarten_set(ui32Module, am_hal_uart_pwrsave[ui32Module].UARTEN);
+
+ //
+ // Restore the configuration registers from the global variable in SRAM.
+ //
+ AM_REGn(UART, ui32Module, ILPR) = am_hal_uart_pwrsave[ui32Module].ILPR;
+ AM_REGn(UART, ui32Module, IBRD) = am_hal_uart_pwrsave[ui32Module].IBRD;
+ AM_REGn(UART, ui32Module, FBRD) = am_hal_uart_pwrsave[ui32Module].FBRD;
+ AM_REGn(UART, ui32Module, LCRH) = am_hal_uart_pwrsave[ui32Module].LCRH;
+ AM_REGn(UART, ui32Module, CR) = am_hal_uart_pwrsave[ui32Module].CR;
+ AM_REGn(UART, ui32Module, IFLS) = am_hal_uart_pwrsave[ui32Module].IFLS;
+ AM_REGn(UART, ui32Module, IER) = am_hal_uart_pwrsave[ui32Module].IER;
+
+ //
+ // Indicates we have restored the configuration.
+ //
+ am_hal_uart_pwrsave[ui32Module].bValid = 0;
+
+ return;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the UART in the power control block.
+//!
+//! This function disables the UART device in the power control block.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_power_off_save(uint32_t ui32Module)
+{
+ //
+ // Check to make sure we're acting on a real UART module.
+ //
+ am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
+ "Trying to disable a UART module that doesn't exist");
+
+ //
+ // Save all of the configuration register information for the selected
+ // UART.
+ //
+ am_hal_uart_pwrsave[ui32Module].ILPR = AM_REGn(UART, ui32Module, ILPR);
+ am_hal_uart_pwrsave[ui32Module].IBRD = AM_REGn(UART, ui32Module, IBRD);
+ am_hal_uart_pwrsave[ui32Module].FBRD = AM_REGn(UART, ui32Module, FBRD);
+ am_hal_uart_pwrsave[ui32Module].LCRH = AM_REGn(UART, ui32Module, LCRH);
+ am_hal_uart_pwrsave[ui32Module].CR = AM_REGn(UART, ui32Module, CR);
+ am_hal_uart_pwrsave[ui32Module].IFLS = AM_REGn(UART, ui32Module, IFLS);
+ am_hal_uart_pwrsave[ui32Module].IER = AM_REGn(UART, ui32Module, IER);
+
+ //
+ // Save the clock setting and disable power to the selected UART.
+ // Save the current enable value.
+ //
+ am_hal_uart_pwrsave[ui32Module].UARTEN =
+ (AM_REG(CLKGEN, UARTEN) & AM_HAL_CLKGEN_UARTEN_UARTENn_M(ui32Module)) >>
+ AM_HAL_CLKGEN_UARTEN_UARTENn_S(ui32Module);
+
+ //
+ // Disable the UART.
+ //
+ am_hal_clkgen_uarten_set(ui32Module, AM_HAL_CLKGEN_UARTEN_DIS);
+
+ //
+ // Indicates we have a valid saved configuration.
+ //
+ am_hal_uart_pwrsave[ui32Module].bValid = 1;
+
+ //
+ // Disable power to the selected UART.
+ //
+ am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_UART0 << ui32Module);
+
+ return;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the UART clock.
+//!
+//! This function enables the clock to the UART.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_clock_enable(uint32_t ui32Module)
+{
+ //
+ // Set CLKGEN.UARTEN, clear the field then write the desired enable value
+ // Valid enable values are DIS, EN, REDUCE_FREQ, EN_POWER_SAV.
+ //
+ am_hal_clkgen_uarten_set(ui32Module, AM_HAL_CLKGEN_UARTEN_EN);
+
+ //
+ // Enable the UART clock.
+ //
+ AM_REGn(UART, ui32Module, CR) |= AM_REG_UART_CR_CLKEN_M;
+
+ //
+ // Select default UART clock source
+ //
+ AM_REGn(UART, ui32Module, CR) |= AM_REG_UART_CR_CLKSEL_24MHZ;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the UART clock.
+//!
+//! This function disables the clock to the UART.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_clock_disable(uint32_t ui32Module)
+{
+ //
+ // Disable the UART clock.
+ //
+ AM_REGn(UART, ui32Module, CR) &= ~AM_REG_UART_CR_CLKEN_M;
+
+ //
+ // Disable the UART clock in the CLKGEN module.
+ //
+ am_hal_clkgen_uarten_set(ui32Module, AM_HAL_CLKGEN_UARTEN_DIS);
+}
+
+//*****************************************************************************
+//
+//! @brief Set and enable the desired interrupt levels for the RX/TX fifo.
+//!
+//! @param ui32LvlCfg - Desired FIFO RX/TX levels.
+//!
+//! This function sets the desired interrupt levels for the RX/TX fifo and
+//! enables the use of transmit and receive FIFO buffers.
+//!
+//! Valid values for ui32LvlCfg are:
+//!
+//! AM_HAL_UART_TX_FIFO_1_8
+//! AM_HAL_UART_TX_FIFO_1_4
+//! AM_HAL_UART_TX_FIFO_1_2
+//! AM_HAL_UART_TX_FIFO_3_4
+//! AM_HAL_UART_TX_FIFO_7_8
+//!
+//! AM_HAL_UART_RX_FIFO_1_8
+//! AM_HAL_UART_RX_FIFO_1_4
+//! AM_HAL_UART_RX_FIFO_1_2
+//! AM_HAL_UART_RX_FIFO_3_4
+//! AM_HAL_UART_RX_FIFO_7_8
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_fifo_config(uint32_t ui32Module, uint32_t ui32LvlCfg)
+{
+ //
+ // Enable the use of FIFOs.
+ //
+ AM_REGn(UART, ui32Module, LCRH) |= AM_REG_UART_LCRH_FEN_M;
+
+ //
+ // Write the FIFO level register.
+ //
+ AM_REGn(UART, ui32Module, IFLS) = ui32LvlCfg;
+}
+
+//*****************************************************************************
+//
+//! @brief Return the UART Flags.
+//!
+//! This function reads and returns the UART flags.
+//!
+//! @return Returns the Flags.
+//
+//*****************************************************************************
+uint32_t
+am_hal_uart_flags_get(uint32_t ui32Module)
+{
+ //
+ // Read and return the Flags.
+ //
+ return AM_REGn(UART, ui32Module, FR);
+}
+
+//*****************************************************************************
+//
+//! @brief Outputs a single character using polling.
+//!
+//! @param cChar - Character to send.
+//!
+//! This function outputs a single character using polling.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_char_transmit_polled(uint32_t ui32Module, char cChar)
+{
+ //
+ // Wait for space, i.e. TX FIFO EMPTY
+ //
+ while (AM_BFRn(UART, ui32Module, FR, TXFF));
+
+ //
+ // Write the char.
+ //
+ AM_REGn(UART, ui32Module, DR) = cChar;
+}
+
+//*****************************************************************************
+//
+//! @brief Outputs a zero terminated string using polling.
+//!
+//! @param pcString - Pointer to character string to send.
+//!
+//! This function outputs a zero terminated string using polling.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_string_transmit_polled(uint32_t ui32Module, char *pcString)
+{
+ while (*pcString)
+ {
+ //
+ // Wait for space, i.e. TX FIFO EMPTY.
+ //
+ while (AM_BFRn(UART, ui32Module, FR, TXFF));
+
+ //
+ // Write the char.
+ //
+ AM_REGn(UART, ui32Module, DR) = *pcString++;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Receives a character using polling.
+//!
+//! @param pcChar - Pointer to character to store received char.
+//!
+//! This function receives a character using polling.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_char_receive_polled(uint32_t ui32Module, char *pcChar)
+{
+ //
+ // Wait for data, i.e. RX FIFO NOT EMPTY.
+ //
+ while (AM_BFRn(UART, ui32Module, FR, RXFE));
+
+ //
+ // Save the char.
+ //
+ *pcChar = AM_REGn(UART, ui32Module, DR);
+}
+
+//*****************************************************************************
+//
+//! @brief Receives one line using polling.
+//!
+//! @param ui32MaxChars - Maximum number of characters to receive.
+//! @param pcChar - Pointer to character string to store received line.
+//!
+//! This function receives a line (delimited by '/n' or '/r') using polling.
+//! Line buffer is 0 (NULL) terminated.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_line_receive_polled(uint32_t ui32Module,
+ uint32_t ui32MaxChars,
+ char *pcChar)
+{
+ char cRecChar;
+ uint32_t i;
+
+ //
+ // Loop until we receive ui32MaxChars or receive a line ending.
+ //
+ for (i = 0; i < (ui32MaxChars - 1); i++)
+ {
+ //
+ // Get char.
+ //
+ am_hal_uart_char_receive_polled(ui32Module, &cRecChar);
+
+ if ((cRecChar == '\n') || (cRecChar == '\r'))
+ {
+ //
+ // Zero terminate the buffer.
+ //
+ *pcChar = 0;
+
+ return;
+ }
+
+ *pcChar++ = cRecChar;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Initialize the buffered UART.
+//!
+//! @param pui8RxArray - Pointer to the RX buffer to fill.
+//! @param ui32RxSize - size of RX buffer.
+//! @param pui8TxArray - Pointer to the TX buffer to fill.
+//! @param ui32TxSize - size of TX buffer.
+//!
+//! This function initializes the buffered UART.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_init_buffered(uint32_t ui32Module,
+ uint8_t *pui8RxArray, uint32_t ui32RxSize,
+ uint8_t *pui8TxArray, uint32_t ui32TxSize)
+{
+ //
+ // Enable the UART RX timeout interrupt.
+ //
+ AM_REGn(UART, ui32Module, IER) |= (AM_REG_UART_IES_RTRIS_M |
+ AM_REG_UART_IES_TXRIS_M);
+
+ //
+ // Initialize the ring buffers.
+ //
+ am_hal_queue_init(&g_psTxQueue[ui32Module], pui8TxArray, 1, ui32TxSize);
+ am_hal_queue_init(&g_psRxQueue[ui32Module], pui8RxArray, 1, ui32RxSize);
+}
+
+//*****************************************************************************
+//
+//! @brief Get the status of the buffered UART.
+//!
+//! @param pui32RxSize - Pointer to variable to return the Rx ring data size.
+//! @param pui32TxSize - Pointer to variable to return the Tx ring data size.
+//!
+//! This function gets the status of the buffered UART.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_get_status_buffered(uint32_t ui32Module,
+ uint32_t *pui32RxSize,
+ uint32_t *pui32TxSize)
+{
+ //
+ // Return the current size of ring buffers.
+ //
+ if ( pui32RxSize )
+ {
+ *pui32RxSize = am_hal_queue_data_left(&g_psRxQueue[ui32Module]);
+ }
+
+ if ( pui32TxSize )
+ {
+ *pui32TxSize = am_hal_queue_data_left(&g_psTxQueue[ui32Module]);
+ }
+}
+
+
+//*****************************************************************************
+//
+//! @brief Services the buffered UART.
+//!
+//! @param ui32Status is the contents of the UART interrupt status register.
+//!
+//! This function is responsible for servicing the buffered UART. Designed to
+//! be called from the UART interrupt handler.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_uart_service_buffered(uint32_t ui32Module, uint32_t ui32Status)
+{
+ uint8_t ui8Character = '\x00';
+ uint32_t ui32FifoEntry = 0;
+
+ //
+ // Check to see if we have filled the Rx FIFO past the configured limit, or
+ // if we have an 'old' character or two sitting in the FIFO.
+ //
+ if (ui32Status & (AM_REG_UART_IES_RXRIS_M | AM_REG_UART_IES_RTRIS_M))
+ {
+ //
+ // While there's stuff in the RX fifo....
+ //
+ while (!AM_BFRn(UART, ui32Module, FR, RXFE))
+ {
+ //
+ // Read each character out one by one, and add it to the ring
+ // buffer. This will start losing bytes if the fifo ever overflows.
+ //
+ ui32FifoEntry = AM_REGn(UART, ui32Module , DR);
+
+ //
+ // As long as no error bits were set, we should push this byte to
+ // the FIFO.
+ //
+ if ( (ui32FifoEntry & 0xF00) == 0 )
+ {
+ ui8Character = ui32FifoEntry & 0xFF;
+ am_hal_queue_item_add(&g_psRxQueue[ui32Module], &ui8Character, 1);
+ }
+ }
+ }
+
+ //
+ // Check to see if our TX buffer has been recently emptied. If so, we
+ // should refill it from the TX ring buffer.
+ //
+ if (ui32Status & AM_REG_UART_IES_TXRIS_M)
+ {
+ //
+ // Keep refilling until the fifo is full, or the ring buffer is empty,
+ // whichever happens first.
+ //
+ while (am_hal_queue_data_left(&g_psTxQueue[ui32Module]) &&
+ !AM_BFRn(UART, ui32Module, FR, TXFF))
+ {
+ am_hal_queue_item_get(&g_psTxQueue[ui32Module], &ui8Character, 1);
+ AM_REGn(UART, ui32Module , DR) = ui8Character;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Services the buffered UART.
+//!
+//! @param ui32Status is the contents of the UART interrupt status register.
+//!
+//! This function is responsible for servicing the buffered UART. Designed to
+//! be called from the UART interrupt handler.
+//!
+//! This function behaves exactly like am_hal_uart_service_buffered() \e except
+//! it does not completely empty the RX FIFO on every interrupt event. Instead,
+//! it will leave at least one byte behind until it receives a UART RX TIMEOUT
+//! interrupt. If you use this service routine, you can treat the RX TIMEOUT
+//! interrupt as a UART IDLE interrupt. Every time the UART RX line goes IDLE
+//! for 32 consecutive bit-times you WILL receive a UART RX TIMEOUT interrupt.
+//! This behavior is not guaranteed for am_hal_uart_service_buffered().
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_uart_service_buffered_timeout_save(uint32_t ui32Module, uint32_t ui32Status)
+{
+ uint8_t ui8Character = '\x00';
+ uint32_t ui32Count = 0;
+ uint32_t ui32FifoEntry = 0;
+
+ //
+ // Check to see if we have filled the Rx FIFO past the configured limit, or
+ // if we have an 'old' character or two sitting in the FIFO.
+ //
+ if (ui32Status & (AM_REG_UART_IES_RXRIS_M | AM_REG_UART_IES_RTRIS_M))
+ {
+ //
+ // Check to see what our FIFO configuration setting is.
+ //
+ uint32_t ui32FifoThreshold;
+ uint32_t ui32FifoCfg = AM_BFMn(UART, ui32Module, IFLS, RXIFLSEL);
+
+ //
+ // Compute the number of bytes for receive interrupt from the FIFO level
+ // register.
+ //
+ switch(ui32FifoCfg)
+ {
+ case AM_HAL_UART_RX_FIFO_1_8: ui32FifoThreshold = 4; break;
+ case AM_HAL_UART_RX_FIFO_1_4: ui32FifoThreshold = 8; break;
+ case AM_HAL_UART_RX_FIFO_1_2: ui32FifoThreshold = 16; break;
+ case AM_HAL_UART_RX_FIFO_3_4: ui32FifoThreshold = 24; break;
+ case AM_HAL_UART_RX_FIFO_7_8: ui32FifoThreshold = 28; break;
+ default:
+ ui32FifoThreshold = 32;
+ }
+
+ //
+ // While there's stuff in the RX fifo....
+ //
+ while (!AM_BFRn(UART, ui32Module, FR, RXFE))
+ {
+ //
+ // Read each character out one by one, and add it to the ring
+ // buffer. This will start losing bytes if the fifo ever overflows.
+ //
+ ui32FifoEntry = AM_REGn(UART, ui32Module, DR);
+
+ //
+ // As long as no error bits were set, we should push this byte to
+ // the FIFO.
+ //
+ if ( (ui32FifoEntry & 0xF00) == 0)
+ {
+ ui8Character = ui32FifoEntry & 0xFF;
+ am_hal_queue_item_add(&g_psRxQueue[ui32Module], &ui8Character, 1);
+ }
+
+ //
+ // Leave one byte to trigger the RX timeout interrupt.
+ //
+ if ( ++ui32Count >= (ui32FifoThreshold - 1) )
+ {
+ break;
+ }
+ }
+ }
+
+ //
+ // Check to see if our TX buffer has been recently emptied. If so, we
+ // should refill it from the TX ring buffer.
+ //
+ if (ui32Status & AM_REG_UART_IES_TXRIS_M)
+ {
+ //
+ // Keep refilling until the fifo is full, or the ring buffer is empty,
+ // whichever happens first.
+ //
+ while (am_hal_queue_data_left(&g_psTxQueue[ui32Module]) &&
+ !AM_BFRn(UART, ui32Module, FR, TXFF))
+ {
+ am_hal_queue_item_get(&g_psTxQueue[ui32Module], &ui8Character, 1);
+ AM_REGn(UART, ui32Module , DR) = ui8Character;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Puts a char in the buffer or directly to the fifo if available.
+//!
+//! @param cChar - Character to send.
+//!
+//! This function puts a character in the buffer or directly to the fifo.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_char_transmit_buffered(uint32_t ui32Module, char cChar)
+{
+ //
+ // Check the status of the Tx fifo and the Tx ring buffer.
+ //
+ if (am_hal_queue_empty(&g_psTxQueue[ui32Module]) &&
+ !AM_BFRn(UART, ui32Module, FR, TXFF))
+ {
+ //
+ // If the fifo isn't full yet, and the ring buffer isn't being used,
+ // just write the new character directly to the fifo.
+ //
+ AM_REGn(UART, ui32Module, DR) = cChar;
+ }
+ else
+ {
+ //
+ // If we get here, either the fifo is full, or the ring buffer is
+ // already in use. In either case, we need to use the ring buffer
+ // to make sure that the transmitted data gets sent in the right
+ // order. If the buffer is already full, we will simply lose this
+ // byte.
+ //
+ am_hal_queue_item_add(&g_psTxQueue[ui32Module], &cChar, 1);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Puts a null terminaled string in the buffer or directly to the fifo.
+//!
+//! @param pcString - Pointer to buffer used for sending.
+//!
+//! This function puts a string in the buffer or directly to the fifo if there
+//! is space available.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_uart_string_transmit_buffered(uint32_t ui32Module, char *pcString)
+{
+ //
+ // Check the status of the Tx fifo and the Tx ring buffer.
+ //
+ while (*pcString)
+ {
+ if (am_hal_queue_empty(&g_psTxQueue[ui32Module]) &&
+ !AM_BFRn(UART, ui32Module, FR, TXFF))
+ {
+ //
+ // If the fifo isn't full yet, and the ring buffer isn't being used,
+ // just write the new character directly to the fifo.
+ //
+ AM_REGn(UART, ui32Module, DR) = *pcString;
+ }
+ else
+ {
+ //
+ // If we get here, either the fifo is full, or the ring buffer is
+ // already in use. In either case, we need to use the ring buffer
+ // to make sure that the transmitted data gets sent in the right
+ // order. If the buffer is already full, we will simply lose this
+ // byte.
+ //
+ am_hal_queue_item_add(&g_psTxQueue[ui32Module], pcString, 1);
+ }
+
+ //
+ // Move the pointer to the next character.
+ //
+ pcString++;
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Returns n number of characters from the ring buffer or until empty.
+//!
+//! @param pcString - Pointer to buffer for putting received characters.
+//! @param ui32MaxChars - Maximum number of characters to receive.
+//!
+//! This function puts a char string in the buffer.
+//!
+//! @return Returns the number of chars received.
+//
+//*****************************************************************************
+uint32_t
+am_hal_uart_char_receive_buffered(uint32_t ui32Module,
+ char *pcString,
+ uint32_t ui32MaxChars)
+{
+ uint32_t ui32NumChars = 0;
+
+ //
+ // Loop until ui32MaxChars or until empty.
+ //
+ while (am_hal_queue_data_left(&g_psRxQueue[ui32Module]) && ui32MaxChars)
+ {
+ //
+ // Pull a char out of the ring buffer.
+ //
+ am_hal_queue_item_get(&g_psRxQueue[ui32Module], pcString, 1);
+
+ //
+ // Subtract from ui32MaxChars.
+ // Add to ui32NumChars.
+ // Move pointer in buffer.
+ //
+ ui32MaxChars--;
+ ui32NumChars++;
+ pcString++;
+ }
+
+ //
+ // return the number of chars received.
+ //
+ return ui32NumChars;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_uart.h b/bsp/apollo2/libraries/drivers/hal/am_hal_uart.h
new file mode 100644
index 0000000000..4aab828582
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_uart.h
@@ -0,0 +1,345 @@
+//*****************************************************************************
+//
+// am_hal_uart.h
+//! @file
+//!
+//! @brief Functions for accessing and configuring the UART.
+//!
+//! @addtogroup uart2 UART
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_UART_H
+#define AM_HAL_UART_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! @name UART Interrupts
+//! @brief Macro definitions for UART FIFO levels.
+//!
+//! They may be used with the \e am_hal_uart_fifo_config() function.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_UART_INT_OVER_RUN AM_REG_UART_IER_OEIM_M
+#define AM_HAL_UART_INT_BREAK_ERR AM_REG_UART_IER_BEIM_M
+#define AM_HAL_UART_INT_PARITY_ERR AM_REG_UART_IER_PEIM_M
+#define AM_HAL_UART_INT_FRAME_ERR AM_REG_UART_IER_FEIM_M
+#define AM_HAL_UART_INT_RX_TMOUT AM_REG_UART_IER_RTIM_M
+#define AM_HAL_UART_INT_TX AM_REG_UART_IER_TXIM_M
+#define AM_HAL_UART_INT_RX AM_REG_UART_IER_RXIM_M
+#define AM_HAL_UART_INT_DSRM AM_REG_UART_IER_DSRMIM_M
+#define AM_HAL_UART_INT_DCDM AM_REG_UART_IER_DCDMIM_M
+#define AM_HAL_UART_INT_CTSM AM_REG_UART_IER_CTSMIM_M
+#define AM_HAL_UART_INT_TXCMP AM_REG_UART_IER_TXCMPMIM_M
+//! @}
+
+//*****************************************************************************
+//
+//! @name UART FIFO Levels
+//! @brief Macro definitions for RTV interrupt status bits.
+//!
+//! These macros correspond to the bits in the UART interrupt status register.
+//! They may be used with any of the \e am_hal_uart_int_x() functions.
+//!
+//! @{
+//
+//*****************************************************************************
+//TX
+#define AM_HAL_UART_TX_FIFO_1_8 AM_REG_UART_IFLS_TXIFLSEL(0)
+#define AM_HAL_UART_TX_FIFO_1_4 AM_REG_UART_IFLS_TXIFLSEL(1)
+#define AM_HAL_UART_TX_FIFO_1_2 AM_REG_UART_IFLS_TXIFLSEL(2)
+#define AM_HAL_UART_TX_FIFO_3_4 AM_REG_UART_IFLS_TXIFLSEL(3)
+#define AM_HAL_UART_TX_FIFO_7_8 AM_REG_UART_IFLS_TXIFLSEL(4)
+// RX
+#define AM_HAL_UART_RX_FIFO_1_8 AM_REG_UART_IFLS_RXIFLSEL(0)
+#define AM_HAL_UART_RX_FIFO_1_4 AM_REG_UART_IFLS_RXIFLSEL(1)
+#define AM_HAL_UART_RX_FIFO_1_2 AM_REG_UART_IFLS_RXIFLSEL(2)
+#define AM_HAL_UART_RX_FIFO_3_4 AM_REG_UART_IFLS_RXIFLSEL(3)
+#define AM_HAL_UART_RX_FIFO_7_8 AM_REG_UART_IFLS_RXIFLSEL(4)
+//! @}
+
+//*****************************************************************************
+//
+//! @name UART Status Register
+//! @brief Macro definitions for UART Status Register Bits.
+//!
+//! They may be used with the \e am_hal_uart_status_get() function.
+//!
+//! @{
+//
+//*****************************************************************************
+// This is the overrun error indicator.
+#define AM_HAL_UART_RSR_OVERRUN_NOERR AM_REG_UART_RSR_OESTAT_NOERR
+#define AM_HAL_UART_RSR_OVERRUN_ERROR AM_REG_UART_RSR_OESTAT_ERR
+
+// This is the break error indicator.
+#define AM_HAL_UART_RSR_BREAK_NOERR AM_REG_UART_RSR_BESTAT_NOERR
+#define AM_HAL_UART_RSR_BREAK_ERROR AM_REG_UART_RSR_BESTAT_ERR
+
+// This is the parity error indicator.
+#define AM_HAL_UART_RSR_PARITY_NOERR AM_REG_UART_RSR_PESTAT_NOERR
+#define AM_HAL_UART_RSR_PARITY_ERROR AM_REG_UART_RSR_PESTAT_ERR
+
+// This is the framing error indicator.
+#define AM_HAL_UART_RSR_FRAME_ERROR_NOERR AM_REG_UART_RSR_FESTAT_NOERR
+#define AM_HAL_UART_RSR_FRAME_ERROR_ERROR AM_REG_UART_RSR_FESTAT_ERR
+//! @}
+
+//*****************************************************************************
+//
+//! @name UART Flag Register
+//! @brief Macro definitions for UART Flag Register Bits.
+//!
+//! They may be used with the \e am_hal_uart_flags_get() function.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_UART_FR_RING AM_REG_UART_FR_RI_M
+#define AM_HAL_UART_FR_TX_EMPTY AM_REG_UART_FR_TXFE_XMTFIFO_EMPTY
+#define AM_HAL_UART_FR_RX_FULL AM_REG_UART_FR_RXFF_RCVFIFO_FULL
+#define AM_HAL_UART_FR_TX_FULL AM_REG_UART_FR_TXFF_XMTFIFO_FULL
+#define AM_HAL_UART_FR_RX_EMPTY AM_REG_UART_FR_RXFE_RCVFIFO_EMPTY
+#define AM_HAL_UART_FR_BUSY AM_REG_UART_FR_BUSY_BUSY
+#define AM_HAL_UART_FR_DCD_DETECTED AM_REG_UART_FR_DCD_DETECTED
+#define AM_HAL_UART_FR_DSR_READY AM_REG_UART_FR_DSR_READY
+#define AM_HAL_UART_FR_CTS AM_REG_UART_FR_CTS_M
+//! @}
+
+
+//*****************************************************************************
+//
+//! @name UART Config Macros
+//! @brief Macro definitions for available Data bits.
+//!
+//! They may be used with the \e am_hal_uart_config_t structure used by \e
+//! am_hal_uart_config().
+//!
+//! @{
+//
+//*****************************************************************************
+//*****************************************************************************
+//
+// Data bits defines.
+//
+//*****************************************************************************
+#define AM_HAL_UART_DATA_BITS_8 AM_REG_UART_LCRH_WLEN(3)
+#define AM_HAL_UART_DATA_BITS_7 AM_REG_UART_LCRH_WLEN(2)
+#define AM_HAL_UART_DATA_BITS_6 AM_REG_UART_LCRH_WLEN(1)
+#define AM_HAL_UART_DATA_BITS_5 0
+
+//*****************************************************************************
+//
+// Parity defines.
+//
+//*****************************************************************************
+#define AM_HAL_UART_PARITY_NONE 0
+#define AM_HAL_UART_PARITY_ODD AM_REG_UART_LCRH_PEN_M
+#define AM_HAL_UART_PARITY_EVEN AM_REG_UART_LCRH_PEN_M | \
+ AM_REG_UART_LCRH_EPS_M
+
+//*****************************************************************************
+//
+// Flow control defines.
+//
+//*****************************************************************************
+#define AM_HAL_UART_FLOW_CTRL_NONE 0
+#define AM_HAL_UART_FLOW_CTRL_RTS_CTS AM_REG_UART_CR_CTSEN_M | \
+ AM_REG_UART_CR_RTSEN_M
+//! @}
+
+//*****************************************************************************
+//
+//! UART configuration structure
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! Desired Baudrate for the UART.
+ //
+ uint32_t ui32BaudRate;
+
+ //
+ //! Number of data bits.
+ //!
+ //! Valid values for ui32DataBits are:
+ //!
+ //! AM_HAL_UART_DATA_BITS_8
+ //! AM_HAL_UART_DATA_BITS_7
+ //! AM_HAL_UART_DATA_BITS_6
+ //! AM_HAL_UART_DATA_BITS_5
+ //
+ uint32_t ui32DataBits;
+
+ //
+ //! Use two stop bits.
+ //
+ bool bTwoStopBits;
+
+ //
+ //! Parity.
+ //!
+ //! Valid values for ui32Parity are:
+ //!
+ //! AM_HAL_UART_PARITY_NONE
+ //! AM_HAL_UART_PARITY_ODD
+ //! AM_HAL_UART_PARITY_EVEN
+ //
+ uint32_t ui32Parity;
+
+ //
+ //! Flow control.
+ //!
+ //! Valid values for ui32FlowCtrl are:
+ //!
+ //! AM_HAL_UART_FLOW_CTRL_NONE
+ //! AM_HAL_UART_FLOW_CTRL_RTS_CTS
+ //
+ uint32_t ui32FlowCtrl;
+}
+am_hal_uart_config_t;
+
+//*****************************************************************************
+//
+// Structure for containing information about the UART's configuration while
+// it is powered down.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint32_t ILPR;
+ uint32_t IBRD;
+ uint32_t FBRD;
+ uint32_t LCRH;
+ uint32_t CR;
+ uint32_t IFLS;
+ uint32_t IER;
+ uint32_t UARTEN;
+ uint32_t bValid;
+}
+am_hal_uart_pwrsave_t;
+
+//*****************************************************************************
+//
+// Global Variables
+//
+//*****************************************************************************
+extern am_hal_uart_pwrsave_t am_hal_uart_pwrsave[AM_REG_UART_NUM_MODULES];
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_uart_pwrctrl_enable(uint32_t ui32Module);
+extern void am_hal_uart_pwrctrl_disable(uint32_t ui32Module);
+extern void am_hal_uart_power_on_restore(uint32_t ui32Module);
+extern void am_hal_uart_power_off_save(uint32_t ui32Module);
+extern void am_hal_uart_config(uint32_t ui32Module,
+ am_hal_uart_config_t *psConfig);
+extern uint32_t am_hal_uart_status_get(uint32_t ui32Module);
+extern uint32_t am_hal_uart_int_status_get(uint32_t ui32Module,
+ bool bEnabledOnly);
+extern void am_hal_uart_int_clear(uint32_t ui32Module,
+ uint32_t ui32Interrupt);
+extern void am_hal_uart_int_disable(uint32_t ui32Module,
+ uint32_t ui32Interrupt);
+extern void am_hal_uart_int_enable(uint32_t ui32Module,
+ uint32_t ui32Interrupt);
+extern uint32_t am_hal_uart_int_enable_get(uint32_t ui32Module);
+extern void am_hal_uart_enable(uint32_t ui32Module);
+extern void am_hal_uart_disable(uint32_t ui32Module);
+extern void am_hal_uart_clock_enable(uint32_t ui32Module);
+extern void am_hal_uart_clock_disable(uint32_t ui32Module);
+extern void am_hal_uart_fifo_config(uint32_t ui32Module, uint32_t ui32LvlCfg);
+extern uint32_t am_hal_uart_flags_get(uint32_t ui32Module);
+
+// rx/tx polled
+extern void am_hal_uart_char_transmit_polled(uint32_t ui32Module,
+ char cChar);
+extern void am_hal_uart_string_transmit_polled(uint32_t ui32Module,
+ char *pcString);
+extern void am_hal_uart_char_receive_polled(uint32_t ui32Module,
+ char *pcChar);
+extern void am_hal_uart_line_receive_polled(uint32_t ui32Module,
+ uint32_t ui32MaxChars,
+ char *pcChar);
+
+// rx/tx buffered
+extern void am_hal_uart_init_buffered(uint32_t ui32Module,
+ uint8_t *pui8RxArray,
+ uint32_t ui32RxSize,
+ uint8_t *pui8TxArray,
+ uint32_t ui32TxSize);
+extern void am_hal_uart_get_status_buffered(uint32_t ui32Module,
+ uint32_t *pui32RxSize,
+ uint32_t *pui32TxSize);
+extern void am_hal_uart_service_buffered(uint32_t ui32Module,
+ uint32_t ui32Status);
+
+extern void am_hal_uart_service_buffered_timeout_save(uint32_t ui32Module,
+ uint32_t ui32Status);
+extern void am_hal_uart_char_transmit_buffered(uint32_t ui32Module,
+ char cChar);
+extern void am_hal_uart_string_transmit_buffered(uint32_t ui32Module,
+ char *pcString);
+extern uint32_t am_hal_uart_char_receive_buffered(uint32_t ui32Module,
+ char *pcString,
+ uint32_t ui32MaxChars);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_UART_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.c b/bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.c
new file mode 100644
index 0000000000..31e28855e4
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.c
@@ -0,0 +1,287 @@
+//*****************************************************************************
+//
+// am_hal_vcomp.c
+//! @file
+//!
+//! @brief Functions for operating the on-chip Voltage Comparator
+//!
+//! @addtogroup vcomp2 Voltage Comparator (VCOMP)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Configure the Voltage Comparator module.
+//!
+//! @param psConfig is a structure containing configuration information for the
+//! voltage comparator.
+//!
+//! This function configures the positive and negative input signals for the
+//! voltage comparator.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_config(const am_hal_vcomp_config_t *psConfig)
+{
+ //
+ // The configuration word should be a simple OR of the components of the
+ // configuration structure.
+ //
+ AM_REG(VCOMP, CFG) = (psConfig->ui32LevelSelect |
+ psConfig->ui32PosInput |
+ psConfig->ui32NegInput);
+}
+
+//*****************************************************************************
+//
+//! @brief Set the Voltage Comparator DAC Level Select in Configuration Reg.
+//!
+//! @param ui32Level - DAC voltage selector (use macros enumerations)
+//!
+//! This function sets the DAC level select in the configuration register.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_dac_level_set(uint32_t ui32Level)
+{
+ //
+ // Insert the supplied level into the vcomp configuration register
+ //
+ AM_BFW(VCOMP, CFG, LVLSEL, ui32Level >> AM_REG_VCOMP_CFG_LVLSEL_S);
+}
+
+//*****************************************************************************
+//
+//! @brief Read the state of the voltage comparator.
+//!
+//! This function extracts the comparator state from the status register.
+//!
+//! @return the voltage comparator state
+//
+//*****************************************************************************
+bool
+am_hal_vcomp_read(void)
+{
+ return (AM_BFR(VCOMP, STAT, CMPOUT) == 1);
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the voltage comparator.
+//!
+//! This function powers up the voltage comparator.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_enable(void)
+{
+ AM_REG(VCOMP, PWDKEY) = 0;
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the voltage comparator.
+//!
+//! This function powers down the voltage comparator.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_disable(void)
+{
+ AM_REG(VCOMP, PWDKEY) = AM_REG_VCOMP_PWDKEY_KEYVAL;
+}
+
+//*****************************************************************************
+//
+//! @brief Read the state of the voltage comparator interrupt status bits.
+//!
+//! @param bEnabledOnly - return the status of only the enabled interrupts.
+//!
+//! This function extracts the interrupt status bits and returns the raw or
+//! only the enabled based on bEnabledOnly.
+//!
+//! @return Bitwise representation of the current interrupt status.
+//!
+//! The return value will be the logical OR of one or more of the following
+//! values:
+//!
+//! AM_HAL_VCOMP_INT_OUTHI
+//! AM_HAL_VCOMP_INT_OUTLO
+//
+//*****************************************************************************
+uint32_t
+am_hal_vcomp_int_status_get(bool bEnabledOnly)
+{
+ if (bEnabledOnly)
+ {
+ uint32_t u32RetVal = AM_REG(VCOMP, INTSTAT);
+ return u32RetVal & AM_REG(VCOMP, INTEN);
+ }
+ else
+ {
+ return AM_REG(VCOMP, INTSTAT);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Set the state of the voltage comparator interrupt status bits.
+//!
+//! @param ui32Interrupt - interrupts to be set.
+//!
+//! This function sets the specified interrupt status bits.
+//!
+//! ui32Interrupt should be a logical or of:
+//!
+//! AM_HAL_VCOMP_INT_OUTHI
+//! AM_HAL_VCOMP_INT_OUTLO
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_int_set(uint32_t ui32Interrupt)
+{
+ AM_REG(VCOMP, INTSET) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Clear the state of the voltage comparator interrupt status bits.
+//!
+//! @param ui32Interrupt - interrupts to be cleared.
+//!
+//! This function clears the specified interrupt status bits.
+//!
+//! ui32Interrupt should be a logical or of:
+//!
+//! AM_HAL_VCOMP_INT_OUTHI
+//! AM_HAL_VCOMP_INT_OUTLO
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_int_clear(uint32_t ui32Interrupt)
+{
+ AM_REG(VCOMP, INTCLR) = ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the voltage comparator interrupt status bits.
+//!
+//! @param ui32Interrupt - interrupts to be enabled.
+//!
+//! This function enables desired interrupt status bits.
+//!
+//! ui32Interrupt should be a logical or of:
+//!
+//! AM_HAL_VCOMP_INT_OUTHI
+//! AM_HAL_VCOMP_INT_OUTLO
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_int_enable(uint32_t ui32Interrupt)
+{
+ AM_REG(VCOMP, INTEN) |= ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+//! @brief Return the enabled, voltage comparator interrupt status bits.
+//!
+//! This function returns the enabled interrupt status bits
+//!
+//! @return returns the enabled interrupt status bits. The return is a logical
+//! or of:
+//!
+//! AM_HAL_VCOMP_INT_OUTHI
+//! AM_HAL_VCOMP_INT_OUTLO
+//
+//*****************************************************************************
+uint32_t
+am_hal_vcomp_int_enable_get(void)
+{
+ return AM_REG(VCOMP, INTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the voltage comparator interrupt status bits.
+//!
+//! @param ui32Interrupt - interrupts to be disabled.
+//!
+//! This function disables desired interrupt status bits.
+//!
+//! ui32Interrupt should be a logical or of:
+//!
+//! AM_HAL_VCOMP_INT_OUTHI
+//! AM_HAL_VCOMP_INT_OUTLO
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_vcomp_int_disable(uint32_t ui32Interrupt)
+{
+ AM_REG(VCOMP, INTEN) &= ~ui32Interrupt;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.h b/bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.h
new file mode 100644
index 0000000000..a6ca991aae
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_vcomp.h
@@ -0,0 +1,176 @@
+//*****************************************************************************
+//
+// am_hal_vcomp.h
+//! @file
+//!
+//! @brief Functions for operating the on-chip Voltage Comparator
+//!
+//! @addtogroup vcomp2 Voltage Comparator (VCOMP)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_VCOMP_H
+#define AM_HAL_VCOMP_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+//! @name Positive Input Selection
+//! @brief Use these macros to determine the positive input to the comparator.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_VCOMP_PSEL_VDDADJ AM_REG_VCOMP_CFG_PSEL_VDDADJ
+#define AM_HAL_VCOMP_PSEL_VTEMP AM_REG_VCOMP_CFG_PSEL_VTEMP
+#define AM_HAL_VCOMP_PSEL_VEXT1 AM_REG_VCOMP_CFG_PSEL_VEXT1
+#define AM_HAL_VCOMP_PSEL_VEXT2 AM_REG_VCOMP_CFG_PSEL_VEXT2
+//! @}
+
+//*****************************************************************************
+//
+//! @name Negative Input Selection
+//! @brief Use these macros to determine the negative input to the comparator.
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_VCOMP_NSEL_VREFEXT1 AM_REG_VCOMP_CFG_NSEL_VREFEXT1
+#define AM_HAL_VCOMP_NSEL_VREFEXT2 AM_REG_VCOMP_CFG_NSEL_VREFEXT2
+#define AM_HAL_VCOMP_NSEL_VREFEXT3 AM_REG_VCOMP_CFG_NSEL_VREFEXT3
+#define AM_HAL_VCOMP_NSEL_DAC_LEVEL AM_REG_VCOMP_CFG_NSEL_DAC
+//! @}
+
+//*****************************************************************************
+//
+//! @name Negative Input DAC Selectioin
+//! @brief Use these macros to determine the NSEL DAC voltage setting
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_VCOMP_DAC_LVLSEL_0_58V AM_REG_VCOMP_CFG_LVLSEL_0P58V
+#define AM_HAL_VCOMP_DAC_LVLSEL_0_77V AM_REG_VCOMP_CFG_LVLSEL_0P77V
+#define AM_HAL_VCOMP_DAC_LVLSEL_0_97V AM_REG_VCOMP_CFG_LVLSEL_0P97V
+#define AM_HAL_VCOMP_DAC_LVLSEL_1_16V AM_REG_VCOMP_CFG_LVLSEL_1P16V
+#define AM_HAL_VCOMP_DAC_LVLSEL_1_35V AM_REG_VCOMP_CFG_LVLSEL_1P35V
+#define AM_HAL_VCOMP_DAC_LVLSEL_1_55V AM_REG_VCOMP_CFG_LVLSEL_1P55V
+#define AM_HAL_VCOMP_DAC_LVLSEL_1_74V AM_REG_VCOMP_CFG_LVLSEL_1P74V
+#define AM_HAL_VCOMP_DAC_LVLSEL_1_93V AM_REG_VCOMP_CFG_LVLSEL_1P93V
+#define AM_HAL_VCOMP_DAC_LVLSEL_2_13V AM_REG_VCOMP_CFG_LVLSEL_2P13V
+#define AM_HAL_VCOMP_DAC_LVLSEL_2_32V AM_REG_VCOMP_CFG_LVLSEL_2P32V
+#define AM_HAL_VCOMP_DAC_LVLSEL_2_51V AM_REG_VCOMP_CFG_LVLSEL_2P51V
+#define AM_HAL_VCOMP_DAC_LVLSEL_2_71V AM_REG_VCOMP_CFG_LVLSEL_2P71V
+#define AM_HAL_VCOMP_DAC_LVLSEL_2_90V AM_REG_VCOMP_CFG_LVLSEL_2P90V
+#define AM_HAL_VCOMP_DAC_LVLSEL_3_09V AM_REG_VCOMP_CFG_LVLSEL_3P09V
+#define AM_HAL_VCOMP_DAC_LVLSEL_3_29V AM_REG_VCOMP_CFG_LVLSEL_3P29V
+#define AM_HAL_VCOMP_DAC_LVLSEL_3_48V AM_REG_VCOMP_CFG_LVLSEL_3P48V
+//! @}
+
+//*****************************************************************************
+//
+//! @name Interrupt Status Bits
+//! @brief Interrupt Status Bits for enable/disble use
+//!
+//! These macros may be used to set and clear interrupt bits
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_VCOMP_INT_OUTHI AM_REG_VCOMP_INTEN_OUTHI_M
+#define AM_HAL_VCOMP_INT_OUTLO AM_REG_VCOMP_INTEN_OUTLOW_M
+//! @}
+
+//*****************************************************************************
+//
+//! @brief Configuration struct
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! The DAC level setting
+ //
+ uint32_t ui32LevelSelect;
+
+ //
+ //! The "positive" comparator input channel
+ //!
+ //! This channel is usually used as the signal to be monitored.
+ //
+ uint32_t ui32PosInput;
+
+ //
+ //! The "negative" comparator input channel
+ //!
+ //! This channel is usually used as the reference signal.
+ //
+ uint32_t ui32NegInput;
+}
+am_hal_vcomp_config_t;
+
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_vcomp_config(const am_hal_vcomp_config_t *psConfig);
+extern void am_hal_vcomp_dac_level_set(uint32_t ui3Level);
+extern bool am_hal_vcomp_read(void);
+extern void am_hal_vcomp_enable(void);
+extern void am_hal_vcomp_disable(void);
+extern void am_hal_vcomp_int_enable(uint32_t ui32Interrupt);
+extern uint32_t am_hal_vcomp_int_enable_get(void);
+extern void am_hal_vcomp_int_disable(uint32_t ui32Interrupt);
+extern void am_hal_vcomp_int_clear(uint32_t ui32Interrupt);
+extern void am_hal_vcomp_int_set(uint32_t ui32Interrupt);
+extern uint32_t am_hal_vcomp_int_status_get(bool bEnabledOnly);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_VCOMP_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_wdt.c b/bsp/apollo2/libraries/drivers/hal/am_hal_wdt.c
new file mode 100644
index 0000000000..4e80113fd1
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_wdt.c
@@ -0,0 +1,454 @@
+//*****************************************************************************
+//
+// am_hal_wdt.c
+//! @file
+//!
+//! @brief Hardware abstraction layer for the Watchdog Timer module.
+//!
+//! @addtogroup wdt2 Watchdog Timer (WDT)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+// Adjacency check
+//
+// This is related to the timer read workaround. This macro checks to see if
+// the two supplied count values are within one "tick" of eachother. It should
+// still pass in the event of a timer rollover. The "B" read is assumed to
+// follow the "A" read. The macro returns "TRUE" when the adjacent timer reads
+// can be used.
+//
+//*****************************************************************************
+#define adjacent(A, B) (((A) == (B)) || (((A) + 1) == (B)) || ((B) == 0))
+
+//*****************************************************************************
+//
+//! @brief Configure the watchdog timer.
+//!
+//! @param psConfig - pointer to a configuration structure containing the
+//! desired watchdog settings.
+//!
+//! This function will set the watchdog configuration register based on the
+//! user's desired settings listed in the structure referenced by psConfig. If
+//! the structure indicates that watchdog interrupts are desired, this function
+//! will also set the interrupt enable bit in the configuration register.
+//!
+//! @note In order to actually receive watchdog interrupt and/or watchdog reset
+//! events, the caller will also need to make sure that the watchdog interrupt
+//! vector is enabled in the ARM NVIC, and that watchdog resets are enabled in
+//! the reset generator module. Otherwise, the watchdog-generated interrupt and
+//! reset events will have no effect.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_wdt_init(const am_hal_wdt_config_t *psConfig)
+{
+ uint32_t ui32ConfigVal;
+ uint16_t ui16IntCount, ui16ResetCount;
+ bool bResetEnabled = psConfig->ui32Config & AM_HAL_WDT_ENABLE_RESET;
+ bool bInterruptEnabled = psConfig->ui32Config & AM_HAL_WDT_ENABLE_INTERRUPT;
+
+ //
+ // Read the desired settings from the psConfig structure.
+ //
+ ui16IntCount = psConfig->ui16InterruptCount;
+ ui16ResetCount = psConfig->ui16ResetCount;
+
+ //
+ // Write the interrupt and reset count values to a temporary variable.
+ //
+ // Accept the passed Config value, but clear the Counts that we are about to set.
+ ui32ConfigVal = psConfig->ui32Config & ~(AM_REG_WDT_CFG_INTVAL_M | AM_REG_WDT_CFG_RESVAL_M);
+ ui32ConfigVal |= AM_WRITE_SM(AM_REG_WDT_CFG_INTVAL, ui16IntCount);
+ ui32ConfigVal |= AM_WRITE_SM(AM_REG_WDT_CFG_RESVAL, ui16ResetCount);
+
+ //
+ // If interrupts should be enabled, set the appropriate bit in the
+ // temporary variable. Also, enable the interrupt in INTEN register in the
+ // watchdog module.
+ //
+ if ( bInterruptEnabled )
+ {
+ //
+ // Enable the watchdog interrupt if the configuration calls for them.
+ //
+ AM_REGn(WDT, 0, INTEN) |= AM_REG_WDT_INTEN_WDT_M;
+ }
+ else
+ {
+ //
+ // Disable the watchdog interrupt if the configuration doesn't call for
+ // watchdog interrupts.
+ //
+ AM_REGn(WDT, 0, INTEN) &= ~AM_REG_WDT_INTEN_WDT_M;
+ }
+
+ //
+ // If resets should be enabled, set the appropriate bit in the temporary
+ // variable.
+ //
+ if ( bResetEnabled )
+ {
+ //
+ // Also enable watchdog resets in the reset module.
+ //
+ AM_REG(RSTGEN, CFG) |= AM_REG_RSTGEN_CFG_WDREN_M;
+ }
+ else
+ {
+ //
+ // Disable watchdog resets in the reset module.
+ //
+ AM_REG(RSTGEN, CFG) &= ~AM_REG_RSTGEN_CFG_WDREN_M;
+ }
+
+ //
+ // Check for a user specified clock select. If none specified then
+ // set 128Hz.
+ //
+ if ( !(psConfig->ui32Config & AM_REG_WDT_CFG_CLKSEL_M) )
+ {
+ ui32ConfigVal |= AM_REG_WDT_CFG_CLKSEL_128HZ;
+ }
+
+ //
+ // Write the saved value to the watchdog configuration register.
+ //
+ AM_REGn(WDT, 0, CFG) = ui32ConfigVal;
+}
+
+//*****************************************************************************
+//
+//! @brief Starts the watchdog timer.
+//!
+//! Enables the watchdog timer tick using the 'enable' bit in the watchdog
+//! configuration register. This function does not perform any locking of the
+//! watchdog timer, so it can be disabled or reconfigured later.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_wdt_start(void)
+{
+ //
+ // Make sure the watchdog timer is in the "reset" state, and then set the
+ // enable bit to start counting.
+ //
+ AM_REGn(WDT, 0, CFG) |= AM_REG_WDT_CFG_WDTEN_M;
+ AM_REGn(WDT, 0, RSTRT) |= AM_REG_WDT_RSTRT_RSTRT_KEYVALUE;
+
+}
+
+//*****************************************************************************
+//
+//! @brief Stops the watchdog timer.
+//!
+//! Disables the watchdog timer tick by clearing the 'enable' bit in the
+//! watchdog configuration register.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_wdt_halt(void)
+{
+
+ //
+ // Clear the watchdog enable bit.
+ //
+ AM_REGn(WDT, 0, CFG) &= ~AM_REG_WDT_CFG_WDTEN_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Locks the watchdog configuration and starts the watchdog timer.
+//!
+//! This function sets the watchdog "lock" register, which prevents software
+//! from re-configuring the watchdog. This action will also set the enable bit
+//! for the watchdog timer, so it will start counting immediately.
+//!
+//! @return None.
+//
+//*****************************************************************************
+void
+am_hal_wdt_lock_and_start(void)
+{
+ //
+ // Write the 'key' value to the watchdog lock register.
+ //
+ AM_REGn(WDT, 0, LOCK) = AM_REG_WDT_LOCK_LOCK_KEYVALUE;
+}
+
+//*****************************************************************************
+//
+//! @brief Read the state of the wdt interrupt status.
+//!
+//! @param bEnabledOnly - return the status of only the enabled interrupts.
+//!
+//! This function extracts the interrupt status bits and returns the enabled or
+//! raw based on bEnabledOnly.
+//!
+//! @return WDT interrupt status.
+//
+//*****************************************************************************
+uint32_t
+am_hal_wdt_int_status_get(bool bEnabledOnly)
+{
+ if (bEnabledOnly)
+ {
+ uint32_t u32RetVal = AM_REG(WDT, INTSTAT);
+ return u32RetVal & AM_REG(WDT, INTEN);
+ }
+ else
+ {
+ return AM_REG(WDT, INTSTAT);
+ }
+}
+
+//*****************************************************************************
+//
+//! @brief Set the state of the wdt interrupt status bit.
+//!
+//! This function sets the interrupt bit.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_wdt_int_set(void)
+{
+ AM_REG(WDT, INTSET) = AM_REG_WDT_INTSET_WDT_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Clear the state of the wdt interrupt status bit.
+//!
+//! This function clear the interrupt bit.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_wdt_int_clear(void)
+{
+ AM_REGn(WDT, 0, INTCLR) = AM_REG_WDT_INTCLR_WDT_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Enable the wdt interrupt.
+//!
+//! This function enable the interrupt.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_wdt_int_enable(void)
+{
+ AM_REG(WDT, INTEN) |= AM_REG_WDT_INTSET_WDT_M;
+}
+
+//*****************************************************************************
+//
+//! @brief Return the enabled WDT interrupts.
+//!
+//! This function returns the enabled WDT interrupts.
+//!
+//! @return enabled WDT interrupts.
+//
+//*****************************************************************************
+uint32_t
+am_hal_wdt_int_enable_get(void)
+{
+ return AM_REG(WDT, INTEN);
+}
+
+//*****************************************************************************
+//
+//! @brief Disable the wdt interrupt.
+//!
+//! This function disablee the interrupt.
+//!
+//! @return None
+//
+//*****************************************************************************
+void
+am_hal_wdt_int_disable(void)
+{
+ AM_REG(WDT, INTEN) &= ~AM_REG_WDT_INTSET_WDT_M;
+}
+
+//*****************************************************************************
+//
+// Static function for reading the WDT counter value.
+//
+//*****************************************************************************
+#if defined(__GNUC_STDC_INLINE__)
+__attribute__((naked))
+static
+void
+back2back_read_asm(uint32_t *pui32Array, uint32_t *pui32Register)
+{
+ // pui32Array[] is a pointer to a 3 word data array provided by the caller.
+ // pui32Register = address of the timer to be read.
+ __asm
+ (
+ // Do 3 back-to-back reads of the register
+ " ldr r2, [r1, #0]\n" // Get counter register value
+ " ldr r3, [r1, #0]\n" // Get counter register value again
+ " ldr r1, [r1, #0]\n" // Get counter register value for a third time
+ " str r2, [r0, #0]\n" // Store register value to variable
+ " str r3, [r0, #4]\n" // Store register value to variable
+ " str r1, [r0, #8]\n" // Store register value to variable
+ " bx lr\n"
+ );
+}
+
+#elif defined(__ARMCC_VERSION)
+__asm static uint32_t
+back2back_read_asm(uint32_t *pui32Array, uint32_t *pui32Register)
+{
+ ldr r2, [r1, #0] // Get TMRn register value
+ ldr r3, [r1, #0] // Get TMRn register value again
+ ldr r1, [r1, #0] // Get TMRn register value for a third time
+ str r2, [r0, #0] // Store register value to variable
+ str r3, [r0, #4] // Store register value to variable
+ str r1, [r0, #8] // Store register value to variable
+ bx lr
+}
+
+#elif defined(__IAR_SYSTEMS_ICC__)
+#pragma diag_suppress = Pe940 // Suppress IAR compiler warning about missing
+ // return statement on a non-void function
+__stackless static uint32_t
+back2back_read_asm(uint32_t *pui32Array, uint32_t *pui32Register)
+{
+ __asm(" ldr r2, [r1, #0]"); // Get TMRn register value
+ __asm(" ldr r3, [r1, #0]"); // Get TMRn register value again
+ __asm(" ldr r1, [r1, #0]"); // Get TMRn register value for a third time
+ __asm(" str r2, [r0, #0]"); // Store register value to variable
+ __asm(" str r3, [r0, #4]"); // Store register value to variable
+ __asm(" str r1, [r0, #8]"); // Store register value to variable
+ __asm(" bx lr");
+}
+#pragma diag_default = Pe940 // Restore IAR compiler warning
+#endif
+
+
+//*****************************************************************************
+//
+//! @brief Get the wdt counter value.
+//!
+//! This function reads the current value of watch dog timer counter register.
+//!
+//! WARNING caller is responsible for masking interrutps before calling this
+//! function.
+//!
+//! @return None
+//
+//*****************************************************************************
+uint32_t
+am_hal_wdt_counter_get(void)
+{
+ uint32_t ui32Values[3] = {0};
+ uint32_t ui32Value;
+
+ //
+ // First, go read the value from the counter register 3 times
+ // back to back in assembly language.
+ //
+ back2back_read_asm(ui32Values, (uint32_t *)AM_REG_WDTn(0));
+
+ //
+ // Now, we'll figure out which of the three values is the correct time.
+ //
+ if (ui32Values[0] == ui32Values[1])
+ {
+ //
+ // If the first two values match, then neither one was a bad read.
+ // We'll take this as the current time.
+ //
+ ui32Value = ui32Values[1];
+ }
+ else
+ {
+ //
+ // If the first two values didn't match, then one of them might be bad.
+ // If one of the first two values is bad, then the third one should
+ // always be correct. We'll take the third value as the correct count.
+ //
+ ui32Value = ui32Values[2];
+
+ //
+ // If all of the statements about the architecture are true, the third
+ // value should be correct, and it should always be within one count of
+ // either the first or the second value.
+ //
+ // Just in case, we'll check against the previous two values to make
+ // sure that our final answer was reasonable. If it isn't, we will
+ // flag it as a "bad read", and fail this assert statement.
+ //
+ // This shouldn't ever happen, and it hasn't ever happened in any of
+ // our tests so far.
+ //
+ am_hal_debug_assert_msg((adjacent(ui32Values[1], ui32Values[2]) ||
+ adjacent(ui32Values[0], ui32Values[2])),
+ "Bad CDT read");
+ }
+
+ return ui32Value;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_wdt.h b/bsp/apollo2/libraries/drivers/hal/am_hal_wdt.h
new file mode 100644
index 0000000000..63766fa458
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_wdt.h
@@ -0,0 +1,184 @@
+//*****************************************************************************
+//
+// am_hal_wdt.h
+//! @file
+//!
+//! @brief Hardware abstraction layer for the Watchdog Timer module.
+//!
+//! @addtogroup wdt2 Watchdog Timer (WDT)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, 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.
+//
+// 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 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+#ifndef AM_HAL_WDT_H
+#define AM_HAL_WDT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+//*****************************************************************************
+//
+// Macro definitions
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! @name WDT Clock Divider Selections.
+//! @brief Macro definitions for WDT clock frequencies.
+//!
+//! These macros may be used with the am_hal_wdt_config_t structure to set the
+//! clock frequency of the watch dog timer.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_WDT_LFRC_CLK_DEFAULT AM_REG_WDT_CFG_CLKSEL_128HZ
+#define AM_HAL_WDT_LFRC_CLK_128HZ AM_REG_WDT_CFG_CLKSEL_128HZ
+#define AM_HAL_WDT_LFRC_CLK_16HZ AM_REG_WDT_CFG_CLKSEL_16HZ
+#define AM_HAL_WDT_LFRC_CLK_1HZ AM_REG_WDT_CFG_CLKSEL_1HZ
+#define AM_HAL_WDT_LFRC_CLK_1_16HZ AM_REG_WDT_CFG_CLKSEL_1_16HZ
+#define AM_HAL_WDT_LFRC_CLK_OFF AM_REG_WDT_CFG_CLKSEL_OFF
+//! @}
+
+//*****************************************************************************
+//
+//! @name WDT Enable Reset in the WDT Configuration.
+//! @brief Macro definitions for WDT Reset Enable.
+//!
+//! These macros may be used with the am_hal_wdt_config_t structure to enable
+//! the watch dog timer to generate resets to the chip.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_WDT_ENABLE_RESET AM_REG_WDT_CFG_RESEN(1)
+#define AM_HAL_WDT_DISABLE_RESET AM_REG_WDT_CFG_RESEN(0)
+//! @}
+
+//*****************************************************************************
+//
+//! @name WDT Enable Interrupt Generation from the WDT Configuration.
+//! @brief Macro definitions for WDT Interrupt Enable.
+//!
+//! These macros may be used with the am_hal_wdt_config_t structure to enable
+//! the watch dog timer to generate generate WDT interrupts.
+//!
+//! @{
+//
+//*****************************************************************************
+#define AM_HAL_WDT_ENABLE_INTERRUPT AM_REG_WDT_CFG_INTEN(1)
+#define AM_HAL_WDT_DISABLE_INTERRUPT AM_REG_WDT_CFG_INTEN(0)
+//! @}
+
+//*****************************************************************************
+//
+//! @brief Watchdog timer configuration structure.
+//!
+//! This structure is made to be used with the am_hal_wdt_init() function. It
+//! describes the configuration of the watchdog timer.
+//
+//*****************************************************************************
+typedef struct
+{
+ //! Configuration Values for watchdog timer
+ //! event is generated.
+ uint32_t ui32Config;
+
+ //! Number of watchdog timer ticks allowed before a watchdog interrupt
+ //! event is generated.
+ uint16_t ui16InterruptCount;
+
+ //! Number of watchdog timer ticks allowed before the watchdog will issue a
+ //! system reset.
+ uint16_t ui16ResetCount;
+
+}
+am_hal_wdt_config_t;
+
+
+//*****************************************************************************
+//
+//! @brief Restarts the watchdog timer ("Pets" the dog)
+//!
+//! This function restarts the watchdog timer from the beginning, preventing
+//! any interrupt or reset even from occuring until the next time the watchdog
+//! timer expires.
+//!
+//! @return None.
+//
+//*****************************************************************************
+#define am_hal_wdt_restart() \
+ do \
+ { \
+ AM_REGn(WDT, 0, RSTRT) = AM_REG_WDT_RSTRT_RSTRT_KEYVALUE; \
+ (void)AM_REGn(WDT, 0, RSTRT); \
+ } \
+ while(0)
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+//*****************************************************************************
+//
+// External function definitions
+//
+//*****************************************************************************
+extern void am_hal_wdt_init(const am_hal_wdt_config_t *psConfig);
+extern void am_hal_wdt_start(void);
+extern void am_hal_wdt_halt(void);
+extern void am_hal_wdt_lock_and_start(void);
+extern void am_hal_wdt_int_enable(void);
+extern uint32_t am_hal_wdt_int_enable_get(void);
+extern void am_hal_wdt_int_disable(void);
+extern void am_hal_wdt_int_clear(void);
+extern void am_hal_wdt_int_set(void);
+extern uint32_t am_hal_wdt_int_status_get(bool bEnabledOnly);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AM_HAL_WDT_H
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************