devc-ser8250 write v/s read

Greetings!

I am using devc-ser8250 to communicate with my serial interfaced card. When sending the data to the card, everything works fine. I write an alert byte, wait for acknowledgement and then send the entire data packet.
But the problem occurs when the card wants to send the data.

According to the protocol, the card will send an alert byte and wait for acknowlegment (ack) from the host CPU only till 100 ms. If the card fails to receive the ack within 100 ms, it will again send the alert byte or send the data packet, if otherwise. This process of card sending the alert byte goes uptill 3 seconds.

So, in my scenario, I read the alert byte as
read (portHandle, readBuffer, 1);
tcflush (portHandle, TCIFLUSH);

and then write the ack as
write(portHandle, ack, 1);
tcdrain(fd);

and then wait for the data packet as
read(portHandle, dataBuffer, sizeof(dataBuffer);

Unfortunately, my dataBuffer contains countless of alert bytes with no data at all.

To tweak this out, I used another application to:

  1. write multiple acks after reading the first alert byte
  2. write multiple acks before and after reading the first alert byte

In the first case, the output still remained the same.
But in the last case, I got the data. It suggested that there is some synchronisation problem between writes and read.
The flags O_SYNC, O_DSYNC and O_RSYNC also don’t work, in the sense that the app don’t read/write any data then.

I also tried the O_NONBLOCK flag, but still faced the same problem.

Any suggestions on how to tackle this problem.

Rahil,

How do you know the card is working correctly in the case where your app is sending to the card? Is there a way to verify that it received the data correctly?

Regarding the code flow on the receive side:

  1. Why are you doing the tcflush() command? I am assuming you are hoping to flush any garbage from the input buffer?
  2. Why are you doing the tcdrain() command? What reason do you have for wanting to wait for the data to be outputted by the driver?
  3. In blocking mode your read() command doesn’t have any way to exit if there ever occurs a case where you get fewer than expected bytes of data.

What kind of app are you using to do these tests? Is it just a simple short test program? Are you doing the write test AND read test at the same time?

Here’s my guess as to what’s happening (based on some assumptions that you are using a simple test program to read from the card. Also it assumes the card can send data on it’s own and isn’t a master/slave where it only sends data after you send data to it.)

  1. The card probably doesn’t know when your app starts and likely is always trying to send data. Hence it is likely perpetually sending the alert byte even when your program is not running. This is probably filling up the serial buffer in QNX with alert bytes.
  2. Your program starts, sees an alert byte and then sends the ack and then reads the reply but the buffer is full of alert bytes so it looks like you only get alert bytes. The real reply is probably deeper in the buffer.

I’d suggest that when you start your test app the first thing you do is clear the read() buffer. Then try the receive-reply-receive data scenario you describe.

Tim

The card communicates with my app using a link layer protocol. So, when my app sends an Alert, the card responds back with the acknowledgement… That ensures me that the card is working correctly. Secondly, during initial testing, I sent the data packet, with intentional delay in transmitting the data packet after ack, containing one or two bytes resembling the alert byte. The card at that time responded with the equal numbers of ack bytes, as expected. So, I think I can only verify it by getting the response from the card.

Yes.

I did that to ensure that the driver actually transmit the ack to the card and then shall I wait for the data packet to come. Moresoever, even if I had sent the ack, I had still got the Alert bytes deep down the buffer. So, that prompted me to use this.

yeah…as an alternative I used readcond calls.

I’m using a single instance of the test program. I don’t use two different test app. In the same application I write the alert, wait for the ack, and so on.

Yeah you are right. That’s why I have to clear all the accumulated Alert bytes and then transmit the ack…(It worked)

I verified this and came to the conclusion that the ack byte was actually not getting transmitted.

Though it is silly, the actual problem was that the app was not transmitting the ack byte…due to this

write(portHandle, ack, 1);

All I did was to replace the above with the following and it all started working.

write(portHandle, &ack, 1);

Well…I’m all but thankful to you for the reply.