📄 async.doc
字号:
ASYNCHRONOUS FUNCTIONS FOR MICROSOFT, TURBO, OR ZORTECH C
The LIB(s) on the included disk are libraries of serial
communications functions designed specifically for use with
Microsoft C, Turbo C / C++, and Zortech C / C++. The regis-
tered version has LIBs for all memory models. The shareware
version is small model only.
--- Features of the library functions ---
o Support for 16550 UART's FIFO mode of operation
o Fully interrupt driven
o Baud rates up to 115,200 baud
o User defined transmit and receive ring buffer sizes.
o Ring buffers may be in placed in FAR memory even in small
and medium model programs.
o User defined port addresses, IRQ use, and interrupt vector
numbers.
o Support for simultaneous operation of 2 ports.
o Built in support for XON/XOFF and hardware flow control
o Block transmit and receive functions
o Receive buffer look ahead function
o 100% assembler code for maximum speed
o Totally compatible with Microsoft C, Turbo C, Zortech C,
and other C compilers that use standard Microsoft high
level language calling conventions.
---------------------------------------------------------------
Mike Dumdei, 6 Holly Lane, Texarkana TX 75503
MCOMM5 (c) 1989, 1990, 1991 All Rights Reserved
---------------------------------------------------------------
REGISTRATION AND DISTRIBUTION POLICY
MCOMM5, the various versions of Smalterm, the ANSI video
routines, and other miscellaneous functions contained in the
COMM_x libraries are distributed as shareware. If you use
these functions regularly please register them.
Two types of registration are available for MCOMM5. The
first is $25 and includes assembled libraries for all memory
models. The $25 registration does not include source code.
The second type of registration is $45 and includes libraries
and source code. Previous versions were $25 for source code
and libraries. If you send $25 and want source code based on
previous offers, you will receive a previous version of the
source. Registered users of versions prior to version 5 may
upgrade their libraries for $3 or upgrade source code version
for $10.
I also have developed a version of these routines for use
with the DigiBoard(r) COM4 and COM8 boards that support up to
32 DigiBoard ports and 1 standard port simultaneously. Please
contact me if you are interested in this product. It is $35
for libraries only. No source is available for the DigiBoard
version.
Considerable time and effort has gone into developing and
debugging these routines. If you are not a registered user and
have obtained a copy of the registered version, please take
time now to register the software or delete it. The copy you
have is a registered version if it contains libraries for any
memory model other than small model or if any of the ASM source
code is included.
This software is provided as is without warranty as to its
fitness for a particular use or being free of errors. I assume
no liability for any loss or damages you may incur through its
use. I will, however, make every effort to correct any
software errors that may exist, and provide you with a working
version.
I will continue to assist registered and non-registered
users whenever possible. If you have any problems using these
routines or questions, I may be contacted at:
Split Up the Middle BBS -- 903 838-6713 (modem)
Mike Dumdei -- 903 838-8307 (voice)
GETTING STARTED
All functions included in this library are listed on the fol-
lowing pages in alphabetical order. The basic functions needed
to begin are: async_open, async_tx, async_rx, and async_close.
Functions are also available to support XON/XOFF and hardware
flow control, the 16550 UART, block transmit and receive,
receive buffer look ahead, and several other features.
All functions take a pointer to an ASYNC structure for one of
its arguments. This structure is defined in COMM.H. It
may be helpful to think of this structure as being similar to
the standard C library 'FILE *'.
If you have been using versions of these routines prior to
version 5.00, there have been some changes made that will
require you to make some modifications to any existing code
before it can be used with the new libraries. The main
differences are:
> Async_open takes different parameters. Also, instead
of the open function automatically allocating the ring
buffers for you, you provide the ring buffers.
> All functions now take a pointer to an ASYNC structure
as the first argument rather than 0 (COM1) or 1 (COM2).
> LITES is no longer supported.
NOTES ON 16550 FIFO MODE
The 16550 UART is automatically detected and enabled when
async_open is called. If, for some reason, you want to operate
a 16550 UART in non-FIFO mode, automatic detection and use can
be disabled. See async_open for more information.
--- Use of receiver FIFOs ---
The receiver trigger level may be programmed for 1, 4, 8, or
14 bytes by the async_FIFOrxlvl function. When a port is first
opened the trigger is set to 1 byte. There are 3 reasons why I
chose to default to a 1 byte receive trigger level.
1) While a higher trigger level results in less CPU
overhead, it also provides less overrun protection if the
CPU is slow to respond. For example, with a 1 byte
trigger level the 16550 -- when it generates an interrupt
-- can hold 15 more characters in its FIFOs before the
CPU responds. With a 14 byte trigger level it will only
have room for 2 more characters.
2) The MCOMM interrupt functions completely empty the
receiver FIFOs every time an interrupt occurs. If the
CPU is slow to respond, the interrupt handler will
process 2,3,4.. characters (whatever is in the FIFOs)
whenever it does get control so the data still gets
buffered if the CPU isn't able to keep up.
3) Setting the trigger level at higher trigger levels when
displaying incoming data to the screen will result in a
jerky looking display, especially at low baud rates.
Again, this is because MCOMM empties the buffer
completely when it processes the interrupt. With a
trigger level other than 1, data stacks up in the FIFOs
until the trigger level is reached. When the interrupt
finally occurs, all the data in the FIFOs is pulled out
and made available to the higher level functions at
one time. The result is your code sits for 4, 8, or 14
bytes (whatever the trigger is) and then puts those bytes
on the screen in a burst. It looks rough at low baud
rates. At 9600 baud and above you could probably get by
with a slightly higher trigger level.
For best use of the receive FIFOs, stick with 1 byte trigger
level when displaying data to the screen. If your application
does not display the data or uses a high baud rate, you may
want to experiment with setting it to either 4 or 8 bytes.
--- Use of transmit FIFOs ---
The MCOMM transmit interrupt handler takes a parameter (set
by async_FIFOtxlvl) that is the maximum number of bytes to load
into the transmit FIFOs at one time. The default value for
NOTES ON 16550 FIFO MODE
this parameter is 3 bytes. The reason for not loading up the
FIFOs to maximum capacity (16 bytes) is flow control. The
16550 UART will continue to transmit characters in its FIFOs
regardless of the state of CTS, DSR, or CD, or if an XOFF is
received. It is totally up to the software to respond to
requests for flow control. If the FIFOs are loaded with more
bytes than the receiver can handle when it invokes flow
control, the receiver gets overwritten. There is a bit that
can be sent to the UART to flush the transmit FIFOs but then it
is impossible to tell what was flushed and what was sent. The
solution is to not the load the FIFOs up so full. If the
receiving device can handle more than 3 characters of overrun,
use a larger value. If the application does not require flow
control, you can use a 16 byte level with no problems.
Another factor to consider concerning the transmit FIFO byte
level is that (from the NS Data Communications/LAN/UART
Handbook) the transmit FIFO empty indication will be delayed by
1 character time minus the last stop bit until there are at
least 2 bytes in the transmit FIFOs simultaneously for the
current transmit operation. After the 2 byte requirement is
met the transmit interrupt occurs immediately when the transmit
FIFOs empty. Using a value of 3 or above (1 byte for the
transmit shift register and 2 for the FIFO registers)
guarantees the interrupt delay is deactivated. Once the '2
bytes in the FIFOs' requirement is met, the transmit byte level
can be reduced if necessary.
--- Problems with Western Digital 16550s ---
The following problems DO NOT apply to the National Semicon-
ductor version of the 16550. Neither are they unique to MCOMM.
Western Digital 16550 UARTs have two problems you should be
aware of if your application will be ran on system that uses
this chip.
The first of these only shows up under the following
conditions:
1) The UART is in FIFO mode.
2) A low baud rate is being used.
3) The transmitter is initially empty.
4) A block of data longer than 16 to 18 bytes (depth of the
FIFOs plus 1 or 2 for what gets out while the FIFOs are
being filled up) is sent to the chip.
Under these conditions the WD16550 UART will momentarily fail
to recognize the FIFOs are full and continue to generate
transmit interrupts. It also fails to reset the 'Transmit Hold
Register Empty' bit making it impossible for the software to
detect a full FIFO condition. The result is the software keeps
sending data to the chip, overrunning the FIFOs. What you will
NOTES ON 16550 FIFO MODE
see is, the first 16 to 18 bytes transmitted correctly, a
missing block of data, and then the remainder of the block also
correct. This can be verified by trying to send blocks of data
through this chip (WD16550) at a low baud rate with any
software that enables the FIFOs. How low of a baud rate is low
enough to cause the problem depends on the particular chip and
how fast the CPU and software can supply data to the chip.
With MCOMM, a 20 MHZ 386, and the TxByteCnt at the default
level of 3, the chip I was testing would not work in FIFO mode
below 9600 baud. On the same system using different software,
it worked as low as 4800 baud. On a 12 MHZ 286, MCOMM would
work at 4800 and above while the other software worked at 2400
and above.
For publicly distributed applications, I recommend you do one
or more of the following:
1) Provide an option in your program to allow the end user
to operate a 16550 with the FIFOs disabled. When the
FIFOs are disabled, all baud rates work. ORing the
ComBase parameter of async_open with 0x4000 will force
FIFO mode off.
2) Provide an option in your program to allow setting the
TxByteCnt level (async_FIFOtxlvl) to a lower value. This
will help slightly.
3) Put a flag in your program the end user can set to let
you know you are dealing with a WD16550.
4) State your application does not support the Western
Digital version of the 16550 at low baud rates.
The second problem with the WD16550 is that if the 'Clear to
Send' signal is not connected it can, under some conditions,
cause the 'Delta Clear to Send' bit in the Modem Status
Register to become set and it will not reset. I did not
research the problem enough to know if the 'locked bit' only
occurs when MSR interrupts are enabled, whether other floating
MSR input signals can cause the same problem, if all WD16550's
have the problem, or that is unique to the Western Digital chip
(considering the FIFO overrun problem, I assume it is unique).
With a properly functioning UART, reading the MSR register will
reset all the 'delta bits' and clear any interrupts. With the
chip I had, I tried everything I could think of to clear the
interrupt and nothing worked except the ON/OFF switch. I tried
clearing interrupts and reading the MSR multiple times checking
to see if the bit reset with interrupts off (it didn't),
disabling Modem Status interrupts via the Interrupt Enable
Register and then reading the MSR register (didn't work), FIFO
mode on / FIFO mode off (no difference), keyboard reboot of the
computer (didn't fix it), shut the computer off and turn it
back on (that fixed it).
NOTES ON 16550 FIFO MODE
After encountering this problem and having the system lock up,
I added code to MCOMM's interrupt driver so that it would quit
trying to clear an interrupt after 1000 attempts. It then sets
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -