Unverified Commit 0e18f098 authored by Earle F. Philhower, III's avatar Earle F. Philhower, III Committed by GitHub

Enable IPv4 or IPv4/IPv6 stacks, Ethernet class (#695)

IPv4-only mode saves 20KB+ of flash memory.

Add some backwards compatibility with the global Arduino Ethernet
class when running in IPv4 only mode.

Fixes #687

* Speed P.IO build by not cloning 2GB of sources
* Document P.IO new option
parent 40f4fdf2
...@@ -185,7 +185,14 @@ jobs: ...@@ -185,7 +185,14 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
submodules: 'recursive' submodules: 'true'
- name: Initialize needed submodules
run: |
cd pico-sdk
git submodule update --init
cd ../libraries/Adafruit_TinyUSB_Arduino
git submodule update --init
cd ../..
- name: Cache pip - name: Cache pip
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
......
This diff is collapsed.
...@@ -179,8 +179,10 @@ bool IPAddress::isValid(const char* arg) { ...@@ -179,8 +179,10 @@ bool IPAddress::isValid(const char* arg) {
return IPAddress().fromString(arg); return IPAddress().fromString(arg);
} }
namespace arduino {
const IPAddress INADDR_ANY; // generic "0.0.0.0" for IPv4 & IPv6 const IPAddress INADDR_ANY; // generic "0.0.0.0" for IPv4 & IPv6
const IPAddress INADDR_NONE(255,255,255,255); const IPAddress INADDR_NONE(255,255,255,255);
};
void IPAddress::clear() { void IPAddress::clear() {
(*this) = INADDR_ANY; (*this) = INADDR_ANY;
......
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
#include <lwip/ip_addr.h> #include <lwip/ip_addr.h>
#include <lwip/ip4_addr.h> #include <lwip/ip4_addr.h>
namespace arduino {
#if !LWIP_IPV6 // forward declarations of global name space friend classes
struct ip_addr: ipv4_addr { }; class EthernetClass;
#endif // !LWIP_IPV6 class DhcpClass;
class DNSClient;
namespace arduino {
// to display a netif id with printf: // to display a netif id with printf:
#define NETIFID_STR "%c%c%u" #define NETIFID_STR "%c%c%u"
...@@ -48,8 +51,19 @@ struct ip_addr: ipv4_addr { }; ...@@ -48,8 +51,19 @@ struct ip_addr: ipv4_addr { };
class IPAddress: public Printable { class IPAddress: public Printable {
private: private:
#if !LWIP_IPV6
// Ugly hack to allow Arduino Ethernet library to twiddle internal bits.
// This can only work in IPv4-only mode, of course.
union {
ip_addr_t _ip; ip_addr_t _ip;
struct {
uint8_t bytes[4];
} _address;
};
static_assert(sizeof(_ip) == sizeof(_address), "IP_ADDR_T size != _ADDRESS size");
#else
ip_addr_t _ip;
#endif
// Access the raw byte array containing the address. Because this returns a pointer // Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only // to the internal structure rather than a copy of the address this function should only
...@@ -149,6 +163,10 @@ class IPAddress: public Printable { ...@@ -149,6 +163,10 @@ class IPAddress: public Printable {
friend class DhcpClass; friend class DhcpClass;
friend class DNSClient; friend class DNSClient;
friend ::EthernetClass;
friend ::DhcpClass;
friend ::DNSClient;
/* /*
lwIP address compatibility lwIP address compatibility
*/ */
...@@ -167,7 +185,6 @@ class IPAddress: public Printable { ...@@ -167,7 +185,6 @@ class IPAddress: public Printable {
bool isLocal () const { return ip_addr_islinklocal(&_ip); } bool isLocal () const { return ip_addr_islinklocal(&_ip); }
#if LWIP_IPV6
IPAddress(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); } IPAddress(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); }
IPAddress(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); } IPAddress(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); }
...@@ -175,6 +192,7 @@ class IPAddress: public Printable { ...@@ -175,6 +192,7 @@ class IPAddress: public Printable {
IPAddress& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; } IPAddress& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; }
IPAddress& operator=(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); return *this; } IPAddress& operator=(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); return *this; }
#if LWIP_IPV6
uint16_t* raw6() uint16_t* raw6()
{ {
setV6(); setV6();
......
...@@ -222,6 +222,18 @@ default Pico SDK USB stack. To change it, add ...@@ -222,6 +222,18 @@ default Pico SDK USB stack. To change it, add
Note that the special "No USB" setting is also supported, through the Note that the special "No USB" setting is also supported, through the
shortcut-define ``PIO_FRAMEWORK_ARDUINO_NO_USB``. shortcut-define ``PIO_FRAMEWORK_ARDUINO_NO_USB``.
IP Stack
---------
The lwIP stack can be configured to support only IPv4 (default) or additionally IPv6. To activate IPv6 support, add
.. code:: ini
; IPv6
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6
to the ``platformio.ini``.
Selecting a different core version Selecting a different core version
---------------------------------- ----------------------------------
......
No preview for this file type
...@@ -179,7 +179,7 @@ int LwipIntfDev<RawDev>::hostByName(const char* aHostname, IPAddress& aResult, i ...@@ -179,7 +179,7 @@ int LwipIntfDev<RawDev>::hostByName(const char* aHostname, IPAddress& aResult, i
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &_dns_found_callback, &cb, LWIP_DNS_ADDRTYPE_DEFAULT); err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &_dns_found_callback, &cb, LWIP_DNS_ADDRTYPE_DEFAULT);
#else #else
err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &cb); err_t err = dns_gethostbyname(aHostname, &addr, &_dns_found_callback, &cb);
#endif #endif
if (err == ERR_OK) { if (err == ERR_OK) {
aResult = IPAddress(&addr); aResult = IPAddress(&addr);
......
...@@ -41,12 +41,11 @@ compiler.warning_flags.default=-Werror=return-type ...@@ -41,12 +41,11 @@ compiler.warning_flags.default=-Werror=return-type
compiler.warning_flags.more=-Wall -Werror=return-type -Wno-ignored-qualifiers compiler.warning_flags.more=-Wall -Werror=return-type -Wno-ignored-qualifiers
compiler.warning_flags.all=-Wall -Wextra -Werror=return-type -Wno-ignored-qualifiers compiler.warning_flags.all=-Wall -Wextra -Werror=return-type -Wno-ignored-qualifiers
compiler.netdefines=-DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_LWIP=0 -DLWIP_IPV6=1 -DLWIP_IPV4=1 -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1 compiler.netdefines=-DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_LWIP=0 {build.lwipdefs} -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1
compiler.defines={build.led} {build.usbstack_flags} -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' {compiler.netdefines} compiler.defines={build.led} {build.usbstack_flags} -DCFG_TUSB_MCU=OPT_MCU_RP2040 -DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' {compiler.netdefines}
compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt" "-I{runtime.platform.path}/include" compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt" "-I{runtime.platform.path}/include"
compiler.flags=-march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections {build.flags.exceptions} {build.flags.stackprotect} compiler.flags=-march=armv6-m -mcpu=cortex-m0plus -mthumb -ffunction-sections -fdata-sections {build.flags.exceptions} {build.flags.stackprotect}
compiler.wrap="@{runtime.platform.path}/lib/platform_wrap.txt" compiler.wrap="@{runtime.platform.path}/lib/platform_wrap.txt"
compiler.libpico="{runtime.platform.path}/lib/libpico.a"
compiler.libbearssl="{runtime.platform.path}/lib/libbearssl.a" compiler.libbearssl="{runtime.platform.path}/lib/libbearssl.a"
compiler.c.cmd=arm-none-eabi-gcc compiler.c.cmd=arm-none-eabi-gcc
...@@ -92,8 +91,9 @@ build.usbstack_flags= ...@@ -92,8 +91,9 @@ build.usbstack_flags=
build.flags.libstdcpp=-lstdc++ build.flags.libstdcpp=-lstdc++
build.flags.exceptions=-fno-exceptions build.flags.exceptions=-fno-exceptions
build.flags.stackprotect= build.flags.stackprotect=
build.libpico=libpico.a
build.boot2=boot2_generic_03h_4_padded_checksum build.boot2=boot2_generic_03h_4_padded_checksum
build.lwipdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1
# Allow Pico boards do be auto-discovered by the IDE # Allow Pico boards do be auto-discovered by the IDE
discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" -I "{runtime.platform.path}/tools/discovery.py" discovery.rp2040.pattern="{runtime.tools.pqt-python3.path}/python3" -I "{runtime.platform.path}/tools/discovery.py"
...@@ -123,7 +123,7 @@ recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3 ...@@ -123,7 +123,7 @@ recipe.hooks.linking.prelink.1.pattern="{runtime.tools.pqt-python3.path}/python3
recipe.hooks.linking.prelink.2.pattern="{compiler.path}{compiler.S.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -c "{runtime.platform.path}/boot2/{build.boot2}.S" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" -o "{build.path}/boot2.o" recipe.hooks.linking.prelink.2.pattern="{compiler.path}{compiler.S.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -c "{runtime.platform.path}/boot2/{build.boot2}.S" "-I{runtime.platform.path}/pico-sdk/src/rp2040/hardware_regs/include/" "-I{runtime.platform.path}/pico-sdk/src/common/pico_binary_info/include" -o "{build.path}/boot2.o"
## Combine gc-sections, archives, and objects ## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {compiler.ldflags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/{archive_file}" "{build.path}/boot2.o" {compiler.libraries.ldflags} {compiler.libpico} {compiler.libbearssl} -lm -lc {build.flags.libstdcpp} -lc -Wl,--end-group recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} {compiler.ldflags} "-Wl,--script={build.path}/memmap_default.ld" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/{archive_file}" "{build.path}/boot2.o" {compiler.libraries.ldflags} "{runtime.platform.path}/lib/{build.libpico}" {compiler.libbearssl} -lm -lc {build.flags.libstdcpp} -lc -Wl,--end-group
## Create output (UF2 file) ## Create output (UF2 file)
recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2" recipe.objcopy.uf2.pattern="{runtime.tools.pqt-elf2uf2.path}/elf2uf2" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.uf2"
......
...@@ -21,7 +21,7 @@ target_compile_definitions(pico PUBLIC ...@@ -21,7 +21,7 @@ target_compile_definitions(pico PUBLIC
PICO_FLASH_SIZE_BYTES=16777216 PICO_FLASH_SIZE_BYTES=16777216
PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64 PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64
LWIP_IPV4=1 LWIP_IPV4=1
LWIP_IPV6=1 LWIP_IPV6=${IPV6}
LWIP_UDP=1 LWIP_UDP=1
LWIP_IGMP=1 LWIP_IGMP=1
LWIP_CHECKSUM_CTRL_PER_NETIF=1 LWIP_CHECKSUM_CTRL_PER_NETIF=1
......
...@@ -8,7 +8,7 @@ export PATH="$(cd ../../system/arm-none-eabi/bin; pwd):$PATH" ...@@ -8,7 +8,7 @@ export PATH="$(cd ../../system/arm-none-eabi/bin; pwd):$PATH"
rm -rf build rm -rf build
mkdir build mkdir build
cd build cd build
cmake .. cmake .. -DIPV6=0
make -j make -j
# Put everything in its place # Put everything in its place
...@@ -17,6 +17,14 @@ mv generated/pico_base/pico/version.h ../../../include/pico_base/pico/. ...@@ -17,6 +17,14 @@ mv generated/pico_base/pico/version.h ../../../include/pico_base/pico/.
cp ../lwipopts.h ../../../include/. cp ../lwipopts.h ../../../include/.
cp ../tusb_config.h ../../../include/. cp ../tusb_config.h ../../../include/.
cd ..
rm -rf build
mkdir build
cd build
cmake .. -DIPV6=1
make -j
mv libpico.a ../../../lib/libpico-ipv6.a
rm -rf boot rm -rf boot
mkdir boot mkdir boot
cd boot cd boot
......
...@@ -83,6 +83,14 @@ def BuildWithoutUSBStack(name): ...@@ -83,6 +83,14 @@ def BuildWithoutUSBStack(name):
print("%s.menu.usbstack.nousb=No USB" % (name)) print("%s.menu.usbstack.nousb=No USB" % (name))
print('%s.menu.usbstack.nousb.build.usbstack_flags="-DNO_USB -DDISABLE_USB_SERIAL -I{runtime.platform.path}/tools/libpico"' % (name)) print('%s.menu.usbstack.nousb.build.usbstack_flags="-DNO_USB -DDISABLE_USB_SERIAL -I{runtime.platform.path}/tools/libpico"' % (name))
def BuildIPStack(name):
print("%s.menu.ipstack.ipv4only=IPv4 Only" % (name))
print('%s.menu.ipstack.ipv4only.build.libpico=libpico.a' % (name))
print('%s.menu.ipstack.ipv4only.build.lwipdefs=-DLWIP_IPV6=0 -DLWIP_IPV4=1' % (name))
print("%s.menu.ipstack.ipv4ipv6=IPv4 and IPv6" % (name))
print('%s.menu.ipstack.ipv4ipv6.build.libpico=libpico-ipv6.a' % (name))
print('%s.menu.ipstack.ipv4ipv6.build.lwipdefs=-DLWIP_IPV6=1 -DLWIP_IPV4=1' % (name))
def BuildHeader(name, vendor_name, product_name, vidtouse, pidtouse, vid, pid, pwr, boarddefine, variant, uploadtool, flashsize, ramsize, boot2): def BuildHeader(name, vendor_name, product_name, vidtouse, pidtouse, vid, pid, pwr, boarddefine, variant, uploadtool, flashsize, ramsize, boot2):
prettyname = vendor_name + " " + product_name prettyname = vendor_name + " " + product_name
print() print()
...@@ -133,7 +141,7 @@ def BuildGlobalMenuList(): ...@@ -133,7 +141,7 @@ def BuildGlobalMenuList():
print("menu.dbglvl=Debug Level") print("menu.dbglvl=Debug Level")
print("menu.boot2=Boot Stage 2") print("menu.boot2=Boot Stage 2")
print("menu.usbstack=USB Stack") print("menu.usbstack=USB Stack")
print("menu.ipstack=IP Stack")
def MakeBoard(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flashsizemb, boot2): def MakeBoard(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flashsizemb, boot2):
for a, b, c in [ ["", "", "uf2conv"], ["picoprobe", " (Picoprobe)", "picoprobe"], ["picodebug", " (pico-debug)", "picodebug"]]: for a, b, c in [ ["", "", "uf2conv"], ["picoprobe", " (Picoprobe)", "picoprobe"], ["picodebug", " (pico-debug)", "picodebug"]]:
...@@ -171,6 +179,7 @@ def MakeBoard(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flash ...@@ -171,6 +179,7 @@ def MakeBoard(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flash
BuildWithoutUSBStack(n) BuildWithoutUSBStack(n)
else: else:
BuildUSBStack(n) BuildUSBStack(n)
BuildIPStack(n)
if name == "generic": if name == "generic":
BuildBoot(n) BuildBoot(n)
MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flashsizemb, boot2) MakeBoardJSON(name, vendor_name, product_name, vid, pid, pwr, boarddefine, flashsizemb, boot2)
......
...@@ -79,6 +79,12 @@ env.Replace( ...@@ -79,6 +79,12 @@ env.Replace(
SIZEPROGREGEXP=r"^(?:\.boot2|\.text|\.data|\.rodata|\.text.align|\.ARM.exidx)\s+(\d+).*" SIZEPROGREGEXP=r"^(?:\.boot2|\.text|\.data|\.rodata|\.text.align|\.ARM.exidx)\s+(\d+).*"
) )
# pico support library depends on ipv6 enable/disable
if "PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6" in flatten_cppdefines:
libpico = File(os.path.join(FRAMEWORK_DIR, "lib", "libpico-ipv6.a"))
else:
libpico = File(os.path.join(FRAMEWORK_DIR, "lib", "libpico.a"))
env.Append( env.Append(
ASFLAGS=env.get("CCFLAGS", [])[:], ASFLAGS=env.get("CCFLAGS", [])[:],
...@@ -106,13 +112,6 @@ env.Append( ...@@ -106,13 +112,6 @@ env.Append(
"ARDUINO_ARCH_RP2040", "ARDUINO_ARCH_RP2040",
("F_CPU", "$BOARD_F_CPU"), ("F_CPU", "$BOARD_F_CPU"),
("BOARD_NAME", '\\"%s\\"' % env.subst("$BOARD")), ("BOARD_NAME", '\\"%s\\"' % env.subst("$BOARD")),
# LWIP-related
("PICO_CYW43_ARCH_THREADSAFE_BACKGROUND", 1),
("CYW43_LWIP", 0),
("LWIP_IPV6", 1),
("LWIP_IPV4", 1),
("LWIP_IGMP", 1),
("LWIP_LWIP_CHECKSUM_CTRL_PER_NETIF", 1),
], ],
CPPPATH=[ CPPPATH=[
...@@ -147,7 +146,7 @@ env.Append( ...@@ -147,7 +146,7 @@ env.Append(
# link lib/libpico.a by full path, ignore libstdc++ # link lib/libpico.a by full path, ignore libstdc++
LIBS=[ LIBS=[
File(os.path.join(FRAMEWORK_DIR, "lib", "libpico.a")), libpico,
File(os.path.join(FRAMEWORK_DIR, "lib", "libbearssl.a")), File(os.path.join(FRAMEWORK_DIR, "lib", "libbearssl.a")),
"m", "c", stdcpp_lib, "c"] "m", "c", stdcpp_lib, "c"]
) )
...@@ -228,15 +227,19 @@ def configure_usb_flags(cpp_defines): ...@@ -228,15 +227,19 @@ def configure_usb_flags(cpp_defines):
board.update("build.hwids", hw_ids) board.update("build.hwids", hw_ids)
board.update("upload.maximum_ram_size", ram_size) board.update("upload.maximum_ram_size", ram_size)
def configure_network_flags(): def configure_network_flags(cpp_defines):
env.Append(CPPDEFINES=[ env.Append(CPPDEFINES=[
("PICO_CYW43_ARCH_THREADSAFE_BACKGROUND", 1), ("PICO_CYW43_ARCH_THREADSAFE_BACKGROUND", 1),
("CYW43_LWIP", 0), ("CYW43_LWIP", 0),
("LWIP_IPV6", 1),
("LWIP_IPV4", 1), ("LWIP_IPV4", 1),
("LWIP_IGMP", 1), ("LWIP_IGMP", 1),
("LWIP_CHECKSUM_CTRL_PER_NETIF", 1) ("LWIP_CHECKSUM_CTRL_PER_NETIF", 1)
]) ])
if "PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6" in cpp_defines:
env.Append(CPPDEFINES=[("LWIP_IPV6", 1)])
else:
env.Append(CPPDEFINES=[("LWIP_IPV6", 0)])
# #
# Process configuration flags # Process configuration flags
# #
...@@ -255,7 +258,7 @@ if not "USE_TINYUSB" in cpp_defines: ...@@ -255,7 +258,7 @@ if not "USE_TINYUSB" in cpp_defines:
) )
# configure USB stuff # configure USB stuff
configure_usb_flags(cpp_defines) configure_usb_flags(cpp_defines)
configure_network_flags() configure_network_flags(cpp_defines)
# ensure LWIP headers are in path after any TINYUSB distributed versions, also PicoSDK USB path headers # ensure LWIP headers are in path after any TINYUSB distributed versions, also PicoSDK USB path headers
env.Append(CPPPATH=[os.path.join(FRAMEWORK_DIR, "include")]) env.Append(CPPPATH=[os.path.join(FRAMEWORK_DIR, "include")])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment