Category : Tutorials + Patches
Archive   : NAT_UART.ZIP
Filename : ACT.DOC
======================================================================
National Semiconductor Corporation
Greg DeJager February 8, 1989
Adapted from LBT.C -- Loopback Test Rev 1.1
Developed by: Brian A. Berg
BERG SOFTWARE DESIGN
Summary of Files
--------------------------
ACT.C C source code: main program, subroutines and interrupt handler
ACT.EXE executable ACT program; only this file is needed to run the ACT
SERIO.H header file containing UART definitions for C code use
STDHDR.H header file containing "standard" definitions for C code use
Intro, Hardware Setup and Program Operation
===========================================
This test was developed to run on all IBM AT or AT compatible architectures
as well as IBM PS/2 Model 30 - 80 machines. System requirements include
two separate machines with an NS16450 or INS8250A UART located at COM1, 2 or 3
and an RS-232 DTE to DTE interface between them. The DTE-DTE interface must
have the following connections:
Tx----------------------------Rx
Rx----------------------------Tx
RTS--------------------------CTS
CTS--------------------------RTS
GND--------------------------GND
The executable software is titled ACT.EXE. To run the test, the above
hardware must be set up and after entering the proper directory, the user
must type ACT
to start both machines and then hit a key to begin the test. This procedure
is necessary to ensure that all modem control outputs are deasserted before
program start-up so that a machine won't begin transmitting before the
other is ready to receive. Full duplex transmission begins after a key is
hit on both machines and each machine has exchanged initial RTS signals.
Proper test operation is indicated by a '|' and '_' character being printed
to the screen every 2560 characters received.
All operations are interrupt driven. UART line status, receiver and transmitter
interrupts are enabled. When not servicing interrupts, the CPU sits in a
loop checking for a keyboard hit (means for user to stop test) and for errors
produced within the interrupt service routines. A transmitter interrupt is
generated whenever the transmit holding register empties. The CPU services
the interrupt by writing the next character to the holding register ONLY if CTS
is asserted. If CTS is not asserted a timer variable is incremented and compared
to a large number (50). If 50 transmit interrupts occur in succession
without CTS being asserted, the program assumes that the other machine has
stopped and the program is ended.
A receiver interrupt is generated when the receiver buffer gets a new character.
The CPU immediately deasserts RTS to stop any further transmission from the
other machine. It then reads the byte out of the receiver buffer comparing
it to an expected value. Data transmitted and received sequences between 00
and FFH. If a mismatch occurs, the expected and received data are displayed
and the program stops. A line status interrupt results from an Overrun, Framing
or Parity error or Break condition. Upon receiving the status interrupt, the
program prints the corrupted data and the line status register value and exits
the program. Inconsistencies between the Interrupt ID and Line Status Registers
also cause error messages to be printed and the program to stop.
There is a restriction associated with porgram operation. The maximum baudrate
that can be selected is 56k; however, this baudrate is limited by the processor
speed and the host system. A 10Mhz AT compatible and 12Mhz PS/2 Model 30
operate reliably at a maximum of 19.2k baud. At higher baud rates operation
is system dependent due to the overhead involved with processing the interrupts.
The default com port is COM1 and default baudrate is 9600. However, the user
can control these options by specifying arguments on the command line. Arguments
must be separated by spaces. The first argument is a selection of COM1, COM2
or COM3 (eg. ACT 2 selects COM2). The second argument is a decimal
divisor from 2 through 2304 which specifies a baudrate from 56k to 50 (the
default is 12, 9600 baud). The baudrate arguement must be proceeded on the
command line by the COM port designation. Again, specifying no arguments
causes a default of COM1, 9600 baud to be used. A command line which causes
the program to use COM3 and 19.2k baud is: ACT 3 6. A help screen is printed
if any improper argument is used or if ACT H is entered.
Programmer's Guide for ACT.C -- Rev 1.0
=======================================
Help Screen for ACT
-------------------
NOTE: The following is displayed if any incorrect arguments are supplied
to the ACT (this includes entering "act help")
HELP Screen for NS16450/INS8250A Asynchronous Communications Test (ACT)
USAGE: act [
arg1 arg2
('act' may be followed by no args, arg1 or arg1+2)
ARGUMENT MINIMUM VALUE MAXIMUM VALUE DEFAULT VALUE
============ =============== =============== ==============
COM-number 1 (for COM1) 3 (for COM3) 1
(serial line 0) (serial line 2) (COM1)
baudrate- 2 (56000 baud) 2304 (50 baud) 12
divisor (based on 1.8432 MHz crystal) (9600 baud)
* Sample baudrate divisors: for baud= 1200, use 96 *
* 2400 48 *
* 4800 24 *
* 9600 12 *
* 19200 6 *
Page 2 of 4
Programmer's Guide for ACT
===========================
Summary of ACT.C Subroutines
-----------------------------
NOTE: As the code itself is heavily commented, it should be inspected if
further clarification is necessary.
The following subroutines are contained in this file:
void main(int, char **); /* main program */
void interrupt far serint(void); /* serial interrupt handler */
void procarg(int, char **); /* process invocation arguments */
void savepar(void); /* save our environment parameters */
void rstrpar(void); /* restore our environment parameters */
void dspstr(UCHAR *); /* display a string on the console */
void usage(void); /* display usage info and exit */
1. main(): main program
The main program initializes the system as follows:
processes invocation arguments by calling procarg(),
uses the CLEAR_REGS() macro to clear the RBR, LSR, IIR and MCR registers,
saves environment parameters by calling savepar(),
sets the requested (or default) baud rate and LCR register,
prints name of test to screen
prints "Hit a key when other program has been started" and waits for keyboard hit,
enables IRQ by setting OUT2,
enables UART receiver and line status interrupts,
asserts RTS and after receiving CTS (RTS from other machine),
it prompts the operator to "Hit any non-control key to stop" the program.
It then starts full duplex communication by enabling transmitter interrupts
and then loops until either the global variable "errflag" changes from
FALSE (0) to TRUE (a specific error code), or for the operator strikes any
non-control keyboard key. The errflag variable is set by the interrupt
handler as described for serint().
While this loop is active, the global variable "tick" is inspected. If it is
non-zero, either "|" or "_" is displayed at one place on the screen in order
to inform the operator that the program is active. This is facilitated by
use of a flip-flop variable to index one of two ASCII strings. The character
is changed every 2560 bytes received.
After exiting this loop, the program waits for the TEMT bit in the LSR to be
set to indicate an empty transmitter. The CLEAR_REGS() macro is again
invoked. An 'End of program' message is printed and, if the interrupt
handler found an error, an error message corresponding to the code in the
variable errflag is output.
Page 3 of 4
Programmer's Guide for the ACT
===============================
Summary of ACT.C Subroutines (continued)
----------------------------------------
2. serint(): serial port interrupt handler
The interrupt handler first checks if the global "errflag" is TRUE. If so,
the interrupt is ignored by disabling UART interrupts and by sending the
PIC an EOI and exiting.
Then the IIR is read and each interrupt type is handled:
NO Interrupt Pending:
errflag <- False Interrupt error message code
Receiver Line STatus interrupt:
read and store LSR
read and store RBR
errflag <- Status error message code
Received Data AVailable (RDAV):
clear RTS
if Data Ready bit is set
read byte and compare to expected value else errflag <-
Receiver Error code
if mismatch is found, errflag <- Mismatch Error code
else increment byte counter variable and set 'tick if
2560 characters were received
if no errors were found RTS is reasserted
Transmitter Holding Register Empty:
the LSR is read
verify THRE bit set, errflag <- Tx Error message code if not
if CTS is asserted
write next byte to transmitter and clear timeout counter
else increment timeout counter and if it is > 50 (arbitrary
large number), errflag <- End of Program code (this means
that other machine has stopped requesting more data
(ie. CTS = 0) )
Any other value for the IIR:
errflag <- IIR Error code
All UART interrupts are disabled (IER <- 0)
If no errors were found, all interrupts are reenabled. This creates an edge
on the INTR line if multiple interrupts are pending. It also fixes the
full duplex bug involving simultaneous interrupts which is present in
16450 and 8250A UARTs
An EOI is sent to the PIC.
(NOTE: an IRET instruction is automatically generated to exit this int. handler)
Page 4 of 4
Programmer's Guide for ACT
===========================
Summary of ACT.C Subroutines (concluded)
----------------------------------------
3. procarg(): process invocation arguments
The invocation arguments as defined in the help screen are validated
by this routine. The help screen itself is displayed by calling
usage() if any illegal arguments are found.
Based on the COM argument (or its default), the interrupt vector number
and UART base address are set up for global use. The existence of
the requested COM port is verified; its non-existence causes program
termination.
4. savepar(): save our environment parameters
This routine saves the original interrupt vector, ctrl-break/ctrl-c
status and PIC mask, and then sets these up as required for FACT use.
It also saves some of the UART register values.
5. rstrpar(): restore our environment parameters
This routine is the complement for savepar(): it restores the saved
registers, interrupt vector, ctrl-break/ctrl-c status and PIC mask.
6. dspstr(): display a string of characters on the console
This routine uses the INT 10H software interrupt to display a string a
character at a time.
7. usage(): display program usage information and terminate (never return)
This routine displays the help screen and terminates the program.
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/