From ef51eb98e193105cfaf7d4342a8f56f01b5bad84 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Fri, 6 Dec 2024 17:37:08 +0100 Subject: [PATCH] working on lwip --- CMakeLists.txt | 4 +- bsp_linux/CMakeLists.txt | 6 +- bsp_linux/lwip/CMakeLists.txt | 22 ++ bsp_linux/lwip/include/arch/cc.h | 25 ++ bsp_linux/lwip/include/lwipopts.h | 336 +++++++++++++++++++++++ bsp_linux/lwip/include/lwippools.h | 5 + bsp_linux/lwip/include/onrre.h | 2 + bsp_z7/lwip/bare/include/lwipopts.h | 16 +- mission/CMakeLists.txt | 2 + mission/mission.c | 56 +++- mission/netif/CMakeLists.txt | 1 + mission/netif/slipif.c | 409 ++++++++++++++++++++++++++++ mission/netif/slipif.h | 15 + 13 files changed, 886 insertions(+), 13 deletions(-) create mode 100644 bsp_linux/lwip/CMakeLists.txt create mode 100644 bsp_linux/lwip/include/arch/cc.h create mode 100644 bsp_linux/lwip/include/lwipopts.h create mode 100644 bsp_linux/lwip/include/lwippools.h create mode 100644 bsp_linux/lwip/include/onrre.h create mode 100644 mission/netif/CMakeLists.txt create mode 100644 mission/netif/slipif.c create mode 100644 mission/netif/slipif.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c39eef..568720d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,9 +34,7 @@ endif() add_executable(${OBSW_NAME}) # export lwip path, so the bsp can find it -if(${CMAKE_CROSSCOMPILING}) - set (LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/lwip) -endif() +set (LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/lwip) # Platform dependend configuration # Includes setting the FreeRTOS port, compiler options and diff --git a/bsp_linux/CMakeLists.txt b/bsp_linux/CMakeLists.txt index c5bba34..1fc04e6 100644 --- a/bsp_linux/CMakeLists.txt +++ b/bsp_linux/CMakeLists.txt @@ -1,8 +1,12 @@ add_library(bsp STATIC) add_subdirectory(hardware) +add_subdirectory(lwip) target_sources(bsp PRIVATE main.c) # bsp depends on FreeRTOS -target_link_libraries(bsp PUBLIC freertos_kernel) \ No newline at end of file +target_link_libraries(bsp PUBLIC freertos_kernel) + +# export lwip as part of bsp +target_link_libraries(bsp INTERFACE lwip) \ No newline at end of file diff --git a/bsp_linux/lwip/CMakeLists.txt b/bsp_linux/lwip/CMakeLists.txt new file mode 100644 index 0000000..d5228b9 --- /dev/null +++ b/bsp_linux/lwip/CMakeLists.txt @@ -0,0 +1,22 @@ +# LWIP_DIR should point to the lwip source, to be set in main CMakeLists.txt +include(${LWIP_DIR}/src/Filelists.cmake) + +set (LWIP_INCLUDE_DIRS + "${LWIP_DIR}/src/include" + "${LWIP_DIR}/src/include/compat/posix" + "include" +) + +set(lwip_SRCS + ${lwipcore_SRCS} + ${lwipcore4_SRCS} + ${lwipcore6_SRCS} + ${lwipnetif_SRCS} + ${lwipapi_SRCS} + #${LWIP_DIR}/contrib/ports/freertos/sys_arch.c + #${LWIP_DIR}/src/netif/slipif.c + #${LWIP_DIR}/src/apps/tftp/tftp.c +) + +add_library(lwip ${lwip_SRCS}) +target_include_directories(lwip PUBLIC ${LWIP_INCLUDE_DIRS}) \ No newline at end of file diff --git a/bsp_linux/lwip/include/arch/cc.h b/bsp_linux/lwip/include/arch/cc.h new file mode 100644 index 0000000..4b17f04 --- /dev/null +++ b/bsp_linux/lwip/include/arch/cc.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "lwipopts.h" + +/** if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#define LWIP_TIMEVAL_PRIVATE 0 +#include + +// errno is a macro. If we define LWIP_ERRNO_INCLUDE to errno.h the preprocessor will replace it, +// breaking the include. Instead we supply a helper include which in turn includes errno.h +#define LWIP_ERRNO_INCLUDE + +#define LWIP_RAND rand + +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +#define LWIP_PLATFORM_ASSERT(x) +#define LWIP_PLATFORM_DIAG(x) do { printf x; } while(0) diff --git a/bsp_linux/lwip/include/lwipopts.h b/bsp_linux/lwip/include/lwipopts.h new file mode 100644 index 0000000..e4b0b62 --- /dev/null +++ b/bsp_linux/lwip/include/lwipopts.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +#define LWIP_IPV4 1 +#define LWIP_IPV6 0 + +#define NO_SYS 1 +#define LWIP_SOCKET 0 +#define LWIP_NETCONN 0 +#define LWIP_NETIF_API 0 + +#define LWIP_IGMP 0 +#define LWIP_ICMP LWIP_IPV4 + +#define LWIP_SNMP 0 +//#define MIB2_STATS LWIP_SNMP +#ifdef LWIP_HAVE_MBEDTLS +#define LWIP_SNMP_V3 (LWIP_SNMP) +#endif + +#define LWIP_DNS 0 +#define LWIP_MDNS_RESPONDER 0 + +#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) + +#define LWIP_HAVE_LOOPIF 0 +#define LWIP_NETIF_LOOPBACK 0 +#define LWIP_LOOPBACK_MAX_PBUFS 0 + +#define TCP_LISTEN_BACKLOG 0 + +#define LWIP_COMPAT_SOCKETS 0 +//TODO put this into the OS +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 +#define LWIP_SO_RCVTIMEO 0 +#define LWIP_SO_RCVBUF 0 +//TODO use this with LWIP_POSIX_SOCKETS_IO_NAMES +// TODO why is 100 not working... +#define LWIP_SOCKET_OFFSET 10 + +#define LWIP_SOCKET_SELECT 0 +#define LWIP_SOCKET_POLL 0 + +#define LWIP_TCPIP_CORE_LOCKING 0 + +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_EXT_STATUS_CALLBACK 1 + +//#define LWIP_DEBUG + +#ifdef LWIP_DEBUG + +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#define PPP_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_ON +#define API_LIB_DEBUG LWIP_DBG_ON +#define API_MSG_DEBUG LWIP_DBG_ON +#define TCPIP_DEBUG LWIP_DBG_ON +#define NETIF_DEBUG LWIP_DBG_ON +#define SOCKETS_DEBUG LWIP_DBG_ON +#define DNS_DEBUG LWIP_DBG_ON +#define AUTOIP_DEBUG LWIP_DBG_ON +#define DHCP_DEBUG LWIP_DBG_ON +#define IP_DEBUG LWIP_DBG_ON +#define IP_REASS_DEBUG LWIP_DBG_ON +#define ICMP_DEBUG LWIP_DBG_ON +#define IGMP_DEBUG LWIP_DBG_ON +#define UDP_DEBUG LWIP_DBG_ON +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_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_FR_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define TIMERS_DEBUG LWIP_DBG_OFF +#define LWIP_DEBUG_TIMERNAMES LWIP_DBG_OFF +#endif + +#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) + + +/* ---------- Memory options ---------- */ +/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which + lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 + byte alignment -> define MEM_ALIGNMENT to 2. */ +/* MSVC port: intel processors don't need 4-byte alignment, + but are faster that way! */ + //TODO documentation + //Zynq needs 32 for DMA to work (something about cache I guess...) +#define MEM_ALIGNMENT 32U + +#define MEM_USE_POOLS 1 +#define MEMP_USE_CUSTOM_POOLS MEM_USE_POOLS + +/* MEM_SIZE: the size of the heap memory. If the application will send +a lot of data that needs to be copied, this should be set high. */ +#define MEM_SIZE 102400 + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#define MEMP_NUM_PBUF 16 +/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One + per active RAW "connection". */ +#define MEMP_NUM_RAW_PCB 0 +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#define MEMP_NUM_UDP_PCB 8 +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + connections. */ +#define MEMP_NUM_TCP_PCB 0 +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + connections. */ +#define MEMP_NUM_TCP_PCB_LISTEN 0 +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#define MEMP_NUM_TCP_SEG 0 +/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active + timeouts. */ +#define MEMP_NUM_SYS_TIMEOUT 17 + +/* The following four are used only with the sequential API and can be + set to 0 if the application only will use the raw API. */ +/* MEMP_NUM_NETBUF: the number of struct netbufs. */ +#define MEMP_NUM_NETBUF 0 +/* MEMP_NUM_NETCONN: the number of struct netconns. */ +#define MEMP_NUM_NETCONN 0 +/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used + for sequential API communication and incoming packets. Used in + src/api/tcpip.c. */ +#define MEMP_NUM_TCPIP_MSG_API 0 +#define MEMP_NUM_TCPIP_MSG_INPKT 0 + +#define TCPIP_THREAD_STACKSIZE 10240 + + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#define PBUF_POOL_SIZE 120 + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +/* Needs to be large enough to fit eth MTU to be able to use DMA for xemacps rx*/ +#define PBUF_POOL_BUFSIZE 1600 + +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 0 + + +/* ---------- TCP options ---------- */ +#define LWIP_TCP 0 +#define TCP_TTL 255 + +#define LWIP_ALTCP (LWIP_TCP) +#ifdef LWIP_HAVE_MBEDTLS +#define LWIP_ALTCP_TLS (LWIP_TCP) +#define LWIP_ALTCP_TLS_MBEDTLS (LWIP_TCP) +#endif + + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#define TCP_QUEUE_OOSEQ 1 + +/* TCP Maximum segment size. */ +#define TCP_MSS 1024 + +/* TCP sender buffer space (bytes). */ +#define TCP_SND_BUF 2048 + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS) + +/* TCP writable space (bytes). This must be less than or equal + to TCP_SND_BUF. It is the amount of space which must be + available in the tcp snd_buf for select to return writable */ +#define TCP_SNDLOWAT (TCP_SND_BUF/2) + +/* TCP receive window. */ +#define TCP_WND (20 * 1024) + +/* Maximum number of retransmissions of data segments. */ +#define TCP_MAXRTX 12 + +/* Maximum number of retransmissions of SYN segments. */ +#define TCP_SYNMAXRTX 4 + + +#define TCPIP_MBOX_SIZE 5 + +/* ---------- ARP options ---------- */ +#define LWIP_ARP 1 +#define ARP_TABLE_SIZE 10 +#define ARP_QUEUEING 1 +#define ARP_QUEUE_LEN 10 + + +/* ---------- IP options ---------- */ +/* Define IP_FORWARD to 1 if you wish to have the ability to forward + IP packets across network interfaces. If you are going to run lwIP + on a device with only one network interface, define this to 0. */ +#define IP_FORWARD 1 + +/* IP reassembly and segmentation.These are orthogonal even + * if they both deal with IP fragments */ +#define IP_REASSEMBLY 1 +#define IP_REASS_MAX_PBUFS (10 * ((1500 + PBUF_POOL_BUFSIZE - 1) / PBUF_POOL_BUFSIZE)) +#define MEMP_NUM_REASSDATA IP_REASS_MAX_PBUFS +#define IP_FRAG 1 +#define IPV6_FRAG_COPYHEADER 1 + +/* ---------- ICMP options ---------- */ +#define ICMP_TTL 255 + + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. */ +#define LWIP_DHCP 0 + +/* 1 if you want to do an ARP check on the offered address + (recommended). */ +#define DHCP_DOES_ARP_CHECK (LWIP_DHCP) + + +/* ---------- AUTOIP options ------- */ +#define LWIP_AUTOIP (LWIP_DHCP) +#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) + + +/* ---------- UDP options ---------- */ +#define LWIP_UDP 1 +#define LWIP_UDPLITE 0 +#define UDP_TTL 255 +#define DEFAULT_UDP_RECVMBOX_SIZE 4 + +/* ---------- RAW options ---------- */ +#define LWIP_RAW 0 +#define DEFAULT_TCP_RECVMBOX_SIZE 2 + +/* ---------- Statistics options ---------- */ + +#define LWIP_STATS 0 +#define LWIP_STATS_DISPLAY 0 + +#if LWIP_STATS +#define LINK_STATS 1 +#define IP_STATS 1 +#define ICMP_STATS 1 +#define IGMP_STATS 1 +#define IPFRAG_STATS 1 +#define UDP_STATS 1 +#define TCP_STATS 1 +#define MEM_STATS 1 +#define MEMP_STATS 1 +#define PBUF_STATS 1 +#define SYS_STATS 1 +#endif /* LWIP_STATS */ + +/* ---------- NETBIOS options ---------- */ +#define LWIP_NETBIOS_RESPOND_NAME_QUERY 0 + +/* ---------- PPP options ---------- */ + +#define PPP_SUPPORT 0 /* Set > 0 for PPP */ + +#if PPP_SUPPORT + +#define NUM_PPP 1 /* Max PPP sessions. */ + + +/* Select modules to enable. Ideally these would be set in the makefile but + * we're limited by the command line length so you need to modify the settings + * in this file. + */ +#define PPPOE_SUPPORT 1 +#define PPPOS_SUPPORT 1 + +#define PAP_SUPPORT 1 /* Set > 0 for PAP. */ +#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */ +#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP */ +#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */ +#define CCP_SUPPORT 0 /* Set > 0 for CCP */ +#define VJ_SUPPORT 0 /* Set > 0 for VJ header compression. */ +#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */ + +#endif /* PPP_SUPPORT */ + + +// Disable slip task +#define SLIP_USE_RX_THREAD 0 + + + +#endif /* LWIP_LWIPOPTS_H */ diff --git a/bsp_linux/lwip/include/lwippools.h b/bsp_linux/lwip/include/lwippools.h new file mode 100644 index 0000000..7b5650e --- /dev/null +++ b/bsp_linux/lwip/include/lwippools.h @@ -0,0 +1,5 @@ +LWIP_MALLOC_MEMPOOL_START +LWIP_MALLOC_MEMPOOL(50, 256) +LWIP_MALLOC_MEMPOOL(50, 512) +LWIP_MALLOC_MEMPOOL(50, 1550) +LWIP_MALLOC_MEMPOOL_END \ No newline at end of file diff --git a/bsp_linux/lwip/include/onrre.h b/bsp_linux/lwip/include/onrre.h new file mode 100644 index 0000000..a77254c --- /dev/null +++ b/bsp_linux/lwip/include/onrre.h @@ -0,0 +1,2 @@ +#pragma once +#include \ No newline at end of file diff --git a/bsp_z7/lwip/bare/include/lwipopts.h b/bsp_z7/lwip/bare/include/lwipopts.h index bdc8f01..e4b0b62 100644 --- a/bsp_z7/lwip/bare/include/lwipopts.h +++ b/bsp_z7/lwip/bare/include/lwipopts.h @@ -139,19 +139,19 @@ a lot of data that needs to be copied, this should be set high. */ #define MEMP_NUM_PBUF 16 /* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One per active RAW "connection". */ -#define MEMP_NUM_RAW_PCB 3 +#define MEMP_NUM_RAW_PCB 0 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One per active UDP "connection". */ #define MEMP_NUM_UDP_PCB 8 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. */ -#define MEMP_NUM_TCP_PCB 5 +#define MEMP_NUM_TCP_PCB 0 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. */ -#define MEMP_NUM_TCP_PCB_LISTEN 8 +#define MEMP_NUM_TCP_PCB_LISTEN 0 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. */ -#define MEMP_NUM_TCP_SEG 16 +#define MEMP_NUM_TCP_SEG 0 /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. */ #define MEMP_NUM_SYS_TIMEOUT 17 @@ -159,14 +159,14 @@ a lot of data that needs to be copied, this should be set high. */ /* The following four are used only with the sequential API and can be set to 0 if the application only will use the raw API. */ /* MEMP_NUM_NETBUF: the number of struct netbufs. */ -#define MEMP_NUM_NETBUF 2 +#define MEMP_NUM_NETBUF 0 /* MEMP_NUM_NETCONN: the number of struct netconns. */ -#define MEMP_NUM_NETCONN 12 +#define MEMP_NUM_NETCONN 0 /* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used for sequential API communication and incoming packets. Used in src/api/tcpip.c. */ -#define MEMP_NUM_TCPIP_MSG_API 16 -#define MEMP_NUM_TCPIP_MSG_INPKT 16 +#define MEMP_NUM_TCPIP_MSG_API 0 +#define MEMP_NUM_TCPIP_MSG_INPKT 0 #define TCPIP_THREAD_STACKSIZE 10240 diff --git a/mission/CMakeLists.txt b/mission/CMakeLists.txt index 8501596..ffc52f4 100644 --- a/mission/CMakeLists.txt +++ b/mission/CMakeLists.txt @@ -3,4 +3,6 @@ # adds directly to the OBSW target ################################################ +add_subdirectory(netif) + target_sources(${OBSW_NAME} PRIVATE mission.c freeRTOS_rust_helper.c) \ No newline at end of file diff --git a/mission/mission.c b/mission/mission.c index 021ca5f..c6753ac 100644 --- a/mission/mission.c +++ b/mission/mission.c @@ -7,6 +7,13 @@ #include "semphr.h" #include "task.h" +#include "lwip/init.h" +#include "lwip/timeouts.h" +#include "lwip/udp.h" +#include +#include +#include "netif/slipif.h" + void rust_main(); #include @@ -39,15 +46,62 @@ void test_hardware() { write(1, buffer, read_bytes); } + +struct netif netif; +struct slipif_priv slipif_config; +static struct udp_pcb *udpecho_raw_pcb; + +u32_t sys_now(void) { return xTaskGetTickCount() * portTICK_PERIOD_MS; } + +void test_lwip() { + lwip_init(); + + ip4_addr_t slip_addr = {PP_HTONL(LWIP_MAKEU32(10, 13, 80, 10))}, + slip_mask = {PP_HTONL(LWIP_MAKEU32(255, 255, 255, 0))}, + slip_gw = {PP_HTONL(LWIP_MAKEU32(10, 13, 80, 1))}; + + slipif_config.fd = hw_device_open("uart1", 5); + + netif_add(&netif, &slip_addr, &slip_mask, &slip_gw, &slipif_config, slipif_init, + netif_input); + + netif_set_default(&netif); + // should be done by driver, which does not do it, so we do it here + netif_set_link_up(&netif); + netif_set_up(&netif); + + udpecho_raw_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (udpecho_raw_pcb != NULL) { + err_t err; + + err = udp_bind(udpecho_raw_pcb, IP_ANY_TYPE, 7); + if (err != ERR_OK) { + return; + } + + ip_addr_t addr = IPADDR4_INIT_BYTES(10,13,80,1); + + uint8_t data[] = {'1','2','3','4'}; + + struct pbuf* tx = pbuf_alloc_reference(data, sizeof(data), PBUF_REF); + + udp_sendto(udpecho_raw_pcb,tx,&addr,1234); + } +} + // called to stop execution (either a panic or program ended) // to be implemented by bsp (do not return from it!) void done(); + + void init_task(void * _) { (void )_; // printf("Starting Mission\n"); - test_hardware(); + //test_hardware(); + + test_lwip(); rust_main(); diff --git a/mission/netif/CMakeLists.txt b/mission/netif/CMakeLists.txt new file mode 100644 index 0000000..b9d7a5d --- /dev/null +++ b/mission/netif/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${OBSW_NAME} PRIVATE slipif.c) \ No newline at end of file diff --git a/mission/netif/slipif.c b/mission/netif/slipif.c new file mode 100644 index 0000000..0ae6a53 --- /dev/null +++ b/mission/netif/slipif.c @@ -0,0 +1,409 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + * Simon Goldschmidt + */ + + +/** + * @defgroup slipif SLIP + * @ingroup netifs + * + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + * + * Usage: This netif can be used in three ways: + * 1. For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received. + * 2. In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input(). + * 3. Call slipif_received_byte[s]() from your serial RX ISR and + * slipif_process_rxqueue() from your main loop. ISR level decodes + * packets and puts completed packets on a queue which is fed into + * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for + * pbuf_alloc to work on ISR level!). + * + */ + +#include "slipif.h" +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sys.h" + +#define SLIP_END 0xC0 /* 0300: start and end of every packet */ +#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ +#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ +#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ + +/** Maximum packet size that is received by this netif */ +#ifndef SLIP_MAX_SIZE +#define SLIP_MAX_SIZE 1500 +#endif + +#ifndef SLIP_CHUNK_SIZE +#define SLIP_CHUNK_SIZE 120 +#endif + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE +}; + + + +static void +slipif_send_chunk(uint8_t c, int fd, uint8_t *chunk, size_t *current_index, size_t chunksize, int flush){ + if (*current_index >= chunksize) { + write(0,"stra", 5); + //chunk is already full, send it and reset + write(fd, chunk, chunksize); + *current_index = 0; + } + // add byte to chunk, (can not be full, we checked) + if (*current_index < chunksize) { + chunk[*current_index] = c; + (*current_index)++; + } + // if either chunk is full or we shall flush, send it + if ((*current_index >= chunksize) || ( flush != 0)) { + write(0,"full", 5); + write(fd, chunk, *current_index); + *current_index = 0; + } +} + + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output(struct netif *netif, struct pbuf *p) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + uint8_t chunk[SLIP_CHUNK_SIZE]; + size_t current_index = 0; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output: sending %"U16_F" bytes\n", p->tot_len)); + priv = (struct slipif_priv *)netif->state; + + /* Send pbuf out on the serial I/O device. */ + /* Start with packet delimiter. */ + slipif_send_chunk(SLIP_END, priv->fd, chunk, ¤t_index, sizeof(chunk), 0); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ + slipif_send_chunk(SLIP_ESC, priv->fd, chunk, ¤t_index, sizeof(chunk), 0); + slipif_send_chunk(SLIP_ESC_END, priv->fd, chunk, ¤t_index, sizeof(chunk), 0); + break; + case SLIP_ESC: + /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ + slipif_send_chunk(SLIP_ESC, priv->fd, chunk, ¤t_index, sizeof(chunk), 0); + slipif_send_chunk(SLIP_ESC_ESC, priv->fd, chunk, ¤t_index, sizeof(chunk), 0); + break; + default: + /* normal byte - no need for escaping */ + slipif_send_chunk(c, priv->fd, chunk, ¤t_index, sizeof(chunk), 0); + break; + } + } + } + /* End with packet delimiter, flush the chunk */ + slipif_send_chunk(SLIP_END, priv->fd, chunk, ¤t_index, sizeof(chunk), 1); + return ERR_OK; +} + +#if LWIP_IPV4 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV6 */ + +/** + * Handle the incoming SLIP stream character by character + * + * @param netif the lwip network interface structure for this slipif + * @param c received character (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf * +slipif_rxbyte(struct netif *netif, u8_t c) +{ + struct slipif_priv *priv; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + return NULL; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + return NULL; + default: + break; + } /* end switch (c) */ + break; + case SLIP_RECV_ESCAPE: + /* un-escape END or ESC bytes, leave other bytes + (although that would be a protocol error) */ + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + default: + break; + } + priv->state = SLIP_RECV_NORMAL; + break; + default: + break; + } /* end switch (priv->state) */ + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - PBUF_LINK_ENCAPSULATION_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + return NULL; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + return NULL; +} + +/** Like slipif_rxbyte, but passes completed packets to netif->input + * + * @param netif The lwip network interface structure for this slipif + * @param c received character + */ +static void +slipif_rxbyte_input(struct netif *netif, u8_t c) +{ + struct pbuf *p; + p = slipif_rxbyte(netif, c); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + + +/** + * @ingroup slipif + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note If netif->state is interpreted as an u8_t serial port number. + * + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + + LWIP_ASSERT("slipif needs an input callback", netif->input != NULL); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)sio_num)); + + + netif->name[0] = 's'; + netif->name[1] = 'l'; +#if LWIP_IPV4 + netif->output = slipif_output_v4; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = slipif_output_v6; +#endif /* LWIP_IPV6 */ + netif->mtu = SLIP_MAX_SIZE; + + /* private data needs to be allocated by user and passed via state (see netif_add()) */ + priv = netif->state; + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; + + LWIP_ASSERT("slipif private data fd needs to be initialized before calling netif_add()", priv->fd != 0); + + + + /* initialize the snmp variables and counters inside the struct netif */ + MIB2_INIT_NETIF(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); + + return ERR_OK; +} + +/** + * @ingroup slipif + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + uint8_t chunk[SLIP_CHUNK_SIZE]; + int read_bytes = read(priv->fd, chunk, sizeof(chunk)); + + for (int i = 0; i < read_bytes; i++){ + slipif_rxbyte_input(netif, chunk[i]); + } +} diff --git a/mission/netif/slipif.h b/mission/netif/slipif.h new file mode 100644 index 0000000..1ab8c94 --- /dev/null +++ b/mission/netif/slipif.h @@ -0,0 +1,15 @@ +#pragma once + +#include "lwip/opt.h" +#include "lwip/netif.h" + +struct slipif_priv { + int fd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + u8_t state; + u16_t i, recved; +}; + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); \ No newline at end of file