public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] routing sockets / far end address resolution
@ 2008-01-21 22:04 Daniel Paape
  2008-01-22  9:19 ` [ECOS] Half Duplex RS485 Laurie Gellatly
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Paape @ 2008-01-21 22:04 UTC (permalink / raw)
  To: ecos-discuss

Hello,

Someone asked a question
(http://sourceware.org/ml/ecos-discuss/2006-12/msg00137.html) about a
year ago regarding routing sockets.  There was no response to the
question and I'm wondering whether someone might have a go at a
re-worded version.  Does eCos support routing sockets?  The individual
above was having difficulty with the fileio (read/write) calls
associated with a routing socket.  Could one use sendmsg/recvmsg instead
(if they are indeed supported)?  If so, how does one convey that the
second argument is a "rt_msghdr" rather than just a "msghdr" structure?

My ultimate goal is to resolve a far end IP address to its mac address
(it may be local or may be on the other side of the gateway).  The
address probably isn't resident in the ARP table, so what I am in
essence attempting to do is to get the stack to do a synchronized ARP
request for me.  A ping would (most likely) get the address into the ARP
table but I would really like to avoid an ICMP exchange.  I've cobbled a
proprietary IOCTL into the stack and can get it to do a lookup and if
necessary send out the ARP request... but implementing a wait for the
response is going to be difficult.

Is there a better way?

Thanks for any help.
Dan Paape

--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread
* RE: [ECOS]  Re: Half Duplex RS485
@ 2008-01-25  4:16 wangcui
  2008-01-26 20:41 ` Laurie Gellatly
  0 siblings, 1 reply; 14+ messages in thread
From: wangcui @ 2008-01-25  4:16 UTC (permalink / raw)
  To: Laurie Gellatly, Grant Edwards, ecos-discuss

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 4736 bytes --]



Here is the patch, shows all modifications in my working folder.
Acutally, I did more than FIFO stuff, I also made it support 2 diffent 16x5x chips on my target(different register-offset-step), and something else.

BTW, I prefer to solve half-duplex problem on hardware level, which avoid lots of effort on software level.

> From: laurie.gellatly@netic.com
> To: iucgnaw@msn.com; grante@visi.com; ecos-discuss@sources.redhat.com
> Subject: RE: [ECOS] Re: Half Duplex RS485
> Date: Fri, 25 Jan 2008 12:59:54 +1100
>
> Hi Wang,
> I'd be interested to see what you had to modify to make the FIFO work.
>
> The eCos source does not know about the fractional divider.
> Did you enable fix that as well?
>
> ...Laurie:{)
>
> -----Original Message-----
> From: wangcui [mailto:iucgnaw@msn.com]
> Sent: Friday, 25 January 2008 12:33 PM
> To: Laurie Gellatly; Grant Edwards; ecos-discuss@sources.redhat.com
> Subject: RE: [ECOS] Re: Half Duplex RS485
>
>
>
> Just FYI, the LPC2XXX's UART0 is not fully functional. So when the 16x5x
> serial driver check FIFO(in serial_config_port()), it will fail, thus FIFO
> is disabled for UART0. But UART1 works fine.
>
> To resolve it, I have to modified 16x5x driver code, force enable FIFO for
> UART0 and UART1.
>
>> From: laurie.gellatly@netic.com
>> To: grante@visi.com; ecos-discuss@sources.redhat.com
>> Date: Thu, 24 Jan 2008 08:12:17 +1100
>> Subject: RE: [ECOS] Re: Half Duplex RS485
>>
>> Wang/Grant, thanks for the replies.
>>
>>>> My project has RS485 half duplex driven by UART0 of an
>>>> LPC2112. At present I've modified pc_serial_start_xmit and
>>>> pc_serial_stop_xmit to change a pin state so that the same
>>>> wires can be used for transmit and receive.
>>>>
>>>> This does not see to work when the FIFO is enabled.
>>>
>>>Then you probably did it wrong. :)
>>>
>>>I imagine that RTS is shutting off too soon. The problem is
>>>that pc_serial_stop_xmit() is called when the driver has no
>>>more data to send _to_ the UART. That's not when you need to
>>>shut off RTS. You need to shut off RTS when the UART is done
>>>sending data and both the FIFO and shift register are empty.
>>>
>>>You're probably shutting off RTS while the UART still has data
>>>in the tx FIFO and the tx shift register.
>> Funny thing is that it appears that the first part of the
>> transmission is lost.
>>
>>>> Has anyone else done RS485 half duplex?
>>>
>>>Many, many times.
>>>
>>>> Did you modify these routines or write your own?
>>>
>>>I usually pick a UART that supports half-duplex operation, and
>>>then just enabled that feature in the UART. [I use a custom
>>>eCos serial driver that supports quite a few more advanced UART
>>>features than the standard driver (e.g. flow control,
>>>half-duplex, inter-byte timeouts, 9-bit modes, FIFO control,
>>>etc.).
>>>
>>>If you don't have a proper UART, you need to enable the tx
>>>shift register empty interrupt and use that to trigger code
>>>that de-asserts RTS. If you're using a broken UART that
>>>doesn't have a tx shift register empty interrupt, then you'll
>>>have to poll for the tx shift register empty status. If you're
>>>using a really broken UART that doesn't have a _working_
>>>shift-register empty status[1], then you may have to start a
>>>timer that will wake you up at the point in time where RTS
>>>needs to be changed.
>>>
>>>> Did you get the FIFO to work?
>>>
>>>When there was one, yes.
>>>
>>>
>>>[1] There are broken UARTs (including a few PC chipsets) whose
>>> shift-register empty bit gets set _before_ the stop bit has
>>> been sent. In that case, you may need to use some sort of
>>> time-delay to wait until after the stop bit has been sent
>>> to toggle RTS. On a properly implimented RS-485 bus, there
>>> should be pull-up and pull-down resisters so that the bus
>>> idles in the mark state (same value as a stop bit), but to
>>> be on the safe side you should leave the bus driver on
>>> until after the stop bit has been sent.
>>
>> Grant, do you know if the LPC series have 'broken' UARTS?
>> Specifically LPC2212 and LPC2103?
>> U0TSR looks promising as an indication of when the bits
>> 'have left the building' - is it accurate or do I
>> need to add a time delay?
>>
>> Really appreciate the help. ...Laurie:{)
>>
>> --
>> Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
>> and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
>>
>
> _________________________________________________________________
> ÌìÁ¹ÁË£¬ÌíÒÂÁË£¬ÐĶ¯ÁË£¬¡°Æß¼þ¡±ÁË
> http://get.live.cn
>

_________________________________________________________________
MSN ÖÐÎÄÍø£¬×îÐÂʱÉÐÉú»î×ÊѶ£¬°×Áì¾Û¼¯ÃÅ»§¡£
http://cn.msn.com

[-- Attachment #2: 16x5x.patch --]
[-- Type: text/plain, Size: 10771 bytes --]

diff -r -u5 -N -x CVS /cygdrive/z/Share/Resource/eCos/anoncvs/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c /cygdrive/d/work/dev/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c
--- /cygdrive/z/Share/Resource/eCos/anoncvs/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c	2007-06-22 19:41:49.000000000 +0800
+++ /cygdrive/d/work/dev/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c	2008-01-25 11:47:46.232562700 +0800
@@ -62,15 +62,18 @@
 #include <cyg/hal/hal_io.h>
 
 // Only compile driver if an inline file with driver details was selected.
 #ifdef CYGDAT_IO_SERIAL_GENERIC_16X5X_INL
 
-#ifndef CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP
-#define CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP 1
-#endif
-
-#define SER_REG(_x_) ((_x_)*CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP)
+//here we use a 'step' variable to indicate the address delta between a 16X5X channel's registers
+//user should new a variable named 'step' and set appropriate value before access 16X5X's register.
+//For example:
+//{
+//  int step = ser_chan->step;
+//  HAL_WRITE_UINT8(base+REG_thr, c);
+//}
+#define SER_REG(_x_) ((_x_)*step)
 
 // Receive control Registers
 #define REG_rhr SER_REG(0)    // Receive holding register
 #define REG_isr SER_REG(2)    // Interrupt status register
 #define REG_lsr SER_REG(5)    // Line status register
@@ -180,10 +183,15 @@
 // selec_baud[] must be define by the client
 
 typedef struct pc_serial_info {
     cyg_addrword_t base;
     int            int_num;
+    int            int_prio;
+    int            step;
+    int            baud_num;
+    int           *select_baud;
+    int          (*baud_generator)(unsigned int baud);
     cyg_interrupt  serial_interrupt;
     cyg_handle_t   serial_interrupt_handle;
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
     enum {
         sNone = 0,
@@ -233,12 +241,17 @@
 serial_config_port(serial_channel *chan, 
                    cyg_serial_info_t *new_config, bool init)
 {
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
-    unsigned short baud_divisor = select_baud[new_config->baud];
+    int step = ser_chan->step;
+    unsigned short baud_divisor;
     unsigned char _lcr, _ier;
+    
+    if (new_config->baud >= ser_chan->baud_num) return false;  // Invalid configuration
+
+    baud_divisor = ser_chan->select_baud[new_config->baud];
     if (baud_divisor == 0) return false;  // Invalid configuration
 
     // Disable port interrupts while changing hardware
     HAL_READ_UINT8(base+REG_ier, _ier);
     HAL_WRITE_UINT8(base+REG_ier, 0);
@@ -253,21 +266,22 @@
     if (init) {
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
         unsigned char _fcr_thresh;
         cyg_uint8 b;
 
-        /* First, find out what kind of device it is. */
-        ser_chan->deviceType = sNone;
-        HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP); // enable loopback mode
-        HAL_READ_UINT8(base+REG_msr, b);         
-        if (0 == (b & 0xF0)) {   // see if MSR had CD, RI, DSR or CTS set
-            HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP|MCR_DTR|MCR_RTS);
-            HAL_READ_UINT8(base+REG_msr, b);
-            if (0xF0 != (b & 0xF0))  // check that all of CD,RI,DSR and CTS set
-                ser_chan->deviceType = s8250;
+        if (ser_chan->deviceType == sNone) {
+            /* First, find out what kind of device it is. */
+            HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP); // enable loopback mode
+            HAL_READ_UINT8(base+REG_msr, b);         
+            if (0 == (b & 0xF0)) {   // see if MSR had CD, RI, DSR or CTS set
+                HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP|MCR_DTR|MCR_RTS);
+                HAL_READ_UINT8(base+REG_msr, b);
+                if (0xF0 != (b & 0xF0))  // check that all of CD,RI,DSR and CTS set
+                    ser_chan->deviceType = s8250;
+            }
+            HAL_WRITE_UINT8(base+REG_mcr, 0); // disable loopback mode
         }
-        HAL_WRITE_UINT8(base+REG_mcr, 0); // disable loopback mode
 
         if (ser_chan->deviceType == s8250) {
             // Check for a scratch register; scratch register 
             // indicates 16450 or above.
             HAL_WRITE_UINT8(base+REG_scr, 0x55);
@@ -308,10 +322,11 @@
               CYGNUM_IO_SERIAL_GENERIC_16X5X_FIFO_TX_SIZE;
             // Enable and clear FIFO
             HAL_WRITE_UINT8(base+REG_fcr, _fcr_thresh); 
         }
         else {
+            CYG_FAIL("Can't enable FIFO on this device.");
             ser_chan->tx_fifo_size = 1;
             HAL_WRITE_UINT8(base+REG_fcr, 0); // make sure it's disabled
         }
 
         ser_chan->tx_fifo_avail = ser_chan->tx_fifo_size;
@@ -348,36 +363,39 @@
 
 #ifdef CYG_IO_SERIAL_GENERIC_16X5X_BAUD_GENERATOR
     // Fill in baud rate table - used for platforms where this cannot
     // be determined statically
     int baud_idx, baud_val;
-    if (select_baud[0] == 9999) {
+
+    if (ser_chan->select_baud[0] == 9999) {
+        CYG_ASSERTC(ser_chan->baud_generator != NULL);
+
         // Table not yet initialized
         // Assumes that 'select_baud' looks like this:
         //   static int select_baud[] = {
         //       9999,  -- marker
         //       50,    -- first baud rate
         //       110,   -- second baud rate
         // etc.
-        for (baud_idx = 1;  baud_idx < sizeof(select_baud)/sizeof(select_baud[0]);  baud_idx++) {
-            baud_val = CYG_IO_SERIAL_GENERIC_16X5X_BAUD_GENERATOR(select_baud[baud_idx]);
-            select_baud[baud_idx] = baud_val;
+        for (baud_idx = 1;  baud_idx < ser_chan->baud_num;  baud_idx++) {
+            baud_val = ser_chan->baud_generator(ser_chan->select_baud[baud_idx]);
+            ser_chan->select_baud[baud_idx] = baud_val;
         }
-        select_baud[0] = 0;
+        ser_chan->select_baud[0] = 0;
     }
 #endif
 
 #ifdef CYGDBG_IO_INIT
-    diag_printf("16x5x SERIAL init - dev: %x.%d\n", 
-                ser_chan->base, ser_chan->int_num);
+    diag_printf("16x5x SERIAL init - dev: base=%x.step=%d.int_num=%d\n", 
+                ser_chan->base, ser_chan->step, ser_chan->int_num);
 #endif
     // Really only required for interrupt driven devices
     (chan->callbacks->serial_init)(chan);
 
     if (chan->out_cbuf.len != 0) {
         cyg_drv_interrupt_create(ser_chan->int_num,
-                                 CYG_IO_SERIAL_GENERIC_16X5X_INT_PRIORITY,
+                                 ser_chan->int_prio == -1 ? CYG_IO_SERIAL_GENERIC_16X5X_INT_PRIORITY : ser_chan->int_prio,
                                  (cyg_addrword_t)chan,
                                  pc_serial_ISR,
                                  pc_serial_DSR,
                                  &ser_chan->serial_interrupt_handle,
                                  &ser_chan->serial_interrupt);
@@ -409,10 +427,11 @@
 #ifndef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
     cyg_uint8 _lsr;
 #endif
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
 
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
     if (ser_chan->tx_fifo_avail > 0) {
         HAL_WRITE_UINT8(base+REG_thr, c);
         --ser_chan->tx_fifo_avail;
@@ -436,10 +455,11 @@
 {
     unsigned char c;
     cyg_uint8 _lsr;
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
 
     // Wait for char
     do {
         HAL_READ_UINT8(base+REG_lsr, _lsr);
     } while ((_lsr & LSR_RSR) == 0);
@@ -469,10 +489,11 @@
     case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE:
       {
           cyg_uint8 _mcr;
           pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
           cyg_addrword_t base = ser_chan->base;
+          int step = ser_chan->step;
           cyg_uint32 *f = (cyg_uint32 *)xbuf;
           unsigned char mask=0;
           if ( *len < sizeof(*f) )
               return -EINVAL;
           
@@ -509,26 +530,34 @@
 static void
 pc_serial_start_xmit(serial_channel *chan)
 {
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
-    cyg_uint8 _ier;
+    int step = ser_chan->step;
+    cyg_uint8 _ier, _lsr;
     
     HAL_READ_UINT8(base+REG_ier, _ier);
     _ier |= IER_XMT;                    // Enable xmit interrupt
     HAL_WRITE_UINT8(base+REG_ier, _ier);
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_XMIT_REQUIRE_PRIME
-    (chan->callbacks->xmt_char)(chan);
+    //some chip(at least LPC2XXX's embedded DUART) may not generate ISR_Tx interrupt after enable IER_XMT,
+    //so we try transmitting here to trigger the ISR_Tx intertupt.
+    HAL_READ_UINT8(base+REG_lsr, _lsr);
+    if ((_lsr & LSR_THE)) {
+        // transmitter holding register ready
+        (chan->callbacks->xmt_char)(chan);
+    }
 #endif
 }
 
 // Disable the transmitter on the device
 static void 
 pc_serial_stop_xmit(serial_channel *chan)
 {
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
     cyg_uint8 _ier;
 
     HAL_READ_UINT8(base+REG_ier, _ier);
     _ier &= ~IER_XMT;                   // Disable xmit interrupt
     HAL_WRITE_UINT8(base+REG_ier, _ier);
@@ -550,10 +579,11 @@
 pc_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
 {
     serial_channel *chan = (serial_channel *)data;
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
     cyg_uint8 _isr;
 
     // Check if we have an interrupt pending - note that the interrupt
     // is pending of the low bit of the isr is *0*, not 1.
     HAL_READ_UINT8(base+REG_isr, _isr);
@@ -645,14 +675,16 @@
                 }
             }
             break;
 #endif
         default:
-            // Yes, this assertion may well not be visible. *But*
-            // if debugging, we may still successfully hit a breakpoint
-            // on cyg_assert_fail, which _is_ useful
-            CYG_FAIL("unhandled serial interrupt state");
+            #if 0
+            //some chip(at least Philips SC16C2550B) may generate a interrupt without valid source,
+            //so we print a error message rather than die here.
+            diag_printf("unhandled serial interrupt state""\r\n");
+            #endif
+            break;
         }
 
         HAL_READ_UINT8(base+REG_isr, _isr);
     } // while
 

[-- Attachment #3: Type: text/plain, Size: 148 bytes --]

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-01-28 10:34 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-01-21 22:04 [ECOS] routing sockets / far end address resolution Daniel Paape
2008-01-22  9:19 ` [ECOS] Half Duplex RS485 Laurie Gellatly
     [not found]   ` <001001c85dd0$c8083160$6501a8c0@global.ds.honeywell.com>
2008-01-23 15:01     ` Wang Cui
2008-01-23 16:34   ` [ECOS] " Grant Edwards
2008-01-23 21:12     ` Laurie Gellatly
2008-01-23 22:03       ` Grant Edwards
2008-01-23 23:06         ` Laurie Gellatly
2008-01-23 23:44           ` Grant Edwards
2008-01-24  9:02           ` Daniel Néri
2008-01-25  1:33       ` wangcui
2008-01-25  2:00         ` Laurie Gellatly
2008-01-25  4:16 wangcui
2008-01-26 20:41 ` Laurie Gellatly
2008-01-28 10:34   ` wangcui

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).