FreeRTOS-Kernel/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include/trcHardwarePort.h
Soren Ptak 3a2f6646f0
Use CI-CD-Github-Actions for spelling and formatting, add in the bot formatting action, update the CI-CD workflow files. Fix incorrect spelling and formatting on files. (#1083)
* Use new version of CI-CD Actions,  checkout@v3 instead of checkout@v2 on all jobs
* Use cSpell spell check, and use ubuntu-20.04 for formatting check
* Add in bot formatting action
* Update freertos_demo.yml and freertos_plus_demo.yml files to increase github log readability
* Add in a Qemu demo onto the workflows.
2023-09-06 12:35:37 -07:00

724 lines
31 KiB
C

/*
* Trace Recorder for Tracealyzer v4.6.0
* 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 <trcDefines.h>
#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 __irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = __get_PRIMASK(); __set_PRIMASK( 1 ); } /* PRIMASK disables ALL interrupts - allows for tracing in any ISR */
#define TRACE_EXIT_CRITICAL_SECTION() { __set_PRIMASK( __irq_status ); }
/**************************************************************************
* 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 /* if ( ( __CORTEX_M >= 0x03 ) && ( !defined TRC_CFG_ARM_CM_USE_SYSTICK ) ) */
#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 /* if ( ( __CORTEX_M >= 0x03 ) && ( !defined TRC_CFG_ARM_CM_USE_SYSTICK ) ) */
#elif ( TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Renesas_RX600 )
#define TRACE_ALLOC_CRITICAL_SECTION() TraceBaseType_t __x_irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __x_irq_status = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); }
#define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK( __x_irq_status ); }
#include <iodefine.h>
#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 /* if ( TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING ) */
#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 __x_irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __x_irq_status = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); }
#define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK( __x_irq_status ); }
#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 <xtmrctr_l.h>
#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 __irq_mask_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __irq_mask_status = cortex_a9_r5_enter_critical(); }
#define TRACE_EXIT_CRITICAL_SECTION() { cortex_a9_r5_exit_critical( __irq_mask_status ); }
#include <xttcps_hw.h>
#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 /* ifdef __GNUC__ */
#elif ( TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Altera_NiosII )
/* OFFICIAL PORT */
#include <system.h>
#include <altera_avalon_timer_regs.h>
#include <sys/alt_irq.h>
#define TRACE_ALLOC_CRITICAL_SECTION() alt_irq_context __irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __irq_status = alt_irq_disable_all(); }
#define TRACE_EXIT_CRITICAL_SECTION() { alt_irq_enable_all( __irq_status ); }
#define NOT_SET 1
/* The base address for the system 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 __irq_mask_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __irq_mask_status = cortex_a9_r5_enter_critical(); }
#define TRACE_EXIT_CRITICAL_SECTION() { cortex_a9_r5_exit_critical( __irq_mask_status ); }
/* 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 /* ifdef __GNUC__ */
#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 __irq_mask_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __irq_mask_status = cortex_a9_r5_enter_critical(); }
#define TRACE_EXIT_CRITICAL_SECTION() { cortex_a9_r5_exit_critical( __irq_mask_status ); }
#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 /* ifdef __GNUC__ */
#elif ( TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_ZEPHYR )
#define TRACE_ALLOC_CRITICAL_SECTION() int key;
#define TRACE_ENTER_CRITICAL_SECTION() { key = irq_lock(); }
#define TRACE_EXIT_CRITICAL_SECTION() { irq_unlock( key ); }
#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 /* if CONFIG_FREERTOS_UNICORE == 1 */
/**
* @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 CONFIG_FREERTOS_UNICORE == 1 */
#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 __irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() \
__asm__ __volatile__ ( "csrr %0, mstatus \n\t"\
"csrci mstatus, 8 \n\t"\
"andi %0, %0, 8 \n\t"\
: "=r" ( __irq_status ) )
#define TRACE_EXIT_CRITICAL_SECTION() \
__asm__ __volatile__ ( "csrr a1, mstatus \n\t"\
"or %0, %0, a1 \n\t"\
"csrs mstatus, %0 \n\t"\
: \
: "r" ( __irq_status ) \
: "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 __x_irq_status;
#define TRACE_ENTER_CRITICAL_SECTION() { __x_irq_status = TRC_KERNEL_PORT_SET_INTERRUPT_MASK(); }
#define TRACE_EXIT_CRITICAL_SECTION() { TRC_KERNEL_PORT_CLEAR_INTERRUPT_MASK( __x_irq_status ); }
#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 /* if ( TRC_CFG_HARDWARE_PORT == TRC_HARDWARE_PORT_Win32 ) */
#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 <stdio.h>
#include <windows.h>
#include <direct.h>
/***************************************************************************
* 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 /* ifdef WIN32 */
#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 /* if ( TRC_CFG_HARDWARE_PORT != TRC_HARDWARE_PORT_NOT_SET ) */
#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_SNAPSHOT_HARDWARE_PORT_H*/