1 /***************************************************************************//**
2 * \file cy_profile.h
3 * \version 1.30
4 *
5 * Provides an API declaration of the energy profiler driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2020 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 /**
26 * \addtogroup group_energy_profiler
27 * \{
28 *
29 * The energy profiler driver is an API for configuring and using the profile
30 * hardware block.
31 *
32 * The functions and other declarations used in this driver are in cy_profile.h.
33 * You can include cy_pdl.h to get access to all functions
34 * and declarations in the PDL.
35 *
36 * The profile block enables measurement of the signal activity
37 * of select peripherals and monitor sources during a measurement window. Using
38 * these measurements, you can construct a profile of the energy consumed
39 * in the device by scaling the individual peripheral activities with appropriate
40 * scaling (weight) factors. This gives the application the ability to monitor
41 * the energy consumed by the internal resources with minimal CPU overhead and
42 * without external monitoring hardware.
43 *
44 * \section group_profile_details Details
45 *
46 * \subsection group_profile_hardware Profile Hardware
47 *
48 * The profile hardware consists of a number of profile counters that accept specific
49 * triggers for incrementing the count value. This allows the events of the source
50 * (such as the number of SCB0 bus accesses or the duration of time the BLE RX radio
51 * is active) to be counted during the measurement window. The available monitor
52 * sources in the device can be found in the en_ep_mon_sel_t enum in the device
53 * configuration file (e.g. psoc62_config.h). These can be sourced to any of the
54 * profile counters as triggers. There are two methods of using the monitor sources
55 * in a profile counter.
56 *
57 * - Event: The count value is incremented when a pulse event signal is seen by the
58 * counter. This type of monitoring is suitable when the monitoring source of
59 * interest needs to count the discrete events (such as the number of flash read
60 * accesses) happening in the measurement window.
61 *
62 * - Duration: The count value is incremented at every clock edge while the monitor
63 * signal is high. This type of monitoring is suitable when a signal is active for
64 * a finite amount of time (such as the time the BLE TX radio is active) and the
65 * duration must be expressed as number of clock cycles in the measurement window.
66 *
67 * Many of the available monitor sources are suitable for event type monitoring.
68 * Using a duration type on these signals may not give valuable information. Review
69 * the device TRM for more information on the monitor sources and detail on how they
70 * should be used.
71 *
72 * \subsection group_profile_measurement_types Measurement Types
73 *
74 * Depending on the item of interest, energy measurement can be performed by using
75 * the following methods.
76 *
77 * - Continuous measurement: A profile counter can be assigned a monitor signal of
78 * constant 1 (PROFILE_ONE), which sets the counter to increment at every (assigned)
79 * clock cycle. This can be used to give a reference time for the measurement window
80 * and also allows the construction of timestamps. For example, a software controlled
81 * GPIO can be "timestamped" by reading the counter value (on the fly) before it is
82 * toggled. When the measurement window ends, the energy contribution caused by the
83 * GPIO toggle can be incorporated into the final calculation.
84 *
85 * - Event measurement: Monitored events happening in a measurement window can be
86 * used to increment a profile counter. This gives the activity numbers, which can
87 * then be multiplied by the instantaneous power numbers associated with the source
88 * to give the average energy consumption (Energy = Power x time). For example, the
89 * energy consumed by an Operating System (OS) task can be estimated by monitoring
90 * the processor's active cycle count (E.g. CPUSS_MONITOR_CM4) and the flash read
91 * accesses (CPUSS_MONITOR_FLASH). Note that these activity numbers can also be
92 * timestamped using the continuous measurement method to differentiate between the
93 * different task switches. The activity numbers are then multiplied by the associated
94 * processor and flash access power numbers to give the average energy consumed by
95 * that task.
96 *
97 * - Duration measurement: A peripheral event such as the SMIF select signal can be
98 * used by a profile counter to measure the time spent on XIP communication through the
99 * SPI interface. This activity number can then be multiplied by the power associated
100 * with that activity to give the average energy consumed by that block during the
101 * measurement window. This type of monitoring should be performed only for signals
102 * that are difficult to track in software. For example, a combination of interrupts
103 * and timestamps can be used to track the activity of many peripherals in a continuous
104 * monitoring model. However tracking the activity of signals such the BLE radio
105 * should be done using the duration measurement method.
106 *
107 * - Low power measurement: The profile counters do not support measurement during chip
108 * Deep Sleep, Hibernate, and off states. I.e. the profile counters are meant for active
109 * run-time measurements only. To measure the time spent in low power modes (LPM),
110 * a real-time clock (RTC) should be used. Take a timestamp before LPM entry and a
111 * timestamp upon LPM exit in a continuous measurement model. Then multiply the difference
112 * by the appropriate LPM power numbers.
113 *
114 * \subsection group_profile_usage Driver Usage
115 *
116 * At the highest level, the energy profiler must perform the following steps to
117 * obtain a measurement:
118 *
119 * 1. Initialize the profile hardware block.
120 * 2. Initialize the profile interrupt (profile_interrupt_IRQn).
121 * 3. Configure, initialize, and enable the profile counters.
122 * 4. Enable the profile interrupt and start the profiling/measurement window.
123 * 5. Perform run-time reads of the counters (if needed).
124 * 6. Disable the profile interrupt and stop the profiling/measurement window.
125 * 7. Read the counters and gather the results.
126 * 8. Calculate the energy consumption.
127 *
128 * Refer to the SysInt driver on the details of configuring the profile hardware interrupt.
129 *
130 * The profile interrupt triggers when a counter overflow event is detected on any of the
131 * enabled profile counters. A sample interrupt service routine Cy_Profile_ISR() is provided,
132 * which can be used to update the internal counter states stored in RAM. Refer to the
133 * Configuration Considerations for more information.
134 *
135 * \section group_profile_configuration Configuration Considerations
136 *
137 * Each counter is a 32-bit register that counts either a number of clock cycles,
138 * or a number of events. Overflowing the 32-bit register is possible. To address
139 * this issue, the driver implements a 32-bit overflow counter. Combined with the 32-bit
140 * register, this gives a 64-bit counter for each monitored source.
141 *
142 * When an overflow occurs, the profile hardware generates an interrupt. The interrupt is
143 * configured using the SysInt driver, where the sample interrupt handler Cy_Profile_ISR()
144 * can be used as the ISR. The ISR increments the overflow counter for each profiling counter
145 * and clears the interrupt.
146 *
147 * \section group_profile_more_information More Information
148 *
149 * See the profiler chapter of the device technical reference manual (TRM).
150 *
151 * \section group_profile_changelog Changelog
152 * <table class="doxtable">
153 * <tr><th>Version</th><th>Changes</th><th>Reason for Change</th></tr>
154 * <tr>
155 * <td>1.30</td>
156 * <td>Fixed MISRA 2012 violations.</td>
157 * <td>MISRA 2012 compliance.</td>
158 * </tr>
159 * <tr>
160 * <td>1.20.1</td>
161 * <td>Minor documentation updates.</td>
162 * <td>Documentation enhancement.</td>
163 * </tr>
164 * <tr>
165 * <td>1.20</td>
166 * <td>Updated API function \ref Cy_Profile_GetSumWeightedCounts().</td>
167 * <td>Minor defect fixing: now the function supports the correct number of counters.</td>
168 * </tr>
169 * <tr>
170 * <td rowspan="3">1.10</td>
171 * <td>Flattened the organization of the driver source code into the single source directory and the single include directory.</td>
172 * <td>Driver library directory-structure simplification.</td>
173 * </tr>
174 * <tr>
175 * <td>Added register access layer. Use register access macros instead
176 * of direct register access using dereferenced pointers.</td>
177 * <td>Makes register access device-independent, so that the PDL does
178 * not need to be recompiled for each supported part number.</td>
179 * </tr>
180 * <tr>
181 * <td>Added parameter check asserts.</td>
182 * <td>Driver defect fix.</td>
183 * </tr>
184 * <tr>
185 * <td>1.0</td>
186 * <td>Initial version</td>
187 * <td></td>
188 * </tr>
189 * </table>
190 *
191 * \defgroup group_profile_macros Macros
192 * \defgroup group_profile_functions Functions
193 * \{
194 * \defgroup group_profile_functions_interrupt Interrupt Functions
195 * \defgroup group_profile_functions_general General Functions
196 * \defgroup group_profile_functions_counter Counter Functions
197 * \defgroup group_profile_functions_calculation Calculation Functions
198 * \}
199 * \defgroup group_profile_data_structures Data Structures
200 * \defgroup group_profile_enums Enumerated Types
201 */
202
203 #if !defined(CY_PROFILE_H)
204 #define CY_PROFILE_H
205
206 #include "cy_device.h"
207
208 #if defined (CY_IP_MXPROFILE)
209
210 #include "cy_syslib.h"
211 #include <stddef.h>
212
213 #if defined(__cplusplus)
214 extern "C" {
215 #endif /* __cplusplus */
216
217 /** \addtogroup group_profile_macros
218 * \{
219 */
220
221 /** Driver major version */
222 #define CY_PROFILE_DRV_VERSION_MAJOR 1
223
224 /** Driver minor version */
225 #define CY_PROFILE_DRV_VERSION_MINOR 30
226
227 /** Profile driver identifier */
228 #define CY_PROFILE_ID CY_PDL_DRV_ID(0x1EU)
229
230 /** Start profiling command for the CMD register */
231 #define CY_PROFILE_START_TR 1UL
232
233 /** Stop profiling command for the CMD register */
234 #define CY_PROFILE_STOP_TR 2UL
235
236 /** Command to clear all counter registers to 0 */
237 #define CY_PROFILE_CLR_ALL_CNT 0x100UL
238
239 /** \} group_profile_macros */
240
241 /***************************************
242 * Constants
243 ***************************************/
244
245 /** \cond INTERNAL */
246
247 /* Parameter check macros */
248 #define CY_PROFILE_IS_MONITOR_VALID(monitor) (CY_EP_MONITOR_COUNT > ((uint32_t)(monitor)))
249 #define CY_PROFILE_IS_DURATION_VALID(duration) (((duration) == CY_PROFILE_EVENT) || \
250 ((duration) == CY_PROFILE_DURATION))
251 #define CY_PROFILE_IS_REFCLK_VALID(refClk) (((refClk) == CY_PROFILE_CLK_TIMER) || \
252 ((refClk) == CY_PROFILE_CLK_IMO) || \
253 ((refClk) == CY_PROFILE_CLK_ECO) || \
254 ((refClk) == CY_PROFILE_CLK_LF) || \
255 ((refClk) == CY_PROFILE_CLK_HF) || \
256 ((refClk) == CY_PROFILE_CLK_PERI))
257 #define CY_PROFILE_IS_CNT_VALID(numCounters) (CY_EP_CNT_NR >= (numCounters))
258
259 /** \endcond */
260
261 /***************************************
262 * Enumerations
263 ***************************************/
264
265 /**
266 * \addtogroup group_profile_enums
267 * \{
268 */
269
270 /**
271 * Profile counter reference clock source. Used when duration monitoring.
272 */
273 typedef enum
274 {
275 CY_PROFILE_CLK_TIMER = 0, /**< Timer clock (TimerClk) */
276 CY_PROFILE_CLK_IMO = 1, /**< Internal main oscillator (IMO) */
277 CY_PROFILE_CLK_ECO = 2, /**< External crystal oscillator (ECO) */
278 CY_PROFILE_CLK_LF = 3, /**< Low-frequency clock (LFCLK) */
279 CY_PROFILE_CLK_HF = 4, /**< High-Frequency clock (HFCLK0) */
280 CY_PROFILE_CLK_PERI = 5, /**< Peripheral clock (PeriClk) */
281 } cy_en_profile_ref_clk_t;
282
283 /**
284 * Monitor method type.
285 */
286 typedef enum
287 {
288 CY_PROFILE_EVENT = 0, /**< Count (edge-detected) module events */
289 CY_PROFILE_DURATION = 1, /**< Count (level) duration in clock cycles */
290 } cy_en_profile_duration_t;
291
292 /** Profiler status codes */
293 typedef enum
294 {
295 CY_PROFILE_SUCCESS = 0x00U, /**< Operation completed successfully */
296 CY_PROFILE_BAD_PARAM = CY_PROFILE_ID | CY_PDL_STATUS_ERROR | 1UL /**< Invalid input parameters */
297
298 } cy_en_profile_status_t;
299
300 /** \} group_profile_enums */
301
302 /***************************************
303 * Configuration Structures
304 ***************************************/
305
306 /**
307 * \addtogroup group_profile_data_structures
308 * \{
309 */
310
311 /**
312 * Profile counter control register structure. For each counter, holds the CTL register fields.
313 */
314 typedef struct
315 {
316 cy_en_profile_duration_t cntDuration; /**< 0 = event; 1 = duration */
317 cy_en_profile_ref_clk_t refClkSel; /**< The reference clock used by the counter */
318 en_ep_mon_sel_t monSel; /**< The monitor signal to be observed by the counter */
319 } cy_stc_profile_ctr_ctl_t;
320
321 /**
322 * Software structure for holding a profile counter status and configuration information.
323 */
324 typedef struct
325 {
326 uint8_t ctrNum; /**< Profile counter number */
327 uint8_t used; /**< 0 = available; 1 = used */
328 cy_stc_profile_ctr_ctl_t ctlRegVals; /**< Initial counter CTL register settings */
329 PROFILE_CNT_STRUCT_Type * cntAddr; /**< Base address of the counter instance registers */
330 uint32_t ctlReg; /**< Current CTL register value */
331 uint32_t cntReg; /**< Current CNT register value */
332 uint32_t overflow; /**< Extension of cntReg to form a 64-bit counter value */
333 uint32_t weight; /**< Weighting factor for the counter */
334 } cy_stc_profile_ctr_t;
335
336 /**
337 * Pointer to a structure holding the status information for a profile counter.
338 */
339 typedef cy_stc_profile_ctr_t * cy_stc_profile_ctr_ptr_t;
340 /** \} group_profile_data_structures */
341
342 /**
343 * \addtogroup group_profile_functions
344 * \{
345 */
346
347 /**
348 * \addtogroup group_profile_functions_interrupt
349 * \{
350 */
351 /* ========================================================================== */
352 /* ==================== INTERRUPT FUNCTION SECTION ==================== */
353 /* ========================================================================== */
354 void Cy_Profile_ISR(void);
355 /** \} group_profile_functions_interrupt */
356
357 /**
358 * \addtogroup group_profile_functions_general
359 * \{
360 */
361 __STATIC_INLINE void Cy_Profile_Init(void);
362 __STATIC_INLINE void Cy_Profile_DeInit(void);
363 void Cy_Profile_StartProfiling(void);
364 __STATIC_INLINE void Cy_Profile_StopProfiling(void);
365 __STATIC_INLINE uint32_t Cy_Profile_IsProfiling(void);
366
367
368 /* ========================================================================== */
369 /* =============== GENERAL PROFILE FUNCTIONS SECTION ================= */
370 /* ========================================================================== */
371 /*******************************************************************************
372 * Function Name: Cy_Profile_Init
373 ****************************************************************************//**
374 *
375 * Initializes and enables the profile hardware.
376 *
377 * This function must be called once when energy profiling is desired. The
378 * operation does not start a profiling session.
379 *
380 * \note The profile interrupt must also be configured. \ref Cy_Profile_ISR()
381 * can be used as its handler.
382 *
383 * \funcusage
384 * \snippet profile/snippet/main.c snippet_Cy_Profile_Init
385 *
386 *******************************************************************************/
Cy_Profile_Init(void)387 __STATIC_INLINE void Cy_Profile_Init(void)
388 {
389 PROFILE_CTL = _VAL2FLD(PROFILE_CTL_ENABLED, 1UL/*enabled */) |
390 _VAL2FLD(PROFILE_CTL_WIN_MODE, 0UL/*start/stop mode*/);
391 PROFILE_INTR_MASK = 0UL; /* clear all counter interrupt mask bits */
392 }
393
394
395 /*******************************************************************************
396 * Function Name: Cy_Profile_DeInit
397 ****************************************************************************//**
398 *
399 * Clears the interrupt mask and disables the profile hardware.
400 *
401 * This function should be called when energy profiling is no longer desired.
402 *
403 * \note The profile interrupt is not disabled by this operation and must be
404 * disabled separately.
405 *
406 * \funcusage
407 * \snippet profile/snippet/main.c snippet_Cy_Profile_DeInit
408 *
409 *******************************************************************************/
Cy_Profile_DeInit(void)410 __STATIC_INLINE void Cy_Profile_DeInit(void)
411 {
412 PROFILE_CTL = _VAL2FLD(PROFILE_CTL_ENABLED, 0UL/*disabled */);
413 PROFILE_INTR_MASK = 0UL; /* clear all counter interrupt mask bits */
414 }
415
416
417 /*******************************************************************************
418 * Function Name: Cy_Profile_StopProfiling
419 ****************************************************************************//**
420 *
421 * Stops the profiling/measurement window.
422 *
423 * This operation prevents the enabled profile counters from counting.
424 *
425 * \note The profile interrupt should be disabled before calling this function.
426 *
427 * \funcusage
428 * \snippet profile/snippet/main.c snippet_Cy_Profile_StopProfiling
429 *
430 *******************************************************************************/
Cy_Profile_StopProfiling(void)431 __STATIC_INLINE void Cy_Profile_StopProfiling(void)
432 {
433 PROFILE_CMD = CY_PROFILE_STOP_TR;
434 }
435
436
437 /*******************************************************************************
438 * Function Name: Cy_Profile_IsProfiling
439 ****************************************************************************//**
440 *
441 * Reports the active status of the profiling window.
442 *
443 * \return 0 = profiling is not active; 1 = profiling is active
444 *
445 * \funcusage
446 * \snippet profile/snippet/main.c snippet_Cy_Profile_IsProfiling
447 *
448 *******************************************************************************/
Cy_Profile_IsProfiling(void)449 __STATIC_INLINE uint32_t Cy_Profile_IsProfiling(void)
450 {
451 return _FLD2VAL(PROFILE_STATUS_WIN_ACTIVE, PROFILE_STATUS);
452 }
453 /** \} group_profile_functions_general */
454
455 /**
456 * \addtogroup group_profile_functions_counter
457 * \{
458 */
459 void Cy_Profile_ClearConfiguration(void);
460 __STATIC_INLINE void Cy_Profile_ClearCounters(void);
461 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);
462 cy_en_profile_status_t Cy_Profile_FreeCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
463 cy_en_profile_status_t Cy_Profile_EnableCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
464 cy_en_profile_status_t Cy_Profile_DisableCounter(cy_stc_profile_ctr_ptr_t ctrAddr);
465
466 /* ========================================================================== */
467 /* =================== COUNTER FUNCTIONS SECTION ====================== */
468 /* ========================================================================== */
469 /*******************************************************************************
470 * Function Name: Cy_Profile_ClearCounters
471 ****************************************************************************//**
472 *
473 * Clears all hardware counters to 0.
474 *
475 * \funcusage
476 * \snippet profile/snippet/main.c snippet_Cy_Profile_ClearCounters
477 *
478 *******************************************************************************/
Cy_Profile_ClearCounters(void)479 __STATIC_INLINE void Cy_Profile_ClearCounters(void)
480 {
481 PROFILE_CMD = CY_PROFILE_CLR_ALL_CNT;
482 }
483 /** \} group_profile_functions_counter */
484
485 /**
486 * \addtogroup group_profile_functions_calculation
487 * \{
488 */
489 /* ========================================================================== */
490 /* ================== CALCULATION FUNCTIONS SECTION =================== */
491 /* ========================================================================== */
492 cy_en_profile_status_t Cy_Profile_GetRawCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result);
493 cy_en_profile_status_t Cy_Profile_GetWeightedCount(cy_stc_profile_ctr_ptr_t ctrAddr, uint64_t *result);
494 uint64_t Cy_Profile_GetSumWeightedCounts(cy_stc_profile_ctr_ptr_t ptrsArray[], uint32_t numCounters);
495 /** \} group_profile_functions_calculation */
496
497 /** \} group_profile_functions */
498
499 #if defined(__cplusplus)
500 }
501 #endif /* __cplusplus */
502
503 #endif /* CY_IP_MXPROFILE */
504
505 #endif /* CY_PROFILE_H */
506
507 /** \} group_profile */
508
509
510 /* [] END OF FILE */
511