123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- //*****************************************************************************
- //
- // 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.11 of the AmbiqSuite Development Package.
- //
- //*****************************************************************************
- #include <stdint.h>
- #include <stdbool.h>
- #include "am_mcu_apollo.h"
- //*****************************************************************************
- //
- // Global Variables
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- //! @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.
- //
- 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_flash_delay(FLASH_CYCLES_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.
- //! @}
- //
- //*****************************************************************************
|