11 UART PORT
Figure 11-0.
Table 11-0.
Listing 1-0.
Overview
The UART peripheral is a full-duplex, Universal Asynchronous Receiver /
Transmitter that is compatible with the industry-standard 16450. The
UART converts data between serial and parallel formats. The serial com-
munication follows an asynchronous protocol that supports various word
length, stop bit, and parity generation options. This UART also contains
modem control and interrupt handling hardware although only the data
signals TxD and RxD are routed to pins on the ADSP-2191. Interrupts
may be generated from 12 unique events.
As the UART is ADSP-2191 DMA capable with support for separate TX
and RX DMA Master channels, the UART may be used in either a pro-
grammed I/O mode or in a DMA mode of operation. The I/O mode
requires software management of the data flow using either interrupts or
polling. The DMA mode requires minimal software intervention as the
DMA engine itself moves the data.
The UART and DMA Channel registers can be accessed through I/O
memory space (registers). For a description of I/O memory space, see
“ADSP-2191 DSP I/O Registers” on page B-1.
The UART memory map is a 16450 legacy with byte wide registers
(remapped as half words with MSByte zero-filled) and the packing of mul-
tiple registers into the same address location.
The UART has two interrupt outputs referred to as the RX and TX inter-
rupts. The TX interrupt is available in DMA mode only. In IO mode all
ADSP-219x/2191 DSP Hardware Reference 11-1
Serial Communications
interrupts use the RX interrupt channel. Also note that in the DMA
mode, the Break and Modem status interrupts are not available.
In the I/O mode, the RX interrupt is generated for all cases:
• RBR Full
• Receive Overrun Error
• Receive Parity Error
• Receive Framing Error
• Break Interrupt (RXD held low)
• Modem status interrupt
• THR Empty
For information on the DMA process, see “I/O Processor” on page 6-1.
Serial Communications
An asynchronous serial communication protocol is followed with these
options:
• 5–8 data bits
• 1, 1½, or 2 stop bits
• None, even, or odd parity
• Baud rate = HCLK / (16 * DIVISOR) where DIVISOR = 1 to 65536
All data words require a start bit and at least one stop bit. This creates a
range of 7 to 12 bits for each word. The format of a received and transmit-
ted character frame is controlled by the Line Control (LCR) register. It is
11-2 ADSP-219x/2191 DSP Hardware Reference
UART Port
described Figure B-26 on page B-71. Data is always transmitted and
received Least Significant Bit first.
Transmit operation is initiated by writing to the Transmit Holding (THR)
register. After a synchronization delay the data is moved to the Transmit
Shift (TSR) register, where it is shifted out at a baud (bit) rate equal to HCLK
/ (16 * DIVISOR) with start, stop, and parity bits appended as required. All
data words begin with a low-going start bit. The transfer of the THR to the
TSR sets the Transmit register Empty Status flag.
Figure 11-1 shows the physical bit stream as it could be measured on the
TxD pin.
Data bits (5 to 8) Stop bits
0x53 = 'S'
D0 D1 D2 D3 D4 D5 D6 D7
Start bit LSB Parity (optional, odd or even)
Figure 11-1. Bit Stream as Measured on TxD Pin
Receive operation uses the same data format as the transmit configuration
except that the number of stop bits is always one. Upon detection of the
start bit, the received word is shifted in the Receive Shift (RSR) register,
assuming again a bit rate of HCLK / (16 * DIVISOR). After the appropriate
number of bits (including stop bits) are received, the data and status are
updated, and the RSR is transferred to the Receive Buffer (RBR) register.
The receive buffer register full status flag (Data Ready DR) is updated after
the appropriate synchronization delay and transfer of the received word to
the buffer.
A sampling clock equal to 16 times the baud rate is used to sample the
data as close to the midpoint of the bit as possible. Because the internal
sample clock may not exactly match the asynchronous receive data rate,
ADSP-219x/2191 DSP Hardware Reference 11-3
I/O Mode
the sampling error (drift of sampling point from the center of each bit)
needs to be taken into account. The sampling point is re-synchronized
with each start bit so that the error only accumulates over the length of a
single word. A receive filter removes spurious pulses of less than two times
the sampling clock period.
The bit rate is characterized by the Peripheral Clock HCLK and 16-bit
DIVISOR. DIVISOR is split into the low significant byte DLL and the high
significant byte DLH. If both DLL and DLH equal zero, a DIVISOR value of
65536 is assumed. As on the 16450, the divisor latch registers DLL and DLH
are mapped to the same addresses as RBR, THR and IER. The DLAB bit in the
LCR register needs to be set before these registers can be accessed. Please
refer to “UART Registers” on page B-65 for details.
I/O Mode
In I/O mode data is moved to and from the UART by the DSP's core. To
transmit a character, please load it into the Transmit Hold (THR) register.
Received Data can be read from the Receive Buffer (RBR) register.
Since the architecture does not provide send and receive FIFOs, the core
has to write and read one character at time. To prevent any loss of data
and misalignments of the serial data stream, the Line Status ( LSR) register
provides two status flags for handshaking.
The THR Empty (THRE) flag is set when the THR register is ready for new
data and cleared when the core loads new data into. Writing the THR when
it is not empty overwrites the register by the new value and the previous
character is never transmitted. The Data Ready (DR) flag signals when new
data is available in the RBR register. This flag is cleared automatically when
the core reads from RBR. Reading the RBR when it is not full means that the
previously received word will be read again.
With Interrupts disabled, the program might poll these status flags to
determine when data is ready to move. Please note that because polling is
11-4 ADSP-219x/2191 DSP Hardware Reference
UART Port
processor intensive, it is not typically used in real-time signal processing
environments.
Alternatively UART writes and reads might be accomplished by Interrupt
Services Routines (ISRs). Both of the flag pins, the THRE and the DR can
generate an Interrupt Request, when enabled in the Interrupt Enable ( IER)
register. Interrupts may also be masked using the IMASK register and the
Global Interrupt Enable bit in INCTL. In I/O Mode both Interrupt Sources
share the same Interrupt request mentioned as “UART Receive Interrupt”
listed in Table C-2 on page C-3. The Interrupt Service Routine might
evaluate the STATUS bit field within the Interrupt Identification (IIR)
register to determine the exact interrupt source.
Please be aware that also this single-character Interrupt mode puts certain
constraints on the software to respond within a guaranteed time to prevent
overrun errors from occurring in the receive channel.
DMA Mode
In the DMA mode, separate and independent RX and TX DMA channels
are responsible for moving data between the peripheral and memory. The
processor is relieved of the task of moving data, and simply sets up the
appropriate transfers through either the ADSP-2191 descriptor mecha-
nism or the autobuffer mode. In DMA mode RX and TX have separate
Interrupt channels. The DMA Interrupt mechanism works independent
from the IER and IIR registers.
No additional buffering is provided in the UART’s DMA channel so the
same latency requirements exist as in I/O mode. However the latency is
determined by the bus activity and arbitration mechanism and not the
processor loading and interrupt priorities.
ADSP-219x/2191 DSP Hardware Reference 11-5
DMA Mode
Descriptors
DMA functionality is most often controlled by the ADSP-2191 DMA
descriptor method. Each descriptor block contains all the information on
a particular data movement operation as well as the pointer to the next
descriptor block of information. When a descriptor block is complete,
work proceeds to the next descriptor block. The data structure for a single
descriptor block is illustrated in Table 11-1 on page 11-6 where HEAD
refers to the address of the current descriptor:
Table 11-1. Descriptor Block Data Structure
Address Location Name Description
HEAD+0 DMA Configuration Descriptor ownership and control info
HEAD+1 DMA Start Page Page info for transfer
HEAD+2 DMA Start Addr Address of transfer
HEAD+3 DMA Word Cnt Number of words in transfer
HEAD+4 Next Descriptor Pointer to address of next descriptor
Since descriptors are contained in Page 0 of internal memory, each DMA
master unit must fetch this descriptor information from internal memory
and update the peripheral’s internal DMA registers. The dynamic alloca-
tion of descriptors is controlled by the “ownership” bit of each descriptor
block (bit 15 of the configuration). Before a full descriptor block down-
load is begun this bit is checked to determine if the descriptor block is
configured and ready for use. If it is not ready, then the DMA engine goes
into a wait mode until this bit is set. This “snoop” mode waits until a core
write occurs to the descriptor ready register. There must be a concluding
write to this register after a descriptor block is added to Page 0. This trig-
gers the DMA hardware to reread the configuration descriptor. Once the
“ownership” bit is read as a one, the remaining four words of the block are
11-6 ADSP-219x/2191 DSP Hardware Reference
UART Port
loaded. This descriptor information is then used to carry out the required
data transactions.
The following illustrates the typical steps the software takes in setting up a
single descriptor.
1. Memory writes HEAD+1,+2,+3,+4 to memory Page 0.
2. Memory writes HEAD+0 to memory Page 0. Bit 15 (ownership)
must be set to 1.
3. I/O writes descriptor ready register of respective DMA channel (if
necessary)
4. I/O writes NXTPTR register of DMA channel.
5. I/O writes Config register setting DEN high (if not already enabled)
The Interrupt Service Routine must write a '0x01' to the UARDT_IRQ or
UARDR_IRQ register in order to clear the DMA Interrupt Request. Also the
last instance might reset the entire UARDT_CFG or UARDR_CFG register to dis-
able the DMA.
After a work unit is complete, the DMA writes the completion status
information back to the Page 0 and the descriptor’s HEAD address. It also
resets the Ownership bit back to 0 returning ownership back to the pro-
cessor. The software is responsible for cleaning up or reusing descriptors as
desired. The management of the descriptor cleanup is typically initiated
by a completion interrupt.
Autobuffer Mode
The Autobuffer DMA mode can be used when only simple linear or circu-
lar buffer types of transfers are required. This mode is less flexible than the
Descriptor DMA mode but requires also less software overhead and DMA
bandwidth.
ADSP-219x/2191 DSP Hardware Reference 11-7
DMA Mode
Most of DMA register are normally read-only, but become writable when
Autobuffer DMA mode is enabled. (The register section indicates these
registers with an *). After configuring the DMA, the software enables the
DMA with the DMAEn control bit. DMA operation proceeds as described.
When the count reaches its endpoint, the start address and count are both
reset to their original value, effectively creating a circular buffer. If
enabled, interrupts are generated at the halfway point (rounded down)
and completion point of the transfer (for example: an 11 word transfer
would generate interrupts after the 6th and 11th transfers).
The following example illustrates typical Autobuffer DMA mode use:
• IO writes config register setting only the DAUTO bit high.
• IO writes page, start, and count values.
• IO writes config again, setting direction and sets DEN high.
Transfers can be aborted at any point by setting DEN low.
Mixing Modes
The IO mode and the DMA modes use different synchronization mecha-
nisms. Basically this means that any serial communication should be
completed before the program can switch from IO mode to DMA mode
or vice versa. Before setting up a DMA transmission, make sure that both
the Transmit Hold (THR) register and the Transmit Send ( TSR) register are
empty by polling the THRE and the TEMT Bit in the Line Status (LSR) regis-
ter. In the opposite case, wait until the two bits of the dma buffer status in
the UARDT_CFG register get cleared.
11-8 ADSP-219x/2191 DSP Hardware Reference
UART Port
Code Examples
Initiate UART
The following code example initializes the UART assuming a HCLK clock
of 16 MHz. The serial format is 8 bits, 9600 bps, no parity, and one stop
bit.
#include <def2191.h>
#define DLAB 0x80 /* divisor latch access bit in LCR */
#define WLS8CHAR 0x03 /* Word length of 8 Bits */
/*UART registers are mapped to IO page 5 */
iopg =UART_Controller_Page;
/*To access divisor latch registers set DLAB bit */
ar =DLAB; io(LCR)=ar;
/* 16MHz / 16 / 9600 =104d =68h */
ar =0x68; io(DLL)=ar;
ar =0x00; io(DLH)=ar;
/*8 bit,no parity,one stop bit,clear DLAB */
ar =WLS8CHAR; io(LCR)=ar;
Polling on the TX Channel
The following example code demonstrates how polling can be imple-
mented on the TX channel. A real-world implementation might require
additional time-out functionality.
#include <def2191.h>
#define THRE…0x20…/* THR empty */
/*AR holds the next value to transmit */
putc:
/*UART registers are mapped to IO page 5 */
iopg =UART_Controller_Page;
/* wait until Transmit Hold register is ready */
ADSP-219x/2191 DSP Hardware Reference 11-9
Code Examples
poll_thre:
ax0 =io(LSR);
af =ax0 and THRE;
if eq jump poll_thre;
/* finally send next value */
io(THR)=ar;
rts;
Interrupt Controlled Transmission
To prepare interrupt controlled transmission the following lines might be
used. Please note that in IO mode also the TX channel signals interrupt
requests to the RX interrupt. By default the RX interrupt uses the IRQ 11
as assumed in this example.
#include <def2191.h>
#define ETBEI 0x02 /* Enable TX Interrupt */
/*UART registers are mapped to IO page 5 */
iopg =UART_Controller_Page;
/*load first value manually */
ar =dm(first_value);
call putc;
/*enable TX source on RX interrupt using IRQ 11 */
ar =ETBEI; io(IER)=ar;
/*clear pending RX requests and enable IRQ 11*/
irptl =0x0000;
nop;
imask =0x0800;
/*enable Interrupt globally */
ena int;
Descriptor DMA on the UART TX channel
The following example illustrates the typical setup of a descriptor DMA
on the UART TX channel. Two strings will be sent out. Once the first one
11-10 ADSP-219x/2191 DSP Hardware Reference
UART Port
has been completed the descriptor block of the second one is activated
without core activity. After the second (and last) one has been shifted out
an interrupt is generated. Please note that strings are usually null-termi-
nated by convention (C-style). The trailing null character is not used in
DMA mode.
#include <def2191.h>
.section /dm dmdata;
.var sText1 [] = 'Test String 1',13,10,0;
.var sText2 [] = 'Test String 2',13,10,0;
/*descriptor blocks must be placed in page 0 */
.var tcbTX1 [5] =
0x8001, /*ownership and enable */
PAGE(sText1), /*start page */
sText1, /*start address */
LENGTH(sText1)-1, /*number of bytes */
tcbTX2; /*next descriptor block */
.var tcbTX2 [5] =
0x8005, /*interrupt on completion */
PAGE(sText2), /*start page */
sText2, /*start address */
LENGTH(sText2)-1, /*number of bytes */
0; /*don 't care if ISR disables DMA */
.section /pm program;
iopg =UART_Controller_Page;
/* enable TX interrupt on IRQ 12 as assigned by default */
irptl =0x0000;
nop;
imask =0x1000;
ena int;
/*first disable DMA and Autobuffer mode */
ar =0x0000; dm(UARDT_CFG)=ar;
/*load address of first descriptor block */
ar =tcbTX1; io(UARDT_CP)=ar;
ADSP-219x/2191 DSP Hardware Reference 11-11
Code Examples
/*signal Descriptor Block ready */
ar =0x0001; io(UARDT_CPR)=ar;
/*start DMA by setting Enable Bit */
ar =0x0001; io(UARDT_CFG)=ar;
This example assumes that the DMA is disabled by the interrupt service
routine invoked when the last character of sText2 has been loaded by the
DMA engine. Alternatively, the next descriptor pointer of the last descrip-
tor in the chain (here tcbTX2) might point to any page 0 address that
contains a zero value. Then, the DMA is be stopped automatically,
because the additional TCB load clears the DMA enable bit.
Note that the ownership bit in the descriptor is set. Doing so, the program
might poll the ownership bit within tcbTX2 in memory to determine the
completion of the DMA transfer without having interrupts enabled.
Setup Autobuffer DMA on TX Channel
The following example illustrates the typical setup of an autobuffer DMA
on the UART TX channel. Please note that the TX interrupt is requested
twice. Without any additional software flag the Interrupt Service Routine
cannot determine whether it was invoked by a halfway request or a com-
pletion request.
#include <def2191.h>
.section /dm dmdata;
.var sText [] = 'Hello World',13,10,0;
.section /pm program;
iopg = UART_Controller_Page;
/*set to autobuffer mode -make DMA registers writeable */
ar = 0x0010; io(UARDT_CFG) = ar;
/*set start page and address */
ar = PAGE(sText); io(UARDT_SRP) = ar;
ar = sText; io(UARDT_SRA) = ar;
11-12 ADSP-219x/2191 DSP Hardware Reference
UART Port
/*set number of characters without terminating zero */
ar = LENGTH(sText)-1; io(UARDT_CNT) = ar;
/*enable DMA, Autobuffer Mode, Interrupt on completion */
ar =0x0015; io(UARDT_CFG) = ar;
/*finally enable IRQ 12 -TX is assigned to by default */
irptl =0x0000;
nop;
imask =0x1000;
ena int;
Auto-baud Rate Detection Using Timer 0
In WIDTH_CNT mode, the three general purpose timers have the capability
to disconnect their input from the TMRx pin and connect it to the UART’s
RXD pin. This enables a glueless auto-baud support.
In the following example, the DSP waits after reset until it receives any
low pulse on the RXD pin. By convention, it assumes that this low pulse
represents a NULL character (ASCII 0x00) in an 8 bit data format and
parity bit disabled. In this way, the DSP can divide the measured pulse
width by number of containing bits to get the reciprocal baudrate. To
determine the proper value for the divisor latch registers, use the following
formula:
Width Count
Divisor Latch = ------------------------------------------------
16 × Number of Bits
width count is composed by the two 16-bit registers T_WHRx and T_WLRx.
The two 8-Bit registers DLH and DLL form the divisor latch. In the example,
the low pulse contains 9 bits: 8 data bits plus the start bit.
#include <def2191.h>
#define TIMIRQ0 0x01 /* Timer 0 Interrupt Latch */
ADSP-219x/2191 DSP Hardware Reference 11-13
Code Examples
#define TIMEN0 0x0100 /* Timer 0 Enable Set */
#define TIMDIS0 0x0200 /* Timer 0 Enable Clear */
#define DLAB 0x80 /* divisor latch access bit in LCR */
#define WLS8CHAR 0x03 /* Word length of 8 Bits */
/* First Initialize Timer 0 */
iopg = Timer_Page;
/* Width Capture Mode on Auxiliary, Low-Pulse,
Enable Interrupt Latch */
ar = 0x0032; io(CFGR0) = ar;
/* clear IRQ latch */
ar = TIMIRQ0; io(GSR0) = ar;
/* enable timer 0 */
ar = TIMEN0; io(GSR0) = ar;
/* wait until complete low pulse is done */
ay0 = TIMIRQ0;
wait_for_low_pulse:
ax0 = io(GSR0);
none = ax0 and ay0;
if eq jump wait_for_low_pulse;
/* pulse width is captured by WHR0:WLR0 */
/* divide WHR0:WLR0 by (16 x 9 = 144) */
/* integer division requires left shift */
sr0 = io(WLR0);
si = io(WHR0);
sr = lshift sr0 by 1 (lo);
sr = sr or lshift si by 1 (hi);
/* unsigned division core ay0 = af:ay0 / ax0 */
ay0 = sr1;
af = pass ay0, ay0 = sr0;
ax0 = 144;
astat = 0;
divq ax0; divq ax0; divq ax0; divq ax0;
divq ax0; divq ax0; divq ax0; divq ax0;
divq ax0; divq ax0; divq ax0; divq ax0;
divq ax0; divq ax0; divq ax0; divq ax0;
/* division result in ay0 */
11-14 ADSP-219x/2191 DSP Hardware Reference
UART Port
iopg = UART_Controller_Page;
/* access baud rate divisor latch */
ar = DLAB; io(LCR) = ar;
/* split ay0 into DLH and DLL */
ar = 0xFF;
ar = ar and ay0;
sr = lshift ay0 by -8 (lo);
io(DLL) = ar;
io(DLH) = sr0;
/* initialize UART to 8 Bit, No Parity */
ar = WLS8CHAR; io(LCR) = ar;
/* disable timer 0 again */
ar = TIMDIS0; io(GSR0) = ar;
ADSP-219x/2191 DSP Hardware Reference 11-15
Code Examples
11-16 ADSP-219x/2191 DSP Hardware Reference