1 /*
2  * Trace Recorder for Tracealyzer v4.5.1
3  * Copyright 2021 Percepio AB
4  * www.percepio.com
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * The hardware abstraction layer for the trace recorder.
9  */
10 
11 #ifndef TRC_HARDWARE_PORT_H
12 #define TRC_HARDWARE_PORT_H
13 
14 #include "trcPortDefines.h"
15 
16 
17 #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET)
18 	#error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h"
19 #endif
20 
21 /*******************************************************************************
22  * TRC_IRQ_PRIORITY_ORDER
23  *
24  * Macro which should be defined as an integer of 0 or 1.
25  *
26  * This should be 0 if lower IRQ priority values implies higher priority
27  * levels, such as on ARM Cortex M. If the opposite scheme is used, i.e.,
28  * if higher IRQ priority values means higher priority, this should be 1.
29  *
30  * This setting is not critical. It is used only to sort and colorize the
31  * interrupts in priority order, in case you record interrupts using
32  * the vTraceStoreISRBegin and vTraceStoreISREnd routines.
33  *
34  ******************************************************************************
35  *
36  * HWTC Macros
37  *
38  * These macros provides a hardware isolation layer representing the
39  * hardware timer/counter used for the event timestamping.
40  *
41  * TRC_HWTC_COUNT: How to read the current value of the timer/counter.
42  *
43  * TRC_HWTC_TYPE: Tells the type of timer/counter used for TRC_HWTC_COUNT:
44  *
45  * - TRC_FREE_RUNNING_32BIT_INCR:
46  *   Free-running 32-bit timer/counter, counting upwards from 0.
47  *
48  * - TRC_FREE_RUNNING_32BIT_DECR
49  *   Free-running 32-bit timer/counter, counting downwards from 0xFFFFFFFF.
50  *
51  * - TRC_OS_TIMER_INCR
52  *	 Periodic timer that drives the OS tick interrupt, counting upwards
53  *   from 0 until (TRC_HWTC_PERIOD-1).
54  *
55  * - TRC_OS_TIMER_DECR
56  *	 Periodic timer that drives the OS tick interrupt, counting downwards
57  *   from TRC_HWTC_PERIOD-1 until 0.
58  *
59  * - TRC_CUSTOM_TIMER_INCR
60  *   A custom timer or counter independent of the OS tick, counting
61  *   downwards from TRC_HWTC_PERIOD-1 until 0. (Currently only supported
62  *   in streaming mode).
63  *
64  * - TRC_CUSTOM_TIMER_DECR
65  *   A custom timer independent of the OS tick, counting downwards
66  *   from TRC_HWTC_PERIOD-1 until 0. (Currently only supported
67  *   in streaming mode).
68  *
69  * TRC_HWTC_PERIOD: The number of HWTC_COUNT ticks until the timer wraps
70  * around. If using TRC_FREE_RUNNING_32BIT_INCR/DECR, this should be 0.
71  *
72  * TRC_HWTC_FREQ_HZ: The clock rate of the TRC_HWTC_COUNT counter in Hz. If using
73  * TRC_OS_TIMER_INCR/DECR, this is should be TRC_HWTC_PERIOD * TRACE_TICK_RATE_HZ.
74  * If using a free-running timer, this is often TRACE_CPU_CLOCK_HZ (if running at
75  * the core clock rate). If using TRC_CUSTOM_TIMER_INCR/DECR, this should match
76  * the clock rate of your custom timer (i.e., TRC_HWTC_COUNT). If the default value
77  * of TRC_HWTC_FREQ_HZ is incorrect for your setup, you can override it by calling
78  * vTraceSetFrequency before calling vTraceEnable.
79  *
80  * TRC_HWTC_DIVISOR (used in snapshot mode only):
81  * In snapshot mode, the timestamp resolution is TRC_HWTC_FREQ_HZ/TRC_HWTC_DIVISOR.
82  * If the timer frequency is very high (hundreds of MHz), we recommend increasing
83  * the TRC_HWTC_DIVISOR prescaler, to reduce the bandwidth needed to store
84  * timestamps. This since extra "XTS" events are inserted if the time since the
85  * previous event exceeds a certain limit (255 or 65535 depending on event type).
86  * It is advised to keep the time between most events below 65535 native ticks
87  * (after division by TRC_HWTC_DIVISOR) to avoid frequent XTS events.
88  ******************************************************************************/
89 
90 #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET)
91 	#error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h"
92 #endif
93 
94 #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32)
95 	/* This can be used as a template for any free-running 32-bit counter */
96 	unsigned long ulGetRunTimeCounterValue(void);
97 
98 
99 	#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
100 	#define TRC_HWTC_COUNT (ulGetRunTimeCounterValue())
101 	#define TRC_HWTC_PERIOD 0
102 	#define TRC_HWTC_DIVISOR 1
103 	#define TRC_HWTC_FREQ_HZ 100000
104 
105 	#define TRC_IRQ_PRIORITY_ORDER 1
106 
107 	#define TRC_PORT_SPECIFIC_INIT()
108 
109 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_HWIndependent)
110 	/* Timestamping by OS tick only (typically 1 ms resolution) */
111 	#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
112 	#define TRC_HWTC_COUNT 0
113 	#define TRC_HWTC_PERIOD 1
114 	#define TRC_HWTC_DIVISOR 1
115 	#define TRC_HWTC_FREQ_HZ TRACE_TICK_RATE_HZ
116 
117 	/* Set the meaning of IRQ priorities in ISR tracing - see above */
118 	#define TRC_IRQ_PRIORITY_ORDER NOT_SET
119 
120 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M)
121 
122 	#ifndef __CORTEX_M
123 	#error "Can't find the CMSIS API. Please include your processor's header file in trcConfig.h"
124 	#endif
125 
126 	/**************************************************************************
127 	* For Cortex-M3, M4 and M7, the DWT cycle counter is used for timestamping.
128 	* For Cortex-M0 and M0+, the SysTick timer is used since DWT is not
129 	* available. Systick timestamping can also be forced on Cortex-M3, M4 and
130 	* M7 by defining the preprocessor directive TRC_CFG_ARM_CM_USE_SYSTICK,
131 	* either directly below or in trcConfig.h.
132 	*
133 	* #define TRC_CFG_ARM_CM_USE_SYSTICK
134     **************************************************************************/
135 
136 	#if ((__CORTEX_M >= 0x03) && (! defined TRC_CFG_ARM_CM_USE_SYSTICK))
137 
138 		void prvTraceInitCortexM(void);
139 
140 		#define TRC_REG_DEMCR (*(volatile uint32_t*)0xE000EDFC)
141 		#define TRC_REG_DWT_CTRL (*(volatile uint32_t*)0xE0001000)
142 		#define TRC_REG_DWT_CYCCNT (*(volatile uint32_t*)0xE0001004)
143 		#define TRC_REG_DWT_EXCCNT (*(volatile uint32_t*)0xE000100C)
144 
145 		#define TRC_REG_ITM_LOCKACCESS (*(volatile uint32_t*)0xE0001FB0)
146 		#define TRC_ITM_LOCKACCESS_UNLOCK (0xC5ACCE55)
147 
148 		/* Bit mask for TRCENA bit in DEMCR - Global enable for DWT and ITM */
149 		#define TRC_DEMCR_TRCENA (1 << 24)
150 
151 		/* Bit mask for NOPRFCNT bit in DWT_CTRL. If 1, DWT_EXCCNT is not supported */
152 		#define TRC_DWT_CTRL_NOPRFCNT (1 << 24)
153 
154 		/* Bit mask for NOCYCCNT bit in DWT_CTRL. If 1, DWT_CYCCNT is not supported */
155 		#define TRC_DWT_CTRL_NOCYCCNT (1 << 25)
156 
157 		/* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_EXCCNT */
158 		#define TRC_DWT_CTRL_EXCEVTENA (1 << 18)
159 
160 		/* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_CYCCNT */
161 		#define TRC_DWT_CTRL_CYCCNTENA (1)
162 
163 		#define TRC_PORT_SPECIFIC_INIT() prvTraceInitCortexM()
164 
165 		#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
166 		#define TRC_HWTC_COUNT TRC_REG_DWT_CYCCNT
167 		#define TRC_HWTC_PERIOD 0
168 		#define TRC_HWTC_DIVISOR 4
169 		#define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ
170 		#define TRC_IRQ_PRIORITY_ORDER 0
171 
172 	#else
173 
174 		#define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
175 		#define TRC_HWTC_COUNT (*((volatile uint32_t*)0xE000E018))
176 		#define TRC_HWTC_PERIOD ((*((volatile uint32_t*)0xE000E014)) + 1)
177 		#define TRC_HWTC_DIVISOR 4
178 		#define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ
179 		#define TRC_IRQ_PRIORITY_ORDER 0
180 
181 	#endif
182 
183 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600)
184 
185 	#include "iodefine.h"
186 
187 	#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
188 
189 		#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
190 		#define TRC_HWTC_COUNT (CMT0.CMCNT)
191 
192 	#elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
193 
194 		/* Decreasing counters better for Tickless Idle? */
195 		#define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
196 		#define TRC_HWTC_COUNT (CMT0.CMCOR - CMT0.CMCNT)
197 
198 	#endif
199 
200 	#define TRC_HWTC_PERIOD (CMT0.CMCOR + 1)
201 	#define TRC_HWTC_DIVISOR 1
202 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
203 	#define TRC_IRQ_PRIORITY_ORDER 1
204 
205 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32)
206 
207 	#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
208 	#define TRC_HWTC_COUNT (TMR1)
209 	#define TRC_HWTC_PERIOD (PR1 + 1)
210 	#define TRC_HWTC_DIVISOR 1
211 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
212 	#define TRC_IRQ_PRIORITY_ORDER 1
213 
214 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48)
215 
216 	#define TRC_RTIFRC0 *((uint32_t *)0xFFFFFC10)
217 	#define TRC_RTICOMP0 *((uint32_t *)0xFFFFFC50)
218 	#define TRC_RTIUDCP0 *((uint32_t *)0xFFFFFC54)
219 
220 	#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
221 	#define TRC_HWTC_COUNT (TRC_RTIFRC0 - (TRC_RTICOMP0 - TRC_RTIUDCP0))
222 	#define TRC_HWTC_PERIOD (TRC_RTIUDCP0)
223 	#define TRC_HWTC_DIVISOR 1
224 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
225 	#define TRC_IRQ_PRIORITY_ORDER 0
226 
227 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_AT91SAM7)
228 
229 	/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
230 
231 	#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
232 	#define TRC_HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF))
233 	#define TRC_HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1))
234 	#define TRC_HWTC_DIVISOR 1
235 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
236 	#define TRC_IRQ_PRIORITY_ORDER 1
237 
238 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_UC3A0)
239 
240 	/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO*/
241 
242 	/* For Atmel AVR32 (AT32UC3A) */
243 
244 	#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
245 	#define TRC_HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT))
246 	#define TRC_HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1))
247 	#define TRC_HWTC_DIVISOR 1
248 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
249 	#define TRC_IRQ_PRIORITY_ORDER 1
250 
251 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NXP_LPC210X)
252 
253 	/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
254 
255 	/* Tested with LPC2106, but should work with most LPC21XX chips. */
256 
257 	#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
258 	#define TRC_HWTC_COUNT *((uint32_t *)0xE0004008 )
259 	#define TRC_HWTC_PERIOD *((uint32_t *)0xE0004018 )
260 	#define TRC_HWTC_DIVISOR 1
261 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
262 	#define TRC_IRQ_PRIORITY_ORDER 0
263 
264 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_MSP430)
265 
266 	/* UNOFFICIAL PORT - NOT YET VERIFIED */
267 
268 	#define TRC_HWTC_TYPE TRC_OS_TIMER_INCR
269 	#define TRC_HWTC_COUNT (TA0R)
270 	#define TRC_HWTC_PERIOD (((uint16_t)TACCR0)+1)
271 	#define TRC_HWTC_DIVISOR 1
272 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
273 	#define TRC_IRQ_PRIORITY_ORDER 1
274 
275 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC405)
276 
277 	/* UNOFFICIAL PORT - NOT YET VERIFIED */
278 
279 	#define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
280 	#define TRC_HWTC_COUNT mfspr(0x3db)
281 	#define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ)
282 	#define TRC_HWTC_DIVISOR 1
283 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
284 	#define TRC_IRQ_PRIORITY_ORDER 0
285 
286 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC440)
287 
288 	/* UNOFFICIAL PORT */
289 
290 	/* This should work with most PowerPC chips */
291 
292 	#define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
293 	#define TRC_HWTC_COUNT mfspr(0x016)
294 	#define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRACE_TICK_RATE_HZ)
295 	#define TRC_HWTC_DIVISOR 1
296 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
297 	#define TRC_IRQ_PRIORITY_ORDER 0
298 
299 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_MICROBLAZE)
300 
301 	/* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
302 
303 	/* This should work with most Microblaze configurations.
304 	 * It uses the AXI Timer 0 - the tick interrupt source.
305 	 * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required.
306 	 */
307 	#include "xtmrctr_l.h"
308 
309 	#define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
310 	#define TRC_HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 )
311  	#define TRC_HWTC_PERIOD (XTmrCtr_mGetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1)
312 	#define TRC_HWTC_DIVISOR 16
313 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
314 	#define TRC_IRQ_PRIORITY_ORDER 0
315 
316 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5)
317 
318 	#include "xttcps_hw.h"
319 
320 	#define TRC_HWTC_TYPE  TRC_OS_TIMER_INCR
321 	#define TRC_HWTC_COUNT  (*(volatile uint32_t *)(configTIMER_BASEADDR + XTTCPS_COUNT_VALUE_OFFSET))
322 	#define TRC_HWTC_PERIOD  (*(volatile uint32_t *)(configTIMER_BASEADDR + XTTCPS_INTERVAL_VAL_OFFSET))
323 	#define TRC_HWTC_DIVISOR  16
324 	#define TRC_HWTC_FREQ_HZ  (TRC_HWTC_PERIOD * TRACE_TICK_RATE_HZ)
325 	#define TRC_IRQ_PRIORITY_ORDER  0
326 
327 	#ifdef __GNUC__
328 	/* For Arm Cortex-A and Cortex-R in general. */
prvGetCPSR(void)329 	static inline uint32_t prvGetCPSR(void)
330 	{
331 		unsigned long ret;
332 		/* GCC-style assembly for getting the CPSR/APSR register, where the system execution mode is found. */
333 		asm volatile (" mrs  %0, cpsr" : "=r" (ret) : /* no inputs */  );
334 		return ret;
335 	}
336 	#else
337 		#error "Only GCC Supported!"
338 	#endif
339 
340 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII)
341 
342     /* OFFICIAL PORT */
343 
344 	#include <system.h>
345 	#include <altera_avalon_timer_regs.h>
346 
347 	#define NOT_SET 1
348 
349 	/* The base address for the sustem timer set.
350 	 * The name user for the system timer can be found in the BSP editor.
351 	 * If the name of the timer is sys_tmr SYSTEM_TIMER_BASE should be set to SYS_TMR_BASE.
352 	*/
353 	#define SYSTEM_TIMER_BASE NOT_SET
354 
355 	#if (SYSTEM_TIMER == NOT_SET)
356 		#error "Set SYSTEM_TIMER_BASE to the timer base used for system ticks."
357 	#endif
358 
altera_nios2_GetTimerSnapReg(void)359  	static inline uint32_t altera_nios2_GetTimerSnapReg(void)
360 	{
361 		/* A processor can read the current counter value by first writing to either snapl or snaph to request a coherent snapshot of the counter,
362 		 * and then reading snapl and snaph for the full 32-bit value.
363 		*/
364 		IOWR_ALTERA_AVALON_TIMER_SNAPL(SYSTEM_TIMER_BASE, 0);
365 		return (IORD_ALTERA_AVALON_TIMER_SNAPH(SYSTEM_TIMER_BASE) << 16) | IORD_ALTERA_AVALON_TIMER_SNAPL(SYSTEM_TIMER_BASE);
366 	}
367 
368 	#define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
369 	#define TRC_HWTC_COUNT altera_nios2_GetTimerSnapReg()
370 	#define TRC_HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ )
371 	#define TRC_HWTC_DIVISOR 16
372 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
373 	#define TRC_IRQ_PRIORITY_ORDER 0
374 
375 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9)
376 
377 	/**************************************************************************
378 	* This hardware port only supports FreeRTOS and the GCC compiler at the
379 	* moment, due to the implementation of critical sections (trcKernelPort.h).
380 	*
381 	* Assuming FreeRTOS is used:
382 	*
383     * For critical sections, this uses vTaskEnterCritical is when called from
384 	* task context and ulPortSetInterruptMask when called from ISR context.
385 	* Thus, it does not disable all ISRs. This means that the trace recorder
386 	* can only be called from ISRs with priority less or equal to
387 	* configMAX_API_CALL_INTERRUPT_PRIORITY (like FreeRTOS fromISR functions).
388 	*
389     * This hardware port has been tested on it a Xilinx Zync 7000 (Cortex-A9),
390 	* but should work with all Cortex-A and R processors assuming that
391 	* TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS is set accordingly.
392 	**************************************************************************/
393 
394 	/* INPUT YOUR PERIPHERAL BASE ADDRESS HERE (0xF8F00000 for Xilinx Zynq 7000)*/
395 	#define TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS	0
396 
397 	#if (TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS == 0)
398 		#error "Please specify TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS."
399 	#endif
400 
401 	#define TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET	0x0600
402 	#define TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG	(*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x00))
403 	#define TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG	(*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x04))
404 	#define TRC_CA9_MPCORE_PRIVCTR_CONTROL_REG	(*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x08))
405 
406 	#define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK    0x0000FF00
407 	#define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT   8
408 	#define TRC_CA9_MPCORE_PRIVCTR_PRESCALER        (((TRC_CA9_MPCORE_PRIVCTR_CONTROL_REG & TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK) >> TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT) + 1)
409 
410     #define TRC_HWTC_TYPE                           TRC_OS_TIMER_DECR
411     #define TRC_HWTC_COUNT                          TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG
412     #define TRC_HWTC_PERIOD                         (TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG + 1)
413 
414     /****************************************************************************************
415 	NOTE: The private timer ticks with a very high frequency (half the core-clock usually),
416 	depending on the prescaler used. If a low prescaler is used, the number of HW ticks between
417 	the trace events gets large, and thereby inefficient to store (sometimes extra events are
418 	needed). To improve efficiency, you may use the TRC_HWTC_DIVISOR as an additional prescaler.
419     *****************************************************************************************/
420 	#define TRC_HWTC_DIVISOR 1
421 
422 	#define TRC_HWTC_FREQ_HZ (TRACE_TICK_RATE_HZ * TRC_HWTC_PERIOD)
423     #define TRC_IRQ_PRIORITY_ORDER 0
424 
425 	#ifdef __GNUC__
426 	/* For Arm Cortex-A and Cortex-R in general. */
prvGetCPSR(void)427 	static inline uint32_t prvGetCPSR(void)
428 	{
429 		unsigned long ret;
430 		/* GCC-style assembly for getting the CPSR/APSR register, where the system execution mode is found. */
431 		asm volatile (" mrs  %0, cpsr" : "=r" (ret) : /* no inputs */  );
432 		return ret;
433 	}
434 	#else
435 		#error "Only GCC Supported!"
436 	#endif
437 
438 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ZEPHYR)
439 	#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
440 	#define TRC_HWTC_COUNT k_cycle_get_32()
441 	#define TRC_HWTC_PERIOD (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
442 	#define TRC_HWTC_DIVISOR 4
443 	#define TRC_HWTC_FREQ_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC
444 	#define TRC_IRQ_PRIORITY_ORDER 0 // Lower IRQ priority values are more significant
445 
446 	#define TRC_PORT_SPECIFIC_INIT()
447 
448 #elif ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XTensa_LX6) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XTensa_LX7))
449 	/**
450 	 * @note	When running with SMP FreeRTOS we cannot use the CCOUNT register for timestamping,
451 	 * 			instead we use the external 40MHz timer for synchronized timestamping between the cores.
452 	 */
453 	#if CONFIG_FREERTOS_UNICORE == 1
454 		#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
455 		#define TRC_HWTC_COUNT ({ unsigned int __ccount; 			\
456 			__asm__ __volatile__("rsr.ccount %0" : "=a"(__ccount)); \
457 			__ccount; })
458 #ifdef CONFIG_IDF_TARGET_ESP32
459 		#define TRC_HWTC_FREQ_HZ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000)
460 #elif defined(CONFIG_IDF_TARGET_ESP32S2)
461 		#define TRC_HWTC_FREQ_HZ (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000)
462 #else
463 		#error "Invalid IDF target, check your sdkconfig."
464 #endif
465 		#define TRC_HWTC_PERIOD 0
466 		#define TRC_HWTC_DIVISOR 4
467 		#define TRC_IRQ_PRIORITY_ORDER 0
468 	#else
469 		/**
470 		 * @brief 	Fetch core agnostic timestamp using the external 40MHz timer. This is used by tracerecorder
471 		 * 			when running with both cores.
472 		 *
473 		 * @return 	Ticks since the timer started
474 		 */
475 		uint32_t prvGetSMPTimestamp();
476 
477 		#define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR
478 		#define TRC_HWTC_COUNT prvGetSMPTimestamp()
479 		#define TRC_HWTC_FREQ_HZ 40000000
480 		#define TRC_HWTC_PERIOD 0
481 		#define TRC_HWTC_DIVISOR 4
482 		#define TRC_IRQ_PRIORITY_ORDER 0
483 	#endif
484 
485 	#if !defined(TRC_HWTC_FREQ_HZ)
486 		#error "The XTensa LX6/LX7 trace hardware clock frequency is not defined."
487 	#endif
488 
489 
490 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4)
491 
492     /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */
493 
494     #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR
495     //#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING
496     #define TRC_HWTC_COUNT PIT.TIMER[configTICK_PIT_CHANNEL].CVAL.R // must be the PIT channel used for the systick
497     #define TRC_HWTC_PERIOD ((configPIT_CLOCK_HZ / configTICK_RATE_HZ) - 1U) // TODO FIXME or maybe not -1? what's the right "period" value?
498     #define TRC_HWTC_FREQ_HZ configPIT_CLOCK_HZ
499     #define TRC_HWTC_DIVISOR 1
500     #define TRC_IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant
501 
502 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_APPLICATION_DEFINED)
503 
504 	#if !( defined (TRC_HWTC_TYPE) && defined (TRC_HWTC_COUNT) && defined (TRC_HWTC_PERIOD) && defined (TRC_HWTC_FREQ_HZ) && defined (TRC_IRQ_PRIORITY_ORDER) )
505 		#error "The hardware port is not completely defined!"
506 	#endif
507 
508 #elif (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET)
509 
510 	#error "TRC_CFG_HARDWARE_PORT had unsupported value!"
511 	#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET
512 
513 #endif
514 
515 #ifndef TRC_HWTC_DIVISOR
516 	#define TRC_HWTC_DIVISOR 1
517 #endif
518 
519 #ifndef TRC_PORT_SPECIFIC_INIT
520 	#define TRC_PORT_SPECIFIC_INIT()
521 #endif
522 
523 /* If Win32 port */
524 #ifdef WIN32
525 
526 	#undef _WIN32_WINNT
527 	#define _WIN32_WINNT 0x0600
528 
529 	/* Standard includes. */
530 	#include <stdio.h>
531 	#include <windows.h>
532 	#include <direct.h>
533 
534     /***************************************************************************
535     * The Win32 port by default saves the trace to file and then kills the
536     * program when the recorder is stopped, to facilitate quick, simple tests
537     * of the recorder.
538     ***************************************************************************/
539 	#define WIN32_PORT_SAVE_WHEN_STOPPED 1
540 	#define WIN32_PORT_EXIT_WHEN_STOPPED 1
541 
542 #endif
543 
544 #if (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET)
545 
546 	#ifndef TRC_HWTC_TYPE
547 	#error "TRC_HWTC_TYPE is not set!"
548 	#endif
549 
550 	#ifndef TRC_HWTC_COUNT
551 	#error "TRC_HWTC_COUNT is not set!"
552 	#endif
553 
554 	#ifndef TRC_HWTC_PERIOD
555 	#error "TRC_HWTC_PERIOD is not set!"
556 	#endif
557 
558 	#ifndef TRC_HWTC_DIVISOR
559 	#error "TRC_HWTC_DIVISOR is not set!"
560 	#endif
561 
562 	#ifndef TRC_IRQ_PRIORITY_ORDER
563 	#error "TRC_IRQ_PRIORITY_ORDER is not set!"
564 	#elif (TRC_IRQ_PRIORITY_ORDER != 0) && (TRC_IRQ_PRIORITY_ORDER != 1)
565 	#error "TRC_IRQ_PRIORITY_ORDER has bad value!"
566 	#endif
567 
568 	#if (TRC_HWTC_DIVISOR < 1)
569 	#error "TRC_HWTC_DIVISOR must be a non-zero positive value!"
570 	#endif
571 
572 	#ifndef TRC_HWTC_FREQ_HZ
573 	#error "TRC_HWTC_FREQ_HZ not defined!"
574 	#endif
575 
576 #endif
577 
578 #endif /*TRC_SNAPSHOT_HARDWARE_PORT_H*/
579