AT32UC3 work with external interruptions

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

Hi, everybody.
I decided to master 32-bit AT32UC3C1512C, before I worked only with 8-bit at the Assembler. I have a question whether it is possible to work with the controller using only the standard enclosed libraries (not to use an includes for debugging boards)? I wrote the program for management of a light-emitting diode of polling method, but with use of interruptions - it is be impossible. How the minimum program for work with interruption has to look? My code:

#include <avr32/io.h>
#include <avr32/uc3c1512c.h>
#include <avr32/eic_302.h>
#include <avr32/intc_102.h>

__attribute__((__interrupt__)) 
static void _AVR32_EIC_INT3(void)           // I need to use external interruption INT3
     {    // code
      }

//--------------------------------------
int main(void)
  {    
     while (1) {}
  }

the compiler writes: warning: '_AVR32_EIC_INT3' defined but not used.

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

1:
uc3c1512c.h already includes the processor-specific eic_302.h and intc102.h


2:
Interrupt handling in the UC3xxx family is different to that in the AVR8 family.
You must first initialise the INTC module, and then configure the INTC to connect your ISRs to the interrupt sources.


The INTC module has a requirement that an ISR must start within 16kb from the start of the interrupt-vector table (the EVBA), and that can be a problem in the 'C' language.
There are several solutions, but the simplest is to use the INTC 'driver' from the ASF.
intc.c in the ASF has two routines INTC_init_interrupts() and INTC_register_interrupt(,,)
So you will need to do ;

...<br />
INTC_init_interrupts();  // only once<br />
...<br />
INTC_register_interrupts( _AVR32_EIC_INT3, AVR32_EIC_IRQ_3, AVR32_INTC_INT0 );  // at runtime, associate your ISR with an interrupt-source and give it a priority.<br />
...<br />
configure the GPIO module to enable the EXTINT3 feature on the physical pin you want.<br />
configure the EIC module and enable the INT3 interrupt. ( AVR32_EIC_IER_INT3 )<br />
...
From the INTC table Interrupt Request Signal Map, EIC 3 is Group 15, Line 2 which is interrupt request 482 (=15*32+2 = AVR32_EIC_IRQ_3 )
AVR32_INTC_INT0 is the interrupt priority (0=lowest, 3=highest).

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

I.e. if I have correctly understood, my code has to look it seems:

#include <avr32/uc3c1512c.h>

INTC_init_interrupts();
INTC_register_interrupts(_AVR32_EIC_INT3, AVR32_EIC_IRQ_3, AVR32_INTC_INT0); 

__attribute__((__interrupt__)) 
static void _AVR32_EIC_INT3(void)
{	 
	AVR32_GPIO.port[2].ifrc = 1<<24;
	AVR32_GPIO.port[0].ovrt = 1<<22;
}
///////////////////////////////////////////////
int main(void)
{	AVR32_GPIO.port[0].gpers = 1<<22;
	AVR32_GPIO.port[2].gpers = 1<<4;
			
	AVR32_GPIO.port[0].oders = 1<<22;
	AVR32_GPIO.port[2].puers = 1<<4;
	
	AVR32_GPIO.port[2].iers = 1<<4;


	eic_options[0].eic_mode   = EIC_MODE_EDGE_TRIGGERED;
	eic_options[0].eic_async  = EIC_SYNCH_MODE;
	eic_options[0].eic_line   = EXT_INT_EXAMPLE_LINE1;

     while (1) {}
}

But in that case the compiler gives error messages:

 

Error: recipe for target 'main.o' failed

Warning: data definition has no type or storage class

Warning: type defaults to 'int' in declaration of 'INTC_init_interrupts'

Error: expected ')' before numeric constant

Error: 'eic_options' undeclared (first use in this function)

Message: each undeclared identifier is reported only once for each function it appears in

Error: 'EIC_MODE_EDGE_TRIGGERED' undeclared (first use in this function)

Error: 'EIC_SYNCH_MODE' undeclared (first use in this function)

Error: 'EXT_INT_EXAMPLE_LINE1' undeclared (first use in this function)

 

Prompt that I do not so.

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

Those definitions are in intc.h and eic.h You will need to #include them.


If you are using Atmel Studio to develop/manage your project it will be simpler to create a new project, then use the ASF wizard to include the INTC and EIC 'drivers'.
The ASF wizard will also add the 'C' startup code.

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

Thanks for a response. The matter is that work of ASF wizard in Atmelstudio7 requires "User Board template UC3 C0/C1/C2". Further he suggests to connect various modules. Having connected a little (eic, gpio, intc), the compiler still doesn't understand that it:

eic_options[0].eic_mode   = EIC_MODE_EDGE_TRIGGERED;  
eic_options[0].eic_async  = EIC_SYNCH_MODE;

He writes:

'EIC_MODE_EDGE_TRIGGERED' undeclared (first use in this function).

 

Whether writing of the minimum piece of the program from "blank sheet", without use of application-oriented files is possible?

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

You can create a minimum project but you will need to add the appropriate C startup-code and tell Studio where your .c and .h files are located.


This works for Studio 6.2 (I do not have a Win7 machine that has Studio 7 installed)
menu File -> New Project -> C/C++ -> GCC executable project
Device Selection -> AT32UC3C1512C -> OK
menu ASF -> ASF Wizard
press "CANCEL" to the "No defined board" dialog.
Select EIC then Add>>
Select INTC then Add>>
Select GPIO then Add>>
Apply
OK


At this point the ASF Wizard has put the .c and .h files into a .src subdirectory, however, a little bit of manual work still needs to be preformed.
menu Project -> xxxx Properties -> Toolchain -> AVR32/GNU linker -> General -> tick(select) the option "Do not use standard start files -nostartfiles"


In the file where your int main(void) is, add #include "src/asf.h"
( If you move your main file to the src subfolder then add #include "asf.h" )

Last Edited: Wed. May 10, 2017 - 04:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Mikech , for the detailed comment. Following your recommendations I have received such code:

#include <avr32/io.h>
#include "src/asf.h"
#include <avr32/uc3c1512c.h>

INTC_init_interrupts();
INTC_register_interrupts(_AVR32_EIC_INT3, AVR32_EIC_IRQ_3, AVR32_INTC_INT0);

__attribute__((__interrupt__))
static void _AVR32_EIC_INT3(void)
{
}
int main(void)
{
      	Enable_global_interrupt();
   	AVR32_GPIO.port[0].gpers = 1<<22;
    	AVR32_GPIO.port[0].oders = 1<<22;
        AVR32_GPIO.port[2].puers = 1<<4;
     	AVR32_GPIO.port[2].iers = 1<<4;
   	////----------------------------------------------------------------------
	eic_options[0].eic_mode = EIC_MODE_EDGE_TRIGGERED;
   	eic_options[0].eic_edge = EIC_EDGE_FALLING_EDGE;
   	eic_options[0].eic_async = EIC_SYNCH_MODE;
   	eic_options[0].eic_line = EXT_INT3;

    while (1) 
    {
    }
}

On what the compiler gives 7 error messages, in particular on registration of interruptions:

Error        conflicting types for 'INTC_init_interrupts'

Error        expected ')' before numeric constant

Having looked at syntax in files "eic.h" and "intc.h", I have changed lines

extern void INTC_init_interrupts(void);
extern void INTC_register_interrupt(__int_handler handler, uint32_t irq, uint32_t int_level);
 eic_options_t[0].eic_mode = EIC_MODE_EDGE_TRIGGERED;
 eic_options_t[0].eic_edge = EIC_EDGE_FALLING_EDGE;
 eic_options_t[0].eic_async = EIC_SYNCH_MODE;
 eic_options_t[0].eic_line = EXT_INT3;

That there are no mistakes, but on interruption compiler gives the message:
Warning: "_AVR32_EIC_INT3" defined but not used.

I believe that registration of interruptions hasn't taken place?

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

Alex-A wrote:
On what the compiler gives 7 error messages, in particular on registration of interruptions: Error conflicting types for 'INTC_init_interrupts' Error expected ')' before numeric constant
Then why have you included a declaration in  your own C code? Surely the function is declared in one of the .h files you are including?

 

I can't help thinking you have made too large a leap here. Going from AVR8 and assembler to 32bit, C and using a complex support library (ASF) looks like a step too far to me.

 

I'd take it in steps. For AVR8 first switch from Asm to C. Then, assuming there is ASF support for it start to use ASF in C projects for AVR8. When you understand all the techniques involved then consider the move to C+ASF for 32 bit

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

INTC_init_interrupts();<br />
INTC_register_interrupts(_AVR32_EIC_INT3, AVR32_EIC_IRQ_3, AVR32_INTC_INT0);
are not declarations, they are calls to procedures.
You want something like
int main(void)<br />
{<br />
      	INTC_init_interrupts();<br />
      	INTC_register_interrupts(_AVR32_EIC_INT3, AVR32_EIC_IRQ_3, AVR32_INTC_INT0);<br />
      	Enable_global_interrupt();<br />
 ...

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

in this case the compiler writes:

Warning        implicit declaration of function 'INTC_register_interrupts'

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

1: Confirm that in the file asf.h there is a #include for the file intc.h
2: Why ? Where ? and to What ? did you change

extern void INTC_init_interrupts(void);<br />
extern void INTC_register_interrupt(__int_handler handler, uint32_t irq, uint32_t int_level);

Last Edited: Thu. May 11, 2017 - 03:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This including is present. The matter  has appeared in syntax:

INTC_register_interrupt(_AVR32_EIC_INT3, AVR32_EIC_IRQ_3, AVR32_INTC_INT0);

At such writing of mistakes isn't given.

 

The last that remained to solve with settings eic_options.

If to write:

eic_options[0].eic_mode  = EIC_MODE_EDGE_TRIGGERED;

There will be a mistake:

Error        'eic_options' undeclared (first use in this function)

And if so:

eic_options_t[0].eic_mode = EIC_MODE_EDGE_TRIGGERED;

Error        expected identifier or '(' before '[' token

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

Where have you declared what the variable eic_options[] is ?.
You need a eic_options_t eic_options[2]; declaration.


I recommend that you use Atmel Studio to create an example-project, (there are several EIC examples) and examine how the ASF routines are used and what the data-structures are.




The ASF is the software layer that Atmel puts between you and the hardware, to try and insulate you from some of the details at the hardware level.,
you can also manipulate the hardware directly because all the modules, bits, fields and addresses are predefined.
for example,
AVR32_EIC.MODE.int2 = EIC_EDGE_RISING_EDGE; will set the field 'int2' in the EIC MODE register.
AVR32_EIC.mode = 0x04; will put a value into all 32 bits of the MODE register.

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

you can also manipulate the hardware directly

 It what now is necessary for me. Because ASF connects a set of macroes and functions which still need to be found.
Whether there is literature for on this subject? I a lot of things has reconsidered, but in relation to Atmel haven't found.

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

Learning how to use the ASF is not easy, it takes time and effort to understand how it names things and how it does operations.
A technique that worked for me was to look at the description of a module in the datasheet, (for example, the EIC module),
and then look at the ASF code (of the EIC 'driver') to help explain what needs to be done.

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

I didn't think that everything is so difficult. Mikech thanks for all councils they very much were useful to me.

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

Hi All,

 

I hope I haven't entered this discussion too late...  I'm having a semi-similar issue trying to implement external interrupts with an AT32UC3C0256C.  I've found several examples of interrupt implementations using ASF, but where I'm stuck is that my project is written in C++ which seems inherently incompatible with ASF, even in Atmel Studio 7 which is the platform I'm using.  As poster mikech pointed out, reading through the chip datasheet and then tracing through ASF code is a technique that I've been using to march through several pieces of my code (SPI, UART, Clock and Power Management, PWM, and so on) but the implementation of interrupts seems extraordinarily tedious... so much so that I felt compelled to register as a new user here and ask, "What the heck am I missing??"  

 

I'm not new to microcontrollers (truth told I go all the way back to the 6502 and Z80 days!  HA!) nor am I new to Atmel, 32-bit micro's and so on, but this interrupt thing really has me scratching my head.  I've spent a fair amount of time searching around (i.e., I'm not a lazy programmer looking for an easy out by way of the hard work of others), but so far haven't come up with much.  I'm not looking for ready-made solutions, but if anyone could point me in the right direction I would be truly grateful.  

 

Thanks in advance for any assistance!

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

Here my code which has earned can be still to whom to be useful:

#include <avr32/io.h>
#include "compiler.h"
#include "gpio.h"
#include "eic.h"
#include "intc.h"

# define LED_Up AVR32_PIN_PD02	// Светодиоды
# define LED_Down AVR32_PIN_PD03
# define LED_Left AVR32_PIN_PD22
# define LED_Right AVR32_PIN_PB02
# define LED_Enter AVR32_PIN_PB03
# define LED_TC0 AVR32_PIN_PD30
# define LED_DAC1A AVR32_PIN_PA12
# define LED_G AVR32_PIN_PA20
# define LED_R AVR32_PIN_PA22

# define Bt_Up AVR32_PIN_PC04	// Кнопки
# define Bt_Down AVR32_PIN_PC13
# define Bt_Left AVR32_PIN_PC18
# define Bt_Right AVR32_PIN_PD24
# define Bt_Enter AVR32_PIN_PD29

unsigned char key_number=0;						// Объявляем глобальную переменную для переключения светодиодов.
static volatile bool CancelSwDelay = false;		// Объявляем глобальную переменную (целочисленного (логического) типа данных) для использования для очистки программной задержки в обработке внешнего прерывания
//---------------------------------------------------------------------------------
__attribute__((__interrupt__))	// Обработчик внешнего прерывания (INT3) от кнопки "Up"
static void But_Up(void)
{	eic_clear_interrupt_line(&AVR32_EIC, AVR32_EIC_INT3);	// Очищаем флаг прерывания
	key_number = 1;											// Выставляем флаг кнопки
	CancelSwDelay = true;									// Сбрасываем флаг задержки
	volatile int i;											// Объявляем локальную переменную. Реализуем "антидребезг" - задерживаемся в прерывании
		for (i=1000; i>=0; i--);							// Локальный цикл задержки
		if (!gpio_get_pin_value(Bt_Up))						// Считываем значение на кнопке, если не равно 1,
			{gpio_tgl_gpio_pin(LED_Up);}							// то переключаем светодиод
}
//---------------------------------------------------------------------------------
__attribute__((__interrupt__))	// Обработчик внешнего прерывания (INT7) от кнопки "Down"
static void But_Down(void)
{	eic_clear_interrupt_line(&AVR32_EIC, AVR32_EIC_INT7);
	volatile int i;										
	for (i=1000; i>=0; i--);							
	if (!gpio_get_pin_value(Bt_Down))					
		{gpio_tgl_gpio_pin(LED_Down);}				
}
//---------------------------------------------------------------------------------
__attribute__((__interrupt__))	// Обработчик внешнего прерывания (INT5) от кнопки "Left"
static void But_Left(void)
{	eic_clear_interrupt_line(&AVR32_EIC, AVR32_EIC_INT5);
	volatile int i;
	for (i=1000; i>=0; i--);
	if (!gpio_get_pin_value(Bt_Left))
		{gpio_tgl_gpio_pin(LED_Left);}
}
//---------------------------------------------------------------------------------
__attribute__((__interrupt__))	// Обработчик внешнего прерывания (INT8) от кнопки "Right"
static void But_Right(void)
{	eic_clear_interrupt_line(&AVR32_EIC, AVR32_EIC_INT8);
	volatile int i;
	for (i=1000; i>=0; i--);
	if (!gpio_get_pin_value(Bt_Right))
		{gpio_tgl_gpio_pin(LED_Right);}
}
//---------------------------------------------------------------------------------
__attribute__((__interrupt__))	// Обработчик внешнего прерывания (INT6) от кнопки "Enter"
static void But_Enter(void)
{	eic_clear_interrupt_line(&AVR32_EIC, AVR32_EIC_INT6);
	volatile int i;
	for (i=1000; i>=0; i--);
	if (!gpio_get_pin_value(Bt_Enter))
		{gpio_tgl_gpio_pin(LED_Enter);}
}
//---------------------------------------------------------------------------------
static void delay1(void)			// Функция программной задержки1
{	volatile int i;					// Объявляем локальную переменную
	CancelSwDelay = false;			// Устанавливаем значение переменной "ЛОЖЬ"
	for (i=300; (i>=0)&&(false == CancelSwDelay); i--);	// Мы в цикле пока i>=0 и переменная "bCancelSwDelay"=ЛОЖЬ. После каждой итерации уменьшаем i на 1.
}															// Выходим из цикла в случае если вышло время или сработало прерывание ("bCancelSwDelay" стала = ИСТИНА)
//---------------------------------------------------------------------------------
static void delay2(void)	// Функция программной задержки2
{	volatile int i;
	CancelSwDelay = false;
	for (i=10000; (i>=0)&&(false == CancelSwDelay); i--);
}
//__________________________________________________________________________________________________________________________________
int main(void)							// Главная функция. Инициализация. Ждём внешнего прерывания от EIC.
{	eic_options_t eic_options[5];	// Структура, содержащая параметры конфигурации модуля EIC.

	eic_options[0].eic_mode = EIC_MODE_EDGE_TRIGGERED;
	eic_options[0].eic_level = EIC_EDGE_FALLING_EDGE;
	eic_options[0].eic_filter = EIC_FILTER_ENABLED;
	eic_options[0].eic_async = EIC_ASYNCH_MODE;
	eic_options[0].eic_line = AVR32_EIC_INT3;	

	eic_options[1].eic_mode = EIC_MODE_EDGE_TRIGGERED;
	eic_options[1].eic_level = EIC_EDGE_FALLING_EDGE;
	eic_options[1].eic_filter = EIC_FILTER_ENABLED;
	eic_options[1].eic_async = EIC_ASYNCH_MODE;
	eic_options[1].eic_line = AVR32_EIC_INT7;
	
	eic_options[2].eic_mode = EIC_MODE_EDGE_TRIGGERED;
	eic_options[2].eic_level = EIC_EDGE_FALLING_EDGE;
	eic_options[2].eic_filter = EIC_FILTER_ENABLED;
	eic_options[2].eic_async = EIC_ASYNCH_MODE;
	eic_options[2].eic_line = AVR32_EIC_INT5;
	
	eic_options[3].eic_mode = EIC_MODE_EDGE_TRIGGERED;
	eic_options[3].eic_level = EIC_EDGE_FALLING_EDGE;
	eic_options[3].eic_filter = EIC_FILTER_ENABLED;
	eic_options[3].eic_async = EIC_ASYNCH_MODE;
	eic_options[3].eic_line = AVR32_EIC_INT8;
	
	eic_options[4].eic_mode = EIC_MODE_EDGE_TRIGGERED;
	eic_options[4].eic_level = EIC_EDGE_FALLING_EDGE;
	eic_options[4].eic_filter = EIC_FILTER_ENABLED;
	eic_options[4].eic_async = EIC_ASYNCH_MODE;
	eic_options[4].eic_line = AVR32_EIC_INT6;

	gpio_enable_pin_pull_up(AVR32_EIC_EXTINT_3_1_PIN);	// Подтяжка на + кнопочных выводов
	gpio_enable_pin_pull_up(AVR32_EIC_EXTINT_7_PIN);
	gpio_enable_pin_pull_up(AVR32_EIC_EXTINT_5_PIN);
	gpio_enable_pin_pull_up(AVR32_EIC_EXTINT_8_PIN);
	gpio_enable_pin_pull_up(AVR32_EIC_EXTINT_6_1_PIN);
				
	gpio_enable_module_pin(AVR32_EIC_EXTINT_3_1_PIN, AVR32_EIC_EXTINT_3_1_FUNCTION);// Каждой линии внешнего прерывания соответствует линия GPIO и номер функции GPIO (0-5)
	gpio_enable_module_pin(AVR32_EIC_EXTINT_7_PIN, AVR32_EIC_EXTINT_7_FUNCTION);
	gpio_enable_module_pin(AVR32_EIC_EXTINT_5_PIN, AVR32_EIC_EXTINT_5_FUNCTION);
	gpio_enable_module_pin(AVR32_EIC_EXTINT_8_PIN, AVR32_EIC_EXTINT_8_FUNCTION);
	gpio_enable_module_pin(AVR32_EIC_EXTINT_6_1_PIN, AVR32_EIC_EXTINT_6_1_FUNCTION);
			
	Disable_global_interrupt();
	INTC_init_interrupts(); // Initialize interrupt vectors.
	
	INTC_register_interrupt(But_Up, AVR32_EIC_IRQ_3, AVR32_INTC_INT0);
	eic_init(&AVR32_EIC, &eic_options[0],5);							// Устанавливаем режим прерывания в соответствии с eic_options
	eic_enable_line(&AVR32_EIC, eic_options[0].eic_line);				// Разрешаем работу EIC-драйвера
	eic_enable_interrupt_line(&AVR32_EIC, eic_options[0].eic_line);		// Разрешаем прерывания от EIC

	INTC_register_interrupt(But_Down, AVR32_EIC_IRQ_7, AVR32_INTC_INT0);
	eic_init(&AVR32_EIC, &eic_options[1],5);
	eic_enable_line(&AVR32_EIC, eic_options[1].eic_line);
	eic_enable_interrupt_line(&AVR32_EIC, eic_options[1].eic_line);

	INTC_register_interrupt(But_Left, AVR32_EIC_IRQ_5, AVR32_INTC_INT0);
	eic_init(&AVR32_EIC, &eic_options[2],5);
	eic_enable_line(&AVR32_EIC, eic_options[2].eic_line);
	eic_enable_interrupt_line(&AVR32_EIC, eic_options[2].eic_line);

	INTC_register_interrupt(But_Right, AVR32_EIC_IRQ_8, AVR32_INTC_INT0);
	eic_init(&AVR32_EIC, &eic_options[3],5);
	eic_enable_line(&AVR32_EIC, eic_options[3].eic_line);
	eic_enable_interrupt_line(&AVR32_EIC, eic_options[3].eic_line);

	INTC_register_interrupt(But_Enter, AVR32_EIC_IRQ_6, AVR32_INTC_INT0);
	eic_init(&AVR32_EIC, &eic_options[4],5);
	eic_enable_line(&AVR32_EIC, eic_options[4].eic_line);
	eic_enable_interrupt_line(&AVR32_EIC, eic_options[4].eic_line);

	//eic_enable_lines(&AVR32_EIC,(1<<eic_options[4].eic_line)| (1<<eic_options[3].eic_line)| (1<<eic_options[2].eic_line)| (1<<eic_options[1].eic_line)|(1<<eic_options[0].eic_line));
	//eic_enable_interrupt_lines(&AVR32_EIC,(1<<eic_options[4].eic_line)| (1<<eic_options[3].eic_line)|(1<<eic_options[2].eic_line)|(1<<eic_options[1].eic_line)|(1<<eic_options[0].eic_line));	

	Enable_global_interrupt();
	
	gpio_clr_gpio_pin(LED_Up);	// LED-Up сбрасываем в 0
	gpio_clr_gpio_pin(LED_Down);
	gpio_clr_gpio_pin(LED_Left);
	gpio_clr_gpio_pin(LED_Right);
	gpio_clr_gpio_pin(LED_Enter);
	gpio_clr_gpio_pin(LED_TC0);
	gpio_clr_gpio_pin(LED_DAC1A);
	gpio_clr_gpio_pin(LED_G);
	gpio_clr_gpio_pin(LED_R);					
 //---------------------------------------------------------------------------------	
	while(1)			// Вечный цикл. Переключение светодиодов зависит от поведения внешнего прерывания.
	{		
		switch (key_number)		// Оператор множественного выбора. В зависимости от переменной "key_number" выполняется одна из 3х ветвей
		{
			case 0 :								// Если key_number=0
				gpio_set_gpio_pin(LED_TC0);		// Вкл. LED
				delay1();						// Вызов задержки
				gpio_clr_gpio_pin(LED_TC0);		// Выкл. LED
				gpio_set_gpio_pin(LED_DAC1A);	// Вкл. LED
				delay1();						// Вызов задержки
				gpio_clr_gpio_pin(LED_DAC1A);	// Выкл. LED
				
				gpio_set_gpio_pin(LED_TC0);	
				delay1();					
				gpio_clr_gpio_pin(LED_TC0);	
				gpio_set_gpio_pin(LED_DAC1A);
				delay1();					
				gpio_clr_gpio_pin(LED_DAC1A);

				delay2();
				//key_number = 0;						// Очищаем флаг кнопки
				//break;								// Выходим из оператора switch
			case 1 :								// Если key_number=2
				gpio_set_gpio_pin(LED_R);		// Вкл. LED
				delay1();						// Вызов задержки
				gpio_clr_gpio_pin(LED_R);		// Выкл. LED
				gpio_set_gpio_pin(LED_G);	// Вкл. LED
				delay1();						// Вызов задержки
				gpio_clr_gpio_pin(LED_G);	// Выкл. LED
				
				gpio_set_gpio_pin(LED_R);
				delay1();
				gpio_clr_gpio_pin(LED_R);
				gpio_set_gpio_pin(LED_G);
				delay1();
				gpio_clr_gpio_pin(LED_G);

				delay2();
				key_number = 0;						// Очищаем переменную
				break;								// Выходим из оператора switch

			default :								// Иначе
				//gpio_set_gpio_pin(LED_DAC1A);
				//gpio_clr_gpio_pin(LED_DAC1A);
				key_number = 0;						// Очищаем переменную
				break;								// Выходим из оператора switch
												
		}								
	}												
}

 

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

Interrupts at the module-level (eg the USART, PWM, EIC, etc) are roughly similar to other processors.
The problem with the UC3 interrupt-handling is in how the hardware actually processes those exceptions/module-interrupts, because it is a requirement that the start of the interrupt-handlers be within 16 kbytes from the start of the 'interrupt-vector-table'. (EVBA + 16kbytes)
There are several techniques to achieve that goal and all have their advantages and disadvantages.
To get the AVR32 GCC compiler/linker to put the interrupt-handlers 'close' together (and close enough to the address has been put into EVBA), requires fiddling with program-sections and linker scripts and might not always work in all cases.


The authors of the ASF INTC 'driver' took a much more general approach that will always work (your interrupt-handlers can be anywhere in memory), but that flexibility and simplicity comes with a run-time penalty because there is extra code and a jump-table between the hardware and your interrupt-handler(s).


The only ASF item that I routinely use is the INTC 'driver' and for my projects I can live with its' code/memory/time overheads.

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

Thank you both for your help!  I tried adding INTC and EIC via the ASF Wizard previously but at compile time saw a "generous" helping of errors.  I didn't pursue it very much because I read so many posters detailing the fundamental incompatibility of C++ and ASF and figured this pile of errors must have been what everyone was talking about.  I tried it again now and quickly got down to the need to remove startup_uc3.s from the newly added ASF support files and now I seem able to compile.  I'll start adding more interrupt related code next and see what happens and surely borrow from the code that Alex-A provided above.  Hopefully it's all forward progress from here!

 

Losing one's hair as a natural consequence of age is one thing, losing it because you're literally tearing it out of your head is quite another...  Thank you both for preventing that process from getting too far out of hand!