Hello, I am now using the QNX6.3.2 to read data from a serial port connected to a peripheral device.
The procedure is like this: i first send a request packet, the hardware should return the responding packet, and then read them into the buffer. And the data length each time i read should be 30 bytes. This is usually the case. But sometimes, the data bytes i could read from the serial port is less than 30 bytes, (I have given enough time for the hardware processing part to render the corresponding packet). And for the lost bytes, they are not the last few bytes in the packet. Instead, the bytes lost usually lie some random positions of the correct packet. what might be the possible reasons?
Can you post your read code. That includes where you read from the serial port and where you place those bytes along with the code that processes those bytes.
/* … some processing for the data received, could be igored,
since the problem still exist without this processing part … */
the write(request) operation;
the read and write keep working with a period of 20ms, and the data length replied is 37 bytes for each request. Thanks for your suggestions.
So each reply packet is a fixed 37 bytes. How big is the send packet? Is it also 37 bytes?
One other question, is your serial link entirely full duplex RS232 or is there any single duplex RS232 or RS485 involved here? I ask because it’s possible the timing might be VERY tight on sending/receiving that much data on single duplex serial lines and thus you could get some corruption.
Since you didn’t post exact code, it’s hard to see if you have any coding mistakes that might explain the problem. For example are you memsetting your receive buffer to all 0’s before doing the read() to ensure you don’t have left over data in the read buffer?
If you don’t have RS485 or a single duplex serial line, I’d try to code a much simpler example that uses no threads. Basically, you send your packet and then wait for a reply. You can time how long you wait for a response to make sure it’s less than 20 ms and print an error if it’s not. I’d make sure that works 100% reliably before going any further:
uint64_t _cycle0; //initial clock cycle as the application start
uint64_t _cps = SYSPAGE_ENTRY(qtime)->cycles_per_sec; //cycles in one second
uint64_t _cpms = (uint64_t)(0.001*_cps);
Since the hardware needs around 15ms to accept the request packet and render the corresponding packet, so 20ms is long enough (i used 15ms in the above code to wait for the response). And following is the output: obviously, most of the time, the packets are 37 bytes. But some are less than 37.
Thx, but in the output packet, most of the time is ok. So i don’t think the status of the serial port may get changed during the execution of my program. Somehow finally i believe it might be the malfunction of the hardware itself, or the configuration of it. And I also don’t see any further settings for the serial port. Look forward to your ideas. Thanks.
It would have been nice to print out the number of bytes received as it’s a pain to manually count them on each line
I assume that the reply packets always start with the ‘55 55 41’ sequence. From looking at the output it’s clear the device always replied each time to your request and there aren’t any extra bytes waiting around in the serial buffer because if there were, each line wouldn’t start with the ‘55 55 41’ sequence but would instead have left over bytes from prior packets (which did happen twice time so your 15 ms time isn’t quite enough time to wait so you might want to retry the test with 20ms wait and printing number of bytes received).
But yeah, it certainly appears as if the hardware is configured incorrectly/not working or else the documentation that the reply packet is always 37 bytes long isn’t right.
The other things to do are:
Try another serial cable (I assume you have the device plugged in directly via a serial cable for testing) just on the off chance the cable has an issue.
Check the hardware docs to make sure you have flow control correct (H/W, S/W, none) on the serial port.
Thanks, Tim. just tried the 20ms suspension. the annex is the output.
The serial port configuration is: 8bits, no parity check, stopbit =1, no HW or SW flow control, which comply the settings of the hardware product. btw, how to set the start bit to 1?
Ah, now that output file makes a TON more sense to me.
Here is the first few lines of the file:
COMMENT:
NAV440, poll mode, A0, usleep(20000):
Bytes rcved: 1
55
Time used: 0.0332359
Bytes rcved: 36
55 41 30 1e 00 cb 00 3e 35 0a 00 03 00 00 00 05 00 12 ff c0 f3 2d 03 65 f4 b9 f1 e9 1c f3 00 00 03 00 2c e2
Time used: 0.0218138
Bytes rcved: 37
55 55 41 30 1e 00 cb 00 3e 35 0a ff fe ff ff ff ff 00 10 ff c0 f3 2d 03 3c f4 c0 f2 48 1c f3 00 00 03 00 60 85
Time used: 0.0217017
Bytes rcved: 1
55
Time used: 0.0311993
Bytes rcved: 36
55 41 30 1e 00 cb 00 3e 35 09 00 00 00 00 ff ff 00 12 ff c6 f3 2e 03 6b f4 bd f1 e6 1c f4 00 00 03 00 16 fd
Time used: 0.0223163
Bytes rcved: 37
55 55 41 30 1e 00 cb 00 3e 35 09 00 01 00 00 ff f5 00 12 ff c3 f3 2e 03 49 f4 c4 f1 fa 1c f4 00 00 03 00 7c 47
Time used: 0.02177
Notice, the first read returns 1 byte. This is because as soon as the first byte arrives on the serial line, the serial driver is waking up your program and you read 1 byte (the rest haven’t physically arrived yet). Ie:
Bytes rcved: 1
55
Time used: 0.0332359
Now your program processes and prints out the above lines and sends another packet to the device and waits again for data.
This time you are returning right away with the remaining 36 bytes from the 1st packet which the serial driver has buffered while your program was away printing out the single byte and sending another packet.
Then you print and wait again and once again you get woken on the 1st byte from the device and repeat the sequence all over again. Eventually things fall so far behind that muliple packets get queued up in the serial driver buffer and hence you see those large numbers of bytes returned.
The issue for you is that you are thinking the read() call will wait until it receives 37 bytes. But you told read() to expect anywhere up to 4096 bytes. But when you check the doc’s on read() you’ll see it can return fewer bytes than requested (or else you’d never return since you’ll never get 4096 bytes).
What your read thread has to expect is that it’s not going to get 37 bytes at a time. It’s going to get them sometimes 1 at a time and sometimes 2 at a time, sometimes 36 at a time etc. Your code has to deal with getting fewer bytes than expected and put together the multiple strings into one 37 byte packet.
This happened to me once. As I remember it was the ohpaged flag. It did not happen with a P3 which run the application some time ago… but later, the hardware was replaced by a P4 and this crazy flag began to change from time to time. Really never knew why, but it did. We changed the application to set this flag before each write, and the application did not fail anymore.
But ok. This is not necessarily the case. I only suggest that you check this, to rule out a potential problem.
Thanks so much for your analysis. Yes, i could make up a whole packet after several read operations. But our application requires to have a complete packet every 20ms. And the hardware itself claimed to be able to respond within 20ms. So after each request packet, after 20ms, the read operation should be able to retrieve 37 bytes data in the buffer. And i will check with the flag configuration as JM said. Thanks again.
If the hardware claims it responds in 20 ms you better plan on leaving a couple extra ms to read the data. In other words if you sleep for 20 ms after sending a packet and then try and read, it may not have all arrived back yet because their time claim is going to be based entirely on UART hardware transmit time + processing turn around time on their CPU. They can’t make any guarantees about the sending O/S having the data in 20 ms.
That’s because your QNX system could be slightly busy so the serial driver doesn’t get enough time to run to get all 37 bytes from the hardware UART.
Thanks but how should i set this flag in the code everytime b4 the write operations. I checked the serial port status and didnot find the ohpaged settings somehow.