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