- lwip is available again

This commit is contained in:
András Wiesner 2026-09-18 09:49:20 +02:00
parent 0e8c11c081
commit 6059b083e1
21 changed files with 1474 additions and 11 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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}

View File

@ -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
)

View File

@ -0,0 +1,398 @@
#include "eth_drv_lwip.h"
#include <memory.h>
#include <stdbool.h>
#include <stdint.h>
#include <stm32h7xx_hal.h>
#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 <string.h>
#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);
}

View File

@ -0,0 +1,14 @@
#ifndef ETHDRV_ETH_DRV_LWIP
#define ETHDRV_ETH_DRV_LWIP
#include <stdint.h>
#include <stdbool.h>
typedef struct {
bool init;
bool up;
uint16_t speed;
bool duplex;
} LinkState;
#endif /* ETHDRV_ETH_DRV_LWIP */

View File

@ -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
)

1
Modules/lwip Submodule

@ -0,0 +1 @@
Subproject commit d08f4773edd0182b7910fc8f046eed82ffcd67c9

View File

@ -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 <adam@sics.se>
*
*/
/* 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 */

View File

@ -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 <adam@sics.se>
*
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma pack(1)
#endif

View File

@ -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 <adam@sics.se>
*
*/
#ifndef __CC_H__
#define __CC_H__
#include "cpu.h"
#include <stdlib.h>
#include <stdio.h>
typedef int sys_prot_t;
#define LWIP_PROVIDE_ERRNO
#if defined (__GNUC__) & !defined (__CC_ARM)
#define LWIP_TIMEVAL_PRIVATE 0
#include <sys/time.h>
#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__ */

View File

@ -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 <adam@sics.se>
*
*/
#ifndef __CPU_H__
#define __CPU_H__
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#endif /* __CPU_H__ */

View File

@ -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 <adam@sics.se>
*
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma pack()
#endif

View File

@ -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 <adam@sics.se>
*
*/
#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__ */

View File

@ -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 <adam@sics.se>
*
*/
#ifndef __LIB_H__
#define __LIB_H__
#include <string.h>
#endif /* __LIB_H__ */

View File

@ -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 <adam@sics.se>
*
*/
#ifndef __PERF_H__
#define __PERF_H__
#define PERF_START /* null definition */
#define PERF_STOP(x) /* null definition */
#endif /* __PERF_H__ */

View File

@ -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 <adam@sics.se>
*
*/
#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__ */

View File

@ -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 [<on|off>] \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 <ip> <router> <netmask> <dns> \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 <address>\t\t\tRead a single PHY register", 2, 1, read_phy_reg);

View File

@ -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}
)

View File

@ -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 <stdbool.h>
#include <stddef.h>
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;
}

View File

@ -0,0 +1,6 @@
#ifndef ETHERNET_ETHERNET_LWIP
#define ETHERNET_ETHERNET_LWIP
void init_ethernet();
#endif /* ETHERNET_ETHERNET_LWIP */

View File

@ -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() {