I am using AT32UC series (custom board) for my application and Usart RS485 interrupts are killing me today. I have Rx interrupt set up and working. Now trying to add Tx interrupt to be called if data is available to send. My problem is that the tx interrupt is never called. After few hours fighting for this I've found something strange.
int main()
.....// other initialisations
INTC_init_interrupts();
INTC_register_interrupt(&timerInterrupt, AVR32_TC_IRQ0, AVR32_INTC_INT0);
INTC_register_interrupt(&rs485TxInterrupt, AVR32_USART2_IRQ, AVR32_INTC_INT1);
INTC_register_interrupt(&rs485RxInterrupt, AVR32_USART2_IRQ, AVR32_INTC_INT0);
Enable_global_interrupt();
From above, I get rx interrupt working and if I change the order of INTC rx interrupt with tx interrupt, I get tx interrupt working and no rx interrupt. Function calling each interrupts are also in main. Can someone explain what is wrong with my understanding in implementing interrupts. I've also attached snippets of relevant codes for further reference.
static void SendTx(void)
{
txLength = 5;
gpio_set_pin_high(AVR32_PIN_PA10);
txBuf[0] = ATEAddress;
AVR32_USART2.THR.txchr = txBuf[0];
tx_outctr = 1;
if(peaksRdy_flag == true)
{
txBuf[1] = peaks[loop][0];
txempty_flag = false;
AVR32_USART2.ier = AVR32_USART_IER_TXRDY_MASK;
}
}
__attribute__((__interrupt__)) static void rs485TxInterrupt(void)
{
//AVR32_USART2.IDR.txrdy = 1;
AVR32_USART2.THR.txchr = txBuf[1];
AVR32_USART2.CR.sttbrk = 1;
gpio_set_pin_low(AVR32_PIN_PA10);
gpio_set_pin_low(AVR32_PIN_PA06);
if(!txempty_flag)
{
//gpio_set_pin_high(AVR32_PIN_PA06);
//AVR32_USART2.IMR.txrdy;
}
}
static void readRx(void)
{
AVR32_USART2.CR.txdis = 1;
AVR32_USART2.ier = AVR32_USART_IER_RXRDY_MASK;
}
__attribute__((__interrupt__)) static void rs485RxInterrupt(void)
{
//AVR32_USART2.IDR.rxrdy = 1;
uint32_t data;
static char RxDatalength = 98;
data = AVR32_USART2.RHR.rxchr;
if(data & 0x00000100)
{
if((data & 0x000000ff) == 0x92) //dsp board address = 0x92
{
rxBuf[0] = data;
addr_flag = true;
rxInCtr = 1;
}
else
{
addr_flag = false;
return;
}
}
else if (addr_flag == true)
{
rxBuf[rxInCtr++] = data;
if(rxInCtr == 2) // command check
{
if(data < 0x80)
{
addr_flag = false; // reset addr flag
if(data==0x10)//START
{
start_flag = true;
}
else if(data == 0x11) //CANCEL
{
gpio_set_pin_high(AVR32_PIN_PA13);
break_flag = true;
}
}
else if(data >= 0x80)
RxDatalength = 3;
}
if ((rxInCtr == RxDatalength) || ((RxDatalength == 98) && (rxInCtr == rxBuf[2]+1)))
{
//gpio_set_pin_high (AVR32_PIN_PA16);
addr_flag = false;
start_flag = true;
}
}
gpio_set_pin_low(AVR32_PIN_PA13);
}
Thanks in advance!
You are registering two different routines for the same interrupt (AVR32_USART2_IRQ
), so that the second registration just overwrites the first one.
Notice that there's only one IRQ/ISR for both RX and TX in the AT32UC and you'll have to determine which one occurred yourself in your ISR, see e.g. http://www.avrfreaks.net/forum/how-distinguish-usart-interrupts-txrdy-rxrdy.