refactor: 完成R8裸机lwIP移植并更新文档
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
* Modified for STM32F103 HAL Library with FreeRTOS support.
|
||||
******************************************************************************/
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include "main.h"
|
||||
#include "CH390.h"
|
||||
#include "CH390_Interface.h"
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ typedef int16_t s16_t;
|
||||
typedef uint32_t u32_t;
|
||||
typedef int32_t s32_t;
|
||||
|
||||
typedef uint32_t sys_prot_t;
|
||||
|
||||
typedef uintptr_t mem_ptr_t;
|
||||
|
||||
/* Byte order - ARM Cortex-M is little endian */
|
||||
@@ -62,15 +64,12 @@ typedef uintptr_t mem_ptr_t;
|
||||
|
||||
/* Platform specific diagnostic output */
|
||||
#ifndef LWIP_PLATFORM_DIAG
|
||||
#define LWIP_PLATFORM_DIAG(x) do { printf x; } while(0)
|
||||
#define LWIP_PLATFORM_DIAG(x) do { } while(0)
|
||||
#endif
|
||||
|
||||
/* Platform specific assertion handling */
|
||||
#ifndef LWIP_PLATFORM_ASSERT
|
||||
#define LWIP_PLATFORM_ASSERT(x) do { \
|
||||
printf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); \
|
||||
while(1); \
|
||||
} while(0)
|
||||
#define LWIP_PLATFORM_ASSERT(x) do { while(1) { } } while(0)
|
||||
#endif
|
||||
|
||||
/* Get current time in milliseconds (provided by sys_arch.c) */
|
||||
|
||||
@@ -1,201 +1,77 @@
|
||||
/**
|
||||
* @file lwipopts.h
|
||||
* @brief LwIP configuration for STM32F103 + FreeRTOS + CH390 Ethernet
|
||||
*
|
||||
* This configuration is optimized for:
|
||||
* - STM32F103 with limited RAM (~20KB available)
|
||||
* - FreeRTOS integration (NO_SYS=0)
|
||||
* - TCP Server + Client dual link transparent transmission
|
||||
* - CH390 Ethernet controller
|
||||
* @brief lwIP configuration for STM32F103 + CH390 in NO_SYS mode.
|
||||
*/
|
||||
|
||||
#ifndef LWIP_LWIPOPTS_H
|
||||
#define LWIP_LWIPOPTS_H
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Platform and OS Options
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Use FreeRTOS - this enables the sequential API (netconn, sockets) */
|
||||
#define NO_SYS 0
|
||||
|
||||
/* Enable socket API */
|
||||
#define LWIP_SOCKET 1
|
||||
#define LWIP_NETCONN 1
|
||||
#define NO_SYS 1
|
||||
#define LWIP_SOCKET 0
|
||||
#define LWIP_NETCONN 0
|
||||
#define LWIP_NETIF_API 0
|
||||
|
||||
/* Critical section protection */
|
||||
#define SYS_LIGHTWEIGHT_PROT 1
|
||||
#define LWIP_PROVIDE_ERRNO 0
|
||||
|
||||
/* Use FreeRTOS memory allocation */
|
||||
#define MEM_LIBC_MALLOC 0
|
||||
#define MEMP_MEM_MALLOC 0
|
||||
|
||||
/* Let lwIP provide the errno values used by sockets/netconn. */
|
||||
#define LWIP_PROVIDE_ERRNO 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Memory Configuration (optimized for STM32F103 with ~20KB RAM)
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Memory alignment (ARM Cortex-M3 = 4 byte alignment) */
|
||||
#define MEM_ALIGNMENT 4
|
||||
#define MEM_SIZE (4 * 1024)
|
||||
|
||||
/* Heap size for dynamic memory allocation */
|
||||
#define MEM_SIZE (4 * 1024) /* 4KB for LwIP heap */
|
||||
|
||||
/* Number of pbufs in pool */
|
||||
#define PBUF_POOL_SIZE 8
|
||||
|
||||
/* Size of each pbuf in pool (must hold one Ethernet frame) */
|
||||
#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)
|
||||
|
||||
/* Number of memp struct pbufs */
|
||||
#define MEMP_NUM_PBUF 8
|
||||
|
||||
/* Number of raw PCBs */
|
||||
#define MEMP_NUM_RAW_PCB 2
|
||||
|
||||
/* Number of UDP PCBs */
|
||||
#define MEMP_NUM_UDP_PCB 4
|
||||
|
||||
/* Number of simultaneously active TCP connections */
|
||||
#define MEMP_NUM_UDP_PCB 1
|
||||
#define MEMP_NUM_TCP_PCB 4
|
||||
|
||||
/* Number of listening TCP connections */
|
||||
#define MEMP_NUM_TCP_PCB_LISTEN 2
|
||||
|
||||
/* Number of simultaneously queued TCP segments */
|
||||
#define MEMP_NUM_TCP_SEG 17
|
||||
|
||||
/* Number of simultaneously active timeouts */
|
||||
#define MEMP_NUM_TCP_SEG 16
|
||||
#define MEMP_NUM_SYS_TIMEOUT 8
|
||||
|
||||
/* Number of netbufs (for sequential API) */
|
||||
#define MEMP_NUM_NETBUF 4
|
||||
|
||||
/* Number of netconns */
|
||||
#define MEMP_NUM_NETCONN 6
|
||||
|
||||
/* TCPIP message queue size */
|
||||
#define MEMP_NUM_TCPIP_MSG_API 8
|
||||
#define MEMP_NUM_TCPIP_MSG_INPKT 8
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* IP Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define MEMP_NUM_NETBUF 0
|
||||
#define MEMP_NUM_NETCONN 0
|
||||
#define MEMP_NUM_TCPIP_MSG_API 0
|
||||
#define MEMP_NUM_TCPIP_MSG_INPKT 0
|
||||
|
||||
#define LWIP_IPV4 1
|
||||
#define LWIP_IPV6 0
|
||||
|
||||
/* No IP forwarding (single interface device) */
|
||||
#define IP_FORWARD 0
|
||||
|
||||
/* IP fragment reassembly */
|
||||
#define IP_REASSEMBLY 0
|
||||
#define IP_FRAG 0
|
||||
|
||||
/* IP options processing */
|
||||
#define IP_OPTIONS_ALLOWED 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* ICMP Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_ICMP 1
|
||||
#define ICMP_TTL 255
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* ARP Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_ARP 1
|
||||
#define ARP_TABLE_SIZE 10
|
||||
#define ARP_QUEUEING 1
|
||||
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* DHCP Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_DHCP 1
|
||||
#define LWIP_DHCP 0
|
||||
#define DHCP_DOES_ARP_CHECK 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* UDP Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_UDP 1
|
||||
#define UDP_TTL 255
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* TCP Configuration (optimized for transparent transmission)
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_UDP 0
|
||||
#define LWIP_TCP 1
|
||||
#define TCP_TTL 255
|
||||
|
||||
/* TCP Maximum Segment Size */
|
||||
#define TCP_MSS 536 /* Conservative value for compatibility */
|
||||
|
||||
/* TCP sender buffer space (bytes) */
|
||||
#define TCP_SND_BUF (4 * TCP_MSS)
|
||||
|
||||
/* TCP sender buffer space (pbufs) */
|
||||
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
|
||||
|
||||
/* TCP receive window */
|
||||
#define TCP_WND (4 * TCP_MSS)
|
||||
|
||||
/* TCP writable space threshold */
|
||||
#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1)
|
||||
|
||||
/* Enable TCP keepalive */
|
||||
#define LWIP_TCP_KEEPALIVE 1
|
||||
|
||||
/* TCP segment queue handling */
|
||||
#define TCP_QUEUE_OOSEQ 0 /* Disable out-of-order segment queuing to save RAM */
|
||||
|
||||
/* Maximum number of retransmissions */
|
||||
#define TCP_MAXRTX 12
|
||||
#define TCP_SYNMAXRTX 6
|
||||
|
||||
/* TCP listen backlog */
|
||||
#define TCP_LISTEN_BACKLOG 1
|
||||
|
||||
/* TCP timestamp option */
|
||||
#define LWIP_TCP_TIMESTAMPS 0
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* RAW API (used for ping, etc.)
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_RAW 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* DNS Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define TCP_TTL 255
|
||||
#define UDP_TTL 255
|
||||
#define ICMP_TTL 255
|
||||
|
||||
#define LWIP_DNS 0 /* Disable DNS to save RAM */
|
||||
#define TCP_MSS 536
|
||||
#define TCP_SND_BUF (4 * TCP_MSS)
|
||||
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
|
||||
#define TCP_WND (4 * TCP_MSS)
|
||||
#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1)
|
||||
#define LWIP_TCP_KEEPALIVE 1
|
||||
#define TCP_QUEUE_OOSEQ 0
|
||||
#define TCP_MAXRTX 12
|
||||
#define TCP_SYNMAXRTX 6
|
||||
#define TCP_LISTEN_BACKLOG 1
|
||||
#define LWIP_TCP_TIMESTAMPS 0
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* IGMP Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define LWIP_DNS 0
|
||||
#define LWIP_IGMP 0
|
||||
|
||||
#define LWIP_IGMP 0 /* Disable IGMP to save RAM */
|
||||
#define LWIP_NETIF_STATUS_CALLBACK 0
|
||||
#define LWIP_NETIF_LINK_CALLBACK 0
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Callback Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Checksum Configuration
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Use software checksums (CH390 doesn't have checksum offload) */
|
||||
#define CHECKSUM_GEN_IP 1
|
||||
#define CHECKSUM_GEN_UDP 1
|
||||
#define CHECKSUM_GEN_TCP 1
|
||||
@@ -205,106 +81,20 @@
|
||||
#define CHECKSUM_CHECK_TCP 1
|
||||
#define CHECKSUM_CHECK_ICMP 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Statistics (disabled to save RAM)
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_STATS 0
|
||||
#define LWIP_STATS_DISPLAY 0
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Debug Options (disabled for production)
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_DEBUG 0
|
||||
|
||||
#if LWIP_DEBUG
|
||||
#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL
|
||||
#define LWIP_DBG_TYPES_ON LWIP_DBG_ON
|
||||
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
#define IGMP_DEBUG LWIP_DBG_OFF
|
||||
#define INET_DEBUG LWIP_DBG_OFF
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||
#define RAW_DEBUG LWIP_DBG_OFF
|
||||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
#define SYS_DEBUG LWIP_DBG_OFF
|
||||
#define TIMERS_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FreeRTOS Specific Options
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Task stack sizes */
|
||||
#define TCPIP_THREAD_STACKSIZE 512
|
||||
#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 2)
|
||||
|
||||
#define DEFAULT_THREAD_STACKSIZE 256
|
||||
#define DEFAULT_THREAD_PRIO (configMAX_PRIORITIES - 3)
|
||||
|
||||
/* Mailbox sizes */
|
||||
#define TCPIP_MBOX_SIZE 8
|
||||
#define DEFAULT_RAW_RECVMBOX_SIZE 4
|
||||
#define DEFAULT_UDP_RECVMBOX_SIZE 4
|
||||
#define DEFAULT_TCP_RECVMBOX_SIZE 8
|
||||
#define DEFAULT_ACCEPTMBOX_SIZE 4
|
||||
|
||||
/* Thread name length */
|
||||
#define LWIP_NETCONN_SEM_PER_THREAD 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Ethernet Specific
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Ethernet MTU */
|
||||
#define LWIP_ETHERNET 1
|
||||
|
||||
/* Link layer header overhead */
|
||||
#define PBUF_LINK_HLEN 14 /* Ethernet header size */
|
||||
#define PBUF_LINK_HLEN 14
|
||||
#define PBUF_LINK_ENCAPSULATION_HLEN 0
|
||||
#define LWIP_NETIF_HOSTNAME 0
|
||||
|
||||
/* Use static Ethernet address (configured at runtime) */
|
||||
#define LWIP_NETIF_HOSTNAME 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Socket Options
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define LWIP_SO_SNDTIMEO 1
|
||||
#define LWIP_SO_RCVTIMEO 1
|
||||
#define LWIP_SO_RCVBUF 0
|
||||
#define SO_REUSE 1
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Additional Options
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Enable loop interface for testing */
|
||||
#define LWIP_HAVE_LOOPIF 0
|
||||
#define LWIP_NETIF_LOOPBACK 0
|
||||
#define LWIP_TIMERS 1
|
||||
#define LWIP_TIMERS_CUSTOM 0
|
||||
|
||||
/* Random number generator (required for some TCP operations) */
|
||||
#define LWIP_RAND() ((uint32_t)rand())
|
||||
|
||||
#endif /* LWIP_LWIPOPTS_H */
|
||||
#endif
|
||||
|
||||
@@ -1,90 +1,28 @@
|
||||
/**
|
||||
* @file sys_arch.h
|
||||
* @brief LwIP system architecture for FreeRTOS
|
||||
* @brief Minimal sys_arch definitions for lwIP NO_SYS mode.
|
||||
*/
|
||||
|
||||
#ifndef __SYS_ARCH_H__
|
||||
#define __SYS_ARCH_H__
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
#include "lwip/arch.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
typedef uint32_t sys_prot_t;
|
||||
|
||||
sys_prot_t sys_arch_protect(void);
|
||||
void sys_arch_unprotect(sys_prot_t pval);
|
||||
|
||||
#ifndef SYS_ARCH_DECL_PROTECT
|
||||
#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev
|
||||
#endif
|
||||
|
||||
/* Semaphore type */
|
||||
typedef SemaphoreHandle_t sys_sem_t;
|
||||
|
||||
/* Mutex type */
|
||||
typedef SemaphoreHandle_t sys_mutex_t;
|
||||
|
||||
/* Mailbox (message queue) type */
|
||||
typedef QueueHandle_t sys_mbox_t;
|
||||
|
||||
/* Thread type */
|
||||
typedef TaskHandle_t sys_thread_t;
|
||||
|
||||
/* Protection level type */
|
||||
typedef u32_t sys_prot_t;
|
||||
|
||||
/* Null values */
|
||||
#define SYS_SEM_NULL ((sys_sem_t)NULL)
|
||||
#define SYS_MBOX_NULL ((sys_mbox_t)NULL)
|
||||
#define SYS_MUTEX_NULL ((sys_mutex_t)NULL)
|
||||
|
||||
/* Use one per-thread semaphore for lwIP netconn/socket API calls. */
|
||||
#define LWIP_NETCONN_THREAD_SEM_TLS_INDEX 0
|
||||
#define LWIP_NETCONN_THREAD_SEM_GET() \
|
||||
((sys_sem_t *)pvTaskGetThreadLocalStoragePointer(NULL, LWIP_NETCONN_THREAD_SEM_TLS_INDEX))
|
||||
#define LWIP_NETCONN_THREAD_SEM_ALLOC() \
|
||||
do { \
|
||||
sys_sem_t *sem = (sys_sem_t *)mem_malloc(sizeof(sys_sem_t)); \
|
||||
if (sem != NULL) { \
|
||||
*sem = SYS_SEM_NULL; \
|
||||
if (sys_sem_new(sem, 0) == ERR_OK) { \
|
||||
vTaskSetThreadLocalStoragePointer(NULL, \
|
||||
LWIP_NETCONN_THREAD_SEM_TLS_INDEX,\
|
||||
sem); \
|
||||
} else { \
|
||||
mem_free(sem); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#define LWIP_NETCONN_THREAD_SEM_FREE() \
|
||||
do { \
|
||||
sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); \
|
||||
if (sem != NULL) { \
|
||||
sys_sem_free(sem); \
|
||||
mem_free(sem); \
|
||||
vTaskSetThreadLocalStoragePointer(NULL, \
|
||||
LWIP_NETCONN_THREAD_SEM_TLS_INDEX, \
|
||||
NULL); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Check if semaphore/mbox is valid */
|
||||
#define sys_sem_valid(sem) ((sem) != NULL && (*(sem)) != SYS_SEM_NULL)
|
||||
#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = SYS_SEM_NULL; } } while(0)
|
||||
|
||||
#define sys_mbox_valid(mbox) ((mbox) != NULL && (*(mbox)) != SYS_MBOX_NULL)
|
||||
#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = SYS_MBOX_NULL; } } while(0)
|
||||
|
||||
#define sys_mutex_valid(mutex) ((mutex) != NULL && (*(mutex)) != SYS_MUTEX_NULL)
|
||||
#define sys_mutex_set_invalid(mutex) do { if ((mutex) != NULL) { *(mutex) = SYS_MUTEX_NULL; } } while(0)
|
||||
|
||||
/* System initialization */
|
||||
void sys_init(void);
|
||||
|
||||
/* Get current time in milliseconds */
|
||||
u32_t sys_now(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#ifndef SYS_ARCH_PROTECT
|
||||
#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect()
|
||||
#endif
|
||||
|
||||
#endif /* __SYS_ARCH_H__ */
|
||||
#ifndef SYS_ARCH_UNPROTECT
|
||||
#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,23 +5,17 @@
|
||||
|
||||
extern struct netif ch390_netif;
|
||||
|
||||
/**
|
||||
* Helper struct to hold private data used to operate your ethernet interface.
|
||||
* Keeping the ethernet address of the MAC in this struct is not necessary
|
||||
* as it is already kept in the struct netif.
|
||||
* But this is only an example, anyway...
|
||||
*/
|
||||
struct ethernetif {
|
||||
// struct eth_addr *ethaddr;
|
||||
/* Add whatever per-interface state that is needed here. */
|
||||
uint16_t rx_len;
|
||||
uint8_t rx_status;
|
||||
};
|
||||
|
||||
void init_lwip_netif(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw);
|
||||
void lwip_netif_init(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw);
|
||||
err_t ethernetif_init(struct netif *netif);
|
||||
void ethernetif_input(struct netif *netif);
|
||||
void ethernetif_check_link(void);
|
||||
void ethernetif_poll(void);
|
||||
void ethernetif_set_irq_pending(void);
|
||||
uint8_t ethernetif_is_irq_pending(void);
|
||||
|
||||
void print_netif(struct netif *netif);
|
||||
|
||||
#endif /* _ETHERNETIF_H_ */
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* @file
|
||||
* Ethernet common functions
|
||||
*
|
||||
* @defgroup ethernet Ethernet
|
||||
* @ingroup callbackstyle_api
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_ARP || LWIP_ETHERNET
|
||||
|
||||
#include "netif/ethernet.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "netif/ppp/ppp_opts.h"
|
||||
#if PPPOE_SUPPORT
|
||||
#include "netif/ppp/pppoe.h"
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_HOOK_FILENAME
|
||||
#include LWIP_HOOK_FILENAME
|
||||
#endif
|
||||
|
||||
const struct eth_addr ethbroadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||||
const struct eth_addr ethzero = {{0, 0, 0, 0, 0, 0}};
|
||||
|
||||
err_t ethernet_input(struct pbuf *p, struct netif *netif)
|
||||
{
|
||||
struct eth_hdr *ethhdr;
|
||||
u16_t type;
|
||||
#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6
|
||||
u16_t next_hdr_offset = SIZEOF_ETH_HDR;
|
||||
#endif
|
||||
|
||||
LWIP_ASSERT_CORE_LOCKED();
|
||||
|
||||
if (p->len <= SIZEOF_ETH_HDR) {
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
MIB2_STATS_NETIF_INC(netif, ifinerrors);
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
type = ethhdr->type;
|
||||
|
||||
#if ETHARP_SUPPORT_VLAN
|
||||
if (type == PP_HTONS(ETHTYPE_VLAN)) {
|
||||
struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethhdr) + SIZEOF_ETH_HDR);
|
||||
next_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
|
||||
if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
MIB2_STATS_NETIF_INC(netif, ifinerrors);
|
||||
goto free_and_return;
|
||||
}
|
||||
type = vlan->tpid;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LWIP_ARP_FILTER_NETIF
|
||||
netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type));
|
||||
#endif
|
||||
|
||||
if (p->if_idx == NETIF_NO_INDEX) {
|
||||
p->if_idx = netif_get_index(netif);
|
||||
}
|
||||
|
||||
if (ethhdr->dest.addr[0] & 1) {
|
||||
if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) {
|
||||
#if LWIP_IPV4
|
||||
if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) &&
|
||||
(ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) {
|
||||
p->flags |= PBUF_FLAG_LLMCAST;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) &&
|
||||
(ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) {
|
||||
p->flags |= PBUF_FLAG_LLMCAST;
|
||||
}
|
||||
#endif
|
||||
else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) {
|
||||
p->flags |= PBUF_FLAG_LLBCAST;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
#if LWIP_IPV4 && LWIP_ARP
|
||||
case PP_HTONS(ETHTYPE_IP):
|
||||
if (!(netif->flags & NETIF_FLAG_ETHARP)) {
|
||||
goto free_and_return;
|
||||
}
|
||||
if (pbuf_remove_header(p, next_hdr_offset)) {
|
||||
goto free_and_return;
|
||||
} else {
|
||||
ip4_input(p, netif);
|
||||
}
|
||||
break;
|
||||
|
||||
case PP_HTONS(ETHTYPE_ARP):
|
||||
if (!(netif->flags & NETIF_FLAG_ETHARP)) {
|
||||
goto free_and_return;
|
||||
}
|
||||
if (pbuf_remove_header(p, next_hdr_offset)) {
|
||||
ETHARP_STATS_INC(etharp.lenerr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
goto free_and_return;
|
||||
} else {
|
||||
etharp_input(p, netif);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if PPPOE_SUPPORT
|
||||
case PP_HTONS(ETHTYPE_PPPOEDISC):
|
||||
pppoe_disc_input(netif, p);
|
||||
break;
|
||||
|
||||
case PP_HTONS(ETHTYPE_PPPOE):
|
||||
pppoe_data_input(netif, p);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if LWIP_IPV6
|
||||
case PP_HTONS(ETHTYPE_IPV6):
|
||||
if ((p->len < next_hdr_offset) || pbuf_remove_header(p, next_hdr_offset)) {
|
||||
goto free_and_return;
|
||||
} else {
|
||||
ip6_input(p, netif);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL
|
||||
if (LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
MIB2_STATS_NETIF_INC(netif, ifinunknownprotos);
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
|
||||
free_and_return:
|
||||
pbuf_free(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t ethernet_output(struct netif *netif, struct pbuf *p,
|
||||
const struct eth_addr *src, const struct eth_addr *dst,
|
||||
u16_t eth_type)
|
||||
{
|
||||
struct eth_hdr *ethhdr;
|
||||
u16_t eth_type_be = lwip_htons(eth_type);
|
||||
|
||||
#if ETHARP_SUPPORT_VLAN && (defined(LWIP_HOOK_VLAN_SET) || LWIP_VLAN_PCP)
|
||||
s32_t vlan_prio_vid;
|
||||
#ifdef LWIP_HOOK_VLAN_SET
|
||||
vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type);
|
||||
#elif LWIP_VLAN_PCP
|
||||
vlan_prio_vid = -1;
|
||||
if (netif->hints && (netif->hints->tci >= 0)) {
|
||||
vlan_prio_vid = (u16_t)netif->hints->tci;
|
||||
}
|
||||
#endif
|
||||
if (vlan_prio_vid >= 0) {
|
||||
struct eth_vlan_hdr *vlanhdr;
|
||||
|
||||
LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF);
|
||||
|
||||
if (pbuf_add_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) {
|
||||
goto pbuf_header_failed;
|
||||
}
|
||||
vlanhdr = (struct eth_vlan_hdr *)(((u8_t *)p->payload) + SIZEOF_ETH_HDR);
|
||||
vlanhdr->tpid = eth_type_be;
|
||||
vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid);
|
||||
eth_type_be = PP_HTONS(ETHTYPE_VLAN);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (pbuf_add_header(p, SIZEOF_ETH_HDR) != 0) {
|
||||
goto pbuf_header_failed;
|
||||
}
|
||||
}
|
||||
|
||||
LWIP_ASSERT_CORE_LOCKED();
|
||||
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
ethhdr->type = eth_type_be;
|
||||
SMEMCPY(ðhdr->dest, dst, ETH_HWADDR_LEN);
|
||||
SMEMCPY(ðhdr->src, src, ETH_HWADDR_LEN);
|
||||
|
||||
return netif->linkoutput(netif, p);
|
||||
|
||||
pbuf_header_failed:
|
||||
LINK_STATS_INC(link.lenerr);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
#endif
|
||||
+141
-285
@@ -1,150 +1,120 @@
|
||||
/**
|
||||
* @file ethernetif.c
|
||||
* @brief Ethernet interface implementation for CH390 + LwIP + FreeRTOS
|
||||
* @brief CH390 Ethernet interface for lwIP NO_SYS mode.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "netif/ethernet.h"
|
||||
#include "ethernetif.h"
|
||||
|
||||
#include "CH390.h"
|
||||
#include "CH390_Interface.h"
|
||||
#include "config.h"
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Interface name */
|
||||
#define IFNAME0 'e'
|
||||
#define IFNAME1 'n'
|
||||
|
||||
/* Global network interface */
|
||||
struct netif ch390_netif;
|
||||
static volatile uint8_t g_ch390_irq_pending;
|
||||
static void ethernetif_unlock(uint32_t primask);
|
||||
|
||||
/* Mutex for SPI access protection */
|
||||
static SemaphoreHandle_t spi_mutex = NULL;
|
||||
static uint32_t ethernetif_lock(void)
|
||||
{
|
||||
uint32_t primask = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
return primask;
|
||||
}
|
||||
|
||||
/* Forward declarations */
|
||||
static void low_level_init(struct netif *netif);
|
||||
static err_t low_level_output(struct netif *netif, struct pbuf *p);
|
||||
static struct pbuf *low_level_input(struct netif *netif);
|
||||
sys_prot_t sys_arch_protect(void)
|
||||
{
|
||||
return (sys_prot_t)ethernetif_lock();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Low Level Hardware Functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
void sys_arch_unprotect(sys_prot_t pval)
|
||||
{
|
||||
ethernetif_unlock((uint32_t)pval);
|
||||
}
|
||||
|
||||
static void ethernetif_unlock(uint32_t primask)
|
||||
{
|
||||
if ((primask & 1u) == 0u) {
|
||||
__enable_irq();
|
||||
}
|
||||
}
|
||||
|
||||
void ethernetif_set_irq_pending(void)
|
||||
{
|
||||
g_ch390_irq_pending = 1u;
|
||||
}
|
||||
|
||||
uint8_t ethernetif_is_irq_pending(void)
|
||||
{
|
||||
return g_ch390_irq_pending;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the CH390 hardware
|
||||
* @param netif Network interface structure
|
||||
*/
|
||||
static void low_level_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
|
||||
/* Create SPI mutex */
|
||||
if (spi_mutex == NULL)
|
||||
{
|
||||
spi_mutex = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
/* Initialize CH390 GPIO and SPI */
|
||||
|
||||
ch390_gpio_init();
|
||||
ch390_spi_init();
|
||||
|
||||
/* Hardware reset CH390 */
|
||||
ch390_hardware_reset();
|
||||
|
||||
/* Configure CH390 with default settings */
|
||||
ch390_default_config();
|
||||
|
||||
/* Set MAC hardware address length */
|
||||
ch390_set_mac_address((uint8_t *)config_get()->mac);
|
||||
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* Get MAC address from CH390 */
|
||||
ch390_get_mac(netif->hwaddr);
|
||||
|
||||
/* Maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* Device capabilities */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||
|
||||
/* Initialize state */
|
||||
ethernetif->rx_len = 0;
|
||||
ethernetif->rx_status = 0;
|
||||
|
||||
/* Enable CH390 interrupt */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
|
||||
|
||||
ethernetif->rx_len = 0u;
|
||||
ethernetif->rx_status = 0u;
|
||||
|
||||
ch390_interrupt_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit a packet via CH390
|
||||
* @param netif Network interface structure
|
||||
* @param p Packet buffer to transmit
|
||||
* @return ERR_OK on success
|
||||
*/
|
||||
static err_t low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
|
||||
/* Take SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
||||
}
|
||||
|
||||
uint32_t primask;
|
||||
|
||||
LWIP_UNUSED_ARG(netif);
|
||||
primask = ethernetif_lock();
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_remove_header(p, ETH_PAD_SIZE);
|
||||
#endif
|
||||
|
||||
/* Copy data to CH390 TX buffer */
|
||||
for (q = p; q != NULL; q = q->next)
|
||||
{
|
||||
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
ch390_write_mem(q->payload, q->len);
|
||||
}
|
||||
|
||||
/* Wait until last transmit complete */
|
||||
while (ch390_read_reg(CH390_TCR) & TCR_TXREQ)
|
||||
{
|
||||
taskYIELD();
|
||||
|
||||
while (ch390_read_reg(CH390_TCR) & TCR_TXREQ) {
|
||||
}
|
||||
|
||||
/* Set packet length */
|
||||
ch390_write_reg(CH390_TXPLL, p->tot_len & 0xFF);
|
||||
ch390_write_reg(CH390_TXPLH, (p->tot_len >> 8) & 0xFF);
|
||||
|
||||
/* Issue transmit request */
|
||||
|
||||
ch390_write_reg(CH390_TXPLL, p->tot_len & 0xFFu);
|
||||
ch390_write_reg(CH390_TXPLH, (p->tot_len >> 8) & 0xFFu);
|
||||
ch390_send_request();
|
||||
|
||||
/* Release SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreGive(spi_mutex);
|
||||
}
|
||||
|
||||
ethernetif_unlock(primask);
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_add_header(p, ETH_PAD_SIZE);
|
||||
#endif
|
||||
|
||||
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive a packet from CH390
|
||||
* @param netif Network interface structure
|
||||
* @return Packet buffer containing received data, or NULL if no packet
|
||||
*/
|
||||
static struct pbuf *low_level_input(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
@@ -153,281 +123,167 @@ static struct pbuf *low_level_input(struct netif *netif)
|
||||
uint16_t len;
|
||||
uint8_t rx_ready;
|
||||
uint8_t rx_header[4];
|
||||
|
||||
/* Take SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
||||
}
|
||||
|
||||
/* Check if packet is ready */
|
||||
ch390_read_reg(CH390_MRCMDX); /* Dummy read */
|
||||
uint32_t primask;
|
||||
|
||||
primask = ethernetif_lock();
|
||||
ch390_read_reg(CH390_MRCMDX);
|
||||
rx_ready = ch390_read_reg(CH390_MRCMDX);
|
||||
|
||||
if (rx_ready & CH390_PKT_ERR)
|
||||
{
|
||||
/* RX error - reset RX FIFO */
|
||||
ch390_write_reg(CH390_RCR, 0); /* RX disable */
|
||||
ch390_write_reg(CH390_MPTRCR, 0x01); /* Reset RX FIFO pointer */
|
||||
ch390_write_reg(CH390_MRRH, 0x0C);
|
||||
ch390_delay_us(1000);
|
||||
ch390_write_reg(CH390_RCR, RCR_RXEN | RCR_DIS_CRC); /* RX Enable */
|
||||
|
||||
|
||||
if (rx_ready & CH390_PKT_ERR) {
|
||||
ch390_write_reg(CH390_RCR, 0u);
|
||||
ch390_write_reg(CH390_MPTRCR, 0x01u);
|
||||
ch390_write_reg(CH390_MRRH, 0x0Cu);
|
||||
ch390_delay_us(1000u);
|
||||
ch390_write_reg(CH390_RCR, RCR_RXEN | RCR_DIS_CRC);
|
||||
ethernetif->rx_len = 0u;
|
||||
LINK_STATS_INC(link.drop);
|
||||
ethernetif->rx_len = 0;
|
||||
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreGive(spi_mutex);
|
||||
}
|
||||
ethernetif_unlock(primask);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(rx_ready & CH390_PKT_RDY))
|
||||
{
|
||||
/* No packet ready */
|
||||
ethernetif->rx_len = 0;
|
||||
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreGive(spi_mutex);
|
||||
}
|
||||
|
||||
if ((rx_ready & CH390_PKT_RDY) == 0u) {
|
||||
ethernetif->rx_len = 0u;
|
||||
ethernetif_unlock(primask);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read RX header (status + length) */
|
||||
|
||||
ch390_read_mem(rx_header, 4);
|
||||
ethernetif->rx_status = rx_header[1];
|
||||
/* Length includes 4-byte CRC, subtract it */
|
||||
ethernetif->rx_len = (rx_header[2] | (rx_header[3] << 8)) - 4;
|
||||
ethernetif->rx_len = (uint16_t)(((uint16_t)rx_header[2] | ((uint16_t)rx_header[3] << 8)) - 4u);
|
||||
len = ethernetif->rx_len;
|
||||
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
len += ETH_PAD_SIZE;
|
||||
#endif
|
||||
|
||||
/* Allocate pbuf chain */
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
if (p != NULL) {
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_remove_header(p, ETH_PAD_SIZE);
|
||||
#endif
|
||||
|
||||
/* Read packet data into pbuf chain */
|
||||
for (q = p; q != NULL; q = q->next)
|
||||
{
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
ch390_read_mem(q->payload, q->len);
|
||||
}
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_add_header(p, ETH_PAD_SIZE);
|
||||
#endif
|
||||
|
||||
/* Skip CRC (4 bytes) */
|
||||
ch390_drop_packet(4);
|
||||
|
||||
ch390_drop_packet(4u);
|
||||
LINK_STATS_INC(link.recv);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No memory - drop packet */
|
||||
ch390_drop_packet(ethernetif->rx_len + 4);
|
||||
} else {
|
||||
ch390_drop_packet((uint16_t)(ethernetif->rx_len + 4u));
|
||||
LINK_STATS_INC(link.memerr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
}
|
||||
|
||||
/* Release SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreGive(spi_mutex);
|
||||
}
|
||||
|
||||
|
||||
ethernetif_unlock(primask);
|
||||
return p;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Public Interface Functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Process received ethernet packets
|
||||
* @param netif Network interface structure
|
||||
*/
|
||||
void ethernetif_input(struct netif *netif)
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
/* Get received packet */
|
||||
p = low_level_input(netif);
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
/* Pass to LwIP stack */
|
||||
if (netif->input(p, netif) != ERR_OK)
|
||||
{
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
||||
struct pbuf *p = low_level_input(netif);
|
||||
|
||||
if (p != NULL) {
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the ethernet interface
|
||||
* @param netif Network interface structure
|
||||
* @return ERR_OK on success
|
||||
*/
|
||||
err_t ethernetif_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif;
|
||||
|
||||
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
/* Allocate ethernetif state structure */
|
||||
|
||||
ethernetif = mem_malloc(sizeof(struct ethernetif));
|
||||
if (ethernetif == NULL)
|
||||
{
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
|
||||
if (ethernetif == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
memset(ethernetif, 0, sizeof(struct ethernetif));
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
netif->hostname = "tcp2uart";
|
||||
#endif
|
||||
|
||||
/* Initialize SNMP variables */
|
||||
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000);
|
||||
|
||||
|
||||
netif->state = ethernetif;
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
|
||||
/* Set output functions */
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
netif->hostname = "tcp2uart";
|
||||
#endif
|
||||
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000);
|
||||
#if LWIP_IPV4
|
||||
netif->output = etharp_output;
|
||||
#endif
|
||||
netif->linkoutput = low_level_output;
|
||||
|
||||
/* Initialize hardware */
|
||||
low_level_init(netif);
|
||||
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize LwIP network interface
|
||||
* @param ipaddr IP address
|
||||
* @param netmask Network mask
|
||||
* @param gw Gateway address
|
||||
*/
|
||||
void lwip_netif_init(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw)
|
||||
{
|
||||
/* Add network interface */
|
||||
netif_add(&ch390_netif, ipaddr, netmask, gw, NULL,
|
||||
ðernetif_init, &tcpip_input);
|
||||
|
||||
/* Set as default interface */
|
||||
netif_add(&ch390_netif, ipaddr, netmask, gw, NULL, ðernetif_init, ðernet_input);
|
||||
netif_set_default(&ch390_netif);
|
||||
|
||||
/* Set interface down initially */
|
||||
netif_set_link_down(&ch390_netif);
|
||||
netif_set_up(&ch390_netif);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check and handle CH390 link status
|
||||
*/
|
||||
void ethernetif_check_link(void)
|
||||
{
|
||||
uint8_t link_status;
|
||||
|
||||
/* Take SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
||||
}
|
||||
|
||||
link_status = ch390_get_link_status();
|
||||
|
||||
/* Release SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreGive(spi_mutex);
|
||||
}
|
||||
|
||||
if (link_status)
|
||||
{
|
||||
if (!netif_is_link_up(&ch390_netif))
|
||||
{
|
||||
uint8_t link_up;
|
||||
uint32_t primask = ethernetif_lock();
|
||||
|
||||
link_up = (uint8_t)ch390_get_link_status();
|
||||
ethernetif_unlock(primask);
|
||||
|
||||
if (link_up) {
|
||||
if (!netif_is_link_up(&ch390_netif)) {
|
||||
netif_set_link_up(&ch390_netif);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (netif_is_link_up(&ch390_netif))
|
||||
{
|
||||
netif_set_link_down(&ch390_netif);
|
||||
}
|
||||
} else if (netif_is_link_up(&ch390_netif)) {
|
||||
netif_set_link_down(&ch390_netif);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process all pending RX packets
|
||||
*/
|
||||
void ethernetif_poll(void)
|
||||
{
|
||||
uint8_t int_status;
|
||||
|
||||
/* Take SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
||||
uint32_t primask;
|
||||
|
||||
if (g_ch390_irq_pending == 0u) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read interrupt status */
|
||||
|
||||
primask = ethernetif_lock();
|
||||
int_status = ch390_read_reg(CH390_ISR);
|
||||
|
||||
/* Clear interrupt flags */
|
||||
ch390_write_reg(CH390_ISR, int_status);
|
||||
|
||||
/* Release SPI mutex */
|
||||
if (spi_mutex != NULL)
|
||||
{
|
||||
xSemaphoreGive(spi_mutex);
|
||||
}
|
||||
|
||||
/* Handle link change */
|
||||
if (int_status & ISR_LNKCHG)
|
||||
{
|
||||
g_ch390_irq_pending = 0u;
|
||||
ethernetif_unlock(primask);
|
||||
|
||||
if ((int_status & ISR_LNKCHG) != 0u) {
|
||||
ethernetif_check_link();
|
||||
}
|
||||
|
||||
/* Handle RX overflow */
|
||||
if (int_status & ISR_ROS)
|
||||
{
|
||||
/* RX overflow - packets might be corrupted */
|
||||
|
||||
if ((int_status & ISR_ROS) != 0u) {
|
||||
LINK_STATS_INC(link.err);
|
||||
}
|
||||
|
||||
/* Process received packets */
|
||||
if (int_status & ISR_PR)
|
||||
{
|
||||
/* Process all available packets */
|
||||
while (1)
|
||||
{
|
||||
|
||||
if ((int_status & ISR_PR) != 0u) {
|
||||
while (1) {
|
||||
struct pbuf *p = low_level_input(&ch390_netif);
|
||||
if (p == NULL)
|
||||
{
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch390_netif.input(p, &ch390_netif) != ERR_OK)
|
||||
{
|
||||
if (ch390_netif.input(p, &ch390_netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32_t sys_now(void)
|
||||
{
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
u32_t sys_jiffies(void)
|
||||
{
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
@@ -1,63 +1,27 @@
|
||||
/**
|
||||
* @file ethernetif.h
|
||||
* @brief Ethernet interface header for CH390 + LwIP + FreeRTOS
|
||||
* @brief CH390 Ethernet interface for lwIP NO_SYS mode.
|
||||
*/
|
||||
|
||||
#ifndef __ETHERNETIF_H__
|
||||
#define __ETHERNETIF_H__
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Ethernet interface state structure */
|
||||
struct ethernetif {
|
||||
uint16_t rx_len;
|
||||
uint8_t rx_status;
|
||||
uint8_t rx_status;
|
||||
};
|
||||
|
||||
/* Global network interface */
|
||||
extern struct netif ch390_netif;
|
||||
|
||||
/**
|
||||
* @brief Initialize the ethernet interface
|
||||
* @param netif Network interface structure
|
||||
* @return ERR_OK on success
|
||||
*/
|
||||
err_t ethernetif_init(struct netif *netif);
|
||||
|
||||
/**
|
||||
* @brief Process received ethernet packets
|
||||
* @param netif Network interface structure
|
||||
* @note Call this from the LwIP task when packets are available
|
||||
*/
|
||||
void ethernetif_input(struct netif *netif);
|
||||
|
||||
/**
|
||||
* @brief Initialize LwIP network interface with static IP
|
||||
* @param ipaddr IP address
|
||||
* @param netmask Network mask
|
||||
* @param gw Gateway address
|
||||
*/
|
||||
void lwip_netif_init(const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw);
|
||||
|
||||
/**
|
||||
* @brief Check and handle CH390 interrupt status
|
||||
* @note Call this from the LwIP task periodically or on interrupt
|
||||
*/
|
||||
void ethernetif_check_link(void);
|
||||
|
||||
/**
|
||||
* @brief Process all pending RX packets
|
||||
* @note Call this from the LwIP task when RX interrupt occurs
|
||||
*/
|
||||
void ethernetif_poll(void);
|
||||
void ethernetif_set_irq_pending(void);
|
||||
uint8_t ethernetif_is_irq_pending(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ETHERNETIF_H__ */
|
||||
|
||||
Reference in New Issue
Block a user