xmega128A1 interrupt problem

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

Hi,
I am relatively new to AVR and I just hit a problem with I/O interrupts. I am trying to read ethernet packet from SPI on every interrupt I get from ENC28J60.

The problem is that in few minutes after starting the controller it suddenly freezes. Irregulary.

I have read the AVR1305 note and found this:

Quote:
Since the AVR data bus is 8-bit wide and access to multi-byte variables requires execution of more than one instruction, it is possible that an interrupt can occur between accessing the first and the second byte of a 16-bit (or 32-bit variable). If a 16-bit variable used in the main loop of the code is modified by an interrupt, the variable can be corrupted.

There are absolutely no interrupts and no other code. Only one interrupt.
So I disabled interrupts globally when processing packet. Here are code examples from my project:

static uint8_t packet[512];
static uint16_t packet_rcv_len;

void ethernet_interrupt_init(void);

ISR(PORTC_INT0_vect) {
	cpu_irq_disable();
	packet_rcv_len = enc28j60_packet_receive(511, &packet);
	if (packet_rcv_len > 0) {
		recvstack_packet_parse(&packet);
	}
	cpu_irq_enable();
}

void ethernet_interrupt_init(void) {
	ioport_configure_pin(IOPORT_CREATE_PIN(PORTC, 2), IOPORT_DIR_INPUT | IOPORT_RISING);
	PORTC.INT0MASK = 0x02;
	PORTC.INTCTRL |= PORT_INT0LVL_HI_gc;
	pmic_enable_level(PMIC_LVL_HIGH);
}

int main (void)
{
     /*
	usart_rs232_options_t e232config;
	e232config.baudrate = 57600;
	e232config.charlength = USART_CHSIZE_8BIT_gc;
	e232config.paritytype = USART_PMODE_DISABLED_gc;
	e232config.stopbits = false;
     */

	sysclk_init();
	board_init();
	pmic_init();
	cpu_irq_enable();
	
.....................................

	
	ethernet_interrupt_init();

	while (true) {}
}

I have tried it with sleep mode. I tried almost everything. Nothing solves my problem. The only solution I found is to not use interrupts. And that's what I wouldn't like to do.

So if anyone knows, where is my problem please help. Thank you :-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ISR(PORTC_INT0_vect) { 
   cpu_irq_disable(); 
   packet_rcv_len = enc28j60_packet_receive(511, &packet); 
   if (packet_rcv_len > 0) { 
      recvstack_packet_parse(&packet); 
   } 
   cpu_irq_enable(); 
}

If cpu_irq_disable() and cpu_irq_enable() are really just CLI and SEI then this is a very very bad idea. You don't need to manually mess with I in an ISR and the real dangerous one is when you SEI before the ISR is finished in which case it can be pre-empted by another interrupt. If that is one of the same type you will get return address nesting which may eventually lead to a stack crash which matches your symptoms exactly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ISR(PORTC_INT0_vect) {
   packet_rcv_len = enc28j60_packet_receive(511, &packet);
   if (packet_rcv_len > 0) {
      recvstack_packet_parse(&packet);
   }

}

The cpu_irq_disable and enable thing was just my try. It didnt work also when it was like is the code above.

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

So I ask and please again... No one can help me ? :-(

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

Do the interrupts work correctly up until it freezes?

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

Yes, the interrupts work correctly. All packets are handled as wanted. But then it freezes completely.