From c19fb2ab58d0ea77263a5eafa28fe2cf6ca9dec6 Mon Sep 17 00:00:00 2001 From: lin <429426691@qq.com> Date: Fri, 15 Sep 2017 18:10:51 +0800 Subject: Add bsp apollo2 --- bsp/apollo2/libraries/drivers/hal/am_hal_itm.c | 453 +++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 bsp/apollo2/libraries/drivers/hal/am_hal_itm.c (limited to 'bsp/apollo2/libraries/drivers/hal/am_hal_itm.c') 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 +#include +#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. +//! @} +// +//***************************************************************************** -- cgit v1.3.1