⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ser2enet.c

📁 ARM CORTEX L3M6XXX CPU 以太网 lwip 源码
💻 C
📖 第 1 页 / 共 4 页
字号:

    //
    // See if the Ethernet receive interrupt occurred.
    //
    if(ulTemp & ETH_INT_RX)
    {
        //
        // Indicate that the Ethernet receive intererupt occurred.
        //
        HWREGBITW(&g_ulFlags, FLAG_RXPKT) = 1;

        //
        // Disable the receive interrupt.
        //
        EthernetIntDisable(ETH_BASE, ETH_INT_RX);
    }

    //
    // See if the Ethernet transmit interrupt occurred.
    //
    if(ulTemp & ETH_INT_TX)
    {
        //
        // Disable the transmit interrupt.
        //
        EthernetIntDisable(ETH_BASE, ETH_INT_TX);
    }
}

//*****************************************************************************
//
//! Handles the UART interrupt.
//!
//! This function is called when the UART generates 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.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    unsigned long ulStatus;
    unsigned char ucChar;

    //
    // Get the cause of the interrupt.
    //
    ulStatus = UARTIntStatus(UART0_BASE, true);

    //
    // Clear the cause of the interrupt.
    //
    UARTIntClear(UART0_BASE, 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(UART0_BASE))
        {
            //
            // Get the next character from the receive FIFO.
            //
            ucChar = UARTCharGet(UART0_BASE);

            //
            // See if this character is 0xff and there is space for two
            // characters in the receive FIFO.
            //
            if((ucChar == 0xff) &&
               (((g_ulRXWrite + 1) % UART_BUF_SIZE) != g_ulRXRead) &&
               (((g_ulRXWrite + 2) % UART_BUF_SIZE) != g_ulRXRead))
            {
                //
                // Write the 0xff into the receive FIFO twice since 0xff is the
                // interpret as command (IAC) byte for telnet, and a doubled
                // 0xff is interpreted as a single 0xff byte.
                //
                g_pucRXBuffer[g_ulRXWrite] = ucChar;
                g_ulRXWrite = (g_ulRXWrite + 1) % UART_BUF_SIZE;
                g_pucRXBuffer[g_ulRXWrite] = ucChar;
                g_ulRXWrite = (g_ulRXWrite + 1) % UART_BUF_SIZE;
            }

            //
            // See if the character is not 0xff adn there is space for a
            // character in the receive FIFO.
            //
            if((ucChar != 0xff) &&
               (((g_ulRXWrite + 1) % UART_BUF_SIZE) != g_ulRXRead))
            {
                g_pucRXBuffer[g_ulRXWrite] = ucChar;
                g_ulRXWrite = (g_ulRXWrite + 1) % UART_BUF_SIZE;
            }
        }

        //
        // Set a flag indicating that there are newly received characters that
        // need to be handled.
        //
        HWREGBITW(&g_ulFlags, FLAG_RXUART) = 1;
    }

    //
    // See if there is space to be filled in the transmit FIFO.
    //
    if(ulStatus & UART_INT_TX)
    {
        //
        // Loop while there is space in the transmit FIFO and characters to be
        // sent.
        //
        while((g_ulTXRead != g_ulTXWrite) && UARTSpaceAvail(UART0_BASE))
        {
            //
            // Write the next character into the transmit FIFO.
            //
            UARTCharPut(UART0_BASE, g_pucTXBuffer[g_ulTXRead]);

            //
            // Advance the read offset.
            //
            g_ulTXRead = (g_ulTXRead + 1) % UART_BUF_SIZE;
        }
    }
}

//*****************************************************************************
//
//! Sends a character to the UART.
//!
//! \param ucChar is the character to be sent.
//!
//! This function sends a character to the UART.  The character will either be
//! directly written into the UART FIFO or into the UART transmit buffer, as
//! appropriate.
//!
//! \return None.
//
//*****************************************************************************
static void
UARTSend(unsigned char ucChar)
{
    //
    // Disable the UART transmit interrupt while determining how to handle this
    // character.  Failure to do so could result in the loss of this character,
    // or stalled output due to this character being placed into the UART
    // transmit buffer but never transferred out into the UART FIFO.
    //
    UARTIntDisable(UART0_BASE, UART_INT_TX);

    //
    // See if the transmit buffer is empty and there is space in the FIFO.
    //
    if((g_ulTXRead == g_ulTXWrite) && UARTSpaceAvail(UART0_BASE))
    {
        //
        // Write this character directly into the FIFO.
        //
        UARTCharPut(UART0_BASE, ucChar);
    }

    //
    // See if there is room in the transmit buffer.
    //
    else if(((g_ulTXWrite + 1) % UART_BUF_SIZE) != g_ulTXRead)
    {
        //
        // Put this character into the transmit buffer.
        //
        g_pucTXBuffer[g_ulTXWrite] = ucChar;

        //
        // Increment the transmit buffer write pointer.
        //
        g_ulTXWrite = (g_ulTXWrite + 1) % UART_BUF_SIZE;
    }

    //
    // Enable the UART transmit interrupt.
    //
    UARTIntEnable(UART0_BASE, UART_INT_TX);
}

//*****************************************************************************
//
//! Closes an existing Ethernet connection.
//!
//! \param pcb is the pointer to the TCP control structure.
//!
//! This function is called when the the TCP connection should be closed.
//!
//! \return None.
//
//*****************************************************************************
static void
TelnetClose(struct tcp_pcb *pcb)
{
    //
    // Clear out all of the TCP callbacks.
    //
    tcp_arg(pcb, NULL);
    tcp_sent(pcb, NULL);
    tcp_recv(pcb, NULL);
    tcp_err(pcb, NULL);
    tcp_poll(pcb, NULL, 1);

    //
    // Clear the telnet data structure pointer, to indicate that
    // we are no longer connected.
    //
    g_psTelnetPCB = NULL;

    //
    // Close the TCP connection.
    //
    tcp_close(pcb);
}

//*****************************************************************************
//
//! Processes a telnet WILL request.
//!
//! \param ucOption is the telnet option in question.
//!
//! This function will handle a WILL request for a telnet option.  If it is an
//! option that is known by the telnet server, a DO response will be generated
//! if the option is not already enabled.  For unknown options, a DONT response
//! will always be generated.
//!
//! The response (if any) is written into the telnet transmit buffer.
//!
//! \return None.
//
//*****************************************************************************
static void
TelnetProcessWill(unsigned char ucOption)
{
    unsigned long ulIdx;

    //
    // Loop through the known options.
    //
    for(ulIdx = 0; ulIdx < (sizeof(g_psOptions) / sizeof(g_psOptions[0]));
        ulIdx++)
    {
        //
        // See if this option matches the option in question.
        //
        if(g_psOptions[ulIdx].ucOption == ucOption)
        {
            //
            // See if the WILL flag for this option has already been set.
            //
            if(HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_WILL) == 0)
            {
                //
                // Set the WILL flag for this option.
                //
                HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_WILL) = 1;

                //
                // Send a DO response to this option.
                //
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_IAC;
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_DO;
                g_pucTelnetBuffer[g_ulTelnetLength++] = ucOption;
            }

            //
            // Return without any further processing.
            //
            return;
        }
    }

    //
    // This option is not recognized, so send a DONT response.
    //
    g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_IAC;
    g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_DONT;
    g_pucTelnetBuffer[g_ulTelnetLength++] = ucOption;
}

//*****************************************************************************
//
//! Processes a telnet WONT request.
//!
//! \param ucOption is the telnet option in question.
//!
//! This function will handle a WONT request for a telnet option.  If it is an
//! option that is known by the telnet server, a DONT response will be
//! generated if the option is not already disabled.  For unknown options, a
//! DONT response will always be generated.
//!
//! The response (if any) is written into the telnet transmit buffer.
//!
//! \return None.
//
//*****************************************************************************
static void
TelnetProcessWont(unsigned char ucOption)
{
    unsigned long ulIdx;

    //
    // Loop through the known options.
    //
    for(ulIdx = 0; ulIdx < (sizeof(g_psOptions) / sizeof(g_psOptions[0]));
        ulIdx++)
    {
        //
        // See if this option matches the option in question.
        //
        if(g_psOptions[ulIdx].ucOption == ucOption)
        {
            //
            // See if the WILL flag for this option is currently set.
            //
            if(HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_WILL) == 1)
            {
                //
                // Clear the WILL flag for this option.
                //
                HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_WILL) = 0;

                //
                // Send a DONT response to this option.
                //
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_IAC;
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_DONT;
                g_pucTelnetBuffer[g_ulTelnetLength++] = ucOption;
            }

            //
            // Return without any further processing.
            //
            return;
        }
    }

    //
    // This option is not recognized, so send a DONT response.
    //
    g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_IAC;
    g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_DONT;
    g_pucTelnetBuffer[g_ulTelnetLength++] = ucOption;
}

//*****************************************************************************
//
//! Processes a telnet DO request.
//!
//! \param ucOption is the telnet option in question.
//!
//! This function will handle a DO request for a telnet optoin.  If it is an
//! option that is known by the telnet server, a WILL response will be
//! generated if the option is not already enabled.  For unknown options, a
//! WONT response will always be generated.
//!
//! The response (if any) is written into the telnet transmit buffer.
//!
//! \return None.
//
//*****************************************************************************
static void
TelnetProcessDo(unsigned char ucOption)
{
    unsigned long ulIdx;

    //
    // Loop through the known options.
    //
    for(ulIdx = 0; ulIdx < (sizeof(g_psOptions) / sizeof(g_psOptions[0]));
        ulIdx++)
    {
        //
        // See if this option matches the option in question.
        //
        if(g_psOptions[ulIdx].ucOption == ucOption)
        {
            //
            // See if the DO flag for this option has already been set.
            //
            if(HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_DO) == 0)
            {
                //
                // Set the DO flag for this option.
                //
                HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_DO) = 1;

                //
                // Send a WILL response to this option.
                //
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_IAC;
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_WILL;
                g_pucTelnetBuffer[g_ulTelnetLength++] = ucOption;
            }

            //
            // Return without any further processing.
            //
            return;
        }
    }

    //
    // This option is not recognized, so send a WONT response.
    //
    g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_IAC;
    g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_WONT;
    g_pucTelnetBuffer[g_ulTelnetLength++] = ucOption;
}

//*****************************************************************************
//
//! Processes a telnet DONT request.
//!
//! \param ucOption is the telnet option in question.
//!
//! This funciton will handle a DONT request for a telnet option.  If it is an
//! option that is known by the telnet server, a WONT response will be
//! generated if the option is not already disabled.  For unknown options, a
//! WONT resopnse will always be generated.
//!
//! The response (if any) is written into the telnet transmit buffer.
//!
//! \return None.
//
//*****************************************************************************
static void
TelnetProcessDont(unsigned char ucOption)
{
    unsigned long ulIdx;

    //
    // Loop through the known options.
    //
    for(ulIdx = 0; ulIdx < (sizeof(g_psOptions) / sizeof(g_psOptions[0]));
        ulIdx++)
    {
        //
        // See if this option matches the option in question.
        //
        if(g_psOptions[ulIdx].ucOption == ucOption)
        {
            //
            // See if the DO flag for this option is currently set.
            //
            if(HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_DO) == 1)
            {
                //
                // Clear the DO flag for this option.
                //
                HWREGBITB(&(g_psOptions[ulIdx].ucFlags), OPT_FLAG_DO) = 0;

                //
                // Send a WONT response to this option.
                //
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_IAC;
                g_pucTelnetBuffer[g_ulTelnetLength++] = TELNET_WONT;
                g_pucTelnetBuffer[g_ulTelnetLength++] = ucOption;
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -