Overview: I'm trying to trigger an Overrun error indication, by issuing long delays between each byte read from the serial port. To make long story short - I don't get this event.
The test: The DTE is configured to work at 920000BPS 8N1, no flow control. The DTE is connected to my Windows10 host via "Silicon Labs CP210x USB to UART Bridge" device.
The provided code fragment opens the port, calls the SetCommMask function. A delay of 10 seconds was inserted between each call to ReadFile within a loop. The DTE continuously sends data at a stable rate.
The problem: I don't get any Overrun signal from WaitCommEvent.
Question: Is there a problem with my code? is there some known limitation with the USB driver? Do I need to use flow control to get noticed about overrun events?
#include <Windows.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
HANDLE hComm; // Handle to the Serial port
BOOL Status; // Status
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
COMMTIMEOUTS timeouts = { 0 }; //Initializing timeouts structure
char SerialBuffer[64] = { 0 }; //Buffer to send and receive data
DWORD BytesWritten = 0; // No of bytes written to the port
DWORD dwEventMask; // Event mask to trigger
char ReadData; //temperory Character
DWORD NoBytesRead; // Bytes read by ReadFile()
unsigned char loop = 0;
wchar_t pszPortName[10] = { 0 }; //com port id
wchar_t PortNo[20] = { 0 }; //contain friendly name
//Enter the com port id
do
{
printf_s("Enter the Com Port: ");
wscanf_s(L"%s", pszPortName, (unsigned)_countof(pszPortName));
swprintf_s(PortNo, 20, L"\\\\.\\%s", pszPortName);
//Open the serial com port
hComm = CreateFile(PortNo, //friendly name
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE)
{
printf_s("\n Port can't be opened\n\n");
break;
}
//Setting the Parameters for the SerialPort
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(hComm, &dcbSerialParams); //retreives the current settings
if (Status == FALSE)
{
printf_s("\nError to Get the Com state\n\n");
break;
}
dcbSerialParams.BaudRate = 920000;//CBR_9600; //BaudRate = 9600
dcbSerialParams.ByteSize = 8; //ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT; //StopBits = 1
dcbSerialParams.Parity = NOPARITY; //Parity = None
Status = SetCommState(hComm, &dcbSerialParams);
if (Status == FALSE)
{
printf_s("\nError to Setting DCB Structure\n\n");
break;
}
//Setting Timeouts
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hComm, &timeouts) == FALSE)
{
printf_s("\nError to Setting Time outs");
break;
}
//Setting Receive Mask
Status = SetCommMask(hComm, EV_ERR| EV_RX80FULL| EV_BREAK/*EV_RXCHAR*/);
if (Status == FALSE)
{
printf_s("\nError to in Setting CommMask\n\n");
break;
}
//Read data and store in a buffer
do
{
Status = ReadFile(hComm, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
//Setting WaitComm() Event
Sleep(10000); /* Ten seconds */
Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
if (Status == FALSE)
{
printf_s("\nError! in Setting WaitCommEvent()\n\n");
break;
}
SerialBuffer[loop] = ReadData;
++loop;
} while (NoBytesRead > 0);
--loop; //Get Actual length of received data
printf_s("\nNumber of bytes received = %d\n\n", loop);
//print receive data on console
printf_s("\n\n");
int index = 0;
for (index = 0; index < loop; ++index)
{
printf_s("%c", SerialBuffer[index]);
}
printf_s("\n\n");
} while (0);
CloseHandle(hComm);//Closing the Serial Port
system("pause");
return 0;
}
Serial port overrun errors should occur as data is sent even after the interface chip and device driver buffers are full.
And a narrow definition overrun will only signal what the interface chip(8250/16550/etc) has detected.
So it's unclear if it will occur even if you take a long interval to call ReadFile.
Please try the following.
Use the overlapped mode for asynchronous processing.
Set all DCB flow control specifications to False
DCB structure (winbase.h)
Set the buffer size to the minimum value in SetupComm
SetupComm function (winbase.h)
Make sure it is set correctly in GetCommProperties
GetCommProperties function (winbase.h)
COMMPROP structure (winbase.h)
Do not call ReadFile
Disable the FIFO buffer or set the threshold to the minimum size in the advanced settings of the device driver properties
You need to call ClearCommError to get more information about the error that occurred.
ClearCommError function (winbase.h)
However, no matter what you do, it may not occur if you are using a USB serial conversion chip.
At the same time as trying the above, please ask the chip vendor if there is an overrun error or if it may be detected, and if so, how to try it.