Network Write Delay using PPPD

Thomas Doerfler Thomas.Doerfler at imd-systems.de
Mon Jun 25 13:32:48 UTC 2001


Hi Mike,

> 
> Hi Thomas,
> I am currently using the i386/pc586 BSP which does not use 
> task driven termios.  Why does PPP require a task driven 
> serial driver?  How hard is it to convert an interrupt
> serial driver to be task driven?
> 

When you switch a serial device into PPP mode, termios transfers each 
character directly to a PPP unpacking function, which itself pushes 
the corresponding packets into the IP stack. The last step requires 
to acquire the network semaphore, and waiting for a semaphore is not 
possible in interrupt context.

The general structure is derived from FreeBSD.

Changing a driver from interrupt-driven to task-driven mode is not so 
complicated. There is a document:

http://www.oarcorp.com/rtems/releases/4.5.0/rtemsdoc-
4.5.0/share/rtemsdoc/pdf/bsp_howto.pdf

which also discusses device driver operation. I have sent some 
modifications for that document to OAR, but it they are not yet 
integrated. So I attached a list of necessary modifications to that 
document to this mail.

Hope this helps. By the way: I think many people would benefit from a 
task-driven i386 driver...


	Bye, Thomas.





> Thanks for you help
> Mike Siers
> 
> 
> -----Original Message-----
> From: Thomas Doerfler [mailto:Thomas.Doerfler at imd-systems.de]
> Sent: Saturday, June 23, 2001 12:43 PM
> To: Mike Siers
> Cc: rtems-users at OARcorp.com
> Subject: Re: Network Write Delay using PPPD
> 
> 
> Hello Mike,
> 
> I just had another thought concerning your PPP problem: What kind of 
> serial driver do you use? The serial device driver used for PPP 
> connections MUST (!) use the new "task-driven" termios interface, and 
> currently only few BSPs (if any) support this model. So check the 
> device driver, if it uses termios polled or interrupt-driven mode, 
> problems are to be expected...
> 
> Bye,
> 	Thomas.
> 
> 
> > 
> > Hi,
> > I am using the i386/pc586 BSP with the latest snapshot.  My code
> > is using the standard pppd task to establish a network connection.
> > The ppp connection gets established and I can create a socket and 
> > connect to my server test application.  
> > 
> > The RTEMS client code will write a block of data every time it 
> > receives some data over the socket.  The problem that I am seeing 
> > is that the client write seems to be getting delayed.  And the
> > delay keeps getting longer after each successive write.  After four 
> > writes, the delay is about 90 seconds!  I have turned off the pppd
> > compression options.
> > 
> > I added some debug statements to the pppd code.  Basically it looks
> > like the pppoutput function is getting called immediately but the
> > modem_sendpacket function call gets delayed.
> > 
> > Has anyone seen this problem before?  Any thoughts or suggestions
> > would be greatly appreciated.
> > 
> > Thanks
> > Mike Siers
> 
> 
> --------------------------------------------
> IMD Ingenieurbuero fuer Microcomputertechnik
> Thomas Doerfler           Herbststrasse 8
> D-82178 Puchheim          Germany
> email:    Thomas.Doerfler at imd-systems.de
> PGP public key available at: http://www.imd-systems.de/pgp_key.htm


--------------------------------------------
IMD Ingenieurbuero fuer Microcomputertechnik
Thomas Doerfler           Herbststrasse 8
D-82178 Puchheim          Germany
email:    Thomas.Doerfler at imd-systems.de
PGP public key available at: http://www.imd-systems.de/pgp_key.htm



-------------- Enclosure number 1 ----------------
******************** 

Add In documentation for "task driven mode" in RTEMS 4.5.0
termios. These are some change notes/add ins to the document "BSP and
Device Driver Development Guide" Edition 1 for 4.5.0-beta3, May 2000

********************

8.3 Driver Functioning Modes

There are generally two main functioning modes for an UART (Universal
Asynchronous Receiver-Transmitter, i.e. the serial chip):   

	     polled mode
	     interrupt driven mode 
***** snip NEW BEGIN ****
	     task driven mode
***** snip NEW END ****

In polled mode, the processor blocks on sending/receiving
characters. This mode is not the most e cient way to utilize the
UART. But polled mode is usually necessary when one wants to print an
error message in the event of a fatal error such as a fatal error in
the BSP. This is also the simplest mode to program. Polled mode is
generally preferred if the serial port is to be used primarily as a
debug console. In a simple polled driver, the software will
continuously check the status of the UART when it is reading or
writing to the UART. Termios improves on this by delaying the caller
for 1 clock tick between successive checks of the UART on a read
operation. 

In interrupt driven mode, the processor does not block on
sending/receiving characters. Data is buffered between the interrupt
service routine and application code. Two buffers are used to insulate
the application from the relative slowness of the serial device. One
of the buffers is used for incoming characters, while the other is
used for outgoing characters. 

An interrupt is raised when a character is received by the UART. The
interrupt subroutine places the incoming character at the end of the
input buffer. When an application asks for input, the characters at the
front of the buffer are returned. 

When the application prints to the serial device, the outgoing
characters are placed at the end of the output buffer. The driver will
place one or more characters in the UART (the exact number depends on
the UART) An interrupt will be raised when all the characters have
been transmitted. The interrupt service routine has to send the
characters remaining in the output bu er the same way. When the
transmitting side of the UART is idle, it is typically necessary to
prime the transmitter before the first interrupt will occur.

***** snip NEW BEGIN ****
Task driven mode works similar to interrupt driven mode with one
exception: termios creates two tasks to perform the actual character
transfers between the buffers and the serial device. One task will
handle the receive and one the transmit direction. 

The device will still raise interrupts when characters have been
received or new characters can be transmitted. Due to the interrupts
the corresponding task will wake up and the data transfer between the
data buffer and the serial device are executed in task context. This
reduces dramatically the time spent in interrupt context.

Another benefit of task driven mode is the ability to add new "line
disciplines" like SLIP or PPP to the serial device. Termios has a line
discipline interface used to hook additional interface modes to the
serial device. Please note that the line discipline interface is not
further discussed here, it is very similar to the implementation in
FreeBSD.

Each serial device that supports termios in task driven mode will
automatically also support these line disciplines. The individual line
discipline code is executed in the context of the same tasks that are
responsible for the data transfers between the data buffers and the
serial devices. 
***** snip NEW END ****

***** New chapters "8.4.T".x to be added before chapter 8.4.3 
8.4.T Termios and Task Driven I/O 

During initialization, termios creates two tasks for each serial
device working in task driven mode, one for receive processing and one
for transmit processing. The UART generally generates interrupts, when
it is ready to accept or to emit a number of characters. The interrupt
subroutine signals, that new data can be transferred between serial
device and data buffer, but the actual transfers are performed in two
tasks dedicated to each serial interface.

8.4.T.1 InterruptHandler 

In this mode, the InterruptHandler only has to wake up the
corresponding task. The basic structure is of the InterruptHandler is
the same as in interrupt driven mode, it depends on the structure of
the serial device. The following describes the operation of an
InterruptHandler: 

rtems_isr InterruptHandler (rtems_vector_number v) 
{ 
  check whether there was an error 

  if some characters were received:

    disable further receive interrupts of device

    Tell TERMIOS, that new characters have been received 
    using the function:

    rtems_termios_rxirq_occured(device_tty_ptr);

    TERMIOS will then wake up the corresponding receive task which in
    turn calls the driver's "taskRead" function (callbacks.pollRead). 
    (Receive interrupts will be reenabled in the taskRead" function).

  if some characters have been transmitted 
    (i.e. the UART output buffer is no longer full) 

    Tell TERMIOS that the characters have been transmitted
    using the function:

    rtems_termios_dequeue_characters (device_tty_ptr, 
                                      number_of_characters_sent);

    TERMIOS will then wake up the corresponding transmit task which in
    turn calls the driver's "TaskWrite" function (callbacks.write).


8.4.T.2 TaskRead

The taskRead function is called in task context, whenever a receive
interrupt has occured previously. Note that for some device types this
may mean, that zero, one or multiple new characters have been received. 

The taskRead function can call the function
"rtems_termios_enqueue_raw_characters" to transfer the received characters
to the termios system. The function might have a structure like this:

int taskRead(int minor)
{
   char tmp_buf[];

   check receive status of device
   while(further characters or character_buffers received)
   {
    read character(s) from hardware device and write it to tmp_buf
    rtems_termios_enqueue_raw_characters (device_tty_ptr,
					  tmp_buf,
					  number_of_chars_in_tmp_buf);
   }
   reenable receive interrupts
}

The passing of receive buffers to termios is very similar the the
interrupt driven mode, but in task driven mode the
"rtems_enqueue_raw_characters" function is called from driver function
"taskRead" (in task context) and not in the interruptHandler function.

Due to compatibility reasons, the "taskRead" function must be hooked to the
"pollRead" pointer of the device "callback" structure.

8.4.T.3 TaskWrite

The TaskWrite function has the same structure as the InterruptWrite
function discussed in interrupt driven mode. The only thing to keep in
mind is that it is no longer executed in interrupt context but in task
context. For many devices the same code can be used to form the
InterruptWrite function or the TaskWrite function.

Due to compatibility reasons, this function must be hooked to the
"interruptWrite" pointer of the device "callback" structure.
***** snip NEW END ****

***** snip CHANGE BEGIN ****
In chapter "8.4.3 Initialization", replace the term "If interrupt
driven, register the ..." with "If interrupt or task driven, register
the ..."
***** snip CHANGE END ****

***** snip NEW chapter 8.4.4.3 to be added 
      before 8.4.5 "Closing a Serial Device" ****

8.4.4.3 Task Driven I/O 

In this mode, the driver has to pass a read function aswell as a write
function to Termios (see Section 8.4.T [Console Driver Termios and
Task Driven I/O], page XX). The driver is responsible for providing a
pointer to the taskRead and taskWrite function.
***** snip NEW END ****



More information about the users mailing list