# HG changeset patch # User jld # Date 1292791760 0 # Node ID 790fa8c690f453e52c886c5732c517a94c4e3f95 # Parent 2155db30673470124c229457ce875060bab332fa * src/timer_tc.c: Implement a profiling timer on TC1. * cdl/hal_arm_at91.cdl: Add CDL option to enable the profiling timer. diff --git a/packages/hal/arm/at91/var/current/ChangeLog b/packages/hal/arm/at91/var/current/ChangeLog --- a/packages/hal/arm/at91/var/current/ChangeLog +++ b/packages/hal/arm/at91/var/current/ChangeLog @@ -1,3 +1,8 @@ +2010-12-17 John Dallaway + + * src/timer_tc.c: Implement a profiling timer on TC1. + * cdl/hal_arm_at91.cdl: Add CDL option to enable the profiling timer. + 2010-05-27 ccoutand * include/var_io.h: Added ADC defines for AT91_M55800A CPU @@ -477,7 +482,7 @@ 2001-07-16 Gary Thomas // Register state info #include // necessary? +#ifdef CYGFUN_HAL_ARM_AT91_PROFILE_TIMER +#include // CYG_ISR_HANDLED +#include // __profile_hit() +#endif + // ------------------------------------------------------------------------- // Clock support @@ -158,4 +163,57 @@ void hal_delay_us(cyg_int32 usecs) } while ((stat & AT91_TC_SR_CPC) == 0); } +#ifdef CYGFUN_HAL_ARM_AT91_PROFILE_TIMER + +// Use TC1 for profiling +#define AT91_TC_PROFILE AT91_TC_TC1 +#define HAL_INTERRUPT_PROFILE CYGNUM_HAL_INTERRUPT_TIMER1 + +// Profiling timer ISR +static cyg_uint32 profile_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data, HAL_SavedRegisters *regs) +{ + cyg_uint32 status; + + HAL_READ_UINT32(AT91_TC+AT91_TC_PROFILE+AT91_TC_SR, status); // Clear interrupt + HAL_INTERRUPT_ACKNOWLEDGE(HAL_INTERRUPT_PROFILE); + __profile_hit(regs->pc); + return CYG_ISR_HANDLED; +} + +// Profiling timer setup +int hal_enable_profile_timer(int resolution) +{ + cyg_uint32 period; + + // Calculate how many timer ticks the requested resolution in + // microseconds equates to. We do this calculation in 64 bit + // arithmetic to avoid overflow. + period = (cyg_uint32)((((cyg_uint64)resolution) * + ((cyg_uint64)CYGNUM_HAL_ARM_AT91_CLOCK_SPEED))/32000000LL); + + CYG_ASSERT(period < 0x10000, "Invalid profile timer resolution"); // 16 bits only + + // Attach ISR + HAL_INTERRUPT_ATTACH(HAL_INTERRUPT_PROFILE, &profile_isr, 0x1111, 0); + HAL_INTERRUPT_UNMASK(HAL_INTERRUPT_PROFILE); + + // Disable counter + HAL_WRITE_UINT32(AT91_TC+AT91_TC_PROFILE+AT91_TC_CCR, AT91_TC_CCR_CLKDIS); + + // Set registers + HAL_WRITE_UINT32(AT91_TC+AT91_TC_PROFILE+AT91_TC_CMR, AT91_TC_CMR_CPCTRG | // Reset counter on CPC + AT91_TC_CMR_CLKS_MCK32); // Use MCLK/32 + HAL_WRITE_UINT32(AT91_TC+AT91_TC_PROFILE+AT91_TC_RC, period); + + // Start timer + HAL_WRITE_UINT32(AT91_TC+AT91_TC_PROFILE+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN); + + // Enable timer interrupt + HAL_WRITE_UINT32(AT91_TC+AT91_TC_PROFILE+AT91_TC_IER, AT91_TC_IER_CPC); + + return resolution; +} + +#endif // CYGFUN_HAL_ARM_AT91_PROFILE_TIMER + // timer_tc.c