2
\$\begingroup\$

I'm making a simple communication between an ARM mcu and a GSM module.

The problem I'm facing is how to deal with simultaneously writing and reading to and from the FIFO buffer.

Due to scale of the program I have a big buffer array of 1000 bytes long.

At the moment an interrupt is triggered every time a byte received at UART's data register and the interrupt's routine is filling my 1KB FIFO.

My read routine calculates the available data in FIFO and copies some of the data in a second buffer for further processing.

The interrupt routine stops to put more data when no more space is left in FIFO buffer, to prevent overwriting on reading pointer in the cases my main program didn't have the time to process the data.

Now I'm trying to find the best solution to prevent overwriting on reading pointer while interrupt routine never stops to put data. Is there any solution for this or overwriting is inevitable?

\$\endgroup\$
  • 3
    \$\begingroup\$ A faster processor or quicker software. \$\endgroup\$ – Andy aka Jan 20 '18 at 12:58
  • 2
    \$\begingroup\$ Does the GSM have handshake capability? \$\endgroup\$ – Trevor_G Jan 20 '18 at 13:25
  • 3
    \$\begingroup\$ Using flow control signals to stop the GSM module from sending data could be an alternative. \$\endgroup\$ – Turbo J Jan 20 '18 at 13:30
  • 1
    \$\begingroup\$ Set the interrupt when the FIFO is half full. \$\endgroup\$ – Marko Buršič Jan 20 '18 at 13:39
  • 1
    \$\begingroup\$ @MarkoBuršič. You may have the best answer. An ISR MUST do its job and exit fast. OP may have to compromise by moving 1/2 FIFO content at a time. Maybe the MPU is too slow. OP did not specify clock rates of MPU or UART \$\endgroup\$ – Sparky256 Jan 21 '18 at 2:24
3
\$\begingroup\$

On UART receive event:

    FIFO[Wr_pointer]= UART_Char;
    WR_Pointer++;
    WR_Pointer & = 3FF;// FIFO[1024] roll over 1022..1023...0...1...2
    if WR_Pointer==RD_Pointer then
        Overrun= true;
    else
    {
        SizeFIFO = (WR_Pointer - RD_Pointer);
        SizeFIFO & = 3FF;
    }

Circular buffer example. There is no need to copy data from FIFO to another location since the data are just overwritten.

In the application:

SizeFIFO_temp = SizeFIFO; //you don't want a bug when ISR will insert new data while processing the buffer
for i=0 to SizeFIFO_temp  do
{
   Data[i]=FIFO[RD_Pointer]; //it's all up to you how you process the FIFO's data
   RD_Pointer++;
   RD_Pointer &= 3FF; 
}
SizeFIFO = (WR_Pointer - RD_Pointer);
SizeFIFO & = 3FF;
\$\endgroup\$
  • \$\begingroup\$ Me thinks you missed the bit where he says "copies some of the data in a second buffer for further processing." He does not indicate how long it needs to stay there. \$\endgroup\$ – Trevor_G Jan 20 '18 at 14:00
  • 1
    \$\begingroup\$ @Trevor_G He can process it just as long the buffer is not overwritten with new data - overruned. This is valid for both cases, if he copies a part of the buffer or he processes the data within the same buffer. \$\endgroup\$ – Marko Buršič Jan 20 '18 at 14:07
  • \$\begingroup\$ Yup, question has some big holes in it. \$\endgroup\$ – Trevor_G Jan 20 '18 at 14:18
  • \$\begingroup\$ The data has to be copied from the fifo to another buffer because the incoming data from the GSM is incoming frames of the GSM 0710 protocol which is used for virtual serial ports. Every DLC has to have its own buffer because some AT response may be received with more than one frames with many milliseconds (or even few seconds) in between while frames are always received for other DLCs. (etsi.org/deliver/etsi_ts/101300_101399/101369/07.01.00_60/…). So, I copy a new frame in a second buffer to indicate that a new frame has been received. \$\endgroup\$ – MrBit Jan 20 '18 at 17:15
  • \$\begingroup\$ @MrBit You could expand your question as it's not clear what problems you encounter. Like showing a piece of ISR routine and read routine. \$\endgroup\$ – Marko Buršič Jan 21 '18 at 8:16
0
\$\begingroup\$

The problem I'm facing is how to deal with simultaneously writing and reading to and from the FIFO buffer.

Sequential Not parallel.

Now I'm trying to find the best solution to prevent overwriting on reading pointer while interrupt routine never stops to put data

Code must never exist always in the ISR(generally,depends on application). You need time to copy data, process data,reset flags and various states etc before a new request can be processed. If you are always receiving data when will you do the rest?.

1.When an interrupt occurs: Disable the interrupt(many forget to do this)

2.Since you have a 1K Buffer(Waste of memory,implement a circular buffer of smaller length),copy the data to a buffer and watch a counter when the minimum number of bytes required for a processing is received. Dont forget to enable the ISR again and reset the counter before leaving ISR.

3.When the minimum number of bytes required for a processing is received,process the data.

Alternatively, you can make the uC as the master that polls the GSM for data when needed so that you have control, instead of GSM sending you data always.

\$\endgroup\$
  • \$\begingroup\$ For Cortex-M, a valid coding style is to have all functional code in ISRs, and use the 'sleep on exit' feature to idle when there is no exception to handle. Your 4th paragraph seems contrary to this. \$\endgroup\$ – Sean Houlihane Jan 26 '18 at 10:45
  • \$\begingroup\$ For an event based system it makes sense to put the system to sleep once the event is serviced. \$\endgroup\$ – Akshay Immanuel D Jan 28 '18 at 16:56
  • \$\begingroup\$ Saying 'code must never exist in the ISR' is wrong. Sometimes, ALL code in the system is in ISRs. \$\endgroup\$ – Sean Houlihane Jan 29 '18 at 12:59
  • \$\begingroup\$ hmm...modified the answer \$\endgroup\$ – Akshay Immanuel D Jan 30 '18 at 3:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.