[En-Nut-Discussion] Fixes/additions to usartavr.c

Damian Slee damian at commtech.com.au
Fri Apr 16 05:45:55 CEST 2004


Hi,
Submitting these again, more detailed inline this time.



------------------------------------------------------------------------
--------------------------------------------------------------------	
After receving XOFF, Tx  keeps transmitting.  Add this to fix it.

static void AvrUsartTxEmpty(void *arg)
{
    register RINGBUF *rbf = (RINGBUF *) arg;
    register u_char *cp = rbf->rbf_tail;

    /*
     * Process pending software flow controls first.
     */
    if (flow_control & (XON_PENDING | XOFF_PENDING)) {
        if (flow_control & XON_PENDING) {
            outb(UDRn, ASCII_XOFF);
            flow_control |= XOFF_SENT;
        } else {
            outb(UDRn, ASCII_XON);
            flow_control &= ~XOFF_SENT;
        }
        flow_control &= ~(XON_PENDING | XOFF_PENDING);
        return;
    }
// ADD >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    if (flow_control & XOFF_RCVD) {
        /* 
         * If XOFF has been received, we disable the transmit interrupts
         * and return without sending anything.
         */
        cbi(UCSRnB, UDRIE);
        return;
	}
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
...
}

------------------------------------------------------------------------
--------------------------------------------------------------------
When setting XONXOFF flow control, force an XON to be sent.  If you
change between flow control methods, currently a XON is never sent when
software flow control is selected.  So remote never sends.

static int AvrUsartSetFlowControl(u_long flags)
{
    /*
     * Set software handshake mode.
     */
    if (flags & USART_MF_XONXOFF) {
        if(flow_control == 0) {
// CHANGE>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
			NutEnterCritical();
			flow_control = 1 | XOFF_SENT;  /* force XON to
be sent on next read */
			NutExitCritical();
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        }
    } else {
        NutEnterCritical();
        flow_control = 0;
        NutExitCritical();
    }

------------------------------------------------------------------------
--------------------------------------------------------------------
When setting half duplex mode, tx complete interrupt is never enabled.
Only enabled if required
on initialisation of uart.  So if you change from one flow control
method to another, it doesn't currently work.

static int AvrUsartSetFlowControl(u_long flags)
{
...

   if (flags & USART_MF_HALFDUPLEX) {
        /* Register transmit complete interrupt. */
        if (NutRegisterIrqHandler(&sig_UART_TRANS, AvrUsartTxComplete,
&dcb_usart.dcb_rx_rbf)) {
            return -1;
        }
        /* Initially enable the receiver. */
// see change at bottom of email for this one >>>>>>>>>>>>>>>>>>>>
        UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
// <<<<<<<<<<<<<<<<<<<<<<<<<<,
        sbi(UART_HDX_DDR, UART_HDX_BIT);
        hdx_control = 1;
// ADD >>>>>>>>>>>>>>>>>>>>>>
        /* Enable transmit complete interrupt. */
        sbi(UCSRnB, TXCIE);
// <<<<<<<<<<<<<<<<<<<<<<<<<<
    } else if (hdx_control) {
        hdx_control = 0;
// ADD >>>>>>>>>>>>>>>>>>>>>>
		/* disable transmit complete interrupt */
		cbi(UCSRnB, TXCIE);
// <<<<<<<<<<<<<<<<<<<<<<<<<<
        /* Deregister transmit complete interrupt. */
        NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
        cbi(UART_HDX_DDR, UART_HDX_BIT);
    }
...
}

------------------------------------------------------------------------
--------------------------------------------------------------------
Option to flip the state of the half duplex bit.

// ADD at top of usartavr.c >>>>>>>>>>>>>>>>>>>>>>>>
#ifdef UART_HDX_BIT
	/* define in cfg/modem.h */
	#ifdef UART_HDX_FLIP_BIT	/* same as RTS toggle by Windows
NT driver */
		#define UART_HDX_TX		cbi
		#define UART_HDX_RX		sbi
	#else						/* previous
usage by Ethernut */
		#define UART_HDX_TX		sbi
		#define UART_HDX_RX		cbi
	#endif
#endif
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
...
// replace the set and clears of the bit with UART_HDX_TX & UART_HDX_RX
respectively

static void AvrUsartTxStart(void)
{
...
	UART_HDX_TX(UART_RTS_PORT, UART_RTS_BIT);
...
}

static void AvrUsartTxComplete(void *arg)
{
...
        UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
...
}

static int AvrUsartSetFlowControl(u_long flags)
{
...
    if (flags & USART_MF_HALFDUPLEX) {
...
        /* Initially enable the receiver. */
        UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
...
}




More information about the En-Nut-Discussion mailing list