5 Replies Latest reply on Nov 6, 2018 11:23 AM by odissey1

    UART temporarily disable interrupts while receive large amounts of data.

    chris.vanbrederode_3548136

      Hello All,

       

      I'm having a bit of a difficulty.  I have a board with a PSoC 5 and a header with a Digi XBee Modem (Wifi or LTE-M, but it doesn't matter to the issue).  The PSoC and Digi talk over a UART at 9600 bps, with just the internal 4 byte FIFO.  I'm also running FreeRTOS.

       

      Here's the scenario: I'm trying to download ~190 KB files over the XBee.  I have an ISR routine on the UART, that moves data into a FreeRTOS stream buffer, if there's room in (important point).  Then a task waits on the stream buffer, and moves data from it to another buffer, then writes that to the SD card when there's 64 bytes to write.

       

      Mostly, this works just fine, with the stream buffer having on average 2 bytes in it at a time.  Until some other major task under FreeRTOS happens (notably a datalogging action every 10 minutes that formats several handfuls of variables and write almost 500 bytes to the SD card.  When this happens, the UART ISR will fill the stream buffer to capacity, and then things go south.  Because I don't want to lose data, my ISR doesn't move data from the FIFO to the stream buffer if there's no room.  But because I'm not moving data from the FIFO, the interrupt happens again immediately, without allowing any other code to run (or, if the interrupt is set to edge driven, the interrupt never happens again).

       

      Here's some code snippets:

       

      /*

      * XBC Rx Interrupt Handler

      *

      * This passes data to the xbc stream buffer

      */

      void XBC_Rx_ISR_Interrupt_InterruptCallback(){

         

          BaseType_t higherTaskWoken = pdFALSE;

          uint8 status = UART_XBC_Cellular_ReadRxStatus();

       

          size_t cap = xStreamBufferSpacesAvailable(xbcInputQueue);

       

          while (status & UART_XBC_Cellular_RX_STS_FIFO_NOTEMPTY && cap > 0){

             

              uint8 temp = UART_XBC_Cellular_ReadRxData();

             

              if (xStreamBufferSendFromISR(xbcInputQueue, &temp, 1, &higherTaskWoken) != 1){

                  UART_232_PutStringConst("-<!ERR XBC UNKNOWN!>-\r\n");

              }

             

              status = UART_XBC_Cellular_ReadRxStatus();

              cap--;

          }

          portYIELD_FROM_ISR(higherTaskWoken)l

      }

       

      And the loop that reads the stream buffer:

       

                      while (content_length > 0){

                          r = xStreamBufferReceive(xbcInputQueue, &c, 1, pdMS_TO_TICKS(2000));

                          if (r == pdFALSE){

                               //timeout

                          }

                          content_length--;

                          Buffer_xbc[Buffer_xbc_Ptr++] = c;

                          if (Buffer_xbc_Ptr == WRITE_TO_DISK_BLOCK_SIZE){

                                  FS_Write(pFile, Buffer_xbc, WRITE_TO_DISK_BLOCK_SIZE);

                                  Buffer_xbc_Ptr = 0;

                          }

                     }

       

       

      Is there a way to turn off or delay the Rx interrupt from the UART long enough for the task to catch up and empty the stream buffer, or do I need to work out another solution.  I believe I could switch the whole thing to polling (I don't get data from the XBee unless I'm expecting it) if that is the correct thing to do in this situation.  It just would be a lot of leg work.

       

      Thanks in advance!!