[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