Even/Odd Parity Problems w/ MV2700 & 8250 UART

Even/Odd Parity Problems w/ MV2700 & 8250 UART

Post by Jim Pisan » Thu, 29 Jul 1999 04:00:00



I'm trying to send binary data out the /tyCo/1 serial port (at 57.6KB)
which is controlled by the 8250 UART on an 266 MHz MV2700 board. I need
to set the parity to even send a couple of bytes and then set the parity
odd for the remaining bytes which can range from a few to ~1000 bytes.

The problem that I've run into is that the 1st 2 bytes are correctly
sent in even parity and then the remaining odd parity bytes get sent,
but a few bytes have even parity.  This problem goes away if I put a
taskDelay(1) call after a write() call of each byte.

One thing that I've tried which I thought would solve the problem but
didn't, was to make sure that all of the bytes are transmitted out of
the UART before I change parity from even to odd using a busy/wait loop.
This function, waitForTransmitterEmpty() is included below.

Both functions are adapted from i8250Sio.c in target\src\drv\sio &
i8250Sio.h in target\h\drv\sio

I realize that I'm doing something wrong, but I can't see it. Any
assistance would be greatly appreciated as I'm stuck on this problem.

Thanks,

-Jim

Here's the code that sets the parity:
void SerialTest::setParity( SerialTest::eParity _parity )
{
    FAST int oldlevel;
    char lcr = 0;

    switch( _parity )
    {
    case PARITY_NONE:
        lcr |= I8250_LCR_PDIS;
        break;

    case PARITY_ODD:
        lcr |= (I8250_LCR_PEN);
        break;

    case PARITY_EVEN:
        lcr |= (I8250_LCR_PEN | I8250_LCR_EPS);
        break;
    }

    // always 8-bits, 1 stop bit
    lcr |= (I8250_LCR_CS8 | I8250_LCR_1_STB);

    oldlevel = intLock ();

    SIO_CHAN *pChan = sysSerialChanGet(1);
    I8250_CHAN *pI8250_chan = (I8250_CHAN *)pChan;

    (*pI8250_chan->outByte) (pI8250_chan->lcr, lcr);

    intUnlock (oldlevel);

Quote:}

Here's the waitForTransmitterEmpty() code.

void SerialTest::waitForTransmitterEmpty()
{
    // wait until these bytes are sent before proceeding
    SIO_CHAN *pChan = sysSerialChanGet(1);
    I8250_CHAN *pI8250_chan = (I8250_CHAN *)pChan;

    bool bBusy = true;

    do
    {
        char pollStatus = ( *(pI8250_chan)->inByte) (pI8250_chan->lst);
        if( pollStatus & (I8250_LSR_TEMT | I8250_LSR_THRE) )
        {
            bBusy = false;
        }
    }while( bBusy );

Quote:}

--
Jim Pisano
Senior Scientific Programmer
National Radio Astronomy Observatory
Central Development Lab
2015 Ivy Road, C*tesville, VA 22903
804-296-0351
 
 
 

Even/Odd Parity Problems w/ MV2700 & 8250 UART

Post by Charlie Grame » Fri, 30 Jul 1999 04:00:00


Jim,

This is a wild guess, but I notice that you are reading from and writing
to device registers directly instead of using sysInByte() and
sysOutByte().  There may be an I/O ordering problem without the
synchronization that these two routines provide.  Perhaps you could try
incorporating these routines into your driver and see if it makes any
difference.

I also think you should be able to use the FIONWRITE ioctl() call (see
the documentation for tyLib) to determine when all bytes have been
output rather than writing a device-specific routine.

Just out of curiousity, why would you need to do anything like this?

HTH

Charlie Grames
The Boeing Company


> I'm trying to send binary data out the /tyCo/1 serial port (at 57.6KB)
> which is controlled by the 8250 UART on an 266 MHz MV2700 board. I need
> to set the parity to even send a couple of bytes and then set the parity
> odd for the remaining bytes which can range from a few to ~1000 bytes.

> The problem that I've run into is that the 1st 2 bytes are correctly
> sent in even parity and then the remaining odd parity bytes get sent,
> but a few bytes have even parity.  This problem goes away if I put a
> taskDelay(1) call after a write() call of each byte.

> One thing that I've tried which I thought would solve the problem but
> didn't, was to make sure that all of the bytes are transmitted out of
> the UART before I change parity from even to odd using a busy/wait loop.
> This function, waitForTransmitterEmpty() is included below.

> Both functions are adapted from i8250Sio.c in target\src\drv\sio &
> i8250Sio.h in target\h\drv\sio

> I realize that I'm doing something wrong, but I can't see it. Any
> assistance would be greatly appreciated as I'm stuck on this problem.

> Thanks,

> -Jim

> Here's the code that sets the parity:
> void SerialTest::setParity( SerialTest::eParity _parity )
> {
>     FAST int oldlevel;
>     char lcr = 0;

>     switch( _parity )
>     {
>     case PARITY_NONE:
>         lcr |= I8250_LCR_PDIS;
>         break;

>     case PARITY_ODD:
>         lcr |= (I8250_LCR_PEN);
>         break;

>     case PARITY_EVEN:
>         lcr |= (I8250_LCR_PEN | I8250_LCR_EPS);
>         break;
>     }

>     // always 8-bits, 1 stop bit
>     lcr |= (I8250_LCR_CS8 | I8250_LCR_1_STB);

>     oldlevel = intLock ();

>     SIO_CHAN *pChan = sysSerialChanGet(1);
>     I8250_CHAN *pI8250_chan = (I8250_CHAN *)pChan;

>     (*pI8250_chan->outByte) (pI8250_chan->lcr, lcr);

>     intUnlock (oldlevel);
> }

> Here's the waitForTransmitterEmpty() code.

> void SerialTest::waitForTransmitterEmpty()
> {
>     // wait until these bytes are sent before proceeding
>     SIO_CHAN *pChan = sysSerialChanGet(1);
>     I8250_CHAN *pI8250_chan = (I8250_CHAN *)pChan;

>     bool bBusy = true;

>     do
>     {
>         char pollStatus = ( *(pI8250_chan)->inByte) (pI8250_chan->lst);
>         if( pollStatus & (I8250_LSR_TEMT | I8250_LSR_THRE) )
>         {
>             bBusy = false;
>         }
>     }while( bBusy );
> }

> --
> Jim Pisano
> Senior Scientific Programmer
> National Radio Astronomy Observatory
> Central Development Lab
> 2015 Ivy Road, C*tesville, VA 22903
> 804-296-0351