The UART Project: Applying What We've Learned About Linux Device-Drivers To The PC's Serial-Port Controller
The UART Project: Applying What We've Learned About Linux Device-Drivers To The PC's Serial-Port Controller
<http://cs.usfca.edu/~cruse/cs635f07>
student student
workstation workstation
rackmount rackmount
PC system ‘null-modem’ serial cable PC system
ethernet cables
Using ‘echo’ and ‘cat’
• Your device-driver module (named ‘uart.c’)
is intended to allow unprivileged programs
that are running on a pair of adjacent PCs
to communicate via a “null-modem” cable
Transmitting… Receiving…
08 09 10 15 16 17 18 19 20 28 29 30
04 05 06 07 11 12 13 14 24 25 26 27
01 02 03 21 22 23
lectern
module’s ‘payload’
function
is a collection of
function callback-functions
having prescribed
prototypes
function AND
...
a ‘package’ of
fops
function-pointers
serial
cable
Data Data
phone Communications Terminal
wire
Equipment Equipment
(DCE) (DTE)
Serial data-transmission
The Transmitter Holding Register (8-bits) Software outputs a byte
of data to the THR
0 1 1 0 0 0 0 1
The bits are immediately
copied into an internal
‘shift’-register
0 1 1 0 0 0 0 1 1-0-1-1-0-0-0-0-1-0
stop start
clock clock-pulses bit bit
trigger bit-shifts
Serial data reception
input voltage
clock
clock-pulses trigger
voltage-sampling
and bit-shifts
at regular intervals The receiver’s internal ‘shift’ register
1-0-1-1-0-0-0-0-1-0 0 1 1 0 0 0 0 1
data-bits
stop start
bit bit
1 Carrier Detect 1
6 6
Data Set Ready
Rx data
Request To Send
Tx data
Clear To Send
Data Terminal Ready
Ring Indicator
9 9
Signal Ground
5 5
Signal functions
• CD: Carrier Detect The modem asserts
this signal to indicate that it successfully
made its connection to a remote device
• RI: Ring Indicator The modem asserts
this signal to indicate that the phone is
ringing at the other end of its connection
• DSR: Data Set Ready Modem to PC
• DTR: Data Terminal Ready PC to Modem
Signal functions (continued)
• RTS: Request To Send PC is ready for
the modem to relay some received data
• CLS: Clear To Send Modem is ready for
the PC to begin transmitting some data
9-wire null-modem cable
CD CD
RxD RxD
TxD TxD
GND GND
DSR DSR
DTR DTR
RTS RTS
CTS CTS
RI RI
Data Data
Terminal Terminal
Equipment Equipment
no modems
The 16550 UART registers
Base+0 Divisor Latch Register 16-bits (R/W)
DATA
OUT
start-bit data-bit 0 data-bit 1 …
sample sample
7 6 5 4 3 2 1 0
LOOP
0 0 0 OUT2 OUT1 RTS DTR
BACK
Legend:
DTR = Data Terminal Ready (1=yes, 0=no)
RTS = Request To Send (1=yes, 0=no)
OUT1 = not used (except in loopback mode)
OUT2 = enables the UART to issue interrupts
LOOPBACK-mode (1=enabled, 0=disabled)
Modem Status Register
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
Received
Error in Transmitter THR Break Framing Parity Overrun
idle
Data
Rx FIFO empty interrupt error error error
Ready
This status-bit
indicates that the This status-bit indicates that
data-transmission the Transmitter Holding Register
has been completed is ready to accept a new data byte
7 6 5 4 3 2 1 0
Divisor even number
set stick parity word length
Latch parity of stop
break parity enable selection
access select bits
00 = 5 bits
01 = 6 bits
10 = 7 bits
11 = 8 bits
0 = 1 stop bit
0 = normal 1 = 2 stop bits
1 = ‘break’ 0 = no parity bits
1 = one parity bit
0 = not accessible
1 = even parity
1 = assessible
0 = ‘odd’ parity
Interrupt Enable Register
7 6 5 4 3 2 1 0
Modem Rx Line THR Received
0 0 0 0 Status Status is data is
change change empty available
7 6 5 4 3 2 1 0
DMA XMIT RCVR
RCVR FIFO FIFO
reserved reserved Mode FIFO FIFO
trigger-level select reset reset enable
00 = 1 byte
NOTE: DMA is unsupported
01 = 4 bytes
for the UART on our systems
10 = 8 bytes
11 = 14 bytes
Writing 0 will disable the UART’s FIFO-mode, writing 1 will enable FIFO-mode
Interrupt Identification Register
7 6 5 4 3 2 1 0
0 0
‘highest priority’
00 = FIFO-mode has not been enabled
11 = FIFO-mode is currently enabled UART interrupt
highest
still pending
011 = receiver line-status
010 = received data ready
100 = character timeout
001 = Tx Holding Reg empty
000 = modem-status change
lowest
YES
DONE
How to receive a byte
Received Data
NO is Ready?
YES
DONE
How to implement in C/C++
DONE
How to adjust the cpu’s IOPL
• Linux provides a system-call to privileged
programs which need to access I/O ports
• The <sys/io.h> header-file prototypes it,
and the ‘iopl()’ library-function invokes it
• The kernel will modify the CPU’s current
I/O Permission Level in cpu’s EFLAGS (if
the program’s owner has ‘root’ privileges)
• So you first execute our ‘iopl3’ command
In-class experiments
• For learning purposes, we can write user-
programs that are able to execute ‘in’ and
‘out’ instructions, and so control the UART
• But to avoid the CPU’s normal ‘segfaults’
we will have to acquire I/O privileges
• The ‘iopl3’ command (created by our CS
System Administrator Alex Fedosov) will
establish the permissions which we need
Experiment #1
• Download and run our ‘testuart.cpp’ demo
• It uses the UART’s ‘loopback’ test mode to
‘receive’ each character that it ‘transmits’
TxShiftReg TxData
RxShiftReg RxData
Output loops back to become input The external signal-lines are bypased
Experiment #2
• Download and run our ‘uartecho.cpp’ app
(it does nothing untill you do the next step)
• Modify the ‘testuart.cpp’ demo-program by
commenting out the instruction that places
the UART into ‘loopback’ mode
• Execute those two programs on a pair of
PCs that are connected by a null-modem
Experiment #3
• Add a pair of counters to ‘testuart.cpp’:
– Declare two integer variables (initialized to 0)
int txwait = 0, rxwait = 0;
– Increment these in the body of your do-loops
do { ++txwait; } while ( /* Transmitter is busy */ );
do { ++rxwait; } while ( /* Receiver not ready */ );
– Display their totals at the demo’s conclusion
printf( “txwait=%d rxwait=%d \n”, txwait, rxwait );
Experiment #4
• Modify the ‘testuart.cpp’ demo-program to
experiment with using a different baud rate
and a different data-format
• For example, use 300 baud and 7-N-2:
– output 0x0180 to the Divisor Latch register
– output 0x06 to the Line Control register
• Then, to better observe the effect, add the
statement ‘fflush( stdout );’ in the program
loop immediately after ‘printf( “%c”, data);’
Is your cable working?
• We created a diagnostic program (called
‘trycable.cpp’) that you can use to check
whether two PCs are properly connected
with a working “null-modem” cable
• You run ‘uartecho.cpp’ on one of the PCs
and then execute ‘testcable.cpp’ on the
adjacent PC – you will see a message on
both screens if your cable is working OK