Not triggering RX interrupt ISR

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

Hey all, I am trying to set up communication between 2 XMega (2 XMega256a3u's), I have the first MCU, call it MCU1, sending data through its UART, which I can measure on a scope to be at 9600bps, and the code I am running on my MCU2 should be interrupted whenever data is sent, but I am current getting dead air. I have also tried reversing it (MCU2 --> MCU1), and the same issues results. I tried using the simulator functionality of Atmel studio (rather than the emulation of my JTAG-ICE3), and I am setting the RXCIF flag (I think this should cause the ISR to trigger), but nothing happens still. The MCU's are connected from USARTC0 (MCU1) to USARTE0 (MCU2). I appreciate any help! I am hoping its a simple mistake. 

Here is my code on MCU2:

 

#define F_CPU 32000000UL
#include <avr/io.h>
#include <util/delay.h> 

void FastRCClock(void)
{
    CCP = CCP_IOREG_gc;              // disable register security for oscillator update
    OSC.CTRL = OSC_RC32MEN_bm;       // enable 32MHz oscillator
    while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for oscillator to be ready
    CCP = CCP_IOREG_gc;              // disable register security for clock update
    CLK.CTRL = CLK_SCLKSEL_RC32M_gc; // switch to 32MHz clock
}
void setUpSerial()
{

    /* This PORT setting is only valid to USARTE0 if other USARTs is used a
     * different PORT and/or pins are used.
      
     PE3 (TXD0) as output. */
    PORTE.DIRSET   = PIN3_bm;
    /* PE2 (RXD0) as input. */
    PORTE.DIRCLR   = PIN2_bm;

    
    // Baud rate selection
    // BSEL = (32000000 / (2^0 * 16*9600) -1 = 207.333 -> BSCALE = 0
    // FBAUD = ( (32000000)/(2^0*16(207+1)) = 9615.384 -> it's alright
    
    USARTE0_BAUDCTRLB = 0; //Just to be sure that BSCALE is 0
    USARTE0_BAUDCTRLA = 0xCF; // 207, 9600 BAUD
    
    
    //Disable interrupts, just for safety
    USARTE0_CTRLA = 0;

    //8 data bits, no parity and 1 stop bit
    USARTE0_CTRLC = USART_CHSIZE_8BIT_gc;
    
    //Enable receive and transmit
    USARTE0_CTRLB = USART_TXEN_bm | USART_RXEN_bm;

    //Sets interrupt to low level priority in the PMIC
    USARTE0_CTRLA |= USART_RXCINTLVL_LO_gc; 
}
void sendChar(char c)
{
    while( !(USARTE0_STATUS & USART_DREIF_bm) ); //Wait until DATA buffer is empty &'d the status register and USART DREIF bit mask together
    
    USARTE0_DATA = c;
}

ISR(USARTE0_RXC_vect)
{
    char temp = 0;
    PORTB.OUT =  0x1C;
    temp = USARTE0_DATA;
    sendChar(~temp);	
}

int main(void)
{
    PORTB.DIRSET = 0x1C;
    //PORTB.OUT =  0x1C;
    FastRCClock();
    setUpSerial();
    PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;//enable all interrupts
    PMIC.CTRL |= PMIC_LOLVLEX_bm; //Low level interrupt may be occurring don't stop it
    SREG |= 0x80; //sei(); equivalent

while (1)
    {
    }
    return 0;
}

Here is the code for MCU1:

 

#define F_CPU 32000000UL
#include <avr/io.h>
#include <util/delay.h> 
	

void FastRCClock(void)
{
	CCP = CCP_IOREG_gc;              // disable register security for oscillator update
	OSC.CTRL = OSC_RC32MEN_bm;       // enable 32MHz oscillator
	while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for oscillator to be ready
	CCP = CCP_IOREG_gc;              // disable register security for clock update
	CLK.CTRL = CLK_SCLKSEL_RC32M_gc; // switch to 32MHz clock
}
void setUpSerial()
{

	/* This PORT setting is only valid to USARTC0 if other USARTs is used a
	 * different PORT and/or pins are used.
	  
  	 PE3 (TXD0) as output. */
	PORTC.DIRSET   = PIN3_bm;
	/* PE2 (RXD0) as input. */
	PORTC.DIRCLR   = PIN2_bm;

	
	// Baud rate selection
	// BSEL = (32000000 / (2^0 * 16*9600) -1 = 207.333 -> BSCALE = 0
	// FBAUD = ( (32000000)/(2^0*16(207+1)) = 9615.384 -> it's alright
	
	USARTC0_BAUDCTRLB = 0; //Just to be sure that BSCALE is 0
	USARTC0_BAUDCTRLA = 0xCF; // 207, 9600 BAUD
	
	
	//Disable interrupts, just for safety
	USARTC0_CTRLA = 0;

	//8 data bits, no parity and 1 stop bit
	USARTC0_CTRLC = USART_CHSIZE_8BIT_gc;
	
	//Enable receive and transmit
	USARTC0_CTRLB = USART_TXEN_bm | USART_RXEN_bm; // And enable high speed mode
}

void sendChar(char c)
{
	while( !(USARTC0_STATUS & USART_DREIF_bm) ); //Wait until DATA buffer is empty &'d the status register and USART DREIF bit mask together
	
	USARTC0_DATA = c;
}

int main(void)
	{
	PORTA.DIRSET = 0x38;
	PORTA.OUT =  0x38;
	FastRCClock();
	setUpSerial();

while (1)
	{
	//PORTA.OUT = 0x00;
	//_delay_ms(1000);
	//PORTA.OUT = 0x38;
	//_delay_ms(1000);
	sendChar(0x20);
	_delay_ms(1000);
	sendChar(0xBB);
	_delay_ms(1000);
	//sendChar(0xCC);
	//sendChar(0xDD);
	//sendChar(0xFF);
	}
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am setting the RXCIF flag (I think this should cause the ISR to trigger)

No it doesn't.  Writing a one to RXCIF clears the flag.

 

    PMIC.CTRL |= PMIC_LOLVLEX_bm; //Low level interrupt may be occurring don't stop it
    SREG |= 0x80; //sei(); equivalent

How could a low level interrupt be occurring when global interrupts are disabled?

 

Edit:

void sendChar(char c)
{
    while( !(USARTE0_STATUS & USART_DREIF_bm) ); //Wait until DATA buffer is empty &'d the status register and USART DREIF bit mask together
    
    USARTE0_DATA = c;
}

ISR(USARTE0_RXC_vect)
{
    char temp = 0;
    PORTB.OUT =  0x1C;
    temp = USARTE0_DATA;
    sendChar(~temp);	
}

Having an ISR that calls a function that blocks while waiting until it can write to the USART.DATA register is not a good idea.  Echo the received char in the main loop, not the ISR.

Greg Muth

Portland, OR, US

Atmel Studio 7 (Version: 7.0.1652) on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

Last Edited: Sun. Dec 3, 2017 - 04:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

okay, thanks for the response. 

That makes sense when writing a 1 clears the flag, but how is the interrupt triggered, i.e. what bit value is set to 1 or what occurs to make the ISR trigger? 

I also understand why that line before the sei() does not make sense.

 

Yeah, I try to keep ISR's short, but the code itself is not doing much, so I didnt see the harm, but you're right.

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

what occurs to make the ISR trigger?

The USART receiving a char triggers the interrupt (if the RXC interrupt and global interrupts are enabled).

Greg Muth

Portland, OR, US

Atmel Studio 7 (Version: 7.0.1652) on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

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

Okay, that's what I understood. Is there a way to simulate this? Also, do you see any obvious errors in my code, besides the aforementioned (which I have corrected)?

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

The USART receiving a char triggers the interrupt (if the RXC interrupt and global interrupts are enabled).

And if interrupts for that level, High, Med, or low, are also enabled.

 

JC 

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

@DocJC said:

And if interrupts for that level, High, Med, or low, are also enabled.

Right.  Because this is not the ATmega328P I was thinking about, it is an ATxmega256A3BU. 

 

@MaxwellZ said:

Also, do you see any obvious errors in my code...

No.  But I am curious as to why you are inverting (~) the received char before echoing it:

ISR(USARTE0_RXC_vect)
{
    char temp = 0;
    PORTB.OUT =  0x1C;
    temp = USARTE0_DATA;
    sendChar(~temp);
}

I prefer to use the _PROTECTED_WRITE() macro with CCP-protected registers:

#include <avr/io.h>

void FastRCClock(void)
{
    _PROTECTED_WRITE(OSC.CTRL, OSC_RC32MEN_bm);
    while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for oscillator to be ready
    _PROTECTED_WRITE(CLK.CTRL, CLK_SCLKSEL_RC32M_gc); // switch to 32MHz clock
}

 

Edit: I see a hidden error in the FastRCClock() function.  The first line enables the RC32M and disables the RC2M, the current clock source.  If the Xmega clock hardware did not prevent you from disabling the current clock source, this would be a problem.

 

void FastRCClock(void)
{
    _PROTECTED_WRITE(OSC.CTRL, OSC_RC32MEN_bm | OSC_RC2MEN_bm); // enable RC32M
    while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for RC32M ready
    _PROTECTED_WRITE(CLK.CTRL, CLK_SCLKSEL_RC32M_gc); // switch to RC32M
    _PROTECTED_WRITE(OSC.CTRL, OSC_RC32MEN_bm); // disable RC2M
}

 

Greg Muth

Portland, OR, US

Atmel Studio 7 (Version: 7.0.1652) on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

Last Edited: Sun. Dec 3, 2017 - 10:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth wrote:
I am curious as to why you are inverting (~) the received char before echoing it:

Presumably so (s)he can tell it's actually the software doing the loop-back - and not just a hardware short-circuit?

 

Trouble with this is that it's liable to lead to unprintable character codes!

 

surprise

 

A better idea might be to just add one, or convert upper <--> lower case, etc ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
A better idea might be to just add one,
That's the one I generally do when testing such things and then, of course, typing "HAL" at it.

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

That's a good idea, and yeah I was sending the inverse because I wanted to make sure it was functioning properly. Would you happen to understand why my software is not functioning correctly?

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

Op said " trying to set up communication between 2 XMega "

 

Could this be a simple h/w error,  i.e.  tx -> tx / rx -> rx, instead of the correct way, tx -> rx both directions???

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

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

Nope, my hardware is correct :/

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

Okay, my original code actually works fine, I was just testing incorrectly. Sorry about that!

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

Thanks for feeding black - please mark the solution: https://www.avrfreaks.net/comment...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...