📄 ser2enet.c
字号:
//*****************************************************************************
//
// ser2enet.c - Serial to Ethernet converter.
//
// Copyright (c) 2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 195 of the Serial to Ethernet Converter.
//
//*****************************************************************************
#include "../../hw_ints.h"
#include "../../hw_memmap.h"
#include "../../hw_types.h"
#include "../../src/ethernet.h"
#include "../../src/flash.h"
#include "../../src/gpio.h"
#include "../../src/interrupt.h"
#include "../../src/sysctl.h"
#include "../../src/systick.h"
#include "../../src/uart.h"
#include "lwip/api.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/opt.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#include "netif/etharp.h"
#include "config.h"
#include "luminaryif.h"
#include "telnet.h"
//*****************************************************************************
//
//! \page ser2enet_intro Introduction
//!
//! The Serial to Ethernet Converter provides a means of accessing the UART on
//! a Stellaris device via a network connection. The UART can be connected to
//! the UART on a non-networked device, providing the ability to access the
//! device via a network. This can be useful to overcome the cable length
//! limitations of a UART connection (in fact, the cable can become thousands
//! of miles long) and to provide networking capability to existing devices
//! without modifing the device's operation.
//!
//! The telnet protocol (as defined by RFC854) is used to make the connection
//! across the network. The Serial to Ethernet Converter provides the telnet
//! server, and a connection is made to the converter using a telnet client.
//! In its simplest form, a telnet client is simply a TCP connect to the
//! appropriate port. Telnet interprets 0xff as a command indicator (known as
//! the Interpret As Command, or IAC, byte). Consecutive IAC bytes are used to
//! transfer an actual 0xff byte; thus, the only special processing required is
//! to translate 0xff to 0xff 0xff when sending, and to translate 0xff 0xff to
//! 0xff when receiving.
//!
//! The WILL, WONT, DO, DONT option negotiation protocol is also imlpemented.
//! This is a simple means of determining if capabilities are present, and for
//! enabling or disabling features that do not require configuration. Through
//! the use of this negotiation protocol, telnet clients and servers are able
//! to easily match capabilities and avoid trying to configure features that
//! are not shared by both ends of the connection (which would therefore result
//! in the negotiation sequence being sent as actual data instead of being
//! absorbed by the client or server).
//!
//! In this implementation, only the SUPPRESS_GA option is supported; all other
//! options are negatively responded to in order to prevent the client from
//! trying to use them.
//!
//! The converter can be configured to use a static IP configuration or to use
//! DHCP to obtain its IP configuration. Since the converter is providing a
//! telnet server, the effective use of DHCP requires a reservation in the DHCP
//! server so that the converter gets the same IP address each time it is
//! connected to the network.
//
//*****************************************************************************
//*****************************************************************************
//
//! \defgroup ser2enet_api Definitions
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
//! The number of times per second that the SysTick timer generates a processor
//! interrupt.
//
//*****************************************************************************
#define SYSTICKHZ 100
//*****************************************************************************
//
//! The number of milliseconds between SysTick generated processor interrupts.
//
//*****************************************************************************
#define SYSTICKMS (1000 / SYSTICKHZ)
//*****************************************************************************
//
//! The bit in #g_ulFlags that indicates that a SysTick interrupt has occurred.
//
//*****************************************************************************
#define FLAG_SYSTICK 0
//*****************************************************************************
//
//! The bit in #g_ulFlags that indicates that an Ethernet controller interrupt
//! has occurred.
//
//*****************************************************************************
#define FLAG_RXPKT 1
//*****************************************************************************
//
//! The bit in #g_ulFlags that indicates that a UART receive interrupt has
//! occurred.
//
//*****************************************************************************
#define FLAG_RXUART 2
//*****************************************************************************
//
//! A set of flags that indicate the occurrence of interrupts. The bits in
//! this word are defined by #FLAG_SYSTICK, #FLAG_RXPKT, and #FLAG_RXUART.
//
//*****************************************************************************
static volatile unsigned long g_ulFlags;
//*****************************************************************************
//
//! The possible states of the telnet option parser.
//
//*****************************************************************************
typedef enum
{
//
//! The telnet option parser is in its normal mode. Characters are passed
//! as is until an IAC byte is received.
//
STATE_NORMAL,
//
//! The previous character received by the telnet option parser was an IAC
//! byte.
//
STATE_IAC,
//
//! The previous character sequence received by the telnet option parser
//! was IAC WILL.
//
STATE_WILL,
//
//! The previous character sequence received by the telnet option parser
//! was IAC WONT.
//
STATE_WONT,
//
//! The previous character sequence received by the telnet option parser
//! was IAC DO.
//
STATE_DO,
//
//! The previous character sequence received by the telnet option parser
//! was IAC DONT.
//
STATE_DONT
}
tTelnetState;
//*****************************************************************************
//
//! The current state of the telnet option parser.
//
//*****************************************************************************
static tTelnetState g_eState;
//*****************************************************************************
//
//! A structure that contains the state of the options supported by the telnet
//! server, along with the possible flags.
//
//*****************************************************************************
typedef struct
{
//
//! The option byte.
//
unsigned char ucOption;
//
//! The flags for this option. The bits in this byte are defined by
//! OPT_FLAG_WILL and OPT_FLAG_DO.
//
unsigned char ucFlags;
}
tTelnetOpts;
//*****************************************************************************
//
//! The bit in the ucFlags member of #tTelnetOpts that is set when the remote
//! client has sent a WILL request and the server has accepted it.
//
//*****************************************************************************
#define OPT_FLAG_WILL 1
//*****************************************************************************
//
//! The bit in the ucFlags member of #tTelnetOpts that is set when the remote
//! client has sent a DO request and the server has accepted it.
//
//*****************************************************************************
#define OPT_FLAG_DO 2
//*****************************************************************************
//
//! The telnet options supported by this server.
//
//*****************************************************************************
static tTelnetOpts g_psOptions[] =
{
//
// This telnet server will always suppress go ahead generation, regardless
// of this setting.
//
{ TELNET_OPT_SUPPRESS_GA, (1 << OPT_FLAG_WILL) },
};
//*****************************************************************************
//
//! The initialization sequence sent to a remote telnet client when it first
//! connects to the telnet server.
//
//*****************************************************************************
static const unsigned char g_pucTelnetInit[] =
{
TELNET_IAC, TELNET_DO, TELNET_OPT_SUPPRESS_GA
};
//*****************************************************************************
//
//! The lwIP network interface structure for the Stellaris Ethernet controller.
//
//*****************************************************************************
static struct netif g_sEMAC_if;
//*****************************************************************************
//
//! The lwIP TCP fast timer, used to determine the rate at which to call
//! tcp_fasttmr().
//
//*****************************************************************************
static unsigned long g_ulTCPFastTimer = 0;
//*****************************************************************************
//
//! The lwIP TCP slow timer, used to determine the rate at which to call
//! tcp_slowtimer().
//
//*****************************************************************************
static unsigned long g_ulTCPSlowTimer = 0;
//*****************************************************************************
//
//! The lwIP ARP timer, used to determine the rate at which to call
//! etharp_tmr().
//
//*****************************************************************************
static unsigned long g_ulARPTimer = 0;
//*****************************************************************************
//
//! The lwIP DHCP coarse timer, used to determine the rate at which to call
//! dhcp_coarse_tmr().
//
//*****************************************************************************
#if defined(USE_DHCP) || defined(DOXYGEN)
static unsigned long g_ulDHCPCoarseTimer = 0;
#endif
//*****************************************************************************
//
//! The lwIP DHCP fine timer, used to determine the rate at which to call
//! dhcp_fine_tmr().
//
//*****************************************************************************
#if defined(USE_DHCP) || defined(DOXYGEN)
static unsigned long g_ulDHCPFineTimer = 0;
#endif
//*****************************************************************************
//
//! The size of the buffers used for transmitting to and receiving from the
//! UART.
//
//*****************************************************************************
#define UART_BUF_SIZE 256
//*****************************************************************************
//
//! The buffer used to hold characters received from the UART.
//
//*****************************************************************************
static unsigned char g_pucRXBuffer[UART_BUF_SIZE];
//*****************************************************************************
//
//! The buffer used to hold characters to be sent to the UART.
//
//*****************************************************************************
static unsigned char g_pucTXBuffer[UART_BUF_SIZE];
//*****************************************************************************
//
//! The offset into the UART receive buffer (#g_pucRXBuffer) where the next
//! character is to be read. The buffer is empty when this is equal to the
//! write offset (#g_ulRXWrite), and is full when the write offset is one
//! character behind the read offset (modulo the buffer size).
//
//*****************************************************************************
static unsigned long g_ulRXRead;
//*****************************************************************************
//
//! The offset into the UART receive buffer (#g_pucRXBuffer) where the next
//! character is to be written. The buffer is empty when this is equal to the
//! read offset (#g_ulRXRead), and is full when the write offset is one
//! character behind the read offset (modulo the buffer size).
//
//*****************************************************************************
static unsigned long g_ulRXWrite;
//*****************************************************************************
//
//! The offset into the UART transmit buffer (#g_pucTXBuffer) where the next
//! character is to be read. The buffer is empty when this is equal to the
//! write offset (#g_ulTXWrite), and is full when the write offset is one
//! character behind the read offset (modulo the buffer size).
//
//*****************************************************************************
static unsigned long g_ulTXRead;
//*****************************************************************************
//
//! The offset into the UART transmit buffer (#g_pucTXBuffer) where the next
//! character is to be written. The buffer is empty when this is equal to the
//! read offset (#g_ulTXRead), and is full when the write offset is one
//! character behind the read offset (modulo the buffer size).
//
//*****************************************************************************
static unsigned long g_ulTXWrite;
//*****************************************************************************
//
//! A buffer used to construct a packet of data to be transmitted to the telnet
//! client.
//
//*****************************************************************************
static unsigned char g_pucTelnetBuffer[512];
//*****************************************************************************
//
//! The number of bytes of valid data in the telnet packet buffer
//! (#g_pucTelnetBuffer).
//
//*****************************************************************************
static unsigned long g_ulTelnetLength;
//*****************************************************************************
//
//! A pointer to the telnet session PCB data structure.
//
//*****************************************************************************
static struct tcp_pcb *g_psTelnetPCB = NULL;
//*****************************************************************************
//
//! A counter for the TCP connection timeout.
//
//*****************************************************************************
#if TELNET_TIMEOUT || defined(DOXYGEN)
static unsigned long g_ulConnectionTimeout;
#endif
//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif
//*****************************************************************************
//
//! Handles the SysTick interrupt.
//!
//! This function is called when the SysTick timer expires. It increments the
//! lwIP timers and sets a flag indicating that the timeout functions need to
//! be called if necessary.
//!
//! \return None.
//
//*****************************************************************************
void
SysTickIntHandler(void)
{
//
// Increment the assorted timers.
//
g_ulTCPFastTimer += SYSTICKMS;
g_ulTCPSlowTimer += SYSTICKMS;
g_ulARPTimer += SYSTICKMS;
#ifdef USE_DHCP
g_ulDHCPCoarseTimer += SYSTICKMS;
g_ulDHCPFineTimer += SYSTICKMS;
#endif
//
// Indicate that a SysTick has occurred.
//
HWREGBITW(&g_ulFlags, FLAG_SYSTICK) = 1;
}
//*****************************************************************************
//
//! Handles the Ethernet interrupt.
//!
//! This function is called when the Ethernet controller generates an interrupt
//! as a result of the reception of a packet. It sets a flag indicating that
//! lwIP should read the packet when possible.
//!
//! \return None.
//
//*****************************************************************************
void
EthernetIntHandler(void)
{
unsigned long ulTemp;
//
// Read and clear the interrupt(s).
//
ulTemp = EthernetIntStatus(ETH_BASE, false);
EthernetIntClear(ETH_BASE, ulTemp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -