/* * Trace Recorder for Tracealyzer v4.6.6 * Copyright 2021 Percepio AB * www.percepio.com * * SPDX-License-Identifier: Apache-2.0 * * The hardware abstraction layer for the trace recorder. */ #ifndef TRC_HARDWARE_PORT_H #define TRC_HARDWARE_PORT_H #include /* * @brief * This macro must be used as name for the variable in the critical section allocation. * Example: #define TRACE_ALLOC_CRITICAL_SECION uint32_t TRACE_ALLOC_CRITICAL_SECTION_NAME; */ #define TRACE_ALLOC_CRITICAL_SECTION_NAME xTraceCriticalSectionStatus #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET) #error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h" #endif /******************************************************************************* * TRC_IRQ_PRIORITY_ORDER * * Macro which should be defined as an integer of 0 or 1. * * This should be 0 if lower IRQ priority values implies higher priority * levels, such as on ARM Cortex M. If the opposite scheme is used, i.e., * if higher IRQ priority values means higher priority, this should be 1. * * This setting is not critical. It is used only to sort and colorize the * interrupts in priority order, in case you record interrupts using * the vTraceStoreISRBegin and vTraceStoreISREnd routines. * ****************************************************************************** * * HWTC Macros * * These macros provides a hardware isolation layer representing the * hardware timer/counter used for the event timestamping. * * TRC_HWTC_COUNT: How to read the current value of the timer/counter. * * TRC_HWTC_TYPE: Tells the type of timer/counter used for TRC_HWTC_COUNT: * * - TRC_FREE_RUNNING_32BIT_INCR: * Free-running 32-bit timer/counter, counting upwards from 0. * * - TRC_FREE_RUNNING_32BIT_DECR * Free-running 32-bit timer/counter, counting downwards from 0xFFFFFFFF. * * - TRC_OS_TIMER_INCR * Periodic timer that drives the OS tick interrupt, counting upwards * from 0 until (TRC_HWTC_PERIOD-1). * * - TRC_OS_TIMER_DECR * Periodic timer that drives the OS tick interrupt, counting downwards * from TRC_HWTC_PERIOD-1 until 0. * * - TRC_CUSTOM_TIMER_INCR * A custom timer or counter independent of the OS tick, counting * downwards from TRC_HWTC_PERIOD-1 until 0. (Currently only supported * in streaming mode). * * - TRC_CUSTOM_TIMER_DECR * A custom timer independent of the OS tick, counting downwards * from TRC_HWTC_PERIOD-1 until 0. (Currently only supported * in streaming mode). * * TRC_HWTC_PERIOD: The number of HWTC_COUNT ticks until the timer wraps * around. If using TRC_FREE_RUNNING_32BIT_INCR/DECR, this should be 0. * * TRC_HWTC_FREQ_HZ: The clock rate of the TRC_HWTC_COUNT counter in Hz. If using * TRC_OS_TIMER_INCR/DECR, this is should be TRC_HWTC_PERIOD * TRC_TICK_RATE_HZ. * If using a free-running timer, this is often TRACE_CPU_CLOCK_HZ (if running at * the core clock rate). If using TRC_CUSTOM_TIMER_INCR/DECR, this should match * the clock rate of your custom timer (i.e., TRC_HWTC_COUNT). If the default value * of TRC_HWTC_FREQ_HZ is incorrect for your setup, you can override it by calling * vTraceSetFrequency before calling vTraceEnable. * * TRC_HWTC_DIVISOR (used in snapshot mode only): * In snapshot mode, the timestamp resolution is TRC_HWTC_FREQ_HZ/TRC_HWTC_DIVISOR. * If the timer frequency is very high (hundreds of MHz), we recommend increasing * the TRC_HWTC_DIVISOR prescaler, to reduce the bandwidth needed to store * timestamps. This since extra "XTS" events are inserted if the time since the * previous event exceeds a certain limit (255 or 65535 depending on event type). * It is advised to keep the time between most events below 65535 native ticks * (after division by TRC_HWTC_DIVISOR) to avoid frequent XTS events. ******************************************************************************/ #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NOT_SET) #error "TRC_CFG_HARDWARE_PORT not selected - see trcConfig.h" #endif #if (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32) /* This can be used as a template for any free-running 32-bit counter */ void vTraceTimerReset(void); uint32_t uiTraceTimerGetFrequency(void); uint32_t uiTraceTimerGetValue(void); #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT ((TraceUnsignedBaseType_t)uiTraceTimerGetValue()) #define TRC_HWTC_PERIOD 0 #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ ((TraceUnsignedBaseType_t)uiTraceTimerGetFrequency()) #define TRC_IRQ_PRIORITY_ORDER 1 #define TRC_PORT_SPECIFIC_INIT() vTraceTimerReset() #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win64) /* This can be used as a template for any free-running 32-bit counter */ void vTraceTimerReset(void); uint32_t uiTraceTimerGetFrequency(void); uint32_t uiTraceTimerGetValue(void); #define TRC_BASE_TYPE int64_t #define TRC_UNSIGNED_BASE_TYPE uint64_t #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT ((TraceUnsignedBaseType_t)uiTraceTimerGetValue()) #define TRC_HWTC_PERIOD 0 #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ ((TraceUnsignedBaseType_t)uiTraceTimerGetFrequency()) #define TRC_IRQ_PRIORITY_ORDER 1 #define TRC_PORT_SPECIFIC_INIT() vTraceTimerReset() #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_HWIndependent) /* Timestamping by OS tick only (typically 1 ms resolution) */ #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT 0 #define TRC_HWTC_PERIOD 1 #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ TRC_TICK_RATE_HZ /* Set the meaning of IRQ priorities in ISR tracing - see above */ #define TRC_IRQ_PRIORITY_ORDER NOT_SET #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_Cortex_M) #ifndef __CORTEX_M #error "Can't find the CMSIS API. Please include your processor's header file in trcConfig.h" #endif #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t TRACE_ALLOC_CRITICAL_SECTION_NAME; #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 */ #define TRACE_EXIT_CRITICAL_SECTION() {__set_PRIMASK(TRACE_ALLOC_CRITICAL_SECTION_NAME);} /************************************************************************** * For Cortex-M3, M4 and M7, the DWT cycle counter is used for timestamping. * For Cortex-M0 and M0+, the SysTick timer is used since DWT is not * available. Systick timestamping can also be forced on Cortex-M3, M4 and * M7 by defining the preprocessor directive TRC_CFG_ARM_CM_USE_SYSTICK, * either directly below or in trcConfig.h. * * #define TRC_CFG_ARM_CM_USE_SYSTICK **************************************************************************/ #if ((__CORTEX_M >= 0x03) && (! defined TRC_CFG_ARM_CM_USE_SYSTICK)) void xTraceHardwarePortInitCortexM(void); #define TRC_REG_DEMCR (*(volatile uint32_t*)0xE000EDFC) #define TRC_REG_DWT_CTRL (*(volatile uint32_t*)0xE0001000) #define TRC_REG_DWT_CYCCNT (*(volatile uint32_t*)0xE0001004) #define TRC_REG_DWT_EXCCNT (*(volatile uint32_t*)0xE000100C) #define TRC_REG_ITM_LOCKACCESS (*(volatile uint32_t*)0xE0001FB0) #define TRC_ITM_LOCKACCESS_UNLOCK (0xC5ACCE55) /* Bit mask for TRCENA bit in DEMCR - Global enable for DWT and ITM */ #define TRC_DEMCR_TRCENA (1 << 24) /* Bit mask for NOPRFCNT bit in DWT_CTRL. If 1, DWT_EXCCNT is not supported */ #define TRC_DWT_CTRL_NOPRFCNT (1 << 24) /* Bit mask for NOCYCCNT bit in DWT_CTRL. If 1, DWT_CYCCNT is not supported */ #define TRC_DWT_CTRL_NOCYCCNT (1 << 25) /* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_EXCCNT */ #define TRC_DWT_CTRL_EXCEVTENA (1 << 18) /* Bit mask for EXCEVTENA_ bit in DWT_CTRL. Set to 1 to enable DWT_CYCCNT */ #define TRC_DWT_CTRL_CYCCNTENA (1) #define TRC_PORT_SPECIFIC_INIT() xTraceHardwarePortInitCortexM() #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT TRC_REG_DWT_CYCCNT #define TRC_HWTC_PERIOD 0 #define TRC_HWTC_DIVISOR 4 #define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ #define TRC_IRQ_PRIORITY_ORDER 0 #else #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR #define TRC_HWTC_COUNT (*((volatile uint32_t*)0xE000E018)) #define TRC_HWTC_PERIOD ((*((volatile uint32_t*)0xE000E014)) + 1) #define TRC_HWTC_DIVISOR 4 #define TRC_HWTC_FREQ_HZ TRACE_CPU_CLOCK_HZ #define TRC_IRQ_PRIORITY_ORDER 0 #endif #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600) #define TRACE_ALLOC_CRITICAL_SECTION() TraceBaseType_t TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() { TRACE_ALLOC_CRITICAL_SECTION_NAME = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); } #define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(TRACE_ALLOC_CRITICAL_SECTION_NAME); } #include #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT (CMT0.CMCNT) #elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT) /* Decreasing counters better for Tickless Idle? */ #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR #define TRC_HWTC_COUNT (CMT0.CMCOR - CMT0.CMCNT) #endif #define TRC_HWTC_PERIOD (CMT0.CMCOR + 1) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 1 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_MICROCHIP_PIC24_PIC32) #define TRACE_ALLOC_CRITICAL_SECTION() TraceBaseType_t TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() { TRACE_ALLOC_CRITICAL_SECTION_NAME = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); } #define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(TRACE_ALLOC_CRITICAL_SECTION_NAME); } #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT (TMR1) #define TRC_HWTC_PERIOD (PR1 + 1) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 1 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_TMS570_RM48) #define TRC_RTIFRC0 *((uint32_t *)0xFFFFFC10) #define TRC_RTICOMP0 *((uint32_t *)0xFFFFFC50) #define TRC_RTIUDCP0 *((uint32_t *)0xFFFFFC54) #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT (TRC_RTIFRC0 - (TRC_RTICOMP0 - TRC_RTIUDCP0)) #define TRC_HWTC_PERIOD (TRC_RTIUDCP0) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_AT91SAM7) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT ((uint32_t)(AT91C_BASE_PITC->PITC_PIIR & 0xFFFFF)) #define TRC_HWTC_PERIOD ((uint32_t)(AT91C_BASE_PITC->PITC_PIMR + 1)) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 1 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Atmel_UC3A0) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO*/ /* For Atmel AVR32 (AT32UC3A) */ #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT ((uint32_t)sysreg_read(AVR32_COUNT)) #define TRC_HWTC_PERIOD ((uint32_t)(sysreg_read(AVR32_COMPARE) + 1)) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 1 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_NXP_LPC210X) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* Tested with LPC2106, but should work with most LPC21XX chips. */ #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT *((uint32_t *)0xE0004008 ) #define TRC_HWTC_PERIOD *((uint32_t *)0xE0004018 ) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_TEXAS_INSTRUMENTS_MSP430) /* UNOFFICIAL PORT - NOT YET VERIFIED */ #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT (TA0R) #define TRC_HWTC_PERIOD (((uint16_t)TACCR0)+1) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 1 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC405) /* UNOFFICIAL PORT - NOT YET VERIFIED */ #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR #define TRC_HWTC_COUNT mfspr(0x3db) #define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRC_TICK_RATE_HZ) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_PPC440) /* UNOFFICIAL PORT */ /* This should work with most PowerPC chips */ #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR #define TRC_HWTC_COUNT mfspr(0x016) #define TRC_HWTC_PERIOD (TRACE_CPU_CLOCK_HZ / TRC_TICK_RATE_HZ) #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_MICROBLAZE) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ /* This should work with most Microblaze configurations. * It uses the AXI Timer 0 - the tick interrupt source. * If an AXI Timer 0 peripheral is available on your hardware platform, no modifications are required. */ #include #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR #define TRC_HWTC_COUNT XTmrCtr_GetTimerCounterReg( XPAR_TMRCTR_0_BASEADDR, 0 ) #define TRC_HWTC_PERIOD (XTmrCtr_GetLoadReg( XPAR_TMRCTR_0_BASEADDR, 0) + 1) #define TRC_HWTC_DIVISOR 16 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XILINX_ZyncUltraScaleR5) extern int cortex_a9_r5_enter_critical(void); extern void cortex_a9_r5_exit_critical(int irq_already_masked_at_enter); #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() { TRACE_ALLOC_CRITICAL_SECTION_NAME = cortex_a9_r5_enter_critical(); } #define TRACE_EXIT_CRITICAL_SECTION() { cortex_a9_r5_exit_critical(TRACE_ALLOC_CRITICAL_SECTION_NAME); } #include #define TRC_HWTC_TYPE TRC_OS_TIMER_INCR #define TRC_HWTC_COUNT (*(volatile uint32_t *)(configTIMER_BASEADDR + XTTCPS_COUNT_VALUE_OFFSET)) #define TRC_HWTC_PERIOD (*(volatile uint32_t *)(configTIMER_BASEADDR + XTTCPS_INTERVAL_VAL_OFFSET)) #define TRC_HWTC_DIVISOR 16 #define TRC_HWTC_FREQ_HZ (TRC_HWTC_PERIOD * TRC_TICK_RATE_HZ) #define TRC_IRQ_PRIORITY_ORDER 0 #ifdef __GNUC__ /* For Arm Cortex-A and Cortex-R in general. */ static inline uint32_t prvGetCPSR(void) { unsigned long ret; /* GCC-style assembly for getting the CPSR/APSR register, where the system execution mode is found. */ asm volatile (" mrs %0, cpsr" : "=r" (ret) : /* no inputs */ ); return ret; } #else #error "Only GCC Supported!" #endif #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII) /* OFFICIAL PORT */ #include #include #include #define TRACE_ALLOC_CRITICAL_SECTION() alt_irq_context TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION(){TRACE_ALLOC_CRITICAL_SECTION_NAME = alt_irq_disable_all();} #define TRACE_EXIT_CRITICAL_SECTION() {alt_irq_enable_all(TRACE_ALLOC_CRITICAL_SECTION_NAME);} #define NOT_SET 1 /* The base address for the sustem timer set. * The name user for the system timer can be found in the BSP editor. * If the name of the timer is sys_tmr SYSTEM_TIMER_BASE should be set to SYS_TMR_BASE. */ #define SYSTEM_TIMER_BASE NOT_SET #if (SYSTEM_TIMER == NOT_SET) #error "Set SYSTEM_TIMER_BASE to the timer base used for system ticks." #endif static inline uint32_t altera_nios2_GetTimerSnapReg(void) { /* A processor can read the current counter value by first writing to either snapl or snaph to request a coherent snapshot of the counter, * and then reading snapl and snaph for the full 32-bit value. */ IOWR_ALTERA_AVALON_TIMER_SNAPL(SYSTEM_TIMER_BASE, 0); return (IORD_ALTERA_AVALON_TIMER_SNAPH(SYSTEM_TIMER_BASE) << 16) | IORD_ALTERA_AVALON_TIMER_SNAPL(SYSTEM_TIMER_BASE); } #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR #define TRC_HWTC_COUNT altera_nios2_GetTimerSnapReg() #define TRC_HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define TRC_HWTC_DIVISOR 16 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ARM_CORTEX_A9) /************************************************************************** * This hardware port only supports FreeRTOS and the GCC compiler at the * moment, due to the implementation of critical sections (trcKernelPort.h). * * Assuming FreeRTOS is used: * * For critical sections, this uses vTaskEnterCritical is when called from * task context and ulPortSetInterruptMask when called from ISR context. * Thus, it does not disable all ISRs. This means that the trace recorder * can only be called from ISRs with priority less or equal to * configMAX_API_CALL_INTERRUPT_PRIORITY (like FreeRTOS fromISR functions). * * This hardware port has been tested on it a Xilinx Zync 7000 (Cortex-A9), * but should work with all Cortex-A and R processors assuming that * TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS is set accordingly. **************************************************************************/ extern int cortex_a9_r5_enter_critical(void); extern void cortex_a9_r5_exit_critical(int irq_already_masked_at_enter); #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() { TRACE_ALLOC_CRITICAL_SECTION_NAME = cortex_a9_r5_enter_critical(); } #define TRACE_EXIT_CRITICAL_SECTION() { cortex_a9_r5_exit_critical(TRACE_ALLOC_CRITICAL_SECTION_NAME); } /* INPUT YOUR PERIPHERAL BASE ADDRESS HERE (0xF8F00000 for Xilinx Zynq 7000)*/ #define TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS 0 #if (TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS == 0) #error "Please specify TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS." #endif #define TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET 0x0600 #define TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x00)) #define TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x04)) #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_REG (*(volatile uint32_t*)(TRC_CA9_MPCORE_PERIPHERAL_BASE_ADDRESS + TRC_CA9_MPCORE_PRIVATE_MEMORY_OFFSET + 0x08)) #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_MASK 0x0000FF00 #define TRC_CA9_MPCORE_PRIVCTR_CONTROL_PRESCALER_SHIFT 8 #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) #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR #define TRC_HWTC_COUNT TRC_CA9_MPCORE_PRIVCTR_COUNTER_REG #define TRC_HWTC_PERIOD (TRC_CA9_MPCORE_PRIVCTR_PERIOD_REG + 1) /**************************************************************************************** NOTE: The private timer ticks with a very high frequency (half the core-clock usually), depending on the prescaler used. If a low prescaler is used, the number of HW ticks between the trace events gets large, and thereby inefficient to store (sometimes extra events are needed). To improve efficiency, you may use the TRC_HWTC_DIVISOR as an additional prescaler. *****************************************************************************************/ #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (TRC_TICK_RATE_HZ * TRC_HWTC_PERIOD) #define TRC_IRQ_PRIORITY_ORDER 0 #ifdef __GNUC__ /* For Arm Cortex-A and Cortex-R in general. */ static inline uint32_t prvGetCPSR(void) { unsigned long ret; /* GCC-style assembly for getting the CPSR/APSR register, where the system execution mode is found. */ asm volatile (" mrs %0, cpsr" : "=r" (ret) : /* no inputs */ ); return ret; } #else #error "Only GCC Supported!" #endif #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_CYCLONE_V_HPS) #include "alt_clock_manager.h" extern int cortex_a9_r5_enter_critical(void); extern void cortex_a9_r5_exit_critical(int irq_already_masked_at_enter); #define TRACE_ALLOC_CRITICAL_SECTION() uint32_t TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() { TRACE_ALLOC_CRITICAL_SECTION_NAME = cortex_a9_r5_enter_critical(); } #define TRACE_EXIT_CRITICAL_SECTION() { cortex_a9_r5_exit_critical(TRACE_ALLOC_CRITICAL_SECTION_NAME); } #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT *((uint32_t *)0xFFFEC200) #define TRC_HWTC_PERIOD 0 #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ (({ \ uint32_t __freq; \ alt_clk_freq_get( ALT_CLK_MPU_PERIPH, &__freq ); \ __freq; \ })) #define TRC_IRQ_PRIORITY_ORDER 0 #ifdef __GNUC__ /* For Arm Cortex-A and Cortex-R in general. */ static inline uint32_t prvGetCPSR(void) { unsigned long ret; /* GCC-style assembly for getting the CPSR/APSR register, where the system execution mode is found. */ __asm__ __volatile__(" mrs %0, cpsr" : "=r" (ret) : /* no inputs */ ); return ret; } #else #error "Only GCC Supported!" #endif #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ZEPHYR) #define TRACE_ALLOC_CRITICAL_SECTION() int TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() { TRACE_ALLOC_CRITICAL_SECTION_NAME = irq_lock(); } #define TRACE_EXIT_CRITICAL_SECTION() { irq_unlock(TRACE_ALLOC_CRITICAL_SECTION_NAME); } #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT k_cycle_get_32() #define TRC_HWTC_PERIOD (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) #define TRC_HWTC_DIVISOR 4 #define TRC_HWTC_FREQ_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC #define TRC_IRQ_PRIORITY_ORDER 0 // Lower IRQ priority values are more significant #define TRC_PORT_SPECIFIC_INIT() #elif ((TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XTensa_LX6) || (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XTensa_LX7)) /** * @note When running with SMP FreeRTOS we cannot use the CCOUNT register for timestamping, * instead we use the external 40MHz timer for synchronized timestamping between the cores. */ #if CONFIG_FREERTOS_UNICORE == 1 #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT ({ unsigned int __ccount; \ __asm__ __volatile__("rsr.ccount %0" : "=a"(__ccount)); \ __ccount; }) #ifdef CONFIG_IDF_TARGET_ESP32 #define TRC_HWTC_FREQ_HZ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000) #elif defined(CONFIG_IDF_TARGET_ESP32S2) #define TRC_HWTC_FREQ_HZ (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000) #else #error "Invalid IDF target, check your sdkconfig." #endif #define TRC_HWTC_PERIOD 0 #define TRC_HWTC_DIVISOR 4 #define TRC_IRQ_PRIORITY_ORDER 0 #else /** * @brief Fetch core agnostic timestamp using the external 40MHz timer. This is used by tracerecorder * when running with both cores. * * @return Ticks since the timer started */ uint32_t prvGetSMPTimestamp(); #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT prvGetSMPTimestamp() #define TRC_HWTC_FREQ_HZ 40000000 #define TRC_HWTC_PERIOD 0 #define TRC_HWTC_DIVISOR 4 #define TRC_IRQ_PRIORITY_ORDER 0 #endif #if !defined(TRC_HWTC_FREQ_HZ) #error "The XTensa LX6/LX7 trace hardware clock frequency is not defined." #endif #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_RISCV_RV32I) #define TRACE_ALLOC_CRITICAL_SECTION() unsigned int TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() __asm__ __volatile__("csrr %0, mstatus \n\t" \ "csrci mstatus, 8 \n\t" \ "andi %0, %0, 8 \n\t" \ : "=r"(TRACE_ALLOC_CRITICAL_SECTION_NAME)) #define TRACE_EXIT_CRITICAL_SECTION() __asm__ __volatile__("csrr a1, mstatus \n\t" \ "or %0, %0, a1 \n\t" \ "csrs mstatus, %0 \n\t" \ : \ : "r" (TRACE_ALLOC_CRITICAL_SECTION_NAME) \ : "a1") #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT ({ unsigned int __count; \ __asm__ __volatile__("rdcycle %0" : "=r"(__count)); \ __count; }) #define TRC_HWTC_PERIOD 0 #define TRC_HWTC_DIVISOR 1 #define TRC_HWTC_FREQ_HZ 16000000 #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_XMOS_XCOREAI) #define TRC_PORT_SPECIFIC_INIT() #define TRC_HWTC_TYPE TRC_FREE_RUNNING_32BIT_INCR #define TRC_HWTC_COUNT xscope_gettime() #define TRC_HWTC_PERIOD (configCPU_CLOCK_HZ / configTICK_RATE_HZ ) #define TRC_HWTC_DIVISOR 4 #define TRC_HWTC_FREQ_HZ 100000000 #define TRC_IRQ_PRIORITY_ORDER 0 #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_POWERPC_Z4) /* UNOFFICIAL PORT - NOT YET VERIFIED BY PERCEPIO */ #define TRACE_ALLOC_CRITICAL_SECTION() TraceBaseType_t TRACE_ALLOC_CRITICAL_SECTION_NAME; #define TRACE_ENTER_CRITICAL_SECTION() { TRACE_ALLOC_CRITICAL_SECTION_NAME = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); } #define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK(TRACE_ALLOC_CRITICAL_SECTION_NAME); } #define TRC_HWTC_TYPE TRC_OS_TIMER_DECR //#define HWTC_COUNT_DIRECTION DIRECTION_DECREMENTING #define TRC_HWTC_COUNT PIT.TIMER[configTICK_PIT_CHANNEL].CVAL.R // must be the PIT channel used for the systick #define TRC_HWTC_PERIOD ((configPIT_CLOCK_HZ / configTICK_RATE_HZ) - 1U) // TODO FIXME or maybe not -1? what's the right "period" value? #define TRC_HWTC_FREQ_HZ configPIT_CLOCK_HZ #define TRC_HWTC_DIVISOR 1 #define TRC_IRQ_PRIORITY_ORDER 1 // higher IRQ priority values are more significant #elif (TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_APPLICATION_DEFINED) #if !( defined (TRC_HWTC_TYPE) && defined (TRC_HWTC_COUNT) && defined (TRC_HWTC_PERIOD) && defined (TRC_HWTC_FREQ_HZ) && defined (TRC_IRQ_PRIORITY_ORDER) ) #error "The hardware port is not completely defined!" #endif #elif (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET) #error "TRC_CFG_HARDWARE_PORT had unsupported value!" #define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET #endif #ifndef TRC_HWTC_DIVISOR #define TRC_HWTC_DIVISOR 1 #endif #ifndef TRC_PORT_SPECIFIC_INIT #define TRC_PORT_SPECIFIC_INIT() #endif /* If Win32 port */ #ifdef WIN32 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 /* Standard includes. */ #include #include #include /*************************************************************************** * The Win32 port by default saves the trace to file and then kills the * program when the recorder is stopped, to facilitate quick, simple tests * of the recorder. ***************************************************************************/ #define WIN32_PORT_SAVE_WHEN_STOPPED 1 #define WIN32_PORT_EXIT_WHEN_STOPPED 1 #endif #if (TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET) #ifndef TRC_HWTC_TYPE #error "TRC_HWTC_TYPE is not set!" #endif #ifndef TRC_HWTC_COUNT #error "TRC_HWTC_COUNT is not set!" #endif #ifndef TRC_HWTC_PERIOD #error "TRC_HWTC_PERIOD is not set!" #endif #ifndef TRC_HWTC_DIVISOR #error "TRC_HWTC_DIVISOR is not set!" #endif #ifndef TRC_IRQ_PRIORITY_ORDER #error "TRC_IRQ_PRIORITY_ORDER is not set!" #elif (TRC_IRQ_PRIORITY_ORDER != 0) && (TRC_IRQ_PRIORITY_ORDER != 1) #error "TRC_IRQ_PRIORITY_ORDER has bad value!" #endif #if (TRC_HWTC_DIVISOR < 1) #error "TRC_HWTC_DIVISOR must be a non-zero positive value!" #endif #ifndef TRC_HWTC_FREQ_HZ #error "TRC_HWTC_FREQ_HZ not defined!" #endif #endif #ifndef TRACE_ALLOC_CRITICAL_SECTION #define TRACE_ALLOC_CRITICAL_SECTION() TRC_KERNEL_PORT_ALLOC_CRITICAL_SECTION() #endif #ifndef TRACE_ENTER_CRITICAL_SECTION #define TRACE_ENTER_CRITICAL_SECTION() TRC_KERNEL_PORT_ENTER_CRITICAL_SECTION() #endif #ifndef TRACE_EXIT_CRITICAL_SECTION #define TRACE_EXIT_CRITICAL_SECTION() TRC_KERNEL_PORT_EXIT_CRITICAL_SECTION() #endif #endif /*TRC_HARDWARE_PORT_H*/