DSPRelated.com
Forums

UART using SPORT

Started by tejabhi p June 5, 2004

I am referring the App.Note EE-60 and the corresponding code

(pls find attached) to generate UART using SPORT.

I have two queries

1) In the functions to output character from the processor e.g. Outchar function,

we move the data into 'Txdata'. But how does the transmit interrupt get generated

when we do this ?

2) For what is the IDMA used here? Is it necessary?

Regards,

Tejabhi




/* 21xxUart.dsp

AUTHOR: Greg G.

VERSION 1.0 02/22/99
Name Date Description
---- -------- -----------
MOD/HISTORY: gg 02/22/99 put everythin in one file,
add support for both sports,
create a minimal example

gg 09/13/99 port to the 218x ez-kit lite,
changed tx routines to 2 words,
changed to 15 bits/serial word,
no parity, tested to 115200 baud

CALLED BY:

notes: The idea is to gather all of the various include files
and other stuff all into this one file. The initial testing
platform is the ADMC32x evaluation board (which has a ADMC331
installed.) Subroutines: */

/* software uart state machine definitions */
#define UartTxStateInactive 0
#define UartTxStateWord1 1
#define UartTxStateWord2 2
#define UartTxStateWord3 3
#define UartTxStateError 4

#define UartRxStateWord1 0
#define UartRxStateWord2 1
#define UartRxStateError 2

#define TxLowerLimit 0x30
#define TxUpperLimit 0x7f

/* serial port control register stuff */
#define InvertReceiveFrameSync 6
#define InternalTransmitFrameSync 9
#define TransmitFrameAlternate 10
#define TransmitFrameRequired 11
#define ReceiveFrameAlternate 12
#define ReceiveFrameRequired 13
#define InternalSerialClock 14
#define SerialWordLength_16bits 15
#define SerialWordLength_15bits 14

#define ReceiveAutoBufferEnable 0
#define TransmitAutoBufferEnable 1

/* processor specific stuff */
/* memory mapped core registers of the ADMC331 */

.CONST SYSCNTL = 0x3fff;
.CONST MEMWAIT = 0x3ffe;
.CONST TPERIOD = 0x3ffd;
.CONST TCOUNT = 0x3ffc;
.CONST TSCALE = 0x3ffb;
.CONST Sport0_Rx_Words1 = 0x3ffa;
.CONST Sport0_Rx_Words0 = 0x3ff9;
.CONST Sport0_Tx_Words1 = 0x3ff8;
.CONST Sport0_Tx_Words0 = 0x3ff7;
.CONST Sport0_Ctrl_Reg = 0x3ff6;
.CONST Sport0_Sclkdiv = 0x3ff5;
.CONST Sport0_Rfsdiv = 0x3ff4;
.CONST Sport0_Autobuf_Ctrl= 0x3ff3;
.CONST Sport1_Ctrl_Reg = 0x3ff2;
.CONST Sport1_Sclkdiv = 0x3ff1;
.CONST Sport1_Rfsdiv = 0x3ff0;
.CONST Sport1_Autobuf_Ctrl= 0x3fef;

#define IdmaControlReg 0x3fe0
#define IDMAD_BIT 14 /* IDMAD = 1 for dm */
#define IDMA_BUFFER_SIZE 2000

/* Interrupt Vector Table */
.CONST PIO_INT_ADDR = 0x0008;
.CONST PWMSYNC_INT_ADDR = 0x000C;
.CONST PWMTRIP_INT_ADDR = 0x002C;
.CONST TX0_INT_ADDR = 0x0010;
.CONST RX0_INT_ADDR = 0x0014;
.CONST SW1_INT_ADDR = 0x0018;
.CONST SW0_INT_ADDR = 0x001C;
.CONST TX1_INT_ADDR = 0x0020;
.CONST RX1_INT_ADDR = 0x0024;
.CONST TIMER_INT_ADDR = 0x0028;

/* Rom Utilities */
.CONST PUT_VECTOR = 0X0DF4; /* miscellaneous definitions */
#define ZERO m0 /* m0=0 always */
#define ONE m1 /* m1=1 always */

#define TRUE ONE
#define FALSE ZERO {*****************************************************}
{ }
{ Variable definitions }
{ }
{*****************************************************}

.var/ram/dm/circ TestBuffer[32]; /* test capture buffer */

.var/dm/ram TxState; /* uart 0 tx state variable */
.var/dm/ram TxData; /* data byte to tx */
.var/dm/ram RxState; /* uart 0 rx state variable */
.var/dm/ram RxData; /* data byte to rx */

.VAR/RAM/DM RxUpperWord;
.VAR/RAM/DM RxLowerWord;
.VAR/RAM/DM TxUpperWord;
.VAR/RAM/DM TxLowerWord;

.var/ram/dm ByteCharHi; /* storage for ascii display values */
.var/ram/dm ByteCharLo;

.var/ram/dm BigBuffer[IDMA_BUFFER_SIZE];
.var/ram/dm IdmaTop;
.var/ram/dm BufferPtr;

#define SPORT1_UART /* use the sport1 pins */
#define BAUD 57600 #define ASCII_0 0x30
#define ASCII_9 0x39
#define ASCII_ADJUST 7 /* to convert to A..F ascii range */ .CONST CLKFREQ = 33340000; /* processor instruction frequency */
.CONST UARTCLK=(CLKFREQ/((3*BAUD)*2)) - 1;
/******************************************************************************
* Interrupt vector table
******************************************************************************/
jump Start; rti; rti; rti; /* 00: reset */
rti; rti; rti; rti; /* 04: IRQ2 */

rti; rti; rti; rti; /* 08: IRQL1 */
rti; rti; rti; rti; /* 0c: IRQL0 */

rti; rti; rti; rti; /* 10: SPORT0 tx */
rti; rti; rti; rti; /* 14: SPORT0 rx */

jump Irqe; rti; rti; rti; /* 18: IRQE */
rti; rti; rti; rti; /* 1c: BDMA */

jump UartTx; rti; rti; rti; /* 20: SPORT1 tx or IRQ1 */
jump UartRx; rti; rti; rti; /* 24: SPORT1 rx or IRQ0 */

rti; rti; rti; rti; /* 28: timer */
rti; rti; rti; rti; /* 2c: power down */

/******************************************************************************
* ADSP 2181 intialization
******************************************************************************/ /*-*/
Start:

call InitStuff; /* setup various registers */
call InitUart;

IFC = 0x00; {Clear any pending interrupts }

#ifdef SPORT0_UART
ay0 = 0x060;
#else
ay0 = 0x006;
#endif

ar = IMASK;
ar = ar OR ay0; /* enable sport tx and receive ints */
ay0=0x10; /* irQE enabled */
ar=ar OR ay0;
IMASK = ar;

ar=0xffff; /* start serial transmit - all 1's */

#ifdef SPORT0_UART
tx0=ar;
#else
tx1=ar;
#endif
idle;

call CrLf;
call CrLf;

ar=0x1234;
call DisplayWord;
call Spaces;

ar=0xabcd;
call DisplayWord;
call CrLf; ar=0x5678;
call DisplayWord;
call Spaces;

ar=0xef01;
call DisplayWord;
call CrLf;
call CrLf;
ar=0x55;
call TxTest;
ar=0x56;
call TxTest;

ar=0x56;
call TxTest;
ar=0x31;
call TxTest;

ar=0x30;
call TxTest;
ar=0x31;
call TxTest;

ar=0x32;
call TxTest;
ar=0x33;
call TxTest;

ar=0x34;
call TxTest;
ar=0x35;
call TxTest;

ar=0x36;
call TxTest;
ar=0x37;
call TxTest;

ar=0x38;
call TxTest;
ar=0x39;
call TxTest;

ar=0x41;
call TxTest;
ar=0x42;
call TxTest; IdmaTestLoop:
call CheckIDMA;
nop;
jump IdmaTestLoop; cntrP0;
do TxAsciiTest until ce;
call TxTestData;
call PollForTxEmpty;
TxAsciiTest: nop;

MainLoop: /* dummy loop, interrupts handle everything */
nop;
jump MainLoop;

TxTest:
OutChar:
dm(TxData)=ar;
dm(TxState)=ONE;

PollForTxEmpty:
ar=dm(TxState);
ay0=UartTxStateInactive;
ar=ar-ay0;
if NE jump PollForTxEmpty;
rts;

/*-*/
InitUart:

#ifdef SPORT0_UART
ar=0;
ar=SETBIT InternalSerialClock of ar;
ar=SETBIT ReceiveFrameAlternate of ar;
ar=CLRBIT ReceiveFrameRequired of ar;

ar=SETBIT InternalTransmitFrameSync of ar;
ar=SETBIT TransmitFrameAlternate of ar;
ar=SETBIT TransmitFrameRequired of ar;

ar=SETBIT InvertReceiveFrameSync of ar;

ay0=SerialWordLength_15bits;
ar=ar or ay0;

dm(Sport0_Ctrl_Reg)=ar;

ar=UARTCLK;

dm(Sport0_Sclkdiv)=ar;

ar=dm(Sport0_Autobuf_Ctrl);
ar=CLRBIT TransmitAutoBufferEnable of ar;
ar=CLRBIT ReceiveAutoBufferEnable of ar;
dm(Sport0_Autobuf_Ctrl)=ar;

dm(TxState)=ZERO; /* uart state machine counter */
dm(RxState)=ZERO;

ar = TxLowerLimit;
dm(TxData)=ar;

ar=dm(SYSCNTL); /* enable serial port 0 */
ar=setbit 12 of ar;
dm(SYSCNTL)=ar;

#else /* sport 1 uart setup */
ar=0;
ar=SETBIT InternalSerialClock of ar;
ar=SETBIT ReceiveFrameAlternate of ar;
ar=CLRBIT ReceiveFrameRequired of ar;

ar=SETBIT InternalTransmitFrameSync of ar;
ar=SETBIT TransmitFrameAlternate of ar;
ar=SETBIT TransmitFrameRequired of ar;

ar=SETBIT InvertReceiveFrameSync of ar;

ay0=SerialWordLength_15bits;
ar=ar or ay0;

dm(Sport1_Ctrl_Reg)=ar;

ar=UARTCLK;

dm(Sport1_Sclkdiv)=ar;

ar=dm(Sport1_Autobuf_Ctrl);
ar=CLRBIT TransmitAutoBufferEnable of ar;
ar=CLRBIT ReceiveAutoBufferEnable of ar;
dm(Sport1_Autobuf_Ctrl)=ar;

dm(TxState)=ZERO; /* uart state machine counter */
dm(RxState)=ZERO;

ar = TxLowerLimit;
dm(TxData)=ar;

ar=dm(SYSCNTL); /* enable serial port 1 */
ar=setbit 11 of ar;
ar=setbit 10 of ar;
dm(SYSCNTL)=ar;
#endif
rts;

/*-*/
UartTx:
/* use this as the entry point for the tx isr */
ena sec_reg;

m7=dm(TxState); /* remember that m7, i7 are used */
i7=^UartTxCommands;
modify(i7,m7);
call (i7);
rti; /* bit patterns for serial word with parity: (16-bits/serial word */

/* sss0 0011 1222 3334 4455 5666 777p ppss ssss ssss ssss ssss*/
/* 3 2 2 1 1 0 0 0 */

/* 1 4 3 6 5 8 7 0 */ /* bit patterns for serial word without parity: (15-bits/serial word */

/* Xsss 0001 1122 2333 X444 5556 6677 7sss */
/* 3 2 2 1 1 0 0 0 */
/* 1 4 3 6 5 8 7 0 */

UartTxCommands:
jump UartInactive;
jump UartWord1;
jump UartWord2;
jump UartWord3;
jump UartError;

UartInactive:
ar=0xffff; /* send out all stop bits... */
#ifdef SPORT0_UART
tx0=ar; /* stay in state 0 - inactive */
#else
tx1=ar;
#endif
rts;

UartWord1:
/* call xmit; here is where the other stuff gets called */
call PrepareTxWords;
ar = UartTxStateWord2;
dm(TxState)=ar; /* move on to tx next word */
#ifdef SPORT0_UART
tx0=dm(TxUpperWord); /* write the word out... */
#else
tx1=dm(TxUpperWord);
#endif
rts;

UartWord2:
ar = UartTxStateInactive; /* Word3; */
dm(TxState)=ar; /* move on to tx next word */
#ifdef SPORT0_UART
tx0=dm(TxLowerWord); /* write the word out... */
#else
tx1=dm(TxLowerWord);
#endif
rts;

UartWord3:
ar = UartTxStateInactive;
dm(TxState)=ar; /* move on to inactive tx state when done */
ar = 0xffff; /* send out dummy stop bits */

#ifdef SPORT0_UART
tx0=ar;
#else
tx1=ar;
#endif
rts;

UartError:
dm(TxState)=ZERO; /* just clear the state machine... */
ar=0xffff;
#ifdef SPORT0_UART
tx0=ar;
#else
tx1=ar;
#endif

rts;

/* Xsss 0001 1122 2333 X444 5556 6677 7sss */
/* 3 2 2 1 1 0 0 0 */
/* 1 4 3 6 5 8 7 0 */

PrepareTxWords:
ar=dm(TxData);
sr=lshift ar by -8 (hi); /* sr00xx00 data byte to xmit */
mr0=sr0; /* mr0 contains byte to shift out */
sr=lshift ar by 32 (lo); /* clear sr */
ar=8; /* process 8 bits */
af=pass ar; /* bit counter in af */

txMirrorImage:
ay0=mr0; /* get the byte...xx00 */
ar=mr0+ay0; /* mr0=mr0<<1 */
mr0=ar;
if ac jump txItsAOne;
ar=sr1;
jump txGwon;

txItsAOne:
ay0=0xe000;
ar=sr1 or ay0; /* ar1 in msb's this is a 'one' */

txGwon:
sr=lshift sr0 by -3 (lo); /* 32 bit shift right 3 bits */
sr=sr or lshift ar by -3 (hi);
af-1; /* decrement bit counter */
if ne jump txMirrorImage;

/* XXss s000 1112 2233 3444 5556 6677 7sss */
/* 3 2 2 1 1 0 0 0 */
/* 1 4 3 6 5 8 7 0 */
si=sr1; /* shift sr right 2 bits */
sr=lshift sr0 by -2 (lo);
sr=sr or lshift si by -2 (hi);

ay0=7;
ar=sr0 or ay0; /* add in the stop bits */
dm(TxLowerWord)=ar; /* msb not tx as only 15-bits serial word */
si=sr0;
sr=lshift sr1 by 1 (hi);
sr=sr or lshift si by 1 (lo);

dm(TxUpperWord)=sr1; /* upper word to transfer */
rts;
/*-*/

/* generate some test data - increment byte to send out */

TxTestData:
ar=dm(TxData);
ar=ar+1;
ay0=TxUpperLimit;
af=ar-ay0;
if le jump reload;
ar=TxLowerLimit;
reload:
dm(TxData)=ar;
dm(TxState)=ONE;
rts;
/*-*/ UartRx: /* isr for sport 0 rx interrupts */
ena sec_reg;

ar =dm(RxState); /* get the present state */
af =pass ar;
if ne jump rxWord2;

#ifdef SPORT0_UART
dm(RxUpperWord)=rx0; /* store upper word - 1st word received
*/
#else
dm(RxUpperWord)=rx1; /* store upper word - 1st word received
*/
#endif

dm(RxState)=ONE; /* advance rx state machine - word 2 */

ar=dm(RxUpperWord);
dm(i2,m1)=ar;

#ifdef SPORT0_UART
ar=dm(Sport0_Ctrl_Reg); /* set up frame sync to re-sync next byte */
ar=SETBIT ReceiveFrameRequired of ar;
dm(Sport0_Ctrl_Reg)=ar;
#else
ar=dm(Sport1_Ctrl_Reg); /* set up frame sync to re-sync next byte */
ar=SETBIT ReceiveFrameRequired of ar;
dm(Sport1_Ctrl_Reg)=ar;
#endif

rti;

rxWord2:

#ifdef SPORT0_UART
DM(RxLowerWord)=rx0;
#else
DM(RxLowerWord)=rx1;
#endif

ar=dm(RxLowerWord);
dm(i2,m1)=ar; call unpackRxWords;
! call Receive; /* main recieve processor... */

dm(RxState)=ZERO; /* have unpacked rx byte, get ready for next one */

#ifdef SPORT0_UART
ar=dm(Sport0_Ctrl_Reg); /* frame sync not required for 2nd word */
ar=CLRBIT ReceiveFrameRequired of ar;
dm(Sport0_Ctrl_Reg)=ar;
#else
ar=dm(Sport1_Ctrl_Reg); /* frame sync not required for 2nd word */
ar=CLRBIT ReceiveFrameRequired of ar;
dm(Sport1_Ctrl_Reg)=ar;
#endif

rti;

rxInactive:
ar=rx0; /* flush rx buffer */
rti;

unpackRxWords:
si=dm(RxLowerWord);
mr0=dm(RxUpperWord); /* get the rx words */
ar=tstbit 14 of mr0; /* check start bit... */
if ne jump startBitError;

ar=8;
ay0=0;
af=pass ar, ar=ay0; /* bit counter */
mr2=0;
mr1=0; /* clear parity counter, etc. */
se = -3;
sr=lshift si by -3 (lo); /* move center parity bit to lsb */
ar=tstbit 0 of sr0;
if eq jump rxParityZero;
mr2=ONE; /* parity bit is set, else mr2=0 */

rxParityZero:
sr=sr or lshift mr0 (hi);
si=sr0; /* entire 32 bits shifted */
mr0=sr1;

ar=0;
rxMirror:
sr=lshift si by -3 (lo); /* move next bit to lsb of sr */
sr=sr or lshift mr0 (hi);
si=sr0;
mr0=sr1;
ar=ar+ay0; /* ar=ar<<1 */
ay0=ar;
ar=tstbit 0 of sr0; /* bit to shift in to form byte */
if eq jump rxItsAZero;
ar=mr1+1; /* increment parity counter */
ar=pass 1,mr1=ar;

rxItsAZero:
ar=ar or ay0;
ay0=ar; /* new bit is installed */
af-1; /* check bit counter */
if gt jump rxMirror; /* do all 8 bits */

dm(RxData)=ar;
ar=tglbit 5 of ar;
dm(TxData)=ar;
dm(TxState)=ONE;
dm(i2,m1)=ar;
rts;

startBitError:
dm(RxState)=ZERO;
dm(RxData)=ZERO; /* null for start bit error... */
rts;
/*-*/

/* InitStuff - setup various processor registers and initial conditions... */

InitStuff:
m0=0;
m1=1;
l7=0;
l3=0;

ICNTL = 0x000; {Configure interrupt format }
i2 = ^TestBuffer;
l2 = %TestBuffer;

/* set up IDMA address */
ar=^BigBuffer;
i3=^BigBuffer;
dm(BufferPtr)=i3;

ar=setbit IDMAD_BIT of ar;
dm(IdmaControlReg)=ar; /* select data memory space for idma */

ay0=IDMA_BUFFER_SIZE;
ar=ar+ay0;
dm(IdmaTop)=ar;

rts;
/*-*/

Irqe: toggle fl1; /* toggle the LED when pushbutton pressed */
rti;
/*-*/

/* ascii conversion routines... */
/*
ByteToAscii - ar contains byte in lower 8 bits, return two ascii chars in
mem vars ByteCharHi and ByteCharLo.

*/

ByteToAscii:
ay0=0x00ff; /* remove any extraneous upper bits */
ar=ar AND ay0;
si=ar;
sr=lshift ar by 12 (lo); /* sr = 000h l000 */
call toAscii;
dm(ByteCharHi)=ar;

sr = lshift sr0 by 4 (lo); /* convert lower nibble */
call toAscii;
dm(ByteCharLo)=ar;
rts;

toAscii: /* sr1 contains the nibble value */
ay0=ASCII_0;
ar = sr1 + ay0; /* convert to ascii 0..9 */
ay0 = ASCII_9;
ay1 = ASCII_ADJUST;
none = ar-ay0; /* check for range of a..f */
if gt ar = ar + ay1;
rts;

CrLf:
ar=0x000a;
call OutChar;
ar=0x000d;
call OutChar;
rts;

Cr:
ar=0x000d;
call OutChar;
rts;

Spaces:
cntr=8;
do addSpace until ce;
ar=0x20;
call OutChar;
addSpace: nop;
rts; DisplayByte0x: /* ar has the byte to display */
call ByteToAscii;
ar=0x0030;
call OutChar;
ar=0x0078; /* 0x */
call OutChar;
ar=dm(ByteCharHi);
call OutChar;
ar=dm(ByteCharLo);
call OutChar;
rts;

DisplayWord: /* ar contains 16 bit word to display in format: 0xABCD */
ax0=ar;
sr = lshift ar by 8 (lo);
ar = sr1;
call DisplayByte0x; /* get ascii values for this byte */
ar=ax0;
call ByteToAscii;
ar=dm(ByteCharHi);
call OutChar;
ar=dm(ByteCharLo);
call OutChar;
rts;

CheckIDMA:
ar=dm(IdmaControlReg);
ay0=dm(IdmaTop);
ay1=dm(BufferPtr);
none=ar-ay0;
if ge jump resetIdmaPtr;
ar=clrbit IDMAD_BIT of ar;
none=ar-ay1;
if eq rts;

/* new data so display it... */

ar=dm(i3,m1);

dm(BufferPtr)=i3;
call DisplayWord;
call CrLf;
rts;

resetIdmaPtr:
ar=^BigBuffer;
i3=^BigBuffer;
ar=setbit IDMAD_BIT of ar;
dm(IdmaControlReg)=ar; /* select data memory space for idma */
dm(BufferPtr)=ar;
rts; /*-*/

.ENDMOD;




On Sat, 5 Jun 2004, tejabhi p wrote:

>
> I am referring the App.Note EE-60 and the corresponding code
>
> (pls find attached) to generate UART using SPORT.
>
> I have two queries
>
> 1) In the functions to output character from the processor e.g. Outchar
function,
>
> we move the data into 'Txdata'. But how does the transmit interrupt get
generated
>
> when we do this ?

The processor is double buffered. When the holding register is empty it
generates an interrupt. When the transmit register is empty the data from
holding register is sent to the transmit register.

The first time you start - both registers are empty. So you write data to
the holding register (Txdata) and it is immediatly transfered to the
transmit register, generating an interrupt. You then write the second
word into to the holding register (if there is one - turn off interrupts
if there isn't)

> 2) For what is the IDMA used here? Is it necessary?

If you want to use the dma engine to move data into the sport you can move
a lot of data without using the central processor. This is a very
powerful technique. Not for amatures :-) It is not necessary at all!
Just mighty useful.

Patience, persistence, truth,
Dr. mike