示例#1
0
//*****************************************************************************
//
//! Reads data from a ring buffer.
//!
//! \param ptRingBuf points to the ring buffer to be read from.
//! \param pucData points to where the data should be stored.
//! \param ulLength is the number of bytes to be read.
//!
//! This function reads a sequence of bytes from a ring buffer.
//!
//! \return None.
//
//*****************************************************************************
void
RingBufRead(tRingBufObject *ptRingBuf, unsigned char *pucData,
               unsigned long ulLength)
{
    unsigned long ulTemp;

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

    //
    // Verify that data is available in the buffer.
    //
    ASSERT(ulLength <= RingBufUsed(ptRingBuf));

    //
    // Read the data from the ring buffer.
    //
    for(ulTemp = 0; ulTemp < ulLength; ulTemp++)
    {
        pucData[ulTemp] = RingBufReadOne(ptRingBuf);
    }
}
示例#2
0
//*****************************************************************************
//
//! Reads data from a ring buffer.
//!
//! \param psRingBuf points to the ring buffer to be read from.
//! \param pui8Data points to where the data should be stored.
//! \param ui32Length is the number of bytes to be read.
//!
//! This function reads a sequence of bytes from a ring buffer.
//!
//! \return None.
//
//*****************************************************************************
void
RingBufRead(tRingBufObject *psRingBuf, uint8_t *pui8Data, uint32_t ui32Length)
{
    uint32_t ui32Temp;

    //
    // Check the arguments.
    //
    ASSERT(psRingBuf != NULL);
    ASSERT(pui8Data != NULL);
    ASSERT(ui32Length != 0);

    //
    // Verify that data is available in the buffer.
    //
    ASSERT(ui32Length <= RingBufUsed(psRingBuf));

    //
    // Read the data from the ring buffer.
    //
    for(ui32Temp = 0; ui32Temp < ui32Length; ui32Temp++)
    {
        pui8Data[ui32Temp] = RingBufReadOne(psRingBuf);
    }
}
示例#3
0
//*****************************************************************************
//
// Puts a UART message on the line to the RNP.
//
// \param pui8Msg pointer to the data that will be put on the bus. Must be
// already formated with SOF, length and checksum by the caller.
//
// \param ui16Length the number of bytes that are to be put out the UART.
//
// This function copies the message to the ring buffer and then starts a
// transmission process. Application must assure that transmitter is not busy.
//
//*****************************************************************************
void
RemoTIUARTPutMsg(uint8_t* pui8Msg, uint_fast16_t ui16Length)
{
    bool bIntState;

    //
    // Capture the current state of the master interrupt enable.
    //
    bIntState = IntMasterDisable();

    //
    // Store the message in the ringbuffer for transmission.
    //
    RingBufWrite(&g_rbRemoTITxRingBuf, pui8Msg, ui16Length);

    //
    // If the UART transmit is idle prime the transmitter with first byte and.
    // enable transmit interrupts.
    //
    if(!g_bTxBusy)
    {
        //
        // Enable the TX interrupts and start the transmission of the first
        // byte.
        //
        UARTIntEnable(g_ui32UARTBase, UART_INT_TX);
        UARTCharPutNonBlocking(g_ui32UARTBase,
                               RingBufReadOne(&g_rbRemoTITxRingBuf));

        //
        // Set the Transmit busy flag.
        //
        g_bTxBusy = true;
    }

    //
    // Restore the master interrupt enable to its previous state.
    //
    if(!bIntState)
    {
        IntMasterEnable();
    }

    //
    // Finished.
    //
}
// UART interrupt handler
// For each received byte, pushes it into the buffer.
// For each transmitted byte, read the next available from the buffer.
void USART2_IRQHandler()
{
  // TX the next available char on the buffer
  if (USART_GetITStatus(USART2, USART_IT_TC))
  {
    USART_ClearITPendingBit(USART2, USART_IT_TC);
    if (RingBufUsed(&txBuffer))
      USART_SendData(USART2, (uint8_t)RingBufReadOne(&txBuffer));
  }

  // RX and copy the data to buffer
  if (USART_GetITStatus(USART2, USART_IT_RXNE))
  {
    if (!RingBufFull(&rxBuffer))
    {
      RingBufWriteOne(&rxBuffer, (uint8_t)USART_ReceiveData(USART2));
    }
  }
}
示例#5
0
//*****************************************************************************
//
// UART interrupt handler.
//
// This is the interrupt handler for the UART interrupts from the UART
// peripheral that has been associated with the remote network processor.
//
// \return None.
//*****************************************************************************
void
RemoTIUARTIntHandler(void)
{
    uint8_t ui8TxByte;

    //
    // Process all available interrupts while we are in this routine.
    //
    do
    {
        //
        // Check if a receive interrupt is pending.
        //
        if(UARTIntStatus(g_ui32UARTBase, 1) & UART_INT_RX)
        {
            //
            // A char was receieved, process it
            // Do this first so it does not get overwritten by future bytes.
            //
            RemoTIUARTRxHandler();
            UARTIntClear(g_ui32UARTBase, UART_INT_RX);

        }

        //
        // Check if a transmit interrupt is pending.
        //
        if(UARTIntStatus(g_ui32UARTBase, 1) & UART_INT_TX)
        {
            //
            // A byte transmission completed so load another byte or turn off
            // tx interrupts.
            //
            if(RingBufUsed(&g_rbRemoTITxRingBuf))
            {
                //
                // We still have more stuff to transfer so read the next byte
                // from the buffer and load it into the UART. Finally clear
                // the pending interrupt status.
                //
                ui8TxByte = RingBufReadOne(&g_rbRemoTITxRingBuf);
                UARTCharPutNonBlocking(g_ui32UARTBase, ui8TxByte);
                UARTIntClear(g_ui32UARTBase, UART_INT_TX);
            }
            else
            {
                //
                // Transmission is complete the internal buffer is empty.
                // Therefore, disable TX interrupts until next transmit is
                // started by the user.
                //
                UARTIntDisable(g_ui32UARTBase, UART_INT_TX);
                UARTIntClear(g_ui32UARTBase, UART_INT_TX);

                //
                // Clear the transmitter busy flag.
                //
                g_bTxBusy = false;

                //
                // callback to the TX Complete callback function
                //
                if(g_pfnTxCallback)
                {
                    g_pfnTxCallback(0);
                }
            }
        }
    //
    // Continue to process the interrupts until there are no more pending.
    //
    }while(UARTIntStatus(g_ui32UARTBase, 1) & (UART_INT_RX | UART_INT_TX));

    //
    // Finished.
    //
}
示例#6
0
//*****************************************************************************
//
// Gets a message from the UART buffer.
//
// \param pui8Msg is a pointer to storage allocated by the caller where the
// message will be copied to.
//
// \param ui16Length is the length of the pui8Msg buffer.
//
// Copies a message from the UART buffer to the \e pui8Msg caller supplied
// storage.  If the caller supplied storage length is less than the next
// UART message length then the UART message is dumped and no data is returned.
// Therefore it is critical to make sure that caller supplies sufficient length
// for the longest anticipated message from the RNP.  256 bytes is recommended.
//
// \return None.
//
//*****************************************************************************
void
RemoTIUARTGetMsg(uint8_t* pui8Msg, uint_fast16_t ui16Length)
{
    bool bIntState;
    uint8_t ui8MsgLength;
    uint8_t ui8SOF;

    //
    // State previous state of master interrupt enable then disable all
    // interrupts.
    //
    bIntState = IntMasterDisable();

    //
    // Determine if a message is in the buffer available for the caller.
    //
    if(g_ui16RxMsgCount != 0)
    {
       //
       // Read out the SOF and Msg Length characters.
       //
       ui8SOF = RingBufReadOne(&g_rbRemoTIRxRingBuf);
       ui8MsgLength = RingBufReadOne(&g_rbRemoTIRxRingBuf);

       //
       // Make sure that the user buffer has room for the message and the
       // packet overhead bytes.
       //
       if((ui8MsgLength + 5) <= ui16Length)
       {
           //
           // We have enough room, so store the two already bytes in the user
           // buffer.
           //
           pui8Msg[0] = ui8SOF;
           pui8Msg[1] = ui8MsgLength;

           //
           // Read the remaining bytes to the user buffer.
           //
           RingBufRead(&g_rbRemoTIRxRingBuf, pui8Msg + 2, ui8MsgLength + 3);

       }
       else
       {
           //
           // The user did not provide enough room and we cannot easily put
           // the first couple of bytes back into the buffer.  Therefore,
           // we dump the remainder of the message.
           //
           RingBufAdvanceRead(&g_rbRemoTIRxRingBuf, ui8MsgLength + 3);
       }

       //
       // Decrement the msg counter. Now one less message in the UART buffer.
       //
       g_ui16RxMsgCount -= 1;
    }

    //
    // Restore the master interrupt enable state.
    //
    if(!bIntState)
    {
        IntMasterEnable();
    }

    //
    // Finished.
    //
}
//*****************************************************************************
//! 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);
          }
        }
    }
}