summaryrefslogtreecommitdiff
path: root/bsp/apollo2/libraries/drivers/hal/am_hal_itm.c
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/am_hal_itm.c
parent7b4e7224e4fba7080c33ebf11b45dc9b093a73d6 (diff)
Add bsp apollo2
Diffstat (limited to 'bsp/apollo2/libraries/drivers/hal/am_hal_itm.c')
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_itm.c453
1 files changed, 453 insertions, 0 deletions
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.
+//! @}
+//
+//*****************************************************************************