mirror of
https://github.com/pvvx/RTL00_WEB.git
synced 2024-11-22 05:54:19 +00:00
update + NAT + rtlbtool
This commit is contained in:
parent
b381813514
commit
54bf751b9c
62 changed files with 2268 additions and 3067 deletions
6
.project
6
.project
|
@ -6,6 +6,11 @@
|
|||
<project>RTL00_SDKV35a</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
|
@ -24,6 +29,7 @@
|
|||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
<nature>org.python.pydev.pythonNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
|
|
2
Makefile
2
Makefile
|
@ -6,7 +6,7 @@ mp: ram_all_mp
|
|||
.PHONY: ram_all
|
||||
ram_all:
|
||||
@$(MAKE) -f $(SDK_PATH)sdkbuild.mk
|
||||
@$(MAKE) -f $(SDK_PATH)flasher.mk genbin1 genbin23
|
||||
@$(MAKE) -f $(SDK_PATH)flasher.mk genbin
|
||||
|
||||
.PHONY: ram_all_mp
|
||||
ram_all_mp:
|
||||
|
|
|
@ -6,7 +6,7 @@ mp: ram_all_mp
|
|||
.PHONY: ram_all
|
||||
ram_all:
|
||||
@$(MAKE) -f $(SDK_PATH)sdkbuild.mk
|
||||
@$(MAKE) -f $(SDK_PATH)flasher.mk genbin1 genbin23
|
||||
@$(MAKE) -f $(SDK_PATH)flasher.mk genbin
|
||||
|
||||
.PHONY: ram_all_mp
|
||||
ram_all_mp:
|
||||
|
|
|
@ -904,16 +904,17 @@ int wifi_off(void) {
|
|||
|
||||
uint32 timeout = xTaskGetTickCount();
|
||||
|
||||
if ((rltk_wlan_running(WLAN0_IDX) == 0)
|
||||
&& (rltk_wlan_running(WLAN1_IDX) == 0)) {
|
||||
info_printf("WIFI is not running\n");
|
||||
wifi_mode = RTW_MODE_NONE;
|
||||
return 0;
|
||||
}
|
||||
#if CONFIG_LWIP_LAYER
|
||||
dhcps_deinit();
|
||||
LwIP_DHCP(0, DHCP_STOP);
|
||||
LwIP_DHCP(1, DHCP_STOP);
|
||||
#endif
|
||||
if ((rltk_wlan_running(WLAN0_IDX) == 0)
|
||||
&& (rltk_wlan_running(WLAN1_IDX) == 0)) {
|
||||
info_printf("WIFI is not running\n");
|
||||
return 0;
|
||||
}
|
||||
info_printf("Deinitializing WIFI ...\n");
|
||||
|
||||
#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "main.h"
|
||||
#include "wifi_user_set.h"
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
#undef debug_printf
|
||||
#define debug_printf(fmt, ...) rtl_printf(fmt, ##__VA_ARGS__)
|
||||
#undef info_printf
|
||||
|
@ -701,6 +701,9 @@ int wifi_run(rtw_mode_t mode) {
|
|||
switch(mode) {
|
||||
case RTW_MODE_STA_AP:
|
||||
ret = wifi_run_ap() | wifi_run_st();
|
||||
#if IP_NAPT
|
||||
xnetif[WLAN_AP_NETIF_NUM].napt = 1;
|
||||
#endif
|
||||
// _wext_enable_powersave(0, 0, 0);
|
||||
break;
|
||||
case RTW_MODE_STA:
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "wifi_constants.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* Get one byte from the 4-byte address */
|
||||
#ifndef ip4_addr1
|
||||
#define ip4_addr1(ipaddr) (((uint8_t*)(ipaddr))[0])
|
||||
#define ip4_addr2(ipaddr) (((uint8_t*)(ipaddr))[1])
|
||||
|
|
|
@ -665,7 +665,7 @@ __inline static uint get_WLAN_BSSID_EX_sz(WLAN_BSSID_EX *bss)
|
|||
}
|
||||
|
||||
struct wlan_network {
|
||||
_list list;
|
||||
struct list_head list;
|
||||
int network_type; //refer to ieee80211.h for WIRELESS_11A/B/G
|
||||
int fixed; // set to fixed when not to be removed as site-surveying
|
||||
unsigned long last_scanned; //timestamp for the network
|
||||
|
|
|
@ -153,8 +153,18 @@ void rltk_wlan_recv(int idx, struct eth_drv_sg *sg_list, int sg_len)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* uses in void __fastcall rltk_netif_rx(sk_buff *skb) */
|
||||
|
||||
int netif_is_valid_IP(int idx, unsigned char *ip_dest)
|
||||
{
|
||||
#if IP_FORWARD // add pvvx
|
||||
return 1;
|
||||
#elif defined(CONFIG_DONT_CARE_TP)
|
||||
if(pnetif->flags & NETIF_FLAG_IPSWITCH)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
#else
|
||||
#if CONFIG_LWIP_LAYER == 1
|
||||
#if DEVICE_EMAC
|
||||
struct netif *pnetif = xnetif[idx];
|
||||
|
@ -187,13 +197,9 @@ int netif_is_valid_IP(int idx, unsigned char *ip_dest)
|
|||
return 1;
|
||||
|
||||
DBG_TRACE("invalid IP: %d.%d.%d.%d ",ip_dest[0],ip_dest[1],ip_dest[2],ip_dest[3]);
|
||||
#endif
|
||||
#ifdef CONFIG_DONT_CARE_TP
|
||||
if(pnetif->flags & NETIF_FLAG_IPSWITCH)
|
||||
return 1;
|
||||
else
|
||||
#endif
|
||||
return 0;
|
||||
#endif // CONFIG_LWIP_LAYER
|
||||
#endif // IP_FORWARD / CONFIG_DONT_CARE_TP
|
||||
}
|
||||
|
||||
int netif_get_idx(struct netif *pnetif)
|
||||
|
|
|
@ -143,7 +143,11 @@ static void add_offer_options(uint8_t *option_start_address)
|
|||
The option specifies a list of DNS servers available to the client. */
|
||||
temp_option_addr = fill_one_option_content(temp_option_addr,
|
||||
DHCP_OPTION_CODE_DNS_SERVER, DHCP_OPTION_LENGTH_FOUR,
|
||||
#if IP_NAPT
|
||||
(void *)&dhcps_local_gateway);
|
||||
#else
|
||||
(void *)&dhcps_local_address);
|
||||
#endif
|
||||
/* add DHCP options 51.
|
||||
This option is used to request a lease time for the IP address. */
|
||||
temp_option_addr = fill_one_option_content(temp_option_addr,
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
#if defined(__IAR_SYSTEMS_ICC__)|| defined (__GNUC__)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ typedef int sys_prot_t;
|
|||
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#define PACK_STRUCT_USE_INCLUDES
|
||||
|
||||
#elif defined (__TASKING__)
|
||||
|
||||
|
|
|
@ -32,5 +32,7 @@
|
|||
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
#pragma pack()
|
||||
#elif defined (__GNUC__)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
|
||||
typedef xSemaphoreHandle sys_sem_t;
|
||||
typedef xSemaphoreHandle sys_mutex_t;
|
||||
typedef xQueueHandle sys_mbox_t;
|
||||
typedef xTaskHandle sys_thread_t;
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ static void low_level_init(struct netif *netif)
|
|||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* set netif maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
netif->mtu = netifMTU;
|
||||
|
||||
/* Accept broadcast address and ARP traffic */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
|
||||
|
|
|
@ -443,7 +443,6 @@ void sys_mutex_unlock(sys_mutex_t *mutex)
|
|||
thread() function. The id of the new thread is returned. Both the id and
|
||||
the priority are system dependent.
|
||||
*/
|
||||
#if 0
|
||||
sys_thread_t sys_thread_new_tcm(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
|
||||
{
|
||||
xTaskHandle CreatedTask;
|
||||
|
@ -456,6 +455,9 @@ int result;
|
|||
{
|
||||
void *stack_addr = tcm_heap_malloc(stacksize * sizeof(int));
|
||||
|
||||
if(stack_addr == NULL){
|
||||
}
|
||||
|
||||
result = xTaskGenericCreate(
|
||||
thread,
|
||||
( signed portCHAR * ) name,
|
||||
|
@ -489,7 +491,6 @@ int result;
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// TODO
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
typedef unsigned char u8_t;
|
||||
typedef signed char s8_t;
|
||||
typedef unsigned short u16_t;
|
||||
typedef signed short s16_t;
|
||||
typedef unsigned int u32_t;
|
||||
typedef signed int s32_t;
|
||||
typedef u32_t mem_ptr_t;
|
||||
typedef int sys_prot_t;
|
||||
|
||||
|
||||
#define U16_F "hu"
|
||||
#define S16_F "d"
|
||||
#define X16_F "hx"
|
||||
#define U32_F "u"
|
||||
#define S32_F "d"
|
||||
#define X32_F "x"
|
||||
#define SZT_F "uz"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* 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 (__CC_ARM)
|
||||
|
||||
#define PACK_STRUCT_BEGIN __packed
|
||||
#define PACK_STRUCT_STRUCT
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
|
||||
#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 (__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 { if(!(x)) while(1); } while(0)
|
||||
|
||||
#endif /* __CC_H__ */
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* 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__
|
||||
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#endif /* __CPU_H__ */
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* 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_RTXC_H__
|
||||
#define __SYS_RTXC_H__
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#define SYS_MBOX_NULL (xQueueHandle)0
|
||||
#define SYS_SEM_NULL (xSemaphoreHandle)0
|
||||
#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
|
||||
typedef xSemaphoreHandle sys_sem_t;
|
||||
typedef xSemaphoreHandle sys_mutex_t;
|
||||
typedef xQueueHandle sys_mbox_t;
|
||||
typedef xTaskHandle sys_thread_t;
|
||||
|
||||
typedef struct _sys_arch_state_t
|
||||
{
|
||||
// Task creation data.
|
||||
char cTaskName[configMAX_TASK_NAME_LEN];
|
||||
unsigned short nStackDepth;
|
||||
unsigned short nTaskCount;
|
||||
} sys_arch_state_t;
|
||||
|
||||
|
||||
|
||||
//extern sys_arch_state_t s_sys_arch_state;
|
||||
|
||||
//void sys_set_default_state();
|
||||
//void sys_set_state(signed char *pTaskName, unsigned short nStackSize);
|
||||
|
||||
/* Message queue constants. */
|
||||
#define archMESG_QUEUE_LENGTH ( 6 )
|
||||
#endif /* __SYS_RTXC_H__ */
|
||||
|
|
@ -1,489 +0,0 @@
|
|||
/**
|
||||
* @file
|
||||
* Ethernet Interface Skeleton
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is a skeleton for developing Ethernet network interface
|
||||
* drivers for lwIP. Add code to the low_level functions and do a
|
||||
* search-and-replace for the word "ethernetif" to replace it with
|
||||
* something that better describes your network interface.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
//#include "lwip/sys.h"
|
||||
//#include "lwip/tcpip.h"
|
||||
//#include "lwip/icmp.h"
|
||||
#include "lwip/lwip_timers.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "err.h"
|
||||
#include "ethernetif.h"
|
||||
//#include "queue.h"
|
||||
|
||||
#include "main.h" // for the definition of CONFIG_WLAN
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
#include "stm32f2x7_eth.h"
|
||||
#else
|
||||
#include <lwip_intf.h>
|
||||
#endif
|
||||
#include <platform/platform_stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define netifMTU (1500)
|
||||
#define netifINTERFACE_TASK_STACK_SIZE ( 350 )
|
||||
#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||
#define netifGUARD_BLOCK_TIME ( 250 )
|
||||
/* The time to block waiting for input. */
|
||||
#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 )
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/* Define those to better describe your network interface. */
|
||||
#define IFNAME0 's'
|
||||
#define IFNAME1 't'
|
||||
|
||||
static struct netif *s_pxNetIf = NULL;
|
||||
xSemaphoreHandle s_xSemaphore = NULL;
|
||||
|
||||
|
||||
/* Ethernet Rx & Tx DMA Descriptors */
|
||||
extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
|
||||
|
||||
/* Ethernet Receive buffers */
|
||||
extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
|
||||
|
||||
/* Ethernet Transmit buffers */
|
||||
extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
|
||||
|
||||
/* Global pointers to track current transmit and receive descriptors */
|
||||
extern ETH_DMADESCTypeDef *DMATxDescToSet;
|
||||
extern ETH_DMADESCTypeDef *DMARxDescToGet;
|
||||
|
||||
/* Global pointer for last received frame infos */
|
||||
extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos;
|
||||
|
||||
|
||||
static void ethernetif_input( void * pvParameters );
|
||||
#endif
|
||||
|
||||
static void arp_timer(void *arg);
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* set netif MAC hardware address length */
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/* set netif MAC hardware address */
|
||||
netif->hwaddr[0] = MAC_ADDR0;
|
||||
netif->hwaddr[1] = MAC_ADDR1;
|
||||
netif->hwaddr[2] = MAC_ADDR2;
|
||||
netif->hwaddr[3] = MAC_ADDR3;
|
||||
netif->hwaddr[4] = MAC_ADDR4;
|
||||
netif->hwaddr[5] = MAC_ADDR5;
|
||||
#endif
|
||||
|
||||
/* set netif maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* Accept broadcast address and ARP traffic */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
s_pxNetIf =netif;
|
||||
|
||||
/* create binary semaphore used for informing ethernetif of frame reception */
|
||||
if (s_xSemaphore == NULL)
|
||||
{
|
||||
vSemaphoreCreateBinary(s_xSemaphore);
|
||||
xSemaphoreTake( s_xSemaphore, 0);
|
||||
}
|
||||
|
||||
/* initialize MAC address in ethernet MAC */
|
||||
ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr);
|
||||
|
||||
/* Initialize Tx Descriptors list: Chain Mode */
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
|
||||
/* Initialize Rx Descriptors list: Chain Mode */
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
|
||||
|
||||
/* Enable Ethernet Rx interrrupt */
|
||||
{
|
||||
for(i=0; i<ETH_RXBUFNB; i++)
|
||||
{
|
||||
ETH_DMARxDescReceiveITConfig(&DMARxDscrTab[i], ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CHECKSUM_BY_HARDWARE
|
||||
/* Enable the checksum insertion for the Tx frames */
|
||||
{
|
||||
for(i=0; i<ETH_TXBUFNB; i++)
|
||||
{
|
||||
ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* create the task that handles the ETH_MAC */
|
||||
xTaskCreate(ethernetif_input, (signed char*) "Eth_if", netifINTERFACE_TASK_STACK_SIZE, NULL,
|
||||
netifINTERFACE_TASK_PRIORITY,NULL);
|
||||
|
||||
/* Enable MAC and DMA transmission and reception */
|
||||
ETH_Start();
|
||||
#else //#if !CONFIG_WLAN
|
||||
/* WLAN interface is initialized later */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 availale 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)
|
||||
{
|
||||
#if !CONFIG_WLAN
|
||||
static xSemaphoreHandle xTxSemaphore = NULL;
|
||||
struct pbuf *q;
|
||||
u8 *buffer ;
|
||||
__IO ETH_DMADESCTypeDef *DmaTxDesc;
|
||||
uint16_t framelength = 0;
|
||||
uint32_t bufferoffset = 0;
|
||||
uint32_t byteslefttocopy = 0;
|
||||
uint32_t payloadoffset = 0;
|
||||
|
||||
if (xTxSemaphore == NULL)
|
||||
{
|
||||
vSemaphoreCreateBinary (xTxSemaphore);
|
||||
}
|
||||
|
||||
if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME))
|
||||
{
|
||||
DmaTxDesc = DMATxDescToSet;
|
||||
buffer = (u8 *)(DmaTxDesc->Buffer1Addr);
|
||||
bufferoffset = 0;
|
||||
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
{
|
||||
if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get bytes in current lwIP buffer */
|
||||
byteslefttocopy = q->len;
|
||||
payloadoffset = 0;
|
||||
|
||||
/* Check if the length of data to copy is bigger than Tx buffer size*/
|
||||
while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE )
|
||||
{
|
||||
/* Copy data to Tx buffer*/
|
||||
memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );
|
||||
|
||||
/* Point to next descriptor */
|
||||
DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
|
||||
|
||||
/* Check if the buffer is available */
|
||||
if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
buffer = (u8 *)(DmaTxDesc->Buffer1Addr);
|
||||
|
||||
byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
bufferoffset = 0;
|
||||
}
|
||||
|
||||
/* Copy the remaining bytes */
|
||||
memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), byteslefttocopy );
|
||||
bufferoffset = bufferoffset + byteslefttocopy;
|
||||
framelength = framelength + byteslefttocopy;
|
||||
}
|
||||
|
||||
/* Prepare transmit descriptors to give to DMA*/
|
||||
ETH_Prepare_Transmit_Descriptors(framelength);
|
||||
|
||||
/* Give semaphore and exit */
|
||||
error:
|
||||
|
||||
xSemaphoreGive(xTxSemaphore);
|
||||
}
|
||||
#endif // #if !CONFIG_WLAN
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/**
|
||||
* Should allocate a pbuf and transfer the bytes of the incoming
|
||||
* packet from the interface into the pbuf.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return a pbuf filled with the received packet (including MAC header)
|
||||
* NULL on memory error
|
||||
*/
|
||||
static struct pbuf * low_level_input(struct netif *netif)
|
||||
{
|
||||
struct pbuf *p= NULL, *q;
|
||||
u32_t len;
|
||||
FrameTypeDef frame;
|
||||
u8 *buffer;
|
||||
__IO ETH_DMADESCTypeDef *DMARxDesc;
|
||||
uint32_t bufferoffset = 0;
|
||||
uint32_t payloadoffset = 0;
|
||||
uint32_t byteslefttocopy = 0;
|
||||
uint32_t i=0;
|
||||
|
||||
/* get received frame */
|
||||
frame = ETH_Get_Received_Frame_interrupt();
|
||||
|
||||
/* Obtain the size of the packet and put it into the "len" variable. */
|
||||
len = frame.length;
|
||||
buffer = (u8 *)frame.buffer;
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
/* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
}
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
DMARxDesc = frame.descriptor;
|
||||
bufferoffset = 0;
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
{
|
||||
byteslefttocopy = q->len;
|
||||
payloadoffset = 0;
|
||||
|
||||
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
|
||||
while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE )
|
||||
{
|
||||
/* Copy data to pbuf*/
|
||||
memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
|
||||
|
||||
/* Point to next descriptor */
|
||||
DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr);
|
||||
buffer = (unsigned char *)(DMARxDesc->Buffer1Addr);
|
||||
|
||||
byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
|
||||
payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
|
||||
bufferoffset = 0;
|
||||
}
|
||||
|
||||
/* Copy remaining data in pbuf */
|
||||
memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy);
|
||||
bufferoffset = bufferoffset + byteslefttocopy;
|
||||
}
|
||||
|
||||
/* Release descriptors to DMA */
|
||||
DMARxDesc =frame.descriptor;
|
||||
|
||||
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
|
||||
for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
|
||||
{
|
||||
DMARxDesc->Status = ETH_DMARxDesc_OWN;
|
||||
DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
|
||||
/* Clear Segment_Count */
|
||||
DMA_RX_FRAME_infos->Seg_Count =0;
|
||||
/* added for test*/
|
||||
}
|
||||
|
||||
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
|
||||
if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
|
||||
{
|
||||
/* Clear RBUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_RBUS;
|
||||
/* Resume DMA reception */
|
||||
ETH->DMARPDR = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 ethernetif_input( void * pvParameters )
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
|
||||
{
|
||||
TRY_GET_NEXT_FRAME:
|
||||
p = low_level_input( s_pxNetIf );
|
||||
if (p != NULL)
|
||||
{
|
||||
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
|
||||
{
|
||||
pbuf_free(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto TRY_GET_NEXT_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* 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));
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/* ethernet */
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
#else
|
||||
/* wlan interface*/
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwip";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
#endif // WLAN
|
||||
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = low_level_output;
|
||||
|
||||
/* initialize the hardware */
|
||||
low_level_init(netif);
|
||||
|
||||
etharp_init();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
static void arp_timer(void *arg)
|
||||
{
|
||||
etharp_tmr();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* For FreeRTOS tickless
|
||||
*/
|
||||
int lwip_tickless_used = 0;
|
||||
|
||||
/*
|
||||
int arp_timeout_exist(void)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *t;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
for(t = timeouts->next; t != NULL;t = t->next)
|
||||
if(t->h == arp_timer)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
//Called by rltk_wlan_PRE_SLEEP_PROCESSING()
|
||||
void lwip_PRE_SLEEP_PROCESSING(void)
|
||||
{
|
||||
if(arp_timeout_exist()) {
|
||||
tcpip_untimeout(arp_timer, NULL);
|
||||
}
|
||||
lwip_tickless_used = 1;
|
||||
}
|
||||
|
||||
//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit
|
||||
void lwip_POST_SLEEP_PROCESSING(void)
|
||||
{
|
||||
if(lwip_tickless_used) {
|
||||
tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,653 +0,0 @@
|
|||
/**
|
||||
* @file
|
||||
* Ethernet Interface Skeleton
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is a skeleton for developing Ethernet network interface
|
||||
* drivers for lwIP. Add code to the low_level functions and do a
|
||||
* search-and-replace for the word "ethernetif" to replace it with
|
||||
* something that better describes your network interface.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/lwip_timers.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "err.h"
|
||||
#include "ethernetif.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include "main.h" // for the definition of CONFIG_WLAN
|
||||
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
#include "stm32f2x7_eth.h"
|
||||
#else
|
||||
#include <lwip_intf.h>
|
||||
#endif
|
||||
#include <platform/platform_stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CONFIG_DONT_CARE_TP
|
||||
#define netifMTU (576)
|
||||
#else
|
||||
#define netifMTU (1500)
|
||||
#endif
|
||||
#define netifINTERFACE_TASK_STACK_SIZE ( 350 )
|
||||
#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||
#define netifGUARD_BLOCK_TIME ( 250 )
|
||||
/* The time to block waiting for input. */
|
||||
#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 )
|
||||
#define FAKE_PING_REPLY 0
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/* Define those to better describe your network interface. */
|
||||
#define IFNAME0 's'
|
||||
#define IFNAME1 't'
|
||||
|
||||
static struct netif *s_pxNetIf = NULL;
|
||||
xSemaphoreHandle s_xSemaphore = NULL;
|
||||
|
||||
|
||||
/* Ethernet Rx & Tx DMA Descriptors */
|
||||
extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
|
||||
|
||||
/* Ethernet Receive buffers */
|
||||
extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
|
||||
|
||||
/* Ethernet Transmit buffers */
|
||||
extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
|
||||
|
||||
/* Global pointers to track current transmit and receive descriptors */
|
||||
extern ETH_DMADESCTypeDef *DMATxDescToSet;
|
||||
extern ETH_DMADESCTypeDef *DMARxDescToGet;
|
||||
|
||||
/* Global pointer for last received frame infos */
|
||||
extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos;
|
||||
|
||||
static void ethernetif_input( void * pvParameters );
|
||||
#endif
|
||||
|
||||
static void arp_timer(void *arg);
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* set netif MAC hardware address length */
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/* set netif MAC hardware address */
|
||||
netif->hwaddr[0] = MAC_ADDR0;
|
||||
netif->hwaddr[1] = MAC_ADDR1;
|
||||
netif->hwaddr[2] = MAC_ADDR2;
|
||||
netif->hwaddr[3] = MAC_ADDR3;
|
||||
netif->hwaddr[4] = MAC_ADDR4;
|
||||
netif->hwaddr[5] = MAC_ADDR5;
|
||||
#endif
|
||||
|
||||
/* set netif maximum transfer unit */
|
||||
netif->mtu = netifMTU;
|
||||
|
||||
/* Accept broadcast address and ARP traffic */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
s_pxNetIf =netif;
|
||||
|
||||
/* create binary semaphore used for informing ethernetif of frame reception */
|
||||
if (s_xSemaphore == NULL)
|
||||
{
|
||||
s_xSemaphore= xSemaphoreCreateCounting(20,0);
|
||||
}
|
||||
|
||||
/* initialize MAC address in ethernet MAC */
|
||||
ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr);
|
||||
|
||||
/* Initialize Tx Descriptors list: Chain Mode */
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
|
||||
/* Initialize Rx Descriptors list: Chain Mode */
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
|
||||
|
||||
/* Enable Ethernet Rx interrrupt */
|
||||
{
|
||||
for(i=0; i<ETH_RXBUFNB; i++)
|
||||
{
|
||||
ETH_DMARxDescReceiveITConfig(&DMARxDscrTab[i], ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CHECKSUM_BY_HARDWARE
|
||||
/* Enable the checksum insertion for the Tx frames */
|
||||
{
|
||||
for(i=0; i<ETH_TXBUFNB; i++)
|
||||
{
|
||||
ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* create the task that handles the ETH_MAC */
|
||||
xTaskCreate(ethernetif_input, (signed char*) "Eth_if", netifINTERFACE_TASK_STACK_SIZE, NULL,
|
||||
netifINTERFACE_TASK_PRIORITY,NULL);
|
||||
|
||||
/* Enable MAC and DMA transmission and reception */
|
||||
ETH_Start();
|
||||
#else //#if !CONFIG_WLAN
|
||||
/* WLAN interface is initialized later */
|
||||
#endif
|
||||
}
|
||||
|
||||
#if FAKE_PING_REPLY
|
||||
void fake_arp_reply(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q, *tq, *tp;
|
||||
int q_len, p_len;
|
||||
struct eth_hdr *p_eth, *q_eth;
|
||||
struct etharp_hdr *p_arp, *q_arp;
|
||||
struct eth_addr fake_src_mac = {0xb0, 0x48, 0x7a, 0xfe, 0xea, 0xe0};
|
||||
|
||||
// Allocate buffer to store received packet
|
||||
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL);
|
||||
if (p == NULL) {
|
||||
printf("\n\rCannot allocate pbuf to receive packet");
|
||||
return;
|
||||
}
|
||||
for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next)
|
||||
{
|
||||
p_len = tp->len;
|
||||
while(p_len)
|
||||
{
|
||||
if(q_len > p_len) {
|
||||
memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len);
|
||||
q_len -= p_len;
|
||||
p_len = 0;
|
||||
}else{
|
||||
memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len);
|
||||
p_len -= q_len;
|
||||
tq = tq->next;
|
||||
q_len = tq->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
p_eth = (struct eth_hdr *)p->payload;
|
||||
q_eth = (struct eth_hdr *)q->payload;
|
||||
p_arp = (struct etharp_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr));
|
||||
q_arp = (struct etharp_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr));
|
||||
|
||||
q_eth->dest = p_eth->src;
|
||||
q_eth->src = fake_src_mac;
|
||||
q_arp->opcode = htons(ARP_REPLY);
|
||||
q_arp->shwaddr = fake_src_mac;
|
||||
q_arp->sipaddr = p_arp->dipaddr;
|
||||
q_arp->dhwaddr = p_eth->src;
|
||||
q_arp->dipaddr = p_arp->sipaddr;
|
||||
|
||||
if(0){
|
||||
int i;
|
||||
char *buf = q->payload;
|
||||
printf("\n\r");
|
||||
for(i=0;i<q->tot_len;i++)
|
||||
printf("0x%02x, ", buf[i]);
|
||||
printf("\n\r");
|
||||
}
|
||||
if (ERR_OK != netif->input(q, netif)){
|
||||
printf("\n\rfake_arp_reply input error");
|
||||
pbuf_free(q);
|
||||
}else
|
||||
printf("\n\rfake arp reply \n\r");
|
||||
}
|
||||
|
||||
void fake_echo_reply(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q, *tq, *tp;
|
||||
int q_len, p_len;
|
||||
struct eth_hdr *p_eth, *q_eth;
|
||||
struct ip_hdr *p_ip, *q_ip;
|
||||
struct icmp_echo_hdr *p_echo, *q_echo;
|
||||
|
||||
// Allocate buffer to store received packet
|
||||
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL);
|
||||
if (p == NULL) {
|
||||
printf("\n\rCannot allocate pbuf to receive packet");
|
||||
return;
|
||||
}
|
||||
for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next)
|
||||
{
|
||||
p_len = tp->len;
|
||||
while(p_len)
|
||||
{
|
||||
if(q_len > p_len) {
|
||||
memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len);
|
||||
q_len -= p_len;
|
||||
p_len = 0;
|
||||
}else{
|
||||
memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len);
|
||||
p_len -= q_len;
|
||||
tq = tq->next;
|
||||
q_len = tq->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
p_eth = (struct eth_hdr *)p->payload;
|
||||
q_eth = (struct eth_hdr *)q->payload;
|
||||
p_ip = (struct ip_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr));
|
||||
q_ip = (struct ip_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr));
|
||||
p_echo = (struct icmp_echo_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr));
|
||||
q_echo = (struct icmp_echo_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr));
|
||||
|
||||
q_eth->dest = p_eth->src;
|
||||
q_eth->src = p_eth->dest;
|
||||
q_ip->src.addr = p_ip->dest.addr;
|
||||
q_ip->dest.addr = p_ip->src.addr;
|
||||
q_ip->_chksum = 0;
|
||||
q_ip->_chksum = inet_chksum(q_ip, sizeof(struct ip_hdr));
|
||||
q_echo->type = ICMP_ER;
|
||||
q_echo->code = 0;
|
||||
q_echo->chksum = 0;
|
||||
q_echo->chksum = inet_chksum(q_echo, q->tot_len - sizeof(struct eth_hdr) - sizeof(struct ip_hdr));
|
||||
|
||||
if(0){
|
||||
int i;
|
||||
char *buf = q->payload;
|
||||
printf("\n\r");
|
||||
for(i=0;i<q->tot_len;i++)
|
||||
printf("0x%02x, ", buf[i]);
|
||||
printf("\n\r");
|
||||
}
|
||||
if (ERR_OK != netif->input(q, netif)){
|
||||
printf("\n\rfake_echo_reply input error");
|
||||
pbuf_free(q);
|
||||
}else
|
||||
printf("\n\rfake echo reply \n\r");
|
||||
}
|
||||
#endif // #if FAKE_PING_REPLY
|
||||
|
||||
/**
|
||||
* 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 availale 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)
|
||||
{
|
||||
#if !CONFIG_WLAN
|
||||
static xSemaphoreHandle xTxSemaphore = NULL;
|
||||
struct pbuf *q;
|
||||
uint32_t l = 0;
|
||||
u8 *buffer ;
|
||||
|
||||
if (xTxSemaphore == NULL)
|
||||
{
|
||||
vSemaphoreCreateBinary (xTxSemaphore);
|
||||
}
|
||||
|
||||
if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME))
|
||||
{
|
||||
buffer = (u8 *)(DMATxDescToSet->Buffer1Addr);
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
{
|
||||
memcpy((u8_t*)&buffer[l], q->payload, q->len);
|
||||
l = l + q->len;
|
||||
}
|
||||
ETH_Prepare_Transmit_Descriptors(l);
|
||||
xSemaphoreGive(xTxSemaphore);
|
||||
}
|
||||
#else
|
||||
/* Refer to eCos lwip eth_drv_send() */
|
||||
struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
|
||||
int sg_len = 0;
|
||||
struct pbuf *q;
|
||||
|
||||
if(!rltk_wlan_running(netif_get_idx(netif)))
|
||||
return ERR_IF;
|
||||
|
||||
for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) {
|
||||
sg_list[sg_len].buf = (unsigned int) q->payload;
|
||||
sg_list[sg_len++].len = q->len;
|
||||
}
|
||||
|
||||
#if FAKE_PING_REPLY
|
||||
{
|
||||
char *header = p->payload;
|
||||
if(header[12] == 0x08 && header[13] == 0x06)
|
||||
{ // arp packet
|
||||
if(header[21] == 0x01)
|
||||
{ // arp request packet
|
||||
printf("\n\rfake_ping: arp request packet.");
|
||||
if(0)
|
||||
{
|
||||
int i;
|
||||
printf("\n\r");
|
||||
for (q = p; q != NULL; q = q->next)
|
||||
{
|
||||
char *buf = q->payload;
|
||||
for(i=0;i<q->len;i++)
|
||||
printf("0x%02x, ", buf[i]);
|
||||
}
|
||||
printf("\n\r");
|
||||
}
|
||||
fake_arp_reply(netif, p);
|
||||
return ERR_OK;
|
||||
}
|
||||
}else if(header[12] == 0x08 && header[13] == 0x00)
|
||||
{ // ip packet
|
||||
if(header[15] == 0x00 && header[23] == 0x01)
|
||||
{ // icmp packet
|
||||
printf("\n\rfake_ping: icmp packet.");
|
||||
if(0){
|
||||
int i;
|
||||
printf("\n\r");
|
||||
for (q = p; q != NULL; q = q->next)
|
||||
{
|
||||
char *buf = q->payload;
|
||||
for(i=0;i<q->len;i++)
|
||||
printf("0x%02x, ", buf[i]);
|
||||
}
|
||||
printf("\n\r");
|
||||
}
|
||||
fake_echo_reply(netif, p);
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // #if FAKE_PING_REPLY
|
||||
if (sg_len)
|
||||
rltk_wlan_send(netif_get_idx(netif), sg_list, sg_len, p->tot_len);
|
||||
#endif // #if !CONFIG_WLAN
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/**
|
||||
* Should allocate a pbuf and transfer the bytes of the incoming
|
||||
* packet from the interface into the pbuf.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return a pbuf filled with the received packet (including MAC header)
|
||||
* NULL on memory error
|
||||
*/
|
||||
static struct pbuf * low_level_input(struct netif *netif)
|
||||
{
|
||||
struct pbuf *p, *q;
|
||||
u16_t len;
|
||||
uint32_t l=0,i =0;
|
||||
FrameTypeDef frame;
|
||||
u8 *buffer;
|
||||
__IO ETH_DMADESCTypeDef *DMARxNextDesc;
|
||||
|
||||
p = NULL;
|
||||
|
||||
/* Get received frame */
|
||||
frame = ETH_Get_Received_Frame_interrupt();
|
||||
|
||||
/* check that frame has no error */
|
||||
if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET)
|
||||
{
|
||||
|
||||
/* Obtain the size of the packet and put it into the "len" variable. */
|
||||
len = frame.length;
|
||||
buffer = (u8 *)frame.buffer;
|
||||
|
||||
/* We allocate a pbuf chain of pbufs from the pool. */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
|
||||
/* Copy received frame from ethernet driver buffer to stack buffer */
|
||||
if (p != NULL)
|
||||
{
|
||||
for (q = p; q != NULL; q = q->next)
|
||||
{
|
||||
memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len);
|
||||
l = l + q->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Release descriptors to DMA */
|
||||
/* Check if received frame with multiple DMA buffer segments */
|
||||
if (DMA_RX_FRAME_infos->Seg_Count > 1)
|
||||
{
|
||||
DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMARxNextDesc = frame.descriptor;
|
||||
}
|
||||
|
||||
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
|
||||
for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
|
||||
{
|
||||
DMARxNextDesc->Status = ETH_DMARxDesc_OWN;
|
||||
DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
|
||||
/* Clear Segment_Count */
|
||||
DMA_RX_FRAME_infos->Seg_Count =0;
|
||||
|
||||
|
||||
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
|
||||
if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
|
||||
{
|
||||
/* Clear RBUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_RBUS;
|
||||
|
||||
/* Resume DMA reception */
|
||||
ETH->DMARPDR = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 ethernetif_input( void * pvParameters )
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
|
||||
{
|
||||
p = low_level_input( s_pxNetIf );
|
||||
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
|
||||
{
|
||||
pbuf_free(p);
|
||||
p=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Refer to eCos eth_drv_recv to do similarly in ethernetif_input */
|
||||
void ethernetif_recv(struct netif *netif, int total_len)
|
||||
{
|
||||
#if CONFIG_WLAN
|
||||
struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
|
||||
struct pbuf *p, *q;
|
||||
int sg_len = 0;
|
||||
|
||||
if(!rltk_wlan_running(netif_get_idx(netif)))
|
||||
return;
|
||||
|
||||
if ((total_len > MAX_ETH_MSG) || (total_len < 0))
|
||||
total_len = MAX_ETH_MSG;
|
||||
|
||||
// Allocate buffer to store received packet
|
||||
p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL);
|
||||
if (p == NULL) {
|
||||
printf("\n\rCannot allocate pbuf to receive packet");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create scatter list
|
||||
for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) {
|
||||
sg_list[sg_len].buf = (unsigned int) q->payload;
|
||||
sg_list[sg_len++].len = q->len;
|
||||
}
|
||||
|
||||
// Copy received packet to scatter list from wrapper rx skb
|
||||
//printf("\n\rwlan:%c: Recv sg_len: %d, tot_len:%d", netif->name[1],sg_len, total_len);
|
||||
rltk_wlan_recv(netif_get_idx(netif), sg_list, sg_len);
|
||||
|
||||
// Pass received packet to the interface
|
||||
if (ERR_OK != netif->input(p, netif))
|
||||
pbuf_free(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
#if !CONFIG_WLAN
|
||||
/* ethernet */
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
#else
|
||||
/* wlan interface*/
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
if(netif->name[1] == '0')
|
||||
netif->hostname = "lwip0";
|
||||
else if(netif->name[1] == '1')
|
||||
netif->hostname = "lwip1";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
#endif // WLAN
|
||||
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = low_level_output;
|
||||
|
||||
/* initialize the hardware */
|
||||
low_level_init(netif);
|
||||
|
||||
etharp_init();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
static void arp_timer(void *arg)
|
||||
{
|
||||
etharp_tmr();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* For FreeRTOS tickless
|
||||
*/
|
||||
int lwip_tickless_used = 0;
|
||||
|
||||
|
||||
int arp_timeout_exist(void)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *t;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
for(t = timeouts->next; t != NULL;t = t->next)
|
||||
if(t->h == arp_timer)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Called by rltk_wlan_PRE_SLEEP_PROCESSING()
|
||||
void lwip_PRE_SLEEP_PROCESSING(void)
|
||||
{
|
||||
if(arp_timeout_exist()) {
|
||||
tcpip_untimeout(arp_timer, NULL);
|
||||
}
|
||||
lwip_tickless_used = 1;
|
||||
}
|
||||
|
||||
//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit
|
||||
void lwip_POST_SLEEP_PROCESSING(void)
|
||||
{
|
||||
if(lwip_tickless_used) {
|
||||
tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef __ETHERNETIF_H__
|
||||
#define __ETHERNETIF_H__
|
||||
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
//----- ------------------------------------------------------------------
|
||||
// Ethernet Buffer
|
||||
//----- ------------------------------------------------------------------
|
||||
struct eth_drv_sg {
|
||||
unsigned int buf;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
#define MAX_ETH_DRV_SG 32
|
||||
#define MAX_ETH_MSG 1540
|
||||
|
||||
void ethernetif_recv(struct netif *netif, int total_len);
|
||||
err_t ethernetif_init(struct netif *netif);
|
||||
void lwip_PRE_SLEEP_PROCESSING(void);
|
||||
void lwip_POST_SLEEP_PROCESSING(void);
|
||||
|
||||
#endif
|
|
@ -1,515 +0,0 @@
|
|||
/*
|
||||
* 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/debug.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "lwip/lwip_timers.h"
|
||||
|
||||
xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
struct timeoutlist
|
||||
{
|
||||
struct sys_timeouts timeouts;
|
||||
xTaskHandle pid;
|
||||
};
|
||||
|
||||
/* This is the number of threads that can be started with sys_thread_new() */
|
||||
#define SYS_THREAD_MAX 6
|
||||
|
||||
static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX];
|
||||
static u16_t s_nextthread = 0;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Creates an empty mailbox.
|
||||
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
|
||||
{
|
||||
(void ) size;
|
||||
|
||||
*mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );
|
||||
|
||||
#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( uxQueueMessagesWaiting( *mbox ) )
|
||||
{
|
||||
/* Line for breakpoint. Should never break here! */
|
||||
portNOP();
|
||||
#if SYS_STATS
|
||||
lwip_stats.sys.mbox.err++;
|
||||
#endif /* SYS_STATS */
|
||||
|
||||
// TODO notify the user of failure.
|
||||
}
|
||||
|
||||
vQueueDelete( *mbox );
|
||||
|
||||
#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)
|
||||
{
|
||||
while ( xQueueSendToBack(*mbox, &data, portMAX_DELAY ) != pdTRUE ){}
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Try to post the "msg" to the mailbox.
|
||||
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
|
||||
{
|
||||
err_t result;
|
||||
|
||||
if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*
|
||||
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)
|
||||
{
|
||||
void *dummyptr;
|
||||
portTickType StartTime, EndTime, Elapsed;
|
||||
|
||||
StartTime = xTaskGetTickCount();
|
||||
|
||||
if ( msg == NULL )
|
||||
{
|
||||
msg = &dummyptr;
|
||||
}
|
||||
|
||||
if ( timeout != 0 )
|
||||
{
|
||||
if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) )
|
||||
{
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
|
||||
|
||||
return ( Elapsed );
|
||||
}
|
||||
else // timed out blocking for message
|
||||
{
|
||||
*msg = NULL;
|
||||
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else // block forever for a message.
|
||||
{
|
||||
while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
|
||||
|
||||
return ( Elapsed ); // return time blocked TODO test
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*
|
||||
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)
|
||||
{
|
||||
void *dummyptr;
|
||||
|
||||
if ( msg == NULL )
|
||||
{
|
||||
msg = &dummyptr;
|
||||
}
|
||||
|
||||
if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) )
|
||||
{
|
||||
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)
|
||||
{
|
||||
vSemaphoreCreateBinary(*sem );
|
||||
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
|
||||
{
|
||||
xSemaphoreTake(*sem,1);
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
portTickType StartTime, EndTime, Elapsed;
|
||||
|
||||
StartTime = xTaskGetTickCount();
|
||||
|
||||
if( timeout != 0)
|
||||
{
|
||||
if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE )
|
||||
{
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
|
||||
|
||||
return (Elapsed); // return time blocked TODO test
|
||||
}
|
||||
else
|
||||
{
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else // must block without a timeout
|
||||
{
|
||||
while( xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE){}
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
|
||||
|
||||
return ( Elapsed ); // return time blocked
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Signals a semaphore
|
||||
void sys_sem_signal(sys_sem_t *sem)
|
||||
{
|
||||
xSemaphoreGive(*sem);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Deallocates a semaphore
|
||||
void sys_sem_free(sys_sem_t *sem)
|
||||
{
|
||||
#if SYS_STATS
|
||||
--lwip_stats.sys.sem.used;
|
||||
#endif /* SYS_STATS */
|
||||
|
||||
vQueueDelete(*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;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Initialize sys arch
|
||||
void sys_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Initialize the the per-thread sys_timeouts structures
|
||||
// make sure there are no valid pids in the list
|
||||
for(i = 0; i < SYS_THREAD_MAX; i++)
|
||||
{
|
||||
s_timeoutlist[i].pid = 0;
|
||||
s_timeoutlist[i].timeouts.next = NULL;
|
||||
}
|
||||
|
||||
// keep track of how many threads have been created
|
||||
s_nextthread = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
|
||||
each thread has a list of timeouts which is represented as a linked
|
||||
list of sys_timeout structures. The sys_timeouts structure holds a
|
||||
pointer to a linked list of timeouts. This function is called by
|
||||
the lwIP timeout scheduler and must not return a NULL value.
|
||||
|
||||
In a single threaded sys_arch implementation, this function will
|
||||
simply return a pointer to a global sys_timeouts variable stored in
|
||||
the sys_arch module.
|
||||
*/
|
||||
struct sys_timeouts* sys_arch_timeouts(void)
|
||||
{
|
||||
int i;
|
||||
xTaskHandle pid;
|
||||
struct timeoutlist *tl;
|
||||
|
||||
pid = xTaskGetCurrentTaskHandle();
|
||||
|
||||
for(i = 0; i < s_nextthread; i++)
|
||||
{
|
||||
tl = &(s_timeoutlist[i]);
|
||||
if(tl->pid == pid)
|
||||
{
|
||||
return &(tl->timeouts);
|
||||
}
|
||||
}
|
||||
// Error
|
||||
return NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Mutexes*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
#if LWIP_COMPAT_MUTEX == 0
|
||||
/* Create a new mutex*/
|
||||
err_t sys_mutex_new(sys_mutex_t *mutex) {
|
||||
|
||||
*mutex = xSemaphoreCreateMutex();
|
||||
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 */
|
||||
|
||||
vQueueDelete(*mutex);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Lock a mutex*/
|
||||
void sys_mutex_lock(sys_mutex_t *mutex)
|
||||
{
|
||||
sys_arch_sem_wait(*mutex, 0);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Unlock a mutex*/
|
||||
void sys_mutex_unlock(sys_mutex_t *mutex)
|
||||
{
|
||||
xSemaphoreGive(*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)
|
||||
{
|
||||
xTaskHandle CreatedTask;
|
||||
int result;
|
||||
|
||||
if ( s_nextthread < SYS_THREAD_MAX )
|
||||
{
|
||||
vPortEnterCritical();
|
||||
result = xTaskCreate( thread, ( signed portCHAR * ) name, stacksize, arg, prio, &CreatedTask );
|
||||
|
||||
// For each task created, store the task handle (pid) in the timers array.
|
||||
// This scheme doesn't allow for threads to be deleted
|
||||
s_timeoutlist[s_nextthread++].pid = CreatedTask;
|
||||
vPortExitCritical();
|
||||
|
||||
if(result == pdPASS)
|
||||
{
|
||||
return CreatedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
sys_prot_t sys_arch_protect(void)
|
||||
{
|
||||
vPortEnterCritical();
|
||||
return 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.
|
||||
*/
|
||||
void sys_arch_unprotect(sys_prot_t pval)
|
||||
{
|
||||
( void ) pval;
|
||||
vPortExitCritical();
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints an assertion messages and aborts execution.
|
||||
*/
|
||||
void sys_assert( const char *msg )
|
||||
{
|
||||
( void ) msg;
|
||||
/*FSL:only needed for debugging
|
||||
printf(msg);
|
||||
printf("\n\r");
|
||||
*/
|
||||
vPortEnterCritical( );
|
||||
for(;;)
|
||||
;
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* 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_RTXC_H__
|
||||
#define __SYS_RTXC_H__
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#define SYS_MBOX_NULL (xQueueHandle)0
|
||||
#define SYS_SEM_NULL (xSemaphoreHandle)0
|
||||
#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
|
||||
typedef xSemaphoreHandle sys_sem_t;
|
||||
typedef xQueueHandle sys_mbox_t;
|
||||
typedef xTaskHandle sys_thread_t;
|
||||
|
||||
typedef struct _sys_arch_state_t
|
||||
{
|
||||
// Task creation data.
|
||||
char cTaskName[configMAX_TASK_NAME_LEN];
|
||||
unsigned short nStackDepth;
|
||||
unsigned short nTaskCount;
|
||||
} sys_arch_state_t;
|
||||
|
||||
|
||||
|
||||
//extern sys_arch_state_t s_sys_arch_state;
|
||||
|
||||
//void sys_set_default_state();
|
||||
//void sys_set_state(signed char *pTaskName, unsigned short nStackSize);
|
||||
|
||||
/* Message queue constants. */
|
||||
#define archMESG_QUEUE_LENGTH ( 6 )
|
||||
#endif /* __SYS_RTXC_H__ */
|
||||
|
|
@ -1,366 +0,0 @@
|
|||
/**
|
||||
* @file
|
||||
* Ethernet Interface for standalone applications (without RTOS) - works only for
|
||||
* ethernet polling mode (polling for ethernet frame reception)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "ethernetif.h"
|
||||
#include "stm32f2x7_eth.h"
|
||||
#include "main.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Network interface name */
|
||||
#define IFNAME0 's'
|
||||
#define IFNAME1 't'
|
||||
|
||||
|
||||
/* Ethernet Rx & Tx DMA Descriptors */
|
||||
extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
|
||||
|
||||
/* Ethernet Driver Receive buffers */
|
||||
extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
|
||||
|
||||
/* Ethernet Driver Transmit buffers */
|
||||
extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
|
||||
|
||||
/* Global pointers to track current transmit and receive descriptors */
|
||||
extern ETH_DMADESCTypeDef *DMATxDescToSet;
|
||||
extern ETH_DMADESCTypeDef *DMARxDescToGet;
|
||||
|
||||
/* Global pointer for last received frame infos */
|
||||
extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
#ifdef CHECKSUM_BY_HARDWARE
|
||||
int i;
|
||||
#endif
|
||||
/* set MAC hardware address length */
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* set MAC hardware address */
|
||||
netif->hwaddr[0] = MAC_ADDR0;
|
||||
netif->hwaddr[1] = MAC_ADDR1;
|
||||
netif->hwaddr[2] = MAC_ADDR2;
|
||||
netif->hwaddr[3] = MAC_ADDR3;
|
||||
netif->hwaddr[4] = MAC_ADDR4;
|
||||
netif->hwaddr[5] = MAC_ADDR5;
|
||||
|
||||
/* initialize MAC address in ethernet MAC */
|
||||
ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr);
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Initialize Tx Descriptors list: Chain Mode */
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
|
||||
/* Initialize Rx Descriptors list: Chain Mode */
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
|
||||
|
||||
#ifdef CHECKSUM_BY_HARDWARE
|
||||
/* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */
|
||||
for(i=0; i<ETH_TXBUFNB; i++)
|
||||
{
|
||||
ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Note: TCP, UDP, ICMP checksum checking for received frame are enabled in DMA config */
|
||||
|
||||
/* Enable MAC and DMA transmission and reception */
|
||||
ETH_Start();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 availale 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)
|
||||
{
|
||||
err_t errval;
|
||||
struct pbuf *q;
|
||||
u8 *buffer = (u8 *)(DMATxDescToSet->Buffer1Addr);
|
||||
__IO ETH_DMADESCTypeDef *DmaTxDesc;
|
||||
uint16_t framelength = 0;
|
||||
uint32_t bufferoffset = 0;
|
||||
uint32_t byteslefttocopy = 0;
|
||||
uint32_t payloadoffset = 0;
|
||||
|
||||
DmaTxDesc = DMATxDescToSet;
|
||||
bufferoffset = 0;
|
||||
|
||||
/* copy frame from pbufs to driver buffers */
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
{
|
||||
/* Is this buffer available? If not, goto error */
|
||||
if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
errval = ERR_BUF;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get bytes in current lwIP buffer */
|
||||
byteslefttocopy = q->len;
|
||||
payloadoffset = 0;
|
||||
|
||||
/* Check if the length of data to copy is bigger than Tx buffer size*/
|
||||
while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE )
|
||||
{
|
||||
/* Copy data to Tx buffer*/
|
||||
memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );
|
||||
|
||||
/* Point to next descriptor */
|
||||
DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
|
||||
|
||||
/* Check if the buffer is available */
|
||||
if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
errval = ERR_USE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
buffer = (u8 *)(DmaTxDesc->Buffer1Addr);
|
||||
|
||||
byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
bufferoffset = 0;
|
||||
}
|
||||
|
||||
/* Copy the remaining bytes */
|
||||
memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), byteslefttocopy );
|
||||
bufferoffset = bufferoffset + byteslefttocopy;
|
||||
framelength = framelength + byteslefttocopy;
|
||||
}
|
||||
|
||||
/* Note: padding and CRC for transmitted frame
|
||||
are automatically inserted by DMA */
|
||||
|
||||
/* Prepare transmit descriptors to give to DMA*/
|
||||
ETH_Prepare_Transmit_Descriptors(framelength);
|
||||
|
||||
errval = ERR_OK;
|
||||
|
||||
error:
|
||||
|
||||
/* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
|
||||
if ((ETH->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
|
||||
{
|
||||
/* Clear TUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_TUS;
|
||||
|
||||
/* Resume DMA transmission*/
|
||||
ETH->DMATPDR = 0;
|
||||
}
|
||||
return errval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should allocate a pbuf and transfer the bytes of the incoming
|
||||
* packet from the interface into the pbuf.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return a pbuf filled with the received packet (including MAC header)
|
||||
* NULL on memory error
|
||||
*/
|
||||
static struct pbuf * low_level_input(struct netif *netif)
|
||||
{
|
||||
struct pbuf *p, *q;
|
||||
uint32_t len;
|
||||
FrameTypeDef frame;
|
||||
u8 *buffer;
|
||||
__IO ETH_DMADESCTypeDef *DMARxDesc;
|
||||
uint32_t bufferoffset = 0;
|
||||
uint32_t payloadoffset = 0;
|
||||
uint32_t byteslefttocopy = 0;
|
||||
uint32_t i=0;
|
||||
|
||||
/* get received frame */
|
||||
frame = ETH_Get_Received_Frame();
|
||||
|
||||
/* Obtain the size of the packet and put it into the "len" variable. */
|
||||
len = frame.length;
|
||||
buffer = (u8 *)frame.buffer;
|
||||
|
||||
/* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
DMARxDesc = frame.descriptor;
|
||||
bufferoffset = 0;
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
{
|
||||
byteslefttocopy = q->len;
|
||||
payloadoffset = 0;
|
||||
|
||||
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
|
||||
while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE )
|
||||
{
|
||||
/* Copy data to pbuf*/
|
||||
memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
|
||||
|
||||
/* Point to next descriptor */
|
||||
DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr);
|
||||
buffer = (unsigned char *)(DMARxDesc->Buffer1Addr);
|
||||
|
||||
byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
|
||||
payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
|
||||
bufferoffset = 0;
|
||||
}
|
||||
/* Copy remaining data in pbuf */
|
||||
memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy);
|
||||
bufferoffset = bufferoffset + byteslefttocopy;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release descriptors to DMA */
|
||||
DMARxDesc =frame.descriptor;
|
||||
|
||||
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
|
||||
for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
|
||||
{
|
||||
DMARxDesc->Status = ETH_DMARxDesc_OWN;
|
||||
DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
|
||||
/* Clear Segment_Count */
|
||||
DMA_RX_FRAME_infos->Seg_Count =0;
|
||||
|
||||
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
|
||||
if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
|
||||
{
|
||||
/* Clear RBUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_RBUS;
|
||||
/* Resume DMA reception */
|
||||
ETH->DMARPDR = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
err_t ethernetif_input(struct netif *netif)
|
||||
{
|
||||
err_t err;
|
||||
struct pbuf *p;
|
||||
|
||||
/* move received packet into a new pbuf */
|
||||
p = low_level_input(netif);
|
||||
|
||||
/* no packet could be read, silently ignore this */
|
||||
if (p == NULL) return ERR_MEM;
|
||||
|
||||
/* entry point to the LwIP stack */
|
||||
err = netif->input(p, netif);
|
||||
|
||||
if (err != ERR_OK)
|
||||
{
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
||||
pbuf_free(p);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwip";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
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...) */
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = low_level_output;
|
||||
|
||||
/* initialize the hardware */
|
||||
low_level_init(netif);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef __ETHERNETIF_H__
|
||||
#define __ETHERNETIF_H__
|
||||
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
err_t ethernetif_init(struct netif *netif);
|
||||
err_t ethernetif_input(struct netif *netif);
|
||||
|
||||
#endif
|
|
@ -81,6 +81,7 @@
|
|||
#include "lwip/autoip.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/igmp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -343,11 +344,20 @@ dhcp_coarse_tmr()
|
|||
while (netif != NULL) {
|
||||
/* only act on DHCP configured interfaces */
|
||||
if (netif->dhcp != NULL) {
|
||||
/* Realtek add */
|
||||
/* Not check t0/t1/t2 when dhcp state is DHCP_OFF */
|
||||
if(netif->dhcp->state == DHCP_OFF){
|
||||
netif = netif->next;
|
||||
continue;
|
||||
}
|
||||
/* Realtek add end */
|
||||
/* timer is active (non zero), and triggers (zeroes) now? */
|
||||
if (++netif->dhcp->lease_used == netif->dhcp->t0_timeout) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n"));
|
||||
/* this clients' lease time has expired */
|
||||
igmp_report_groups_leave(netif); // not remove group to make able to report group when dhcp bind
|
||||
dhcp_release(netif);
|
||||
netif->dhcp->seconds_elapsed = sys_now();
|
||||
dhcp_discover(netif);
|
||||
}else if (netif->dhcp->t2_rebind_time-- == 1) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
|
||||
|
@ -480,6 +490,7 @@ dhcp_t1_timeout(struct netif *netif)
|
|||
("dhcp_t1_timeout(): must renew\n"));
|
||||
/* This slightly different to RFC2131: DHCPREQUEST will be sent from state
|
||||
DHCP_RENEWING, not DHCP_BOUND */
|
||||
dhcp->seconds_elapsed = sys_now();
|
||||
dhcp_renew(netif);
|
||||
}
|
||||
}
|
||||
|
@ -682,6 +693,11 @@ dhcp_start(struct netif *netif)
|
|||
LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL );
|
||||
}
|
||||
|
||||
#if DHCP_CREATE_RAND_XID && defined(LWIP_SRAND)
|
||||
/* For each system startup, fill in a random seed with different system ticks. */
|
||||
LWIP_SRAND();
|
||||
#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_SRAND) */
|
||||
|
||||
/* clear data structure */
|
||||
memset(dhcp, 0, sizeof(struct dhcp));
|
||||
/* dhcp_set_state(&dhcp, DHCP_OFF); */
|
||||
|
@ -692,6 +708,7 @@ dhcp_start(struct netif *netif)
|
|||
return ERR_MEM;
|
||||
}
|
||||
ip_set_option(dhcp->pcb, SOF_BROADCAST);
|
||||
ip_set_option(dhcp->pcb, SOF_REUSEADDR);
|
||||
/* set up local and remote port for the pcb */
|
||||
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
|
@ -699,6 +716,7 @@ dhcp_start(struct netif *netif)
|
|||
udp_recv(dhcp->pcb, dhcp_recv, netif);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
|
||||
/* (re)start the DHCP negotiation */
|
||||
dhcp->seconds_elapsed = sys_now();
|
||||
result = dhcp_discover(netif);
|
||||
if (result != ERR_OK) {
|
||||
/* free resources allocated above */
|
||||
|
@ -742,6 +760,7 @@ dhcp_inform(struct netif *netif)
|
|||
}
|
||||
dhcp.pcb = pcb;
|
||||
ip_set_option(dhcp.pcb, SOF_BROADCAST);
|
||||
ip_set_option(dhcp.pcb, SOF_REUSEADDR);
|
||||
udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
|
||||
}
|
||||
|
@ -853,6 +872,9 @@ dhcp_decline(struct netif *netif)
|
|||
dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
|
||||
dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
|
||||
|
||||
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
|
||||
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr)));
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
/* resize pbuf to reflect true size of options */
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
@ -1182,6 +1204,21 @@ dhcp_reboot(struct netif *netif)
|
|||
return result;
|
||||
}
|
||||
|
||||
/** check if DHCP supplied netif->ip_addr
|
||||
*
|
||||
* @param netif the netif to check
|
||||
* @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING),
|
||||
* 0 otherwise
|
||||
*/
|
||||
u8_t
|
||||
dhcp_supplied_address(const struct netif *netif)
|
||||
{
|
||||
if ((netif != NULL) && (netif->dhcp != NULL)) {
|
||||
struct dhcp* dhcp = netif->dhcp;
|
||||
return (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release a DHCP lease.
|
||||
|
@ -1194,8 +1231,15 @@ dhcp_release(struct netif *netif)
|
|||
struct dhcp *dhcp = netif->dhcp;
|
||||
err_t result;
|
||||
u16_t msecs;
|
||||
ip_addr_t server_ip_addr;
|
||||
u8_t is_dhcp_supplied_address;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
|
||||
if (dhcp == NULL) {
|
||||
return ERR_ARG;
|
||||
}
|
||||
ip_addr_copy(server_ip_addr, dhcp->server_ip_addr);
|
||||
|
||||
is_dhcp_supplied_address = dhcp_supplied_address(netif);
|
||||
/* idle DHCP client */
|
||||
dhcp_set_state(dhcp, DHCP_OFF);
|
||||
/* clean old DHCP offer */
|
||||
|
@ -1207,15 +1251,24 @@ dhcp_release(struct netif *netif)
|
|||
ip_addr_set_zero(&dhcp->offered_si_addr);
|
||||
#endif /* LWIP_DHCP_BOOTP_FILE */
|
||||
dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
|
||||
dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0;
|
||||
|
||||
if (!is_dhcp_supplied_address) {
|
||||
/* don't issue release message when address is not dhcp-assigned */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* create and initialize the DHCP message header */
|
||||
result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
|
||||
if (result == ERR_OK) {
|
||||
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
|
||||
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&server_ip_addr)));
|
||||
|
||||
dhcp_option_trailer(dhcp);
|
||||
|
||||
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
|
||||
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
|
||||
udp_sendto_if(dhcp->pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif);
|
||||
dhcp_delete_msg(dhcp);
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
|
||||
} else {
|
||||
|
@ -1751,6 +1804,8 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
|
|||
LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
|
||||
(dhcp->p_out->len >= sizeof(struct dhcp_msg)));
|
||||
|
||||
/* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
|
||||
if (message_type != DHCP_REQUEST) {
|
||||
/* reuse transaction identifier in retransmissions */
|
||||
if (dhcp->tries == 0) {
|
||||
#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
|
||||
|
@ -1760,6 +1815,7 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
|
|||
#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
|
||||
}
|
||||
dhcp->xid = xid;
|
||||
}
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
|
||||
("transaction id xid(%"X32_F")\n", xid));
|
||||
|
||||
|
@ -1771,13 +1827,17 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
|
|||
dhcp->msg_out->hlen = netif->hwaddr_len;
|
||||
dhcp->msg_out->hops = 0;
|
||||
dhcp->msg_out->xid = htonl(dhcp->xid);
|
||||
if ((message_type == DHCP_DISCOVER) || (message_type == DHCP_REQUEST)) {
|
||||
dhcp->msg_out->secs = (uint16_t)((sys_now() - dhcp->seconds_elapsed) / configTICK_RATE_HZ);
|
||||
} else {
|
||||
dhcp->msg_out->secs = 0;
|
||||
}
|
||||
/* we don't need the broadcast flag since we can receive unicast traffic
|
||||
before being fully configured! */
|
||||
dhcp->msg_out->flags = 0;
|
||||
ip_addr_set_zero(&dhcp->msg_out->ciaddr);
|
||||
/* set ciaddr to netif->ip_addr based on message_type and state */
|
||||
if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) ||
|
||||
if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) ||
|
||||
((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */
|
||||
((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) {
|
||||
ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -57,6 +57,9 @@
|
|||
#include "lwip/lwip_timers.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/api.h"
|
||||
#if IP_NAPT
|
||||
#include "lwip/lwip_napt.h"
|
||||
#endif
|
||||
|
||||
/* Compile-time sanity checks for configuration errors.
|
||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
||||
|
@ -329,4 +332,8 @@ lwip_init(void)
|
|||
#if LWIP_TIMERS
|
||||
sys_timeouts_init();
|
||||
#endif /* LWIP_TIMERS */
|
||||
|
||||
#if IP_NAPT && !IP_NAPT_DYNAMIC
|
||||
ip_napt_init(IP_NAPT_MAX, IP_PORTMAP_MAX);
|
||||
#endif /* IP_NAPT */
|
||||
}
|
||||
|
|
|
@ -271,13 +271,27 @@ igmp_report_groups(struct netif *netif)
|
|||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif));
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->netif == netif) {
|
||||
if ((group->netif == netif) && (!ip_addr_cmp(&group->group_address, &allsystems))) {
|
||||
igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Realtek added to only send igmp leave, but not remove group */
|
||||
void
|
||||
igmp_report_groups_leave(struct netif *netif)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
|
||||
while (group != NULL) {
|
||||
if ((group->netif == netif) && (!ip_addr_cmp(&group->group_address, &allsystems)) && (group->last_reporter_flag)) {
|
||||
igmp_send(group, IGMP_LEAVE_GROUP);
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a group in the global igmp_group_list
|
||||
*
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -223,7 +223,7 @@ ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
|
|||
/* @todo Can't we simply remove the last datagram in the
|
||||
* linked list behind reassdatagrams?
|
||||
*/
|
||||
struct ip_reassdata *r, *oldest, *prev;
|
||||
struct ip_reassdata *r, *oldest, *prev, *oldest_prev;
|
||||
int pbufs_freed = 0, pbufs_freed_current;
|
||||
int other_datagrams;
|
||||
|
||||
|
@ -232,6 +232,7 @@ ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
|
|||
do {
|
||||
oldest = NULL;
|
||||
prev = NULL;
|
||||
oldest_prev = NULL;
|
||||
other_datagrams = 0;
|
||||
r = reassdatagrams;
|
||||
while (r != NULL) {
|
||||
|
@ -240,9 +241,11 @@ ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
|
|||
other_datagrams++;
|
||||
if (oldest == NULL) {
|
||||
oldest = r;
|
||||
oldest_prev = prev;
|
||||
} else if (r->timer <= oldest->timer) {
|
||||
/* older than the previous oldest */
|
||||
oldest = r;
|
||||
oldest_prev = prev;
|
||||
}
|
||||
}
|
||||
if (r->next != NULL) {
|
||||
|
@ -251,7 +254,7 @@ ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
|
|||
r = r->next;
|
||||
}
|
||||
if (oldest != NULL) {
|
||||
pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev);
|
||||
pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev);
|
||||
pbufs_freed += pbufs_freed_current;
|
||||
}
|
||||
} while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1));
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
|
||||
/** The one and only timeout list */
|
||||
static struct sys_timeo *next_timeout;
|
||||
#if NO_SYS
|
||||
#if NO_SYS || CONFIG_DYNAMIC_TICKLESS
|
||||
static u32_t timeouts_last_time;
|
||||
#endif /* NO_SYS */
|
||||
|
||||
|
@ -242,7 +242,7 @@ void sys_timeouts_init(void)
|
|||
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#if NO_SYS
|
||||
#if NO_SYS || CONFIG_DYNAMIC_TICKLESS
|
||||
/* Initialise timestamp for sys_check_timeouts */
|
||||
timeouts_last_time = sys_now();
|
||||
#endif
|
||||
|
@ -437,6 +437,53 @@ sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
|
|||
time_needed = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
#if CONFIG_DYNAMIC_TICKLESS
|
||||
if (time_needed == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
u8_t had_one;
|
||||
u32_t now;
|
||||
u32_t diff;
|
||||
|
||||
now = sys_now();
|
||||
/* this cares for wraparounds */
|
||||
diff = now - timeouts_last_time;
|
||||
do
|
||||
{
|
||||
had_one = 0;
|
||||
tmptimeout = next_timeout;
|
||||
if (tmptimeout && (tmptimeout->time <= diff)) {
|
||||
/* timeout has expired */
|
||||
had_one = 1;
|
||||
timeouts_last_time = now;
|
||||
diff -= tmptimeout->time;
|
||||
next_timeout = tmptimeout->next;
|
||||
handler = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
#if LWIP_DEBUG_TIMERNAMES
|
||||
if (handler != NULL) {
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",
|
||||
tmptimeout->handler_name, arg));
|
||||
}
|
||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (handler != NULL) {
|
||||
LOCK_TCPIP_CORE();
|
||||
handler(arg);
|
||||
UNLOCK_TCPIP_CORE();
|
||||
}
|
||||
}
|
||||
/* repeat until all expired timers have been called */
|
||||
}while(had_one);
|
||||
|
||||
LWIP_TCPIP_THREAD_ALIVE();
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
}
|
||||
|
||||
#else
|
||||
if (time_needed == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
|
@ -463,7 +510,9 @@ sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
|
|||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
|
|
|
@ -274,6 +274,7 @@ void
|
|||
mem_init(void)
|
||||
{
|
||||
struct mem *mem;
|
||||
|
||||
LWIP_ASSERT("Sanity check alignment",
|
||||
(SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
|
||||
|
||||
|
|
|
@ -1012,6 +1012,8 @@ tcp_slowtmr_start:
|
|||
++pcb_remove;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* If the PCB should be removed, do it. */
|
||||
if (pcb_remove) {
|
||||
struct tcp_pcb *pcb2;
|
||||
|
|
|
@ -96,6 +96,8 @@ void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest);
|
|||
err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr);
|
||||
err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr);
|
||||
void igmp_tmr(void);
|
||||
void igmp_report_groups_leave(struct netif *netif);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -214,6 +214,12 @@ void ip_debug_print(struct pbuf *p);
|
|||
#define ip_debug_print(p)
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
#if NAPT_DEBUG
|
||||
void napt_debug_print()ICACHE_FLASH_ATTR;
|
||||
#else
|
||||
#define napt_debug_print(p)
|
||||
#endif /* NAPT_DEBUG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -75,8 +75,7 @@
|
|||
LWIP_PLATFORM_ASSERT(message); handler;}} while(0)
|
||||
#endif /* LWIP_ERROR */
|
||||
|
||||
#if LWIP_DEBUG
|
||||
//#ifdef LWIP_DEBUG
|
||||
#if LWIP_DEBUG //#ifdef LWIP_DEBUG
|
||||
/** print debug message only if debug message type is enabled...
|
||||
* AND is of correct type AND is at least LWIP_DBG_LEVEL
|
||||
*/
|
||||
|
|
|
@ -68,6 +68,7 @@ struct dhcp
|
|||
ip_addr_t offered_si_addr;
|
||||
char boot_file_name[DHCP_FILE_LEN];
|
||||
#endif /* LWIP_DHCP_BOOTPFILE */
|
||||
u32_t seconds_elapsed;
|
||||
};
|
||||
|
||||
/* MUST be compiled with "pack structs" or equivalent! */
|
||||
|
|
|
@ -70,45 +70,6 @@ extern "C" {
|
|||
#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
|
||||
#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
|
||||
|
||||
/* DNS protocol flags */
|
||||
#define DNS_FLAG1_RESPONSE 0x80
|
||||
#define DNS_FLAG1_OPCODE_STATUS 0x10
|
||||
#define DNS_FLAG1_OPCODE_INVERSE 0x08
|
||||
#define DNS_FLAG1_OPCODE_STANDARD 0x00
|
||||
#define DNS_FLAG1_AUTHORATIVE 0x04
|
||||
#define DNS_FLAG1_TRUNC 0x02
|
||||
#define DNS_FLAG1_RD 0x01
|
||||
#define DNS_FLAG2_RA 0x80
|
||||
#define DNS_FLAG2_ERR_MASK 0x0f
|
||||
#define DNS_FLAG2_ERR_NONE 0x00
|
||||
#define DNS_FLAG2_ERR_NAME 0x03
|
||||
|
||||
/* DNS protocol states */
|
||||
#define DNS_STATE_UNUSED 0
|
||||
#define DNS_STATE_NEW 1
|
||||
#define DNS_STATE_ASKING 2
|
||||
#define DNS_STATE_DONE 3
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** DNS message header */
|
||||
struct dns_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t id);
|
||||
PACK_STRUCT_FIELD(u8_t flags1);
|
||||
PACK_STRUCT_FIELD(u8_t flags2);
|
||||
PACK_STRUCT_FIELD(u16_t numquestions);
|
||||
PACK_STRUCT_FIELD(u16_t numanswers);
|
||||
PACK_STRUCT_FIELD(u16_t numauthrr);
|
||||
PACK_STRUCT_FIELD(u16_t numextrarr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
#define SIZEOF_DNS_HDR 12
|
||||
|
||||
/* The size used for the next line is rather a hack, but it prevents including socket.h in all files
|
||||
that include memp.h, and that would possibly break portability (since socket.h defines some types
|
||||
and constants possibly already define by the OS).
|
||||
|
@ -148,6 +109,7 @@ void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
|
|||
ip_addr_t dns_getserver(u8_t numdns);
|
||||
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
|
||||
dns_found_callback found, void *callback_arg);
|
||||
void dns_reset_ttl();
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
#ifndef __LWIP_NAPT_H__
|
||||
#define __LWIP_NAPT_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if IP_FORWARD
|
||||
#if IP_NAPT
|
||||
|
||||
/* Default size of the tables used for NAPT */
|
||||
#define IP_NAPT_MAX 512
|
||||
#define IP_PORTMAP_MAX 32
|
||||
|
||||
/* Timeouts in sec for the various protocol types */
|
||||
#define IP_NAPT_TIMEOUT_MS_TCP (30*60*1000)
|
||||
#define IP_NAPT_TIMEOUT_MS_TCP_DISCON (20*1000)
|
||||
#define IP_NAPT_TIMEOUT_MS_UDP (2*1000)
|
||||
#define IP_NAPT_TIMEOUT_MS_ICMP (2*1000)
|
||||
|
||||
#define IP_NAPT_PORT_RANGE_START 49152
|
||||
#define IP_NAPT_PORT_RANGE_END 61439
|
||||
|
||||
struct napt_table {
|
||||
u32_t last;
|
||||
u32_t src;
|
||||
u32_t dest;
|
||||
u16_t sport;
|
||||
u16_t dport;
|
||||
u16_t mport;
|
||||
u8_t proto;
|
||||
u8_t fin1 : 1;
|
||||
u8_t fin2 : 1;
|
||||
u8_t finack1 : 1;
|
||||
u8_t finack2 : 1;
|
||||
u8_t synack : 1;
|
||||
u8_t rst : 1;
|
||||
u16_t next, prev;
|
||||
};
|
||||
|
||||
struct portmap_table {
|
||||
u32_t maddr;
|
||||
u32_t daddr;
|
||||
u16_t mport;
|
||||
u16_t dport;
|
||||
u8_t proto;
|
||||
u8 valid;
|
||||
};
|
||||
|
||||
extern struct portmap_table *ip_portmap_table;
|
||||
|
||||
/**
|
||||
* Allocates and initializes the NAPT tables.
|
||||
*
|
||||
* @param max_nat max number of enties in the NAPT table (use IP_NAPT_MAX if in doubt)
|
||||
* @param max_portmap max number of enties in the NAPT table (use IP_PORTMAP_MAX if in doubt)
|
||||
*/
|
||||
void
|
||||
ip_napt_init(uint16_t max_nat, uint8_t max_portmap);
|
||||
|
||||
|
||||
/**
|
||||
* Enable/Disable NAPT for a specified interface.
|
||||
*
|
||||
* @param addr ip address of the interface
|
||||
* @param enable non-zero to enable NAPT, or 0 to disable.
|
||||
*/
|
||||
void
|
||||
ip_napt_enable(u32_t addr, int enable);
|
||||
|
||||
|
||||
/**
|
||||
* Enable/Disable NAPT for a specified interface.
|
||||
*
|
||||
* @param netif number of the interface
|
||||
* @param enable non-zero to enable NAPT, or 0 to disable.
|
||||
*/
|
||||
void
|
||||
ip_napt_enable_no(u8_t number, int enable);
|
||||
|
||||
|
||||
/**
|
||||
* Register port mapping on the external interface to internal interface.
|
||||
* When the same port mapping is registered again, the old mapping is overwritten.
|
||||
* In this implementation, only 1 unique port mapping can be defined for each target address/port.
|
||||
*
|
||||
* @param proto target protocol
|
||||
* @param maddr ip address of the external interface
|
||||
* @param mport mapped port on the external interface, in host byte order.
|
||||
* @param daddr destination ip address
|
||||
* @param dport destination port, in host byte order.
|
||||
*/
|
||||
u8_t
|
||||
ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport);
|
||||
|
||||
|
||||
/**
|
||||
* Unregister port mapping on the external interface to internal interface.
|
||||
*
|
||||
* @param proto target protocol
|
||||
* @param maddr ip address of the external interface
|
||||
*/
|
||||
u8_t
|
||||
ip_portmap_remove(u8_t proto, u16_t mport);
|
||||
|
||||
#endif /* IP_NAPT */
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_NAPT_H__ */
|
|
@ -230,6 +230,9 @@ struct netif {
|
|||
u16_t loop_cnt_current;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
#if IP_NAPT
|
||||
u8_t napt;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if LWIP_SNMP
|
||||
|
|
|
@ -508,6 +508,14 @@
|
|||
#define IP_FORWARD 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP_NAPT==1: Enables the ability to do Network Address Port Translation (NAPT)
|
||||
* on forwarded packets. This only makes sense with IP_FORWARD==1.
|
||||
*/
|
||||
#ifndef IP_NAPT
|
||||
#define IP_NAPT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP_OPTIONS_ALLOWED: Defines the behavior for IP options.
|
||||
* IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
|
||||
|
@ -1297,7 +1305,7 @@
|
|||
* PPP_THREAD_NAME: The name assigned to the pppInputThread.
|
||||
*/
|
||||
#ifndef PPP_THREAD_NAME
|
||||
#define PPP_THREAD_NAME "pppInputThread"
|
||||
#define PPP_THREAD_NAME "pppIThrd"
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -2131,4 +2139,5 @@
|
|||
#define DNS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __LWIP_OPT_H__ */
|
||||
|
|
|
@ -363,7 +363,6 @@ int lwip_last_err_socket(int s); // errno
|
|||
#define select(a,b,c,d,e) lwip_select(a,b,c,d,e)
|
||||
#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c)
|
||||
|
||||
|
||||
#if LWIP_POSIX_SOCKETS_IO_NAMES
|
||||
#define read(a,b,c) lwip_read(a,b,c)
|
||||
#define write(a,b,c) lwip_write(a,b,c)
|
||||
|
|
|
@ -140,6 +140,12 @@ PACK_STRUCT_END
|
|||
#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */
|
||||
#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */
|
||||
|
||||
#define ETHTYPE_RARP 0x8035U
|
||||
#define RARP_REQUEST 3
|
||||
#define RARP_REPLY 4
|
||||
void rarp_retrieve_hook_callback(void (*callback)(u8_t *, u8_t *));
|
||||
|
||||
|
||||
/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables
|
||||
* or known to be 32-bit aligned within the protocol header. */
|
||||
#ifndef ETHADDR32_COPY
|
||||
|
|
|
@ -811,7 +811,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
|
||||
/* request was not directed to us */
|
||||
} else {
|
||||
#ifdef CONFIG_DONT_CARE_TP
|
||||
#ifdef CONFIG_DONT_CARE_TP
|
||||
if(netif->flags & NETIF_FLAG_IPSWITCH)
|
||||
netif->linkoutput(netif, p);
|
||||
else
|
||||
|
@ -844,6 +844,72 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
|||
pbuf_free(p);
|
||||
}
|
||||
|
||||
static void (*rarp_retrieve_cb)(u8_t *, u8_t *) = NULL;
|
||||
|
||||
void rarp_retrieve_hook_callback(void (*callback)(u8_t *, u8_t *)) {
|
||||
rarp_retrieve_cb = callback;
|
||||
}
|
||||
|
||||
static void
|
||||
etharp_rarp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
||||
{
|
||||
struct etharp_hdr *hdr;
|
||||
struct eth_hdr *ethhdr;
|
||||
#if LWIP_AUTOIP
|
||||
const u8_t * ethdst_hwaddr;
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
LWIP_ERROR("netif != NULL", (netif != NULL), return;);
|
||||
|
||||
/* drop short ARP packets: we have to check for p->len instead of p->tot_len here
|
||||
since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
|
||||
if (p->len < SIZEOF_ETHARP_PACKET) {
|
||||
ETHARP_STATS_INC(etharp.lenerr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
ethhdr = (struct eth_hdr *)p->payload;
|
||||
hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
|
||||
|
||||
/* RFC 826 "Packet Reception": */
|
||||
if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
|
||||
(hdr->hwlen != ETHARP_HWADDR_LEN) ||
|
||||
(hdr->protolen != sizeof(ip_addr_t)) ||
|
||||
(hdr->proto != PP_HTONS(ETHTYPE_IP))) {
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
|
||||
("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
|
||||
hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen));
|
||||
ETHARP_STATS_INC(etharp.proterr);
|
||||
ETHARP_STATS_INC(etharp.drop);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
ETHARP_STATS_INC(etharp.recv);
|
||||
|
||||
switch (hdr->opcode) {
|
||||
/* RARP request? */
|
||||
case PP_HTONS(RARP_REQUEST):
|
||||
LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_rarp_input: incoming RARP request\n"));
|
||||
break;
|
||||
|
||||
case PP_HTONS(RARP_REPLY):
|
||||
if(rarp_retrieve_cb != NULL)
|
||||
rarp_retrieve_cb((u8_t *)&hdr->dipaddr, (u8_t *)&hdr->dhwaddr.addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_rarp_input: RARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
|
||||
ETHARP_STATS_INC(etharp.err);
|
||||
break;
|
||||
|
||||
}
|
||||
/* free ARP packet */
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/** Just a small helper function that sends a pbuf to an ethernet address
|
||||
* in the arp_table specified by the index 'arp_idx'.
|
||||
*/
|
||||
|
@ -1243,6 +1309,9 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
|||
hdr->hwlen = ETHARP_HWADDR_LEN;
|
||||
hdr->protolen = sizeof(ip_addr_t);
|
||||
|
||||
if((opcode == RARP_REQUEST) | (opcode == RARP_REPLY))
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_RARP);
|
||||
else
|
||||
ethhdr->type = PP_HTONS(ETHTYPE_ARP);
|
||||
/* send ARP query */
|
||||
result = netif->linkoutput(netif, p);
|
||||
|
@ -1380,6 +1449,14 @@ ethernet_input(struct pbuf *p, struct netif *netif)
|
|||
/* pass p to ARP module */
|
||||
etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
|
||||
break;
|
||||
|
||||
case PP_HTONS(ETHTYPE_RARP):
|
||||
if (!(netif->flags & NETIF_FLAG_ETHARP)) {
|
||||
goto free_and_return;
|
||||
}
|
||||
/* pass p to RARP module */
|
||||
etharp_rarp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
|
||||
break;
|
||||
#endif /* LWIP_ARP */
|
||||
#if PPPOE_SUPPORT
|
||||
case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */
|
||||
|
|
|
@ -53,7 +53,10 @@ typedef enum _SHA2_TYPE_ {
|
|||
extern int rtl_cryptoEngine_init(void);
|
||||
extern void rtl_cryptoEngine_info(void);
|
||||
|
||||
extern _LONG_CALL_ int __rtl_cryptoEngine_exit_v1_00(void);
|
||||
extern int init_status;
|
||||
|
||||
#define rtl_cryptoEngine_deinit __rtl_cryptoEngine_exit_v1_00
|
||||
|
||||
//
|
||||
// Authentication
|
||||
|
|
Binary file not shown.
143
USDK/flasher.mk
143
USDK/flasher.mk
|
@ -37,6 +37,7 @@ endif
|
|||
PICK = $(TOOLS_PATH)pick$(EXE)
|
||||
PADDING = $(TOOLS_PATH)padding$(EXE)
|
||||
CHCKSUM = $(TOOLS_PATH)checksum$(EXE)
|
||||
IMAGETOOL = $(TOOLS_PATH)rtlaimage$(EXE)
|
||||
|
||||
# openocd tools
|
||||
OPENOCD = $(OPENOCD_PATH)openocd.exe
|
||||
|
@ -72,11 +73,9 @@ NMAPFILE = $(OBJ_DIR)/$(TARGET).nmap
|
|||
|
||||
RAM1_IMAGE ?= $(BIN_DIR)/ram_1.bin
|
||||
RAM1P_IMAGE ?= $(BIN_DIR)/ram_1.p.bin
|
||||
RAM1R_IMAGE ?= $(BIN_DIR)/ram_1.r.bin
|
||||
|
||||
RAM2_IMAGE = $(BIN_DIR)/ram_2.bin
|
||||
RAM2P_IMAGE = $(BIN_DIR)/ram_2.p.bin
|
||||
RAM2NS_IMAGE = $(BIN_DIR)/ram_2.ns.bin
|
||||
|
||||
RAM3_IMAGE = $(BIN_DIR)/sdram.bin
|
||||
RAM3P_IMAGE = $(BIN_DIR)/sdram.p.bin
|
||||
|
@ -89,18 +88,28 @@ OTA_IMAGE = $(BIN_DIR)/ota.bin
|
|||
mp: FLASH_IMAGE = $(BIN_DIR)/ram_all_mp.bin
|
||||
mp: OTA_IMAGE = $(BIN_DIR)/ota_mp.bin
|
||||
|
||||
TST_IMAGE = $(BIN_DIR)/ram_2.bin
|
||||
|
||||
.PHONY: genbin1 genbin23 flashburn reset test readfullflash flashboot flashwebfs flash_OTA runram runsdram
|
||||
.PHONY: genbin flashburn reset test readfullflash flashboot flashwebfs flash_OTA runram runsdram
|
||||
.NOTPARALLEL: all mp genbin1 genbin23 flashburn reset test readfullflash _endgenbin flashwebfs flash_OTA
|
||||
|
||||
all: $(ELFFILE) $(OTA_IMAGE) $(FLASH_IMAGE) _endgenbin
|
||||
mp: $(ELFFILE) $(OTA_IMAGE) $(FLASH_IMAGE) _endgenbin
|
||||
all: $(ELFFILE) $(FLASH_IMAGE) _endgenbin
|
||||
mp: $(ELFFILE) $(FLASH_IMAGE) _endgenbin
|
||||
|
||||
genbin1: $(ELFFILE) $(RAM1P_IMAGE)
|
||||
genbin: $(ELFFILE) $(FLASH_IMAGE) _endgenbin
|
||||
|
||||
genbin23: $(ELFFILE) $(OTA_IMAGE) $(FLASH_IMAGE) _endgenbin
|
||||
$(ELFFILE):
|
||||
$(error Falsher: file $@ not found)
|
||||
|
||||
$(NMAPFILE): $(ELFFILE)
|
||||
@echo "==========================================================="
|
||||
@echo "Build names map file"
|
||||
@echo $@
|
||||
@$(NM) $< | sort > $@
|
||||
# @echo "==========================================================="
|
||||
|
||||
$(FLASH_IMAGE):$(ELFFILE)
|
||||
@echo "==========================================================="
|
||||
$(IMAGETOOL) -a -r -o $(BIN_DIR)/ $(ELFFILE)
|
||||
|
||||
_endgenbin:
|
||||
@echo "-----------------------------------------------------------"
|
||||
|
@ -233,14 +242,14 @@ reset:
|
|||
runram:
|
||||
@$(OPENOCD) -f interface/$(FLASHER).cfg -c 'transport select swd' -c 'adapter_khz 1000' \
|
||||
-f $(FLASHER_PATH)rtl8710.ocd -c 'init' -c 'reset halt' -c 'adapter_khz $(FLASHER_SPEED)' \
|
||||
-c 'load_image $(RAM1R_IMAGE) 0x10000bc8 bin' \
|
||||
-c 'load_image $(RAM1_IMAGE) 0x10000bc8 bin' \
|
||||
-c 'load_image $(RAM2_IMAGE) 0x10006000 bin' \
|
||||
-c 'mww 0x40000210 0x20111157' -c 'rtl8710_reboot' -c shutdown
|
||||
|
||||
runsdram:
|
||||
@$(OPENOCD) -f interface/$(FLASHER).cfg -c 'transport select swd' -c 'adapter_khz 1000' \
|
||||
-f $(FLASHER_PATH)rtl8710.ocd -c 'init' -c 'reset halt' -c 'adapter_khz $(FLASHER_SPEED)' \
|
||||
-c 'load_image $(RAM1R_IMAGE) 0x10000bc8 bin' \
|
||||
-c 'load_image $(RAM1_IMAGE) 0x10000bc8 bin' \
|
||||
-c 'load_image $(RAM2_IMAGE) 0x10006000 bin' \
|
||||
-c 'boot_load_srdam $(RAM3_IMAGE) 0x30000000' \
|
||||
-c shutdown
|
||||
|
@ -248,120 +257,6 @@ runsdram:
|
|||
endif
|
||||
endif
|
||||
|
||||
$(NMAPFILE): $(ELFFILE)
|
||||
@echo "==========================================================="
|
||||
@echo "Build names map file"
|
||||
@echo $@
|
||||
@$(NM) $< | sort > $@
|
||||
# @echo "==========================================================="
|
||||
|
||||
$(FLASH_IMAGE): $(RAM1P_IMAGE) $(RAM2P_IMAGE) $(RAM3P_IMAGE)
|
||||
@echo "==========================================================="
|
||||
@echo "Make Flash image ($(FLASH_IMAGE))"
|
||||
# @echo "==========================================================="
|
||||
@mkdir -p $(BIN_DIR)
|
||||
@rm -f $(FLASH_IMAGE)
|
||||
@cat $(RAM1P_IMAGE) > $(FLASH_IMAGE)
|
||||
# @chmod 777 $(FLASH_IMAGE)
|
||||
ifdef PADDINGSIZE
|
||||
@$(PADDING) $(PADDINGSIZE) 0xFF $(FLASH_IMAGE)
|
||||
endif
|
||||
@cat $(RAM2P_IMAGE) >> $(FLASH_IMAGE)
|
||||
@cat $(RAM3P_IMAGE) >> $(FLASH_IMAGE)
|
||||
# @echo "Image ($(FLASH_IMAGE)) size $(shell printf '%d\n' $$(( $$(stat --printf="%s" $(FLASH_IMAGE)) )) ) bytes"
|
||||
# @echo "==========================================================="
|
||||
# @rm $(BIN_DIR)/ram_*.p.bin
|
||||
|
||||
$(OTA_IMAGE): $(RAM2NS_IMAGE) $(RAM3_IMAGE)
|
||||
@echo "==========================================================="
|
||||
@echo "Make OTA image ($(OTA_IMAGE))"
|
||||
@rm -f $(OTA_IMAGE)
|
||||
@cat $(RAM2NS_IMAGE) > $(OTA_IMAGE)
|
||||
@cat $(RAM3P_IMAGE) >> $(OTA_IMAGE)
|
||||
# @chmod 777 $(OTA_IMAGE)
|
||||
@$(CHCKSUM) $(OTA_IMAGE) || true
|
||||
# @echo "==========================================================="
|
||||
|
||||
$(RAM1P_IMAGE): $(ELFFILE) $(NMAPFILE)
|
||||
@echo "==========================================================="
|
||||
@echo "Create image1r ($(RAM1R_IMAGE))"
|
||||
# @echo "===========================================================" .bootloader
|
||||
ifdef COMPILED_BOOT
|
||||
@mkdir -p $(BIN_DIR)
|
||||
@rm -f $(RAM1_IMAGE) $(RAM1R_IMAGE)
|
||||
ifdef COMPILED_BOOT_BIN
|
||||
@$(eval RAM1_START_ADDR := $(shell grep _binary_build_bin_ram_1_r_bin_start $(NMAPFILE) | awk '{print $$1}'))
|
||||
@$(eval RAM1_END_ADDR := $(shell grep _binary_build_bin_ram_1_r_bin_end $(NMAPFILE) | awk '{print $$1}'))
|
||||
else
|
||||
@$(eval RAM1_START_ADDR := $(shell grep __ram_image1_text_start__ $(NMAPFILE) | awk '{print $$1}'))
|
||||
@$(eval RAM1_END_ADDR := $(shell grep __ram_image1_text_end__ $(NMAPFILE) | awk '{print $$1}'))
|
||||
endif
|
||||
$(if $(RAM1_START_ADDR),,$(error "Not found __ram_image1_text_start__!"))
|
||||
$(if $(RAM1_END_ADDR),,$(error "Not found __ram_image1_text_end__!"))
|
||||
ifeq ($(RAM1_START_ADDR),$(RAM1_END_ADDR))
|
||||
ifdef COMPILED_BOOT_BIN
|
||||
$(OBJCOPY) --change-section-address .boot.head=0x10000ba8 -j .boot.head -j .bootloader -Obinary $(ELFFILE) $(RAM1P_IMAGE)
|
||||
else
|
||||
# $(OBJCOPY) -j .rom_ram -Obinary $(ELFFILE) $(RAM_IMAGE)
|
||||
$(OBJCOPY) -j .ram.start.table -j .ram_image1.text -Obinary $(ELFFILE) $(RAM1R_IMAGE)
|
||||
$(PICK) 0x$(RAM1_START_ADDR) 0x$(RAM1_END_ADDR) $(RAM1R_IMAGE) $(RAM1P_IMAGE) head+reset_offset 0x0B000
|
||||
endif
|
||||
else
|
||||
$(error "BOOT-image size = 0")
|
||||
# $(error Flasher: COMPILE_BOOT = No)
|
||||
endif
|
||||
else
|
||||
@if [ -s $(RAM1R_IMAGE) ]; then echo "Use external $(RAM1R_IMAGE)!"; fi
|
||||
endif
|
||||
|
||||
$(RAM2P_IMAGE): $(ELFFILE) $(NMAPFILE)
|
||||
@echo "==========================================================="
|
||||
@echo "Create image2p ($(RAM2P_IMAGE))"
|
||||
# @echo "==========================================================="
|
||||
@mkdir -p $(BIN_DIR)
|
||||
@rm -f $(RAM2_IMAGE) $(RAM2P_IMAGE)
|
||||
@$(eval RAM2_START_ADDR = $(shell grep __ram_image2_text $(NMAPFILE) | grep _start__ | awk '{print $$1}'))
|
||||
@$(eval RAM2_END_ADDR = $(shell grep __ram_image2_text $(NMAPFILE) | grep _end__ | awk '{print $$1}'))
|
||||
$(if $(RAM2_START_ADDR),,$(error "Not found __ram_image2_text_start__!"))
|
||||
$(if $(RAM2_END_ADDR),,$(error "Not found __ram_image2_text_end__!"))
|
||||
@$(OBJCOPY) -j .image2.start.table -j .ram_image2.text -j .ram_image2.rodata -j .ram.data -Obinary $(ELFFILE) $(RAM2_IMAGE)
|
||||
@$(PICK) 0x$(RAM2_START_ADDR) 0x$(RAM2_END_ADDR) $(RAM2_IMAGE) $(RAM2P_IMAGE) body+reset_offset+sig
|
||||
|
||||
$(RAM2NS_IMAGE):$(ELFFILE) $(NMAPFILE)
|
||||
@echo "==========================================================="
|
||||
@echo "Create image2ns ($(RAM2NS_IMAGE))"
|
||||
# @echo "==========================================================="
|
||||
mkdir -p $(BIN_DIR)
|
||||
rm -f $(RAM2_IMAGE) $(RAM2NS_IMAGE)
|
||||
$(eval RAM2_START_ADDR = $(shell grep __ram_image2_text $(NMAPFILE) | grep _start__ | awk '{print $$1}'))
|
||||
$(eval RAM2_END_ADDR = $(shell grep __ram_image2_text $(NMAPFILE) | grep _end__ | awk '{print $$1}'))
|
||||
$(if $(RAM2_START_ADDR),,$(error "Not found __ram_image2_text_start__!"))
|
||||
$(if $(RAM2_END_ADDR),,$(error "Not found __ram_image2_text_end__!"))
|
||||
$(OBJCOPY) -j .image2.start.table -j .ram_image2.text -j .ram_image2.rodata -j .ram.data -Obinary $(ELFFILE) $(RAM2_IMAGE)
|
||||
$(PICK) 0x$(RAM2_START_ADDR) 0x$(RAM2_END_ADDR) $(RAM2_IMAGE) $(RAM2NS_IMAGE) body+reset_offset
|
||||
|
||||
$(RAM3_IMAGE): $(ELFFILE) $(NMAPFILE)
|
||||
@echo "==========================================================="
|
||||
@echo "Create image3 (SDRAM, $(RAM3P_IMAGE))"
|
||||
# @echo "==========================================================="
|
||||
@mkdir -p $(BIN_DIR)
|
||||
@rm -f $(RAM3_IMAGE) $(RAM3P_IMAGE)
|
||||
@$(eval RAM3_START_ADDR = $(shell grep __sdram_data_ $(NMAPFILE) | grep _start__ | awk '{print $$1}'))
|
||||
@$(eval RAM3_END_ADDR = $(shell grep __sdram_data_ $(NMAPFILE) | grep _end__ | awk '{print $$1}'))
|
||||
$(if $(RAM3_START_ADDR),,$(error "Not found __sdram_data_start__!"))
|
||||
$(if $(RAM3_END_ADDR),,$(error "Not found __sdram_data_end__!"))
|
||||
#ifneq ($(RAM3_START_ADDR),$(RAM3_END_ADDR))
|
||||
@echo $(RAM3_START_ADDR) $(RAM3_END_ADDR)
|
||||
@$(OBJCOPY) -j .image3 -j .sdr_text -j .sdr_rodata -j .sdr_data -Obinary $(ELFFILE) $(RAM3_IMAGE)
|
||||
$(PICK) 0x$(RAM3_START_ADDR) 0x$(RAM3_END_ADDR) $(RAM3_IMAGE) $(RAM3P_IMAGE) body+reset_offset
|
||||
#else
|
||||
# @rm -f $(RAM3_IMAGE) $(RAM3P_IMAGE)
|
||||
# @echo "SDRAM not used (size = 0)"
|
||||
#endif
|
||||
|
||||
$(ELFFILE):
|
||||
$(error Falsher: file $@ not found)
|
||||
|
||||
clean:
|
||||
@rm -f $(BIN_DIR)/*.bin
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#=============================================
|
||||
# SDK CONFIG
|
||||
#=============================================
|
||||
#USE_SDRAM = 1
|
||||
USE_SDRAM = 1
|
||||
WEB_INA219_DRV = 1
|
||||
#WEB_MLX90614_DRV = 1
|
||||
#WEB_ADC_DRV = 1
|
||||
|
@ -29,6 +29,7 @@ endif
|
|||
RTOSDIR=freertos_v9.0.0
|
||||
LWIPDIR=lwip_v1.4.1
|
||||
|
||||
|
||||
ifdef USE_UVC
|
||||
USE_SDRAM = 1
|
||||
USE_GCC_LIB = 1
|
||||
|
@ -46,6 +47,7 @@ ADD_SRC_C += project/src/user/user_start.c
|
|||
# components
|
||||
DRAM_C += project/src/console/atcmd_user.c
|
||||
DRAM_C += project/src/console/wifi_console.c
|
||||
#ADD_SRC_C += project/src/console/acl_tst.c
|
||||
#DRAM_C += project/src/console/wlan_tst.c
|
||||
#ADD_SRC_C += project/src/console/pwm_tst.c
|
||||
#ADD_SRC_C += project/src/WS2812/ws2812_tst.c
|
||||
|
|
|
@ -27,6 +27,27 @@
|
|||
#include <platform/platform_stdlib.h>
|
||||
#include "platform_opts.h"
|
||||
|
||||
////////////////////////////
|
||||
|
||||
#ifdef CONFIG_SDR_EN
|
||||
#define WIFI_LOGO_CERTIFICATION_CONFIG 1 // for ping 10k test buffer setting
|
||||
#else
|
||||
#define WIFI_LOGO_CERTIFICATION_CONFIG 0
|
||||
#endif
|
||||
/*LWIP_UART_ADAPTER==1: Enable LWIP_UART_ADAPTER when CONFIG_GAGENT is enabled,
|
||||
because some GAGENT functions denpond on the following macro definitions.*/
|
||||
#define LWIP_UART_ADAPTER 0
|
||||
|
||||
|
||||
/**
|
||||
* IP_FORWARD==1: Enables the ability to forward IP packets across network
|
||||
* interfaces. If you are going to run lwIP on a device with only one network
|
||||
* interface, define this to 0.
|
||||
*/
|
||||
#define IP_FORWARD 1
|
||||
#define IP_NAPT 1
|
||||
|
||||
////////////////////////////
|
||||
/**
|
||||
* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first
|
||||
* local TCP/UDP pcb (default==0). This can prevent creating predictable port
|
||||
|
@ -34,13 +55,13 @@
|
|||
*/
|
||||
#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1
|
||||
|
||||
#define WIFI_LOGO_CERTIFICATION_CONFIG 1 //for ping 10k test buffer setting
|
||||
/**
|
||||
* MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library
|
||||
* instead of the lwip internal allocator. Can save code size if you
|
||||
* already use it.
|
||||
*/
|
||||
#define MEM_LIBC_MALLOC 1
|
||||
|
||||
/**
|
||||
* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator.
|
||||
* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution
|
||||
|
@ -48,6 +69,29 @@
|
|||
*/
|
||||
#define MEMP_MEM_MALLOC 1
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname
|
||||
* field.
|
||||
*/
|
||||
#define LWIP_NETIF_HOSTNAME 1
|
||||
#define LWIP_NETIF_HOSTNAME_SIZE 16
|
||||
/**
|
||||
* netif0: DEF_HOSTNAME "0", netif1: DEF_HOSTNAME "1", ..
|
||||
*/
|
||||
#define DEF_HOSTNAME "rtl871x"
|
||||
|
||||
/**
|
||||
* LWIP_AUTOIP==1: Enable AUTOIP module.
|
||||
*/
|
||||
#define LWIP_AUTOIP 0 // Realtek modified (0->1)
|
||||
|
||||
/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided
|
||||
* by your system, set this to 0 and include <sys/time.h> in cc.h */
|
||||
#if defined(_SYS__TIMEVAL_H_)
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#endif
|
||||
|
||||
////////////////
|
||||
/**
|
||||
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
|
||||
* critical regions during buffer allocation, deallocation and memory
|
||||
|
@ -64,23 +108,16 @@
|
|||
#define IP_FRAG 1
|
||||
#define ARP_QUEUEING 0
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname
|
||||
* field.
|
||||
*/
|
||||
#define LWIP_NETIF_HOSTNAME 1
|
||||
#define LWIP_NETIF_HOSTNAME_SIZE 16
|
||||
/**
|
||||
* netif0: DEF_HOSTNAME "0", netif1: DEF_HOSTNAME "1", ..
|
||||
*/
|
||||
#define DEF_HOSTNAME "rtl871x"
|
||||
|
||||
/**
|
||||
* NO_SYS==1: Provides VERY minimal functionality. Otherwise,
|
||||
* use lwIP facilities.
|
||||
*/
|
||||
#define NO_SYS 0
|
||||
|
||||
#ifndef CONFIG_DYNAMIC_TICKLESS
|
||||
#define CONFIG_DYNAMIC_TICKLESS 0
|
||||
#endif
|
||||
|
||||
/* ---------- Memory options ---------- */
|
||||
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
|
||||
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
|
||||
|
@ -90,9 +127,9 @@
|
|||
/* MEM_SIZE: the size of the heap memory. If the application will send
|
||||
a lot of data that needs to be copied, this should be set high. */
|
||||
#if WIFI_LOGO_CERTIFICATION_CONFIG
|
||||
#define MEM_SIZE (10*1024) //for ping 10k test
|
||||
#define MEM_SIZE (16*1024) //for ping 10k test
|
||||
#else
|
||||
#define MEM_SIZE (5*1024)
|
||||
#define MEM_SIZE (6*1024)
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||
|
@ -119,7 +156,7 @@ a lot of data that needs to be copied, this should be set high. */
|
|||
/* ---------- Pbuf options ---------- */
|
||||
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
|
||||
#if WIFI_LOGO_CERTIFICATION_CONFIG
|
||||
#define PBUF_POOL_SIZE 30 //for ping 10k test
|
||||
#define PBUF_POOL_SIZE 30 // for ping 10k test
|
||||
#else
|
||||
#define PBUF_POOL_SIZE 20
|
||||
#endif
|
||||
|
@ -155,18 +192,17 @@ a lot of data that needs to be copied, this should be set high. */
|
|||
#define TCP_SND_QUEUELEN (4*TCP_SND_BUF/TCP_MSS)
|
||||
|
||||
/* TCP receive window. */
|
||||
#define TCP_WND (4*TCP_MSS) // (2*TCP_MSS)
|
||||
|
||||
#if WIFI_LOGO_CERTIFICATION_CONFIG
|
||||
#define TCP_WND (4*TCP_MSS)
|
||||
#else
|
||||
#define TCP_WND (2*TCP_MSS)
|
||||
#endif
|
||||
|
||||
/* ---------- ICMP options ---------- */
|
||||
#define LWIP_ICMP 1
|
||||
|
||||
/* ---------- ARP options ----------- */
|
||||
#define LWIP_ARP 1
|
||||
/**
|
||||
* LWIP_AUTOIP==1: Enable AUTOIP module.
|
||||
*/
|
||||
#define LWIP_AUTOIP 0 //Realtek modified (0->1)
|
||||
|
||||
/* ---------- DHCP options ---------- */
|
||||
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
|
||||
|
@ -185,28 +221,29 @@ a lot of data that needs to be copied, this should be set high. */
|
|||
|
||||
/* Support Multicast */
|
||||
#define LWIP_IGMP 1
|
||||
|
||||
extern __attribute__ ((long_call)) unsigned int Rand(void);
|
||||
#define LWIP_RAND() Rand()
|
||||
extern _LONG_CALL_ u32 Rand(void);
|
||||
#define LWIP_RAND() Rand() // srand(sys_now())
|
||||
|
||||
/* Support TCP Keepalive */
|
||||
#define LWIP_TCP_KEEPALIVE 1
|
||||
|
||||
/*LWIP_UART_ADAPTER==1: Enable LWIP_UART_ADAPTER when CONFIG_GAGENT is enabled,
|
||||
because some GAGENT functions denpond on the following macro definitions.*/
|
||||
#if CONFIG_EXAMPLE_UART_ADAPTER
|
||||
#define LWIP_UART_ADAPTER 1
|
||||
#else
|
||||
#define LWIP_UART_ADAPTER 0
|
||||
#endif
|
||||
|
||||
#if LWIP_UART_ADAPTER
|
||||
#if LWIP_UART_ADAPTER || CONFIG_ETHERNET || CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
|
||||
|
||||
/**
|
||||
* LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
|
||||
* SO_SNDTIMEO processing.
|
||||
*/
|
||||
#undef LWIP_SO_SNDTIMEO
|
||||
#define LWIP_SO_SNDTIMEO 1
|
||||
|
||||
#undef SO_REUSE
|
||||
#define SO_REUSE 1
|
||||
|
||||
/**
|
||||
* MEMP_NUM_NETCONN: the number of struct netconns.
|
||||
* (only needed if you use the sequential API, like api_lib.c)
|
||||
*/
|
||||
#undef MEMP_NUM_NETCONN
|
||||
#define MEMP_NUM_NETCONN 10
|
||||
|
||||
|
@ -218,15 +255,7 @@ extern __attribute__ ((long_call)) unsigned int Rand(void);
|
|||
#define TCP_KEEPCNT_DEFAULT 10U
|
||||
#endif
|
||||
|
||||
#if CONFIG_EXAMPLE_UART_ATCMD
|
||||
#undef LWIP_SO_SNDTIMEO
|
||||
#define LWIP_SO_SNDTIMEO 1
|
||||
|
||||
#undef SO_REUSE
|
||||
#define SO_REUSE 1
|
||||
|
||||
#undef MEMP_NUM_NETCONN
|
||||
#define MEMP_NUM_NETCONN 10
|
||||
#if CONFIG_EXAMPLE_UART_ATCMD || CONFIG_EXAMPLE_SPI_ATCMD
|
||||
|
||||
#undef MEMP_NUM_TCP_PCB
|
||||
#define MEMP_NUM_TCP_PCB (MEMP_NUM_NETCONN)
|
||||
|
@ -234,18 +263,21 @@ extern __attribute__ ((long_call)) unsigned int Rand(void);
|
|||
#undef MEMP_NUM_UDP_PCB
|
||||
#define MEMP_NUM_UDP_PCB (MEMP_NUM_NETCONN)
|
||||
|
||||
#undef TCP_WND
|
||||
#define TCP_WND (4*TCP_MSS)
|
||||
|
||||
#define TCP_KEEPIDLE_DEFAULT 10000UL
|
||||
#define TCP_KEEPINTVL_DEFAULT 1000UL
|
||||
#define TCP_KEEPCNT_DEFAULT 10U
|
||||
|
||||
#define ERRNO 1
|
||||
|
||||
#endif
|
||||
|
||||
/* ---------- Statistics options ---------- */
|
||||
/*
|
||||
--------------------------------------
|
||||
--------- Statistics options ---------
|
||||
--------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* LWIP_STATS==1: Enable statistics collection in lwip_stats.
|
||||
*/
|
||||
#define LWIP_STATS 0
|
||||
|
||||
#define LWIP_PROVIDE_ERRNO 1
|
||||
|
||||
|
||||
|
@ -255,15 +287,6 @@ extern __attribute__ ((long_call)) unsigned int Rand(void);
|
|||
--------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
The STM32F2x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
|
||||
- To use this feature let the following define uncommented.
|
||||
- To disable it and process by CPU comment the the checksum.
|
||||
*/
|
||||
//Do checksum by lwip - WLAN nic does not support Checksum offload
|
||||
//#define CHECKSUM_BY_HARDWARE
|
||||
|
||||
|
||||
#ifdef CHECKSUM_BY_HARDWARE
|
||||
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
|
||||
#define CHECKSUM_GEN_IP 0
|
||||
|
@ -321,6 +344,7 @@ The STM32F2x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
|
|||
|
||||
#define LWIP_DEBUG 0
|
||||
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- OS options ----------
|
||||
|
@ -376,11 +400,10 @@ The STM32F2x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
|
|||
*/
|
||||
#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 2)
|
||||
|
||||
/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided
|
||||
* by your system, set this to 0 and include <sys/time.h> in cc.h */
|
||||
#if defined(_SYS__TIMEVAL_H_)
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#endif
|
||||
/* Added by Realtek */
|
||||
#ifndef DNS_IGNORE_REPLY_ERR
|
||||
#define DNS_IGNORE_REPLY_ERR 1
|
||||
#endif /* DNS_IGNORE_REPLY_ERR */
|
||||
|
||||
#endif /* __LWIPOPTS_H__ */
|
||||
|
||||
|
|
|
@ -377,6 +377,7 @@ LOCAL void fATSP(int argc, char *argv[])
|
|||
};
|
||||
printf("WakeLock Status %d\n", pmu_get_wakelock_status());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_at[] = {
|
||||
|
|
|
@ -74,7 +74,7 @@ int main(void)
|
|||
WDGStart();
|
||||
#endif
|
||||
|
||||
#if (defined(CONFIG_CRYPTO_STARTUP) && (CONFIG_CRYPTO_STARTUP))
|
||||
#if 0 // (defined(CONFIG_CRYPTO_STARTUP) && (CONFIG_CRYPTO_STARTUP))
|
||||
if(rtl_cryptoEngine_init() != 0 ) {
|
||||
DBG_8195A("Crypto engine init failed!\n");
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "freertos_pmu.h"
|
||||
#include "task.h"
|
||||
#include "diag.h"
|
||||
#include "hal_crypto.h"
|
||||
#include "netbios/netbios.h"
|
||||
#include "sntp/sntp.h"
|
||||
#include "user/sys_cfg.h"
|
||||
|
@ -59,12 +60,11 @@ void sys_write_cfg(void)
|
|||
}
|
||||
|
||||
extern void console_init(void);
|
||||
extern void HalReInitPlatformTimer(void);
|
||||
|
||||
void user_init_thrd(void) {
|
||||
|
||||
|
||||
/* Read system config*/
|
||||
|
||||
if(syscfg.cfg.b.pin_clear_cfg_enable
|
||||
&& 0) { // user_test_clear_pin()
|
||||
wifi_cfg.load_flg = 0;
|
||||
|
@ -82,6 +82,14 @@ void user_init_thrd(void) {
|
|||
/* Load cfg, init WiFi + LwIP init, WiFi start if wifi_cfg.mode != RTW_MODE_NONE */
|
||||
wifi_init();
|
||||
|
||||
#if (defined(CONFIG_CRYPTO_STARTUP) && (CONFIG_CRYPTO_STARTUP))
|
||||
if(rtl_cryptoEngine_init() != 0 ) {
|
||||
error_printf("Crypto engine init failed!\n");
|
||||
}
|
||||
#else
|
||||
// rtl_cryptoEngine_deinit();
|
||||
#endif
|
||||
|
||||
#if defined(USE_NETBIOS)
|
||||
if(syscfg.cfg.b.netbios_ena) netbios_init();
|
||||
#endif
|
||||
|
|
6
tools/rtlaimage/make_windows_exe.bat
Normal file
6
tools/rtlaimage/make_windows_exe.bat
Normal file
|
@ -0,0 +1,6 @@
|
|||
rem pip install wheel
|
||||
rem pip install pyinstaller
|
||||
pyinstaller -c --onedir --onefile -n rtlaimage rtlaimage.py
|
||||
copy /b dist\rtlaimage.exe ..\..\USDK\component\soc\realtek\8195a\misc\iar_utility\common\tools\rtlaimage.exe
|
||||
del /Q rtlaimage.spec
|
||||
rm -rf dist build
|
345
tools/rtlaimage/rtlaimage.py
Normal file
345
tools/rtlaimage/rtlaimage.py
Normal file
|
@ -0,0 +1,345 @@
|
|||
#!/usr/bin/env python
|
||||
# (RTL8195AM/RTL8711AM/RTL8711AF/RTL8710AF) RtlImages Utility
|
||||
# pvvx
|
||||
|
||||
from __future__ import print_function, division
|
||||
from operator import attrgetter
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
|
||||
__version__ = "17.01.18"
|
||||
|
||||
PYTHON2 = sys.version_info[0] < 3 # True if on pre-Python 3
|
||||
|
||||
HM_IS_HDRR = 1
|
||||
HM_IS_HDRD = 2
|
||||
HM_IS_BOOT = 4
|
||||
HM_IS_OTA = 8
|
||||
HM_IS_SRAM = 16
|
||||
HM_IS_SDRAM = 32
|
||||
|
||||
# Function to return nth byte of a bitstring
|
||||
# Different behaviour on Python 2 vs 3
|
||||
if PYTHON2:
|
||||
def byte(bitstr, index):
|
||||
return ord(bitstr[index])
|
||||
else:
|
||||
def byte(bitstr, index):
|
||||
return bitstr[index]
|
||||
|
||||
|
||||
class FatalError(RuntimeError):
|
||||
"""
|
||||
Wrapper class for runtime errors that aren't caused by internal bugs, but by
|
||||
xchip responses or input content.
|
||||
"""
|
||||
def __init__(self, message):
|
||||
RuntimeError.__init__(self, message)
|
||||
|
||||
@staticmethod
|
||||
def WithResult(message, result):
|
||||
"""
|
||||
Return a fatal error object that appends the hex values of
|
||||
'result' as a string formatted argument.
|
||||
"""
|
||||
message += " (result was %s)" % hexify(result)
|
||||
return FatalError(message)
|
||||
|
||||
class ImageSegment(object):
|
||||
""" Wrapper class for a segment in an RTL image
|
||||
(very similar to a section in an ELFImage also) """
|
||||
def __init__(self, addr, data, file_offs = None):
|
||||
self.addr = addr
|
||||
# pad all ImageSegments to at least 4 bytes length
|
||||
pad_mod = len(data) % 4
|
||||
if pad_mod != 0:
|
||||
data += b"\x00" * (4 - pad_mod)
|
||||
self.data = data
|
||||
self.file_offs = file_offs
|
||||
|
||||
def copy_with_new_addr(self, new_addr):
|
||||
""" Return a new ImageSegment with same data, but mapped at
|
||||
a new address. """
|
||||
return ImageSegment(new_addr, self.data, 0)
|
||||
|
||||
def __repr__(self):
|
||||
r = "len 0x%05x load 0x%08x" % (len(self.data), self.addr)
|
||||
if self.file_offs is not None:
|
||||
r += " file_offs 0x%08x" % (self.file_offs)
|
||||
return r
|
||||
|
||||
class ELFSection(ImageSegment):
|
||||
""" Wrapper class for a section in an ELF image, has a section
|
||||
name as well as the common properties of an ImageSegment. """
|
||||
def __init__(self, name, addr, data, size):
|
||||
super(ELFSection, self).__init__(addr, data)
|
||||
self.name = name.decode("utf-8")
|
||||
self.size = size
|
||||
|
||||
def __repr__(self):
|
||||
return "%s %s" % (self.name, super(ELFSection, self).__repr__())
|
||||
|
||||
class ELFFile(object):
|
||||
SEC_TYPE_PROGBITS = 0x01
|
||||
SEC_TYPE_STRTAB = 0x03
|
||||
|
||||
def __init__(self, name):
|
||||
# Load sections from the ELF file
|
||||
self.name = name
|
||||
try:
|
||||
with open(self.name, 'rb') as f:
|
||||
self._read_elf_file(f)
|
||||
except:
|
||||
print('Error: Not open input ELF file <%s>!' % self.name)
|
||||
sys.exit(-1)
|
||||
|
||||
def get_section(self, section_name):
|
||||
for s in self.sections:
|
||||
if s.name == section_name:
|
||||
return s
|
||||
raise ValueError("No section %s in ELF file" % section_name)
|
||||
|
||||
def _read_elf_file(self, f):
|
||||
# read the ELF file header
|
||||
LEN_FILE_HEADER = 0x34
|
||||
try:
|
||||
(ident,_type,machine,_version,
|
||||
self.entrypoint,_phoff,shoff,_flags,
|
||||
_ehsize, _phentsize,_phnum,_shentsize,
|
||||
_shnum,shstrndx) = struct.unpack("<16sHHLLLLLHHHHHH", f.read(LEN_FILE_HEADER))
|
||||
except struct.error as e:
|
||||
raise FatalError("Failed to read a valid ELF header from %s: %s" % (self.name, e))
|
||||
|
||||
if byte(ident, 0) != 0x7f or ident[1:4] != b'ELF':
|
||||
raise FatalError("%s has invalid ELF magic header" % self.name)
|
||||
if machine != 0x28:
|
||||
raise FatalError("%s does not appear to be an RTL ELF file. e_machine=%04x" % (self.name, machine))
|
||||
self._read_sections(f, shoff, shstrndx, _shnum)
|
||||
|
||||
def _read_sections(self, f, section_header_offs, shstrndx, shnum):
|
||||
LEN_SEC_HEADER = 0x28
|
||||
f.seek(section_header_offs)
|
||||
# print("%d sections found in ELF file" % shnum)
|
||||
if shnum == 0 or shnum > 100:
|
||||
raise FatalError("%d sections found in ELF file!" % shnum)
|
||||
section_header = f.read(shnum *LEN_SEC_HEADER)
|
||||
if len(section_header) == 0:
|
||||
raise FatalError("No section header found at offset %04x in ELF file." % section_header_offs)
|
||||
if len(section_header) != shnum *LEN_SEC_HEADER:
|
||||
print('WARNING: Unexpected ELF section header length %04x is not mod-%02x' % (len(section_header), LEN_SEC_HEADER))
|
||||
|
||||
# walk through the section header and extract all sections
|
||||
section_header_offsets = range(0, len(section_header), LEN_SEC_HEADER)
|
||||
|
||||
def read_section_header(offs):
|
||||
name_offs,sec_type,_flags,lma,sec_offs,size = struct.unpack_from("<LLLLLL", section_header[offs:])
|
||||
# print('read_section_header at %08x' % offs)
|
||||
return (name_offs, sec_type, lma, size, sec_offs)
|
||||
all_sections = [read_section_header(offs) for offs in section_header_offsets]
|
||||
prog_sections = [s for s in all_sections if s[1] == ELFFile.SEC_TYPE_PROGBITS]
|
||||
|
||||
# search for the string table section
|
||||
if not shstrndx * LEN_SEC_HEADER in section_header_offsets:
|
||||
raise FatalError("ELF file has no STRTAB section at shstrndx %d" % shstrndx)
|
||||
_,sec_type,_,sec_size,sec_offs = read_section_header(shstrndx * LEN_SEC_HEADER)
|
||||
if sec_type != ELFFile.SEC_TYPE_STRTAB:
|
||||
print('WARNING: ELF file has incorrect STRTAB section type 0x%02x' % sec_type)
|
||||
f.seek(sec_offs)
|
||||
string_table = f.read(sec_size)
|
||||
|
||||
# build the real list of ELFSections by reading the actual section names from the
|
||||
# string table section, and actual data for each section from the ELF file itself
|
||||
def lookup_string(offs):
|
||||
raw = string_table[offs:]
|
||||
return raw[:raw.index(b'\x00')]
|
||||
|
||||
def read_data(offs, size):
|
||||
f.seek(offs)
|
||||
return f.read(size)
|
||||
|
||||
prog_sections = [ELFSection(lookup_string(n_offs), lma, read_data(offs, size), size) for (n_offs, _type, lma, size, offs) in prog_sections if lma != 0]
|
||||
self.sections = prog_sections
|
||||
|
||||
class xFirmwareImage(object):
|
||||
def __init__(self, fname, segnames, hmode, addrl, addrh):
|
||||
self.fname = fname
|
||||
self.segnames = segnames
|
||||
self.hm = hmode
|
||||
self.addrl = addrl
|
||||
self.addrh = addrh
|
||||
self.addr = None
|
||||
self.data = ''
|
||||
self.size = 0 # size code/data only (without header)
|
||||
self.imgsegs = []
|
||||
|
||||
def load(self, sections):
|
||||
imgsegs = [s for s in sections if s.name in self.segnames]
|
||||
if imgsegs:
|
||||
if len(imgsegs) > 1:
|
||||
sorted(imgsegs, key = attrgetter('addr'))
|
||||
elif len(imgsegs[0].data) == 0: # file size == 0
|
||||
self.addr = imgsegs[0].addr
|
||||
# print('Segment at 0x%08x,' % self.addr, 'size 0x00000000 copy to image', self.fname)
|
||||
sections.remove(imgsegs[0])
|
||||
return
|
||||
self.addr = imgsegs[0].addr
|
||||
s = imgsegs[len(imgsegs) - 1]
|
||||
self.size = s.addr + len(s.data) - self.addr
|
||||
# print('Segment at 0x%08x,' % self.addr, 'size 0x%08x' % self.size, 'copy to image', self.fname)
|
||||
if self.addr < self.addrl and self.addr > self.addrh:
|
||||
print('Segment Address Error!')
|
||||
return
|
||||
if self.size:
|
||||
if self.hm & HM_IS_HDRR:
|
||||
self.data = struct.pack(b'<LLLL', self.size, self.addr, 0x35393138, 0x31313738)
|
||||
elif self.hm & HM_IS_HDRD:
|
||||
self.data = struct.pack(b'<LLLL', self.size, self.addr, 0xffffffff, 0xffffffff)
|
||||
elif self.hm & HM_IS_BOOT: # boot
|
||||
self.data = struct.pack(b'<LLLLLLLL', 0x96969999, 0xFC66CC3F, 0x03CC33C0, 0x6231DCE5, self.size, self.addr, 0xffff002c, 0xffffffff)
|
||||
x = self.addr
|
||||
for s in imgsegs:
|
||||
while x < s.addr:
|
||||
self.data += '\0'
|
||||
x += 1
|
||||
self.data += s.data
|
||||
# print('Segment at 0x%08x,' % s.addr, 'size 0x%08x' % len(s.data), 'name', s.name, 'copy to image', self.fname)
|
||||
x += s.size
|
||||
sections.remove(s)
|
||||
|
||||
def save(self, outdir, flg_p):
|
||||
if self.size:
|
||||
# print('Segment at 0x%08x,' % self.addr, 'size 0x%08x' % self.size, 'save to', self.fname)
|
||||
try:
|
||||
if flg_p:
|
||||
with open(outdir + self.fname + '.p.bin', "wb") as f:
|
||||
f.write(self.data)
|
||||
f.close()
|
||||
else:
|
||||
with open(outdir + self.fname + '.bin', "wb") as f:
|
||||
if self.hm & (HM_IS_HDRR | HM_IS_HDRD):
|
||||
f.write(self.data[16:])
|
||||
elif self.hm & HM_IS_BOOT:
|
||||
f.write(self.data[32:])
|
||||
else:
|
||||
f.write(self.data)
|
||||
f.close()
|
||||
except:
|
||||
print('Error: Not write file <%s>!' % self.fname)
|
||||
sys.exit(-1)
|
||||
|
||||
def save_ota(self, f, fn, chks):
|
||||
if self.size:
|
||||
# print('Segment at 0x%08x,' % self.addr, 'size 0x%08x' % self.size, 'save to %s' % fn)
|
||||
try:
|
||||
f.write(self.data)
|
||||
i = 0
|
||||
while i < len(self.data):
|
||||
chks += byte(self.data, i)
|
||||
i += 1
|
||||
except:
|
||||
print('Error: Not write file %s!' % fn)
|
||||
sys.exit(-1)
|
||||
return chks
|
||||
|
||||
def save_sram(self, f, fn):
|
||||
if self.size:
|
||||
# print('Segment at 0x%08x,' % self.addr, 'size 0x%08x' % self.size, 'save to %s' % fn)
|
||||
try:
|
||||
if self.hm & HM_IS_BOOT:
|
||||
gap = 0x0b000
|
||||
i = len(self.data)
|
||||
if i > gap:
|
||||
print('Error: Segment %s is big!' % self.name)
|
||||
f.write(self.data)
|
||||
while i < gap:
|
||||
f.write('\0')
|
||||
i += 1
|
||||
else:
|
||||
f.write(self.data)
|
||||
except:
|
||||
print('Error: Not write file %s!' % fn)
|
||||
sys.exit(-1)
|
||||
|
||||
def elf2image(args):
|
||||
|
||||
e = ELFFile(args.elffile) # ELFSection is a subclass of ImageSegment
|
||||
# print(e.sections)
|
||||
image = [xFirmwareImage('ram_1', ['.ram.start.table', '.ram_image1.text', '.ram_image1.data'], HM_IS_BOOT + HM_IS_SRAM, 0x10000bc8, 0x10070000),
|
||||
xFirmwareImage('ram_2', ['.image2.start.table', '.ram_image2.text', '.ram_image2.rodata', '.ram.data'], HM_IS_OTA + HM_IS_HDRR + HM_IS_SRAM, 0x10006000, 0x10070000),
|
||||
xFirmwareImage('sdram', ['.sdr_text', '.sdr_rodata', '.sdr_data'], HM_IS_OTA + HM_IS_HDRD + HM_IS_SDRAM, 0x30000000, 0x30200000)]
|
||||
|
||||
img_sram_use = 0
|
||||
img_sdram_use = 0
|
||||
|
||||
for s in image:
|
||||
s.load(e.sections)
|
||||
if s.hm & HM_IS_SRAM:
|
||||
img_sram_use += s.size
|
||||
elif s.hm & HM_IS_SDRAM:
|
||||
img_sdram_use += s.size
|
||||
|
||||
for s in image:
|
||||
if s.size:
|
||||
print('Segment at 0x%08x,' % s.addr, 'size 0x%08x' % s.size, '(%s)' % s.fname)
|
||||
s.save(args.outdir, None);
|
||||
s.save(args.outdir, 1);
|
||||
|
||||
if args.ota:
|
||||
fn = args.outdir + 'ota.bin'
|
||||
try:
|
||||
chks = 0
|
||||
with open(fn, "wb") as f:
|
||||
for s in image:
|
||||
if s.hm & HM_IS_OTA:
|
||||
chks = s.save_ota(f, fn, chks)
|
||||
f.write(struct.pack('<L', chks))
|
||||
f.close()
|
||||
|
||||
except:
|
||||
print('Error: Not write file <%s>!' % fn)
|
||||
sys.exit(-1)
|
||||
|
||||
if args.ram_all:
|
||||
if image[0].size == 0 and image[1].size == 0:
|
||||
print('Error: Ram_all = 0!')
|
||||
sys.exit(-1)
|
||||
fn = args.outdir + 'ram_all.bin'
|
||||
try:
|
||||
with open(fn, "wb") as f:
|
||||
for s in image:
|
||||
if s.hm & HM_IS_SRAM:
|
||||
s.save_sram(f, fn)
|
||||
f.close()
|
||||
|
||||
except:
|
||||
print('Error: Not write file <%s>!' % fn)
|
||||
sys.exit(-1)
|
||||
|
||||
print('Images size: SRAM %u bytes, SDRAM %u bytes [%u]' % (img_sram_use, img_sdram_use, img_sram_use + img_sdram_use))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='RtlAImages Utility version %s' % __version__, prog='rtlimage')
|
||||
parser.add_argument('--ram_all', '-r', action='store_true', help='Generate ram_all files')
|
||||
parser.add_argument('--ota', '-a', action='store_true', help='Generate OTA files')
|
||||
parser.add_argument('elffile', type=str, help='Input ELF file',)
|
||||
parser.add_argument('--outdir', '-o', type=str, default='', help='Outpyt directory')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
print('RtlAImages Utility version %s' % __version__)
|
||||
if args.elffile is None:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
elf2image(args)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except FatalError as e:
|
||||
print('\nA fatal error occurred: %s' % e)
|
||||
sys.exit(2)
|
|
@ -6,8 +6,8 @@ SDK_PATH = USDK/
|
|||
#GCC_PATH = d:/MCU/GNU_Tools_ARM_Embedded/6.2017-q1-update/bin/# + or set in PATH
|
||||
#OPENOCD_PATH = D:/MCU/OpenOCD/bin/# + or set in PATH
|
||||
TOOLS_PATH ?= $(SDK_PATH)component/soc/realtek/8195a/misc/iar_utility/common/tools/
|
||||
FLASHER_TYPE = Jlink
|
||||
#FLASHER_TYPE = cmsis-dap
|
||||
#FLASHER_TYPE = Jlink
|
||||
FLASHER_TYPE = cmsis-dap
|
||||
FLASHER_SPEED = 3500
|
||||
FLASHER_PATH = flasher/
|
||||
JLINK_PATH ?= D:/MCU/SEGGER/JLink_V612i/
|
||||
|
|
Loading…
Reference in a new issue