예제 #1
0
//*****************************************************************************
//! Handles the UART interrupt.
//!
//! \param ucPort is the serial port number to be accessed.
//!
//! This function is called when either of the UARTs generate an interrupt.
//! An interrupt will be generated when data is received and when the transmit
//! FIFO becomes half empty.  The transmit and receive FIFOs are processed as
//! appropriate.
//!
//! \return None.
//*****************************************************************************
static void SerialUARTIntHandler(uint8_t ucPort)
{
    // Get the cause of the interrupt.
    uint32_t ulStatus = UARTIntStatus(g_ulUARTBase[ucPort], true);

    // Clear the cause of the interrupt.
    UARTIntClear(g_ulUARTBase[ucPort], ulStatus);

    // See if there is data to be processed in the receive FIFO.
    if(ulStatus & (UART_INT_RT | UART_INT_RX))
    {
        // Loop while there are characters available in the receive FIFO.
        while(UARTCharsAvail(g_ulUARTBase[ucPort]))
        {
            // Get the next character from the receive FIFO.
            uint8_t ucChar = UARTCharGet(g_ulUARTBase[ucPort]);

#ifdef PROTOCOL_TELNET
            // If Telnet protocol enabled, check for incoming IAC character,
            // and escape it.
            if((g_sParameters.sPort[ucPort].ucFlags &
                        PORT_FLAG_PROTOCOL) == PORT_PROTOCOL_TELNET)
            {
                // If this is a Telnet IAC character, write it twice.
                if((ucChar == TELNET_IAC) &&
                   (RingBufFree(&g_sRxBuf[ucPort]) >= 2))
                {
                    RingBufWriteOne(&g_sRxBuf[ucPort], ucChar);
                    RingBufWriteOne(&g_sRxBuf[ucPort], ucChar);
                }

                // If not a Telnet IAC character, only write it once.
                else if((ucChar != TELNET_IAC) &&
                        (RingBufFree(&g_sRxBuf[ucPort]) >= 1))
                {
                    RingBufWriteOne(&g_sRxBuf[ucPort], ucChar);
                }
            }

            // if not Telnet, then only write the data once.
            else
#endif

            {
                if (fDataDebugFlag)
                  CONSOLE("%u: from UART %02X\n", ucPort, ucChar);

                if (IsModemModeCommand(ucPort))
                  ProcessModemModeCommand(ucPort, ucChar);
                else
                {
                  ProcessModemModeData(ucPort, ucChar);
                  RingBufWriteOne(&g_sRxBuf[ucPort], ucChar);
                }

                ProcessModemToServerData(ucPort);
                ProcessServerToModemData(ucPort, ucChar);
            }
        }
    }

#ifdef SERIAL_FLOW_CONTROL
    // If flow control is enabled, check the status of the RX buffer to
    // determine if flow control GPIO needs to be asserted.
    if(g_sParameters.sPort[ucPort].ucFlowControl == SERIAL_FLOW_CONTROL_HW)
    {
        // If the ring buffer is down to less than 25% free, assert the
        // outbound flow control pin.
        if(RingBufFree(&g_sRxBuf[ucPort]) <
           (RingBufSize(&g_sRxBuf[ucPort]) / 4))
        {
            GPIOPinWrite(g_ulFlowOutBase[ucPort], g_ulFlowOutPin[ucPort],
                         g_ulFlowOutPin[ucPort]);
        }
    }
#endif

    // See if there is space to be filled in the transmit FIFO.
    if(((ulStatus & UART_INT_TX) != 0) || (ulStatus == 0))
    {
        bool fInMode = true;

        // Loop while there is space in the transmit FIFO and characters to be sent.
        while(!RingBufEmpty(&g_sTxBuf[ucPort]) && UARTSpaceAvail(g_ulUARTBase[ucPort]))
        {
            uint8_t ucChar = RingBufReadOne(&g_sTxBuf[ucPort]);

            if (fDataDebugFlag)
              CONSOLE("%u: to UART %02X\n", ucPort, ucChar);

            // Write the next character into the transmit FIFO.
            UARTCharPut(g_ulUARTBase[ucPort], ucChar);

            CustomerSettings1_SerialProcessCharacter(ucPort, ucChar);

            mcwUARTTxOut[ucPort]--;

            fInMode = false;
        }

        if((ulStatus & UART_INT_TX) != 0)
        {
          if ((mcwUARTTxOut[ucPort] == 0) && (fInMode)) {
              InMode(ucPort);
          }
        }
    }
}
예제 #2
0
파일: ringbuf.c 프로젝트: Azz1/RPI_EPI
//*****************************************************************************
//
//! Add bytes to the ring buffer by advancing the write index.
//!
//! \param ptRingBuf points to the ring buffer to which bytes have been added.
//! \param ulNumBytes is the number of bytes added to the buffer.
//!
//! This function should be used by clients who wish to add data to the buffer
//! directly rather than via calls to RingBufWrite() or RingBufWriteOne(). It
//! advances the write index by a given number of bytes.  If the \e ulNumBytes
//! parameter is larger than the amount of free space in the buffer, the
//! read pointer will be advanced to cater for the addition.  Note that this
//! will result in some of the oldest data in the buffer being discarded.
//!
//! \return None.
//
//*****************************************************************************
void
RingBufAdvanceWrite(tRingBufObject *ptRingBuf,
                    unsigned long ulNumBytes)
{
    unsigned long ulCount;
    tBoolean bIntsOff;

    //
    // Check the arguments.
    //
    ASSERT(ptRingBuf != NULL);

    //
    // Make sure we were not asked to add a silly number of bytes.
    //
    ASSERT(ulNumBytes <= ptRingBuf->ulSize);

    //
    // Determine how much free space we currently think the buffer has.
    //
    ulCount = RingBufFree(ptRingBuf);

    //
    // Advance the buffer write index by the required number of bytes and
    // check that we have not run past the read index. Note that we must do
    // this within a critical section (interrupts disabled) to prevent
    // race conditions that could corrupt one or other of the indices.
    //
    bIntsOff = IntMasterDisable();

    //
    // Update the write pointer.
    //
    ptRingBuf->ulWriteIndex += ulNumBytes;

    //
    // Check and correct for wrap.
    //
    if(ptRingBuf->ulWriteIndex >= ptRingBuf->ulSize)
    {
        ptRingBuf->ulWriteIndex -= ptRingBuf->ulSize;
    }

    //
    // Did the client add more bytes than the buffer had free space for?
    //
    if(ulCount < ulNumBytes)
    {
        //
        // Yes - we need to advance the read pointer to ahead of the write
        // pointer to discard some of the oldest data.
        //
        ptRingBuf->ulReadIndex = ptRingBuf->ulWriteIndex + 1;

        //
        // Correct for buffer wrap if necessary.
        //
        if(ptRingBuf->ulReadIndex >= ptRingBuf->ulSize)
        {
            ptRingBuf->ulReadIndex -= ptRingBuf->ulSize;
        }
    }

    //
    // Restore interrupts if we turned them off earlier.
    //
    if(!bIntsOff)
    {
        IntMasterEnable();
    }
}