Page 1 of 1

NB RunTime lib "Writeall()" not blocking release/NANO54415

Posted: Wed Aug 05, 2015 8:09 am
by mstrzelczyk
System: Nano54415
I am using writeall() to block until a write to file descriptor is finished (not a great technique, but I need to toggle a line in my system when the UART transmission is complete). This works ok in debug build, but not a release build. It seems as though the function call returns as soon as the buffer write is completed. Have I goofed (i.e. is there a compiler switch disallowing blocking functions in release builds or something)?

I'm using NNDK 2.6.7 and have not rebuilt my system libraries ever. I would upgrade, but no release notes up to release 2.7.3 seem to indicate these issues discovered or fixed. I hope to not monkey with my development environment unless I must.

The file descriptor to UART1 is opened via SimpleOpenSerial(1, 115200)

Re: NB RunTime lib "Writeall()" not blocking release/NANO544

Posted: Wed Aug 05, 2015 8:44 am
by dciliske
You'll need to poll SendSerialComplete after the writeall(). Writeall will return as soon as the data is queued to be sent out the serial port. SendSerialComplete will not return true until both the queue is empty and the transmitter has finished sending the last byte.

-Dan

Re: NB RunTime lib "Writeall()" not blocking release/NANO544

Posted: Wed Aug 05, 2015 9:58 am
by mstrzelczyk
Thank you, Dan.

The absence of this function in the Runtime Libraries documentation led me to believe the "blocking until complete" in writeall() meant pending on the physical UART transmitter. My apologies, I see it now in serial.h.

Buuut...I'm pending on its return value turning true...and I hang. I realize I need to be more thorough and have a timeout for robustness sake (not just a dumb while() loop)....is it possible this function has the opposite return value as advertised (true when BUSY rather than done)? THAT seems to work properly....

Re: NB RunTime lib "Writeall()" not blocking release/NANO544

Posted: Wed Aug 05, 2015 10:13 am
by pbreed
It returns true when the send is complete...

Re: NB RunTime lib "Writeall()" not blocking release/NANO544

Posted: Thu Aug 06, 2015 9:02 am
by mstrzelczyk
Dan and "pbreed"

I apologize I had to continue with board bring-up, so I circumvented by using a hiResTimer. But, I wanted to circle back and let you know I still couldn't achieve the correct behavior for the SerialSendComplete() function. I ran the following snippet:

Code: Select all

void tiaWrite(char* txbuf, char mask)
{
	int numbytes = strlen(txbuf);

        iprintf("SerialSendComplete before: %d\n", SerialSendComplete(fdTIA));

	tiaMUXassert(mask);//This will be de-asserted later

	writeall(fdTIA, txbuf, numbytes);//Note, this variant of write blocks only until buffer write complete

	pTimer->pollingDelay( 1.0E-6 * (numbytes * 80.0 + 100.0) );

	for(int i=0;i<10;i++){
		iprintf("SerialSendComplete: %d\n", SerialSendComplete(fdTIA));
		pTimer->pollingDelay( 1.0E-6 * (80.0 + 100.0) );
	}
}
With the following results:
SerialSendComplete before: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0
SerialSendComplete: 0

To dig a little deeper, I imported the serial.cpp file into my workspace and altered the source code of SerialSendComplete() a little bit.
(BTW, I had no idea this would compile, link and debug properly, but it seems fine I can single-step).

Code: Select all

BOOL SerialSendComplete(int fd)
{
    int portnum = FdSerialMap(fd);
    if ((portnum < 0) || (portnum > 9))
        return FALSE;

    if ((UartData[portnum].m_UartState & UART_INIT) == 0)
        return FALSE;
#if 0
    if ((UartData[portnum].m_UartState & UART_TX_EMPTY)
            && UartData[portnum].m_FifoWrite.Empty()
            && (Uarts[portnum]->usr & 0x08))
        return TRUE;
    else
#else
        if ( UartData[portnum].m_UartState & UART_TX_EMPTY)
        	if ( UartData[portnum].m_FifoWrite.Empty() )
        		if ( Uarts[portnum]->usr & 0x08 )
        			return TRUE;
#endif
        return FALSE;
}
Anyway, the test of the TXEMP bit of the USR (UART Status) fails:

Code: Select all

if ( Uarts[portnum]->usr & 0x08 )
In the MCF54415 Reference Manual it states that this bit will be zero if the UART transmitter is disabled. Looking at the sim1->uarts->1 peripheral registers, it does seems as though the transmitter is disabled. I'm sorry I couldn't check any deeper, but perhaps the SimpleOpenSerial() mode of opening the serial port and drivers has a DMA interrupt that shuts off the transmitter when the buffer is drained under the hood?

Re: NB RunTime lib "Writeall()" not blocking release/NANO544

Posted: Thu Aug 06, 2015 12:37 pm
by dciliske
You are 100% correct. Currently investigating this...

Re: NB RunTime lib "Writeall()" not blocking release/NANO544

Posted: Thu Aug 13, 2015 1:20 pm
by krastatter
I just ran into this issue with a MOD5234, NNDK 2.6.2 .

From c:\nburn\MOD5234\system\serial.cpp SerialSendComplete():

Code: Select all

    if ((UartData[portnum].m_UartState & UART_INIT) == 0)
        return FALSE;       // Serial port is not open
    else {
        volatile uartstruct *ThisUart = &sim.uarts[portnum];
        if ((UartData[portnum].m_UartState & UART_TX_EMPTY)
                && UartData[portnum].m_FifoWrite.Empty()
                && (ThisUart->usr & 0x08))  <-- this test always fails <---
            return TRUE;    // Tx registers are empty after sending out
        else
            return FALSE;   // Tx registers are not empty, not yet sent out