From 6059b083e1b18162caba9d607f05a35de1a3a922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Wiesner?= Date: Fri, 18 Sep 2026 09:49:20 +0200 Subject: [PATCH] - lwip is available again --- .gitmodules | 3 + CMakeLists.txt | 9 + Drivers/EthDrv/CMakeLists.txt | 17 +- Drivers/EthDrv/eth_drv_lwip.c | 398 +++++++++++++++++++++++++ Drivers/EthDrv/eth_drv_lwip.h | 14 + Modules/CMakeLists.txt | 33 ++- Modules/lwip | 1 + Modules/lwip_port/OS/sys_arch.c | 477 ++++++++++++++++++++++++++++++ Modules/lwip_port/arch/bpstruct.h | 36 +++ Modules/lwip_port/arch/cc.h | 88 ++++++ Modules/lwip_port/arch/cpu.h | 39 +++ Modules/lwip_port/arch/epstruct.h | 36 +++ Modules/lwip_port/arch/init.h | 44 +++ Modules/lwip_port/arch/lib.h | 38 +++ Modules/lwip_port/arch/perf.h | 38 +++ Modules/lwip_port/arch/sys_arch.h | 72 +++++ Src/cmds.c | 23 +- Src/ethernet/CMakeLists.txt | 18 +- Src/ethernet/ethernet_lwip.c | 87 ++++++ Src/ethernet/ethernet_lwip.h | 6 + Src/main.c | 8 +- 21 files changed, 1474 insertions(+), 11 deletions(-) create mode 100644 Drivers/EthDrv/eth_drv_lwip.c create mode 100644 Drivers/EthDrv/eth_drv_lwip.h create mode 160000 Modules/lwip create mode 100644 Modules/lwip_port/OS/sys_arch.c create mode 100644 Modules/lwip_port/arch/bpstruct.h create mode 100644 Modules/lwip_port/arch/cc.h create mode 100644 Modules/lwip_port/arch/cpu.h create mode 100644 Modules/lwip_port/arch/epstruct.h create mode 100644 Modules/lwip_port/arch/init.h create mode 100644 Modules/lwip_port/arch/lib.h create mode 100644 Modules/lwip_port/arch/perf.h create mode 100644 Modules/lwip_port/arch/sys_arch.h create mode 100644 Src/ethernet/ethernet_lwip.c create mode 100644 Src/ethernet/ethernet_lwip.h diff --git a/.gitmodules b/.gitmodules index f8eafff..f1ab4dd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "Modules/etherlib"] path = Modules/etherlib url = https://gitea.epagris.com/epagris/EtherLib +[submodule "Modules/lwip"] + path = Modules/lwip + url = https://github.com/lwip-tcpip/lwip.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 71c3dc1..31ecf18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,9 @@ set(linker_OPTS) # information to the project include("cmake/vscode_generated.cmake") +# Set Ethernet stack +set(ETH_STACK "LWIP") + # Link directories setup # Must be before executable is added link_directories(${CMAKE_PROJECT_NAME} ${link_DIRS}) @@ -88,6 +91,12 @@ set(compile_DEFS ${MCU_TYPE} USE_HAL_DRIVER DEBUG CMSIS_OS2 USE_PWR_DIRECT_SMPS_ add_compile_definitions(${compile_DEFS}) add_compile_definitions(PROJECT_NAME="${CMAKE_PROJECT_NAME}") +if (ETH_STACK STREQUAL "ETHERLIB") + add_compile_definitions(ETH_ETHERLIB) +elseif(ETH_STACK STREQUAL "LWIP") + add_compile_definitions(ETH_LWIP) +endif() + # Add include paths target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${include_DIRS} diff --git a/Drivers/EthDrv/CMakeLists.txt b/Drivers/EthDrv/CMakeLists.txt index dcae956..8524439 100644 --- a/Drivers/EthDrv/CMakeLists.txt +++ b/Drivers/EthDrv/CMakeLists.txt @@ -1,12 +1,23 @@ add_subdirectory(phy_drv) +if (ETH_STACK STREQUAL "ETHERLIB") + set(ETH_DRV_SRC + eth_drv_etherlib.c + eth_drv_etherlib.h + ) +elseif(ETH_STACK STREQUAL "LWIP") + set(ETH_DRV_SRC + eth_drv_lwip.c + eth_drv_lwip.h + ) +endif() + target_sources( ${CMAKE_PROJECT_NAME} PUBLIC + ${ETH_DRV_SRC} + mac_drv.c mac_drv.h - - eth_drv_etherlib.c - eth_drv_etherlib.h ) \ No newline at end of file diff --git a/Drivers/EthDrv/eth_drv_lwip.c b/Drivers/EthDrv/eth_drv_lwip.c new file mode 100644 index 0000000..eca51ed --- /dev/null +++ b/Drivers/EthDrv/eth_drv_lwip.c @@ -0,0 +1,398 @@ +#include "eth_drv_lwip.h" + +#include + +#include +#include +#include + +#include "cmsis_os2.h" +#include "lwip/arch.h" +#include "lwip/err.h" +#include "lwip/etharp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" + +#include "lwip/tcpip.h" +#include "mac_drv.h" +#include "phy_drv/phy_common.h" + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/etharp.h" +#include "lwip/ethip6.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" +#include "lwip/stats.h" +#include "netif/ppp/pppoe.h" +#include "standard_output/standard_output.h" + +#include + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +// ------------------------------------- +// --------- Ethernet buffers ---------- +// ------------------------------------- + +#define ETH_BUFFER_SIZE (1528UL) +#define ETH_RX_BUF_SIZE (ETH_BUFFER_SIZE) +#define ETH_TX_BUF_SIZE (ETH_BUFFER_SIZE) + +uint8_t ETHBuffer[(ETH_RX_DESC_CNT + ETH_TX_DESC_CNT) * ETH_BUFFER_SIZE] __attribute__((section(".ETHBufferSection"))); /* Ethernet Receive Buffers */ + +struct { + ETHHW_State ETHState; + ETHHW_DescFull DMARxDscrTab[ETH_RX_DESC_CNT]; + ETHHW_DescFull DMATxDscrTab[ETH_TX_DESC_CNT]; +} ETHStateAndDesc __attribute__((section(".ETHStateAndDecripSection"))); + +// ------------------------------------- +// ---------- Global objects ----------- +// ------------------------------------- + +static struct netif *if0; + +static LinkState linkState = {false, false, 0, false}; + +static osThreadId_t th; + +static void fetch_link_properties() { + const PHY_LinkStatus *status = phy_get_link_status(); + + // set link up/down state + if ((linkState.up != status->up) || (!linkState.init)) { + linkState.up = status->up; + + if (linkState.up) { + bool fe = status->speed == PHY_LS_100Mbps; + bool duplex = status->type == PHY_LT_FULL_DUPLEX; + ETHHW_SetLinkProperties(ETH, fe, duplex); + + // convert "Fast Ethernet" to numerical speed value + linkState.speed = (status->speed == PHY_LS_100Mbps) ? 100 : 10; + + // save duplex field + linkState.duplex = duplex; + } + + // invoke link change notification callback + if (linkState.up) { + // MSG("UP!\n"); + netif_set_link_up(if0); + } else { + netif_set_link_down(if0); + // MSG("DOWN!\n"); + } + } + + linkState.init = true; +} + +static void phy_thread(void *arg) { + while (true) { + tcpip_callback(fetch_link_properties, NULL); + osDelay(500); + } + return; +} + +// ------------------------------ + +/* Define those to better describe your network interface. */ +#define IFNAME0 'i' +#define IFNAME1 '0' + +/* Forward declarations. */ +static void ethernetif_input(struct netif *netif); + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void low_level_init(struct netif *netif) { + // ------- Ethernet MAC initialization ----- + + ETHHW_InitOpts opts = { + .statePtr = &(ETHStateAndDesc.ETHState), + + .rxRingLen = ETH_RX_DESC_CNT, + .bufPtr = ETHBuffer, + .rxRingPtr = (uint8_t *)ETHStateAndDesc.DMARxDscrTab, + + .txRingLen = ETH_TX_DESC_CNT, + .txRingPtr = (uint8_t *)ETHStateAndDesc.DMATxDscrTab, + .blockSize = ETH_BUFFER_SIZE, + .mac = {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5}}; + + ETHHW_Init(ETH, &opts); + + ETHHW_Start(ETH); + + // -------- Process PHY events occured during the initialization phase + + // start PHY event processing thread + osThreadAttr_t attr; + memset(&attr, 0, sizeof(attr)); + attr.stack_size = 2048; + attr.name = "phy"; + th = osThreadNew(phy_thread, NULL, &attr); + + // ------------------------------------------------------------------- + + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + memcpy(netif->hwaddr, opts.mac, ETHARP_HWADDR_LEN); + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP /*| NETIF_FLAG_LINK_UP*/; + +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* + * For hardware/netifs that implement MAC filtering. + * All-nodes link-local is handled by default, so we must let the hardware know + * to allow multicast packets in. + * Should set mld_mac_filter previously. */ + if (netif->mld_mac_filter != NULL) { + ip6_addr_t ip6_allnodes_ll; + ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); + netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + } +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +static err_t low_level_output(struct netif *netif, struct pbuf *p) { + struct pbuf *q; + static u8_t concat_buf[ETH_TX_BUF_SIZE]; + u32_t concat_buf_level = 0; + +#if ETH_PAD_SIZE + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* Concat pbufs into a single buffer */ + for (q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + memcpy(concat_buf + concat_buf_level, q->payload, q->len); + concat_buf_level += q->len; + } + + /* check if timestamping is demanded */ + uint8_t opts = ETHHW_TXOPT_NONE; + // bool tsEn = (p->tx_cb != NULL); + ETHHW_OptArg_TxTsCap optArg; + memset(&optArg, 0, sizeof(ETHHW_OptArg_TxTsCap)); + + // if (tsEn) { + // opts = ETHHW_TXOPT_CAPTURE_TS; + // optArg.txTsCbPtr = (uint32_t)(p->tx_cb); + // optArg.tag = (uint32_t)p->tag; + // } + + /* Pass the data to the MAC */ + ETHHW_Transmit(ETH, concat_buf, concat_buf_level, opts, &optArg); + + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); + if (((u8_t *)p->payload)[0] & 1) { + /* broadcast or multicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + } else { + /* unicast packet */ + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + } + /* increase ifoutdiscards or ifouterrors on error */ + +#if ETH_PAD_SIZE + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +int ETHHW_ReadCallback(ETHHW_EventDesc *evt) { + // packet reception + if (evt->type != ETHHW_EVT_RX_READ) { + return 0; + } + + /* return indicator */ + int ret = 0; + + /* move received packet into a new pbuf */ + struct pbuf *p, *q; + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, evt->data.rx.size, PBUF_POOL); + + if (p != NULL) { + /* save size waiting for being stored */ + u16_t size_left = evt->data.rx.size; + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; (q != NULL) && (size_left > 0); q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + + /* compute copy size and copy */ + u16_t copy_size = MIN(size_left, q->len); + memcpy(q->payload, evt->data.rx.payload, copy_size); + size_left -= copy_size; + } + + /* Copy the timestamp into the first pbuf */ + // p->time_s = evt->data.rx.ts_s; + // p->time_ns = evt->data.rx.ts_ns; + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); + if (((u8_t *)p->payload)[0] & 1) { + /* broadcast or multicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); + } else { + /* unicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + } + + /* packets has been processed and can be released */ + ret = ETHHW_RET_RX_PROCESSED; + } else { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifindiscards); + } + + /* if no packet could be read, silently ignore this */ + if (p != NULL) { + /* pass all packets to ethernet_input, which decides what packets it supports */ + if (if0->input(p, if0) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + } + + return ret; +} + +int ETHHW_EventCallback(ETHHW_EventDesc *evt) { + if (evt->type == ETHHW_EVT_RX_NOTFY) { + ethernetif_input(if0); + } + + return 0; // unhandled event +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +static void ethernetif_input(struct netif *netif) { + /* read received packets */ + ETHHW_ProcessRx(ETH); +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) { + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + /* store netif for later usage */ + if0 = netif; + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "if0"; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->state = (void *)&linkState; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ +#if LWIP_IPV4 + netif->output = etharp_output; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + /* start up the interface */ + netif_set_up(netif); + + /* refresh and fetch PHY and link status */ + // phy_refresh_link_status(); + // fetch_link_properties(); + + return ERR_OK; +} + +// ----- + +void ETH_IRQHandler() { + ETHHW_ISR(ETH); +} \ No newline at end of file diff --git a/Drivers/EthDrv/eth_drv_lwip.h b/Drivers/EthDrv/eth_drv_lwip.h new file mode 100644 index 0000000..5a2d491 --- /dev/null +++ b/Drivers/EthDrv/eth_drv_lwip.h @@ -0,0 +1,14 @@ +#ifndef ETHDRV_ETH_DRV_LWIP +#define ETHDRV_ETH_DRV_LWIP + +#include +#include + +typedef struct { + bool init; + bool up; + uint16_t speed; + bool duplex; +} LinkState; + +#endif /* ETHDRV_ETH_DRV_LWIP */ diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt index fad6350..012ae53 100644 --- a/Modules/CMakeLists.txt +++ b/Modules/CMakeLists.txt @@ -14,11 +14,36 @@ add_subdirectory(embfmt) add_subdirectory(blocking_io) -set(ETHERLIB_INCLUDES ${include_dirs}) -set(ETHERLIB_CPU_PARAMS ${cpu_PARAMS}) -add_subdirectory(etherlib) +if (ETH_STACK STREQUAL "ETHERLIB") + set(ETHERLIB_INCLUDES ${include_dirs}) + set(ETHERLIB_CPU_PARAMS ${cpu_PARAMS}) + add_subdirectory(etherlib) + + target_link_libraries(${CMAKE_PROJECT_NAME} etherlib) + +elseif (ETH_STACK STREQUAL "LWIP") + set(LWIP_DIR ${CMAKE_CURRENT_LIST_DIR}/lwip) + set(LWIP_PORT_DIR ${CMAKE_CURRENT_LIST_DIR}/lwip_port) + #set(LWIP_CONTRIB_DIR ${LWIP_DIR}/contrib) + set(LWIP_INCLUDE_DIRS + ${LWIP_DIR}/src/include + ${LWIP_DIR}/contrib + ${LWIP_PORT_DIR}/arch + ${LWIP_PORT_DIR} + ${include_dirs} + ) + message(${LWIP_PORT_DIR}) + set(LWIP_COMPILER_FLAGS ${cpu_PARAMS}) + include(${LWIP_DIR}/src/Filelists.cmake) + #include(${LWIP_DIR}/contrib/Filelists.cmake) + + target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${LWIP_DIR}/src/include ${LWIP_PORT_DIR}) + #target_sources(lwipcore PUBLIC ${LWIP_PORT_DIR}/OS/sys_arch.c) + target_sources(${CMAKE_PROJECT_NAME} PUBLIC ${LWIP_PORT_DIR}/OS/sys_arch.c) + + target_link_libraries(${CMAKE_PROJECT_NAME} lwipcore lwipallapps) +endif() target_link_libraries(${CMAKE_PROJECT_NAME} - etherlib embfmt ) diff --git a/Modules/lwip b/Modules/lwip new file mode 160000 index 0000000..d08f477 --- /dev/null +++ b/Modules/lwip @@ -0,0 +1 @@ +Subproject commit d08f4773edd0182b7910fc8f046eed82ffcd67c9 diff --git a/Modules/lwip_port/OS/sys_arch.c b/Modules/lwip_port/OS/sys_arch.c new file mode 100644 index 0000000..4ab5ea7 --- /dev/null +++ b/Modules/lwip_port/OS/sys_arch.c @@ -0,0 +1,477 @@ +/* + * 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 + * + */ + +/* lwIP includes. */ +#include "lwip/arch.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "lwip/sys.h" + +#if !NO_SYS + +#include "cmsis_os2.h" + +#define portNOP() asm("nop") + +#if defined(LWIP_PROVIDE_ERRNO) +int errno; +#endif + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +err_t sys_mbox_new(sys_mbox_t *mbox, int size) { +#if (osCMSIS < 0x20000U) + osMessageQDef(QUEUE, size, void *); + *mbox = osMessageCreate(osMessageQ(QUEUE), NULL); +#else + *mbox = osMessageQueueNew(size, sizeof(void *), NULL); +#endif +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + if (*mbox == NULL) + return ERR_MEM; + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void sys_mbox_free(sys_mbox_t *mbox) { +#if (osCMSIS < 0x20000U) + if (osMessageWaiting(*mbox)) +#else + if (osMessageQueueGetCount(*mbox)) +#endif + { + /* Line for breakpoint. Should never break here! */ + portNOP(); +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + } +#if (osCMSIS < 0x20000U) + osMessageDelete(*mbox); +#else + osMessageQueueDelete(*mbox); +#endif +#if SYS_STATS + --lwip_stats.sys.mbox.used; +#endif /* SYS_STATS */ +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t *mbox, void *data) { +#if (osCMSIS < 0x20000U) + while (osMessagePut(*mbox, (uint32_t)data, osWaitForever) != osOK) + ; +#else + while (osMessageQueuePut(*mbox, &data, 0, osWaitForever) != osOK) + ; +#endif +} + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) { + err_t result; +#if (osCMSIS < 0x20000U) + if (osMessagePut(*mbox, (uint32_t)msg, 0) == osOK) +#else + if (osMessageQueuePut(*mbox, &msg, 0, 0) == osOK) +#endif + { + result = ERR_OK; + } else { + // could not post, queue must be full + result = ERR_MEM; + +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + } + + return result; +} + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg) { + return sys_mbox_trypost(mbox, msg); +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) { +#if (osCMSIS < 0x20000U) + osEvent event; + uint32_t starttime = osKernelSysTick(); +#else + osStatus_t status; + uint32_t starttime = osKernelGetTickCount(); +#endif + if (timeout != 0) { +#if (osCMSIS < 0x20000U) + event = osMessageGet(*mbox, timeout); + + if (event.status == osEventMessage) { + *msg = (void *)event.value.v; + return (osKernelSysTick() - starttime); + } +#else + status = osMessageQueueGet(*mbox, msg, 0, timeout); + if (status == osOK) { + return (osKernelGetTickCount() - starttime); + } +#endif + else { + return SYS_ARCH_TIMEOUT; + } + } else { +#if (osCMSIS < 0x20000U) + event = osMessageGet(*mbox, osWaitForever); + *msg = (void *)event.value.v; + return (osKernelSysTick() - starttime); +#else + osMessageQueueGet(*mbox, msg, 0, osWaitForever); + return (osKernelGetTickCount() - starttime); +#endif + } +} + +/*-----------------------------------------------------------------------------------*/ +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { +#if (osCMSIS < 0x20000U) + osEvent event; + + event = osMessageGet(*mbox, 0); + + if (event.status == osEventMessage) { + *msg = (void *)event.value.v; +#else + if (osMessageQueueGet(*mbox, msg, 0, 0) == osOK) { +#endif + return ERR_OK; + } else { + return SYS_MBOX_EMPTY; + } +} +/*----------------------------------------------------------------------------------*/ +int sys_mbox_valid(sys_mbox_t *mbox) { + if (*mbox == SYS_MBOX_NULL) + return 0; + else + return 1; +} +/*-----------------------------------------------------------------------------------*/ +void sys_mbox_set_invalid(sys_mbox_t *mbox) { + *mbox = SYS_MBOX_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Creates a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +err_t sys_sem_new(sys_sem_t *sem, u8_t count) { +#if (osCMSIS < 0x20000U) + osSemaphoreDef(SEM); + *sem = osSemaphoreCreate(osSemaphore(SEM), 1); +#else + *sem = osSemaphoreNew(UINT16_MAX, count, NULL); +#endif + + if (*sem == NULL) { +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + + if (count == 0) // Means it can't be taken + { +#if (osCMSIS < 0x20000U) + osSemaphoreWait(*sem, 0); +#else + osSemaphoreAcquire(*sem, 0); +#endif + } + +#if SYS_STATS + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) { +#if (osCMSIS < 0x20000U) + uint32_t starttime = osKernelSysTick(); +#else + uint32_t starttime = osKernelGetTickCount(); +#endif + if (timeout != 0) { +#if (osCMSIS < 0x20000U) + if (osSemaphoreWait(*sem, timeout) == osOK) { + return (osKernelSysTick() - starttime); +#else + if (osSemaphoreAcquire(*sem, timeout) == osOK) { + return (osKernelGetTickCount() - starttime); +#endif + } else { + return SYS_ARCH_TIMEOUT; + } + } else { +#if (osCMSIS < 0x20000U) + while (osSemaphoreWait(*sem, osWaitForever) != osOK) + ; + return (osKernelSysTick() - starttime); +#else + while (osSemaphoreAcquire(*sem, osWaitForever) != osOK) + ; + return (osKernelGetTickCount() - starttime); +#endif + } +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void sys_sem_signal(sys_sem_t *sem) { + osSemaphoreRelease(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void sys_sem_free(sys_sem_t *sem) { +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + + osSemaphoreDelete(*sem); +} +/*-----------------------------------------------------------------------------------*/ +int sys_sem_valid(sys_sem_t *sem) { + if (*sem == SYS_SEM_NULL) + return 0; + else + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void sys_sem_set_invalid(sys_sem_t *sem) { + *sem = SYS_SEM_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +#if (osCMSIS < 0x20000U) +osMutexId lwip_sys_mutex; +osMutexDef(lwip_sys_mutex); +#else +osMutexId_t lwip_sys_mutex; +#endif +// Initialize sys arch +void sys_init(void) { +#if (osCMSIS < 0x20000U) + lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex)); +#else + lwip_sys_mutex = osMutexNew(NULL); +#endif +} +/*-----------------------------------------------------------------------------------*/ +/* Mutexes*/ +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ +#if LWIP_COMPAT_MUTEX == 0 +/* Create a new mutex*/ +err_t sys_mutex_new(sys_mutex_t *mutex) { + +#if (osCMSIS < 0x20000U) + osMutexDef(MUTEX); + *mutex = osMutexCreate(osMutex(MUTEX)); +#else + *mutex = osMutexNew(NULL); +#endif + + if (*mutex == NULL) { +#if SYS_STATS + ++lwip_stats.sys.mutex.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + +#if SYS_STATS + ++lwip_stats.sys.mutex.used; + if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) { + lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used; + } +#endif /* SYS_STATS */ + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* Deallocate a mutex*/ +void sys_mutex_free(sys_mutex_t *mutex) { +#if SYS_STATS + --lwip_stats.sys.mutex.used; +#endif /* SYS_STATS */ + + osMutexDelete(*mutex); +} +/*-----------------------------------------------------------------------------------*/ +/* Lock a mutex*/ +void sys_mutex_lock(sys_mutex_t *mutex) { +#if (osCMSIS < 0x20000U) + osMutexWait(*mutex, osWaitForever); +#else + osMutexAcquire(*mutex, osWaitForever); +#endif +} + +/*-----------------------------------------------------------------------------------*/ +/* Unlock a mutex*/ +void sys_mutex_unlock(sys_mutex_t *mutex) { + osMutexRelease(*mutex); +} +#endif /*LWIP_COMPAT_MUTEX*/ +/*-----------------------------------------------------------------------------------*/ +// TODO +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) { +#if (osCMSIS < 0x20000U) + const osThreadDef_t os_thread_def = {(char *)name, (os_pthread)thread, (osPriority)prio, 0, stacksize}; + return osThreadCreate(&os_thread_def, arg); +#else + const osThreadAttr_t attributes = { + .name = name, + .stack_size = stacksize, + .priority = (osPriority_t)prio, + }; + return osThreadNew(thread, arg, &attributes); +#endif +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. + + Note: This function is based on FreeRTOS API, because no equivalent CMSIS-RTOS + API is available +*/ +sys_prot_t sys_arch_protect(void) { +#if (osCMSIS < 0x20000U) + osMutexWait(lwip_sys_mutex, osWaitForever); +#else + osMutexAcquire(lwip_sys_mutex, osWaitForever); +#endif + return (sys_prot_t)1; +} + +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. + + Note: This function is based on FreeRTOS API, because no equivalent CMSIS-RTOS + API is available +*/ +void sys_arch_unprotect(sys_prot_t pval) { + (void)pval; + osMutexRelease(lwip_sys_mutex); +} + +/*-----------------------------------------------------------------------------------*/ + +u32_t sys_now() { + return osKernelGetTickCount(); +} + +#endif /* !NO_SYS */ diff --git a/Modules/lwip_port/arch/bpstruct.h b/Modules/lwip_port/arch/bpstruct.h new file mode 100644 index 0000000..177758c --- /dev/null +++ b/Modules/lwip_port/arch/bpstruct.h @@ -0,0 +1,36 @@ +/* + * 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 + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack(1) +#endif + diff --git a/Modules/lwip_port/arch/cc.h b/Modules/lwip_port/arch/cc.h new file mode 100644 index 0000000..3065318 --- /dev/null +++ b/Modules/lwip_port/arch/cc.h @@ -0,0 +1,88 @@ +/* + * 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 __CC_H__ +#define __CC_H__ + +#include "cpu.h" +#include +#include + +typedef int sys_prot_t; + +#define LWIP_PROVIDE_ERRNO + +#if defined (__GNUC__) & !defined (__CC_ARM) + +#define LWIP_TIMEVAL_PRIVATE 0 +#include + +#endif + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ + x, __LINE__, __FILE__); } while(0) + +/* Define random number generator function */ +#define LWIP_RAND() ((u32_t)rand()) + +#endif /* __CC_H__ */ diff --git a/Modules/lwip_port/arch/cpu.h b/Modules/lwip_port/arch/cpu.h new file mode 100644 index 0000000..bfdf881 --- /dev/null +++ b/Modules/lwip_port/arch/cpu.h @@ -0,0 +1,39 @@ +/* + * 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 __CPU_H__ +#define __CPU_H__ + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#endif /* __CPU_H__ */ diff --git a/Modules/lwip_port/arch/epstruct.h b/Modules/lwip_port/arch/epstruct.h new file mode 100644 index 0000000..1e1a049 --- /dev/null +++ b/Modules/lwip_port/arch/epstruct.h @@ -0,0 +1,36 @@ +/* + * 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 + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack() +#endif + diff --git a/Modules/lwip_port/arch/init.h b/Modules/lwip_port/arch/init.h new file mode 100644 index 0000000..e622c73 --- /dev/null +++ b/Modules/lwip_port/arch/init.h @@ -0,0 +1,44 @@ +/* + * 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 __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg) + +void tcpip_init_done(void *); +int wait_for_tcpip_init(void); + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/Modules/lwip_port/arch/lib.h b/Modules/lwip_port/arch/lib.h new file mode 100644 index 0000000..378f25b --- /dev/null +++ b/Modules/lwip_port/arch/lib.h @@ -0,0 +1,38 @@ +/* + * 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 __LIB_H__ +#define __LIB_H__ + +#include + + +#endif /* __LIB_H__ */ diff --git a/Modules/lwip_port/arch/perf.h b/Modules/lwip_port/arch/perf.h new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/Modules/lwip_port/arch/perf.h @@ -0,0 +1,38 @@ +/* + * 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 __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/Modules/lwip_port/arch/sys_arch.h b/Modules/lwip_port/arch/sys_arch.h new file mode 100644 index 0000000..6371199 --- /dev/null +++ b/Modules/lwip_port/arch/sys_arch.h @@ -0,0 +1,72 @@ +/* + * 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 __SYS_ARCH_H__ +#define __SYS_ARCH_H__ + +#include "lwip/opt.h" + +#if (NO_SYS != 0) +#error "NO_SYS need to be set to 0 to use threaded API" +#endif + +#include "cmsis_os2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if (osCMSIS < 0x20000U) + +#define SYS_MBOX_NULL (osMessageQId)0 +#define SYS_SEM_NULL (osSemaphoreId)0 + +typedef osSemaphoreId sys_sem_t; +typedef osSemaphoreId sys_mutex_t; +typedef osMessageQId sys_mbox_t; +typedef osThreadId sys_thread_t; +#else + +#define SYS_MBOX_NULL (osMessageQueueId_t)0 +#define SYS_SEM_NULL (osSemaphoreId_t)0 + +typedef osSemaphoreId_t sys_sem_t; +typedef osSemaphoreId_t sys_mutex_t; +typedef osMessageQueueId_t sys_mbox_t; +typedef osThreadId_t sys_thread_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SYS_ARCH_H__ */ + diff --git a/Src/cmds.c b/Src/cmds.c index 3ec737c..e703849 100644 --- a/Src/cmds.c +++ b/Src/cmds.c @@ -8,9 +8,14 @@ #include "FreeRTOS.h" #include "cmsis_os2.h" +#ifdef ETH_ETHERLIB #include "etherlib/global_state.h" #include "etherlib/timer.h" #include "etherlib/utils.h" +#elif defined(ETH_LWIP) +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#endif #include "portable.h" #include "standard_output/standard_output.h" @@ -36,6 +41,8 @@ CMD_FUNCTION(phy_info) { return 0; } +#ifdef ETH_ETHERLIB + CMD_FUNCTION(print_ip) { MSGraw("IP: " ANSI_COLOR_BYELLOW); PRINT_IPv4(E.ethIntf->ip); @@ -145,6 +152,19 @@ CMD_FUNCTION(print_hwa) { return 0; } +#elif defined ETH_LWIP + +CMD_FUNCTION(print_ip) { + MSG("IP: " ANSI_COLOR_BYELLOW "%s" ANSI_COLOR_RESET "\n", ipaddr_ntoa(&(netif_default->ip_addr))); + MSG("Gateway: %s\n", ipaddr_ntoa(&(netif_default->gw))); + MSG("Netmask: %s\n", ipaddr_ntoa(&(netif_default->netmask))); + MSGraw(ANSI_COLOR_RESET "\r\n"); + return 0; +} + + +#endif + CMD_FUNCTION(read_all_phy_regs) { phy_read_all_regs(); return 0; @@ -174,6 +194,7 @@ void cmd_init() { cli_register_command("phyinfo \t\t\tPrint Ethernet PHY information", 1, 0, phy_info); cli_register_command("ip \t\t\tPrint IP-address", 1, 0, print_ip); +#ifdef ETH_ETHERLIB cli_register_command("eth tmr \t\t\tPrint EtherLib timer report", 2, 0, eth_tmr); cli_register_command("eth conns \t\t\tPrint active connections", 2, 0, eth_conns); cli_register_command("eth mem \t\t\tPrint EtherLib memory pool state", 2, 0, eth_mem); @@ -182,7 +203,7 @@ void cmd_init() { cli_register_command("eth dhcp [] \t\t\tTurn DHCP ON/OFF", 2, 0, eth_dhcp_onoff); cli_register_command("eth addr [ip|router|netmask|dns] [a.b.c.d] \t\t\tSet or query network addresses", 2, 0, eth_addresses); cli_register_command("eth alladdr \t\t\tSet all four network addresses", 2, 4, eth_alladdr); - +#endif cli_register_command("phy readall \t\t\tRead all PHY registers", 2, 0, read_all_phy_regs); cli_register_command("phy read
\t\t\tRead a single PHY register", 2, 1, read_phy_reg); diff --git a/Src/ethernet/CMakeLists.txt b/Src/ethernet/CMakeLists.txt index 49f1d93..5e2f414 100644 --- a/Src/ethernet/CMakeLists.txt +++ b/Src/ethernet/CMakeLists.txt @@ -1,7 +1,21 @@ +if (ETH_STACK STREQUAL "ETHERLIB") + set(ETH_STACK_SRC + ethernet_etherlib.c + ethernet_etherlib.h + ) +elseif(ETH_STACK STREQUAL "LWIP") + set(ETH_STACK_SRC ethernet_lwip.c) +else() + message("No Ethernet stack was defined!") +endif() + +if (ETH_STACK) + message("Ethernet stack: " ${ETH_STACK}) +endif() + target_sources( ${CMAKE_PROJECT_NAME} PUBLIC - ethernet_etherlib.c - ethernet_etherlib.h + ${ETH_STACK_SRC} ) \ No newline at end of file diff --git a/Src/ethernet/ethernet_lwip.c b/Src/ethernet/ethernet_lwip.c new file mode 100644 index 0000000..a9689a6 --- /dev/null +++ b/Src/ethernet/ethernet_lwip.c @@ -0,0 +1,87 @@ +#include "ethernet_lwip.h" + +#include "Drivers/EthDrv/eth_drv_lwip.h" +#include "cmsis_os2.h" +#include "lwip/dhcp.h" +#include "lwip/ip4_addr.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/tcpip.h" +#include "standard_output/standard_output.h" + +#include +#include + +static ip4_addr_t ipaddr; +static ip4_addr_t netmask; +static ip4_addr_t router; +static struct netif intf; + +err_t ethernetif_init(struct netif *netif); + +static osTimerId_t checkDhcpTmr; + +static bool prevDhcpOK = false; + +void check_dhcp_state(void *param) { + bool dhcpOK = dhcp_supplied_address(&intf); + if (dhcpOK != prevDhcpOK) { + if (dhcpOK) { + MSG("IP-address: %s\n", ipaddr_ntoa(&(netif_default->ip_addr))); + } else { + MSG("DHCP configuration lost!\n"); + } + prevDhcpOK = dhcpOK; + } +} + +void link_chg_cb(struct netif *netif) { + bool ls = netif_is_link_up(netif); + MSG("ETH LINK: %s%s", (ls ? (ANSI_COLOR_BGREEN "UP ") : (ANSI_COLOR_BRED "DOWN\n")), ANSI_COLOR_RESET); + + if (ls) { + LinkState *linkState = (LinkState *)netif->state; + MSG("(%u Mbps, %s duplex)\n", linkState->speed, linkState->duplex ? "FULL" : "HALF"); + } + + if (ls) { + dhcp_start(netif); + } else { + dhcp_stop(netif); + } +} + +void init_ethernet() { + // initialize lwIP + tcpip_init(NULL, NULL); + + // clear all associated addresses + ip_addr_set_zero_ip4(&ipaddr); + ip_addr_set_zero_ip4(&netmask); + ip_addr_set_zero_ip4(&router); + + // add network interface + netif_add(&intf, + &ipaddr, + &netmask, + &router, + NULL, + ethernetif_init, + tcpip_input); + + // make it default + netif_set_default(&intf); + + // register a link change callback + netif_set_link_callback(&intf, link_chg_cb); + + // initialize and start the DHCP-handling + checkDhcpTmr = osTimerNew(check_dhcp_state, osTimerPeriodic, NULL, NULL); + osTimerStart(checkDhcpTmr, 1000); +} + +__attribute__((weak)) err_t hook_unknown_ethertype(struct pbuf *pbuf, struct netif *netif) { + pbuf_free(pbuf); + + return ERR_OK; +} diff --git a/Src/ethernet/ethernet_lwip.h b/Src/ethernet/ethernet_lwip.h new file mode 100644 index 0000000..34d5591 --- /dev/null +++ b/Src/ethernet/ethernet_lwip.h @@ -0,0 +1,6 @@ +#ifndef ETHERNET_ETHERNET_LWIP +#define ETHERNET_ETHERNET_LWIP + +void init_ethernet(); + +#endif /* ETHERNET_ETHERNET_LWIP */ \ No newline at end of file diff --git a/Src/main.c b/Src/main.c index 07bc1ff..a9ccc1a 100644 --- a/Src/main.c +++ b/Src/main.c @@ -118,13 +118,14 @@ void task_startup(void *arg) { print_welcome_message(); // initialize Ethernet - init_ethernet(); + //init_ethernet(); // initialize commands cmd_init(); // ------------- +#ifdef ETH_ETHERLIB cbd cb = udp_new_connblock(E.ethIntf, IPv4_IF_ADDR, 4000, udp_recv_cb); for (;;) { @@ -139,6 +140,11 @@ void task_startup(void *arg) { btn_pressed = false; } } +#elif defined (ETH_LWIP) + for (;;) { + osDelay(1000); + } +#endif } void btn_cb() {