This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DM648 UART hangs on error condition (dvsdk_1_11_00_00_DM648)

Hi

I have my UART set to 57600 baud and unfortunately it has to deal with inputs that can sometimes change to 9600 baud. What I mean by "deal with" is that it only has to continue transmitting and receiving at 57600 baud.

I am using the same GIO APIs as the example below with timeouts set to SYS_FOREVER.

C:\dvsdk_1_11_00_00_DM648\pspdrivers_1_10_00\packages\ti\sdo\pspdrivers\system\dm648\bios\evmDM648\uart\src

PSP_UART_ASYNC_MODE_SUPPORT is NOT defined.

PSP_UART_BUFFERING_ENABLED is defined.

uart0DevParams.opMode          = PSP_OPMODE_INTERRUPT;

The GIO_submit(...IOM_WRITE...) runs in a lower priority task than GIO_submit(...IOM_READ...). GIO_submit sends 16 bytes every 33 msec.

To exercise the error condition, I use Teraterm to send bytes to the DM648 at 9600 baud. Before I start sending bytes at 9600 baud, I check to see if the dm648 UART is transmitting at 57600 baud (which is always is).

As soon as I start the 9600 baud send on Teraterm, the dm648 transmit stops.

I've traced part of the problem down to the function ddc_uartHandleRxError() thats called by ddc_uartIsr() when the line status error interrupt occurs. I've put in counters and breakpoints to check to see of the OE, BI, FE, BE bits are set. They are not. Why would the line status interrupt bit be set when BI, FE, BE bits are not?

This happens most of the time, however, on some experiment trails,  the BI, FE, and BE bits are set. Dm648 transmit also stops in these cases.

I'm still trying to figure out why the tx stops. You'd think the rx and tx would be independent.[:S]

Here is what I observed with both tx and rx timeouts set to SYS_FOREVER:

1) mdSubmitChan() IOM_READ returns -1 (IOM_EBADIO) which I traced was due to PSP_E_UART_IO_ERROR. I'd expect this since we have BI, FE, and PE errors.

2) the tx stops because mdSubmitChan() pends on a semaphore in the code because the tx status goes to IOM_PENDING:

            IOMstatus = PAL_osSemTake(chan->hSyncSem, dataParam->timeout);

    The semaphore never gets posted so tx stops.[:@]

3) I put a counter in mdLayerCallback() where it's supposed to post the semaphore. The counter doesn't increment. Arg.

If I change the tx timeout to 5 msec:

1) mdSubmitChan() IOM_READ returns -1 (same as #1 above)

2) mdSubmitChan() IOM_WRITE returns -2 (IOM_ETIMEDOUT). I'd expect this since the timeout value is not SYS_FOREVER

3) eventually mdSubmitChan() IOM_WRITE returns -5 (IOM_EALLOC) which I traced was due to PSP_E_RESOURCES being set by ddc_uartSubmitIoReq() in the code

        if(TRUE == PAL_osListIsEmpty (&ioHandle->queueFreeList))

So basically the same thing is happening: the tx semaphore never gets posted so tx pends on the semaphore until it times out, and eventually runs out of resources because IOM_WRITES are still occurring.

I can't figure out why the rx errors are causing the tx IOM_WRITE to become IOM_PENDING, and then never get its semaphore posted in mdLayerCallback().[:S]

I'm almost at the point of writing our own driver, but since I've spent so much time debugging the problem, it would be sure nice to fix the TI driver.

Thanks for your help. [:)]

 

 

  • Update....

    Assuming the problem is that the tx semaphore is not being posted:

    The only place the tx semaphore gets posted is in mdLayerCallback(). This is called by

    1) ddc_CompleteCurrentIO() or

    2) ddc_uartCancelAllIO().

    It can't be ddc_CompleteCurrnetIO() because

    a) its called by ddc_uartIntrHandler() when  (0 == ioHandle->bytesRemaining). The code comments indicate that this is only for Rx.

    b) its called by ddc_uartSubmitIoReq() when PSP_OPMODE_POLLED. Since we are OPMODE_INTERRUPT, we don't hit this code.

    As per ddc_uartCancelAllIO(), I put counters in  ddc_uartCancelAllIO() and the code never hits it. It does hit ddc_cancelCurrentIO(), but that doesn't release the tx semaphore.

    It could be that the missing semaphore post is secondary to the problem of why the tx status changed to IOM_PENDING.[:(]

     

  • Yet another update.

    In mdSubmitChan, I added code to so I could break when the tx state becomes IOM_PENDING and just before it takes the semaphore (see below). I also read the LSR register. When I break it is returning with LSR = 0x60. Since b6 is set, the LSR is telling us the tx FIFO is empty. Here is where I think the problem is. Since the only way to get the semaphore released is through a tx interrupt (that gets us to mdLayerCallback which posts the semaphore), the system is now deadlocked.  Since the tx FIFO is empty, no tx interrupts will occur to post a semaphore. Since we are in IOM_PENDING state, no tx packets will be written to the tx FIFO: they keep getting queued until we run out of resources.

    Any idea how to fix this? [:|]

    I'm going to try replacing the cancelCurrentIo with cancelAllIo to see if that fixes the problem. (I'm doing this after the mdSubmit semaphore pend times out and it calls PSP_uartIoctl() to cancel the IO)

    I still don't understand how we got to the state IOM_PENDING when the tx FIFO was empty.[*-)]

        if (IOMstatus == IOM_PENDING)
        {
           
            /* Sync Mode Operation: So wait on a semaphore for the timeout or
            completion or error */
            Uint32  cookie;               
            gLCR = ((DDC_uartIoHandle)(chan->ioHandle))->devHandle->regs->LCR;
            gLSR = ((DDC_uartIoHandle)(chan->ioHandle))->devHandle->regs->LSR;
            if (packet->cmd == IOM_READ)  // collect stats
                gUartStats.mdSubmitChan_readIomPendingCnt++;
            else
                gUartStats.mdSubmitChan_writeIomPendingCnt++;      BREAK POINT IS HERE

            {
                gSemTimeoutValue =  dataParam->timeout;
                IOMstatus = PAL_osSemTake(chan->hSyncSem, dataParam->timeout);

  • Dang, calling cancelAllIo() didn't work because activeIOP is NULL, hence it won't clear buffers or call mdLayerCallback().

    Why it is in IOM_pending when activeIOP is NULL if NULL indicates no IOPs (output request) are active?[:S]

    HELP!

    cancellAllIO()

    {

        /* validate params */
        if(NULL != ioHandle)
        {
            tmpPacket = ioHandle->activeIOP;
        }

        if (NULL != tmpPacket)
        {
            THIS CODE DOESN"T GET EXECUTED