Serial overruns with ChipworkX

I had this issue before and by reducing the baudrate down to 19200 I am able to get reliable communications with a modem via the UART. I am only using SMS with it.

I now need to get the autoupdate working to get the update from an FTP download.

I can get PPP to connect at 19200 but I get lots of serial overruns which means I can’t get a reliable download and gets handled with the try/catch block but the data is corrupted in this case.

If I up the baud rate to 115200 I get lots of serial overruns even with just the SMS working. It doesn’t really make sense as high speeds should be less likely to have this issue.

Is there a driver issue with UART handling that is causing this? I need a working solution fast! :frowning:

I have the same troubles with EMX and 4.2 SDK.Instantiating the serial port without reading it fast enough causes buffer overflow error to be print out. The more it prints this error, the less it has time to read buffer and so on…

Even flushing input buffer does not solve that.

The only workaround I have found is to throw all serial packets (by reading the buffer) in critical parts of the application and do not throw packets only when I need COM ports (but also doing nothing else than storing Uart data and processing them)

This was not the case with 4.1 sdk.

I was not using events. A big loop that poll serialport.

Now to throw available packets and have empty buffer, I am using the event.


COM_X.DataReceived += new SerialDataReceivedEventHandler(ThrowDataReceivedHandler);



private static void ThrowDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            byte[] buf = new byte[sp.BytesToRead];
            sp.Read(buf, 0, buf.Length);
        }

I hope… but this is just to empty the buffer. in normal mode I don’t use events because the app was spending too much time processing a lot of small chunks of data. I think this depends on the manner data are send by peripherals on com ports. In the case of continuous transfert, I think polling is better.

@ andrem. I am using the data received event.

I am processing the receive buffer fast enough. What I determine is the fault is that the interrupt handler for the UART on the processor is not processing the bytes fast enough and this would cause an overrun error.

I don’t have a lot of data going through the UART as I am only processing SMS messages so it is basically just AT commands back and forth. Even with this, it gets overruns if I use 38400, 57600, 115200 etc. 19200 seems to be stable and I never get any errors when working with SMS but it falls over when I use PPP because of the higher data flow.

My original code for this project was running on a 200Mhz Merdian processor and was happy at 115200 with no loss of data.

Since changing to the ChipworkX I get this overrun error when I use the same code.

I am going to try this running on the G400 in the coming days to see if the fault is apparent on that.

Does anyone know what the internal buffer size is for the UART’s? I was getting another issue on a Cobra 2 board and this appeared to have a 16384 byte receive buffer as this was the size it was reporting when I got the overflow on that. Not same issue.

On the datasheet for the ChipworkX there is an RTS and CTS lines for COM3 and I have these connected to the GPRS module. Right now, I have handshaking enabled as NONE.

Is it a simple case of enabling handshaking for these ports to work or do I have to do any other software changes?

I am wiring a test programme for the ChipworkX that will only use Serial COM3 as per my existing design as I want to see if serial overruns happen with higher baud rates without the other code overhead. I suspect that it will fail. I’ll post it here later when I have it ready.

@ Dave McLaughlin - Dave, a friend of mine recently told me he was experiencing a similar issue using a GPS and Spider. I suggested he makes sure its not something else that keeps the processor so busy that it gets overflows. And lo and behold… it turned out that if he disables his Ethernet web server code, the problem disappears. In the end he was able to work out a way to get it to work for him by just reading the GPS periodically and keeping the serial port closed otherwise. I suggest that you also make sure its not some completely unrelated part your code that contributes to the problem. Maybe temporarily disabling other functionality to see if the problem disappears.

@ KiwiSaner.

Interesting point. I disabled all the other code completely this time and I can run at 115200 with no overruns except when I dial a PPP connection.

Putting back the display updating and the other serial port handler, it keeps working, again except for PPP connection.

I printed out the serial port buffer BytesToRead and this is what it shows:


gsm Serial Overrun
Size = 365
gsm Serial Overrun
Size = 408
gsm Serial Overrun
Size = 452
gsm Serial Overrun
Size = 21
gsm Serial Overrun
Size = 47
gsm Serial Overrun
Size = 90

That is just not enough data to be causing a buffer overrun. This error I believe is coming from the UART itself where the byte is not read out before the next one arrives. This is quote common when the interrupt handler does not process the data fast enough. I am only running the comms port at 57600.

What’s strange is that this all worked fine on a different NETMF device running the GSM connection at 115200 with no data loss.

I am trying to setup the G400 to work with this on test. Needs a little more work yet as the G400 does not support the PPP so I need to edit the code to use the TCP commands within the modem to test the connection at speed.

I’ve disabled the display update and analog handling threads so the only thread now running during the PPP connection is the one that dials the PPP connection and starts the HTTP request.

I keep getting CLR_E_FAIL (6) on the socket connection Read of the stream but not on every call to it.

I am still getting Serial Overrun errors on the serial port used for the PPP connection. This should not be happening at 9600 bps.

Has anyone an alternative method of downloading an APP.HEX file from a server I can possibly try?

Hi Dave. This is a long shot, but maybe you can try to do a serial.DiscardInBuffer(); just before you attempt to get the file. Another possibility is to try and get the file in chunks and do a serial.DiscardInBuffer(); after each chunk, but I have no idea how feasible it is to do get the file in chunks.

I can’t do that and risk upsetting the PPP driver. After I get a connect on the serial port all the handling is passed to the PPP driver.

I am going to create a test programme tomorrow on the ChipworkX development board as I am convinced the issue is in the underlying UART driver. This same code worked fine talking a the modem at 115200 on a different .NETMF board so I can’t see any other reason for the failure. I’ll post the test programme tomorrow if I get the results I expect.

I just wrote a test programme to run on the ChipworkX development board.

With the serial port running at 115200 bps and data being transmitted to it every 20ms there is no serial overruns until I touch the screen and then there are loads of them.

I have only 1 other task running that sleeps for 1ms and only has the following line of code.


int x = 1;

When I stop touching the screen, the overruns stop.

This is starting to get frustrating as it should just work.

I have now suspended all threads during the dial PPP and reduced the display update to only redraw the ProgressBar when the value is incremented. It sleeps for 500ms each loop.

This means that there is no other background tasks running. Only the code below.

I have tried, 9600, 19200, 38400, 57600 and 115200 bps and all give me overrun errors when the PPP connection is started and the HTTP request is sending back the ZIP file I am downloading.

I have RTS and CTS connected to the modem but even using handshaking makes no difference.

The following is the code that I am using that is getting the file.


bool GetFileFromServer(string url)
{

            FileStream file = null;
            Stream respStream;
            byte[] byteData = new byte[2048];
            char[] charData = new char[2048];
            int bytesRead = 0;
            long DownloadLength;
 
           try
            {
                file = new FileStream("app.hex", FileMode.Create);
            }
            catch (Exception ex)
            {
                Debug.Print("Failed to create file to save download to");
                return (false);
            }
            HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
            //
            // Set request.KeepAlive to use a persistent connection.
            //
            request.KeepAlive = true;
            //
            // Get a response from the server.
            //
            WebResponse resp = null;

            DLProgressPercent = 0;

            try
            {
                resp = request.GetResponse();
            }
            catch (Exception e)
            {
                Debug.Print("Exception in HttpWebRequest.GetResponse(): " +
                e.ToString());
            }
            //
            // Get the network response stream to read the page data.
            //
            if (resp != null)
            {
                respStream = resp.GetResponseStream();

                Decoder UTF8decoder = System.Text.Encoding.UTF8.GetDecoder();
                //
                // allow 5 seconds for reading the stream
                //
                respStream.ReadTimeout = 5000;
                //
                // If we know the content length, read exactly that amount of
                // data; otherwise, read until there is nothing left to read.
                //
                if (resp.ContentLength != -1)
                {
                    DownloadLength = resp.ContentLength;

                    for (long dataRem = resp.ContentLength; dataRem > 0; )
                    {
                        Thread.Sleep(50);

                        try
                        {
                            bytesRead = respStream.Read(byteData, 0, byteData.Length);

                            dataRem -= bytesRead;
                            //
                            // Save the bytes to the file
                            //
                            file.Write(byteData, 0, bytesRead);
                            //
                            // Work out percentage left
                            //
                            DLProgressPercent = 100 - (int)(((double)dataRem / (double)DownloadLength) * 100.0);
                        }
                        catch (Exception e)
                        {
                            Debug.Print(e.Message);
                        }
                        if (bytesRead == 0)
                        {
                            Debug.Print("Error: Received " +
                            (resp.ContentLength - dataRem) + " Out of " +
                            resp.ContentLength);
                            break;
                        }
                    }
                }
                else
                {
                    //
                    // Read until the end of the data is reached.
                    //
                    while (true)
                    {
                        //
                        // If the Read method times out, it throws an exception,
                        // which is expected for Keep-Alive streams because the
                        // connection isn't terminated.
                        //
                        try
                        {
                            Thread.Sleep(1);

                            bytesRead = respStream.Read(byteData, 0, byteData.Length);
                        }
                        catch (Exception)
                        {
                            bytesRead = 0;
                        }
                        //
                        // Zero bytes indicates the connection has been closed
                        // by the server.
                        //
                        if (bytesRead == 0)
                        {
                            break;
                        }
                        //
                        // Save the bytes to the file
                        //
                        file.Write(byteData, 0, bytesRead);
                    }
                }
                //
                // Close the file on FLASH
                //
                file.Close();
                //
                // Close the response stream. For Keep-Alive streams, the
                // stream will remain open and will be pushed into the unused
                // stream list.
                //
                resp.Close();
}

Any and all help appreciated.

Not tested yet as it requires a bit of work to port to the G400 and currently 4.2 does not support PPP so I won’t have anything to test against.

It’s kind of looking that way just now. For the G400 I am looking to use the AT commands but trying to hook this into the existing TCP/IP stack is not looking like an easy process. It may be that I have to just work at the serial level on this.

I don’t want the cost to replace the existing 8 systems with a G400 processor just to get a working serial connection that has no overruns but if the G400 works, I may have to do this. A costly exercise and one I am not looking too happy with at the present time.

I think I will install the G400 beta board I have tomorrow (luckily I don’t need the missing stuff like Ethernet) and see if I can get this to work with AT commands.

It’s a real shame if PPP does not make it into the portfolio at some point as I see it as a real need for embedded systems. Even Rabbit and Netburner have support for PPP in their latest boards :slight_smile:

Once big issue in changing to the G400. The existing boards have a MicroSD flash disk and the SPI is not compatible with the G400 so I really need ChipworkX for this first 8 to work :frowning:

The new board are already laid out for the G400 so a new batch will work but the prototype has not been tested yet.

Yes :slight_smile: G400 now supports SD on SPI as well as native SD.100% backwards compatible now, except for PPP. Speaking of PPP, we are done with almost all major tasks so will our team work on PPP? Possible no promises yet :slight_smile:

Nice.

Is there any setting changes in code that I need to do to get the SPI option to work?

@ Dave McLaughlin -
All thing need to be changed just is:

PersistentStorage sdPS = new PersistentStorage(“SD_SPI”);

The rest will be same

Thanks Dat, I’ll be looking to port the code over tomorrow.