0
votes

I've been trying to configure & run hardware timer over SAML21 MCU to generate a 100ms delay i.e. ISR is supposed to hit at every 100ms. But it is observed that after starting the timer ISR is hitting at every 10us and changing the Prescaler & Compare register values isn't creating any difference in the 10us interval. Please review my code and let me know where I'm doing wrong. I'm trying to configure Timer1(TC1) in 16bit mode, using GCLK_GENERATOR_1 as its clock source running at 8MHz frequency(CPU Main Clock:16MHz). The timer is expected to cause overflow interrupt every 100ms.

TcCount16 *tc_hw1 = NULL;   /* Pointer to TC1 hardware registers Initilized later */
void init_timer1(void)
{
   struct tc_module tc_inst1;   
   struct tc_config conf_tc1;

   tc_get_config_defaults(&conf_tc1);

   conf_tc1.clock_source = GCLK_GENERATOR_1;
   conf_tc1.clock_prescaler = TC_CLOCK_PRESCALER_DIV64; /* 8MHz/64 = 125KHz*/
   conf_tc1.reload_action = TC_RELOAD_ACTION_GCLK;
   conf_tc1.counter_size = TC_COUNTER_SIZE_16BIT;
   conf_tc1.count_direction = TC_COUNT_DIRECTION_UP;
   conf_tc1.counter_16_bit.value = 0x0000;
   /** Rest of the settings are used as defaults **/
   while (tc_init(&tc_inst1, TC1, &conf_tc1) != STATUS_OK){
   }

   tc_set_top_value(&tc_inst1, 12500); /* Set counter compare top value */
   /* Enable interrupt & Set Priority */
   tc_hw1 = &(tc_inst1.hw->COUNT16);   /* Initialize pointer to TC1 hardware register */
   tc_hw1->INTENSET.reg |= TC_INTFLAG_OVF;  /* Enable Overflow Interrupt */
   NVIC_SetPriority(TC1_IRQn, 2);
   NVIC_EnableIRQ(TC1_IRQn);        
   tc_enable(&tc_inst1);    /*Start The TIMER*/
}

void TC1_Handler(void)
{

   if((tc_hw1->INTFLAG.reg) & (TC_INTFLAG_OVF))
   {
      port_pin_toggle_output_level(PIN_PB03);
   }
   system_interrupt_clear_pending(SYSTEM_INTERRUPT_MODULE_TC1);
}

Debugger Information: I can see that the timer register is configured correctly but the COUNT register is not incrementing itself every time I pause to capture the debug info it shows only 0x0000 values. Please help. Thanks!

1

1 Answers

1
votes

I resolved the issue actually it's kind of mandatory to clear the timer OVF bit in the INTFLAG register. So the interrupt handler should've been like this:

void TC1_Handler(void)
{

   if((tc_hw1->INTFLAG.reg) & (TC_INTFLAG_OVF))
   {
     tc_hw1->INTFLAG.reg = TC_INTFLAG_OVF;  /*Clears the flag by writing 1 to it*/
     port_pin_toggle_output_level(PIN_PB03);
   }
   system_interrupt_clear_pending(SYSTEM_INTERRUPT_MODULE_TC1);  /*Not necessarily needed*/
}