asf interrupts

All design tool related questions: compiler, assembler, linker. Embedded programming questions: assembler, C code.

Moderator: nferre

Forslund
Contact:
Location: Sweden
Posts: 7
Joined: Thu Mar 08, 2007 10:13 am

asf interrupts

Fri Sep 06, 2013 1:24 pm

Hi,

I'm just getting started with developing for the SAM4E-EK using asf 3.11.0 with arm-none-gcc 4.7 and can't quite get the hang of how interrupt handlers should be added.

I've cannibalized the usart_serial_example code to make a small interrupt-driven "blinky". And using TC0 as in the example everything works fine but when I try to move the code to TC1 (by search and replace) nothing happens.

When going through the code I can't quite understand how the Interrupt handler is registered?

My other question is is there a fundamental difference between timer0 and timer1 that demands a different initiation procedure?

My code:

Code: Select all

#include "asf.h"
#include "conf_board.h"
#include "conf_clock.h"


/** All interrupt mask. */
#define ALL_INTERRUPT_MASK  0xffffffff

/** Timer counter frequency in Hz. */
#define TC_FREQ             10
static unsigned int led_tbl_ptr = 0;
static char led_table[] = {0x01, 0x3, 0x7, 0xf, 0xe, 0xc, 0x8 };
/*
 */
void TC1_Handler(void)
{
   /* Read TC1 Status. */
   tc_get_status(TC1, 0);

   if (led_table[led_tbl_ptr] & 0x01)
      LED_On(LED0);
   else
      LED_Off(LED0);
   if (led_table[led_tbl_ptr] & 0x02)
      LED_On(LED1);
   else
      LED_Off(LED1);
   if (led_table[led_tbl_ptr] & 0x04)
      LED_On(LED2);
   else
      LED_Off(LED2);
   if (led_table[led_tbl_ptr] & 0x08)
      LED_On(LED3);
   else
      LED_Off(LED3);

   if (++led_tbl_ptr >= sizeof(led_table))
      led_tbl_ptr = 0;

}

/**
 * \brief Configure Timer Counter 1 (TC1) to generate an interrupt every 200ms.
 * This interrupt will be used to flush USART input and echo back.
 */
static void configure_tc(void)
{
   uint32_t ul_div;
   uint32_t ul_tcclks;
   static uint32_t ul_sysclk;

   /* Get system clock. */
   ul_sysclk = sysclk_get_cpu_hz();

   /* Configure PMC. */
   pmc_enable_periph_clk(ID_TC1);

   /* Configure TC for a 50Hz frequency and trigger on RC compare. */
   tc_find_mck_divisor(TC_FREQ, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
   tc_init(TC1, 0, ul_tcclks | TC_CMR_CPCTRG);
   tc_write_rc(TC1, 0, (ul_sysclk / ul_div) / TC_FREQ);

   /* Configure and enable interrupt on RC compare. */
   NVIC_EnableIRQ((IRQn_Type)ID_TC1);
   tc_enable_interrupt(TC1, 0, TC_IER_CPCS);
}

int main(void)
{
   /* Initialize the SAM system. */
   sysclk_init();
   board_init();

   /* Configure TC. */
   configure_tc();
   tc_start(TC1, 0);
   while (1)
   {
   }
}
Any help, comments or insights are welcome!

Best regards
/Åke
Smoke me a Kipper, I'll be back for breakfast
Forslund
Contact:
Location: Sweden
Posts: 7
Joined: Thu Mar 08, 2007 10:13 am

Re: asf interrupts

Mon Sep 09, 2013 3:11 pm

in the interrupt header for my device (sam4e16e) it says:

Code: Select all

For NVIC devices the interrupt service routines are predefined to add to vector table in binary generation, so there is no service register at run time. The routine collections are in exceptions.h.
and in exceptions.h sam4e.h is included which lists a set of handlers:

Code: Select all

...
void SUPC_Handler       ( void );
void TC0_Handler        ( void );
void TC1_Handler        ( void );
void TC2_Handler        ( void );
void TC3_Handler        ( void );
...
Does NVIC_EnableIRQ() somehow connect the interrupt vector to the handler with matching name? How is this done without requiring me to pass a function pointer to or that the prototypes above all have a matching function?
Smoke me a Kipper, I'll be back for breakfast
andyii
Posts: 1
Joined: Wed Mar 19, 2014 2:30 pm

Re: asf interrupts

Tue May 06, 2014 5:39 pm

I don't know if you're interested in this topic again.
in any case this is the way it work,
I'm on sam3a but it should be the same on your device because you use asf too.

in your code you write:
void TC0_Handler(void){

}

in your device cmsis file you'll have something like this
void TC0_Handler        ( void );

in exceptions.c you have:
void TC0_Handler        ( void ) __attribute__ ((weak, alias("Dummy_Handler")));

the way it works is because the weak attribute.
As gcc man page says: 
The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions which can be overridden in user code, though it can also be used with non-function declarations. Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker. 

so when you compile your code, if you don't have the weak attribute you should have a redefinition error, with the weak attribute the function you declared is used insted of the other one.

Sorry but I cannot help you with the blinking led interrupt.

my 2 cents.

Return to “Development Tools”

Who is online

Users browsing this forum: No registered users and 1 guest