diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c index 384698ef3..b018be453 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c @@ -38,7 +38,7 @@ char tcp_socket_ip[] = {192, 168, 250, 252}; -#define TCP_BUF_SIZE 1024 +#define TCP_DEMO_BUF_SIZE 65535 /******************************************************************************* * Code @@ -46,17 +46,15 @@ char tcp_socket_ip[] = {192, 168, 250, 252}; static void tcp_recv_demo(void *arg) { - lw_print("tcp_recv_demo start.\n"); - - int fd = -1; - char *recv_buf; - struct sockaddr_in tcp_addr, server_addr; + int fd = -1, clientfd; int recv_len; + char *recv_buf; + struct sockaddr_in tcp_addr; socklen_t addr_len; while(1) { - recv_buf = (char *)malloc(TCP_BUF_SIZE); + recv_buf = (char *)malloc(TCP_DEMO_BUF_SIZE); if (recv_buf == NULL) { lw_print("No memory\n"); @@ -81,16 +79,30 @@ static void tcp_recv_demo(void *arg) goto __exit; } - lw_print("tcp bind sucess, start to receive.\n"); + lw_print("tcp bind success, start to receive.\n"); lw_print("\n\nLocal Port:%d\n\n", LWIP_LOCAL_PORT); + // setup socket fd as listening mode + if (listen(fd, 5) != 0 ) + { + lw_print("Unable to listen\n"); + goto __exit; + } + + // accept client connection + clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len); + lw_print("client %s connected\n", inet_ntoa(tcp_addr.sin_addr)); + while(1) { - memset(recv_buf, 0, TCP_BUF_SIZE); - recv_len = recvfrom(fd, recv_buf, TCP_BUF_SIZE, 0, (struct sockaddr *)&server_addr, &addr_len); - lw_pr_info("Receive from : %s\n", inet_ntoa(server_addr.sin_addr)); - lw_pr_info("Receive data : %s\n\n", recv_buf); - sendto(fd, recv_buf, recv_len, 0, (struct sockaddr*)&server_addr, addr_len); + memset(recv_buf, 0, TCP_DEMO_BUF_SIZE); + recv_len = recvfrom(clientfd, recv_buf, TCP_DEMO_BUF_SIZE, 0, (struct sockaddr *)&tcp_addr, &addr_len); + if(recv_len > 0) + { + lw_pr_info("Receive from : %s\n", inet_ntoa(tcp_addr.sin_addr)); + lw_pr_info("Receive data : %d - %s\n\n", recv_len, recv_buf); + } + sendto(clientfd, recv_buf, recv_len, 0, (struct sockaddr*)&tcp_addr, addr_len); } __exit: @@ -116,7 +128,7 @@ void tcp_socket_recv_run(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("tcp_recv_demo", tcp_recv_demo, NULL, 4096, 15); + sys_thread_new("tcp_recv_demo", tcp_recv_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), @@ -125,10 +137,11 @@ SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | static void tcp_send_demo(void *arg) { int cnt = LWIP_DEMO_TIMES; - lw_print("tcp_send_demo start.\n"); int fd = -1; char send_msg[128]; + lw_print("%s start\n", __func__); + memset(send_msg, 0, sizeof(send_msg)); fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) @@ -140,7 +153,7 @@ static void tcp_send_demo(void *arg) struct sockaddr_in tcp_sock; tcp_sock.sin_family = AF_INET; tcp_sock.sin_port = htons(LWIP_TARGET_PORT); - tcp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(tcp_socket_ip[0],tcp_socket_ip[1],tcp_socket_ip[2],tcp_socket_ip[3])); + tcp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(tcp_socket_ip[0], tcp_socket_ip[1], tcp_socket_ip[2], tcp_socket_ip[3])); memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero)); if (connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr))) @@ -150,14 +163,14 @@ static void tcp_send_demo(void *arg) } lw_print("tcp connect success, start to send.\n"); - lw_print("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); + lw_pr_info("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); while (cnt --) { lw_print("Lwip client is running.\n"); snprintf(send_msg, sizeof(send_msg), "TCP test package times %d\r\n", cnt); sendto(fd, send_msg, strlen(send_msg), 0, (struct sockaddr*)&tcp_sock, sizeof(struct sockaddr)); - lw_print("Send tcp msg: %s ", send_msg); + lw_pr_info("Send tcp msg: %s ", send_msg); MdelayKTask(1000); } @@ -178,8 +191,8 @@ void tcp_socket_send_run(int argc, char *argv[]) } ETH_BSP_Config(); - lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("tcp socket", tcp_send_demo, NULL, 4096, 25); + lwip_config_tcp(lwip_ipaddr, lwip_netmask, tcp_socket_ip); + sys_thread_new("tcp socket", tcp_send_demo, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c index aafb460a2..dd91ce952 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c @@ -1,741 +1,686 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. 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 - * - */ - -/* - * Copyright (c) 2013-2016, Freescale Semiconductor, Inc. - * Copyright 2016-2019 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* - * Copyright (c) 2021 AIIT XUOS Lab - * XiUOS is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -/** - * @file enet_ethernetif_kinetis.c - * @brief ethernet drivers - * @version 1.0 - * @author AIIT XUOS Lab - * @date 2021.11.11 - */ - -#include "lwip/opt.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/ethip6.h" -#include "netif/etharp.h" -#include "netif/ppp/pppoe.h" -#include "lwip/igmp.h" -#include "lwip/mld6.h" - -//#define USE_RTOS 1 -//#define FSL_RTOS_FREE_RTOS -//#define FSL_RTOS_XIUOS - -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - -#ifdef FSL_RTOS_XIUOS -#include "xs_sem.h" - -#else -#include "FreeRTOS.h" -#include "event_groups.h" -#include "list.h" -#endif - -typedef uint32_t TickType_t; -#define portMAX_DELAY ( TickType_t ) 0xffffffffUL - -typedef TickType_t EventBits_t; - -typedef long BaseType_t; -typedef unsigned long UBaseType_t; - -#define portBASE_TYPE long - -#define pdFALSE ( ( BaseType_t ) 0 ) -#define pdTRUE ( ( BaseType_t ) 1 ) - -#define pdPASS ( pdTRUE ) -#define pdFAIL ( pdFALSE ) - -#ifndef FSL_RTOS_XIUOS -typedef struct EventGroupDef_t -{ - EventBits_t uxEventBits; - List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ - - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxEventGroupNumber; - #endif - - #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ - #endif -} EventGroup_t; - -struct EventGroupDef_t; -typedef struct EventGroupDef_t * EventGroupHandle_t; -#else -int lwip_sempahore; -#endif - -#endif - -#include "enet_ethernetif.h" -#include "enet_ethernetif_priv.h" - -#include "fsl_enet.h" -#include "fsl_phy.h" - -#include "sys_arch.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/** - * Helper struct to hold private data used to operate your ethernet interface. - */ -struct ethernetif -{ - ENET_Type *base; -#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)) || \ - (USE_RTOS && defined(FSL_RTOS_FREE_RTOS)) - enet_handle_t handle; -#endif -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - -#ifdef FSL_RTOS_XIUOS - int enetSemaphore; -#else - EventGroupHandle_t enetTransmitAccessEvent; -#endif - EventBits_t txFlag; -#endif - enet_rx_bd_struct_t *RxBuffDescrip; - enet_tx_bd_struct_t *TxBuffDescrip; - rx_buffer_t *RxDataBuff; - tx_buffer_t *TxDataBuff; -}; - - -/******************************************************************************* - * Code - ******************************************************************************/ -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - -int32 lwip_obtain_semaphore(struct netif *netif) -{ - struct ethernetif *ethernetif = netif->state; - return (KSemaphoreObtain(ethernetif->enetSemaphore, WAITING_FOREVER) == EOK); -} - -#if FSL_FEATURE_ENET_QUEUE > 1 -static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, uint32_t ringId, enet_event_t event, void *param) -#else -static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) -#endif /* FSL_FEATURE_ENET_QUEUE */ -{ - struct netif *netif = (struct netif *)param; - struct ethernetif *ethernetif = netif->state; - BaseType_t xResult; - - switch (event) - { - case kENET_RxEvent: - ethernetif_input(netif); - break; - case kENET_TxEvent: -#ifdef FSL_RTOS_XIUOS - -#else - { - portBASE_TYPE taskToWake = pdFALSE; - -#ifdef __CA7_REV - if (SystemGetIRQNestingLevel()) -#else - if (__get_IPSR()) -#endif - { - xResult = xEventGroupSetBitsFromISR(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, &taskToWake); - if ((pdPASS == xResult) && (pdTRUE == taskToWake)) - { - portYIELD_FROM_ISR(taskToWake); - } - } - else - { - xEventGroupSetBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag); - } - } -#endif - break; - default: - break; - } - -// KSemaphoreAbandon(ethernetif->enetSemaphore); - KSemaphoreAbandon(lwip_sempahore); -} -#endif - -#if LWIP_IPV4 && LWIP_IGMP -err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, - enum netif_mac_filter_action action) -{ - struct ethernetif *ethernetif = netif->state; - uint8_t multicastMacAddr[6]; - err_t result; - - multicastMacAddr[0] = 0x01U; - multicastMacAddr[1] = 0x00U; - multicastMacAddr[2] = 0x5EU; - multicastMacAddr[3] = (group->addr >> 8) & 0x7FU; - multicastMacAddr[4] = (group->addr >> 16) & 0xFFU; - multicastMacAddr[5] = (group->addr >> 24) & 0xFFU; - - switch (action) - { - case IGMP_ADD_MAC_FILTER: - /* Adds the ENET device to a multicast group.*/ - ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); - result = ERR_OK; - break; - case IGMP_DEL_MAC_FILTER: - /* - * Moves the ENET device from a multicast group. - * Since the ENET_LeaveMulticastGroup() could filter out also other - * group addresses having the same hash, the call is commented out. - */ - /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ - result = ERR_OK; - break; - default: - result = ERR_IF; - break; - } - - return result; -} -#endif - -#if LWIP_IPV6 && LWIP_IPV6_MLD -err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, - enum netif_mac_filter_action action) -{ - struct ethernetif *ethernetif = netif->state; - uint8_t multicastMacAddr[6]; - err_t result; - - multicastMacAddr[0] = 0x33U; - multicastMacAddr[1] = 0x33U; - multicastMacAddr[2] = (group->addr[3]) & 0xFFU; - multicastMacAddr[3] = (group->addr[3] >> 8) & 0xFFU; - multicastMacAddr[4] = (group->addr[3] >> 16) & 0xFFU; - multicastMacAddr[5] = (group->addr[3] >> 24) & 0xFFU; - - switch (action) - { - case NETIF_ADD_MAC_FILTER: - /* Adds the ENET device to a multicast group.*/ - ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); - result = ERR_OK; - break; - case NETIF_DEL_MAC_FILTER: - /* - * Moves the ENET device from a multicast group. - * Since the ENET_LeaveMulticastGroup() could filter out also other - * group addresses having the same hash, the call is commented out. - */ - /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ - result = ERR_OK; - break; - default: - result = ERR_IF; - break; - } - - return result; -} -#endif - -#define netifINTERFACE_TASK_STACK_SIZE ( 4096 ) - -/** - * This function is the ethernetif_input task, it is processed 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 - */ -//void eth_input( void * pvParameters ) -//{ -// struct pbuf *p; -// -// for( ;; ) -// { -// if (KSemaphoreObtain( lwip_sempahore, WAITING_FOREVER)==EOK) -// { -// p = low_level_input( s_pxNetIf ); -// -// if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) -// { -// KPrintf("netif input return not OK ! \n"); -// pbuf_free(p); -// p=NULL; -// } -// } -// } -//} -// -//void low_level_init() -//{ -// /* create the task that handles the ETH_MAC */ -// uint32 thr_id = KTaskCreate((signed char*) "eth_input", -// eth_input, -// NULL, -// netifINTERFACE_TASK_STACK_SIZE, -// 15); -// if (thr_id >= 0) -// { -// StartupKTask(thr_id); -// } -// else -// { -// KPrintf("Eth create failed !"); -// } -//} - - -/** - * Initializes ENET driver. - */ -void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif, - const ethernetif_config_t *ethernetifConfig) -{ - enet_config_t config; - uint32_t sysClock; - enet_buffer_config_t buffCfg[ENET_RING_NUM]; - - /* prepare the buffer configuration. */ - buffCfg[0].rxBdNumber = ENET_RXBD_NUM; /* Receive buffer descriptor number. */ - buffCfg[0].txBdNumber = ENET_TXBD_NUM; /* Transmit buffer descriptor number. */ - buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t); /* Aligned receive data buffer size. */ - buffCfg[0].txBuffSizeAlign = sizeof(tx_buffer_t); /* Aligned transmit data buffer size. */ - buffCfg[0].rxBdStartAddrAlign = &(ethernetif->RxBuffDescrip[0]); /* Aligned receive buffer descriptor start address. */ - buffCfg[0].txBdStartAddrAlign = &(ethernetif->TxBuffDescrip[0]); /* Aligned transmit buffer descriptor start address. */ - buffCfg[0].rxBufferAlign = &(ethernetif->RxDataBuff[0][0]); /* Receive data buffer start address. */ - buffCfg[0].txBufferAlign = &(ethernetif->TxDataBuff[0][0]); /* Transmit data buffer start address. */ - - sysClock = CLOCK_GetFreq(ethernetifConfig->clockName); - - ENET_GetDefaultConfig(&config); - config.ringNum = ENET_RING_NUM; - - ethernetif_phy_init(ethernetif, ethernetifConfig, &config); - -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - uint32_t instance; - static ENET_Type *const enetBases[] = ENET_BASE_PTRS; - static const IRQn_Type enetTxIrqId[] = ENET_Transmit_IRQS; - /*! @brief Pointers to enet receive IRQ number for each instance. */ - static const IRQn_Type enetRxIrqId[] = ENET_Receive_IRQS; -#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - /*! @brief Pointers to enet timestamp IRQ number for each instance. */ - static const IRQn_Type enetTsIrqId[] = ENET_1588_Timer_IRQS; -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ - - /* Create the Event for transmit busy release trigger. */ -#ifdef FSL_RTOS_XIUOS - if(ethernetif->enetSemaphore < 0) - { - ethernetif->enetSemaphore = KSemaphoreCreate(0); - } -// lwip_sempahore = KSemaphoreCreate(0); -#else - ethernetif->enetTransmitAccessEvent = xEventGroupCreate(); -#endif - ethernetif->txFlag = 0x1; - - config.interrupt |= kENET_RxFrameInterrupt | kENET_TxFrameInterrupt | kENET_TxBufferInterrupt; - - for (instance = 0; instance < ARRAY_SIZE(enetBases); instance++) - { - if (enetBases[instance] == ethernetif->base) - { -#ifdef __CA7_REV - GIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); - GIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); -#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - GIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ -#else - NVIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); - NVIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); -#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE - NVIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); -#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ -#endif /* __CA7_REV */ - break; - } - } - - LWIP_ASSERT("Input Ethernet base error!", (instance != ARRAY_SIZE(enetBases))); -#endif /* USE_RTOS */ - - /* Initialize the ENET module.*/ - ENET_Init(ethernetif->base, ðernetif->handle, &config, &buffCfg[0], netif->hwaddr, sysClock); - -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - ENET_SetCallback(ðernetif->handle, ethernet_callback, netif); -#endif - - ENET_ActiveRead(ethernetif->base); -// low_level_init(); -} - -ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif) -{ - return &(ethernetif->base); -} - -/** - * Returns next buffer for TX. - * Can wait if no buffer available. - */ -static unsigned char *enet_get_tx_buffer(struct ethernetif *ethernetif) -{ - static unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN]; - return ucBuffer; -} - -/** - * Sends frame via ENET. - */ -static err_t enet_send_frame(struct ethernetif *ethernetif, unsigned char *data, const uint32_t length) -{ -#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) - { - status_t result; - - lw_print("lw: [%s] len %d\n", __func__, length); - - do - { - result = ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length); - - if (result == kStatus_ENET_TxFrameBusy) - { -#ifdef FSL_RTOS_XIUOS - KSemaphoreObtain(ethernetif->enetSemaphore, portMAX_DELAY); -// KSemaphoreObtain(lwip_sempahore, portMAX_DELAY); -#else - xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false, - portMAX_DELAY); -#endif - } - - } while (result == kStatus_ENET_TxFrameBusy); - - return ERR_OK; - } -#else - { - uint32_t counter; - - for (counter = ENET_TIMEOUT; counter != 0U; counter--) - { - if (ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length) != kStatus_ENET_TxFrameBusy) - { - return ERR_OK; - } - } - - return ERR_TIMEOUT; - } -#endif -} - -struct pbuf *ethernetif_linkinput(struct netif *netif) -{ - struct ethernetif *ethernetif = netif->state; - struct pbuf *p = NULL; - struct pbuf *q; - uint32_t len; - status_t status; - - /* Obtain the size of the packet and put it into the "len" - variable. */ - status = ENET_GetRxFrameSize(ðernetif->handle, &len); - - if (kStatus_ENET_RxFrameEmpty != status) - { - /* Call ENET_ReadFrame when there is a received frame. */ - if (len != 0) - { -#if ETH_PAD_SIZE - len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ -#endif - - /* We allocate a pbuf chain of pbufs from the pool. */ - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - - if (p != NULL) - { -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - if (p->next == 0) /* One-chain buffer.*/ - { - ENET_ReadFrame(ethernetif->base, ðernetif->handle, p->payload, p->len); - } - else /* Multi-chain buffer.*/ - { - uint8_t data_tmp[ENET_FRAME_MAX_FRAMELEN]; - uint32_t data_tmp_len = 0; - - ENET_ReadFrame(ethernetif->base, ðernetif->handle, data_tmp, p->tot_len); - - /* We iterate over the pbuf chain until we have read the entire - * packet into the pbuf. */ - for (q = p; (q != NULL) && ((data_tmp_len + q->len) <= sizeof(data_tmp)); 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. */ - memcpy(q->payload, &data_tmp[data_tmp_len], q->len); - data_tmp_len += q->len; - } - } - - 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); - } -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.recv); - } - else - { - /* drop packet*/ - ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); - - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: Fail to allocate new memory space\n")); - - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifindiscards); - } - } - else - { - /* Update the received buffer when error happened. */ - if (status == kStatus_ENET_RxFrameError) - { -#if 0 && defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0) /* Error statisctics */ - enet_data_error_stats_t eErrStatic; - /* Get the error information of the received g_frame. */ - ENET_GetRxErrBeforeReadFrame(ðernetif->handle, &eErrStatic); -#endif - /* Update the receive buffer. */ - ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); - - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n")); - - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifindiscards); - } - } - } - - return p; -} - -err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) -{ - err_t result; - struct ethernetif *ethernetif = netif->state; - struct pbuf *q; - unsigned char *pucBuffer; - unsigned char *pucChar; - - LWIP_ASSERT("Output packet buffer empty", p); - - pucBuffer = enet_get_tx_buffer(ethernetif); - if (pucBuffer == NULL) - { - return ERR_BUF; - } - -/* Initiate transfer. */ - -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - - if (p->len == p->tot_len) - { - /* No pbuf chain, don't have to copy -> faster. */ - pucBuffer = (unsigned char *)p->payload; - } - else - { - /* pbuf chain, copy into contiguous ucBuffer. */ - if (p->tot_len > ENET_FRAME_MAX_FRAMELEN) - { - return ERR_BUF; - } - else - { - pucChar = pucBuffer; - - 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. */ - /* send data from(q->payload, q->len); */ - memcpy(pucChar, q->payload, q->len); - pucChar += q->len; - } - } - } - - /* Send frame. */ - result = enet_send_frame(ethernetif, pucBuffer, p->tot_len); - - 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_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.xmit); - - return result; -} - -/** - * Should be called at the beginning of the program to set up the - * first network interface. It calls the function ethernetif_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 ethernetif0_init(struct netif *netif) -{ - static struct ethernetif ethernetif_0; - AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static tx_buffer_t txDataBuff_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - - ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]); - ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]); - ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]); - ethernetif_0.TxDataBuff = &(txDataBuff_0[0]); - - return ethernetif_init(netif, ðernetif_0, 0U, (ethernetif_config_t *)netif->state); -} - -#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1) -/** - * Should be called at the beginning of the program to set up the - * second network interface. It calls the function ethernetif_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 ethernetif1_init(struct netif *netif) -{ - static struct ethernetif ethernetif_1; - AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - SDK_ALIGN(static tx_buffer_t txDataBuff_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); - - ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]); - ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]); - ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]); - ethernetif_1.TxDataBuff = &(txDataBuff_1[0]); - - return ethernetif_init(netif, ðernetif_1, 1U, (ethernetif_config_t *)netif->state); -} -#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. 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 + * + */ + +/* + * Copyright (c) 2013-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Copyright (c) 2021 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * @file enet_ethernetif_kinetis.c + * @brief ethernet drivers + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021.11.11 + */ + +#include "sys_arch.h" +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "netif/ppp/pppoe.h" +#include "lwip/igmp.h" +#include "lwip/mld6.h" + +#ifdef FSL_RTOS_XIUOS +#define USE_RTOS 1 +#define FSL_RTOS_FREE_RTOS +#endif + +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + +#ifdef FSL_RTOS_XIUOS +#include "xs_sem.h" + +#else +#include "FreeRTOS.h" +#include "event_groups.h" +#include "list.h" +#endif + +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +typedef TickType_t EventBits_t; + +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#define portBASE_TYPE long + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) + +#ifndef FSL_RTOS_XIUOS +typedef struct EventGroupDef_t +{ + EventBits_t uxEventBits; + List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif + + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ + #endif +} EventGroup_t; + +struct EventGroupDef_t; +typedef struct EventGroupDef_t * EventGroupHandle_t; +#endif + +#endif + +#include "enet_ethernetif.h" +#include "enet_ethernetif_priv.h" + +#include "fsl_enet.h" +#include "fsl_phy.h" + +#include "sys_arch.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/** + * Helper struct to hold private data used to operate your ethernet interface. + */ +struct ethernetif +{ + ENET_Type *base; +#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)) || \ + (USE_RTOS && defined(FSL_RTOS_FREE_RTOS)) + enet_handle_t handle; +#endif +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + +#ifdef FSL_RTOS_XIUOS + int enetSemaphore; +#else + EventGroupHandle_t enetTransmitAccessEvent; +#endif + EventBits_t txFlag; +#endif + enet_rx_bd_struct_t *RxBuffDescrip; + enet_tx_bd_struct_t *TxBuffDescrip; + rx_buffer_t *RxDataBuff; + tx_buffer_t *TxDataBuff; +}; + + +/******************************************************************************* + * Code + ******************************************************************************/ +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + +int32 lwip_obtain_semaphore(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + return (KSemaphoreObtain(ethernetif->enetSemaphore, WAITING_FOREVER) == EOK); +} + +#if FSL_FEATURE_ENET_QUEUE > 1 +static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, uint32_t ringId, enet_event_t event, void *param) +#else +static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) +#endif /* FSL_FEATURE_ENET_QUEUE */ +{ + struct netif *netif = (struct netif *)param; + struct ethernetif *ethernetif = netif->state; + BaseType_t xResult; + + switch (event) + { + case kENET_RxEvent: + ethernetif_input(netif); + break; + case kENET_TxEvent: +#ifndef FSL_RTOS_XIUOS + { + portBASE_TYPE taskToWake = pdFALSE; + +#ifdef __CA7_REV + if (SystemGetIRQNestingLevel()) +#else + if (__get_IPSR()) +#endif + { + xResult = xEventGroupSetBitsFromISR(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, &taskToWake); + if ((pdPASS == xResult) && (pdTRUE == taskToWake)) + { + portYIELD_FROM_ISR(taskToWake); + } + } + else + { + xEventGroupSetBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag); + } + } +#endif + break; + default: + break; + } + + KSemaphoreAbandon(ethernetif->enetSemaphore); +} +#endif + +#if LWIP_IPV4 && LWIP_IGMP +err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, + enum netif_mac_filter_action action) +{ + struct ethernetif *ethernetif = netif->state; + uint8_t multicastMacAddr[6]; + err_t result; + + multicastMacAddr[0] = 0x01U; + multicastMacAddr[1] = 0x00U; + multicastMacAddr[2] = 0x5EU; + multicastMacAddr[3] = (group->addr >> 8) & 0x7FU; + multicastMacAddr[4] = (group->addr >> 16) & 0xFFU; + multicastMacAddr[5] = (group->addr >> 24) & 0xFFU; + + switch (action) + { + case IGMP_ADD_MAC_FILTER: + /* Adds the ENET device to a multicast group.*/ + ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); + result = ERR_OK; + break; + case IGMP_DEL_MAC_FILTER: + /* + * Moves the ENET device from a multicast group. + * Since the ENET_LeaveMulticastGroup() could filter out also other + * group addresses having the same hash, the call is commented out. + */ + /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ + result = ERR_OK; + break; + default: + result = ERR_IF; + break; + } + + return result; +} +#endif + +#if LWIP_IPV6 && LWIP_IPV6_MLD +err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, + enum netif_mac_filter_action action) +{ + struct ethernetif *ethernetif = netif->state; + uint8_t multicastMacAddr[6]; + err_t result; + + multicastMacAddr[0] = 0x33U; + multicastMacAddr[1] = 0x33U; + multicastMacAddr[2] = (group->addr[3]) & 0xFFU; + multicastMacAddr[3] = (group->addr[3] >> 8) & 0xFFU; + multicastMacAddr[4] = (group->addr[3] >> 16) & 0xFFU; + multicastMacAddr[5] = (group->addr[3] >> 24) & 0xFFU; + + switch (action) + { + case NETIF_ADD_MAC_FILTER: + /* Adds the ENET device to a multicast group.*/ + ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr); + result = ERR_OK; + break; + case NETIF_DEL_MAC_FILTER: + /* + * Moves the ENET device from a multicast group. + * Since the ENET_LeaveMulticastGroup() could filter out also other + * group addresses having the same hash, the call is commented out. + */ + /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */ + result = ERR_OK; + break; + default: + result = ERR_IF; + break; + } + + return result; +} +#endif + +/** + * Initializes ENET driver. + */ +void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif, + const ethernetif_config_t *ethernetifConfig) +{ + enet_config_t config; + uint32_t sysClock; + enet_buffer_config_t buffCfg[ENET_RING_NUM]; + + /* prepare the buffer configuration. */ + buffCfg[0].rxBdNumber = ENET_RXBD_NUM; /* Receive buffer descriptor number. */ + buffCfg[0].txBdNumber = ENET_TXBD_NUM; /* Transmit buffer descriptor number. */ + buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t); /* Aligned receive data buffer size. */ + buffCfg[0].txBuffSizeAlign = sizeof(tx_buffer_t); /* Aligned transmit data buffer size. */ + buffCfg[0].rxBdStartAddrAlign = &(ethernetif->RxBuffDescrip[0]); /* Aligned receive buffer descriptor start address. */ + buffCfg[0].txBdStartAddrAlign = &(ethernetif->TxBuffDescrip[0]); /* Aligned transmit buffer descriptor start address. */ + buffCfg[0].rxBufferAlign = &(ethernetif->RxDataBuff[0][0]); /* Receive data buffer start address. */ + buffCfg[0].txBufferAlign = &(ethernetif->TxDataBuff[0][0]); /* Transmit data buffer start address. */ + + sysClock = CLOCK_GetFreq(ethernetifConfig->clockName); + + ENET_GetDefaultConfig(&config); + config.ringNum = ENET_RING_NUM; + + ethernetif_phy_init(ethernetif, ethernetifConfig, &config); + +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + uint32_t instance; + static ENET_Type *const enetBases[] = ENET_BASE_PTRS; + static const IRQn_Type enetTxIrqId[] = ENET_Transmit_IRQS; + /*! @brief Pointers to enet receive IRQ number for each instance. */ + static const IRQn_Type enetRxIrqId[] = ENET_Receive_IRQS; +#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + /*! @brief Pointers to enet timestamp IRQ number for each instance. */ + static const IRQn_Type enetTsIrqId[] = ENET_1588_Timer_IRQS; +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + + /* Create the Event for transmit busy release trigger. */ +#ifdef FSL_RTOS_XIUOS + if(ethernetif->enetSemaphore < 0) + { + ethernetif->enetSemaphore = KSemaphoreCreate(0); + } +#else + ethernetif->enetTransmitAccessEvent = xEventGroupCreate(); +#endif + ethernetif->txFlag = 0x1; + + config.interrupt |= kENET_RxFrameInterrupt | kENET_TxFrameInterrupt | kENET_TxBufferInterrupt; + + for (instance = 0; instance < ARRAY_SIZE(enetBases); instance++) + { + if (enetBases[instance] == ethernetif->base) + { +#ifdef __CA7_REV + GIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); + GIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); +#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + GIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ +#else + NVIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY); + NVIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY); +#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + NVIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY); +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ +#endif /* __CA7_REV */ + break; + } + } + + LWIP_ASSERT("Input Ethernet base error!", (instance != ARRAY_SIZE(enetBases))); +#endif /* USE_RTOS */ + + /* Initialize the ENET module.*/ + ENET_Init(ethernetif->base, ðernetif->handle, &config, &buffCfg[0], netif->hwaddr, sysClock); + +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + ENET_SetCallback(ðernetif->handle, ethernet_callback, netif); +#endif + + ENET_ActiveRead(ethernetif->base); +// low_level_init(); +} + +ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif) +{ + return &(ethernetif->base); +} + +/** + * Returns next buffer for TX. + * Can wait if no buffer available. + */ +static unsigned char *enet_get_tx_buffer(struct ethernetif *ethernetif) +{ + static unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN]; + return ucBuffer; +} + +/** + * Sends frame via ENET. + */ +static err_t enet_send_frame(struct ethernetif *ethernetif, unsigned char *data, const uint32_t length) +{ +#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS) + { + status_t result; + + lw_print("lw: [%s] len %d\n", __func__, length); + + do + { + result = ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length); + + if (result == kStatus_ENET_TxFrameBusy) + { +#ifdef FSL_RTOS_XIUOS + KSemaphoreObtain(ethernetif->enetSemaphore, portMAX_DELAY); +#else + xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false, + portMAX_DELAY); +#endif + } + + } while (result == kStatus_ENET_TxFrameBusy); + + return ERR_OK; + } +#else + { + uint32_t counter; + + for (counter = ENET_TIMEOUT; counter != 0U; counter--) + { + if (ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length) != kStatus_ENET_TxFrameBusy) + { + return ERR_OK; + } + } + + return ERR_TIMEOUT; + } +#endif +} + +struct pbuf *ethernetif_linkinput(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *p = NULL; + struct pbuf *q; + uint32_t len; + status_t status; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + status = ENET_GetRxFrameSize(ðernetif->handle, &len); + + if (kStatus_ENET_RxFrameEmpty != status) + { + /* Call ENET_ReadFrame when there is a received frame. */ + if (len != 0) + { +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) + { +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + if (p->next == 0) /* One-chain buffer.*/ + { + ENET_ReadFrame(ethernetif->base, ðernetif->handle, p->payload, p->len); + } + else /* Multi-chain buffer.*/ + { + uint8_t data_tmp[ENET_FRAME_MAX_FRAMELEN]; + uint32_t data_tmp_len = 0; + + ENET_ReadFrame(ethernetif->base, ðernetif->handle, data_tmp, p->tot_len); + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; (q != NULL) && ((data_tmp_len + q->len) <= sizeof(data_tmp)); 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. */ + memcpy(q->payload, &data_tmp[data_tmp_len], q->len); + data_tmp_len += q->len; + } + } + + 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); + } +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } + else + { + /* drop packet*/ + ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); + + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: Fail to allocate new memory space\n")); + + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifindiscards); + } + } + else + { + /* Update the received buffer when error happened. */ + if (status == kStatus_ENET_RxFrameError) + { +#if 0 && defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0) /* Error statisctics */ + enet_data_error_stats_t eErrStatic; + /* Get the error information of the received g_frame. */ + ENET_GetRxErrBeforeReadFrame(ðernetif->handle, &eErrStatic); +#endif + /* Update the receive buffer. */ + ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U); + + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n")); + + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifindiscards); + } + } + } + + return p; +} + +err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) +{ + err_t result; + struct ethernetif *ethernetif = netif->state; + struct pbuf *q; + unsigned char *pucBuffer; + unsigned char *pucChar; + + LWIP_ASSERT("Output packet buffer empty", p); + + pucBuffer = enet_get_tx_buffer(ethernetif); + if (pucBuffer == NULL) + { + return ERR_BUF; + } + +/* Initiate transfer. */ + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + if (p->len == p->tot_len) + { + /* No pbuf chain, don't have to copy -> faster. */ + pucBuffer = (unsigned char *)p->payload; + } + else + { + /* pbuf chain, copy into contiguous ucBuffer. */ + if (p->tot_len > ENET_FRAME_MAX_FRAMELEN) + { + return ERR_BUF; + } + else + { + pucChar = pucBuffer; + + 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. */ + /* send data from(q->payload, q->len); */ + memcpy(pucChar, q->payload, q->len); + pucChar += q->len; + } + } + } + + /* Send frame. */ + result = enet_send_frame(ethernetif, pucBuffer, p->tot_len); + + 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_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return result; +} + +/** + * Should be called at the beginning of the program to set up the + * first network interface. It calls the function ethernetif_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 ethernetif0_init(struct netif *netif) +{ + static struct ethernetif ethernetif_0; + AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static tx_buffer_t txDataBuff_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + + ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]); + ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]); + ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]); + ethernetif_0.TxDataBuff = &(txDataBuff_0[0]); + + return ethernetif_init(netif, ðernetif_0, 0U, (ethernetif_config_t *)netif->state); +} + +#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1) +/** + * Should be called at the beginning of the program to set up the + * second network interface. It calls the function ethernetif_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 ethernetif1_init(struct netif *netif) +{ + static struct ethernetif ethernetif_1; + AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + SDK_ALIGN(static tx_buffer_t txDataBuff_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT); + + ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]); + ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]); + ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]); + ethernetif_1.TxDataBuff = &(txDataBuff_1[0]); + + return ethernetif_init(netif, ðernetif_1, 1U, (ethernetif_config_t *)netif->state); +} +#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */ diff --git a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c index df323a9e5..388263fcb 100644 --- a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c +++ b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.c @@ -84,11 +84,9 @@ char lwip_ipaddr[] = {192, 168, 250, 253}; char lwip_netmask[] = {255, 255, 255, 0}; char lwip_gwaddr[] = {192, 168, 250, 252}; - -int is_lwip_test = 0; //for lwip input thread +char lwip_flag = 0; x_ticks_t lwip_sys_now; -static int lwip_init_flag = 0; struct sys_timeouts { struct sys_timeo *next; @@ -491,7 +489,7 @@ void lwip_config_net(char *ip, char *mask, char *gw) #endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */ }; - if(lwip_init_flag) + if(chk_lwip_bit(LWIP_INIT_FLAG)) { lw_print("lw: [%s] already ...\n", __func__); @@ -507,7 +505,7 @@ void lwip_config_net(char *ip, char *mask, char *gw) netif_set_up(&gnetif); return; } - lwip_init_flag = 1; + set_lwip_bit(LWIP_INIT_FLAG); lw_print("lw: [%s] start ...\n", __func__); @@ -522,7 +520,7 @@ void lwip_config_net(char *ip, char *mask, char *gw) netif_set_default(&gnetif); netif_set_up(&gnetif); - if(is_lwip_test) + if(chk_lwip_bit(LWIP_PRINT_FLAG)) { lw_pr_info("\r\n************************************************\r\n"); lw_pr_info(" Network Configuration\r\n"); @@ -553,12 +551,13 @@ void lwip_config_tcp(char *ip, char *mask, char *gw) #endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */ }; - if(lwip_init_flag) + if(chk_lwip_bit(LWIP_INIT_FLAG)) { lw_print("lw: [%s] already ...\n", __func__); return; } - lwip_init_flag = 1; + + set_lwip_bit(LWIP_INIT_FLAG); tcpip_init(NULL, NULL); diff --git a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h index b2d059386..ab5a66b2a 100644 --- a/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h +++ b/Ubiquitous/XiUOS/resources/ethernet/LwIP/arch/sys_arch.h @@ -66,7 +66,7 @@ #define LWIP_DEMO_TIMES 3 #define LWIP_TASK_STACK_SIZE 4096 -#define LWIP_TASK_PRIO 15 +#define LWIP_DEMO_TASK_PRIO 20 /* MAC address configuration. */ #define configMAC_ADDR {0x02, 0x12, 0x13, 0x10, 0x15, 0x11} @@ -82,16 +82,23 @@ typedef int32 sys_mbox_t; typedef int32 sys_thread_t; typedef x_base sys_prot_t; -#define MS_PER_SYSTICK_F407 1000/TICK_PER_SECOND +#define MS_PER_SYSTICK_F407 (1000 / TICK_PER_SECOND) //debug rtos with IRQ //#define FSL_RTOS_XIUOS +extern char lwip_flag; + +#define LWIP_INIT_FLAG (1 << 0) +#define LWIP_PRINT_FLAG (1 << 1) + +#define set_lwip_bit(__bit) lwip_flag |= (__bit) +#define clr_lwip_bit(__bit) lwip_flag &= ~(__bit) +#define chk_lwip_bit(__bit) ((lwip_flag & (__bit)) == (__bit)) + extern char lwip_ipaddr[]; extern char lwip_netmask[]; extern char lwip_gwaddr[]; -extern int is_lwip_test; -extern int lwip_sempahore; extern struct netif gnetif; void lwip_tcp_init(void); diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c index b4e47d00e..6cf60699e 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_dhcp_demo.c @@ -133,7 +133,7 @@ void lwip_dhcp_test(void) ETH_BSP_Config(); lwip_config_net(ip_addr, ip_addr, ip_addr); - is_lwip_test = 1; + set_lwip_bit(LWIP_PRINT_FLAG); dhcp_start(&gnetif); @@ -167,7 +167,7 @@ void lwip_dhcp_test(void) } } - is_lwip_test = 0; + clr_lwip_bit(LWIP_PRINT_FLAG); } diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c index 65a159cdb..a0c6807bb 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_ping_demo.c @@ -101,11 +101,13 @@ void lwip_ping_thread(int argc, char *argv[]) return; } } +#if (LWIP_DHCP) && (PING_USE_SOCKETS) else { get_url_ip(argv[1]); return; } +#endif } lw_print("lw: [%s] argc %d\n", __func__, argc); diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c index 94adbf3d2..baebfbbcb 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/lwip_tcp_demo.c @@ -105,7 +105,7 @@ void lwip_tcp_send_run(int argc, char *argv[]) ETH_BSP_Config(); lwip_config_tcp(lwip_ipaddr, lwip_netmask, lwip_gwaddr); - sys_thread_new("tcp send", lwip_tcp_send_thread, NULL, LWIP_TASK_STACK_SIZE, LWIP_TASK_PRIO); + sys_thread_new("tcp send", lwip_tcp_send_thread, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), diff --git a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c index 3312d8da6..1a66bd272 100755 --- a/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c +++ b/Ubiquitous/XiUOS/resources/ethernet/cmd_lwip/ping.c @@ -105,10 +105,6 @@ static u32_t ping_time; static struct raw_pcb *ping_pcb; #endif /* PING_USE_SOCKETS */ -#define PING_THREAD_STACKSIZE 4096 -#define PING_THREAD_PRIO 15 - - /** Prepare a echo ICMP request */ static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) @@ -268,7 +264,7 @@ ping_thread(void *arg) s = lwip_socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6); } #else - s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); + s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); #endif if (s < 0) { lw_print("lw: [%s] ping failed %d!\n", __func__, s); @@ -412,7 +408,7 @@ ping_init(const ip_addr_t* ping_addr) ping_target = ping_addr; #if PING_USE_SOCKETS - th = sys_thread_new("ping_thread", ping_thread, NULL, PING_THREAD_STACKSIZE, PING_THREAD_PRIO); + th = sys_thread_new("ping_thread", ping_thread, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); lw_print("lw: [%s] new thread %d addr %#x\n", __func__, th, (*ping_addr).addr); #else /* PING_USE_SOCKETS */ ping_raw_init(); @@ -476,6 +472,7 @@ int lwip_ping_recv(int s, int *ttl) return len; } +#if (LWIP_DHCP) && (PING_USE_SOCKETS) int get_url_ip(char* url) { #if LWIP_VERSION_MAJOR >= 2U @@ -539,6 +536,6 @@ int get_url_ip(char* url) lwip_close(s); return 0; } - +#endif #endif /* LWIP_RAW */