TC capture problem with AT91SAM7S256

Hello,

I’m having problems using the TC (Timer Counter) functionality on AT91SAM7S256. In order to read in a PWM-signal, I want to use the “capture” function of TC. As input pin, I want to use only TIOA and try not to use TIOB, as I need this pin for other purposes.

I use the following code for initialisation and for interrupt handling:

Init:

//interrupts

AT91C_BASE_PIOA->PIO_PDR = PWM_input;

AT91C_BASE_PIOA->PIO_BSR = PWM_input;

AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC2);

AT91C_BASE_TCB->TCB_BCR = 0;

AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | AT91C_TC_ETRGEDG_NONE | AT91C_TC_LDRA_RISING | AT91C_TC_LDRB_FALLING;

AT91C_BASE_TC2->TC_RC = 0xFFFF;

//init interrupts: activate interrupt on load RA and RB

AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_TC2);

AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC2] = (unsigned long) interrupt_handler_TC2;

AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC2] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;

AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_TC2);

AT91C_BASE_TC2->TC_IER = AT91C_TC_LDRAS | AT91C_TC_LDRBS;

//start TC and interrupts

AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;

AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_TC2);

Interrupt handler:

void interrupt_handler_TC2 (void)

{

unsigned int TC_status;

static unsigned int r_a;

static unsigned int r_b;

TC_status = AT91C_BASE_TC2->TC_SR;

if ((TC_status & AT91C_TC_LDRAS) == AT91C_TC_LDRAS )

r_a = AT91C_BASE_TC2->TC_RA;

if ((TC_status & AT91C_TC_LDRBS) == AT91C_TC_LDRBS ){

r_b = AT91C_BASE_TC2->TC_RB;

PWM_ouput = r_b – r_a;

}

}

So here’s my problem: first of all, I cannot read out the duty cycle of my PWM-signal.

I verified with an oscilloscope that the PWM-signal is OK. Next, I found out that the interrupts for “load ra” and “load rb” fire too often. I would expect them to appear only at the edges of the PWM-signal, but these two interrupts are in fact also triggered many many times when the PWM-signal is on a perfect low-level.

For testing purposes, I set the interrupt to different sources, CPCS (compare RC) and COVFS (overflow TC counter); both these interrupts occur only when they should happen, in contradiction to “load ra” and “load rb”.

Any idea why that happens? If you don’t want to write long answers but have working code with capture-functions, it would be very helpful if you could send me the appropriate sections.

Thanks,

chris