This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

UART interrupt routine

hi guys,

can i have some help regarding the given code below.

in the code i am capable of using the interrupt based receiving.

but i have to tell how much byte i m sending.

Now i wish whenever the data come it should go to IRQ handler

void UART0_IRQHandler(void)
{
  if(UART_GetITStatus(UART0, UART_IT_Receive) != RESET)
  {
        RxBuffer[RxCounter++] = UART0->DR;
        RxBuffer[RxCounter++] = UART0->DR;
        RxCounter==rxNum +2;
        if(rxNum == 0)
        {
         rxNum = (RxBuffer[0] * 256) + RxBuffer[1];
         while((RxCounter - 2) != rxNum)
         {
          test_num++;
          if((UART_GetFlagStatus(UART0, UART_FLAG_RxFIFOEmpty) != SET)&&(RxCounter < RxBufferSize))
            {
              RxBuffer[RxCounter++] = UART0->DR;
            }
          }
          rxNum = 0;
          test_num = 0;
        }
    }
}


Parents
  • You just can't assume there are two characters in the FIFO, unless you happen to know that it was a watermark interrupt and not a timeout interrupt.

    Remember that if you send a large message - larger than the FIFO can handle - then the UART must generate multiple interrupts. The first interrupt is likely to happen when there are two or more characters in the FIFO (i.e. a FIFO watermark interrupt where the interrupt happens to let you empty it before it overflows) but the last interrupt may happen for a single byte. When you don't get enough characters to reach the FIFO watermark level, you will get a last FIFO timeout interrupt, to let your code pick up the remaining part of a transfer.

    You can receive as big message as your buffer can handle - or even larger in case you have a state machine that starts to consume data on-the-fly.

    But your interrupt code should contain something like:

    while (UART_GetFlagStatus(UART0,UART_FLAG_RxFIFOEmpty) != SET) {
        c = UART0->DR;
        if (my_rx_buffer_full)
            my_rx_overflows++;
        else
            RxBuffer[InsertPos++] = c;
    }
    


    Your interrupt routine is of course free to look at received data to figure out where a message starts/ends. But that is totally separate from how the interrupt routine should check the status flags to figure out if it can pick up more data or not.

    It would be considered a bug in your program, if you can't consume data fast enough from your receive buffer, so the UART interrupt handler gets a buffer overflow.

    Another thing - you do not want the receive buffer to insert like that. It's way better to have a ring buffer, where one counter is insert position (producer) and one counter is remove position (consumer). Then you get the lucky situation that the interrupt only modifies the insert (write) position, and the main program only modifies the remove (read) position. The world is full of sample implementations. Go for one where the buffer size is 2^n large and where the two indices are allowed to use the full numeric range - it has the advantage that you can have 0 to n characters in the buffer. The variant that folds the indices when they reaches the full size of the buffer can only store n-1 entries to avoid the duality that rx-idx == tx-idx would happen both for a full or for an empty buffer.

Reply
  • You just can't assume there are two characters in the FIFO, unless you happen to know that it was a watermark interrupt and not a timeout interrupt.

    Remember that if you send a large message - larger than the FIFO can handle - then the UART must generate multiple interrupts. The first interrupt is likely to happen when there are two or more characters in the FIFO (i.e. a FIFO watermark interrupt where the interrupt happens to let you empty it before it overflows) but the last interrupt may happen for a single byte. When you don't get enough characters to reach the FIFO watermark level, you will get a last FIFO timeout interrupt, to let your code pick up the remaining part of a transfer.

    You can receive as big message as your buffer can handle - or even larger in case you have a state machine that starts to consume data on-the-fly.

    But your interrupt code should contain something like:

    while (UART_GetFlagStatus(UART0,UART_FLAG_RxFIFOEmpty) != SET) {
        c = UART0->DR;
        if (my_rx_buffer_full)
            my_rx_overflows++;
        else
            RxBuffer[InsertPos++] = c;
    }
    


    Your interrupt routine is of course free to look at received data to figure out where a message starts/ends. But that is totally separate from how the interrupt routine should check the status flags to figure out if it can pick up more data or not.

    It would be considered a bug in your program, if you can't consume data fast enough from your receive buffer, so the UART interrupt handler gets a buffer overflow.

    Another thing - you do not want the receive buffer to insert like that. It's way better to have a ring buffer, where one counter is insert position (producer) and one counter is remove position (consumer). Then you get the lucky situation that the interrupt only modifies the insert (write) position, and the main program only modifies the remove (read) position. The world is full of sample implementations. Go for one where the buffer size is 2^n large and where the two indices are allowed to use the full numeric range - it has the advantage that you can have 0 to n characters in the buffer. The variant that folds the indices when they reaches the full size of the buffer can only store n-1 entries to avoid the duality that rx-idx == tx-idx would happen both for a full or for an empty buffer.

Children
No data