1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00

AVR32 timer interrupt on match bugfix

This commit is contained in:
Bogdan Marinescu 2011-11-30 23:34:56 +02:00
parent 8b60c5f44b
commit 583191e697
2 changed files with 3 additions and 45 deletions

View File

@ -587,21 +587,21 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data )
int platform_s_timer_set_match_int( unsigned id, timer_data_type period_us, int type )
{
volatile avr32_tc_t *tc = &AVR32_TC;
u32 final;
u64 final;
if( period_us == 0 )
{
tc->channel[ id ].CMR.waveform.wavsel = TC_WAVEFORM_SEL_UP_MODE;
return PLATFORM_TIMER_INT_OK;
}
final = ( u32 )( ( u64 )( platform_timer_get_clock( id ) * period_us ) / 1000000 );
final = ( u64 )platform_timer_get_clock( id ) * period_us / 1000000;
if( final == 0 )
return PLATFORM_TIMER_INT_TOO_SHORT;
if( final > 0xFFFF )
return PLATFORM_TIMER_INT_TOO_LONG;
tc_stop( tc, id );
tc->channel[ id ].CMR.waveform.wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER;
tc->channel[ id ].rc = final;
tc->channel[ id ].rc = ( u32 )final;
avr32_timer_int_periodic_flag[ id ] = type;
tc_start( tc, id );
return PLATFORM_TIMER_INT_OK;

View File

@ -78,22 +78,13 @@ static void tmr_match_common_handler( int id )
volatile avr32_tc_t *tc = &AVR32_TC;
tc_read_sr( tc, id ); // clear interrupt
// When VTMR_CH == 2, which is the usual case,
// its interrupt is handled separately below.
#if VTMR_CH != 2
if( id == VTMR_CH )
{
cmn_virtual_timer_cb();
platform_eth_timer_handler();
}
else
#endif
cmn_int_handler( INT_TMR_MATCH, id );
// VTMR is set as CYCLIC, so the VTMR-specific interrupt routine below
// will not need to do the following.
if( avr32_timer_int_periodic_flag[ id ] != PLATFORM_TIMER_INT_CYCLIC )
{
tc->channel[ id ].IDR.cpcs = 1;
@ -111,43 +102,10 @@ __attribute__((__interrupt__)) static void tmr1_int_handler()
tmr_match_common_handler( 1 );
}
// The Virtual timer interrupt os usually 2 on AVR32, so if it is,
// we handle it separately in its on routine. If not, call the
// generic timer handler routine for timer 2.
__attribute__((__interrupt__)) static void tmr2_int_handler()
{
#if VTMR_CH != 2
// Timer 2 is not the virtual timer, so handle it normally
tmr_match_common_handler( 2 );
#else
// Virtual timer/systick interrupt on timer 2
volatile avr32_tc_t *tc = &AVR32_TC;
# ifdef FOSC32
// With FOSC32, the virtual timer interrupts VTMR_FREQ_HZ times a second
// so call the once-per-tick routines
cmn_virtual_timer_cb();
platform_eth_timer_handler();
# else
// With no FOSC32, the VTMR timer runs at REQ_PBA_FREQ/128 = 128906.25hz.
// We divide this down and only call the routines every 1/VTMR_FREQ_HZ
// of a second
# define DIVIDER (REQ_PBA_FREQ / 128 / VTMR_FREQ_HZ)
static unsigned stride = DIVIDER; // Divider counter
if (--stride == 0 )
{
cmn_virtual_timer_cb();
platform_eth_timer_handler();
stride = DIVIDER;
}
# undef DIVIDER
#endif
tc_read_sr( tc, VTMR_CH ); // clear interrupt
}
#endif
// ----------------------------------------------------------------------------
// GPIO interrupts and helpers