[En-Nut-Discussion] a strange "trace" code in usartavr.c

Michael Gong mwgong at cs.utoronto.ca
Fri Mar 2 18:59:37 CET 2007


Hi,

I have a question regarding to the appended code, which is from 
"arch/avr/usartavr.c" included in ethernut-3.9.9.

Just focus on following segments:

    #ifdef NUTTRACER
    TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);
    #endif


There are totally 4 such segments, which I listed below as "trace 1", 
"trace 2", "trace 3" and "trace 4". It's obvious that "trace1/2/3" is to 
add tracing informaiton before a "return" statements. However, the 
"trace 4" appears inside a "do" loops, which will executes multiple 
times.

My question is:
      if I move "trace 4" to the end of the function, will it change the 
semantics of this function ?


Since I am not familiar with how Nut/OS works, I would like to ask for 
experts' suggestions.


Thanks.

Mike


Appended code:

--------------------------------------------------------------------------------------------
...
#ifdef USE_USART
SIGNAL( SIG_UART_RECV ){
    register RINGBUF *rbf = &dcb_usart.dcb_rx_rbf;

#else

static void AvrUsartRxComplete(void *arg) {
    register RINGBUF *rbf = (RINGBUF *) arg;

#endif

    register size_t cnt;
    register u_char ch;


#ifdef NUTTRACER
    TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_ENTER,TRACE_INT_UART_RXCOMPL);
#endif

#ifdef UART_READMULTIBYTE
    register u_char postEvent = 0;
    do {
#endif

        /*
         * We read the received character as early as possible to avoid 
overflows
         * caused by interrupt latency. However, reading the error flags 
must come
         * first, because reading the ATmega128 data register clears the 
status.
         */
        rx_errors |= inb(UCSRnA);
        ch = inb(UDRn);

#ifndef UART_NO_SW_FLOWCONTROL
        /*
         * Handle software handshake. We have to do this before checking 
the
         * buffer, because flow control must work in write-only mode, 
where
         * there is no receive buffer.
         */
        if (flow_control) {
            /* XOFF character disables transmit interrupts. */
            if (ch == ASCII_XOFF) {
                cbi(UCSRnB, UDRIE);
                flow_control |= XOFF_RCVD;
#ifdef NUTTRACER
                TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL); 
/* trace 1 */
#endif
                return;
            }
            /* XON enables transmit interrupts. */
            else if (ch == ASCII_XON) {
                sbi(UCSRnB, UDRIE);
                flow_control &= ~XOFF_RCVD;
#ifdef NUTTRACER
                TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL); 
/* trace 2 */
#endif
                return;
            }
        }
#endif

        /*
         * Check buffer overflow.
         */
        cnt = rbf->rbf_cnt;
        if (cnt >= rbf->rbf_siz) {
            rx_errors |= _BV(DOR);
#ifdef NUTTRACER
            TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL); 
/* trace 3 */
#endif
            return;
        }

        /* Wake up waiting threads if this is the first byte in the 
buffer. */
        if (cnt++ == 0){
#ifdef UART_READMULTIBYTE
            // we do this later, to get the other bytes in time..
            postEvent = 1;
#else
            NutEventPostFromIrq(&rbf->rbf_que);
#endif
        }

#ifndef UART_NO_SW_FLOWCONTROL

        /*
         * Check the high watermark for software handshake. If the 
number of
         * buffered bytes is above this mark, then send XOFF.
         */
        else if (flow_control) {
            if(cnt >= rbf->rbf_hwm) {
                if((flow_control & XOFF_SENT) == 0) {
                    if (inb(UCSRnA) & _BV(UDRE)) {
                        outb(UDRn, ASCII_XOFF);
                        flow_control |= XOFF_SENT;
                        flow_control &= ~XOFF_PENDING;
                    } else {
                        flow_control |= XOFF_PENDING;
                    }
                }
            }
        }
#endif


#ifdef UART_RTS_BIT
        /*
         * Check the high watermark for hardware handshake. If the 
number of
         * buffered bytes is above this mark, then disable RTS.
         */
        else if (rts_control && cnt >= rbf->rbf_hwm) {
            sbi(UART_RTS_PORT, UART_RTS_BIT);
        }
#endif

        /*
         * Store the character and increment and the ring buffer 
pointer.
         */
        *rbf->rbf_head++ = ch;
        if (rbf->rbf_head == rbf->rbf_last) {
            rbf->rbf_head = rbf->rbf_start;
        }

        /* Update the ring buffer counter. */
        rbf->rbf_cnt = cnt;
#ifdef NUTTRACER
        TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL); 
/* trace 4 */
#endif

#ifdef UART_READMULTIBYTE
    } while ( inb(UCSRnA) & _BV(RXC) ); // byte in buffer?

    // Eventually post event to wake thread
    if (postEvent)
        NutEventPostFromIrq(&rbf->rbf_que);
#endif

}

--------------------------------------------------------------------------------------------




More information about the En-Nut-Discussion mailing list