mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-14 16:57:41 -04:00
* 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.
724 lines
31 KiB
C
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*/
|