Changeset b3fd1641 in rtems for c/src/lib/libc/termios.c


Ignore:
Timestamp:
Aug 21, 1998, 3:32:19 PM (21 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
29381405
Parents:
d47de32
Message:

Fix from Eric Norum <eric@…>:

"Thomas Doerfler" <td@…> wrote:

While implementing/testing the console/termios support for
PPC403 in RTEMS-4.0.0-beta3, I am stuck at a certain location in
termios.c:

During "rtems_termios_initialize", the main control data structure
"*tty" is allocated using malloc(). (Note, that malloc does not
clear the allocated memory and my BSP does not clear memory during
startup). Furtheron, a lot of fields of that structure are
initialized, but the field "rawOutBufState" is not, and therefore
keeps an arbitrary contents.

When "osend()" is called the first time(with the serial device
driver working in interrupt mode), termios gets stuck and will not
call the device drivers output function.

My questions now are:

  • anybody already experienced this bug?
  • is it a bug at all or did I do anything fundamentally wrong?
  • is there already a common bugfix for that?

I don't like poking around in other people code, as long as I am
not absolutely sure, what I do...

Yes, there's a bug there.
I thought that Joel had patched this already, but here's a patch to
fix this. This patch also addresses a concern that many others have
raised regarding enabling and disabling of transmitter interrupts.

First, here's the example I've been using of a simple UART-style
interrupt-driven driver:
===============================================================
void
device_write_routine (int minor, char *buf, int count)
{

UART->control_register &= ~UART_TRANSMITTER_READY;
UART->output_register = *buf;
UART->control_register |= UART_TRANSMIT_INTERRUPT_ENABLE;

}

void
device_transmit_interrupt_routine (int vector)
{

UART->control_register &= ~UART_TRANSMIT_INTERRUPT_ENABLE;
rtems_termios_dequeue_characters (device_ttyp, 1);

}
==============================================================

Several people have expressed their concern about the disable/enable
of transmitter interrupts for every character. On some machines
this disable/enable is an expensive operation. With the attached
patch applied you can write the two routines as:
==============================================================
void
device_write_routine (int minor, char *buf, int count)
{

code_to_clear_transmitter_ready_status ();
if (device_ttyp->rawOutBufState == rob_idle)

code_to_enable_transmitter_interrupts ();

code_to_send_one_character_to_transmitter (*buf);

}

void
device_transmit_interrupt_routine (int vector)
{

rtems_termios_dequeue_characters (device_ttyp, 1);
if (device_ttyp->rawOutBufState == rob_idle)

code_to_disable_transmitter_interrupts ();

}
===============================================================

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libc/termios.c

    rd47de32 rb3fd1641  
    214214                tty->forw = ttyHead;
    215215                ttyHead = tty;
    216                 tty->back = NULL;
    217216                if (ttyTail == NULL)
    218217                        ttyTail = tty;
     
    248247                if (sc != RTEMS_SUCCESSFUL)
    249248                        rtems_fatal_error_occurred (sc);
    250                 tty->rawOutBufHead = 0;
    251                 tty->rawOutBufTail = 0;
    252                 tty->refcount = 0;
    253249                tty->rawOutBufState = rob_idle;
    254250
     
    266262                        if (sc != RTEMS_SUCCESSFUL)
    267263                                rtems_fatal_error_occurred (sc);
    268                         tty->rawInBufHead = 0;
    269                         tty->rawInBufTail = 0;
    270                 }
    271 
    272                 /*
    273                  * Initialize variables
    274                  */
    275                 tty->column = 0;
    276                 tty->cindex = tty->ccount = 0;
     264                }
    277265
    278266                /*
     
    482470                tty->rawOutBufHead = newHead;
    483471                if (tty->rawOutBufState == rob_idle) {
    484                         tty->rawOutBufState = rob_busy;
    485472                        (*tty->device.write)(tty->minor,
    486473                                (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1);
     474                        tty->rawOutBufState = rob_busy;
    487475                }
    488476                rtems_interrupt_enable (level);
     
    936924                 * Buffer not empty, start tranmitter
    937925                 */
    938                 tty->rawOutBufState = rob_busy;
    939926                if (newTail > tty->rawOutBufHead)
    940927                        nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail;
     
    942929                        nToSend = tty->rawOutBufHead - newTail;
    943930                (*tty->device.write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend);
     931                tty->rawOutBufState = rob_busy;
    944932        }
    945933        tty->rawOutBufTail = newTail;
Note: See TracChangeset for help on using the changeset viewer.