Os 2 Serial Port Programming

Posted on by  admin
Os 2 Serial Port Programming 5,6/10 5975 reviews

This document describes how to program communications with devices over a serial port on a. Multi−processing operating system. Serial Programming HOWTO 2.3.

Allen Denver Microsoft Windows Developer Support December 11, 1995 Summary: Learn about serial communications in Microsoft Windows. The Multithreaded TTY (MTTTY) sample is included with this article. (35 printed pages) for this technical article. Contents Overview This article provides a foundation for learning about serial communications in Windows. This article assumes you are familiar with the fundamentals of multiple threading and synchronization in Windows. In addition, a basic familiarity of the heap functions is useful to fully comprehend the memory management methods used by the sample, MTTTY, included with this article.

Application programming interfaces (APIs) that control user interface features of windows and dialog boxes, though not discussed here, are useful to know in order to fully comprehend the sample provided with this article. Readers unfamiliar with general Windows programming practices should learn some of the fundamentals of general Windows programming before taking on serial communications. In other words, get your feet wet before diving in head first.

(36 printed pages) Introduction This article does not discuss TAPI. TAPI does deserve mention, however, in that it very nicely implements modem interfacing and call controlling. A production application that works with modems and makes telephone calls should implement these features using the TAPI interface. This will allow seamless integration with the other TAPI-enabled applications that a user may have. Furthermore, this article does not discuss some of the configuration functions, such as GetCommProperties. The sample included with this article, MTTTY: Multithreaded TTY (4918.exe), implements many of the features discussed here. It uses three threads in its implementation: a user interface thread that does memory management, a writer thread that controls all writing, and a reader/status thread that reads data and handles status changes on the port.

The sample employs a few different data heaps for memory management. It also makes extensive use of synchronization methods to facilitate communication between threads.

Opening a Port The CreateFile function opens a communications port. There are two ways to call CreateFile to open the communications port: overlapped and nonoverlapped. The following is the proper way to open a communications resource for overlapped operation. HANDLE hComm; hComm = CreateFile( gszPort, GENERICREAD GENERICWRITE, 0, 0, OPENEXISTING, FILEFLAGOVERLAPPED, 0); if (hComm INVALIDHANDLEVALUE) // error opening port; abort Removal of the FILEFLAGOVERLAPPED flag from the call to CreateFile specifies nonoverlapped operation. The next section discusses overlapped and nonoverlapped operations. The Platform SDK documentation states that when opening a communications port, the call to CreateFile has the following requirements:.

fdwShareMode must be zero. Communications ports cannot be shared in the same manner that files are shared. Applications using TAPI can use the TAPI functions to facilitate sharing resources between applications. For applications not using TAPI, handle inheritance or duplication is necessary to share the communications port.

Handle duplication is beyond the scope of this article; please refer to the Platform SDK documentation for more information. fdwCreate must specify the OPENEXISTING flag. hTemplateFile parameter must be NULL. One thing to note about port names is that traditionally they have been COM1, COM2, COM3, or COM4. The Windows API does not provide any mechanism for determining what ports exist on a system. Some systems even have more ports than the traditional maximum of four.

Hardware vendors and serial-device-driver writers are free to name the ports anything they like. For this reason, it is best that users have the ability to specify the port name they want to use. If a port does not exist, an error will occur (ERRORFILENOTFOUND) after attempting to open the port, and the user should be notified that the port isn't available. Reading and Writing Reading from and writing to communications ports in Windows is very similar to file input/output (I/O) in Windows. In fact, the functions that accomplish file I/O are the same functions used for serial I/O.

I/O can be done either of two ways: overlapped or nonoverlapped. The Platform SDK documentation uses the terms asynchronous and synchronous to connote these types of I/O operations. This article, however, uses the terms overlapped and nonoverlapped.

Nonoverlapped I/O is familiar to most developers because this is the traditional form of I/O, where an operation is requested and is assumed to be complete when the function returns. In the case of overlapped I/O, the system may return to the caller immediately even when an operation is not finished and will signal the caller when the operation completes.

The program may use the time between the I/O request and its completion to perform some 'background' work. Nonoverlapped I/O Nonoverlapped I/O is very straightforward, though it has limitations.

An operation takes place while the calling thread is blocked. Once the operation is complete, the function returns and the thread can continue its work. This type of I/O is useful for multithreaded applications because while one thread is blocked on an I/O operation, other threads can still perform work. It is the responsibility of the application to serialize access to the port correctly. If one thread is blocked waiting for its I/O operation to complete, all other threads that subsequently call a communications API will be blocked until the original operation completes. For instance, if one thread were waiting for a ReadFile function to return, any other thread that issued a WriteFile function would be blocked. One of the many factors to consider when choosing between nonoverlapped and overlapped operations is portability.

Overlapped operation is not a good choice because most operating systems do not support it. Most operating systems support some form of multithreading, however, so multithreaded nonoverlapped I/O may be the best choice for portability reasons. Overlapped I/O Overlapped I/O is not as straightforward as nonoverlapped I/O, but allows more flexibility and efficiency. A port open for overlapped operations allows multiple threads to do I/O operations at the same time and perform other work while the operations are pending. Furthermore, the behavior of overlapped operations allows a single thread to issue many different requests and do work in the background while the operations are pending. In both single-threaded and multithreaded applications, some synchronization must take place between issuing requests and processing the results.

One thread will have to be blocked until the result of an operation is available. The advantage is that overlapped I/O allows a thread to do some work between the time of the request and its completion. If no work can be done, then the only case for overlapped I/O is that it allows for better user responsiveness. Overlapped I/O is the type of operation that the MTTTY sample uses. It creates a thread that is responsible for reading the port's data and reading the port's status.

It also performs periodic background work. The program creates another thread exclusively for writing data out the port. Note Applications sometimes abuse multithreading systems by creating too many threads. Although using multiple threads can resolve many difficult problems, creating excessive threads is not the most efficient use of them in an application.

Threads are less a strain on the system than processes but still require system resources such as CPU time and memory. An application that creates excessive threads may adversely affect the performance of the entire system. A better use of threads is to create a different request queue for each type of job and to have a worker thread issue an I/O request for each entry in the request queue. This method is used by the MTTTY sample provided with this article. An overlapped I/O operation has two parts: the creation of the operation and the detection of its completion. Creating the operation entails setting up an OVERLAPPED structure, creating a manual-reset event for synchronization, and calling the appropriate function ( ReadFile or WriteFile). The I/O operation may or may not be completed immediately.

It is an error for an application to assume that a request for an overlapped operation always yields an overlapped operation. If an operation is completed immediately, an application needs to be ready to continue processing normally. The second part of an overlapped operation is to detect its completion. Detecting completion of the operation involves waiting for the event handle, checking the overlapped result, and then handling the data. The reason that there is more work involved with an overlapped operation is that there are more points of failure. If a nonoverlapped operation fails, the function just returns an error-return result. If an overlapped operation fails, it can fail in the creation of the operation or while the operation is pending.

You may also have a time-out of the operation or a time-out waiting for the signal that the operation is complete. Reading The ReadFile function issues a read operation. ReadFileEx also issues a read operation, but since it is not available on Windows 95, it is not discussed in this article. Here is a code snippet that details how to issue a read request. Notice that the function calls a function to process the data if the ReadFile returns TRUE. This is the same function called if the operation becomes overlapped. Note the fWaitingOnRead flag that is defined by the code; it indicates whether or not a read operation is overlapped.

It is used to prevent the creation of a new read operation if one is outstanding. Note GetOverlappedResult can detect completion of the operation, as well as return the operation's failure status. GetOverlappedResult returns FALSE and GetLastError returns ERRORIOINCOMPLETE when the operation is not completed. In addition, GetOverlappedResult can be made to block until the operation completes. This effectively turns the overlapped operation into a nonoverlapped operation and is accomplished by passing TRUE as the bWait parameter. Here is a code snippet that shows one way to detect the completion of an overlapped read operation.

Note that the code calls the same function to process the data that was called when the operation completed immediately. Also note the use of the fWaitingOnRead flag. Here it controls entry into the detection code, since it should be called only when an operation is outstanding. Event Flag Description EVBREAK A break was detected on input. EVCTS The CTS (clear-to-send) signal changed state.

To get the actual state of the CTS line, GetCommModemStatus should be called. EVDSR The DSR (data-set-ready) signal changed state. To get the actual state of the DSR line, GetCommModemStatus should be called. EVERR A line-status error occurred.

Line-status errors are CEFRAME, CEOVERRUN, and CERXPARITY. To find the cause of the error, ClearCommError should be called. EVRING A ring indicator was detected. EVRLSD The RLSD (receive-line-signal-detect) signal changed state. To get the actual state of the RLSD line, GetCommModemStatus should be called. Note that this is commonly referred to as the CD (carrier detect) line. EVRXCHAR A new character was received and placed in the input buffer.

Programming

See the 'Caveat' section below for a discussion of this flag. EVRXFLAG The event character was received and placed in the input buffer. The event character is specified in the EvtChar member of the DCB structure discussed later. The 'Caveat' section below also applies to this flag. EVTXEMPTY The last character in the output buffer was sent to the serial port device. If a hardware buffer is used, this flag only indicates that all data has been sent to the hardware. There is no way to detect when the hardware buffer is empty without talking directly to the hardware with a device driver.

After specifying the event mask, the WaitCommEvent function detects the occurrence of the events. If the port is open for nonoverlapped operation, then the WaitCommEvent function does not contain an OVERLAPPED structure. The function blocks the calling thread until the occurrence of one of the events.

If an event never occurs, the thread may block indefinitely. Here is a code snippet that shows how to wait for an EVRING event when the port is open for nonoverlapped operation. COMSTAT comStat; DWORD dwErrors; BOOL fOOP, fOVERRUN, fPTO, fRXOVER, fRXPARITY, fTXFULL; BOOL fBREAK, fDNS, fFRAME, fIOE, fMODE; // Get and clear current errors on the port.

If (!ClearCommError(hComm, &dwErrors, &comStat)) // Report error in ClearCommError. Return; // Get error flags. FDNS = dwErrors & CEDNS; fIOE = dwErrors & CEIOE; fOOP = dwErrors & CEOOP; fPTO = dwErrors & CEPTO; fMODE = dwErrors & CEMODE; fBREAK = dwErrors & CEBREAK; fFRAME = dwErrors & CEFRAME; fRXOVER = dwErrors & CERXOVER; fTXFULL = dwErrors & CETXFULL; fOVERRUN = dwErrors & CEOVERRUN; fRXPARITY = dwErrors & CERXPARITY; // COMSTAT structure contains information regarding // communications status. If (comStat.fCtsHold) // Tx waiting for CTS signal if (comStat.fDsrHold) // Tx waiting for DSR signal if (comStat.fRlsdHold) // Tx waiting for RLSD signal if (comStat.fXoffHold) // Tx waiting, XOFF char rec'd if (comStat.fXoffSent) // Tx waiting, XOFF char sent if (comStat.fEof) // EOF character received if (comStat.fTxim) // Character waiting for Tx; char queued with TransmitCommChar if (comStat.cbInQue) // comStat.cbInQue bytes have been received, but not read if (comStat.cbOutQue) // comStat.cbOutQue bytes are awaiting transfer Modem Status (a.k.a. Line Status) The call to SetCommMask may include the flags EVCTS, EVDSR, EVRING, and EVRLSD. These flags indicate changes in the voltage on the lines of the serial port.

There is no indication of the actual status of these lines, just that a change occurred. The GetCommModemStatus function retrieves the actual state of these status lines by returning a bit mask indicating a 0 for low or no voltage and 1 for high voltage for each of the lines. Please note that the term RLSD (Receive Line Signal Detect) is commonly referred to as the CD (Carrier Detect) line. Note The EVRING flag does not work in Windows 95 as mentioned earlier.

The GetCommModemStatus function, however, does detect the state of the RING line. Changes in these lines may also cause a flow-control event. The ClearCommError function reports whether transmission is suspended because of flow control.

If necessary, a thread may call ClearCommError to detect whether the event is the cause of a flow-control action. Flow control is covered in the 'Flow Control' section later in this article. Here is some code that demonstrates how to call GetCommModemStatus. DWORD dwModemStatus; BOOL fCTS, fDSR, fRING, fRLSD; if (!GetCommModemStatus(hComm, &dwModemStatus)) // Error in GetCommModemStatus; return; fCTS = MSCTSON & dwModemStatus; fDSR = MSDSRON & dwModemStatus; fRING = MSRINGON & dwModemStatus; fRLSD = MSRLSDON & dwModemStatus; // Do something with the flags.

Extended Functions The driver will automatically change the state of control lines as necessary. Generally speaking, changing status lines is under the control of a driver. If a device uses communications port control lines in a manner different from RS-232 standards, the standard serial communications driver will not work to control the device. If the standard serial communications driver will not control the device, a custom device driver is necessary.

There are occasions when standard control lines are under the control of the application instead of the serial communications driver. For instance, an application may wish to implement its own flow control.

The application would be responsible for changing the status of the RTS and DTR lines. EscapeCommFunction directs a communications driver to perform such extended operations.

EscapeCommFunction can make the driver perform some other function, such as setting or clearing a BREAK condition. Serial Settings DCB Settings The most crucial aspect of programming serial communications applications is the settings in the Device-Control Block (DCB) structure. The most common errors in serial communications programming occur in initializing the DCB structure improperly. When the serial communications functions do not behave as expected, a close examination of the DCB structure usually reveals the problem. There are three ways to initialize a DCB structure. The first method is to use the function GetCommState.

This function returns the current DCB in use for the communications port. The following code shows how to use the GetCommState function. Member Description DCBlength Size, in bytes, of the structure. Should be set before calling SetCommState to update the settings.

BaudRate Specifies the baud at which the communications device operates. This member can be an actual baud value, or a baud index. FBinary Specifies whether binary mode is enabled. The Windows API does not support nonbinary mode transfers, so this member should be TRUE. Trying to use FALSE will not work. FParity Specifies whether parity checking is enabled.

If this member is TRUE, parity checking is performed and parity errors are reported. This should not be confused with the Parity member, which controls the type of parity used in communications. FOutxCtsFlow Specifies whether the CTS (clear-to-send) signal is monitored for output flow control.

If this member is TRUE and CTS is low, output is suspended until CTS is high again. The CTS signal is under control of the DCE (usually a modem), the DTE (usually the PC) simply monitors the status of this signal, the DTE does not change it. FOutxDsrFlow Specifies whether the DSR (data-set-ready) signal is monitored for output flow control. If this member is TRUE and DSR is low, output is suspended until DSR is high again.

Once again, this signal is under the control of the DCE; the DTE only monitors this signal. FDtrControl Specifies the DTR (data-terminal-ready) input flow control. This member can be one of the following values: Value Meaning DTRCONTROLDISABLE Lowers the DTR line when the device is opened. The application can adjust the state of the line with EscapeCommFunction. DTRCONTROLENABLE Raises the DTR line when the device is opened.

The application can adjust the state of the line with EscapeCommFunction. DTRCONTROLHANDSHAKE Enables DTR flow-control handshaking.

If this value is used, it is an error for the application to adjust the line with EscapeCommFunction. FDsrSensitivity Specifies whether the communications driver is sensitive to the state of the DSR signal. If this member is TRUE, the driver ignores any bytes received, unless the DSR modem input line is high. FTXContinueOnXoff Specifies whether transmission stops when the input buffer is full and the driver has transmitted the XOFF character. If this member is TRUE, transmission continues after the XOFF character has been sent. If this member is FALSE, transmission does not continue until the input buffer is within XonLim bytes of being empty and the driver has transmitted the XON character. FOutX Specifies whether XON/XOFF flow control is used during transmission.

If this member is TRUE, transmission stops when the XOFF character is received and starts again when the XON character is received. FInX Specifies whether XON/XOFF flow control is used during reception. If this member is TRUE, the XOFF character is sent when the input buffer comes within XoffLim bytes of being full, and the XON character is sent when the input buffer comes within XonLim bytes of being empty. FErrorChar Specifies whether bytes received with parity errors are replaced with the character specified by the ErrorChar member. If this member is TRUE and the fParity member is TRUE, replacement occurs. FNull Specifies whether null bytes are discarded.

If this member is TRUE, null bytes are discarded when received. FRtsControl Specifies the RTS (request-to-send) input flow control. If this value is zero, the default is RTSCONTROLHANDSHAKE. This member can be one of the following values: Value Meaning RTSCONTROLDISABLE Lowers the RTS line when the device is opened.

The application can use EscapeCommFunction to change the state of the line. RTSCONTROLENABLE Raises the RTS line when the device is opened. The application can use EscapeCommFunction to change the state of the line. RTSCONTROLHANDSHAKE Enables RTS flow-control handshaking. The driver raises the RTS line, enabling the DCE to send, when the input buffer has enough room to receive data. The driver lowers the RTS line, preventing the DCE to send, when the input buffer does not have enough room to receive data.

If this value is used, it is an error for the application to adjust the line with EscapeCommFunction. RTSCONTROLTOGGLE Specifies that the RTS line will be high if bytes are available for transmission. After all buffered bytes have been sent, the RTS line will be low. If this value is set, it would be an error for an application to adjust the line with EscapeCommFunction.

This value is ignored in Windows 95; it causes the driver to act as if RTSCONTROLENABLE were specified. FAbortOnError Specifies whether read and write operations are terminated if an error occurs. If this member is TRUE, the driver terminates all read and write operations with an error status (ERRORIOABORTED) if an error occurs. The driver will not accept any further communications operations until the application has acknowledged the error by calling the ClearCommError function.

FDummy2 Reserved; do not use. WReserved Not used; must be set to zero. XonLim Specifies the minimum number of bytes allowed in the input buffer before the XON character is sent. XoffLim Specifies the maximum number of bytes allowed in the input buffer before the XOFF character is sent. The maximum number of bytes allowed is calculated by subtracting this value from the size, in bytes, of the input buffer.

Parity Specifies the parity scheme to be used. This member can be one of the following values: Value Meaning EVENPARITY Even MARKPARITY Mark NOPARITY No parity ODDPARITY Odd StopBits Specifies the number of stop bits to be used. This member can be one of the following values: Value Meaning ONESTOPBIT 1 stop bit ONE5STOPBITS 1.5 stop bits TWOSTOPBITS 2 stop bits XonChar Specifies the value of the XON character for both transmission and reception. XoffChar Specifies the value of the XOFF character for both transmission and reception. ErrorChar Specifies the value of the character used to replace bytes received with a parity error. EofChar Specifies the value of the character used to signal the end of data. EvtChar Specifies the value of the character used to cause the EVRXFLAG event.

This setting does not actually cause anything to happen without the use of EVRXFLAG in the SetCommMask function and the use of WaitCommEvent. WReserved1 Reserved; do not use.

Flow Control Flow control in serial communications provides a mechanism for suspending communications while one of the devices is busy or for some reason cannot do any communication. There are traditionally two types of flow control: hardware and software. A common problem with serial communications is write operations that actually do not write the data to the device.

Often, the problem lies in flow control being used when the program did not specify it. A close examination of the DCB structure reveals that one or more of the following members may be TRUE: fOutxCtsFlow, fOutxDsrFlow, or fOutX. Another mechanism to reveal that flow control is enabled is to call ClearCommError and examine the COMSTAT structure. It will reveal when transmission is suspended because of flow control. Before discussing the types of flow control, a good understanding of some terms is in order. Serial communications takes place between two devices. Traditionally, there is a PC and a modem or printer.

The PC is labeled the Data Terminal Equipment (DTE). The DTE is sometimes called the host. The modem, printer, or other peripheral equipment is identified as the Data Communications Equipment (DCE).

The DCE is sometimes referred to as the device. Hardware flow control Hardware flow control uses voltage signals on control lines of the serial cable to control whether sending or receiving is enabled.

The DTE and the DCE must agree on the types of flow control used for a communications session. Setting the DCB structure to enable flow control just configures the DTE. The DCE also needs configuration to make certain the DTE and DCE use the same type of flow control. There is no mechanism provided by Windows to set the flow control of the DCE.

DIP switches on the device, or commands sent to it typically establish its configuration. The following table describes the control lines, the direction of the flow control, and the line's effect on the DTE and DCE. Hardware Flow-control Lines. Line and Direction Effect on DTE/DCE CTS (Clear To Send) Output flow control DCE sets the line high to indicate that it can receive data. DCE sets the line low to indicate that it cannot receive data. If the fOutxCtsFlow member of the DCB is TRUE, then the DTE will not send data if this line is low. It will resume sending if the line is high.

Os 2 Serial Port Programming

If the fOutxCtsFlow member of the DCB is FALSE, then the state of the line does not affect transmission. DSR (Data Set Ready) Output flow control DCE sets the line high to indicate that it can receive data. DCE sets the line low to indicate that it cannot receive data. If the fOutxDsrFlow member of the DCB is TRUE, then the DTE will not send data if this line is low.

It will resume sending if the line is high. If the fOutxDsrFlow member of the DCB is FALSE, then the state of the line does not affect transmission. DSR (Data Set Ready) Input flow control If the DSR line is low, then data that arrives at the port is ignored. If the DSR line is high, data that arrives at the port is received. This behavior occurs if the fDsrSensitivity member of the DCB is set to TRUE. If it is FALSE, then the state of the line does not affect reception.

RTS (Ready To Send) Input flow control The RTS line is controlled by the DTE. If the fRtsControl member of the DCB is set to RTSCONTROLHANDSHAKE, the following flow control is used: If the input buffer has enough room to receive data (at least half the buffer is empty), the driver sets the RTS line high. If the input buffer has little room for incoming data (less than a quarter of the buffer is empty), the driver sets the RTS line low.

If the fRtsControl member of the DCB is set to RTSCONTROLTOGGLE, the driver sets the RTS line high when data is available for sending. The driver sets the line low when no data is available for sending. Windows 95 ignores this value and treats it the same as RTSCONTROLENABLE. If the fRtsControl member of the DCB is set to RTSCONTROLENABLE or RTSCONTROLDISABLE, the application is free to change the state of the line as it needs. Note that in this case, the state of the line does not affect reception.

The DCE will suspend transmission when the line goes low. The DCE will resume transmission when the line goes high. DTR (Data Terminal Ready) Input flow control The DTR line is controlled by the DTE. If the fDtrControl member of the DCB is set to DTRCONTROLHANDSHAKE, the following flow control is used: If the input buffer has enough room to receive data (at least half the buffer is empty), the driver sets the DTR line high. If the input buffer has little room for incoming data (less than a quarter of the buffer is empty), the driver sets the DTR line low. If the fDtrControl member of the DCB is set to DTRCONTROLENABLE or DTRCONTROLDISABLE, the application is free to change the state of the line as it needs. In this case, the state of the line does not affect reception.

The DCE will suspend transmission when the line goes low. The DCE will resume transmission when the line goes high. The need for flow control is easy to recognize when the CERXOVER error occurs. This error indicates an overflow of the receive buffer and data loss. If data arrives at the port faster than it is read, CERXOVER can occur. Increasing the input buffer size may cause the error to occur less frequently, but it does not completely solve the problem. Input flow control is necessary to completely alleviate this problem.

When the driver detects that the input buffer is nearly full, it will lower the input flow-control lines. This should cause the DCE to stop transmitting, which gives the DTE enough time to read the data from the input buffer. When the input buffer has more room available, the voltage on flow-control lines is set high, and the DCE resumes sending data. A similar error is CEOVERRUN. This error occurs when new data arrives before the communications hardware and serial communications driver completely receives old data. This can occur when the transmission speed is too high for the type of communications hardware or CPU. This can also occur when the operating system is not free to service the communications hardware.

The only way to alleviate this problem is to apply some combination of decreasing the transmission speed, replacing the communications hardware, and increasing the CPU speed. Sometimes third-party hardware drivers that are not very efficient with CPU resources cause this error. Flow control cannot completely solve the problems that cause the CEOVERRUN error, although it may help to reduce the frequency of the error. Software flow control Software flow control uses data in the communications stream to control the transmission and reception of data.

Because software flow control uses two special characters, XOFF and XON, binary transfers cannot use software flow control; the XON or XOFF character may appear in the binary data and would interfere with data transfer. Software flow control befits text-based communications or data being transferred that does not contain the XON and XOFF characters.

In order to enable software flow control, the fOutX and fInX members of the DCB must be set to TRUE. The fOutX member controls output flow control. The fInX member controls input flow control. One thing to note is that the DCB allows the program to dynamically assign the values the system recognizes as flow-control characters. The XoffChar member of the DCB dictates the XOFF character for both input and output flow control. The XonChar member of the DCB similarly dictates the XON character. For input flow control, the XoffLim member of the DCB specifies the minimum amount of free space allowed in the input buffer before the XOFF character is sent.

If the amount of free space in the input buffer drops below this amount, then the XOFF character is sent. For input flow control, the XonLim member of the DCB specifies the minimum number of bytes allowed in the input buffer before the XON character is sent. If the amount of data in the input buffer drops below this value, then the XON character is sent. Table 4 lists the behavior of the DTE when using XOFF/XON flow control. Software flow-control behavior. Flow-control character Behavior XOFF received by DTE DTE transmission is suspended until XON is received. DTE reception continues.

The fOutX member of the DCB controls this behavior. XON received by DTE If DTE transmission is suspended because of a previous XOFF character being received, DTE transmission is resumed.

The fOutX member of the DCB controls this behavior. XOFF sent from DTE XOFF is automatically sent by the DTE when the receive buffer approaches full.

The actual limit is dictated by the XoffLim member of the DCB. The fInX member of the DCB controls this behavior. DTE transmission is controlled by the fTXContinueOnXoff member of the DCB as described below.

XON sent from the DTE XON is automatically sent by the DTE when the receive buffer approaches empty. The actual limit is dictated by the XonLim member of the DCB. The fInX member of the DCB controls this behavior. If software flow control is enabled for input control, then the fTXContinueOnXoff member of the DCB takes effect. The fTXContinueOnXoff member controls whether transmission is suspended after the XOFF character is automatically sent by the system. If fTXContinueOnXoff is TRUE, then transmission continues after the XOFF is sent when the receive buffer is full. If fTXContinueOnXoff is FALSE, then transmission is suspended until the system automatically sends the XON character.

DCE devices using software flow control will suspend their sending after the XOFF character is received. Some equipment will resume sending when the XON character is sent by the DTE. On the other hand, some DCE devices will resume sending after any character arrives.

The fTXContinueOnXoff member should be set to FALSE when communicating with a DCE device that resumes sending after any character arrives. If the DTE continued transmission after it automatically sent the XOFF, the resumption of transmission would cause the DCE to continue sending, defeating the XOFF. There is no mechanism available in the Windows API to cause the DTE to behave the same way as these devices. The DCB structure contains no members for specifying suspended transmission to resume when any character is received.

Mac Os Serial Number

The XON character is the only character that causes transmission to resume. One other interesting note about software flow control is that reception of XON and XOFF characters causes pending read operations to complete with zero bytes read. The XON and XOFF characters cannot be read by the application, since they are not placed in the input buffer. A lot of programs on the market, including the Terminal program that comes with Windows, give the user three choices for flow control: Hardware, Software, or None.

The Windows operating system itself does not limit an application in this way. The settings of the DCB allow for Software and Hardware flow control simultaneously. In fact, it is possible to separately configure each member of the DCB that affects flow control, which allows for several different flow-control configurations. The limits placed on flow-control choices are there for ease-of-use reasons to reduce confusion for end users. The limits placed on flow-control choices may also be because devices used for communications may not support all types of flow control. Communications Time-outs Another major topic affecting the behavior of read and write operations is time-outs.

Time-outs affect read and write operations in the following way. If an operation takes longer than the computed time-out period, the operation is completed. There is no error code that is returned by ReadFile, WriteFile, GetOverlappedResult, or WaitForSingleObject. All indicators used to monitor the operation indicate that it completed successfully. The only way to tell that the operation timed out is that the number of bytes actually transferred are fewer than the number of bytes requested. So, if ReadFile returns TRUE, but fewer bytes were read than were requested, the operation timed out.

If an overlapped write operation times out, the overlapped event handle is signaled and WaitForSingleObject returns WAITOBJECTO. GetOverlappedResult returns TRUE, but dwBytesTransferred contains the number of bytes that were transferred before the time-out. The following code demonstrates how to handle this in an overlapped write operation. Note Once again, communications time-outs are not the same as time-out values supplied in synchronization functions. WaitForSingleObject, for instance, uses a time-out value to wait for an object to become signaled; this is not the same as a communications time-out. Setting the members of the COMMTIMEOUTS structure to all zeros causes no time-outs to occur.

Nonoverlapped operations will block until all the requested bytes are transferred. The ReadFile function is blocked until all the requested characters arrive at the port.

The WriteFile function is blocked until all requested characters are sent out. On the other hand, an overlapped operation will not finish until all the characters are transferred or the operation is aborted. The following conditions occur until the operation is completed:.

WaitForSingleObject always returns WAITTIMEOUT if a synchronization time-out is supplied. WaitForSingleObject will block forever if an INFINITE synchronization time-out is used. GetOverlappedResult always returns FALSE and GetLastError returns ERRORIOINCOMPLETE if called directly after the call to GetOverlappedResult. Setting the members of the COMMTIMEOUTS structure in the following manner causes read operations to complete immediately without waiting for any new data to arrive. COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 0; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts(hComm, &timeouts)) // Error setting time-outs.

These settings are necessary when used with an event-based read described in the 'Caveat' section earlier. In order for ReadFile to return 0 bytes read, the ReadIntervalTimeout member of the COMMTIMEOUTS structure is set to MAXDWORD, and the ReadTimeoutMultiplier and ReadTimeoutConstant are both set to zero. An application must always specifically set communications time-outs when it uses a communications port. The behavior of read and write operations is affected by communications time-outs. When a port is initially open, it uses default time-outs supplied by the driver or time-outs left over from a previous communications application. If an application assumes that time-outs are set a certain way, while the time-outs are actually different, then read and write operations may never complete or may complete too often.

Conclusion This article serves as a discussion of some of the common pitfalls and questions that arise when developing a serial communications application. The Multithreaded TTY sample that comes with this article is designed using many of the techniques discussed here. Download it and try it out. Learning how it works will provide a thorough understanding of the serial communications functions. Bibliography Brain, Marshall.

Win32 System Services: The Heart of Windows NT. Englewood Cliffs, NJ: Prentice Hall, 1994. Campbell, Joe. C Programmer's Guide to Serial Communications. Indianapolis, IN: Howard W. Sams & Company, 1994. Mirho, Charles, and Andy Terrice.

'Create Communications Programs for Windows 95 with the Win32 Comm API.' Microsoft Systems Journal 12 (December 1994). (MSDN Library, Books and Periodicals).

Serial ports are a legacy communications port which has pretty much been succeeded by and other modern communications technology. However, it is much easier to program than USB, and it is still found in a lot of computers (especially older ones such as the ones the financially limited amateur OS writer might use for ). Also, a lot of phone modems connect via the serial interface. Furthermore, it is possible to use the serial ports for debugging, since a lot of emulators allow the redirection of their output into a file.

Contents. Wires, Pins, Connectors and the like The Wikipedia page on has a lot of information, and it is summarised here.

The serial interface is very simple. There are actually two kinds of serial port: 25-pin and 9-pin.

25-pin ports are not any better, they just have more pins and are bigger. 9-pin is smaller and is used more often though in the past the 25-pin ones were used more often. The 9-pin ones are called DE-9 (or more commonly, DB-9 even though DE-9 is its technical name) and the 25-pin ones are called DB-25. They plug in to your computer using a female plug (unless your computer is odd and has a female port, in which case your cable will need a male plug). Has more information on the plug used. Both have the same basic types of pins.

A DB-25 has most of the pins as ground pins, whereas a DE-9 has only a few ground pins. There is a transmitting pin (for sending information away) and a receiving pin (for getting information). Some serial ports can have a duplex mode-that is, they can send and receive simultaneously. There are a few other pins, used for hardware handshaking. In the past, there was no duplex mode, so if a computer wanted to send something it had to tell the other device or computer that it was about to transmit, using one of the hardware handshaking pins. The other thing would then use another handshaking pin to tell it to send whatever it wanted to send. Today there is duplex mode, but the handshaking pins are still used.

If you want to connect two computers, you need two things in your cable:. The cable needs to have two female plugs so it can plug into both computers. The cable needs to have it's transmit-receive wires and it's handshaking wires switched. This can be done in the cable itself, or as an extension called a For serial devices, you don't need to setup the cable this way. The receiving end of the device has the wires switched and it has a female port, which means you can plug a male plug into it. Why Use a Serial Port? During the early stages of kernel development, you might wonder why you would bother writing a serial driver.

There are several reasons why you might: debugging You can use the serial port to connect to a host computer, and use the GDB debugger to debug your operating system. This involves writing a stub for GDB within your OS. Helpful information might be found. Headless console You can operate the computer without a monitor, keyboard or mouse and instead use the serial port as a console using a protocol such as TTY or VT100. External logging When the system itself is in danger of potentially crashing at times, it's nice to get debugging outputs safe to another computer before the test system triple-faults. Networking and File transfers Serial ports are useful for transferring information between systems when other more traditional methods are unavailable. Programming the Serial Communications Port If you want to use the serial port for communications, you first have to initialize it.

You tell it how fast your connection speed between the other computer or device will be (this is called the baud rate)-you must have the same speed as the other device or computer is setup to use, or you will have problems. It is probably safer to use the slower speeds unless you need the faster speeds for some reason, for example if you are playing a multi-player game over a serial connection. Chess engine rating list.

You also need to setup the parity type and the number of bits in a character. Once again, your computer must be setup with the same values for these things as the other computer or device has, or communication will not work. Once you have setup these things, you still need to setup the interrupt handlers. You can poll the port to see if any new things have arrived, or if it's time to send another character, but this slows things down and will not work very well in most real-time applications or multi-threaded environments. In the case of a game, this is not a good idea at all. You use IRQ #4 for COM ports 1 or 3, and IRQ #3 for COM ports 2 or 4 (you can tell which port sent the interrupt when you receive the interrupt).

The IRQ handlers check if you are receiving something, and if so they receive the character and handle it somehow, such as placing it into a buffer. They also check if the other side is ready to receive something from you, and if you have something to send, it is sent. Port Addresses The addresses for COM ports can vary depending on how they are connected to the machine and how the BIOS is configured. Some BIOS configuration utilities allow you to see and set what these are, so if you in doubt for a test machine, this might be a good place to look to get you started. For the most part, the first two COM ports will be at the addresses specified, the addresses for further COM ports is less reliable.

COM Port IO Port COM1 0x3F8 COM2 0x2F8 COM3 0x3E8 COM4 0x2E8 You might be able to find the IO port addresses of the COM ports in the; however be warned that this won't work on modern/UEFI systems, can tell you about serial ports that only exist in the chipset (and lack any kind of connector that anything can be plugged into), won't tell you about any additional serial ports (e.g. On expansion cards, etc) that firmware doesn't/can't know about, and will make your OS susceptible to 'BIOS quirks/bugs'. Because the serial ports have relatively standard IO ports it's far more effective to use manual probing techniques instead; specifically, see if the scratch pad register can store a value, then try the loopback test (that you should use to determine if the serial port is faulty anyway).

Once you have the base address of your COM port, you add an offset value to get to one of the data registers. One of the registers hold what is termed the DLAB or Divisor Latch Access Bit.

When this bit is set, offsets 0 and 1 are mapped to the low and high bytes of the Divisor register for setting the baud rate of the port. When this bit is clear, offsets 0 and 1 are mapped to their normal registers. The DLAB bit only affects port offsets 0 and 1, the other offsets ignore this setting. IO Port Offset Setting of DLAB Register mapped to this port +0 0 Data register.

Reading this registers read from the Receive buffer. Writing to this register writes to the Transmit buffer. +1 0 Interrupt Enable Register.

Port

+0 1 With DLAB set to 1, this is the least significant byte of the divisor value for setting the baud rate. +1 1 With DLAB set to 1, this is the most significant byte of the divisor value. +2 - Interrupt Identification and FIFO control registers +3 - Line Control Register. The most significant bit of this register is the DLAB. +4 - Modem Control Register. +5 - Line Status Register.

+6 - Modem Status Register. +7 - Scratch Register. Line Protocol The serial data transmitted across the wire can have a number of different parameters set. As a rule, the sending device and the receiving device require the same protocol parameter values written to each serial controller in order for communication to be successful.

These days you could consider 8N1 (8 bits, no parity, one stop bit) pretty much the default. Baud Rate The serial controller (UART) has an internal clock which runs at 115200 ticks per second and a clock divisor which is used to control the baud rate. This is exactly the same type of system used by the Programmable Interrupt Timer (PIT). In order to set the speed of the port, calculate the divisor required for the given baud rate and program that in to the divisor register.

Raspberry Pi 2 Serial Port Pins

For example, a divisor of 1 will give 115200 baud, a divisor of 2 will give 57600 baud, 3 will give 38400 baud, etc. Do not be tempted to use a divisor of 0 to try to get an infinite baud rate, it won't work. Most serial controllers will generate a unspecified and unpredictable baud rate (and anyway infinite baud would mean infinite transmission errors as they are proportional.) To set the divisor to the controller:. Set the most significant bit of the Line Control Register.

This is the DLAB bit, and allows access to the divisor registers. Send the least significant byte of the divisor value to PORT + 0. Send the most significant byte of the divisor value to PORT + 1. Clear the most significant bit of the Line Control Register. Data Bits The number of bits in a character is variable.

Having fewer bits is, of course, faster, but they store less information. If you are only sending ASCII text, you probably only need 7 bits. Set this value by writing to the two least significant bits of the Line Control Register PORT + 3.

Bit 1 Bit 0 Character Length (bits) 0 0 5 0 1 6 1 0 7 1 1 8 Stop bits The serial controller can be configured to send a number of bits after each character of data. These reliable bits can be used to by the controller to verify that the sending and receiving devices are in phase.

Serial Port Communication

If the character length is specifically 5 bits, the stop bits can only be set to 1 or 1.5. For other character lengths, the stop bits can only be set to 1 or 2. To set the number of stop bits, set bit 2 of the Line Control Register PORT + 3. Bit 2 Stop bits 0 1 1 1.5 / 2 (depending on character length) Parity The controller can be made to add or expect a parity bit at the end of each character of data transmitted.

With this parity bit, if a single bit of data is inverted by interference, a parity error can be raised. The parity type can be NONE, EVEN, ODD, MARK or SPACE. If parity is set to NONE, no parity bit will be added and none will be expected. If one is sent by the transmitter and not expected by the receiver, it will likely cause an error. If the parity is MARK or SPACE, the parity bit will be expected to be always set to 1 or 0 respectively. If the parity is set to EVEN or ODD, the controller calculates the accuracy of the parity by adding together the values of all the data bits and the parity bit. If the port is set to have EVEN parity, the result must be even.

If it is set to have ODD parity, the result must be odd. To set the port parity, set bits 3, 4 and 5 of the Line Control Register PORT + 3. Bit 5 Bit 4 Bit 3 Parity -0 NONE 0 0 1 ODD 0 1 1 EVEN 1 0 1 MARK 1 1 1 SPACE Interrupt enable register To communicate with a serial port in interrupt mode, the interrupt-enable-register (see table above) must be set correctly. To determine which interrupts should be enabled, a value with the following bits (0 = disabled, 1 = enabled) must be written to the interrupt-enable-register: Bit Interrupt 0 Data available 1 Transmitter empty 2 Break/error 3 Status change 4-7 Unused Example Code Initialization.

Comments are closed.