Attiny 1614 Timer D ISR not firing but waveforms look good

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have enabled global interrupts with an sei() command and using the debugger I can see the following lines being executed in the debugger;
 

	TCD0.INTCTRL = 0 << TCD_OVF_bp      /* Overflow interrupt enable: disabled */
	               | 1 << TCD_TRIGA_bp  /* Trigger A interrupt enable: enabled */
	               | 1 << TCD_TRIGB_bp; /* Trigger B interrupt enable: enabled */

 

(from Atmel start)

 

I'm getting the waveform I expect on an output (which indicates the counter is running)  but the ISR is never executed (again provided by Atmel Start):

 

ISR(TCD0_TRIG_vect)
{
      /* Insert your TCD TRIGB interrupt handling code here */

	timeslot = ++timeslot %16;
	
	if (timeslot == ACTIVE_SLOTS)
		CCL.LUT1CTRLA &= ~(1 << CCL_OUTEN_bp);
	
	else if (timeslot == 0)
		CCL.LUT1CTRLA |= (1 << CCL_OUTEN_bp);
		
	/* TRIGB interrupt flag has to be cleared manually */
	TCD0.INTFLAGS = TCD_TRIGB_bm;
}

 

 

Here's the complete Timer D initialization code:

/**
 * \brief Initialize TCD interface
 *
 * \return Initialization status.
 */
int8_t TIMER_2_init()
{

	// Enable Protected register, peripheral must be disabled (ENABLE=0, in TCD.CTRLA).

	// TCD0.CMPASET = 0; /* Compare A Set: 0 */

	TCD0.CMPACLR = 528; /* Compare A Clear: 528 */

	// TCD0.CMPBSET = 0; /* Compare B Set: 0 */

	TCD0.CMPBCLR = 1219; /* Compare B Clear: 1219 */

	// TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc; /* One ramp mode */

	// TCD0.CTRLC = 0 << TCD_AUPDATE_bp /* Auto update: disabled */
	//		 | TCD_CMPCSEL_PWMA_gc /* PWM A output */
	//		 | TCD_CMPDSEL_PWMA_gc /* PWM A output */
	//		 | 0 << TCD_CMPOVR_bp /* Compare output value override: disabled */
	//		 | 0 << TCD_FIFTY_bp; /* Fifty percent waveform: disabled */

	// TCD0.CTRLD = 0 << TCD_CMPAVAL_gp /* Compare A value: 0 */
	//		 | 0 << TCD_CMPBVAL_gp; /* Compare B value: 0 */

	// TCD0.DBGCTRL = 0 << TCD_DBGRUN_bp /* Debug run: disabled */
	//		 | 0 << TCD_FAULTDET_bp; /* Fault detection: disabled */

	// TCD0.DITCTRL = TCD_DITHERSEL_ONTIMEB_gc; /* On-time ramp B */

	// TCD0.DITVAL = 0; /* Dither value: 0 */

	// TCD0.DLYCTRL = TCD_DLYPRESC_DIV1_gc /* No prescaling */
	//		 | TCD_DLYSEL_OFF_gc /* No delay */
	//		 | TCD_DLYTRIG_CMPASET_gc; /* Compare A set */

	// TCD0.DLYVAL = 0 << TCD_DLYVAL_gp; /* Delay value: 0 */

	// TCD0.EVCTRLA = TCD_CFG_NEITHER_gc /* Neither Filter nor Asynchronous Event is enabled */
	//		 | TCD_ACTION_FAULT_gc /* Event trigger a fault */
	//		 | TCD_EDGE_FALL_LOW_gc /* The falling edge or low level of event generates retrigger or fault action */
	//		 | 0 << TCD_TRIGEI_bp; /* Trigger event enable: disabled */

	// TCD0.EVCTRLB = TCD_CFG_NEITHER_gc /* Neither Filter nor Asynchronous Event is enabled */
	//		 | TCD_ACTION_FAULT_gc /* Event trigger a fault */
	//		 | TCD_EDGE_FALL_LOW_gc /* The falling edge or low level of event generates retrigger or fault action */
	//		 | 0 << TCD_TRIGEI_bp; /* Trigger event enable: disabled */

	// ccp_write_io((void*)&(TCD0.FAULTCTRL),0 << TCD_CMPAEN_bp /* Compare A enable: disabled */
	//		 | 0 << TCD_CMPA_bp /* Compare A value: disabled */
	//		 | 0 << TCD_CMPB_bp /* Compare B value: disabled */
	//		 | 0 << TCD_CMPBEN_bp /* Compare B enable: disabled */
	//		 | 0 << TCD_CMPC_bp /* Compare C value: disabled */
	//		 | 0 << TCD_CMPCEN_bp /* Compare C enable: disabled */
	//		 | 0 << TCD_CMPD_bp /* Compare D vaule: disabled */
	//		 | 0 << TCD_CMPDEN_bp /* Compare D enable: disabled */);

	// TCD0.INPUTCTRLA = TCD_INPUTMODE_NONE_gc; /* Input has no actions */

	// TCD0.INPUTCTRLB = TCD_INPUTMODE_NONE_gc; /* Input has no actions */

	TCD0.INTCTRL = 0 << TCD_OVF_bp      /* Overflow interrupt enable: disabled */
	               | 1 << TCD_TRIGA_bp  /* Trigger A interrupt enable: enabled */
	               | 1 << TCD_TRIGB_bp; /* Trigger B interrupt enable: enabled */

	while ((TCD0.STATUS & TCD_ENRDY_bm) == 0)
		; // Wait for Enable Ready to be high.

	TCD0.CTRLA = 1 << TCD_ENABLE_bp      /* Enable: enabled */
	             | TCD_CLKSEL_20MHZ_gc   /*  */
	             | TCD_CNTPRES_DIV1_gc   /* Sync clock divided by 1 */
	             | TCD_SYNCPRES_DIV1_gc; /*  */

	return 0;
}

 

For some reason, TCD0.INTCRL is not shown in the debugger. ( I'd like to step through the line of code and see the register getting updated)

 

Am I missing something needed to get the interrupts to occur?  The spec says:                  

 

 

I interpret this to mean I can get an interrupt on the rising edge of the WOA or WOB waveforms.  Maybe I misunderstand, since that seems a strange way of wording it.

 

Again, I see WOA waveform on pin (as output of LUT), but not getting any interrupts.

 

Thanks for any help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not sure this is your problem, but you enable two interrupts(TRIGA & TRIGB), but clear only one flag(TRIGB)?

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Worth a try, but clearing both doesn't help (the ISR NEVER gets entered,  so adding any code there can't help).

 

I did add this to main.c:

 

	TCD0.INTFLAGS = TCD_TRIGB_bm;
	TCD0.INTFLAGS = TCD_TRIGA_bm;

 

to make sure the flags were cleared, but that doesn't help either.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Other references talk about the interrupt occurring when a "capture" happens.  So, I'm thinking the interrupts provided aren't what I was looking for.

 

Maybe I can get there by using events, but it looks complicated--or at least it will take me a while to figure it out.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, that was the problem.

 

The ISR is fired on the input events, not just on an edge of the  WOA or WOB waveform.

 

I routed the Timer D output events using EVSYS back to Timer D "trigger inputs" and now the ISR gets executed.

 

Not sure it's doing what I want yet, but at least I'm learning how to use it.

 

If anyone's  interested, I'll update the thread with how to get interrupts that correspond to the available output events.  It's in the spec, but maybe another "concrete" example will help.

 

Thanks,

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, could you please post the code using input events ?

Because I'm trying to generate a pwm signal with variable duty cycle but the duty cycle is always the same, the initialized value... I'm not able to change it and I'm thinking that maybe I've to use the input events to modify it.

 

this is the part in tcd.c generate from atmel start

int8_t TCD_PWM_init()
{

    // Enable Protected register, peripheral must be disabled (ENABLE=0, in TCD.CTRLA).

    TCD0.CMPASET = 0;                            /* Compare A Set: 0 */

    TCD0.CMPACLR = DUTY_CYCLE;    /* Compare A Clear: 900 */

    TCD0.CMPBSET = DUTY_CYCLE;    /* Compare B Set: 900 */

    TCD0.CMPBCLR = SIGNAL_PERIOD;                /* Compare B Clear: 1000 */

    TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;            /* One ramp mode */

    TCD0.CTRLC = 0 << TCD_AUPDATE_bp            /* Auto update: disabled */
                 | TCD_CMPCSEL_PWMA_gc            /* PWM A output */
                 | TCD_CMPDSEL_PWMB_gc            /* PWM B output */
                 | 0 << TCD_CMPOVR_bp            /* Compare output value override: disabled */
                 | 0 << TCD_FIFTY_bp;            /* Fifty percent waveform: disabled */

  

    ccp_write_io((void *)&(TCD0.FAULTCTRL),
                 0 << TCD_CMPAEN_bp       /* Compare A enable: disabled */
                     | 0 << TCD_CMPA_bp   /* Compare A value: disabled */
                     | 0 << TCD_CMPB_bp   /* Compare B value: disabled */
                     | 0 << TCD_CMPBEN_bp /* Compare B enable: disabled */
                     | 0 << TCD_CMPC_bp   /* Compare C value: disabled */
                     | 1 << TCD_CMPCEN_bp /* Compare C enable: enabled */
                     | 0 << TCD_CMPD_bp   /* Compare D value: disabled */
                     | 1 << TCD_CMPDEN_bp /* Compare D enable: enabled */);

 

    TCD0.INTCTRL = 0 << TCD_OVF_bp      /* Overflow interrupt enable: enabled */
                   | 0 << TCD_TRIGA_bp  /* Trigger A interrupt enable: disabled */
                   | 0 << TCD_TRIGB_bp; /* Trigger B interrupt enable: disabled */

    while ((TCD0.STATUS & TCD_ENRDY_bm) == 0)
        ; // Wait for Enable Ready to be high.

    TCD0.CTRLA = 1 << TCD_ENABLE_bp      /* Enable: enabled */
                 | TCD_CLKSEL_SYSCLK_gc   /*  */
                 | TCD_CNTPRES_DIV4_gc  /* Sync clock divided by 32 */
                 | TCD_SYNCPRES_DIV1_gc; /*  */

    return 0;
}

 

 

this is the part in the main.c

 

int main(void)
{
    atmel_start_init();
    cpu_irq_enable();
    
    while (1) {

        asm("wdr");

    
        if (brightness < PWM_PERIOD)
        {
            brightness += 250;
        }
        else brightness = 0;

        // wait to see the LED brightness change effect
 
        TCD0.CMPACLR = brightness;                  
        TCD0.CMPBSET = brightness;                   
        
        _delay_ms(250);
        
        asm("nop");
    }
}