(Solved)No SerialPort eventhandlers fired upon wrong init

Hi all,

And again, i’ve returned.

Not with a single question, and the hope that someone gives me an answer.
This time, i’ve managed to sort the problem out myself. The reason why i’m posting this, is because i think that there is a problem in the firmware of Fez Domino, or in NETMF. By posting this, i hope that someone will actually take the effort to try this out for themselves(when possible) and post some feedback.

The situation is as follows:
I’ve got a MOD-GPS from Olimex (MOD-GPS), which uses the UEXT connector to communicate with the Domino. It uses the +3.3v, gnd and COM2 RX/TX.

So far, so good. I’ve programmed some very basic code to read the GPS module. Everything works fine, as long as i start the program in Visual Studio, using the ‘start debugging’ button(or F5). The program let’s the LED flash when data which comes in over COM2, and it also writes that data to an USB drive.
Now the weird part starts:
When powering the Domino without a pc(using the power connector), or only using the usb-connector, nothing happend. No flashes, no usb-activity, no nothing. I tried (almost) everything! Putting it in release mode, testing led flash without data, writing bullshit data to the USB drive.
In many code examples, the SerialPort class is used by registering a ‘data received’ event handler. This didn’t work, unless i started the Domino using the ‘start debugging’ button in VS.
Solution:
I checked the SerialPort class for incoming data myself, and hey presto! There is actually data coming in! So, i’ve wrote a seperate thread in which the serialport’s ‘bytestoread’ field is constantly checked.

In code.
Doesn’t work:


{
SerialPort COM2 = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One);
COM2.DataReceived += new SerialDataReceivedEventHandler(COM2_DataReceived);
COM2.Open();
}
void COM2_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
... LED flash, Read data using COM2.Read(), ect. ...
}

Works:


{
SerialPort COM2 = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One);
COM2.Open();
}

/** Seperate thread */
void WorkerThread
{
      while(true){
            if(COM2.COM2.BytesToRead>0){
                  ... LED flash, Read data using COM2.Read(), ect. ...
            }
            Thread.sleep(COM_CHECK_INTERVAL);
      }
}

}

Solution for using Eventhandlers
When using the eventhandlers, they must be added to the serialport AFTER opening the serial port.
So this:

SerialPort COM2 = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One);
COM2.DataReceived += new SerialDataReceivedEventHandler(COM2_DataReceived);
COM2.Open();

is the wrong way. And this:

SerialPort COM2 = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One);
COM2.Open();
COM2.DataReceived += new SerialDataReceivedEventHandler(COM2_DataReceived);

Is the good way.

Case closed. Lesson learned. Time wasted. :wink:

Instead of summarizing the code in your event, can you spell it out?

Code runs much slower when running with the debugger attached. I have a lot of experience with SerialPort on a full PC and I absolutely refuse to use the event because in my experience the events can get stacked up. If you have written non-reentrant code or something that’s a bit off in there, you could be throwing an exception when you start because you will get a lot of data at once the first time (RX buffer is probably full as the framework is starting up).

Hi Silic0re,

I’ve spelled it out, above the code? What are you asking me?

And, thats probably right. But no, the code inside the eventhandler only wrote the data off the SerialPort into another buffer. Constantly. That data was sent to the USB drive once in a while. Also, as a visual indicator, i made the LED blink. But, when the program is running that fast, i can imaging not being able to spot blinks, because it is blinking that fast.

Again, i’ll test some more.

I’m asking can you please post the full code listing of the COM2_DataReceived event.


... LED flash, Read data using COM2.Read(), ect. ...

doesn’t help us find any possible exceptions being thrown or problems with your code.

Ok. Well, that is written as an idication for trying all those things. :slight_smile:

I just tested this basic code:


        void COM2_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // Visual indication of data received.
            led.Write(true);
            // Read the number of bytes to read from the serialport
            int numbytes = COM2.BytesToRead;
            // Create local array to put data from serialport in.
            byte[] bytearray = new byte[numbytes];
            
            // Read the bytes from the serial port
            COM2.Read(bytearray, 0, numbytes);

            // Write received data to USB drive.
            Write(bytearray, "test.txt");
        }

But the LED won’t even come on. So it’s not fired even once.
The LED is initialized on ‘off’.

led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);

Can you post the code for your “Write” function at the end?

I have a feeling that you are opening/closing a file each time you get data on the serial port. That is a very time consuming process and can cause problems if you get another serial data received event while you are writing your data out to the file. I would suggest putting the data in a buffer somewhere and writing it to the file only periodically.

Think of the data received event like an interrupt. You want to get in and get out as quickly as possible. You should be storing the data in a global buffer and raising a flag for your main application code to deal with it, instead of trying to do it in the event. This is where events can stack up, especially when first starting up a program where the serial data can come very quickly.

Since you are reading NMEA data from a GPS, you can add your data to a buffer until you get the “\r\n” at the end of the sentence and then raise a flag telling the main code that you have a new sentence to process. That is how I write my GPS code.

I know. The write function is placed there because i thought something went wrong while trying to read/write to the buffer, since i’m using different threads for the GPS and USB operations. (which i’m not doing in this testsetup)

Like i said earlier, the LED won’t even come on. The USB drive was just a double-chek to eliminate possible errors using the LED.

In previous tests i returned ALL incoming data to COM1, but that didn’t work either. No data was coming out of COM1.

And with all of these tests, the problem was solved when i removed the eventhandler, and used a while-loop. (like i explained in the first post)

Try adding an event for COM2.ErrorReceived and see if you are getting some kind of error on the serial port.

That’s a good one. adding now.
Edit: No response on that event. I tried using the same thing: turning the LED on and write to USB.
I also ran the code which reads the COM port constantly in a second test, like i told in the first post. That went OK: incoming data was actually written to the USB drive. But still no eventhandler being fired…

I might be wrong, but I vaguely remember there being an issue with the serial port in regards to the order of commands.

I think you must first open the port then attach to the event.

This gives problems:


SerialPort COM2 = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One);
COM2.DataReceived += new SerialDataReceivedEventHandler(COM2_DataReceived);
COM2.Open();

But this works:


SerialPort COM2 = new SerialPort("COM2", 19200, Parity.None, 8, StopBits.One);
COM2.Open();
COM2.DataReceived += new SerialDataReceivedEventHandler(COM2_DataReceived);

I have not tested it, but that is what I remember…

Errol. Thanks for your reply. I assumed that it didn’t matter because it also worked in the debugger. But it’s worth a shot. Reporting back in a few!
Edit: You’re right! This works! How strange is this?! How bad of me for not trying this much sooner. Like i said, the fact this worked while debugging made me assume that wasn’t the issue.
Well, it’s sorted out now. Thanks Errol and Silic0re!

Glad I could help. :slight_smile:

retracting statement…didn’t read enough.