123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- //*****************************************************************************
- //
- // 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.11 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_flash_delay(FLASH_CYCLES_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.
- //! @}
- //
- //*****************************************************************************
|