Newer
Older
mbed-os / targets / TARGET_Cypress / TARGET_PSOC6 / mtb-pdl-cat1 / drivers / include / cy_profile.h
@Dustin Crossman Dustin Crossman on 4 Jun 2021 20 KB Fix file modes.
/***************************************************************************//**
* \file cy_profile.h
* \version 1.30
*
* Provides an API declaration of the energy profiler driver.
*
********************************************************************************
* \copyright
* Copyright 2016-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

/**
* \addtogroup group_energy_profiler
* \{
*
* The energy profiler driver is an API for configuring and using the profile
* hardware block.
*
* The functions and other declarations used in this driver are in cy_profile.h.
* You can include cy_pdl.h to get access to all functions
* and declarations in the PDL.
*
* The profile block enables measurement of the signal activity
* of select peripherals and monitor sources during a measurement window. Using
* these measurements, you can construct a profile of the energy consumed
* in the device by scaling the individual peripheral activities with appropriate
* scaling (weight) factors. This gives the application the ability to monitor
* the energy consumed by the internal resources with minimal CPU overhead and
* without external monitoring hardware.
*
* \section group_profile_details Details
*
* \subsection group_profile_hardware Profile Hardware
*
* The profile hardware consists of a number of profile counters that accept specific
* triggers for incrementing the count value. This allows the events of the source
* (such as the number of SCB0 bus accesses or the duration of time the BLE RX radio
* is active) to be counted during the measurement window. The available monitor
* sources in the device can be found in the en_ep_mon_sel_t enum in the device
* configuration file (e.g. psoc62_config.h). These can be sourced to any of the
* profile counters as triggers. There are two methods of using the monitor sources
* in a profile counter.
*
* - Event: The count value is incremented when a pulse event signal is seen by the
*   counter. This type of monitoring is suitable when the monitoring source of
*   interest needs to count the discrete events (such as the number of flash read
*   accesses) happening in the measurement window.
*
* - Duration: The count value is incremented at every clock edge while the monitor
*   signal is high. This type of monitoring is suitable when a signal is active for
*   a finite amount of time (such as the time the BLE TX radio is active) and the
*   duration must be expressed as number of clock cycles in the measurement window.
*
* Many of the available monitor sources are suitable for event type monitoring.
* Using a duration type on these signals may not give valuable information. Review
* the device TRM for more information on the monitor sources and detail on how they
* should be used.
*
* \subsection group_profile_measurement_types Measurement Types
*
* Depending on the item of interest, energy measurement can be performed by using
* the following methods.
*
* - Continuous measurement: A profile counter can be assigned a monitor signal of
*   constant 1 (PROFILE_ONE), which sets the counter to increment at every (assigned)
*   clock cycle. This can be used to give a reference time for the measurement window
*   and also allows the construction of timestamps. For example, a software controlled
*   GPIO can be "timestamped" by reading the counter value (on the fly) before it is
*   toggled. When the measurement window ends, the energy contribution caused by the
*   GPIO toggle can be incorporated into the final calculation.
*
* - Event measurement: Monitored events happening in a measurement window can be
*   used to increment a profile counter. This gives the activity numbers, which can
*   then be multiplied by the instantaneous power numbers associated with the source
*   to give the average energy consumption (Energy = Power x time). For example, the
*   energy consumed by an Operating System (OS) task can be estimated by monitoring
*   the processor's active cycle count (E.g. CPUSS_MONITOR_CM4) and the flash read
*   accesses (CPUSS_MONITOR_FLASH). Note that these activity numbers can also be
*   timestamped using the continuous measurement method to differentiate between the
*   different task switches. The activity numbers are then multiplied by the associated
*   processor and flash access power numbers to give the average energy consumed by
*   that task.
*
* - Duration measurement: A peripheral event such as the SMIF select signal can be
*   used by a profile counter to measure the time spent on XIP communication through the
*   SPI interface. This activity number can then be multiplied by the power associated
*   with that activity to give the average energy consumed by that block during the
*   measurement window. This type of monitoring should be performed only for signals
*   that are difficult to track in software. For example, a combination of interrupts
*   and timestamps can be used to track the activity of many peripherals in a continuous
*   monitoring model. However tracking the activity of signals such the BLE radio
*   should be done using the duration measurement method.
*
* - Low power measurement: The profile counters do not support measurement during chip
*   Deep Sleep, Hibernate, and off states. I.e. the profile counters are meant for active
*   run-time measurements only. To measure the time spent in low power modes (LPM),
*   a real-time clock (RTC) should be used. Take a timestamp before LPM entry and a
*   timestamp upon LPM exit in a continuous measurement model. Then multiply the difference
*   by the appropriate LPM power numbers.
*
* \subsection group_profile_usage Driver Usage
*
* At the highest level, the energy profiler must perform the following steps to
* obtain a measurement:
*
*  1. Initialize the profile hardware block.
*  2. Initialize the profile interrupt (profile_interrupt_IRQn).
*  3. Configure, initialize, and enable the profile counters.
*  4. Enable the profile interrupt and start the profiling/measurement window.
*  5. Perform run-time reads of the counters (if needed).
*  6. Disable the profile interrupt and stop the profiling/measurement window.
*  7. Read the counters and gather the results.
*  8. Calculate the energy consumption.
*
* Refer to the SysInt driver on the details of configuring the profile hardware interrupt.
*
* The profile interrupt triggers when a counter overflow event is detected on any of the
* enabled profile counters. A sample interrupt service routine Cy_Profile_ISR() is provided,
* which can be used to update the internal counter states stored in RAM. Refer to the
* Configuration Considerations for more information.
*
* \section group_profile_configuration Configuration Considerations
*
* Each counter is a 32-bit register that counts either a number of clock cycles,
* or a number of events. Overflowing the 32-bit register is possible. To address
* this issue, the driver implements a 32-bit overflow counter. Combined with the 32-bit
* register, this gives a 64-bit counter for each monitored source.
*
* When an overflow occurs, the profile hardware generates an interrupt. The interrupt is
* configured using the SysInt driver, where the sample interrupt handler Cy_Profile_ISR()
* can be used as the ISR. The ISR increments the overflow counter for each profiling counter
* and clears the interrupt.
*
* \section group_profile_more_information More Information
*
* See the profiler chapter of the device technical reference manual (TRM).
*
* \section group_profile_changelog Changelog
* <table class="doxtable">
*   <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
*   <tr>
*     <td>1.30</td>
*     <td>Fixed MISRA 2012 violations.</td>
*     <td>MISRA 2012 compliance.</td>
*   </tr>
*   <tr>
*     <td>1.20.1</td>
*     <td>Minor documentation updates.</td>
*     <td>Documentation enhancement.</td>
*   </tr>
*   <tr>
*     <td>1.20</td>
*     <td>Updated API function \ref Cy_Profile_GetSumWeightedCounts().</td>
*     <td>Minor defect fixing: now the function supports the correct number of counters.</td>
*   </tr>
*   <tr>
*     <td rowspan="3">1.10</td>
*     <td>Flattened the organization of the driver source code into the single source directory and the single include directory.</td>
*     <td>Driver library directory-structure simplification.</td>
*   </tr>
*   <tr>
*     <td>Added register access layer. Use register access macros instead
*         of direct register access using dereferenced pointers.</td>
*     <td>Makes register access device-independent, so that the PDL does
*         not need to be recompiled for each supported part number.</td>
*   </tr>
*   <tr>
*     <td>Added parameter check asserts.</td>
*     <td>Driver defect fix.</td>
*   </tr>
*   <tr>
*     <td>1.0</td>
*     <td>Initial version</td>
*     <td></td>
*   </tr>
* </table>
*
* \defgroup group_profile_macros Macros
* \defgroup group_profile_functions Functions
* \{
*   \defgroup group_profile_functions_interrupt    Interrupt Functions
*   \defgroup group_profile_functions_general      General Functions
*   \defgroup group_profile_functions_counter      Counter Functions
*   \defgroup group_profile_functions_calculation  Calculation Functions
* \}
* \defgroup group_profile_data_structures Data Structures
* \defgroup group_profile_enums Enumerated Types
*/

#if !defined(CY_PROFILE_H)
#define CY_PROFILE_H

#include "cy_device.h"

#if defined (CY_IP_MXPROFILE)

#include "cy_syslib.h"
#include <stddef.h>

#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */

/** \addtogroup group_profile_macros
* \{
*/

/** Driver major version */
#define CY_PROFILE_DRV_VERSION_MAJOR  1

/** Driver minor version */
#define CY_PROFILE_DRV_VERSION_MINOR  30

/** Profile driver identifier */
#define CY_PROFILE_ID   CY_PDL_DRV_ID(0x1EU)

/** Start profiling command for the CMD register */
#define CY_PROFILE_START_TR    1UL

/** Stop profiling command for the CMD register */
#define CY_PROFILE_STOP_TR     2UL

/** Command to clear all counter registers to 0 */
#define CY_PROFILE_CLR_ALL_CNT 0x100UL

/** \} group_profile_macros */

/***************************************
*        Constants
***************************************/

/** \cond INTERNAL */

/* Parameter check macros */
#define CY_PROFILE_IS_MONITOR_VALID(monitor)    (CY_EP_MONITOR_COUNT > ((uint32_t)(monitor)))
#define CY_PROFILE_IS_DURATION_VALID(duration)  (((duration) == CY_PROFILE_EVENT) || \
                                                 ((duration) == CY_PROFILE_DURATION))
#define CY_PROFILE_IS_REFCLK_VALID(refClk)      (((refClk) == CY_PROFILE_CLK_TIMER) || \
                                                 ((refClk) == CY_PROFILE_CLK_IMO) || \
                                                 ((refClk) == CY_PROFILE_CLK_ECO) || \
                                                 ((refClk) == CY_PROFILE_CLK_LF) || \
                                                 ((refClk) == CY_PROFILE_CLK_HF) || \
                                                 ((refClk) == CY_PROFILE_CLK_PERI))
#define CY_PROFILE_IS_CNT_VALID(numCounters)    (CY_EP_CNT_NR >= (numCounters))

/** \endcond */

/***************************************
*        Enumerations
***************************************/

/**
* \addtogroup group_profile_enums
* \{
*/

/**
* Profile counter reference clock source. Used when duration monitoring.
*/
typedef enum
{
    CY_PROFILE_CLK_TIMER  = 0, /**< Timer clock (TimerClk) */
    CY_PROFILE_CLK_IMO    = 1, /**< Internal main oscillator (IMO) */
    CY_PROFILE_CLK_ECO    = 2, /**< External crystal oscillator (ECO) */
    CY_PROFILE_CLK_LF     = 3, /**< Low-frequency clock (LFCLK) */
    CY_PROFILE_CLK_HF     = 4, /**< High-Frequency clock (HFCLK0) */
    CY_PROFILE_CLK_PERI   = 5, /**< Peripheral clock (PeriClk) */
} cy_en_profile_ref_clk_t;

/**
* Monitor method type.
*/
typedef enum
{
    CY_PROFILE_EVENT    = 0,  /**< Count (edge-detected) module events  */
    CY_PROFILE_DURATION = 1,  /**< Count (level) duration in clock cycles */
} cy_en_profile_duration_t;

/** Profiler status codes */
typedef enum
{
    CY_PROFILE_SUCCESS = 0x00U,                                      /**< Operation completed successfully */
    CY_PROFILE_BAD_PARAM = CY_PROFILE_ID | CY_PDL_STATUS_ERROR | 1UL /**< Invalid input parameters */

 } cy_en_profile_status_t;

 /** \} group_profile_enums */

/***************************************
*       Configuration Structures
***************************************/

/**
* \addtogroup group_profile_data_structures
* \{
*/

/**
* Profile counter control register structure. For each counter, holds the CTL register fields.
*/
typedef struct
{
    cy_en_profile_duration_t  cntDuration; /**< 0 = event; 1 = duration */
    cy_en_profile_ref_clk_t   refClkSel;   /**< The reference clock used by the counter */
    en_ep_mon_sel_t           monSel;      /**< The monitor signal to be observed by the counter */
} cy_stc_profile_ctr_ctl_t;

/**
* Software structure for holding a profile counter status and configuration information.
*/
typedef struct
{
    uint8_t                   ctrNum;      /**< Profile counter number */
    uint8_t                   used;        /**< 0 = available; 1 = used */
    cy_stc_profile_ctr_ctl_t  ctlRegVals;  /**< Initial counter CTL register settings */
    PROFILE_CNT_STRUCT_Type * cntAddr;     /**< Base address of the counter instance registers */
    uint32_t                  ctlReg;      /**< Current CTL register value */
    uint32_t                  cntReg;      /**< Current CNT register value */
    uint32_t                  overflow;    /**< Extension of cntReg to form a 64-bit counter value */
    uint32_t                  weight;      /**< Weighting factor for the counter */
} cy_stc_profile_ctr_t;

/**
* Pointer to a structure holding the status information for a profile counter.
*/
typedef cy_stc_profile_ctr_t * cy_stc_profile_ctr_ptr_t;
/** \} group_profile_data_structures */

/**
* \addtogroup group_profile_functions
* \{
*/

/**
* \addtogroup group_profile_functions_interrupt
* \{
*/
/* ========================================================================== */
/* ====================    INTERRUPT FUNCTION SECTION    ==================== */
/* ========================================================================== */
void Cy_Profile_ISR(void);
/** \} group_profile_functions_interrupt */

/**
* \addtogroup group_profile_functions_general
* \{
*/
__STATIC_INLINE void Cy_Profile_Init(void);
__STATIC_INLINE void Cy_Profile_DeInit(void);
                void Cy_Profile_StartProfiling(void);
__STATIC_INLINE void Cy_Profile_StopProfiling(void);
__STATIC_INLINE uint32_t Cy_Profile_IsProfiling(void);


/* ========================================================================== */
/* ===============    GENERAL PROFILE FUNCTIONS SECTION     ================= */
/* ========================================================================== */
/*******************************************************************************
* Function Name: Cy_Profile_Init
****************************************************************************//**
*
* Initializes and enables the profile hardware.
*
* This function must be called once when energy profiling is desired. The
* operation does not start a profiling session.
*
* \note The profile interrupt must also be configured. \ref Cy_Profile_ISR()
* can be used as its handler.
*
* \funcusage
* \snippet profile/snippet/main.c snippet_Cy_Profile_Init
*
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_Init(void)
{
    PROFILE_CTL = _VAL2FLD(PROFILE_CTL_ENABLED,  1UL/*enabled */) |
                  _VAL2FLD(PROFILE_CTL_WIN_MODE, 0UL/*start/stop mode*/);
    PROFILE_INTR_MASK = 0UL; /* clear all counter interrupt mask bits */
}


/*******************************************************************************
* Function Name: Cy_Profile_DeInit
****************************************************************************//**
*
* Clears the interrupt mask and disables the profile hardware.
*
* This function should be called when energy profiling is no longer desired.
*
* \note The profile interrupt is not disabled by this operation and must be
* disabled separately.
*
* \funcusage
* \snippet profile/snippet/main.c snippet_Cy_Profile_DeInit
*
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_DeInit(void)
{
    PROFILE_CTL = _VAL2FLD(PROFILE_CTL_ENABLED, 0UL/*disabled */);
    PROFILE_INTR_MASK = 0UL; /* clear all counter interrupt mask bits */
}


/*******************************************************************************
* Function Name: Cy_Profile_StopProfiling
****************************************************************************//**
*
* Stops the profiling/measurement window.
*
* This operation prevents the enabled profile counters from counting.
*
* \note The profile interrupt should be disabled before calling this function.
*
* \funcusage
* \snippet profile/snippet/main.c snippet_Cy_Profile_StopProfiling
*
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_StopProfiling(void)
{
    PROFILE_CMD = CY_PROFILE_STOP_TR;
}


/*******************************************************************************
* Function Name: Cy_Profile_IsProfiling
****************************************************************************//**
*
* Reports the active status of the profiling window.
*
* \return 0 = profiling is not active; 1 = profiling is active
*
* \funcusage
* \snippet profile/snippet/main.c snippet_Cy_Profile_IsProfiling
*
*******************************************************************************/
__STATIC_INLINE uint32_t Cy_Profile_IsProfiling(void)
{
    return _FLD2VAL(PROFILE_STATUS_WIN_ACTIVE, PROFILE_STATUS);
}
/** \} group_profile_functions_general */

/**
* \addtogroup group_profile_functions_counter
* \{
*/
void Cy_Profile_ClearConfiguration(void);
__STATIC_INLINE void Cy_Profile_ClearCounters(void);
cy_stc_profile_ctr_ptr_t Cy_Profile_ConfigureCounter(en_ep_mon_sel_t monitor, cy_en_profile_duration_t duration, cy_en_profile_ref_clk_t refClk, uint32_t weight);
cy_en_profile_status_t Cy_Profile_FreeCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
cy_en_profile_status_t Cy_Profile_EnableCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
cy_en_profile_status_t Cy_Profile_DisableCounter(cy_stc_profile_ctr_ptr_t ctrAddr);

/* ========================================================================== */
/* ===================    COUNTER FUNCTIONS SECTION    ====================== */
/* ========================================================================== */
/*******************************************************************************
* Function Name: Cy_Profile_ClearCounters
****************************************************************************//**
*
* Clears all hardware counters to 0.
*
* \funcusage
* \snippet profile/snippet/main.c snippet_Cy_Profile_ClearCounters
*
*******************************************************************************/
__STATIC_INLINE void Cy_Profile_ClearCounters(void)
{
    PROFILE_CMD = CY_PROFILE_CLR_ALL_CNT;
}
/** \} group_profile_functions_counter */

/**
* \addtogroup group_profile_functions_calculation
* \{
*/
/* ========================================================================== */
/* ==================    CALCULATION FUNCTIONS SECTION    =================== */
/* ========================================================================== */
cy_en_profile_status_t Cy_Profile_GetRawCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result);
cy_en_profile_status_t Cy_Profile_GetWeightedCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result);
uint64_t Cy_Profile_GetSumWeightedCounts(cy_stc_profile_ctr_ptr_t ptrsArray[], uint32_t numCounters);
/** \} group_profile_functions_calculation */

/** \} group_profile_functions */

#if defined(__cplusplus)
}
#endif /* __cplusplus */

#endif /* CY_IP_MXPROFILE */

#endif /* CY_PROFILE_H */

/** \} group_profile */


/* [] END OF FILE */