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