This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

patch - at91 serial drivers assumed realtime response for DSRroutines


The at91 serial routines are broken in that they assume a very low
latency for the DSR handler.

This became a problem when I added a 16x5x serial port to my system,
which also spends a fair amount of time in the DSR handler.

My solution was to modify the work that was done to add hardware
buffering support to the at91 serial routines, but remove the rejected
modifications done to the interrupt routines. 

http://sources.redhat.com/ml/ecos-discuss/2002-01/msg00205.html

Although the ISR interrupt latency is still an issue, this should be a
step forward:

- it would bring the hardware buffering code under the scruteny of the
eCos community
- since the code is now in "at91 speak", a bit of the tedium has now
been removed if someone decides to do the "fast interrupt" support.

Testing done so far:

- I've tested that it works for UART0. I've got a maimed board where the
UART1 is physically disconnected, so I can't easily test this right now.
- The interoperability between AT91 uarts and 16x5x seem to be just fine
now.

Ãyvind

Index: ecos/packages/devs/serial/arm/at91/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/serial/arm/at91/current/ChangeLog,v
retrieving revision 1.7
diff -a -w -u -r1.7 ChangeLog
--- ecos/packages/devs/serial/arm/at91/current/ChangeLog	24 Feb 2003 14:12:18 -0000	1.7
+++ ecos/packages/devs/serial/arm/at91/current/ChangeLog	21 Oct 2003 12:39:15 -0000
@@ -1,3 +1,10 @@
+2003-10-21  Øyvind Harboe <oyvind.harboe@zylin.com>
+	* added support for hardware send/receive buffers to avoid
+	problems with real-time response in DSR routine. This helps
+	compatibility with e.g. 16x5x serial drivers that are also
+	spending time in DSR routines. This increases the amount of time
+	spent in the ISR by a relatively modest amount.
+
 2003-02-24  Jonathan Larmour  <jifl@eCosCentric.com>
 
 	* cdl/ser_arm_at91.cdl: Remove irrelevant doc link.
Index: ecos/packages/devs/serial/arm/at91/current/cdl/ser_arm_at91.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/serial/arm/at91/current/cdl/ser_arm_at91.cdl,v
retrieving revision 1.5
diff -a -w -u -r1.5 ser_arm_at91.cdl
--- ecos/packages/devs/serial/arm/at91/current/cdl/ser_arm_at91.cdl	24 Feb 2003 14:12:18 -0000	1.5
+++ ecos/packages/devs/serial/arm/at91/current/cdl/ser_arm_at91.cdl	21 Oct 2003 12:39:15 -0000
@@ -71,6 +71,9 @@
         puts $::cdl_system_header "/*****  serial driver proc output end  *****/"
     }
 
+    # The driver tries to be effective with FIFO transfers
+    implements    CYGINT_IO_SERIAL_BLOCK_TRANSFER
+
 cdl_component CYGPKG_IO_SERIAL_ARM_AT91_SERIAL0 {
     display       "Atmel AT91 serial port 0 driver"
     flavor        bool
Index: ecos/packages/devs/serial/arm/at91/current/src/at91_serial.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/serial/arm/at91/current/src/at91_serial.c,v
retrieving revision 1.5
diff -a -w -u -r1.5 at91_serial.c
--- ecos/packages/devs/serial/arm/at91/current/src/at91_serial.c	23 May 2002 23:01:09 -0000	1.5
+++ ecos/packages/devs/serial/arm/at91/current/src/at91_serial.c	21 Oct 2003 12:39:15 -0000
@@ -64,13 +64,37 @@
 
 #ifdef CYGPKG_IO_SERIAL_ARM_AT91
 
+#define AT91_UART_BUF_SIZE 1024
+#define RECV_UART_CHAR_TIMEOUT 50
+
+#define FLIP_BUFFER_DEF(x)			\
+    struct flip_buffer {			\
+	cyg_uint8      buf[2][x];		\
+	int            buf_which;		\
+	cyg_uint8      *buf_p;			\
+	int            buf_count;		\
+    }
+
+
 #include "at91_serial.h"
 
+FLIP_BUFFER_DEF(AT91_UART_BUF_SIZE);
+
 typedef struct at91_serial_info {
     CYG_ADDRWORD   base;
     CYG_WORD       int_num;
     cyg_interrupt  serial_interrupt;
     cyg_handle_t   serial_interrupt_handle;
+    cyg_interrupt  line_interrupt;
+    cyg_handle_t   line_interrupt_handle;
+    struct flip_buffer recv;
+    cyg_uint8      send_buf[2][AT91_UART_BUF_SIZE];
+    int            send_buf_which;
+    int            send_buf_count[2];
+    int            tx_enabled;
+    cyg_uint32     stat;
+    cyg_serial_info_t config;
+    struct flip_buffer *flip;
 } at91_serial_info;
 
 static bool at91_serial_init(struct cyg_devtab_entry *tab);
@@ -87,6 +111,11 @@
 static cyg_uint32 at91_serial_ISR(cyg_vector_t vector, cyg_addrword_t data);
 static void       at91_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
 
+#if 0
+static cyg_uint32 at91_line_ISR(cyg_vector_t vector, cyg_addrword_t data);
+static void       at91_line_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
+#endif
+
 static SERIAL_FUNS(at91_serial_funs, 
                    at91_serial_putc, 
                    at91_serial_getc,
@@ -175,6 +204,9 @@
     );
 #endif //  CYGPKG_IO_SERIAL_ARM_AT91_SERIAL1
 
+
+
+
 // Internal function to actually configure the hardware to desired baud rate, etc.
 static bool
 at91_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
@@ -185,12 +217,30 @@
     cyg_uint32 word_length = select_word_length[new_config->word_length-CYGNUM_SERIAL_WORD_LENGTH_5];
     cyg_uint32 stop_bits = select_stop_bits[new_config->stop];
 
+    at91_chan->flip=&at91_chan->recv;
+
     if ((word_length == 0xFF) ||
         (parity == 0xFF) ||
         (stop_bits == 0xFF)) {
         return false;  // Unsupported configuration
     }
 
+    if (init) {
+	memset (&at91_chan->config, 0, sizeof (at91_chan->config));
+#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW
+//	HAL_WRITE_UINT32 (AT91_PIO + AT91_PIO_SODR, 0x000000C3);
+#endif
+	at91_chan->recv.buf_which = 0;
+	at91_chan->send_buf_which = 0;
+	at91_chan->recv.buf_count = 0;
+	at91_chan->tx_enabled = 0;
+	at91_chan->send_buf_count[0] = at91_chan->send_buf_count[1] = 0;
+    }
+
+    if (new_config->word_length != at91_chan->config.word_length ||
+	    new_config->parity != at91_chan->config.parity ||
+	    new_config->stop != at91_chan->config.stop ||
+	    new_config->baud != at91_chan->config.baud) {
     // Reset device
     HAL_WRITE_UINT32(base+AT91_US_CR, AT91_US_CR_RxRESET | AT91_US_CR_TxRESET);
 
@@ -200,14 +250,28 @@
     // Baud rate
     HAL_WRITE_UINT32(base+AT91_US_BRG, AT91_US_BAUD(select_baud[new_config->baud]));
 
+	// Enable RX and TX
+	HAL_WRITE_UINT32(base+AT91_US_CR, AT91_US_CR_RxENAB | AT91_US_CR_TxENAB);
+	at91_chan->config = *new_config;
+    }
+
+    if (init) {
     // Disable all interrupts
     HAL_WRITE_UINT32(base+AT91_US_IDR, 0xFFFFFFFF);
 
-    // Enable Rx interrupts
-    HAL_WRITE_UINT32(base+AT91_US_IER, AT91_US_IER_RxRDY);
+	// Initialize hardware buffers
+	HAL_WRITE_UINT32 (base + AT91_US_RPR, (cyg_uint32) at91_chan->recv.buf[at91_chan->recv.buf_which]);
+	HAL_WRITE_UINT32 (base + AT91_US_RCR, (cyg_uint32) AT91_UART_BUF_SIZE);
+	HAL_WRITE_UINT32 (base + AT91_US_TCR, (cyg_uint32) 0);
+	HAL_WRITE_UINT32 (base + AT91_US_TPR, (cyg_uint32) at91_chan->send_buf[at91_chan->send_buf_which]);
+
+	// Enable buffer full and timeout interrupts
+	HAL_WRITE_UINT32(base+AT91_US_IER, AT91_US_IER_TIMEOUT | AT91_US_IER_ENDRX);
+    }
 
-    // Enable RX and TX
-    HAL_WRITE_UINT32(base+AT91_US_CR, AT91_US_CR_RxENAB | AT91_US_CR_TxENAB);
+    // Start timeout
+    HAL_WRITE_UINT32(base+AT91_US_RTOR, RECV_UART_CHAR_TIMEOUT);
+    HAL_WRITE_UINT32(base+AT91_US_CR, AT91_US_CR_STTTO);
 
     return true;
 }
@@ -220,9 +284,12 @@
     at91_serial_info *at91_chan = (at91_serial_info *)chan->dev_priv;
     int res;
 
+    memset(at91_chan->recv.buf, 0x55, sizeof(at91_chan->recv.buf));
+
 #ifdef CYGDBG_IO_INIT
     diag_printf("AT91 SERIAL init - dev: %x.%d\n", at91_chan->base, at91_chan->int_num);
 #endif
+
     (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
     if (chan->out_cbuf.len != 0) {
         cyg_drv_interrupt_create(at91_chan->int_num,
@@ -234,6 +301,28 @@
                                  &at91_chan->serial_interrupt);
         cyg_drv_interrupt_attach(at91_chan->serial_interrupt_handle);
         cyg_drv_interrupt_unmask(at91_chan->int_num);
+
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
+#if 0
+// we need an extra interrupt handler for modem lines
+
+// enable interrupts on modem lines
+	HAL_WRITE_UINT32 (AT91_PIO + AT91_PIO_IER, (AT91_PIO_USART0_IN|AT91_PIO_USART1_IN));
+// should rather be in hal_platform_setup.h (???)
+//        ldr     r1,=0x0007083C          // enable interupts on modem lines
+//        str     r1,[r0,#AT91_PIO_IER]
+
+        cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_PIO,
+                                 4,                      // Priority
+                                 (cyg_addrword_t)chan,   // Data item passed to interrupt handler
+                                 at91_line_ISR,
+                                 at91_line_DSR,
+                                 &at91_chan->line_interrupt_handle,
+                                 &at91_chan->line_interrupt);
+        cyg_drv_interrupt_attach(at91_chan->line_interrupt_handle);
+        cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_PIO);
+#endif
+#endif
     }
     res = at91_serial_config_port(chan, &chan->config, true);
     return res;
@@ -251,38 +340,62 @@
     return ENOERR;
 }
 
+static void
+at91_serial_flip_send_buffer (at91_serial_info * at91_chan)
+{
+    CYG_ADDRWORD base = at91_chan->base;
+    cyg_uint32 count;
+
+//    cyg_drv_isr_lock ();
+
+    HAL_READ_UINT32 (base + AT91_US_TCR, count);
+    if (count > 0) {		// transmitter still busy
+	HAL_WRITE_UINT32 (base + AT91_US_IER, AT91_US_IER_ENDTX);
+    } else {			// transmitter done with old buf
+// empty buffer -
+	at91_chan->send_buf_count[at91_chan->send_buf_which] = 0;
+// flip -
+	at91_chan->send_buf_which = 1 - at91_chan->send_buf_which;
+	HAL_WRITE_UINT32 (base + AT91_US_TPR, (cyg_uint32) at91_chan->send_buf[at91_chan->send_buf_which]);
+	HAL_WRITE_UINT32 (base + AT91_US_TCR,
+			  (cyg_uint32) at91_chan->send_buf_count[at91_chan->send_buf_which]);
+// enable completion interrupt -
+	if (at91_chan->send_buf_count[at91_chan->send_buf_which] > 0)
+	    HAL_WRITE_UINT32 (base + AT91_US_IER, AT91_US_IER_ENDTX);
+	else
+	    HAL_WRITE_UINT32 (base + AT91_US_IDR, AT91_US_IER_ENDTX);
+    }
+
+//    cyg_drv_isr_unlock ();
+}
+
 // Send a character to the device output buffer.
 // Return 'true' if character is sent to device
 static bool
 at91_serial_putc(serial_channel *chan, unsigned char c)
 {
     at91_serial_info *at91_chan = (at91_serial_info *)chan->dev_priv;
-    CYG_ADDRWORD base = at91_chan->base;
-    cyg_uint32 stat;
+    int other;
 
-    // Check status
-    HAL_READ_UINT32(base+AT91_US_CSR, stat);
+    other = 1 - at91_chan->send_buf_which;
+    if (at91_chan->send_buf_count[other] >= AT91_UART_BUF_SIZE)
+	return false;
+
+// append buffer with char
+    at91_chan->send_buf[other][at91_chan->send_buf_count[other]] = (cyg_uint8) c;
+    at91_chan->send_buf_count[other]++;
+
+// flip if needed:
+    at91_serial_flip_send_buffer (at91_chan);
 
-    // Send character if possible
-    if ((stat & AT91_US_CSR_TxRDY) != 0) {
-        HAL_WRITE_UINT32(base+AT91_US_THR, c);
         return true;
-    } else {
-        return false;  // Couldn't send, tx was busy
-    }
 }
 
-// Fetch a character from the device input buffer, waiting if necessary
+// we don't support this - its only for bufferless operation: see serial.c
 static unsigned char 
 at91_serial_getc(serial_channel *chan)
 {
-    at91_serial_info *at91_chan = (at91_serial_info *)chan->dev_priv;
-    CYG_ADDRWORD base = at91_chan->base;
-    cyg_uint32 c;
-
-    // Read data
-    HAL_READ_UINT32(base+AT91_US_RHR, c);
-    return c;
+    return 0;
 }
 
 // Set up the device characteristics; baud rate, etc.
@@ -302,21 +415,66 @@
             return -EINVAL;
       }
       break;
+#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW
+    case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE:
+      {
+          cyg_uint8 *f = (cyg_uint8 *)xbuf;
+          at91_serial_info *at91_chan = (at91_serial_info *)chan->dev_priv;
+          cyg_uint32 pio_pin = 0;
+
+	  if ( at91_chan->base == AT91_USART0 )
+              pio_pin = AT91_PIO_USART0_OUT;
+	  else if ( at91_chan->base == AT91_USART1 )
+              pio_pin = AT91_PIO_USART1_OUT;
+
+          if ( *len < sizeof(*f) )
+              return -EINVAL;
+          
+          if ( !(chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX) )
+	      pio_pin &= ~(AT91_PIO_USART0_RTS|AT91_PIO_USART1_RTS);
+          if ( !(chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_RX) )
+	      pio_pin &= ~(AT91_PIO_USART0_DTR|AT91_PIO_USART1_DTR);
+
+          if (*f) // we should throttle
+              HAL_WRITE_UINT32 (AT91_PIO + AT91_PIO_CODR, pio_pin);
+          else // we should no longer throttle
+              HAL_WRITE_UINT32 (AT91_PIO + AT91_PIO_SODR, pio_pin);
+      }
+      break;
+    case CYG_IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG:
+        // Nothing to do because we do support both RTSCTS and DSRDTR flow
+        // control.
+        // Other targets would clear any unsupported flags here.
+        // We just return ENOERR.
+      break;
+#endif
     default:
         return -EINVAL;
     }
     return ENOERR;
 }
 
+
+
+
 // Enable the transmitter on the device
 static void
 at91_serial_start_xmit(serial_channel *chan)
 {
     at91_serial_info *at91_chan = (at91_serial_info *)chan->dev_priv;
     CYG_ADDRWORD base = at91_chan->base;
+    cyg_uint32 count;
 
-    (chan->callbacks->xmt_char)(chan);  // Kick transmitter (if necessary)
-    HAL_WRITE_UINT32(base+AT91_US_IER, AT91_US_IER_TxRDY);
+//    cyg_drv_isr_lock ();
+
+    HAL_READ_UINT32 (base + AT91_US_TCR, count);
+    if (count > 0)
+	HAL_WRITE_UINT32 (base + AT91_US_IER, AT91_US_IER_ENDTX);
+    at91_chan->tx_enabled = 1;
+
+//    cyg_drv_isr_unlock ();
+
+    (chan->callbacks->xmt_char) (chan);
 }
 
 // Disable the transmitter on the device
@@ -324,18 +482,44 @@
 at91_serial_stop_xmit(serial_channel *chan)
 {
     at91_serial_info *at91_chan = (at91_serial_info *)chan->dev_priv;
-    CYG_ADDRWORD base = at91_chan->base;
-
-    HAL_WRITE_UINT32(base+AT91_US_IDR, AT91_US_IER_TxRDY);
+    at91_chan->tx_enabled = 0;
 }
 
 // Serial I/O - low level interrupt handler (ISR)
 static cyg_uint32 
 at91_serial_ISR(cyg_vector_t vector, cyg_addrword_t data)
 {
+    serial_channel *chan = (serial_channel *) data;
+    at91_serial_info *at91_chan = (at91_serial_info *) chan->dev_priv;
+    CYG_ADDRWORD base = at91_chan->base;
+    cyg_uint32 ipr, imr, count, p;
+
+    // Turn off interrupts and acknowledge the interrupt. This avoids
+    // lost interrupts and unwanted reentrancy. This problem is not entirely
+    // theoretical, since transmit and recieve interrupts are asynchronous
+    // and can happen immediately.
     cyg_drv_interrupt_mask(vector);
     cyg_drv_interrupt_acknowledge(vector);
-    return (CYG_ISR_CALL_DSR|CYG_ISR_HANDLED);  // Cause DSR to be run
+
+    HAL_READ_UINT32 (base + AT91_US_CSR, ipr);
+    HAL_READ_UINT32 (base + AT91_US_IMR, imr);
+    if ((ipr & imr & (AT91_US_IER_ENDRX | AT91_US_IER_TIMEOUT)) && at91_chan->flip)  {
+      HAL_READ_UINT32 (base + AT91_US_RPR, p);
+      count = p - (cyg_uint32) at91_chan->flip->buf[at91_chan->flip->buf_which];
+      if (count > 0) {	// PDC has done work
+	/* record the location of the bytes read while we were away */
+	at91_chan->flip->buf_p = at91_chan->flip->buf[at91_chan->flip->buf_which];
+	at91_chan->flip->buf_count = count;
+	/* flip the buffer */
+	at91_chan->flip->buf_which = 1 - at91_chan->flip->buf_which;
+	HAL_WRITE_UINT32 (base + AT91_US_RPR, (cyg_uint32) at91_chan->flip->buf[at91_chan->flip->buf_which]);
+	HAL_WRITE_UINT32 (base + AT91_US_RCR, (cyg_uint32) AT91_UART_BUF_SIZE);
+      }
+      HAL_WRITE_UINT32 (base + AT91_US_RTOR, RECV_UART_CHAR_TIMEOUT);
+      HAL_WRITE_UINT32 (base + AT91_US_CR, AT91_US_CR_STTTO);
+    }
+
+    return CYG_ISR_CALL_DSR | CYG_ISR_HANDLED;
 }
 
 // Serial I/O - high level interrupt handler (DSR)
@@ -345,24 +529,128 @@
     serial_channel *chan = (serial_channel *)data;
     at91_serial_info *at91_chan = (at91_serial_info *)chan->dev_priv;
     CYG_ADDRWORD base = at91_chan->base;
-    cyg_uint32 stat, c;
+    cyg_uint32 stat, mask;
+
+    HAL_READ_UINT32 (base + AT91_US_CSR, stat);
+    HAL_READ_UINT32 (base + AT91_US_IMR, mask);
 
     // Check status
-    HAL_READ_UINT32(base+AT91_US_IMR, stat);
+    if ((mask & stat & AT91_US_IER_ENDTX)) {
+	if (at91_chan->tx_enabled) {
+	    int count, other;
+	    unsigned char *p;
+
+	    other = 1 - at91_chan->send_buf_which;
+	    if (0 && CYG_XMT_OK ==
+		(chan->callbacks->data_xmt_req) (chan, AT91_UART_BUF_SIZE - at91_chan->send_buf_count[other],
+						 &count, &p)) {
+		do {
+		    if (count <= 0)
+			break;
+		    memcpy (at91_chan->send_buf[other] + at91_chan->send_buf_count[other], p, count);
+		    at91_chan->send_buf_count[other] += count;
 
-    if (stat & (AT91_US_IER_TxRDY)) {
+		    (chan->callbacks->data_xmt_done) (chan, count);
+		    if (!(AT91_UART_BUF_SIZE - at91_chan->send_buf_count[other]))
+			break;
+		} while (CYG_RCV_OK == (chan->callbacks->data_xmt_req) (chan,
+									AT91_UART_BUF_SIZE -
+									at91_chan->send_buf_count[other],
+									&count, &p));
+		at91_serial_flip_send_buffer (at91_chan);
+	    } else {
         (chan->callbacks->xmt_char)(chan);
+		at91_serial_flip_send_buffer (at91_chan);
     }
-    if (stat & (AT91_US_IER_RxRDY)) {
-        while (true) {
-            HAL_READ_UINT32(base+AT91_US_CSR, stat);
-            if ((stat & AT91_US_CSR_RxRDY) == 0) {
+	} else {
+	    at91_serial_flip_send_buffer (at91_chan);
+	}
+    }
+
+    if (at91_chan->recv.buf_count > 0) {	// chars waiting from ISR
+	int count;
+	unsigned char *p;
+	if (CYG_RCV_OK == (chan->callbacks->data_rcv_req) (chan, at91_chan->recv.buf_count, &count, &p)) {
+// block transfer acceptable to upper layer:
+	    do {
+		memcpy (p, at91_chan->recv.buf_p, count);
+		at91_chan->recv.buf_p += count;
+		at91_chan->recv.buf_count -= count;
+		(chan->callbacks->data_rcv_done) (chan, count);
+		if (!at91_chan->recv.buf_count)
                 break;
+	    } while (CYG_RCV_OK ==
+		     (chan->callbacks->data_rcv_req) (chan, at91_chan->recv.buf_count, &count, &p));
+	} else {
+// block transfer not acceptable to upper layer:
+	    do {
+		(chan->callbacks->rcv_char) (chan, (unsigned char) *at91_chan->recv.buf_p++);
+	    } while (--at91_chan->recv.buf_count > 0);
             }
-            HAL_READ_UINT32(base+AT91_US_RHR, c);
-            (chan->callbacks->rcv_char)(chan, c);
         }
+
+    cyg_drv_interrupt_unmask (vector);
+}
+
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
+#if 0
+// Serial I/O - low level interrupt handler (ISR) for modem line changes
+static cyg_uint32 
+at91_line_ISR(cyg_vector_t vector, cyg_addrword_t data)
+{
+    cyg_drv_interrupt_mask(vector);
+    cyg_drv_interrupt_acknowledge(vector);
+    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
     }
+
+// Serial I/O - high level interrupt handler (DSR)
+static void       
+at91_line_DSR (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    cyg_serial_line_status_t stat;
+    serial_channel *chan = (serial_channel *) data;
+    at91_serial_info *at91_chan = (at91_serial_info *) chan->dev_priv;
+    cyg_uint32 pio_pin, status;
+
+    HAL_READ_UINT32 (AT91_PIO + AT91_PIO_ISR, pio_pin);
+    if (at91_chan->base == AT91_USART0)
+	pio_pin &= AT91_PIO_USART0_IN;
+    else if (at91_chan->base == AT91_USART1)
+	pio_pin &= AT91_PIO_USART1_IN;
+    else
+	pio_pin = 0;
+
+    HAL_READ_UINT32 (AT91_PIO + AT91_PIO_PDSR, status);
+
+#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW
+    if (pio_pin & (AT91_PIO_USART0_DSR | AT91_PIO_USART1_DSR))
+	if (chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_TX) {
+	    stat.which = CYGNUM_SERIAL_STATUS_FLOW;
+	    stat.value = (0 != (status & (AT91_PIO_USART0_DSR | AT91_PIO_USART1_DSR)));
+	    (chan->callbacks->indicate_status) (chan, &stat);
+	}
+    if (pio_pin & (AT91_PIO_USART0_CTS | AT91_PIO_USART1_CTS))
+	if (chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_TX) {
+	    stat.which = CYGNUM_SERIAL_STATUS_FLOW;
+	    stat.value = (0 != (status & (AT91_PIO_USART0_CTS | AT91_PIO_USART1_CTS)));
+	    (chan->callbacks->indicate_status) (chan, &stat);
+	}
+#endif
+    if (pio_pin & (AT91_PIO_USART0_DCD | AT91_PIO_USART1_DCD)) {
+	stat.which = CYGNUM_SERIAL_STATUS_CARRIERDETECT;
+	stat.value = (0 != (status & (AT91_PIO_USART0_DCD | AT91_PIO_USART1_DCD)));
+	(chan->callbacks->indicate_status) (chan, &stat);
+    }
+    if (pio_pin & (AT91_PIO_USART0_RI | AT91_PIO_USART1_RI)) {
+	stat.which = CYGNUM_SERIAL_STATUS_RINGINDICATOR;
+	stat.value = (0 != (status & (AT91_PIO_USART0_RI | AT91_PIO_USART1_RI)));
+	(chan->callbacks->indicate_status) (chan, &stat);
+    }
+
     cyg_drv_interrupt_unmask(vector);
 }
 #endif
+#endif
+
+#endif
+
Index: ecos/packages/hal/arm/at91/var/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/var/current/ChangeLog,v
retrieving revision 1.11
diff -a -w -u -r1.11 ChangeLog
--- ecos/packages/hal/arm/at91/var/current/ChangeLog	21 Aug 2003 15:29:53 -0000	1.11
+++ ecos/packages/hal/arm/at91/var/current/ChangeLog	21 Oct 2003 12:39:24 -0000
@@ -1,3 +1,7 @@
+2003-10-21  Øyvind Harboe <oyvind.harboe@zylin.com>
+	* added missing AT91_US_RTOR define for hardware buffer receive
+	timeout
+
 2003-08-21  Thomas Koeller  <thomas.koeller@baslerweb.com>
 
         * include/var_io.h:
Index: ecos/packages/hal/arm/at91/var/current/include/var_io.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/var/current/include/var_io.h,v
retrieving revision 1.5
diff -a -w -u -r1.5 var_io.h
--- ecos/packages/hal/arm/at91/var/current/include/var_io.h	21 Aug 2003 15:29:53 -0000	1.5
+++ ecos/packages/hal/arm/at91/var/current/include/var_io.h	21 Oct 2003 12:39:25 -0000
@@ -134,6 +134,7 @@
 #define AT91_US_RCR 0x34  // Receive counter register
 #define AT91_US_TPR 0x38  // Transmit pointer register
 #define AT91_US_TCR 0x3c  // Transmit counter register
+#define AT91_US_RTOR 0x24
 
 #define AT91_US_BAUD(baud) (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED/(16*(baud)))
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]