chipKIT® Development Platform

Inspired by Arduino™

Serial Communication with interrupts

Created Tue, 21 Mar 2017 15:48:41 +0000 by Codu_


Codu_

Tue, 21 Mar 2017 15:48:41 +0000

Hi,

I’m currently developing a student project that uses UART communication with interrupts. My main board is the Chipkit Max32, and because of the other requirements of the project I’m now using the MPIDE to develop my application (I will use Chipkit Network Shield, and I don’t find libraries compatible with the Arduino IDE).

I made a simple code to test the serial communication with interrupts, but I never have the result that I want. In next example, I try to configure Serial2 with interrupts in reception. Serial in only used to make debug and Serial1 TX is used to send something to Serial2 RX (both connected with a jump wire in my chipkit board).

volatile uint32_t counter = 5;
volatile char inByte = 'M';        

void __USER_ISR  myISR() 
{
  delay(5);
  Serial.println("int");
  while (Serial2.available())  
  {
    inByte = Serial2.read();
    Serial.println(inByte);
  }
  counter++;
  Serial.println("int_counter:");
  Serial.println(counter);

  //clearIntFlag(_UART2_RX_IRQ);
  clearIntFlag(_UART3A_RX_IRQ);

  Serial.println("Int_e:");
  Serial.println(getIntFlag(_UART3A_ERR_IRQ));
  Serial.println("Int_f:");
  Serial.println(getIntFlag(_UART3A_RX_IRQ));
  //Serial.println(getIntFlag(_UART2_RX_IRQ));

}

void setup() 
{
  // initialize both serial ports:
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(9600);

  setIntVector(_UART_3A_VECTOR, myISR);
  setIntPriority(_UART_3A_VECTOR, 2, 0);
  clearIntFlag(_UART3A_RX_IRQ);
  setIntEnable(_UART3A_RX_IRQ);
  //U3STAbits.URXISEL=0x01;
  counter++;

}

void loop() {

  Serial.println("error:");
  Serial.println(getIntFlag(_UART3A_ERR_IRQ));
  Serial.println("flag:");
  Serial.println(getIntFlag(_UART3A_RX_IRQ));
  Serial.println(counter);
  delay(500);

  Serial1.print(4); //TX1 is connected to RX2 with a wire
  delay(500);
  Serial.println(getIntFlag(_UART3A_RX_IRQ));


}

The results are: -When I receive one char in Serial2 my routine goes to my ISR function. That is ok! -In myISR() the function Serial2.available() returns 0. That is not ok, I never read before! -I clear the flag “clearIntFlag(_UART3A_RX_IRQ);” and after I read “Serial.println(getIntFlag(_UART3A_RX_IRQ));” and the result is 1. That is not ok (maybe is normal because apparently, I could never read the buffer). -my routine runs the ISR function in loop and never returns to main loop. That is not ok (maybe is expected because I could never clean the flag).

I don’t understand what is the problem, if someone can help me I will be very grateful.

Thanks


majenko

Tue, 21 Mar 2017 16:06:29 +0000

The problem is that you are overriding the default ISR for serial reception. This means that:

  • The incoming character never gets read and placed in the buffer, so Serial2.available() will always be 0
  • The RX FIFO is never emptied, so the RX interrupt flag will keep getting set to 1.

In your ISR you cannot use any of the Serial2 reading functions. That includes .available(), .peek(), .read(), etc. Simply because they look at a software buffer, and it's the default ISR's responsibility to fill that buffer, and you no longer have that ISR.

So you must manually read the incoming character(s) from the hardware RX FIFO and deal with them before attempting to clear the interrupt flag.

Alternatively we have an undocumented feature:

void myISR(int c) {
    Serial.println(c);
}

Serial2.attachInterrupt(myISR);

which triggers your own ISR function automatically from within the default ISR. It will be called once for each character available in the hardware RX FIFO.


Codu_

Wed, 22 Mar 2017 20:39:58 +0000

Ok. I manually read the incoming character(s) from the hardware RX FIFO and everything works as expected.

Thank you very much for the support.