Add Pico W WiFi support (#670)
* Add support for the WiFi chip on the Pico W board. * USB interrupt now no longer hard coded (conflicted with the WiFi IRQ). * Add in Pico W board to makeboards.py * Add in GPIO and variant support * Initialize WiFi in the Variant * Use manual LWIP, fix size accounting * Remove the SDK WiFi overrides * Pulling in work done in the ESP8266 core. * Make IPAddress support IPv6 * Build LWIP with IPv4 and IPv6 support * Use proper MAC * Avoid cyw_warn crash. Make macro to a comment while building * Add WiFiServer * Add WiFiUdp * Move LWIP-specific support files to LWIP_Ethernet * Add WiFi::ping (ICMP ping) * Move ICMP echo (ping) to LWIPIntfDev * Move hostByName to LwipIntfDev * Add AP mode with simple DHCP server * Add some examples and basic ESP8266 compat hacks * Update Adafruit TinyUSB to fix crash * Set DHCP hostname * Make Wifi.begin() return CONNECTED with link + IP * Return connected() on WiFi::begin * Fix spurious TCP retransmission * Protect LWIP from reentrancy The Pico SDK calls "sys_check_timeouts() from inside a periodic interrupt. This appears unsafe, as the interrupt could happen while already in the (non-reentrant) LWIP code. Block the interrupt from calling sys_check_timeouts by using a global flag manually set via an RAII recursive lock. Add interrupt protection macros around critical sections inside LWIP via the standard defines. These two changes should make LWIP significantly more stable and long running. * Support disconnecting and reconnecting WiFi * Add WiFiServer simple example * Update documentation Fixes #666 Fixed #665
This commit is contained in:
parent
c025c4a1f8
commit
abf2c586c7
72 changed files with 7504 additions and 234 deletions
|
|
@ -11,6 +11,7 @@ See https://arduino-pico.readthedocs.io/en/latest/ along with the examples for m
|
|||
|
||||
# Supported Boards
|
||||
* Raspberry Pi Pico
|
||||
* Raspberry Pi Pico W
|
||||
* Adafruit Feather RP2040
|
||||
* Adafruit ItsyBitsy RP2040
|
||||
* Adafruit KB2040
|
||||
|
|
@ -177,8 +178,10 @@ If you want to contribute or have bugfixes, drop me a note at <earlephilhower@ya
|
|||
* [Arduino-Pico](https://github.com/earlephilhower/arduino-pico) core files are licensed under the LGPL.
|
||||
* [LittleFS](https://github.com/ARMmbed/littlefs) library written by ARM Limited and released under the [BSD 3-clause license](https://github.com/ARMmbed/littlefs/blob/master/LICENSE.md).
|
||||
* [UF2CONV.PY](https://github.com/microsoft/uf2) is by Microsoft Corporation and licensed under the MIT license.
|
||||
* Some filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
|
||||
* Networking and filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
|
||||
* DHCP server for AP host mode from the [Micropython Project](https://micropython.org), distributed under the MIT License.
|
||||
* [FreeRTOS](https://freertos.org) is Copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
|
||||
* [lwIP](https://savannah.nongnu.org/projects/lwip/) is (c) the Swedish Institute of Computer Science and licenced under the BSD license.
|
||||
|
||||
-Earle F. Philhower, III
|
||||
earlephilhower@yahoo.com
|
||||
|
|
|
|||
545
boards.txt
545
boards.txt
|
|
@ -151,7 +151,7 @@ rpipico.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI
|
|||
rpipico.menu.dbglvl.NDEBUG=NDEBUG
|
||||
rpipico.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
rpipico.menu.usbstack.picosdk=Pico SDK
|
||||
rpipico.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
rpipico.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
rpipico.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
rpipico.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ rpipicopicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_R
|
|||
rpipicopicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
rpipicopicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
rpipicopicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
rpipicopicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
rpipicopicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
rpipicopicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
rpipicopicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -435,6 +435,427 @@ rpipicopicodebug.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
|||
rpipicopicodebug.menu.usbstack.nousb=No USB
|
||||
rpipicopicodebug.menu.usbstack.nousb.build.usbstack_flags="-DNO_USB -DDISABLE_USB_SERIAL -I{runtime.platform.path}/tools/libpico"
|
||||
|
||||
# -----------------------------------
|
||||
# Raspberry Pi Pico W
|
||||
# -----------------------------------
|
||||
rpipicow.name=Raspberry Pi Pico W
|
||||
rpipicow.vid.0=0x2e8a
|
||||
rpipicow.pid.0=0xf00a
|
||||
rpipicow.build.usbpid=-DSERIALUSB_PID=0xf00a
|
||||
rpipicow.build.usbpwr=-DUSBD_MAX_POWER_MA=250
|
||||
rpipicow.build.board=RASPBERRY_PI_PICO_W
|
||||
rpipicow.build.mcu=cortex-m0plus
|
||||
rpipicow.build.variant=rpipicow
|
||||
rpipicow.upload.tool=uf2conv
|
||||
rpipicow.upload.maximum_size=2097152
|
||||
rpipicow.upload.maximum_data_size=262144
|
||||
rpipicow.upload.wait_for_upload_port=true
|
||||
rpipicow.upload.erase_cmd=
|
||||
rpipicow.serial.disableDTR=false
|
||||
rpipicow.serial.disableRTS=false
|
||||
rpipicow.build.f_cpu=125000000
|
||||
rpipicow.build.led=
|
||||
rpipicow.build.core=rp2040
|
||||
rpipicow.build.ldscript=memmap_default.ld
|
||||
rpipicow.build.ram_length=256k
|
||||
rpipicow.build.boot2=boot2_w25q080_2_padded_checksum
|
||||
rpipicow.build.vid=0x2e8a
|
||||
rpipicow.build.pid=0xf00a
|
||||
rpipicow.build.usb_manufacturer="Raspberry Pi"
|
||||
rpipicow.build.usb_product="Pico W"
|
||||
rpipicow.menu.flash.2097152_0=2MB (no FS)
|
||||
rpipicow.menu.flash.2097152_0.upload.maximum_size=2093056
|
||||
rpipicow.menu.flash.2097152_0.build.flash_length=2093056
|
||||
rpipicow.menu.flash.2097152_0.build.eeprom_start=270528512
|
||||
rpipicow.menu.flash.2097152_0.build.fs_start=270528512
|
||||
rpipicow.menu.flash.2097152_0.build.fs_end=270528512
|
||||
rpipicow.menu.flash.2097152_65536=2MB (Sketch: 1984KB, FS: 64KB)
|
||||
rpipicow.menu.flash.2097152_65536.upload.maximum_size=2027520
|
||||
rpipicow.menu.flash.2097152_65536.build.flash_length=2027520
|
||||
rpipicow.menu.flash.2097152_65536.build.eeprom_start=270528512
|
||||
rpipicow.menu.flash.2097152_65536.build.fs_start=270462976
|
||||
rpipicow.menu.flash.2097152_65536.build.fs_end=270528512
|
||||
rpipicow.menu.flash.2097152_131072=2MB (Sketch: 1920KB, FS: 128KB)
|
||||
rpipicow.menu.flash.2097152_131072.upload.maximum_size=1961984
|
||||
rpipicow.menu.flash.2097152_131072.build.flash_length=1961984
|
||||
rpipicow.menu.flash.2097152_131072.build.eeprom_start=270528512
|
||||
rpipicow.menu.flash.2097152_131072.build.fs_start=270397440
|
||||
rpipicow.menu.flash.2097152_131072.build.fs_end=270528512
|
||||
rpipicow.menu.flash.2097152_262144=2MB (Sketch: 1792KB, FS: 256KB)
|
||||
rpipicow.menu.flash.2097152_262144.upload.maximum_size=1830912
|
||||
rpipicow.menu.flash.2097152_262144.build.flash_length=1830912
|
||||
rpipicow.menu.flash.2097152_262144.build.eeprom_start=270528512
|
||||
rpipicow.menu.flash.2097152_262144.build.fs_start=270266368
|
||||
rpipicow.menu.flash.2097152_262144.build.fs_end=270528512
|
||||
rpipicow.menu.flash.2097152_524288=2MB (Sketch: 1536KB, FS: 512KB)
|
||||
rpipicow.menu.flash.2097152_524288.upload.maximum_size=1568768
|
||||
rpipicow.menu.flash.2097152_524288.build.flash_length=1568768
|
||||
rpipicow.menu.flash.2097152_524288.build.eeprom_start=270528512
|
||||
rpipicow.menu.flash.2097152_524288.build.fs_start=270004224
|
||||
rpipicow.menu.flash.2097152_524288.build.fs_end=270528512
|
||||
rpipicow.menu.flash.2097152_1048576=2MB (Sketch: 1MB, FS: 1MB)
|
||||
rpipicow.menu.flash.2097152_1048576.upload.maximum_size=1044480
|
||||
rpipicow.menu.flash.2097152_1048576.build.flash_length=1044480
|
||||
rpipicow.menu.flash.2097152_1048576.build.eeprom_start=270528512
|
||||
rpipicow.menu.flash.2097152_1048576.build.fs_start=269479936
|
||||
rpipicow.menu.flash.2097152_1048576.build.fs_end=270528512
|
||||
rpipicow.menu.freq.133=133 MHz
|
||||
rpipicow.menu.freq.133.build.f_cpu=133000000L
|
||||
rpipicow.menu.freq.50=50 MHz
|
||||
rpipicow.menu.freq.50.build.f_cpu=50000000L
|
||||
rpipicow.menu.freq.100=100 MHz
|
||||
rpipicow.menu.freq.100.build.f_cpu=100000000L
|
||||
rpipicow.menu.freq.120=120 MHz
|
||||
rpipicow.menu.freq.120.build.f_cpu=120000000L
|
||||
rpipicow.menu.freq.125=125 MHz
|
||||
rpipicow.menu.freq.125.build.f_cpu=125000000L
|
||||
rpipicow.menu.freq.150=150 MHz (Overclock)
|
||||
rpipicow.menu.freq.150.build.f_cpu=150000000L
|
||||
rpipicow.menu.freq.175=175 MHz (Overclock)
|
||||
rpipicow.menu.freq.175.build.f_cpu=175000000L
|
||||
rpipicow.menu.freq.200=200 MHz (Overclock)
|
||||
rpipicow.menu.freq.200.build.f_cpu=200000000L
|
||||
rpipicow.menu.freq.225=225 MHz (Overclock)
|
||||
rpipicow.menu.freq.225.build.f_cpu=225000000L
|
||||
rpipicow.menu.freq.240=240 MHz (Overclock)
|
||||
rpipicow.menu.freq.240.build.f_cpu=240000000L
|
||||
rpipicow.menu.freq.250=250 MHz (Overclock)
|
||||
rpipicow.menu.freq.250.build.f_cpu=250000000L
|
||||
rpipicow.menu.freq.275=275 MHz (Overclock)
|
||||
rpipicow.menu.freq.275.build.f_cpu=275000000L
|
||||
rpipicow.menu.freq.300=300 MHz (Overclock)
|
||||
rpipicow.menu.freq.300.build.f_cpu=300000000L
|
||||
rpipicow.menu.opt.Small=Small (-Os) (standard)
|
||||
rpipicow.menu.opt.Small.build.flags.optimize=-Os
|
||||
rpipicow.menu.opt.Optimize=Optimize (-O)
|
||||
rpipicow.menu.opt.Optimize.build.flags.optimize=-O
|
||||
rpipicow.menu.opt.Optimize2=Optimize More (-O2)
|
||||
rpipicow.menu.opt.Optimize2.build.flags.optimize=-O2
|
||||
rpipicow.menu.opt.Optimize3=Optimize Even More (-O3)
|
||||
rpipicow.menu.opt.Optimize3.build.flags.optimize=-O3
|
||||
rpipicow.menu.opt.Fast=Fast (-Ofast) (maybe slower)
|
||||
rpipicow.menu.opt.Fast.build.flags.optimize=-Ofast
|
||||
rpipicow.menu.opt.Debug=Debug (-Og)
|
||||
rpipicow.menu.opt.Debug.build.flags.optimize=-Og
|
||||
rpipicow.menu.rtti.Disabled=Disabled
|
||||
rpipicow.menu.rtti.Disabled.build.flags.rtti=-fno-rtti
|
||||
rpipicow.menu.rtti.Enabled=Enabled
|
||||
rpipicow.menu.rtti.Enabled.build.flags.rtti=
|
||||
rpipicow.menu.stackprotect.Disabled=Disabled
|
||||
rpipicow.menu.stackprotect.Disabled.build.flags.stackprotect=
|
||||
rpipicow.menu.stackprotect.Enabled=Enabled
|
||||
rpipicow.menu.stackprotect.Enabled.build.flags.stackprotect=-fstack-protector
|
||||
rpipicow.menu.exceptions.Disabled=Disabled
|
||||
rpipicow.menu.exceptions.Disabled.build.flags.exceptions=-fno-exceptions
|
||||
rpipicow.menu.exceptions.Disabled.build.flags.libstdcpp=-lstdc++
|
||||
rpipicow.menu.exceptions.Enabled=Enabled
|
||||
rpipicow.menu.exceptions.Enabled.build.flags.exceptions=-fexceptions
|
||||
rpipicow.menu.exceptions.Enabled.build.flags.libstdcpp=-lstdc++-exc
|
||||
rpipicow.menu.dbgport.Disabled=Disabled
|
||||
rpipicow.menu.dbgport.Disabled.build.debug_port=
|
||||
rpipicow.menu.dbgport.Serial=Serial
|
||||
rpipicow.menu.dbgport.Serial.build.debug_port=-DDEBUG_RP2040_PORT=Serial
|
||||
rpipicow.menu.dbgport.Serial1=Serial1
|
||||
rpipicow.menu.dbgport.Serial1.build.debug_port=-DDEBUG_RP2040_PORT=Serial1
|
||||
rpipicow.menu.dbgport.Serial2=Serial2
|
||||
rpipicow.menu.dbgport.Serial2.build.debug_port=-DDEBUG_RP2040_PORT=Serial2
|
||||
rpipicow.menu.dbglvl.None=None
|
||||
rpipicow.menu.dbglvl.None.build.debug_level=
|
||||
rpipicow.menu.dbglvl.Core=Core
|
||||
rpipicow.menu.dbglvl.Core.build.debug_level=-DDEBUG_RP2040_CORE
|
||||
rpipicow.menu.dbglvl.SPI=SPI
|
||||
rpipicow.menu.dbglvl.SPI.build.debug_level=-DDEBUG_RP2040_SPI
|
||||
rpipicow.menu.dbglvl.Wire=Wire
|
||||
rpipicow.menu.dbglvl.Wire.build.debug_level=-DDEBUG_RP2040_WIRE
|
||||
rpipicow.menu.dbglvl.All=All
|
||||
rpipicow.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE
|
||||
rpipicow.menu.dbglvl.NDEBUG=NDEBUG
|
||||
rpipicow.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
rpipicow.menu.usbstack.picosdk=Pico SDK
|
||||
rpipicow.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
rpipicow.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
rpipicow.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
# -----------------------------------
|
||||
# Raspberry Pi Pico W (Picoprobe)
|
||||
# -----------------------------------
|
||||
rpipicowpicoprobe.name=Raspberry Pi Pico W (Picoprobe)
|
||||
rpipicowpicoprobe.vid.0=0x2e8a
|
||||
rpipicowpicoprobe.pid.0=0x0004
|
||||
rpipicowpicoprobe.build.usbpid=-DSERIALUSB_PID=0xf00a
|
||||
rpipicowpicoprobe.build.usbpwr=-DUSBD_MAX_POWER_MA=250
|
||||
rpipicowpicoprobe.build.board=RASPBERRY_PI_PICO_W
|
||||
rpipicowpicoprobe.build.mcu=cortex-m0plus
|
||||
rpipicowpicoprobe.build.variant=rpipicow
|
||||
rpipicowpicoprobe.upload.tool=picoprobe
|
||||
rpipicowpicoprobe.upload.maximum_size=2097152
|
||||
rpipicowpicoprobe.upload.maximum_data_size=262144
|
||||
rpipicowpicoprobe.upload.wait_for_upload_port=true
|
||||
rpipicowpicoprobe.upload.erase_cmd=
|
||||
rpipicowpicoprobe.serial.disableDTR=false
|
||||
rpipicowpicoprobe.serial.disableRTS=false
|
||||
rpipicowpicoprobe.build.f_cpu=125000000
|
||||
rpipicowpicoprobe.build.led=
|
||||
rpipicowpicoprobe.build.core=rp2040
|
||||
rpipicowpicoprobe.build.ldscript=memmap_default.ld
|
||||
rpipicowpicoprobe.build.ram_length=256k
|
||||
rpipicowpicoprobe.build.boot2=boot2_w25q080_2_padded_checksum
|
||||
rpipicowpicoprobe.build.vid=0x2e8a
|
||||
rpipicowpicoprobe.build.pid=0xf00a
|
||||
rpipicowpicoprobe.build.usb_manufacturer="Raspberry Pi"
|
||||
rpipicowpicoprobe.build.usb_product="Pico W (Picoprobe)"
|
||||
rpipicowpicoprobe.menu.flash.2097152_0=2MB (no FS)
|
||||
rpipicowpicoprobe.menu.flash.2097152_0.upload.maximum_size=2093056
|
||||
rpipicowpicoprobe.menu.flash.2097152_0.build.flash_length=2093056
|
||||
rpipicowpicoprobe.menu.flash.2097152_0.build.eeprom_start=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_0.build.fs_start=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_0.build.fs_end=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_65536=2MB (Sketch: 1984KB, FS: 64KB)
|
||||
rpipicowpicoprobe.menu.flash.2097152_65536.upload.maximum_size=2027520
|
||||
rpipicowpicoprobe.menu.flash.2097152_65536.build.flash_length=2027520
|
||||
rpipicowpicoprobe.menu.flash.2097152_65536.build.eeprom_start=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_65536.build.fs_start=270462976
|
||||
rpipicowpicoprobe.menu.flash.2097152_65536.build.fs_end=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_131072=2MB (Sketch: 1920KB, FS: 128KB)
|
||||
rpipicowpicoprobe.menu.flash.2097152_131072.upload.maximum_size=1961984
|
||||
rpipicowpicoprobe.menu.flash.2097152_131072.build.flash_length=1961984
|
||||
rpipicowpicoprobe.menu.flash.2097152_131072.build.eeprom_start=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_131072.build.fs_start=270397440
|
||||
rpipicowpicoprobe.menu.flash.2097152_131072.build.fs_end=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_262144=2MB (Sketch: 1792KB, FS: 256KB)
|
||||
rpipicowpicoprobe.menu.flash.2097152_262144.upload.maximum_size=1830912
|
||||
rpipicowpicoprobe.menu.flash.2097152_262144.build.flash_length=1830912
|
||||
rpipicowpicoprobe.menu.flash.2097152_262144.build.eeprom_start=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_262144.build.fs_start=270266368
|
||||
rpipicowpicoprobe.menu.flash.2097152_262144.build.fs_end=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_524288=2MB (Sketch: 1536KB, FS: 512KB)
|
||||
rpipicowpicoprobe.menu.flash.2097152_524288.upload.maximum_size=1568768
|
||||
rpipicowpicoprobe.menu.flash.2097152_524288.build.flash_length=1568768
|
||||
rpipicowpicoprobe.menu.flash.2097152_524288.build.eeprom_start=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_524288.build.fs_start=270004224
|
||||
rpipicowpicoprobe.menu.flash.2097152_524288.build.fs_end=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_1048576=2MB (Sketch: 1MB, FS: 1MB)
|
||||
rpipicowpicoprobe.menu.flash.2097152_1048576.upload.maximum_size=1044480
|
||||
rpipicowpicoprobe.menu.flash.2097152_1048576.build.flash_length=1044480
|
||||
rpipicowpicoprobe.menu.flash.2097152_1048576.build.eeprom_start=270528512
|
||||
rpipicowpicoprobe.menu.flash.2097152_1048576.build.fs_start=269479936
|
||||
rpipicowpicoprobe.menu.flash.2097152_1048576.build.fs_end=270528512
|
||||
rpipicowpicoprobe.menu.freq.133=133 MHz
|
||||
rpipicowpicoprobe.menu.freq.133.build.f_cpu=133000000L
|
||||
rpipicowpicoprobe.menu.freq.50=50 MHz
|
||||
rpipicowpicoprobe.menu.freq.50.build.f_cpu=50000000L
|
||||
rpipicowpicoprobe.menu.freq.100=100 MHz
|
||||
rpipicowpicoprobe.menu.freq.100.build.f_cpu=100000000L
|
||||
rpipicowpicoprobe.menu.freq.120=120 MHz
|
||||
rpipicowpicoprobe.menu.freq.120.build.f_cpu=120000000L
|
||||
rpipicowpicoprobe.menu.freq.125=125 MHz
|
||||
rpipicowpicoprobe.menu.freq.125.build.f_cpu=125000000L
|
||||
rpipicowpicoprobe.menu.freq.150=150 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.150.build.f_cpu=150000000L
|
||||
rpipicowpicoprobe.menu.freq.175=175 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.175.build.f_cpu=175000000L
|
||||
rpipicowpicoprobe.menu.freq.200=200 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.200.build.f_cpu=200000000L
|
||||
rpipicowpicoprobe.menu.freq.225=225 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.225.build.f_cpu=225000000L
|
||||
rpipicowpicoprobe.menu.freq.240=240 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.240.build.f_cpu=240000000L
|
||||
rpipicowpicoprobe.menu.freq.250=250 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.250.build.f_cpu=250000000L
|
||||
rpipicowpicoprobe.menu.freq.275=275 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.275.build.f_cpu=275000000L
|
||||
rpipicowpicoprobe.menu.freq.300=300 MHz (Overclock)
|
||||
rpipicowpicoprobe.menu.freq.300.build.f_cpu=300000000L
|
||||
rpipicowpicoprobe.menu.opt.Small=Small (-Os) (standard)
|
||||
rpipicowpicoprobe.menu.opt.Small.build.flags.optimize=-Os
|
||||
rpipicowpicoprobe.menu.opt.Optimize=Optimize (-O)
|
||||
rpipicowpicoprobe.menu.opt.Optimize.build.flags.optimize=-O
|
||||
rpipicowpicoprobe.menu.opt.Optimize2=Optimize More (-O2)
|
||||
rpipicowpicoprobe.menu.opt.Optimize2.build.flags.optimize=-O2
|
||||
rpipicowpicoprobe.menu.opt.Optimize3=Optimize Even More (-O3)
|
||||
rpipicowpicoprobe.menu.opt.Optimize3.build.flags.optimize=-O3
|
||||
rpipicowpicoprobe.menu.opt.Fast=Fast (-Ofast) (maybe slower)
|
||||
rpipicowpicoprobe.menu.opt.Fast.build.flags.optimize=-Ofast
|
||||
rpipicowpicoprobe.menu.opt.Debug=Debug (-Og)
|
||||
rpipicowpicoprobe.menu.opt.Debug.build.flags.optimize=-Og
|
||||
rpipicowpicoprobe.menu.rtti.Disabled=Disabled
|
||||
rpipicowpicoprobe.menu.rtti.Disabled.build.flags.rtti=-fno-rtti
|
||||
rpipicowpicoprobe.menu.rtti.Enabled=Enabled
|
||||
rpipicowpicoprobe.menu.rtti.Enabled.build.flags.rtti=
|
||||
rpipicowpicoprobe.menu.stackprotect.Disabled=Disabled
|
||||
rpipicowpicoprobe.menu.stackprotect.Disabled.build.flags.stackprotect=
|
||||
rpipicowpicoprobe.menu.stackprotect.Enabled=Enabled
|
||||
rpipicowpicoprobe.menu.stackprotect.Enabled.build.flags.stackprotect=-fstack-protector
|
||||
rpipicowpicoprobe.menu.exceptions.Disabled=Disabled
|
||||
rpipicowpicoprobe.menu.exceptions.Disabled.build.flags.exceptions=-fno-exceptions
|
||||
rpipicowpicoprobe.menu.exceptions.Disabled.build.flags.libstdcpp=-lstdc++
|
||||
rpipicowpicoprobe.menu.exceptions.Enabled=Enabled
|
||||
rpipicowpicoprobe.menu.exceptions.Enabled.build.flags.exceptions=-fexceptions
|
||||
rpipicowpicoprobe.menu.exceptions.Enabled.build.flags.libstdcpp=-lstdc++-exc
|
||||
rpipicowpicoprobe.menu.dbgport.Disabled=Disabled
|
||||
rpipicowpicoprobe.menu.dbgport.Disabled.build.debug_port=
|
||||
rpipicowpicoprobe.menu.dbgport.Serial=Serial
|
||||
rpipicowpicoprobe.menu.dbgport.Serial.build.debug_port=-DDEBUG_RP2040_PORT=Serial
|
||||
rpipicowpicoprobe.menu.dbgport.Serial1=Serial1
|
||||
rpipicowpicoprobe.menu.dbgport.Serial1.build.debug_port=-DDEBUG_RP2040_PORT=Serial1
|
||||
rpipicowpicoprobe.menu.dbgport.Serial2=Serial2
|
||||
rpipicowpicoprobe.menu.dbgport.Serial2.build.debug_port=-DDEBUG_RP2040_PORT=Serial2
|
||||
rpipicowpicoprobe.menu.dbglvl.None=None
|
||||
rpipicowpicoprobe.menu.dbglvl.None.build.debug_level=
|
||||
rpipicowpicoprobe.menu.dbglvl.Core=Core
|
||||
rpipicowpicoprobe.menu.dbglvl.Core.build.debug_level=-DDEBUG_RP2040_CORE
|
||||
rpipicowpicoprobe.menu.dbglvl.SPI=SPI
|
||||
rpipicowpicoprobe.menu.dbglvl.SPI.build.debug_level=-DDEBUG_RP2040_SPI
|
||||
rpipicowpicoprobe.menu.dbglvl.Wire=Wire
|
||||
rpipicowpicoprobe.menu.dbglvl.Wire.build.debug_level=-DDEBUG_RP2040_WIRE
|
||||
rpipicowpicoprobe.menu.dbglvl.All=All
|
||||
rpipicowpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE
|
||||
rpipicowpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
rpipicowpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
rpipicowpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
rpipicowpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
rpipicowpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
rpipicowpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
# -----------------------------------
|
||||
# Raspberry Pi Pico W (pico-debug)
|
||||
# -----------------------------------
|
||||
rpipicowpicodebug.name=Raspberry Pi Pico W (pico-debug)
|
||||
rpipicowpicodebug.vid.0=0x1209
|
||||
rpipicowpicodebug.pid.0=0x2488
|
||||
rpipicowpicodebug.build.usbpid=-DSERIALUSB_PID=0xf00a
|
||||
rpipicowpicodebug.build.usbpwr=-DUSBD_MAX_POWER_MA=250
|
||||
rpipicowpicodebug.build.board=RASPBERRY_PI_PICO_W
|
||||
rpipicowpicodebug.build.mcu=cortex-m0plus
|
||||
rpipicowpicodebug.build.variant=rpipicow
|
||||
rpipicowpicodebug.upload.tool=picodebug
|
||||
rpipicowpicodebug.upload.maximum_size=2097152
|
||||
rpipicowpicodebug.upload.maximum_data_size=245760
|
||||
rpipicowpicodebug.upload.wait_for_upload_port=true
|
||||
rpipicowpicodebug.upload.erase_cmd=
|
||||
rpipicowpicodebug.serial.disableDTR=false
|
||||
rpipicowpicodebug.serial.disableRTS=false
|
||||
rpipicowpicodebug.build.f_cpu=125000000
|
||||
rpipicowpicodebug.build.led=
|
||||
rpipicowpicodebug.build.core=rp2040
|
||||
rpipicowpicodebug.build.ldscript=memmap_default.ld
|
||||
rpipicowpicodebug.build.ram_length=240k
|
||||
rpipicowpicodebug.build.boot2=boot2_w25q080_2_padded_checksum
|
||||
rpipicowpicodebug.build.vid=0x2e8a
|
||||
rpipicowpicodebug.build.pid=0xf00a
|
||||
rpipicowpicodebug.build.usb_manufacturer="Raspberry Pi"
|
||||
rpipicowpicodebug.build.usb_product="Pico W (pico-debug)"
|
||||
rpipicowpicodebug.menu.flash.2097152_0=2MB (no FS)
|
||||
rpipicowpicodebug.menu.flash.2097152_0.upload.maximum_size=2093056
|
||||
rpipicowpicodebug.menu.flash.2097152_0.build.flash_length=2093056
|
||||
rpipicowpicodebug.menu.flash.2097152_0.build.eeprom_start=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_0.build.fs_start=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_0.build.fs_end=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_65536=2MB (Sketch: 1984KB, FS: 64KB)
|
||||
rpipicowpicodebug.menu.flash.2097152_65536.upload.maximum_size=2027520
|
||||
rpipicowpicodebug.menu.flash.2097152_65536.build.flash_length=2027520
|
||||
rpipicowpicodebug.menu.flash.2097152_65536.build.eeprom_start=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_65536.build.fs_start=270462976
|
||||
rpipicowpicodebug.menu.flash.2097152_65536.build.fs_end=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_131072=2MB (Sketch: 1920KB, FS: 128KB)
|
||||
rpipicowpicodebug.menu.flash.2097152_131072.upload.maximum_size=1961984
|
||||
rpipicowpicodebug.menu.flash.2097152_131072.build.flash_length=1961984
|
||||
rpipicowpicodebug.menu.flash.2097152_131072.build.eeprom_start=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_131072.build.fs_start=270397440
|
||||
rpipicowpicodebug.menu.flash.2097152_131072.build.fs_end=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_262144=2MB (Sketch: 1792KB, FS: 256KB)
|
||||
rpipicowpicodebug.menu.flash.2097152_262144.upload.maximum_size=1830912
|
||||
rpipicowpicodebug.menu.flash.2097152_262144.build.flash_length=1830912
|
||||
rpipicowpicodebug.menu.flash.2097152_262144.build.eeprom_start=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_262144.build.fs_start=270266368
|
||||
rpipicowpicodebug.menu.flash.2097152_262144.build.fs_end=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_524288=2MB (Sketch: 1536KB, FS: 512KB)
|
||||
rpipicowpicodebug.menu.flash.2097152_524288.upload.maximum_size=1568768
|
||||
rpipicowpicodebug.menu.flash.2097152_524288.build.flash_length=1568768
|
||||
rpipicowpicodebug.menu.flash.2097152_524288.build.eeprom_start=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_524288.build.fs_start=270004224
|
||||
rpipicowpicodebug.menu.flash.2097152_524288.build.fs_end=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_1048576=2MB (Sketch: 1MB, FS: 1MB)
|
||||
rpipicowpicodebug.menu.flash.2097152_1048576.upload.maximum_size=1044480
|
||||
rpipicowpicodebug.menu.flash.2097152_1048576.build.flash_length=1044480
|
||||
rpipicowpicodebug.menu.flash.2097152_1048576.build.eeprom_start=270528512
|
||||
rpipicowpicodebug.menu.flash.2097152_1048576.build.fs_start=269479936
|
||||
rpipicowpicodebug.menu.flash.2097152_1048576.build.fs_end=270528512
|
||||
rpipicowpicodebug.menu.freq.133=133 MHz
|
||||
rpipicowpicodebug.menu.freq.133.build.f_cpu=133000000L
|
||||
rpipicowpicodebug.menu.freq.50=50 MHz
|
||||
rpipicowpicodebug.menu.freq.50.build.f_cpu=50000000L
|
||||
rpipicowpicodebug.menu.freq.100=100 MHz
|
||||
rpipicowpicodebug.menu.freq.100.build.f_cpu=100000000L
|
||||
rpipicowpicodebug.menu.freq.120=120 MHz
|
||||
rpipicowpicodebug.menu.freq.120.build.f_cpu=120000000L
|
||||
rpipicowpicodebug.menu.freq.125=125 MHz
|
||||
rpipicowpicodebug.menu.freq.125.build.f_cpu=125000000L
|
||||
rpipicowpicodebug.menu.freq.150=150 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.150.build.f_cpu=150000000L
|
||||
rpipicowpicodebug.menu.freq.175=175 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.175.build.f_cpu=175000000L
|
||||
rpipicowpicodebug.menu.freq.200=200 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.200.build.f_cpu=200000000L
|
||||
rpipicowpicodebug.menu.freq.225=225 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.225.build.f_cpu=225000000L
|
||||
rpipicowpicodebug.menu.freq.240=240 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.240.build.f_cpu=240000000L
|
||||
rpipicowpicodebug.menu.freq.250=250 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.250.build.f_cpu=250000000L
|
||||
rpipicowpicodebug.menu.freq.275=275 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.275.build.f_cpu=275000000L
|
||||
rpipicowpicodebug.menu.freq.300=300 MHz (Overclock)
|
||||
rpipicowpicodebug.menu.freq.300.build.f_cpu=300000000L
|
||||
rpipicowpicodebug.menu.opt.Small=Small (-Os) (standard)
|
||||
rpipicowpicodebug.menu.opt.Small.build.flags.optimize=-Os
|
||||
rpipicowpicodebug.menu.opt.Optimize=Optimize (-O)
|
||||
rpipicowpicodebug.menu.opt.Optimize.build.flags.optimize=-O
|
||||
rpipicowpicodebug.menu.opt.Optimize2=Optimize More (-O2)
|
||||
rpipicowpicodebug.menu.opt.Optimize2.build.flags.optimize=-O2
|
||||
rpipicowpicodebug.menu.opt.Optimize3=Optimize Even More (-O3)
|
||||
rpipicowpicodebug.menu.opt.Optimize3.build.flags.optimize=-O3
|
||||
rpipicowpicodebug.menu.opt.Fast=Fast (-Ofast) (maybe slower)
|
||||
rpipicowpicodebug.menu.opt.Fast.build.flags.optimize=-Ofast
|
||||
rpipicowpicodebug.menu.opt.Debug=Debug (-Og)
|
||||
rpipicowpicodebug.menu.opt.Debug.build.flags.optimize=-Og
|
||||
rpipicowpicodebug.menu.rtti.Disabled=Disabled
|
||||
rpipicowpicodebug.menu.rtti.Disabled.build.flags.rtti=-fno-rtti
|
||||
rpipicowpicodebug.menu.rtti.Enabled=Enabled
|
||||
rpipicowpicodebug.menu.rtti.Enabled.build.flags.rtti=
|
||||
rpipicowpicodebug.menu.stackprotect.Disabled=Disabled
|
||||
rpipicowpicodebug.menu.stackprotect.Disabled.build.flags.stackprotect=
|
||||
rpipicowpicodebug.menu.stackprotect.Enabled=Enabled
|
||||
rpipicowpicodebug.menu.stackprotect.Enabled.build.flags.stackprotect=-fstack-protector
|
||||
rpipicowpicodebug.menu.exceptions.Disabled=Disabled
|
||||
rpipicowpicodebug.menu.exceptions.Disabled.build.flags.exceptions=-fno-exceptions
|
||||
rpipicowpicodebug.menu.exceptions.Disabled.build.flags.libstdcpp=-lstdc++
|
||||
rpipicowpicodebug.menu.exceptions.Enabled=Enabled
|
||||
rpipicowpicodebug.menu.exceptions.Enabled.build.flags.exceptions=-fexceptions
|
||||
rpipicowpicodebug.menu.exceptions.Enabled.build.flags.libstdcpp=-lstdc++-exc
|
||||
rpipicowpicodebug.menu.dbgport.Disabled=Disabled
|
||||
rpipicowpicodebug.menu.dbgport.Disabled.build.debug_port=
|
||||
rpipicowpicodebug.menu.dbgport.Serial=Serial
|
||||
rpipicowpicodebug.menu.dbgport.Serial.build.debug_port=-DDEBUG_RP2040_PORT=Serial
|
||||
rpipicowpicodebug.menu.dbgport.Serial1=Serial1
|
||||
rpipicowpicodebug.menu.dbgport.Serial1.build.debug_port=-DDEBUG_RP2040_PORT=Serial1
|
||||
rpipicowpicodebug.menu.dbgport.Serial2=Serial2
|
||||
rpipicowpicodebug.menu.dbgport.Serial2.build.debug_port=-DDEBUG_RP2040_PORT=Serial2
|
||||
rpipicowpicodebug.menu.dbglvl.None=None
|
||||
rpipicowpicodebug.menu.dbglvl.None.build.debug_level=
|
||||
rpipicowpicodebug.menu.dbglvl.Core=Core
|
||||
rpipicowpicodebug.menu.dbglvl.Core.build.debug_level=-DDEBUG_RP2040_CORE
|
||||
rpipicowpicodebug.menu.dbglvl.SPI=SPI
|
||||
rpipicowpicodebug.menu.dbglvl.SPI.build.debug_level=-DDEBUG_RP2040_SPI
|
||||
rpipicowpicodebug.menu.dbglvl.Wire=Wire
|
||||
rpipicowpicodebug.menu.dbglvl.Wire.build.debug_level=-DDEBUG_RP2040_WIRE
|
||||
rpipicowpicodebug.menu.dbglvl.All=All
|
||||
rpipicowpicodebug.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI -DDEBUG_RP2040_CORE
|
||||
rpipicowpicodebug.menu.dbglvl.NDEBUG=NDEBUG
|
||||
rpipicowpicodebug.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
rpipicowpicodebug.menu.usbstack.nousb=No USB
|
||||
rpipicowpicodebug.menu.usbstack.nousb.build.usbstack_flags="-DNO_USB -DDISABLE_USB_SERIAL -I{runtime.platform.path}/tools/libpico"
|
||||
|
||||
# -----------------------------------
|
||||
# Adafruit Feather RP2040
|
||||
# -----------------------------------
|
||||
|
|
@ -608,7 +1029,7 @@ adafruit_feather.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_R
|
|||
adafruit_feather.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_feather.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_feather.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_feather.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_feather.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_feather.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_feather.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -785,7 +1206,7 @@ adafruit_featherpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE
|
|||
adafruit_featherpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_featherpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_featherpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_featherpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_featherpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_featherpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_featherpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -1137,7 +1558,7 @@ adafruit_itsybitsy.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG
|
|||
adafruit_itsybitsy.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_itsybitsy.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_itsybitsy.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_itsybitsy.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_itsybitsy.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_itsybitsy.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_itsybitsy.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -1314,7 +1735,7 @@ adafruit_itsybitsypicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIR
|
|||
adafruit_itsybitsypicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_itsybitsypicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_itsybitsypicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_itsybitsypicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_itsybitsypicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_itsybitsypicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_itsybitsypicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -1666,7 +2087,7 @@ adafruit_qtpy.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP20
|
|||
adafruit_qtpy.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_qtpy.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_qtpy.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_qtpy.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_qtpy.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_qtpy.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_qtpy.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -1843,7 +2264,7 @@ adafruit_qtpypicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DD
|
|||
adafruit_qtpypicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_qtpypicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_qtpypicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_qtpypicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_qtpypicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_qtpypicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_qtpypicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -2195,7 +2616,7 @@ adafruit_stemmafriend.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDE
|
|||
adafruit_stemmafriend.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_stemmafriend.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_stemmafriend.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_stemmafriend.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_stemmafriend.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_stemmafriend.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_stemmafriend.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -2372,7 +2793,7 @@ adafruit_stemmafriendpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_
|
|||
adafruit_stemmafriendpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_stemmafriendpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_stemmafriendpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_stemmafriendpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_stemmafriendpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_stemmafriendpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_stemmafriendpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -2724,7 +3145,7 @@ adafruit_trinkeyrp2040qt.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -
|
|||
adafruit_trinkeyrp2040qt.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_trinkeyrp2040qt.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_trinkeyrp2040qt.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_trinkeyrp2040qt.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_trinkeyrp2040qt.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_trinkeyrp2040qt.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_trinkeyrp2040qt.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -2901,7 +3322,7 @@ adafruit_trinkeyrp2040qtpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP20
|
|||
adafruit_trinkeyrp2040qtpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_trinkeyrp2040qtpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_trinkeyrp2040qtpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_trinkeyrp2040qtpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_trinkeyrp2040qtpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_trinkeyrp2040qtpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_trinkeyrp2040qtpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -3253,7 +3674,7 @@ adafruit_macropad2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDE
|
|||
adafruit_macropad2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_macropad2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_macropad2040.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_macropad2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_macropad2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_macropad2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_macropad2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -3430,7 +3851,7 @@ adafruit_macropad2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_
|
|||
adafruit_macropad2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_macropad2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_macropad2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_macropad2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_macropad2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_macropad2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_macropad2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -3782,7 +4203,7 @@ adafruit_kb2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP
|
|||
adafruit_kb2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_kb2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_kb2040.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_kb2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_kb2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_kb2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_kb2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -3959,7 +4380,7 @@ adafruit_kb2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -
|
|||
adafruit_kb2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
adafruit_kb2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
adafruit_kb2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
adafruit_kb2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
adafruit_kb2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
adafruit_kb2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
adafruit_kb2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -4359,7 +4780,7 @@ arduino_nano_connect.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEB
|
|||
arduino_nano_connect.menu.dbglvl.NDEBUG=NDEBUG
|
||||
arduino_nano_connect.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
arduino_nano_connect.menu.usbstack.picosdk=Pico SDK
|
||||
arduino_nano_connect.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
arduino_nano_connect.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
arduino_nano_connect.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
arduino_nano_connect.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -4584,7 +5005,7 @@ arduino_nano_connectpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_W
|
|||
arduino_nano_connectpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
arduino_nano_connectpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
arduino_nano_connectpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
arduino_nano_connectpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
arduino_nano_connectpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
arduino_nano_connectpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
arduino_nano_connectpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -4948,7 +5369,7 @@ cytron_maker_nano_rp2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -
|
|||
cytron_maker_nano_rp2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
cytron_maker_nano_rp2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
cytron_maker_nano_rp2040.menu.usbstack.picosdk=Pico SDK
|
||||
cytron_maker_nano_rp2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
cytron_maker_nano_rp2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
cytron_maker_nano_rp2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
cytron_maker_nano_rp2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -5089,7 +5510,7 @@ cytron_maker_nano_rp2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP20
|
|||
cytron_maker_nano_rp2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
cytron_maker_nano_rp2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
cytron_maker_nano_rp2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
cytron_maker_nano_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
cytron_maker_nano_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
cytron_maker_nano_rp2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
cytron_maker_nano_rp2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -5369,7 +5790,7 @@ cytron_maker_pi_rp2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DD
|
|||
cytron_maker_pi_rp2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
cytron_maker_pi_rp2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
cytron_maker_pi_rp2040.menu.usbstack.picosdk=Pico SDK
|
||||
cytron_maker_pi_rp2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
cytron_maker_pi_rp2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
cytron_maker_pi_rp2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
cytron_maker_pi_rp2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -5510,7 +5931,7 @@ cytron_maker_pi_rp2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040
|
|||
cytron_maker_pi_rp2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
cytron_maker_pi_rp2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
cytron_maker_pi_rp2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
cytron_maker_pi_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
cytron_maker_pi_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
cytron_maker_pi_rp2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
cytron_maker_pi_rp2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -5802,7 +6223,7 @@ flyboard2040_core.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_
|
|||
flyboard2040_core.menu.dbglvl.NDEBUG=NDEBUG
|
||||
flyboard2040_core.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
flyboard2040_core.menu.usbstack.picosdk=Pico SDK
|
||||
flyboard2040_core.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
flyboard2040_core.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
flyboard2040_core.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
flyboard2040_core.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -5955,7 +6376,7 @@ flyboard2040_corepicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE
|
|||
flyboard2040_corepicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
flyboard2040_corepicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
flyboard2040_corepicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
flyboard2040_corepicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
flyboard2040_corepicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
flyboard2040_corepicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
flyboard2040_corepicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -6247,7 +6668,7 @@ dfrobot_beetle_rp2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDE
|
|||
dfrobot_beetle_rp2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
dfrobot_beetle_rp2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
dfrobot_beetle_rp2040.menu.usbstack.picosdk=Pico SDK
|
||||
dfrobot_beetle_rp2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
dfrobot_beetle_rp2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
dfrobot_beetle_rp2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
dfrobot_beetle_rp2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -6388,7 +6809,7 @@ dfrobot_beetle_rp2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_
|
|||
dfrobot_beetle_rp2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
dfrobot_beetle_rp2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
dfrobot_beetle_rp2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
dfrobot_beetle_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
dfrobot_beetle_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
dfrobot_beetle_rp2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
dfrobot_beetle_rp2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -6704,7 +7125,7 @@ challenger_2040_lora.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEB
|
|||
challenger_2040_lora.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_lora.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_lora.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_lora.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_lora.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_lora.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_lora.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -6881,7 +7302,7 @@ challenger_2040_lorapicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_W
|
|||
challenger_2040_lorapicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_lorapicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_lorapicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_lorapicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_lorapicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_lorapicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_lorapicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -7233,7 +7654,7 @@ challenger_2040_subghz.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DD
|
|||
challenger_2040_subghz.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_subghz.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_subghz.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_subghz.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_subghz.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_subghz.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_subghz.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -7410,7 +7831,7 @@ challenger_2040_subghzpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040
|
|||
challenger_2040_subghzpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_subghzpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_subghzpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_subghzpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_subghzpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_subghzpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_subghzpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -7762,7 +8183,7 @@ challenger_2040_wifi.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEB
|
|||
challenger_2040_wifi.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_wifi.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_wifi.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_wifi.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_wifi.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_wifi.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_wifi.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -7939,7 +8360,7 @@ challenger_2040_wifipicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_W
|
|||
challenger_2040_wifipicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_wifipicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_wifipicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_wifipicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_wifipicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_wifipicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_wifipicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -8291,7 +8712,7 @@ challenger_2040_lte.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBU
|
|||
challenger_2040_lte.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_lte.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_lte.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_lte.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_lte.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_lte.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_lte.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -8468,7 +8889,7 @@ challenger_2040_ltepicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WI
|
|||
challenger_2040_ltepicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_ltepicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_ltepicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_ltepicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_ltepicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_ltepicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_ltepicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -8820,7 +9241,7 @@ challenger_2040_wifi_ble.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -
|
|||
challenger_2040_wifi_ble.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_wifi_ble.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_wifi_ble.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_wifi_ble.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_wifi_ble.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_wifi_ble.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_wifi_ble.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -8997,7 +9418,7 @@ challenger_2040_wifi_blepicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP20
|
|||
challenger_2040_wifi_blepicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_wifi_blepicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_wifi_blepicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_wifi_blepicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_wifi_blepicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_wifi_blepicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_wifi_blepicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -9349,7 +9770,7 @@ challenger_nb_2040_wifi.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -D
|
|||
challenger_nb_2040_wifi.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_nb_2040_wifi.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_nb_2040_wifi.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_nb_2040_wifi.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_nb_2040_wifi.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_nb_2040_wifi.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_nb_2040_wifi.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -9526,7 +9947,7 @@ challenger_nb_2040_wifipicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP204
|
|||
challenger_nb_2040_wifipicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_nb_2040_wifipicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_nb_2040_wifipicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_nb_2040_wifipicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_nb_2040_wifipicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_nb_2040_wifipicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_nb_2040_wifipicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -9878,7 +10299,7 @@ challenger_2040_sdrtc.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDE
|
|||
challenger_2040_sdrtc.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_sdrtc.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_sdrtc.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_sdrtc.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_sdrtc.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_sdrtc.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_sdrtc.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -10055,7 +10476,7 @@ challenger_2040_sdrtcpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_
|
|||
challenger_2040_sdrtcpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
challenger_2040_sdrtcpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
challenger_2040_sdrtcpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
challenger_2040_sdrtcpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
challenger_2040_sdrtcpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
challenger_2040_sdrtcpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
challenger_2040_sdrtcpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -10407,7 +10828,7 @@ ilabs_rpico32.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP20
|
|||
ilabs_rpico32.menu.dbglvl.NDEBUG=NDEBUG
|
||||
ilabs_rpico32.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
ilabs_rpico32.menu.usbstack.picosdk=Pico SDK
|
||||
ilabs_rpico32.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
ilabs_rpico32.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
ilabs_rpico32.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
ilabs_rpico32.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -10584,7 +11005,7 @@ ilabs_rpico32picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DD
|
|||
ilabs_rpico32picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
ilabs_rpico32picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
ilabs_rpico32picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
ilabs_rpico32picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
ilabs_rpico32picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
ilabs_rpico32picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
ilabs_rpico32picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -10984,7 +11405,7 @@ melopero_shake_rp2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDE
|
|||
melopero_shake_rp2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
melopero_shake_rp2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
melopero_shake_rp2040.menu.usbstack.picosdk=Pico SDK
|
||||
melopero_shake_rp2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
melopero_shake_rp2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
melopero_shake_rp2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
melopero_shake_rp2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -11209,7 +11630,7 @@ melopero_shake_rp2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_
|
|||
melopero_shake_rp2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
melopero_shake_rp2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
melopero_shake_rp2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
melopero_shake_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
melopero_shake_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
melopero_shake_rp2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
melopero_shake_rp2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -11609,7 +12030,7 @@ solderparty_rp2040_stamp.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -
|
|||
solderparty_rp2040_stamp.menu.dbglvl.NDEBUG=NDEBUG
|
||||
solderparty_rp2040_stamp.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
solderparty_rp2040_stamp.menu.usbstack.picosdk=Pico SDK
|
||||
solderparty_rp2040_stamp.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
solderparty_rp2040_stamp.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
solderparty_rp2040_stamp.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
solderparty_rp2040_stamp.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -11786,7 +12207,7 @@ solderparty_rp2040_stamppicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP20
|
|||
solderparty_rp2040_stamppicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
solderparty_rp2040_stamppicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
solderparty_rp2040_stamppicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
solderparty_rp2040_stamppicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
solderparty_rp2040_stamppicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
solderparty_rp2040_stamppicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
solderparty_rp2040_stamppicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -12186,7 +12607,7 @@ sparkfun_promicrorp2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -D
|
|||
sparkfun_promicrorp2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
sparkfun_promicrorp2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
sparkfun_promicrorp2040.menu.usbstack.picosdk=Pico SDK
|
||||
sparkfun_promicrorp2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
sparkfun_promicrorp2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
sparkfun_promicrorp2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
sparkfun_promicrorp2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -12411,7 +12832,7 @@ sparkfun_promicrorp2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP204
|
|||
sparkfun_promicrorp2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
sparkfun_promicrorp2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
sparkfun_promicrorp2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
sparkfun_promicrorp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
sparkfun_promicrorp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
sparkfun_promicrorp2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
sparkfun_promicrorp2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -12859,7 +13280,7 @@ sparkfun_thingplusrp2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -
|
|||
sparkfun_thingplusrp2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
sparkfun_thingplusrp2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
sparkfun_thingplusrp2040.menu.usbstack.picosdk=Pico SDK
|
||||
sparkfun_thingplusrp2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
sparkfun_thingplusrp2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
sparkfun_thingplusrp2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
sparkfun_thingplusrp2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -13084,7 +13505,7 @@ sparkfun_thingplusrp2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP20
|
|||
sparkfun_thingplusrp2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
sparkfun_thingplusrp2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
sparkfun_thingplusrp2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
sparkfun_thingplusrp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
sparkfun_thingplusrp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
sparkfun_thingplusrp2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
sparkfun_thingplusrp2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -13448,7 +13869,7 @@ upesy_rp2040_devkit.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBU
|
|||
upesy_rp2040_devkit.menu.dbglvl.NDEBUG=NDEBUG
|
||||
upesy_rp2040_devkit.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
upesy_rp2040_devkit.menu.usbstack.picosdk=Pico SDK
|
||||
upesy_rp2040_devkit.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
upesy_rp2040_devkit.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
upesy_rp2040_devkit.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
upesy_rp2040_devkit.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -13589,7 +14010,7 @@ upesy_rp2040_devkitpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WI
|
|||
upesy_rp2040_devkitpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
upesy_rp2040_devkitpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
upesy_rp2040_devkitpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
upesy_rp2040_devkitpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
upesy_rp2040_devkitpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
upesy_rp2040_devkitpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
upesy_rp2040_devkitpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -13869,7 +14290,7 @@ seeed_xiao_rp2040.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_
|
|||
seeed_xiao_rp2040.menu.dbglvl.NDEBUG=NDEBUG
|
||||
seeed_xiao_rp2040.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
seeed_xiao_rp2040.menu.usbstack.picosdk=Pico SDK
|
||||
seeed_xiao_rp2040.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
seeed_xiao_rp2040.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
seeed_xiao_rp2040.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
seeed_xiao_rp2040.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -14010,7 +14431,7 @@ seeed_xiao_rp2040picoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE
|
|||
seeed_xiao_rp2040picoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
seeed_xiao_rp2040picoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
seeed_xiao_rp2040picoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
seeed_xiao_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
seeed_xiao_rp2040picoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
seeed_xiao_rp2040picoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
seeed_xiao_rp2040picoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -14290,7 +14711,7 @@ wiznet_5100s_evb_pico.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDE
|
|||
wiznet_5100s_evb_pico.menu.dbglvl.NDEBUG=NDEBUG
|
||||
wiznet_5100s_evb_pico.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
wiznet_5100s_evb_pico.menu.usbstack.picosdk=Pico SDK
|
||||
wiznet_5100s_evb_pico.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
wiznet_5100s_evb_pico.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
wiznet_5100s_evb_pico.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
wiznet_5100s_evb_pico.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -14431,7 +14852,7 @@ wiznet_5100s_evb_picopicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_
|
|||
wiznet_5100s_evb_picopicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
wiznet_5100s_evb_picopicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
wiznet_5100s_evb_picopicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
wiznet_5100s_evb_picopicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
wiznet_5100s_evb_picopicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
wiznet_5100s_evb_picopicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
wiznet_5100s_evb_picopicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -14711,7 +15132,7 @@ wiznet_wizfi360_evb_pico.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -
|
|||
wiznet_wizfi360_evb_pico.menu.dbglvl.NDEBUG=NDEBUG
|
||||
wiznet_wizfi360_evb_pico.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
wiznet_wizfi360_evb_pico.menu.usbstack.picosdk=Pico SDK
|
||||
wiznet_wizfi360_evb_pico.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
wiznet_wizfi360_evb_pico.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
wiznet_wizfi360_evb_pico.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
wiznet_wizfi360_evb_pico.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -14852,7 +15273,7 @@ wiznet_wizfi360_evb_picopicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP20
|
|||
wiznet_wizfi360_evb_picopicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
wiznet_wizfi360_evb_picopicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
wiznet_wizfi360_evb_picopicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
wiznet_wizfi360_evb_picopicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
wiznet_wizfi360_evb_picopicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
wiznet_wizfi360_evb_picopicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
wiznet_wizfi360_evb_picopicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -15132,7 +15553,7 @@ wiznet_5500_evb_pico.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEB
|
|||
wiznet_5500_evb_pico.menu.dbglvl.NDEBUG=NDEBUG
|
||||
wiznet_5500_evb_pico.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
wiznet_5500_evb_pico.menu.usbstack.picosdk=Pico SDK
|
||||
wiznet_5500_evb_pico.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
wiznet_5500_evb_pico.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
wiznet_5500_evb_pico.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
wiznet_5500_evb_pico.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -15273,7 +15694,7 @@ wiznet_5500_evb_picopicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_W
|
|||
wiznet_5500_evb_picopicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
wiznet_5500_evb_picopicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
wiznet_5500_evb_picopicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
wiznet_5500_evb_picopicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
wiznet_5500_evb_picopicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
wiznet_5500_evb_picopicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
wiznet_5500_evb_picopicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
|
||||
|
|
@ -15565,7 +15986,7 @@ generic.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_RP2040_SPI
|
|||
generic.menu.dbglvl.NDEBUG=NDEBUG
|
||||
generic.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
generic.menu.usbstack.picosdk=Pico SDK
|
||||
generic.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
generic.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
generic.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
generic.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
generic.menu.boot2.boot2_generic_03h_2_padded_checksum=Generic SPI /2
|
||||
|
|
@ -15734,7 +16155,7 @@ genericpicoprobe.menu.dbglvl.All.build.debug_level=-DDEBUG_RP2040_WIRE -DDEBUG_R
|
|||
genericpicoprobe.menu.dbglvl.NDEBUG=NDEBUG
|
||||
genericpicoprobe.menu.dbglvl.NDEBUG.build.debug_level=-DNDEBUG
|
||||
genericpicoprobe.menu.usbstack.picosdk=Pico SDK
|
||||
genericpicoprobe.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"
|
||||
genericpicoprobe.menu.usbstack.picosdk.build.usbstack_flags=
|
||||
genericpicoprobe.menu.usbstack.tinyusb=Adafruit TinyUSB
|
||||
genericpicoprobe.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
|
||||
genericpicoprobe.menu.boot2.boot2_generic_03h_2_padded_checksum=Generic SPI /2
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -112,5 +111,3 @@ constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) {
|
|||
return i < N ? (1L << a[i]) | __bitset(a, i + 1) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // Arduino_h
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FS_H
|
||||
#define FS_H
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <Arduino.h>
|
||||
|
|
@ -264,5 +263,3 @@ using fs::SeekEnd;
|
|||
using fs::FSInfo;
|
||||
using fs::FSConfig;
|
||||
#endif //FS_NO_GLOBALS
|
||||
|
||||
#endif //FS_H
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef FSIMPL_H
|
||||
#define FSIMPL_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -149,5 +149,3 @@ protected:
|
|||
};
|
||||
|
||||
} // namespace fs
|
||||
|
||||
#endif //FSIMPL_H
|
||||
|
|
|
|||
41
cores/rp2040/LWIPMutex.h
Normal file
41
cores/rp2040/LWIPMutex.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
WiFiMutex.h - Ensure the timer-driven sys_check_timeouts doesn't
|
||||
get executed while we're in the user-level TCP stack.
|
||||
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
Implements the API defined by the Arduino WiFiNINA library,
|
||||
copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern "C" volatile bool __inLWIP;
|
||||
|
||||
class LWIPMutex {
|
||||
public:
|
||||
LWIPMutex() {
|
||||
__inLWIP = true;
|
||||
_ref++;
|
||||
}
|
||||
~LWIPMutex() {
|
||||
if (0 == --_ref) {
|
||||
__inLWIP = false;
|
||||
}
|
||||
}
|
||||
private:
|
||||
static int _ref;
|
||||
};
|
||||
|
|
@ -40,7 +40,7 @@ mutex_t __usb_mutex;
|
|||
|
||||
// USB processing will be a periodic timer task
|
||||
#define USB_TASK_INTERVAL 1000
|
||||
#define USB_TASK_IRQ 31
|
||||
static int __usb_task_irq;
|
||||
|
||||
// USB VID/PID (note that PID can change depending on the add'l interfaces)
|
||||
#define USBD_VID (0x2E8A) // Raspberry Pi
|
||||
|
|
@ -284,7 +284,7 @@ static void usb_irq() {
|
|||
}
|
||||
|
||||
static int64_t timer_task(__unused alarm_id_t id, __unused void *user_data) {
|
||||
irq_set_pending(USB_TASK_IRQ);
|
||||
irq_set_pending(__usb_task_irq);
|
||||
return USB_TASK_INTERVAL;
|
||||
}
|
||||
|
||||
|
|
@ -303,8 +303,9 @@ void __USBStart() {
|
|||
|
||||
tusb_init();
|
||||
|
||||
irq_set_exclusive_handler(USB_TASK_IRQ, usb_irq);
|
||||
irq_set_enabled(USB_TASK_IRQ, true);
|
||||
__usb_task_irq = user_irq_claim_unused(true);
|
||||
irq_set_exclusive_handler(__usb_task_irq, usb_irq);
|
||||
irq_set_enabled(__usb_task_irq, true);
|
||||
|
||||
add_alarm_in_us(USB_TASK_INTERVAL, timer_task, NULL, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __SERIALUSB_H__
|
||||
#define __SERIALUSB_H__
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "api/HardwareSerial.h"
|
||||
|
|
@ -54,5 +53,3 @@ extern SerialUSB Serial;
|
|||
namespace arduino {
|
||||
extern void serialEventRun(void) __attribute__((weak));
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,55 +1,75 @@
|
|||
/*
|
||||
IPAddress.cpp - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
IPAddress.cpp - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "IPAddress.h"
|
||||
#include "Print.h"
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress.h>
|
||||
#include <Print.h>
|
||||
|
||||
using namespace arduino;
|
||||
|
||||
IPAddress::IPAddress()
|
||||
IPAddress::IPAddress(const IPAddress& from)
|
||||
{
|
||||
_address.dword = 0;
|
||||
ip_addr_copy(_ip, from._ip);
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
||||
{
|
||||
_address.bytes[0] = first_octet;
|
||||
_address.bytes[1] = second_octet;
|
||||
_address.bytes[2] = third_octet;
|
||||
_address.bytes[3] = fourth_octet;
|
||||
IPAddress::IPAddress() {
|
||||
_ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
bool IPAddress::isSet () const {
|
||||
return !ip_addr_isany(&_ip) && ((*this) != IPADDR_NONE);
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
|
||||
setV4();
|
||||
(*this)[0] = first_octet;
|
||||
(*this)[1] = second_octet;
|
||||
(*this)[2] = third_octet;
|
||||
(*this)[3] = fourth_octet;
|
||||
}
|
||||
|
||||
bool IPAddress::fromString(const char *address)
|
||||
{
|
||||
// TODO: add support for "a", "a.b", "a.b.c" formats
|
||||
void IPAddress::ctor32(uint32_t address) {
|
||||
setV4();
|
||||
v4() = address;
|
||||
}
|
||||
|
||||
int16_t acc = -1; // Accumulator
|
||||
IPAddress::IPAddress(const uint8_t *address) {
|
||||
setV4();
|
||||
(*this)[0] = address[0];
|
||||
(*this)[1] = address[1];
|
||||
(*this)[2] = address[2];
|
||||
(*this)[3] = address[3];
|
||||
}
|
||||
|
||||
bool IPAddress::fromString(const char *address) {
|
||||
if (!fromString4(address)) {
|
||||
#if LWIP_IPV6
|
||||
return fromString6(address);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IPAddress::fromString4(const char *address) {
|
||||
// TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats
|
||||
|
||||
uint16_t acc = 0; // Accumulator
|
||||
uint8_t dots = 0;
|
||||
|
||||
while (*address)
|
||||
|
|
@ -57,7 +77,7 @@ bool IPAddress::fromString(const char *address)
|
|||
char c = *address++;
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0');
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) {
|
||||
// Value out of [0..255] range
|
||||
return false;
|
||||
|
|
@ -69,12 +89,8 @@ bool IPAddress::fromString(const char *address)
|
|||
// Too much dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
if (acc < 0) {
|
||||
/* No value between dots, e.g. '1..' */
|
||||
return false;
|
||||
}
|
||||
_address.bytes[dots++] = acc;
|
||||
acc = -1;
|
||||
(*this)[dots++] = acc;
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -87,41 +103,144 @@ bool IPAddress::fromString(const char *address)
|
|||
// Too few dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
if (acc < 0) {
|
||||
/* No value between dots, e.g. '1..' */
|
||||
return false;
|
||||
}
|
||||
_address.bytes[3] = acc;
|
||||
(*this)[3] = acc;
|
||||
|
||||
setV4();
|
||||
return true;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
IPAddress& IPAddress::operator=(const uint8_t *address) {
|
||||
setV4();
|
||||
v4() = *reinterpret_cast<const uint32_t*>(address);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
IPAddress& IPAddress::operator=(uint32_t address) {
|
||||
setV4();
|
||||
v4() = address;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPAddress::operator==(const uint8_t* addr) const
|
||||
{
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
bool IPAddress::operator==(const uint8_t* addr) const {
|
||||
return isV4() && v4() == *reinterpret_cast<const uint32_t*>(addr);
|
||||
}
|
||||
|
||||
size_t IPAddress::printTo(Print& p) const
|
||||
size_t IPAddress::printTo(Print& p) const {
|
||||
String s = toString();
|
||||
return p.print(s);
|
||||
}
|
||||
|
||||
String IPAddress::toString() const
|
||||
{
|
||||
size_t n = 0;
|
||||
for (int i =0; i < 3; i++)
|
||||
{
|
||||
n += p.print(_address.bytes[i], DEC);
|
||||
n += p.print('.');
|
||||
String s;
|
||||
|
||||
if (!isSet())
|
||||
return "(IP unset)";
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (isV6()) {
|
||||
int count0 = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint16_t bit = PP_NTOHS(raw6()[i]);
|
||||
if (bit || count0 < 0) {
|
||||
char buff[64];
|
||||
snprintf(buff, 64, "%x", bit);
|
||||
buff[63] = 0;
|
||||
s += buff;
|
||||
if (count0 > 0)
|
||||
// no more hiding 0
|
||||
count0 = -8;
|
||||
} else
|
||||
count0++;
|
||||
if ((i != 7 && count0 < 2) || count0 == 7)
|
||||
s += ':';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
n += p.print(_address.bytes[3], DEC);
|
||||
return n;
|
||||
#endif
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
char buff[16];
|
||||
snprintf(buff, 16, "%d", (*this)[i]);
|
||||
buff[15] = 0;
|
||||
s += buff;
|
||||
if (i != 3)
|
||||
s += '.';
|
||||
}
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
const IPAddress arduino::INADDR_NONE(0,0,0,0);
|
||||
bool IPAddress::isValid(const String& arg) {
|
||||
return IPAddress().fromString(arg);
|
||||
}
|
||||
|
||||
bool IPAddress::isValid(const char* arg) {
|
||||
return IPAddress().fromString(arg);
|
||||
}
|
||||
|
||||
const IPAddress INADDR_ANY; // generic "0.0.0.0" for IPv4 & IPv6
|
||||
const IPAddress INADDR_NONE(255,255,255,255);
|
||||
|
||||
void IPAddress::clear() {
|
||||
(*this) = INADDR_ANY;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
#if LWIP_IPV6
|
||||
|
||||
bool IPAddress::fromString6(const char *address) {
|
||||
// TODO: test test test
|
||||
|
||||
uint32_t acc = 0; // Accumulator
|
||||
int dots = 0, doubledots = -1;
|
||||
|
||||
while (*address)
|
||||
{
|
||||
char c = tolower(*address++);
|
||||
if (isalnum(c)) {
|
||||
if (c >= 'a')
|
||||
c -= 'a' - '0' - 10;
|
||||
acc = acc * 16 + (c - '0');
|
||||
if (acc > 0xffff)
|
||||
// Value out of range
|
||||
return false;
|
||||
}
|
||||
else if (c == ':') {
|
||||
if (*address == ':') {
|
||||
if (doubledots >= 0)
|
||||
// :: allowed once
|
||||
return false;
|
||||
// remember location
|
||||
doubledots = dots + !!acc;
|
||||
address++;
|
||||
}
|
||||
if (dots == 7)
|
||||
// too many separators
|
||||
return false;
|
||||
raw6()[dots++] = PP_HTONS(acc);
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
// Invalid char
|
||||
return false;
|
||||
}
|
||||
|
||||
if (doubledots == -1 && dots != 7)
|
||||
// Too few separators
|
||||
return false;
|
||||
raw6()[dots++] = PP_HTONS(acc);
|
||||
|
||||
if (doubledots != -1) {
|
||||
for (int i = dots - doubledots - 1; i >= 0; i--)
|
||||
raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i];
|
||||
for (int i = doubledots; i < 8 - dots + doubledots; i++)
|
||||
raw6()[i] = 0;
|
||||
}
|
||||
|
||||
setV6();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,85 +1,218 @@
|
|||
/*
|
||||
IPAddress.h - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
IPAddress.h - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Printable.h"
|
||||
#include "String.h"
|
||||
#include <api/String.h>
|
||||
#include <Printable.h>
|
||||
|
||||
// forward declartions of global name space friend classes
|
||||
class EthernetClass;
|
||||
class DhcpClass;
|
||||
class DNSClient;
|
||||
#include <lwip/init.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/ip4_addr.h>
|
||||
|
||||
namespace arduino {
|
||||
|
||||
#if !LWIP_IPV6
|
||||
struct ip_addr: ipv4_addr { };
|
||||
#endif // !LWIP_IPV6
|
||||
|
||||
// to display a netif id with printf:
|
||||
#define NETIFID_STR "%c%c%u"
|
||||
#define NETIFID_VAL(netif) \
|
||||
((netif)? (netif)->name[0]: '-'), \
|
||||
((netif)? (netif)->name[1]: '-'), \
|
||||
((netif)? netif_get_index(netif): 42)
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
// IPv6 update:
|
||||
// IPAddress is now a decorator class for lwIP's ip_addr_t
|
||||
// fully backward compatible with legacy IPv4-only Arduino's
|
||||
// with unchanged footprint when IPv6 is disabled
|
||||
|
||||
class IPAddress : public Printable {
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[4]; // IPv4 address
|
||||
uint32_t dword;
|
||||
} _address;
|
||||
class IPAddress: public Printable {
|
||||
private:
|
||||
|
||||
// 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
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address() { return _address.bytes; };
|
||||
ip_addr_t _ip;
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPAddress();
|
||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||
IPAddress(uint32_t address);
|
||||
IPAddress(const uint8_t *address);
|
||||
// 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
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address() {
|
||||
return reinterpret_cast<uint8_t*>(&v4());
|
||||
}
|
||||
const uint8_t* raw_address() const {
|
||||
return reinterpret_cast<const uint8_t*>(&v4());
|
||||
}
|
||||
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
void ctor32 (uint32_t);
|
||||
|
||||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||
// to a four-byte uint8_t array is expected
|
||||
operator uint32_t() const { return _address.dword; };
|
||||
bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; };
|
||||
bool operator!=(const IPAddress& addr) const { return _address.dword != addr._address.dword; };
|
||||
bool operator==(const uint8_t* addr) const;
|
||||
public:
|
||||
// Constructors
|
||||
IPAddress();
|
||||
IPAddress(const IPAddress& from);
|
||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||
IPAddress(uint32_t address) { ctor32(address); }
|
||||
// IPAddress(unsigned long address) { ctor32(address); }
|
||||
IPAddress(int address) { ctor32(address); }
|
||||
IPAddress(const uint8_t *address);
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const { return _address.bytes[index]; };
|
||||
uint8_t& operator[](int index) { return _address.bytes[index]; };
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||
IPAddress& operator=(const uint8_t *address);
|
||||
IPAddress& operator=(uint32_t address);
|
||||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||
// to a four-byte uint8_t array is expected
|
||||
operator uint32_t() const { return isV4()? v4(): (uint32_t)0; }
|
||||
operator uint32_t() { return isV4()? v4(): (uint32_t)0; }
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
bool isSet () const;
|
||||
operator bool () const { return isSet(); } // <-
|
||||
operator bool () { return isSet(); } // <- both are needed
|
||||
|
||||
// generic IPv4 wrapper to uint32-view like arduino loves to see it
|
||||
const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } // for raw_address(const)
|
||||
uint32_t& v4() { return ip_2_ip4(&_ip)->addr; }
|
||||
|
||||
bool operator==(const IPAddress& addr) const {
|
||||
return ip_addr_cmp(&_ip, &addr._ip);
|
||||
}
|
||||
bool operator!=(const IPAddress& addr) const {
|
||||
return !ip_addr_cmp(&_ip, &addr._ip);
|
||||
}
|
||||
bool operator==(uint32_t addr) const {
|
||||
return isV4() && v4() == addr;
|
||||
}
|
||||
// bool operator==(unsigned long addr) const {
|
||||
// return isV4() && v4() == (uint32_t)addr;
|
||||
// }
|
||||
bool operator!=(uint32_t addr) const {
|
||||
return !(isV4() && v4() == addr);
|
||||
}
|
||||
// bool operator!=(unsigned long addr) const {
|
||||
// return isV4() && v4() != (uint32_t)addr;
|
||||
// }
|
||||
bool operator==(const uint8_t* addr) const;
|
||||
|
||||
int operator>>(int n) const {
|
||||
return isV4()? v4() >> n: 0;
|
||||
}
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const {
|
||||
return isV4()? *(raw_address() + index): 0;
|
||||
}
|
||||
uint8_t& operator[](int index) {
|
||||
setV4();
|
||||
return *(raw_address() + index);
|
||||
}
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||
IPAddress& operator=(const uint8_t *address);
|
||||
IPAddress& operator=(uint32_t address);
|
||||
IPAddress& operator=(const IPAddress&) = default;
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
String toString() const;
|
||||
|
||||
void clear();
|
||||
|
||||
/*
|
||||
check if input string(arg) is a valid IPV4 address or not.
|
||||
return true on valid.
|
||||
return false on invalid.
|
||||
*/
|
||||
static bool isValid(const String& arg);
|
||||
static bool isValid(const char* arg);
|
||||
|
||||
friend class WiFiClass;
|
||||
friend class EthernetClass;
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
friend class DhcpClass;
|
||||
friend class DNSClient;
|
||||
|
||||
/*
|
||||
lwIP address compatibility
|
||||
*/
|
||||
//IPAddress(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; }
|
||||
//IPAddress(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; }
|
||||
|
||||
//IPAddress& operator=(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; return *this; }
|
||||
//IPAddress& operator=(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; return *this; }
|
||||
|
||||
operator ip_addr_t () const { return _ip; }
|
||||
operator const ip_addr_t*() const { return &_ip; }
|
||||
operator ip_addr_t*() { return &_ip; }
|
||||
|
||||
bool isV4() const { return IP_IS_V4_VAL(_ip); }
|
||||
void setV4() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V4); }
|
||||
|
||||
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& 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; }
|
||||
|
||||
uint16_t* raw6()
|
||||
{
|
||||
setV6();
|
||||
return reinterpret_cast<uint16_t*>(ip_2_ip6(&_ip));
|
||||
}
|
||||
|
||||
const uint16_t* raw6() const
|
||||
{
|
||||
return isV6()? reinterpret_cast<const uint16_t*>(ip_2_ip6(&_ip)): nullptr;
|
||||
}
|
||||
|
||||
// when not IPv6, ip_addr_t == ip4_addr_t so this one would be ambiguous
|
||||
// required otherwise
|
||||
operator const ip4_addr_t*() const { return isV4()? ip_2_ip4(&_ip): nullptr; }
|
||||
|
||||
bool isV6() const { return IP_IS_V6_VAL(_ip); }
|
||||
void setV6() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V6); }
|
||||
|
||||
protected:
|
||||
bool fromString6(const char *address);
|
||||
|
||||
#else
|
||||
|
||||
// allow portable code when IPv6 is not enabled
|
||||
|
||||
uint16_t* raw6() { return nullptr; }
|
||||
const uint16_t* raw6() const { return nullptr; }
|
||||
bool isV6() const { return false; }
|
||||
void setV6() { }
|
||||
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool fromString4(const char *address);
|
||||
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
|
||||
friend ::EthernetClass;
|
||||
friend ::DhcpClass;
|
||||
friend ::DNSClient;
|
||||
};
|
||||
|
||||
extern const IPAddress INADDR_ANY;
|
||||
extern const IPAddress INADDR_NONE;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "RP2040USB.h"
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/multicore.h>
|
||||
#include "LWIPMutex.h"
|
||||
#include <reent.h>
|
||||
|
||||
RP2040 rp2040;
|
||||
|
|
@ -31,6 +32,8 @@ extern "C" {
|
|||
|
||||
mutex_t _pioMutex;
|
||||
|
||||
int LWIPMutex::_ref = 0;
|
||||
|
||||
extern void setup();
|
||||
extern void loop();
|
||||
|
||||
|
|
|
|||
319
cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c
Normal file
319
cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
// Taken from the Pico-SDK v1.4.0 and hacked by EFP3 to allow overriding the LWIP setup
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include "pico/mutex.h"
|
||||
#include "pico/sem.h"
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/irq.h"
|
||||
|
||||
#include "cyw43_stats.h"
|
||||
|
||||
#include <lwip/init.h>
|
||||
#include "lwip/timeouts.h"
|
||||
|
||||
#ifndef CYW43_PIN_WL_HOST_WAKE
|
||||
#define CYW43_PIN_WL_HOST_WAKE 24
|
||||
#endif
|
||||
|
||||
#ifndef CYW43_PIN_WL_REG_ON
|
||||
#define CYW43_PIN_WL_REG_ON 23
|
||||
#endif
|
||||
|
||||
#ifndef CYW43_WL_GPIO_COUNT
|
||||
#define CYW43_WL_GPIO_COUNT 3
|
||||
#endif
|
||||
|
||||
#ifndef CYW43_WL_GPIO_LED_PIN
|
||||
#define CYW43_WL_GPIO_LED_PIN 0
|
||||
#endif
|
||||
|
||||
|
||||
volatile bool __inLWIP = false;
|
||||
|
||||
// note same code
|
||||
#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND
|
||||
|
||||
#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && !NO_SYS
|
||||
#error PICO_CYW43_ARCH_THREADSAFE_BACKGROUND requires lwIP NO_SYS=1
|
||||
#endif
|
||||
#if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND && CYW43_LWIP && MEM_LIBC_MALLOC
|
||||
#error MEM_LIBC_MALLOC is incompatible with PICO_CYW43_ARCH_THREADSAFE_BACKGROUND
|
||||
#endif
|
||||
// todo right now we are now always doing a cyw43_dispatch along with a lwip one when hopping cores in low_prio_irq_schedule_dispatch
|
||||
|
||||
#ifndef CYW43_SLEEP_CHECK_MS
|
||||
#define CYW43_SLEEP_CHECK_MS 50 // How often to run lwip callback
|
||||
#endif
|
||||
static alarm_id_t periodic_alarm = -1;
|
||||
|
||||
static inline uint recursive_mutex_enter_count(recursive_mutex_t *mutex) {
|
||||
return mutex->enter_count;
|
||||
}
|
||||
|
||||
static inline lock_owner_id_t recursive_mutex_owner(recursive_mutex_t *mutex) {
|
||||
return mutex->owner;
|
||||
}
|
||||
|
||||
#define CYW43_GPIO_IRQ_HANDLER_PRIORITY 0x40
|
||||
|
||||
enum {
|
||||
CYW43_DISPATCH_SLOT_CYW43 = 0,
|
||||
CYW43_DISPATCH_SLOT_ADAPTER,
|
||||
CYW43_DISPATCH_SLOT_ENUM_COUNT
|
||||
};
|
||||
#ifndef CYW43_DISPATCH_SLOT_COUNT
|
||||
#define CYW43_DISPATCH_SLOT_COUNT CYW43_DISPATCH_SLOT_ENUM_COUNT
|
||||
#endif
|
||||
|
||||
typedef void (*low_prio_irq_dispatch_t)(void);
|
||||
static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f);
|
||||
|
||||
static uint8_t cyw43_core_num;
|
||||
#ifndef NDEBUG
|
||||
static bool in_low_priority_irq;
|
||||
#endif
|
||||
static uint8_t low_priority_irq_num;
|
||||
static bool low_priority_irq_missed;
|
||||
static low_prio_irq_dispatch_t low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_COUNT];
|
||||
static recursive_mutex_t cyw43_mutex;
|
||||
semaphore_t cyw43_irq_sem;
|
||||
|
||||
// Called in low priority pendsv interrupt only to do lwip processing and check cyw43 sleep
|
||||
static void periodic_worker(void) {
|
||||
#if CYW43_USE_STATS
|
||||
static uint32_t counter;
|
||||
if (counter++ % (30000 / LWIP_SYS_CHECK_MS) == 0) {
|
||||
cyw43_dump_stats();
|
||||
}
|
||||
#endif
|
||||
|
||||
CYW43_STAT_INC(LWIP_RUN_COUNT);
|
||||
//#if CYW43_LWIP
|
||||
if (!__inLWIP) {
|
||||
sys_check_timeouts();
|
||||
}
|
||||
//#endif
|
||||
if (cyw43_poll) {
|
||||
if (cyw43_sleep > 0) {
|
||||
if (--cyw43_sleep == 0) {
|
||||
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Regular callback to get lwip to check for timeouts
|
||||
static int64_t periodic_alarm_handler(__unused alarm_id_t id, __unused void *user_data) {
|
||||
// Do lwip processing in low priority pendsv interrupt
|
||||
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_ADAPTER, periodic_worker);
|
||||
return CYW43_SLEEP_CHECK_MS * 1000;
|
||||
}
|
||||
|
||||
void cyw43_await_background_or_timeout_us(uint32_t timeout_us) {
|
||||
// if we are called from within an IRQ, then don't wait (we are only ever called in a polling loop)
|
||||
if (!__get_current_exception()) {
|
||||
sem_acquire_timeout_us(&cyw43_irq_sem, timeout_us);
|
||||
}
|
||||
}
|
||||
|
||||
// GPIO interrupt handler to tell us there's cyw43 has work to do
|
||||
static void gpio_irq_handler(void) {
|
||||
uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE);
|
||||
if (events & GPIO_IRQ_LEVEL_HIGH) {
|
||||
// As we use a high level interrupt, it will go off forever until it's serviced
|
||||
// So disable the interrupt until this is done. It's re-enabled again by CYW43_POST_POLL_HOOK
|
||||
// which is called at the end of cyw43_poll_func
|
||||
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
|
||||
// also clear the force bit which we use to progratically cause this handler to fire (on the right core)
|
||||
io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
|
||||
&iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
hw_clear_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE / 8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7)));
|
||||
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
|
||||
CYW43_STAT_INC(IRQ_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
// Low priority interrupt handler to perform background processing
|
||||
static void low_priority_irq_handler(void) {
|
||||
assert(cyw43_core_num == get_core_num());
|
||||
if (recursive_mutex_try_enter(&cyw43_mutex, NULL)) {
|
||||
if (recursive_mutex_enter_count(&cyw43_mutex) != 1) {
|
||||
low_priority_irq_missed = true;
|
||||
CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
|
||||
} else {
|
||||
CYW43_STAT_INC(PENDSV_RUN_COUNT);
|
||||
#ifndef NDEBUG
|
||||
in_low_priority_irq = true;
|
||||
#endif
|
||||
for (size_t i = 0; i < count_of(low_priority_irq_dispatch_slots); i++) {
|
||||
if (low_priority_irq_dispatch_slots[i] != NULL) {
|
||||
low_prio_irq_dispatch_t f = low_priority_irq_dispatch_slots[i];
|
||||
low_priority_irq_dispatch_slots[i] = NULL;
|
||||
f();
|
||||
}
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
in_low_priority_irq = false;
|
||||
#endif
|
||||
}
|
||||
recursive_mutex_exit(&cyw43_mutex);
|
||||
} else {
|
||||
CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
|
||||
low_priority_irq_missed = true;
|
||||
}
|
||||
sem_release(&cyw43_irq_sem);
|
||||
}
|
||||
|
||||
static bool low_prio_irq_init(uint8_t priority) {
|
||||
assert(get_core_num() == cyw43_core_num);
|
||||
int irq = user_irq_claim_unused(false);
|
||||
if (irq < 0) {
|
||||
return false;
|
||||
}
|
||||
low_priority_irq_num = (uint8_t) irq;
|
||||
irq_set_exclusive_handler(low_priority_irq_num, low_priority_irq_handler);
|
||||
irq_set_enabled(low_priority_irq_num, true);
|
||||
irq_set_priority(low_priority_irq_num, priority);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void low_prio_irq_deinit(void) {
|
||||
if (low_priority_irq_num > 0) {
|
||||
irq_set_enabled(low_priority_irq_num, false);
|
||||
irq_remove_handler(low_priority_irq_num, low_priority_irq_handler);
|
||||
user_irq_unclaim(low_priority_irq_num);
|
||||
low_priority_irq_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cyw43_arch_init(void) {
|
||||
cyw43_core_num = get_core_num();
|
||||
recursive_mutex_init(&cyw43_mutex);
|
||||
cyw43_init(&cyw43_state);
|
||||
sem_init(&cyw43_irq_sem, 0, 1);
|
||||
|
||||
// Start regular lwip callback to handle timeouts
|
||||
periodic_alarm = add_alarm_in_us(CYW43_SLEEP_CHECK_MS * 1000, periodic_alarm_handler, NULL, true);
|
||||
if (periodic_alarm < 0) {
|
||||
return PICO_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_GPIO_IRQ_HANDLER_PRIORITY);
|
||||
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
|
||||
irq_set_enabled(IO_IRQ_BANK0, true);
|
||||
|
||||
lwip_init();
|
||||
|
||||
// start low priority handler (no background work is done before this)
|
||||
bool ok = low_prio_irq_init(PICO_LOWEST_IRQ_PRIORITY);
|
||||
if (!ok) {
|
||||
cyw43_arch_deinit();
|
||||
return PICO_ERROR_GENERIC;
|
||||
}
|
||||
return PICO_OK;
|
||||
}
|
||||
|
||||
void cyw43_arch_deinit(void) {
|
||||
if (periodic_alarm >= 0) {
|
||||
cancel_alarm(periodic_alarm);
|
||||
periodic_alarm = -1;
|
||||
}
|
||||
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, false);
|
||||
gpio_remove_raw_irq_handler(IO_IRQ_BANK0, gpio_irq_handler);
|
||||
low_prio_irq_deinit();
|
||||
}
|
||||
|
||||
void cyw43_post_poll_hook(void) {
|
||||
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
|
||||
}
|
||||
|
||||
// This is called in the gpio and low_prio_irq interrupts and on either core
|
||||
static void low_prio_irq_schedule_dispatch(size_t slot, low_prio_irq_dispatch_t f) {
|
||||
assert(slot < count_of(low_priority_irq_dispatch_slots));
|
||||
low_priority_irq_dispatch_slots[slot] = f;
|
||||
if (cyw43_core_num == get_core_num()) {
|
||||
//on same core, can dispatch directly
|
||||
irq_set_pending(low_priority_irq_num);
|
||||
} else {
|
||||
// on wrong core, so force via GPIO IRQ which itself calls this method for the CYW43 slot.
|
||||
// since the CYW43 slot always uses the same function, this is fine with the addition of an
|
||||
// extra (but harmless) CYW43 slot call when another SLOT is invoked.
|
||||
// We could do better, but would have to track why the IRQ was called.
|
||||
io_irq_ctrl_hw_t *irq_ctrl_base = cyw43_core_num ?
|
||||
&iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
hw_set_bits(&irq_ctrl_base->intf[CYW43_PIN_WL_HOST_WAKE / 8], GPIO_IRQ_LEVEL_HIGH << (4 * (CYW43_PIN_WL_HOST_WAKE & 7)));
|
||||
}
|
||||
}
|
||||
|
||||
void cyw43_schedule_internal_poll_dispatch(void (*func)(void)) {
|
||||
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, func);
|
||||
}
|
||||
|
||||
// Prevent background processing in pensv and access by the other core
|
||||
// These methods are called in pensv context and on either core
|
||||
// They can be called recursively
|
||||
void cyw43_thread_enter(void) {
|
||||
// Lock the other core and stop low_prio_irq running
|
||||
recursive_mutex_enter_blocking(&cyw43_mutex);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void cyw43_thread_lock_check(void) {
|
||||
// Lock the other core and stop low_prio_irq running
|
||||
if (recursive_mutex_enter_count(&cyw43_mutex) < 1 || recursive_mutex_owner(&cyw43_mutex) != lock_get_caller_owner_id()) {
|
||||
panic("cyw43_thread_lock_check failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Re-enable background processing
|
||||
void cyw43_thread_exit(void) {
|
||||
// Run low_prio_irq if needed
|
||||
if (1 == recursive_mutex_enter_count(&cyw43_mutex)) {
|
||||
// note the outer release of the mutex is not via cyw43_exit in the low_priority_irq case (it is a direct mutex exit)
|
||||
assert(!in_low_priority_irq);
|
||||
// if (low_priority_irq_missed) {
|
||||
// low_priority_irq_missed = false;
|
||||
if (low_priority_irq_dispatch_slots[CYW43_DISPATCH_SLOT_CYW43]) {
|
||||
low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
|
||||
}
|
||||
// }
|
||||
}
|
||||
recursive_mutex_exit(&cyw43_mutex);
|
||||
}
|
||||
|
||||
|
||||
static void cyw43_delay_until(absolute_time_t until) {
|
||||
// sleep can be called in IRQs, so there's not much we can do there
|
||||
if (__get_current_exception()) {
|
||||
busy_wait_until(until);
|
||||
} else {
|
||||
sleep_until(until);
|
||||
}
|
||||
}
|
||||
|
||||
void cyw43_delay_ms(uint32_t ms) {
|
||||
cyw43_delay_until(make_timeout_time_ms(ms));
|
||||
}
|
||||
|
||||
void cyw43_delay_us(uint32_t us) {
|
||||
cyw43_delay_until(make_timeout_time_us(us));
|
||||
}
|
||||
|
||||
void cyw43_arch_poll() {
|
||||
// should not be necessary
|
||||
// if (cyw43_poll) {
|
||||
// low_prio_irq_schedule_dispatch(CYW43_DISPATCH_SLOT_CYW43, cyw43_poll);
|
||||
// }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -19,8 +19,7 @@
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef STDLIB_NONISO_H
|
||||
#define STDLIB_NONISO_H
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -54,6 +53,3 @@ const char* strrstr(const char*__restrict p_pcString,
|
|||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
|
||||
static PinMode _pm[30];
|
||||
|
||||
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) __attribute__((weak, alias("__pinMode")));
|
||||
extern "C" void __pinMode(pin_size_t ulPin, PinMode ulMode) {
|
||||
switch (ulMode) {
|
||||
case INPUT:
|
||||
gpio_init(ulPin);
|
||||
|
|
@ -76,7 +77,8 @@ extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
|
|||
_pm[ulPin] = ulMode;
|
||||
}
|
||||
|
||||
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) __attribute__((weak, alias("__digitalWrite")));
|
||||
extern "C" void __digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
|
||||
return;
|
||||
|
|
@ -99,7 +101,8 @@ extern "C" void digitalWrite(pin_size_t ulPin, PinStatus ulVal) {
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" PinStatus digitalRead(pin_size_t ulPin) {
|
||||
extern "C" PinStatus digitalRead(pin_size_t ulPin) __attribute__((weak, alias("__digitalRead")));
|
||||
extern "C" PinStatus __digitalRead(pin_size_t ulPin) {
|
||||
if (ulPin > 29) {
|
||||
DEBUGCORE("ERROR: Illegal pin in digitalRead (%d)\n", ulPin);
|
||||
return LOW;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Arduino-Pico. Arduino-Pico is a community port of the RP2040
|
|||
to make it easier and more fun to use and program the Raspberry Pi
|
||||
Pico / RP2040 based boards.
|
||||
|
||||
This Arduino core uses a custom toolset with GCC 10.2 and Newlib 4.0.0
|
||||
This Arduino core uses a custom toolset with GCC 10.3 and Newlib 4.0.0
|
||||
and doesn't require any system-installed prerequisites.
|
||||
|
||||
For the latest version, always check https://github.com/earlephilhower/arduino-pico
|
||||
|
|
@ -39,6 +39,8 @@ For the latest version, always check https://github.com/earlephilhower/arduino-p
|
|||
|
||||
FreeRTOS SMP (multicore) <freertos>
|
||||
|
||||
WiFi (Raspberry Pi Pico-W Support) <wifi>
|
||||
|
||||
Ported/Optimized Libraries <libraries>
|
||||
Using Pico-SDK <sdk>
|
||||
|
||||
|
|
|
|||
47
docs/wifi.rst
Normal file
47
docs/wifi.rst
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
WiFi (Raspberry Pi Pico W) Support
|
||||
==================================
|
||||
|
||||
WiFi is supported on the Raspberry Pi Pico W by selecting the "Raspbery Pi Pico W" board in the Boards Manager. It is generally compatible with the `Arduino WiFi library <https://www.arduino.cc/en/Reference/WiFi>`__ and the `ESP8266 Arduino WiFi library <https://github.com/esp8266/Arduino>`__.
|
||||
|
||||
Enable WiFi support by selecting the `Raspberry Pi Pico W` board in the IDE and adding ``#include <WiFi.h>`` in your sketch.
|
||||
|
||||
Supported Features
|
||||
------------------
|
||||
* WiFi connection (Open, WPA/WPA2)
|
||||
* Static IP or dynamic DHCP supported
|
||||
* Station Mode (STA, connects to an existing network)
|
||||
* Access Point Mode (AP, creates its own wireless network) with 4 clients
|
||||
* WiFi Scanning and Reporting
|
||||
* See the ``ScanNetworks.ino`` example to better understand the process.
|
||||
* `WiFiClient (TCP/IP client) <wificlient.rst>`__
|
||||
* See the ``WiFiClient.ino`` example which connects the Pico W to a remote internet service and retrieves some data
|
||||
* `WiFiServer (TCP/IP server) <wifiserver.rst>`__
|
||||
* See the ``WiFiServer.ino`` example which implements a frientdy TCP/IP server
|
||||
* `WiFiUDP (UDP packet input/output) <wifiudp.rst>`__
|
||||
* See the ``UDP.ino`` example for a simple send/receive UDP application
|
||||
|
||||
In the near future TLS (SSL/https) encryption is planned, but is not yet implemented.
|
||||
|
||||
Important Information
|
||||
---------------------
|
||||
Please note that WiFi on the Pico W is a work-in-progress and there are some important caveats:
|
||||
* Adding WiFi increases flash usage by > 220KB.
|
||||
* There is a binary firmware blob for the WiFi chip (CYW43-series) which the Pico W uses. It's 220KB of code that needs to be included in any Pico W sketch, even one that simply flashes the onboard LED. There are hopes to reduce this via compression (see `this issue <https://github.com/raspberrypi/pico-sdk/issues/909>`__ )
|
||||
* Adding WiFi increases RAM usage by ~40KB.
|
||||
* LWIP, the TCP/IP driver, requires preallocated buffers to allow it to run in non-polling mode (i.e. packets can be sent and received in the background without the application needing to explicitly do anything).
|
||||
* The WiFi driver is a little limited as of now, but fully functional for sending and receiving data
|
||||
* Extensible Authentication Protocol (EAP) is not supported
|
||||
* Combined STA/AP mode is not supported
|
||||
* Certain WiFi status values (RSSI, BSSID, etc.) are not available.
|
||||
* Multicore is supported, but only one core may run ``WiFi`` code.
|
||||
* FreeRTOS is not yet supported due to the requirement for a very different LWIP implementation. PRs always appreciated!
|
||||
|
||||
The WiFi library borrows much work from the `ESP8266 Arduino Core <https://github.com/esp8266/Arduino>`__ , especially the ``WiFiClient`` and ``WiFiServer`` classes.
|
||||
|
||||
Special Thanks
|
||||
--------------
|
||||
|
||||
Special thanks to:
|
||||
* @todbot for donating one of his Pico W boards to the effort
|
||||
* @d-a-v for much patient explanation about LWIP internals
|
||||
* The whole ESP8266 Arduino team for their network classes
|
||||
110
docs/wificlient.rst
Normal file
110
docs/wificlient.rst
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
:orphan:
|
||||
|
||||
Client Class
|
||||
------------
|
||||
|
||||
Methods documented for `Client <https://www.arduino.cc/en/Reference/WiFiClientConstructor>`__ in `Arduino <https://github.com/arduino/Arduino>`__
|
||||
|
||||
1. `WiFiClient() <https://www.arduino.cc/en/Reference/WiFiClient>`__
|
||||
2. `connected() <https://www.arduino.cc/en/Reference/WiFiClientConnected>`__
|
||||
3. `connect() <https://www.arduino.cc/en/Reference/WiFiClientConnect>`__
|
||||
4. `write() <https://www.arduino.cc/en/Reference/WiFiClientWrite>`__
|
||||
5. `print() <https://www.arduino.cc/en/Reference/WiFiClientPrint>`__
|
||||
6. `println() <https://www.arduino.cc/en/Reference/WiFiClientPrintln>`__
|
||||
7. `available() <https://www.arduino.cc/en/Reference/WiFiClientAvailable>`__
|
||||
8. `read() <https://www.arduino.cc/en/Reference/WiFiClientRead>`__
|
||||
9. `flush() <https://www.arduino.cc/en/Reference/WiFiClientFlush>`__
|
||||
10. `stop() <https://www.arduino.cc/en/Reference/WiFIClientStop>`__
|
||||
|
||||
Methods and properties described further down are specific to ESP8266. They are not covered in `Arduino WiFi library <https://www.arduino.cc/en/Reference/WiFi>`__ documentation. Before they are fully documented please refer to information below.
|
||||
|
||||
flush and stop
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
``flush(timeoutMs)`` and ``stop(timeoutMs)`` both have now an optional argument: ``timeout`` in millisecond, and both return a boolean.
|
||||
|
||||
Default input value 0 means that effective value is left at the discretion of the implementer.
|
||||
|
||||
``flush()`` returning ``true`` indicates that output data have effectively been sent, and ``false`` that a timeout has occurred.
|
||||
|
||||
``stop()`` returns ``false`` in case of an issue when closing the client (for instance a timed-out ``flush``). Depending on implementation, its parameter can be passed to ``flush()``.
|
||||
|
||||
setNoDelay
|
||||
~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
setNoDelay(nodelay)
|
||||
|
||||
With ``nodelay`` set to ``true``, this function will to disable `Nagle algorithm <https://en.wikipedia.org/wiki/Nagle%27s_algorithm>`__.
|
||||
|
||||
This algorithm is intended to reduce TCP/IP traffic of small packets sent over the network by combining a number of small outgoing messages, and sending them all at once. The downside of such approach is effectively delaying individual messages until a big enough packet is assembled.
|
||||
|
||||
*Example:*
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
client.setNoDelay(true);
|
||||
|
||||
getNoDelay
|
||||
~~~~~~~~~~
|
||||
|
||||
Returns whether NoDelay is enabled or not for the current connection.
|
||||
|
||||
setSync
|
||||
~~~~~~~
|
||||
|
||||
This is an experimental API that will set the client in synchronized mode.
|
||||
In this mode, every ``write()`` is flushed. It means that after a call to
|
||||
``write()``, data are ensured to be received where they went sent to (that is
|
||||
``flush`` semantic).
|
||||
|
||||
When set to ``true`` in ``WiFiClient`` implementation,
|
||||
|
||||
- It slows down transfers, and implicitly disable the Nagle algorithm.
|
||||
|
||||
- It also allows to avoid a temporary copy of data that otherwise consumes
|
||||
at most ``TCP_SND_BUF`` = (2 * ``MSS``) bytes per connection,
|
||||
|
||||
getSync
|
||||
~~~~~~~
|
||||
|
||||
Returns whether Sync is enabled or not for the current connection.
|
||||
|
||||
setDefaultNoDelay and setDefaultSync
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These set the default value for both ``setSync`` and ``setNoDelay`` for
|
||||
every future instance of ``WiFiClient`` (including those coming from
|
||||
``WiFiServer.available()`` by default).
|
||||
|
||||
Default values are false for both ``NoDelay`` and ``Sync``.
|
||||
|
||||
This means that Nagle is enabled by default *for all new connections*.
|
||||
|
||||
getDefaultNoDelay and getDefaultSync
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Return the values to be used as default for NoDelay and Sync for all future connections.
|
||||
|
||||
Other Function Calls
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
uint8_t status ()
|
||||
virtual size_t write (const uint8_t *buf, size_t size)
|
||||
size_t write_P (PGM_P buf, size_t size)
|
||||
size_t write (Stream &stream)
|
||||
size_t write (Stream &stream, size_t unitSize) __attribute__((deprecated))
|
||||
virtual int read (uint8_t *buf, size_t size)
|
||||
virtual int peek ()
|
||||
virtual size_t peekBytes (uint8_t *buffer, size_t length)
|
||||
size_t peekBytes (char *buffer, size_t length)
|
||||
virtual operator bool ()
|
||||
IPAddress remoteIP ()
|
||||
uint16_t remotePort ()
|
||||
IPAddress localIP ()
|
||||
uint16_t localPort ()
|
||||
|
||||
Documentation for the above functions is not yet available.
|
||||
75
docs/wifiserver.rst
Normal file
75
docs/wifiserver.rst
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
:orphan:
|
||||
|
||||
Server Class
|
||||
------------
|
||||
|
||||
Methods documented for the `Server Class <https://www.arduino.cc/en/Reference/WiFiServerConstructor>`__ in `Arduino <https://github.com/arduino/Arduino>`__
|
||||
|
||||
1. `WiFiServer() <https://www.arduino.cc/en/Reference/WiFiServer>`__
|
||||
2. `begin() <https://www.arduino.cc/en/Reference/WiFiServerBegin>`__
|
||||
3. `available() <https://www.arduino.cc/en/Reference/WiFiServerAvailable>`__
|
||||
4. `write() <https://www.arduino.cc/en/Reference/WiFiServerWrite>`__
|
||||
5. `print() <https://www.arduino.cc/en/Reference/WiFiServerPrint>`__
|
||||
6. `println() <https://www.arduino.cc/en/Reference/WiFiServerPrintln>`__
|
||||
|
||||
In ESP8266WiFi library the ``ArduinoWiFiServer`` class implements ``available`` and the write-to-all-clients functionality as described in the Arduino WiFi library reference. The PageServer example shows how ``available`` and the write-to-all-clients works.
|
||||
|
||||
For most use cases the basic WiFiServer class of the ESP8266WiFi library is suitable.
|
||||
|
||||
Methods and properties described further down are specific to ESP8266. They are not covered in `Arduino WiFi library <https://www.arduino.cc/en/Reference/WiFi>`__ documentation. Before they are fully documented please refer to information below.
|
||||
|
||||
accept
|
||||
~~~~~~
|
||||
|
||||
Method ``accept()`` returns a waiting client connection. `accept() is documented <https://www.arduino.cc/en/Reference/EthernetServerAccept>`__ for the Arduino Ethernet library.
|
||||
|
||||
available
|
||||
~~~~~~~~~
|
||||
see ``accept``
|
||||
|
||||
``available`` in the ESP8266WiFi library's WiFiServer class doesn't work as documented for the Arduino WiFi library. It works the same way as ``accept``.
|
||||
|
||||
write (write to all clients) not supported
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Please note that the ``write`` method on the ``WiFiServer`` object is not implemented and returns failure always. Use the returned
|
||||
``WiFiClient`` object from the ``WiFiServer::accept()`` method to communicate with individual clients. If you need to send
|
||||
the exact same packets to a series of clients, your application must maintain a list of connected clients and iterate over them manually.
|
||||
|
||||
setNoDelay
|
||||
~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
setNoDelay(nodelay)
|
||||
|
||||
With ``nodelay`` set to ``true``, this function will to disable `Nagle algorithm <https://en.wikipedia.org/wiki/Nagle%27s_algorithm>`__.
|
||||
|
||||
This algorithm is intended to reduce TCP/IP traffic of small packets sent over the network by combining a number of small outgoing messages, and sending them all at once. The downside of such approach is effectively delaying individual messages until a big enough packet is assembled.
|
||||
|
||||
*Example:*
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
server.begin();
|
||||
server.setNoDelay(true);
|
||||
|
||||
By default, ``nodelay`` value will depends on global ``WiFiClient::getDefaultNoDelay()`` (currently false by default).
|
||||
|
||||
However, a call to ``wiFiServer.setNoDelay()`` will override ``NoDelay`` for all new ``WiFiClient`` provided by the calling instance (``wiFiServer``).
|
||||
|
||||
Other Function Calls
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
bool hasClient ()
|
||||
size_t hasClientData ()
|
||||
bool hasMaxPendingClients ()
|
||||
bool getNoDelay ()
|
||||
virtual size_t write (const uint8_t *buf, size_t size)
|
||||
uint8_t status ()
|
||||
void close ()
|
||||
void stop ()
|
||||
|
||||
Documentation for the above functions is not yet prepared.
|
||||
19
docs/wifiudp.rst
Normal file
19
docs/wifiudp.rst
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
:orphan:
|
||||
|
||||
UDP Class
|
||||
---------
|
||||
|
||||
Methods documented for `WiFiUDP Class <https://www.arduino.cc/en/Reference/WiFiUDPConstructor>`__ in `Arduino <https://github.com/arduino/Arduino>`__
|
||||
|
||||
1. `begin() <https://www.arduino.cc/en/Reference/WiFiUDPBegin>`__
|
||||
2. `available() <https://www.arduino.cc/en/Reference/WiFiUDPAvailable>`__
|
||||
3. `beginPacket() <https://www.arduino.cc/en/Reference/WiFiUDPBeginPacket>`__
|
||||
4. `endPacket() <https://www.arduino.cc/en/Reference/WiFiUDPEndPacket>`__
|
||||
5. `write() <https://www.arduino.cc/en/Reference/WiFiUDPWrite>`__
|
||||
6. `parsePacket() <https://www.arduino.cc/en/Reference/WiFiUDPParsePacket>`__
|
||||
7. `peek() <https://www.arduino.cc/en/Reference/WiFiUDPPeek>`__
|
||||
8. `read() <https://www.arduino.cc/en/Reference/WiFiUDPRead>`__
|
||||
9. `flush() <https://www.arduino.cc/en/Reference/WiFiUDPFlush>`__
|
||||
10. `stop() <https://www.arduino.cc/en/Reference/WiFIUDPStop>`__
|
||||
11. `remoteIP() <https://www.arduino.cc/en/Reference/WiFiUDPRemoteIP>`__
|
||||
12. `remotePort() <https://www.arduino.cc/en/Reference/WiFiUDPRemotePort>`__
|
||||
BIN
lib/libpico.a
BIN
lib/libpico.a
Binary file not shown.
|
|
@ -92,7 +92,7 @@ SECTIONS
|
|||
} > FLASH
|
||||
|
||||
.rodata : {
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
|
||||
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata* .big_const*)
|
||||
. = ALIGN(4);
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
|
||||
. = ALIGN(4);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#define _PICO_VERSION_H
|
||||
|
||||
#define PICO_SDK_VERSION_MAJOR 1
|
||||
#define PICO_SDK_VERSION_MINOR 3
|
||||
#define PICO_SDK_VERSION_REVISION 2
|
||||
#define PICO_SDK_VERSION_STRING "1.3.2-develop"
|
||||
#define PICO_SDK_VERSION_MINOR 4
|
||||
#define PICO_SDK_VERSION_REVISION 0
|
||||
#define PICO_SDK_VERSION_STRING "1.4.0"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,9 +40,11 @@
|
|||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_watchdog/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/hardware_xosc/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_bootrom/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_cyw43_arch/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_double/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_float/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_int64_ops/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_lwip/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_multicore/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_platform/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_printf/include
|
||||
|
|
@ -50,3 +52,5 @@
|
|||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_stdio_uart/include
|
||||
-iwithprefixbefore/pico-sdk/src/rp2_common/pico_unique_id/include
|
||||
-iwithprefixbefore/pico-sdk/lib/cyw43-driver/src
|
||||
-iwithprefixbefore/pico-sdk/lib/lwip/src/include
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 122544ce7346a81beac52347d88509b788ecadd6
|
||||
Subproject commit 5be0b21c0a5cf396b139bce0c6c0d403df051b0a
|
||||
|
|
@ -8,3 +8,4 @@ category=Timing
|
|||
url=https://github.com/FreeRTOS/FreeRTOS-Kernel
|
||||
architectures=rp2040
|
||||
license=MIT
|
||||
dot_a_linkage=true
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ paragraph=
|
|||
category=Communication
|
||||
url=http://www.arduino.cc/en/Reference/I2S
|
||||
architectures=rp2040
|
||||
|
||||
dot_a_linkage=true
|
||||
|
|
|
|||
42
libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino
Normal file
42
libraries/WiFi/examples/ScanNetworks/ScanNetworks.ino
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Simple WiFi network scanner application
|
||||
// Released to the public domain in 2022 by Earle F. Philhower, III
|
||||
#include <WiFi.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
}
|
||||
|
||||
const char *macToString(uint8_t mac[6]) {
|
||||
static char s[20];
|
||||
sprintf(s, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return s;
|
||||
}
|
||||
|
||||
const char *encToString(uint8_t enc) {
|
||||
switch (enc) {
|
||||
case ENC_TYPE_NONE: return "NONE";
|
||||
case ENC_TYPE_TKIP: return "WPA";
|
||||
case ENC_TYPE_CCMP: return "WPA2";
|
||||
case ENC_TYPE_AUTO: return "AUTO";
|
||||
}
|
||||
return "UNKN";
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(5000);
|
||||
Serial.printf("Beginning scan at %d\n", millis());
|
||||
auto cnt = WiFi.scanNetworks();
|
||||
if (!cnt) {
|
||||
Serial.printf("No networks found\n");
|
||||
} else {
|
||||
Serial.printf("Found %d networks\n\n", cnt);
|
||||
Serial.printf("%32s %5s %17s %2s %4s\n", "SSID", "ENC", "BSSID ", "CH", "RSSI");
|
||||
for (auto i = 0; i < cnt; i++) {
|
||||
uint8_t bssid[6];
|
||||
WiFi.BSSID(i, bssid);
|
||||
Serial.printf("%32s %5s %17s %2d %4d\n", WiFi.SSID(i), encToString(WiFi.encryptionType(i)), macToString(bssid), WiFi.channel(i), WiFi.RSSI(i));
|
||||
}
|
||||
}
|
||||
Serial.printf("\n--- Sleeping ---\n\n\n");
|
||||
delay(5000);
|
||||
}
|
||||
70
libraries/WiFi/examples/Udp/Udp.ino
Normal file
70
libraries/WiFi/examples/Udp/Udp.ino
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
UDPSendReceive.pde:
|
||||
This sketch receives UDP message strings, prints them to the serial port
|
||||
and sends an "acknowledge" string back to the sender
|
||||
|
||||
A Processing sketch is included at the end of file that can be used to send
|
||||
and received messages for testing with a computer.
|
||||
|
||||
created 21 Aug 2010
|
||||
by Michael Margolis
|
||||
|
||||
This code is in the public domain.
|
||||
|
||||
adapted from Ethernet library examples
|
||||
*/
|
||||
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
unsigned int localPort = 8888; // local port to listen on
|
||||
|
||||
// buffers for receiving and sending data
|
||||
char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; // buffer to hold incoming packet,
|
||||
char ReplyBuffer[] = "acknowledged\r\n"; // a string to send back
|
||||
|
||||
WiFiUDP Udp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(STASSID, STAPSK);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
Serial.print("Connected! IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.printf("UDP server on port %d\n", localPort);
|
||||
Udp.begin(localPort);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// if there's data available, read a packet
|
||||
int packetSize = Udp.parsePacket();
|
||||
if (packetSize) {
|
||||
Serial.printf("Received packet of size %d from %s:%d\n (to %s:%d)\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort(), Udp.destinationIP().toString().c_str(), Udp.localPort());
|
||||
|
||||
// read the packet into packetBufffer
|
||||
int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
|
||||
packetBuffer[n] = 0;
|
||||
Serial.println("Contents:");
|
||||
Serial.println(packetBuffer);
|
||||
|
||||
// send a reply, to the IP address and port that sent us the packet we received
|
||||
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
|
||||
Udp.write(ReplyBuffer);
|
||||
Udp.endPacket();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
test (shell/netcat):
|
||||
--------------------
|
||||
nc -u 192.168.pico.address 8888
|
||||
*/
|
||||
92
libraries/WiFi/examples/WiFiClient/WiFiClient.ino
Normal file
92
libraries/WiFi/examples/WiFiClient/WiFiClient.ino
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
This sketch establishes a TCP connection to a "quote of the day" service.
|
||||
It sends a "hello" message, and then prints received data.
|
||||
*/
|
||||
|
||||
#include <WiFi.h>
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
const char* host = "djxmmx.net";
|
||||
const uint16_t port = 17;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// We start by connecting to a WiFi network
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static bool wait = false;
|
||||
|
||||
Serial.print("connecting to ");
|
||||
Serial.print(host);
|
||||
Serial.print(':');
|
||||
Serial.println(port);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, port)) {
|
||||
Serial.println("connection failed");
|
||||
delay(5000);
|
||||
return;
|
||||
}
|
||||
|
||||
// This will send a string to the server
|
||||
Serial.println("sending data to server");
|
||||
if (client.connected()) {
|
||||
client.println("hello from ESP8266");
|
||||
}
|
||||
|
||||
// wait for data to be available
|
||||
unsigned long timeout = millis();
|
||||
while (client.available() == 0) {
|
||||
if (millis() - timeout > 5000) {
|
||||
Serial.println(">>> Client Timeout !");
|
||||
client.stop();
|
||||
delay(60000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
Serial.println("receiving from remote server");
|
||||
// not testing 'client.connected()' since we do not need to send data here
|
||||
while (client.available()) {
|
||||
char ch = static_cast<char>(client.read());
|
||||
Serial.print(ch);
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
Serial.println();
|
||||
Serial.println("closing connection");
|
||||
client.stop();
|
||||
|
||||
if (wait) {
|
||||
delay(300000); // execute once every 5 minutes, don't flood remote service
|
||||
}
|
||||
wait = true;
|
||||
}
|
||||
49
libraries/WiFi/examples/WiFiServer/WiFiServer.ino
Normal file
49
libraries/WiFi/examples/WiFiServer/WiFiServer.ino
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Placed in the public domain by Earle F. Philhower, III, 2022
|
||||
|
||||
#include <WiFi.h>
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
int port = 4242;
|
||||
|
||||
WiFiServer server(port);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.setHostname("PicoW2");
|
||||
Serial.printf("Connecting to '%s' with '%s'\n", ssid, password);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(100);
|
||||
}
|
||||
Serial.printf("\nConnected to WiFi\n\nConnect to server at %s:%d\n", WiFi.localIP().toString().c_str(), port);
|
||||
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static int i;
|
||||
delay(1000);
|
||||
Serial.printf("--loop %d\n", ++i);
|
||||
delay(10);
|
||||
WiFiClient client = server.available();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
client.println("Type anything and hit return");
|
||||
while (!client.available()) {
|
||||
delay(10);
|
||||
}
|
||||
String req = client.readStringUntil('\n');
|
||||
Serial.println(req);
|
||||
client.printf("Hello from Pico-W\r\n");
|
||||
client.flush();
|
||||
}
|
||||
67
libraries/WiFi/keywords.txt
Normal file
67
libraries/WiFi/keywords.txt
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map For WiFiNINA
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Library (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
WiFi KEYWORD1
|
||||
WiFiPico KEYWORD1
|
||||
WiFiUdp KEYWORD1
|
||||
WiFiClient KEYWORD1
|
||||
WiFiSSLClient KEYWORD1
|
||||
WiFiServer KEYWORD1
|
||||
WiFiUDP KEYWORD1
|
||||
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
firmwareVersion KEYWORD2
|
||||
status KEYWORD2
|
||||
reasonCode KEYWORD2
|
||||
connect KEYWORD2
|
||||
write KEYWORD2
|
||||
available KEYWORD2
|
||||
config KEYWORD2
|
||||
setDNS KEYWORD2
|
||||
read KEYWORD2
|
||||
flush KEYWORD2
|
||||
stop KEYWORD2
|
||||
connected KEYWORD2
|
||||
begin KEYWORD2
|
||||
disconnect KEYWORD2
|
||||
macAddress KEYWORD2
|
||||
localIP KEYWORD2
|
||||
subnetMask KEYWORD2
|
||||
gatewayIP KEYWORD2
|
||||
SSID KEYWORD2
|
||||
BSSID KEYWORD2
|
||||
RSSI KEYWORD2
|
||||
encryptionType KEYWORD2
|
||||
beginPacket KEYWORD2
|
||||
endPacket KEYWORD2
|
||||
parsePacket KEYWORD2
|
||||
remoteIP KEYWORD2
|
||||
remotePort KEYWORD2
|
||||
mode KEYWORD2
|
||||
|
||||
beginAP KEYWORD2
|
||||
beginEnterprise KEYWORD2
|
||||
setHostname KEYWORD2
|
||||
end KEYWORD2
|
||||
getTime KEYWORD2
|
||||
lowPowerMode KEYWORD2
|
||||
noLowPowerMode KEYWORD2
|
||||
ping KEYWORD2
|
||||
beginMulticast KEYWORD2
|
||||
setTimeout KEYWORD2
|
||||
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
WIFI_STA LITERAL1
|
||||
WIFI_AP LITERAL1
|
||||
11
libraries/WiFi/library.properties
Normal file
11
libraries/WiFi/library.properties
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
name=WiFi
|
||||
version=1.0.0
|
||||
author=Earle F. Philhower, III
|
||||
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
sentence=Enables network connection (local and Internet) with the Raspberry Pi Pico W RP2040
|
||||
paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through WiFi. The board can connect either to open or encrypted networks (WEP, WPA). The IP address can be assigned statically or through a DHCP. The library can also manage DNS.
|
||||
category=Communication
|
||||
url=http://github.com/earlephilhower/arduino-pico
|
||||
architectures=rp2040
|
||||
includes=WiFi.h
|
||||
dot_a_linkage=true
|
||||
2
libraries/WiFi/src/ESP8266WiFi.h
Normal file
2
libraries/WiFi/src/ESP8266WiFi.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Since things may just work, we'll redirect for now
|
||||
#include "WiFi.h"
|
||||
13
libraries/WiFi/src/WiFi.h
Normal file
13
libraries/WiFi/src/WiFi.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "wl_definitions.h"
|
||||
#include "wl_types.h"
|
||||
|
||||
#include "LWIPMutex.h"
|
||||
|
||||
#include "WiFiClass.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiServer.h"
|
||||
//#include "WiFiClientSecure.h"
|
||||
//#include "WiFiServerSecure.h"
|
||||
#include "WiFiUdp.h"
|
||||
543
libraries/WiFi/src/WiFiClass.cpp
Normal file
543
libraries/WiFi/src/WiFiClass.cpp
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
WiFiClass.cpp - WiFi class "compat" w/WiFiNINA for Raspberry Pi Pico W
|
||||
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
Implements the API defined by the Arduino WiFiNINA library,
|
||||
copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <pico/cyw43_arch.h>
|
||||
#include <cyw43.h>
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include <map>
|
||||
#include "WiFi.h"
|
||||
|
||||
// This is the real WiFi network object, we just tickle it to do our magic
|
||||
#include <LwipEthernet.h>
|
||||
static CYW43lwIP _wifi(1);
|
||||
|
||||
WiFiClass::WiFiClass() {
|
||||
}
|
||||
|
||||
/*
|
||||
Get firmware version
|
||||
*/
|
||||
const char* WiFiClass::firmwareVersion() {
|
||||
// TODO - does not look like driver reports this now
|
||||
return PICO_SDK_VERSION_STRING;
|
||||
}
|
||||
|
||||
void WiFiClass::mode(_wifiModeESP m) {
|
||||
_calledESP = true;
|
||||
switch (m) {
|
||||
case WIFI_OFF:
|
||||
end();
|
||||
break;
|
||||
case WIFI_AP:
|
||||
_modeESP = WIFI_AP;
|
||||
break;
|
||||
case WIFI_STA:
|
||||
_modeESP = WIFI_STA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Start WiFi connection for OPEN networks
|
||||
|
||||
param ssid: Pointer to the SSID string.
|
||||
*/
|
||||
int WiFiClass::begin(const char* ssid) {
|
||||
return begin(ssid, nullptr);
|
||||
}
|
||||
|
||||
/* Start WiFi connection with passphrase
|
||||
the most secure supported mode will be automatically selected
|
||||
|
||||
param ssid: Pointer to the SSID string.
|
||||
param passphrase: Passphrase. Valid characters in a passphrase
|
||||
must be between ASCII 32-126 (decimal).
|
||||
*/
|
||||
int WiFiClass::begin(const char* ssid, const char *passphrase) {
|
||||
// Simple ESP8266 compatibility hack
|
||||
if (_modeESP == WIFI_AP) {
|
||||
return beginAP(ssid, passphrase);
|
||||
}
|
||||
|
||||
end();
|
||||
|
||||
_ssid = ssid;
|
||||
_password = passphrase;
|
||||
_wifi.setSSID(ssid);
|
||||
_wifi.setPassword(passphrase);
|
||||
_wifi.setTimeout(_timeout);
|
||||
_wifi.setSTA();
|
||||
_apMode = false;
|
||||
_wifiHWInitted = true;
|
||||
uint32_t start = millis(); // The timeout starts from network init, not network link up
|
||||
if (!_wifi.begin()) {
|
||||
return WL_IDLE_STATUS;
|
||||
}
|
||||
while (!_calledESP && ((millis() - start < (uint32_t)2 * _timeout)) && !connected()) {
|
||||
delay(10);
|
||||
}
|
||||
return status();
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::beginAP(const char *ssid) {
|
||||
return beginAP(ssid, nullptr);
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::beginAP(const char *ssid, uint8_t channel) {
|
||||
(void) channel;
|
||||
return beginAP(ssid, nullptr);
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::beginAP(const char *ssid, const char* passphrase, uint8_t channel) {
|
||||
(void) channel;
|
||||
return beginAP(ssid, passphrase);
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::beginAP(const char *ssid, const char* passphrase) {
|
||||
end();
|
||||
|
||||
_ssid = ssid;
|
||||
_password = passphrase;
|
||||
_wifi.setSSID(ssid);
|
||||
_wifi.setPassword(passphrase);
|
||||
_wifi.setTimeout(_timeout);
|
||||
_wifi.setAP();
|
||||
_apMode = true;
|
||||
if (!_wifi.begin()) {
|
||||
return WL_IDLE_STATUS;
|
||||
}
|
||||
IPAddress gw = _wifi.gatewayIP();
|
||||
if (!gw.isSet()) {
|
||||
gw = IPAddress(192, 168, 42, 1);
|
||||
}
|
||||
IPAddress mask = _wifi.subnetMask();
|
||||
if (!mask.isSet()) {
|
||||
mask = IPAddress(255, 255, 255, 0);
|
||||
}
|
||||
config(gw);
|
||||
_dhcpServer = (dhcp_server_t *)malloc(sizeof(dhcp_server_t));
|
||||
if (!_dhcpServer) {
|
||||
// OOM
|
||||
return WL_IDLE_STATUS;
|
||||
}
|
||||
dhcp_server_init(_dhcpServer, gw, mask);
|
||||
|
||||
_wifiHWInitted = true;
|
||||
|
||||
return WL_CONNECTED;
|
||||
}
|
||||
|
||||
bool WiFiClass::connected() {
|
||||
return _wifi.connected() && localIP().isSet();
|
||||
}
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
*/
|
||||
void WiFiClass::config(IPAddress local_ip) {
|
||||
ip4_addr_set_u32(ip_2_ip4(&_wifi.getNetIf()->ip_addr), local_ip.v4());
|
||||
}
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
param dns_server: IP configuration for DNS server 1
|
||||
*/
|
||||
void WiFiClass::config(IPAddress local_ip, IPAddress dns_server) {
|
||||
ip4_addr_set_u32(ip_2_ip4(&_wifi.getNetIf()->ip_addr), local_ip.v4());
|
||||
dns_setserver(0, dns_server);
|
||||
}
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
param dns_server: IP configuration for DNS server 1
|
||||
param gateway : Static gateway configuration
|
||||
*/
|
||||
void WiFiClass::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) {
|
||||
ip4_addr_set_u32(ip_2_ip4(&_wifi.getNetIf()->ip_addr), local_ip.v4());
|
||||
dns_setserver(0, dns_server);
|
||||
ip4_addr_set_u32(ip_2_ip4(&_wifi.getNetIf()->gw), gateway.v4());
|
||||
}
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
param dns_server: IP configuration for DNS server 1
|
||||
param gateway: Static gateway configuration
|
||||
param subnet: Static Subnet mask
|
||||
*/
|
||||
void WiFiClass::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) {
|
||||
_wifi.config(local_ip, gateway, subnet, dns_server);
|
||||
}
|
||||
|
||||
/* Change DNS Ip configuration
|
||||
|
||||
param dns_server1: ip configuration for DNS server 1
|
||||
*/
|
||||
void WiFiClass::setDNS(IPAddress dns_server1) {
|
||||
dns_setserver(0, dns_server1);
|
||||
}
|
||||
|
||||
/* Change DNS Ip configuration
|
||||
|
||||
param dns_server1: ip configuration for DNS server 1
|
||||
param dns_server2: ip configuration for DNS server 2
|
||||
|
||||
*/
|
||||
void WiFiClass::setDNS(IPAddress dns_server1, IPAddress dns_server2) {
|
||||
dns_setserver(0, dns_server1);
|
||||
dns_setserver(1, dns_server2);
|
||||
}
|
||||
|
||||
/* Set the hostname used for DHCP requests
|
||||
|
||||
param name: hostname to set
|
||||
|
||||
*/
|
||||
void WiFiClass::setHostname(const char* name) {
|
||||
_wifi.setHostname(name);
|
||||
}
|
||||
|
||||
/*
|
||||
Disconnect from the network
|
||||
|
||||
return: one value of wl_status_t enum
|
||||
*/
|
||||
int WiFiClass::disconnect(void) {
|
||||
if (_wifiHWInitted) {
|
||||
cyw43_wifi_leave(&cyw43_state, _apMode ? 1 : 0);
|
||||
}
|
||||
_wifiHWInitted = false;
|
||||
if (_dhcpServer) {
|
||||
dhcp_server_deinit(_dhcpServer);
|
||||
free(_dhcpServer);
|
||||
_dhcpServer = nullptr;
|
||||
}
|
||||
_wifi.end();
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
|
||||
void WiFiClass::end(void) {
|
||||
if (_wifiHWInitted) {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Get the interface MAC address.
|
||||
|
||||
return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
*/
|
||||
uint8_t* WiFiClass::macAddress(uint8_t* mac) {
|
||||
if (!_wifiHWInitted) {
|
||||
_apMode = false;
|
||||
cyw43_wifi_set_up(&cyw43_state, _apMode ? 1 : 0, true, CYW43_COUNTRY_WORLDWIDE);
|
||||
}
|
||||
cyw43_wifi_get_mac(&cyw43_state, _apMode ? 1 : 0, mac);
|
||||
return mac;
|
||||
}
|
||||
|
||||
/*
|
||||
Get the interface IP address.
|
||||
|
||||
return: Ip address value
|
||||
*/
|
||||
IPAddress WiFiClass::localIP() {
|
||||
return _wifi.localIP();
|
||||
}
|
||||
|
||||
/*
|
||||
Get the interface subnet mask address.
|
||||
|
||||
return: subnet mask address value
|
||||
*/
|
||||
IPAddress WiFiClass::subnetMask() {
|
||||
return _wifi.subnetMask();
|
||||
}
|
||||
|
||||
/*
|
||||
Get the gateway ip address.
|
||||
|
||||
return: gateway ip address value
|
||||
*/
|
||||
IPAddress WiFiClass::gatewayIP() {
|
||||
return _wifi.gatewayIP();
|
||||
}
|
||||
|
||||
/*
|
||||
Return the current SSID associated with the network
|
||||
|
||||
return: ssid string
|
||||
*/
|
||||
const char* WiFiClass::SSID() {
|
||||
return _ssid;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the current BSSID associated with the network.
|
||||
It is the MAC address of the Access Point
|
||||
|
||||
return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
*/
|
||||
uint8_t* WiFiClass::BSSID(uint8_t* bssid) {
|
||||
// TODO - driver does not return this?!
|
||||
memset(bssid, 0xee, WL_MAC_ADDR_LENGTH);
|
||||
return bssid;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the current RSSI /Received Signal Strength in dBm)
|
||||
associated with the network
|
||||
|
||||
return: signed value
|
||||
*/
|
||||
int32_t WiFiClass::RSSI() {
|
||||
// TODO - driver does not return this?!
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the Encryption Type associated with the network
|
||||
|
||||
return: one value of wl_enc_type enum
|
||||
*/
|
||||
uint8_t WiFiClass::encryptionType() {
|
||||
// TODO - Driver does not return this?!
|
||||
if (_password == nullptr) {
|
||||
return ENC_TYPE_NONE;
|
||||
}
|
||||
return ENC_TYPE_AUTO;
|
||||
}
|
||||
|
||||
//TODO - this can be in the class
|
||||
static uint64_t _to64(uint8_t b[8]) {
|
||||
uint64_t x = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
x <<= 8LL;
|
||||
x |= b[i] & 255;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
int WiFiClass::_scanCB(void *env, const cyw43_ev_scan_result_t *result) {
|
||||
WiFiClass *w = (WiFiClass *)env;
|
||||
if (result) {
|
||||
cyw43_ev_scan_result_t s;
|
||||
memcpy(&s, result, sizeof(s));
|
||||
w->_scan.insert_or_assign(_to64(s.bssid), s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Start scan WiFi networks available
|
||||
|
||||
return: Number of discovered networks
|
||||
*/
|
||||
int8_t WiFiClass::scanNetworks() {
|
||||
cyw43_wifi_scan_options_t scan_options;
|
||||
memset(&scan_options, 0, sizeof(scan_options));
|
||||
_scan.clear();
|
||||
if (!_wifiHWInitted) {
|
||||
_apMode = false;
|
||||
cyw43_arch_enable_sta_mode();
|
||||
_wifiHWInitted = true;
|
||||
}
|
||||
int err = cyw43_wifi_scan(&cyw43_state, &scan_options, this, _scanCB);
|
||||
if (err) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t now = millis();
|
||||
while (cyw43_wifi_scan_active(&cyw43_state) && (millis() - now < 10000)) {
|
||||
delay(10);
|
||||
}
|
||||
return _scan.size();
|
||||
}
|
||||
|
||||
/*
|
||||
Return the SSID discovered during the network scan.
|
||||
|
||||
param networkItem: specify from which network item want to get the information
|
||||
|
||||
return: ssid string of the specified item on the networks scanned list
|
||||
*/
|
||||
const char*WiFiClass::SSID(uint8_t networkItem) {
|
||||
if (networkItem >= _scan.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto it = _scan.begin();
|
||||
for (int i = 0; i < networkItem; i++) {
|
||||
++it;
|
||||
}
|
||||
return (const char *)it->second.ssid;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the encryption type of the networks discovered during the scanNetworks
|
||||
|
||||
param networkItem: specify from which network item want to get the information
|
||||
|
||||
return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list
|
||||
*/
|
||||
uint8_t WiFiClass::encryptionType(uint8_t networkItem) {
|
||||
if (networkItem >= _scan.size()) {
|
||||
return ENC_TYPE_UNKNOWN;
|
||||
}
|
||||
auto it = _scan.begin();
|
||||
for (int i = 0; i < networkItem; i++) {
|
||||
++it;
|
||||
}
|
||||
// TODO - the driver returns a small integer but does not actually provide a way of mapping that to the proper enc type. My best guesses here...
|
||||
switch (it->second.auth_mode) {
|
||||
case 0: return ENC_TYPE_NONE;
|
||||
case 3: return ENC_TYPE_TKIP;
|
||||
case 5: return ENC_TYPE_CCMP;
|
||||
case 7: return ENC_TYPE_AUTO;
|
||||
}
|
||||
return ENC_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
uint8_t* WiFiClass::BSSID(uint8_t networkItem, uint8_t* bssid) {
|
||||
if (networkItem >= _scan.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto it = _scan.begin();
|
||||
for (int i = 0; i < networkItem; i++) {
|
||||
++it;
|
||||
}
|
||||
memcpy(bssid, it->second.bssid, 6);
|
||||
return bssid;
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::channel(uint8_t networkItem) {
|
||||
if (networkItem >= _scan.size()) {
|
||||
return 255;
|
||||
}
|
||||
auto it = _scan.begin();
|
||||
for (int i = 0; i < networkItem; i++) {
|
||||
++it;
|
||||
}
|
||||
return it->second.channel;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the RSSI of the networks discovered during the scanNetworks
|
||||
|
||||
param networkItem: specify from which network item want to get the information
|
||||
|
||||
return: signed value of RSSI of the specified item on the networks scanned list
|
||||
*/
|
||||
int32_t WiFiClass::RSSI(uint8_t networkItem) {
|
||||
if (networkItem >= _scan.size()) {
|
||||
return -9999;
|
||||
}
|
||||
auto it = _scan.begin();
|
||||
for (int i = 0; i < networkItem; i++) {
|
||||
++it;
|
||||
}
|
||||
return it->second.rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
Return Connection status.
|
||||
|
||||
return: one of the value defined in wl_status_t
|
||||
*/
|
||||
uint8_t WiFiClass::status() {
|
||||
switch (cyw43_wifi_link_status(&cyw43_state, _apMode ? 1 : 0)) {
|
||||
case CYW43_LINK_DOWN: return WL_IDLE_STATUS;
|
||||
case CYW43_LINK_JOIN: return localIP().isSet() ? WL_CONNECTED : WL_CONNECTING;
|
||||
case CYW43_LINK_FAIL: return WL_CONNECT_FAILED;
|
||||
case CYW43_LINK_NONET: return WL_CONNECT_FAILED;
|
||||
case CYW43_LINK_BADAUTH: return WL_CONNECT_FAILED;
|
||||
}
|
||||
return WL_NO_MODULE;
|
||||
}
|
||||
|
||||
/*
|
||||
Return The deauthentication reason code.
|
||||
|
||||
return: the deauthentication reason code
|
||||
*/
|
||||
uint8_t WiFiClass::reasonCode() {
|
||||
// TODO - driver does not report this?!
|
||||
return WL_NO_SHIELD;
|
||||
}
|
||||
|
||||
/**
|
||||
Resolve the given hostname to an IP address.
|
||||
@param aHostname Name to be resolved
|
||||
@param aResult IPAddress structure to store the returned IP address
|
||||
@return 1 if aIPAddrString was successfully converted to an IP address,
|
||||
else 0
|
||||
*/
|
||||
|
||||
int WiFiClass::hostByName(const char* aHostname, IPAddress& aResult, int timeout_ms) {
|
||||
return _wifi.hostByName(aHostname, aResult, timeout_ms);
|
||||
}
|
||||
|
||||
// TODO
|
||||
unsigned long WiFiClass::getTime() {
|
||||
return millis();
|
||||
}
|
||||
|
||||
void WiFiClass::lowPowerMode() {
|
||||
cyw43_wifi_pm(&cyw43_state, CYW43_AGGRESSIVE_PM);
|
||||
}
|
||||
|
||||
void WiFiClass::noLowPowerMode() {
|
||||
cyw43_wifi_pm(&cyw43_state, CYW43_DEFAULT_PM);
|
||||
}
|
||||
|
||||
int WiFiClass::ping(const char* hostname, uint8_t ttl) {
|
||||
IPAddress ip;
|
||||
if (!hostByName(hostname, ip)) {
|
||||
return WL_PING_UNKNOWN_HOST;
|
||||
}
|
||||
return ping(ip, ttl);
|
||||
}
|
||||
|
||||
int WiFiClass::ping(const String &hostname, uint8_t ttl) {
|
||||
return ping(hostname.c_str(), ttl);
|
||||
}
|
||||
|
||||
int WiFiClass::ping(IPAddress host, uint8_t ttl) {
|
||||
return _wifi.ping(host, ttl, _timeout);
|
||||
}
|
||||
|
||||
void WiFiClass::setTimeout(unsigned long timeout) {
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
void WiFiClass::setFeedWatchdogFunc(FeedHostProcessorWatchdogFuncPointer func) {
|
||||
(void) func;
|
||||
}
|
||||
void WiFiClass::feedWatchdog() {
|
||||
}
|
||||
|
||||
|
||||
WiFiClass WiFi;
|
||||
304
libraries/WiFi/src/WiFiClass.h
Normal file
304
libraries/WiFi/src/WiFiClass.h
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
WiFi.h - WiFi class "compat" w/WiFiNINA for Raspberry Pi Pico W
|
||||
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
Implements the API defined by the Arduino WiFiNINA library,
|
||||
copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "WiFi.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <map>
|
||||
|
||||
#include <cyw43.h>
|
||||
#include "dhcpserver/dhcpserver.h"
|
||||
|
||||
#define WIFI_FIRMWARE_LATEST_VERSION PICO_SDK_VERSION_STRING
|
||||
|
||||
typedef void(*FeedHostProcessorWatchdogFuncPointer)();
|
||||
|
||||
typedef enum { WIFI_STA, WIFI_AP, WIFI_OFF } _wifiModeESP; // For ESP8266 compatibility
|
||||
|
||||
class WiFiClass {
|
||||
public:
|
||||
WiFiClass();
|
||||
|
||||
/*
|
||||
Get firmware version
|
||||
*/
|
||||
static const char* firmwareVersion();
|
||||
|
||||
void mode(_wifiModeESP m); // For ESP8266 compatibility
|
||||
|
||||
/* Start WiFi connection for OPEN networks
|
||||
|
||||
param ssid: Pointer to the SSID string.
|
||||
*/
|
||||
int begin(const char* ssid);
|
||||
|
||||
/* Start WiFi connection with WEP encryption.
|
||||
Configure a key into the device. The key type (WEP-40, WEP-104)
|
||||
is determined by the size of the key (5 bytes for WEP-40, 13 bytes for WEP-104).
|
||||
|
||||
param ssid: Pointer to the SSID string.
|
||||
param key_idx: The key index to set. Valid values are 0-3.
|
||||
param key: Key input buffer.
|
||||
*/
|
||||
// TODO - WEP is not supported in the driver
|
||||
// int begin(const char* ssid, uint8_t key_idx, const char* key);
|
||||
|
||||
/* Start WiFi connection with passphrase
|
||||
the most secure supported mode will be automatically selected
|
||||
|
||||
param ssid: Pointer to the SSID string.
|
||||
param passphrase: Passphrase. Valid characters in a passphrase
|
||||
must be between ASCII 32-126 (decimal).
|
||||
*/
|
||||
int begin(const char* ssid, const char *passphrase);
|
||||
|
||||
bool connected();
|
||||
|
||||
uint8_t beginAP(const char *ssid);
|
||||
uint8_t beginAP(const char *ssid, uint8_t channel);
|
||||
uint8_t beginAP(const char *ssid, const char* passphrase);
|
||||
uint8_t beginAP(const char *ssid, const char* passphrase, uint8_t channel);
|
||||
|
||||
// TODO - EAP is not supported by the driver. Maybe some way of user-level wap-supplicant in the future?
|
||||
//uint8_t beginEnterprise(const char* ssid, const char* username, const char* password);
|
||||
//uint8_t beginEnterprise(const char* ssid, const char* username, const char* password, const char* identity);
|
||||
//uint8_t beginEnterprise(const char* ssid, const char* username, const char* password, const char* identity, const char* ca);
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
*/
|
||||
void config(IPAddress local_ip);
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
param dns_server: IP configuration for DNS server 1
|
||||
*/
|
||||
void config(IPAddress local_ip, IPAddress dns_server);
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
param dns_server: IP configuration for DNS server 1
|
||||
param gateway : Static gateway configuration
|
||||
*/
|
||||
void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway);
|
||||
|
||||
/* Change Ip configuration settings disabling the dhcp client
|
||||
|
||||
param local_ip: Static ip configuration
|
||||
param dns_server: IP configuration for DNS server 1
|
||||
param gateway: Static gateway configuration
|
||||
param subnet: Static Subnet mask
|
||||
*/
|
||||
void config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet);
|
||||
|
||||
/* Change DNS Ip configuration
|
||||
|
||||
param dns_server1: ip configuration for DNS server 1
|
||||
*/
|
||||
void setDNS(IPAddress dns_server1);
|
||||
|
||||
/* Change DNS Ip configuration
|
||||
|
||||
param dns_server1: ip configuration for DNS server 1
|
||||
param dns_server2: ip configuration for DNS server 2
|
||||
|
||||
*/
|
||||
void setDNS(IPAddress dns_server1, IPAddress dns_server2);
|
||||
|
||||
|
||||
/* Set the hostname used for DHCP requests
|
||||
|
||||
param name: hostname to set
|
||||
|
||||
*/
|
||||
void setHostname(const char* name);
|
||||
|
||||
/*
|
||||
Disconnect from the network
|
||||
|
||||
return: one value of wl_status_t enum
|
||||
*/
|
||||
int disconnect(void);
|
||||
|
||||
void end(void);
|
||||
|
||||
/*
|
||||
Get the interface MAC address.
|
||||
|
||||
return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
*/
|
||||
uint8_t* macAddress(uint8_t* mac);
|
||||
|
||||
/*
|
||||
Get the interface IP address.
|
||||
|
||||
return: Ip address value
|
||||
*/
|
||||
IPAddress localIP();
|
||||
|
||||
/*
|
||||
Get the interface subnet mask address.
|
||||
|
||||
return: subnet mask address value
|
||||
*/
|
||||
IPAddress subnetMask();
|
||||
|
||||
/*
|
||||
Get the gateway ip address.
|
||||
|
||||
return: gateway ip address value
|
||||
*/
|
||||
IPAddress gatewayIP();
|
||||
|
||||
/*
|
||||
Return the current SSID associated with the network
|
||||
|
||||
return: ssid string
|
||||
*/
|
||||
const char* SSID();
|
||||
|
||||
/*
|
||||
Return the current BSSID associated with the network.
|
||||
It is the MAC address of the Access Point
|
||||
|
||||
return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
*/
|
||||
uint8_t* BSSID(uint8_t* bssid);
|
||||
|
||||
/*
|
||||
Return the current RSSI /Received Signal Strength in dBm)
|
||||
associated with the network
|
||||
|
||||
return: signed value
|
||||
*/
|
||||
int32_t RSSI();
|
||||
|
||||
/*
|
||||
Return the Encryption Type associated with the network
|
||||
|
||||
return: one value of wl_enc_type enum
|
||||
*/
|
||||
uint8_t encryptionType();
|
||||
|
||||
/*
|
||||
Start scan WiFi networks available
|
||||
|
||||
return: Number of discovered networks
|
||||
*/
|
||||
int8_t scanNetworks();
|
||||
|
||||
/*
|
||||
Return the SSID discovered during the network scan.
|
||||
|
||||
param networkItem: specify from which network item want to get the information
|
||||
|
||||
return: ssid string of the specified item on the networks scanned list
|
||||
*/
|
||||
const char* SSID(uint8_t networkItem);
|
||||
|
||||
/*
|
||||
Return the encryption type of the networks discovered during the scanNetworks
|
||||
|
||||
param networkItem: specify from which network item want to get the information
|
||||
|
||||
return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list
|
||||
*/
|
||||
uint8_t encryptionType(uint8_t networkItem);
|
||||
|
||||
uint8_t* BSSID(uint8_t networkItem, uint8_t* bssid);
|
||||
uint8_t channel(uint8_t networkItem);
|
||||
|
||||
/*
|
||||
Return the RSSI of the networks discovered during the scanNetworks
|
||||
|
||||
param networkItem: specify from which network item want to get the information
|
||||
|
||||
return: signed value of RSSI of the specified item on the networks scanned list
|
||||
*/
|
||||
int32_t RSSI(uint8_t networkItem);
|
||||
|
||||
/*
|
||||
Return Connection status.
|
||||
|
||||
return: one of the value defined in wl_status_t
|
||||
*/
|
||||
uint8_t status();
|
||||
|
||||
/*
|
||||
Return The deauthentication reason code.
|
||||
|
||||
return: the deauthentication reason code
|
||||
*/
|
||||
uint8_t reasonCode();
|
||||
|
||||
/*
|
||||
Resolve the given hostname to an IP address.
|
||||
param aHostname: Name to be resolved
|
||||
param aResult: IPAddress structure to store the returned IP address
|
||||
result: 1 if aIPAddrString was successfully converted to an IP address,
|
||||
else error code
|
||||
*/
|
||||
int hostByName(const char* aHostname, IPAddress& aResult) {
|
||||
return hostByName(aHostname, aResult, _timeout);
|
||||
}
|
||||
int hostByName(const char* aHostname, IPAddress& aResult, int timeout);
|
||||
|
||||
unsigned long getTime();
|
||||
|
||||
void lowPowerMode();
|
||||
void noLowPowerMode();
|
||||
|
||||
int ping(const char* hostname, uint8_t ttl = 128);
|
||||
int ping(const String &hostname, uint8_t ttl = 128);
|
||||
int ping(IPAddress host, uint8_t ttl = 128);
|
||||
|
||||
void setTimeout(unsigned long timeout);
|
||||
|
||||
void setFeedWatchdogFunc(FeedHostProcessorWatchdogFuncPointer func);
|
||||
void feedWatchdog();
|
||||
|
||||
private:
|
||||
int _timeout = 10000;
|
||||
const char * _ssid = nullptr;
|
||||
const char * _password = nullptr;
|
||||
bool _wifiHWInitted = false;
|
||||
bool _apMode = false;
|
||||
|
||||
// WiFi Scan callback
|
||||
std::map<uint64_t, cyw43_ev_scan_result_t> _scan;
|
||||
static int _scanCB(void *env, const cyw43_ev_scan_result_t *result);
|
||||
|
||||
// DHCP for AP mode
|
||||
dhcp_server_t *_dhcpServer = nullptr;
|
||||
|
||||
// ESP compat
|
||||
bool _calledESP = false; // Should we behave like the ESP8266 for connect?
|
||||
_wifiModeESP _modeESP = WIFI_STA;
|
||||
};
|
||||
|
||||
extern WiFiClass WiFi;
|
||||
414
libraries/WiFi/src/WiFiClient.cpp
Normal file
414
libraries/WiFi/src/WiFiClient.cpp
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
WiFiClient.cpp - TCP/IP client for esp8266, mostly compatible
|
||||
with Arduino WiFi shield library
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include <include/ClientContext.h>
|
||||
//#include <StreamDev.h>
|
||||
|
||||
uint16_t WiFiClient::_localPort = 0;
|
||||
|
||||
static bool defaultNoDelay = false; // false == Nagle enabled by default
|
||||
static bool defaultSync = false;
|
||||
|
||||
bool getDefaultPrivateGlobalSyncValue() {
|
||||
return defaultSync;
|
||||
}
|
||||
|
||||
void WiFiClient::setDefaultNoDelay(bool noDelay) {
|
||||
defaultNoDelay = noDelay;
|
||||
}
|
||||
|
||||
void WiFiClient::setDefaultSync(bool sync) {
|
||||
defaultSync = sync;
|
||||
}
|
||||
|
||||
bool WiFiClient::getDefaultNoDelay() {
|
||||
return defaultNoDelay;
|
||||
}
|
||||
|
||||
bool WiFiClient::getDefaultSync() {
|
||||
return defaultSync;
|
||||
}
|
||||
|
||||
template<>
|
||||
WiFiClient* SList<WiFiClient>::_s_first = 0;
|
||||
|
||||
|
||||
WiFiClient::WiFiClient()
|
||||
: _client(0), _owned(0) {
|
||||
_timeout = 5000;
|
||||
WiFiClient::_add(this);
|
||||
}
|
||||
|
||||
WiFiClient::WiFiClient(ClientContext* client)
|
||||
: _client(client), _owned(0) {
|
||||
_timeout = 5000;
|
||||
_client->ref();
|
||||
WiFiClient::_add(this);
|
||||
|
||||
setSync(defaultSync);
|
||||
setNoDelay(defaultNoDelay);
|
||||
}
|
||||
|
||||
WiFiClient::~WiFiClient() {
|
||||
WiFiClient::_remove(this);
|
||||
if (_client) {
|
||||
_client->unref();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<WiFiClient> WiFiClient::clone() const {
|
||||
return std::make_unique<WiFiClient>(*this);
|
||||
}
|
||||
|
||||
WiFiClient::WiFiClient(const WiFiClient& other) {
|
||||
_client = other._client;
|
||||
_timeout = other._timeout;
|
||||
_localPort = other._localPort;
|
||||
_owned = other._owned;
|
||||
if (_client) {
|
||||
_client->ref();
|
||||
}
|
||||
WiFiClient::_add(this);
|
||||
}
|
||||
|
||||
WiFiClient& WiFiClient::operator=(const WiFiClient& other) {
|
||||
if (_client) {
|
||||
_client->unref();
|
||||
}
|
||||
_client = other._client;
|
||||
_timeout = other._timeout;
|
||||
_localPort = other._localPort;
|
||||
_owned = other._owned;
|
||||
if (_client) {
|
||||
_client->ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const char* host, uint16_t port) {
|
||||
IPAddress remote_addr;
|
||||
if (WiFi.hostByName(host, remote_addr, _timeout)) {
|
||||
return connect(remote_addr, port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const String& host, uint16_t port) {
|
||||
return connect(host.c_str(), port);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port) {
|
||||
if (_client) {
|
||||
stop();
|
||||
_client->unref();
|
||||
_client = nullptr;
|
||||
}
|
||||
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
|
||||
tcp_pcb* pcb = tcp_new();
|
||||
if (!pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_localPort > 0) {
|
||||
pcb->local_port = _localPort++;
|
||||
}
|
||||
|
||||
_client = new ClientContext(pcb, nullptr, nullptr);
|
||||
_client->ref();
|
||||
_client->setTimeout(_timeout);
|
||||
int res = _client->connect(ip, port);
|
||||
if (res == 0) {
|
||||
_client->unref();
|
||||
_client = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
setSync(defaultSync);
|
||||
setNoDelay(defaultNoDelay);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WiFiClient::setNoDelay(bool nodelay) {
|
||||
if (!_client) {
|
||||
return;
|
||||
}
|
||||
_client->setNoDelay(nodelay);
|
||||
}
|
||||
|
||||
bool WiFiClient::getNoDelay() const {
|
||||
if (!_client) {
|
||||
return false;
|
||||
}
|
||||
return _client->getNoDelay();
|
||||
}
|
||||
|
||||
void WiFiClient::setSync(bool sync) {
|
||||
if (!_client) {
|
||||
return;
|
||||
}
|
||||
_client->setSync(sync);
|
||||
}
|
||||
|
||||
bool WiFiClient::getSync() const {
|
||||
if (!_client) {
|
||||
return false;
|
||||
}
|
||||
return _client->getSync();
|
||||
}
|
||||
|
||||
int WiFiClient::availableForWrite() {
|
||||
return _client ? _client->availableForWrite() : 0;
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(uint8_t b) {
|
||||
return write(&b, 1);
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(const uint8_t *buf, size_t size) {
|
||||
if (!_client || !size) {
|
||||
return 0;
|
||||
}
|
||||
_client->setTimeout(_timeout);
|
||||
return _client->write((const char*)buf, size);
|
||||
}
|
||||
|
||||
//TODO - implement!
|
||||
//size_t WiFiClient::write(Stream& stream)
|
||||
//{
|
||||
// // (this method is deprecated)
|
||||
//
|
||||
// if (!_client || !stream.available())
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
// // core up to 2.7.4 was equivalent to this
|
||||
// return _client->write(stream);
|
||||
//}
|
||||
|
||||
int WiFiClient::available() {
|
||||
if (!_client) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int result = _client->getSize();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int WiFiClient::read() {
|
||||
if (!available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _client->read();
|
||||
}
|
||||
|
||||
int WiFiClient::read(uint8_t* buf, size_t size) {
|
||||
return (int)_client->read((char*)buf, size);
|
||||
}
|
||||
|
||||
int WiFiClient::read(char* buf, size_t size) {
|
||||
return (int)_client->read(buf, size);
|
||||
}
|
||||
|
||||
int WiFiClient::peek() {
|
||||
if (!available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _client->peek();
|
||||
}
|
||||
|
||||
size_t WiFiClient::peekBytes(uint8_t *buffer, size_t length) {
|
||||
size_t count = 0;
|
||||
|
||||
if (!_client) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_startMillis = millis();
|
||||
while ((available() < (int) length) && ((millis() - _startMillis) < _timeout)) {
|
||||
yield();
|
||||
}
|
||||
|
||||
if (available() < (int) length) {
|
||||
count = available();
|
||||
} else {
|
||||
count = length;
|
||||
}
|
||||
|
||||
return _client->peekBytes((char *)buffer, count);
|
||||
}
|
||||
|
||||
bool WiFiClient::flush(unsigned int maxWaitMs) {
|
||||
if (!_client) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (maxWaitMs == 0) {
|
||||
maxWaitMs = WIFICLIENT_MAX_FLUSH_WAIT_MS;
|
||||
}
|
||||
return _client->wait_until_acked(maxWaitMs);
|
||||
}
|
||||
|
||||
bool WiFiClient::stop(unsigned int maxWaitMs) {
|
||||
if (!_client) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = flush(maxWaitMs); // virtual, may be ssl's
|
||||
if (_client->close() != ERR_OK) {
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t WiFiClient::connected() {
|
||||
if (!_client || _client->state() == CLOSED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _client->state() == ESTABLISHED || available();
|
||||
}
|
||||
|
||||
uint8_t WiFiClient::status() {
|
||||
if (!_client) {
|
||||
return CLOSED;
|
||||
}
|
||||
return _client->state();
|
||||
}
|
||||
|
||||
WiFiClient::operator bool() {
|
||||
return available() || connected();
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::remoteIP() {
|
||||
if (!_client || !_client->getRemoteAddress()) {
|
||||
return IPAddress(0);
|
||||
}
|
||||
|
||||
return _client->getRemoteAddress();
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::remotePort() {
|
||||
if (!_client) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _client->getRemotePort();
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::localIP() {
|
||||
if (!_client || !_client->getLocalAddress()) {
|
||||
return IPAddress(0);
|
||||
}
|
||||
|
||||
return IPAddress(_client->getLocalAddress());
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::localPort() {
|
||||
if (!_client) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _client->getLocalPort();
|
||||
}
|
||||
|
||||
void WiFiClient::stopAll() {
|
||||
for (WiFiClient* it = _s_first; it; it = it->_next) {
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WiFiClient::stopAllExcept(WiFiClient* except) {
|
||||
// Stop all will look at the lowest-level wrapper connections only
|
||||
while (except->_owned) {
|
||||
except = except->_owned;
|
||||
}
|
||||
for (WiFiClient* it = _s_first; it; it = it->_next) {
|
||||
WiFiClient* conn = it;
|
||||
// Find the lowest-level owner of the current list entry
|
||||
while (conn->_owned) {
|
||||
conn = conn->_owned;
|
||||
}
|
||||
if (conn != except) {
|
||||
conn->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WiFiClient::keepAlive(uint16_t idle_sec, uint16_t intv_sec, uint8_t count) {
|
||||
_client->keepAlive(idle_sec, intv_sec, count);
|
||||
}
|
||||
|
||||
bool WiFiClient::isKeepAliveEnabled() const {
|
||||
return _client->isKeepAliveEnabled();
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::getKeepAliveIdle() const {
|
||||
return _client->getKeepAliveIdle();
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::getKeepAliveInterval() const {
|
||||
return _client->getKeepAliveInterval();
|
||||
}
|
||||
|
||||
uint8_t WiFiClient::getKeepAliveCount() const {
|
||||
return _client->getKeepAliveCount();
|
||||
}
|
||||
|
||||
//bool WiFiClient::hasPeekBufferAPI () const
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
|
||||
// return a pointer to available data buffer (size = peekAvailable())
|
||||
// semantic forbids any kind of read() before calling peekConsume()
|
||||
//const char* WiFiClient::peekBuffer ()
|
||||
//{
|
||||
// return _client? _client->peekBuffer(): nullptr;
|
||||
//}
|
||||
|
||||
// return number of byte accessible by peekBuffer()
|
||||
//size_t WiFiClient::peekAvailable ()
|
||||
//{
|
||||
// return _client? _client->peekAvailable(): 0;
|
||||
//}
|
||||
|
||||
// consume bytes after use (see peekBuffer)
|
||||
//void WiFiClient::peekConsume (size_t consume)
|
||||
//{
|
||||
// if (_client)
|
||||
// _client->peekConsume(consume);
|
||||
//}
|
||||
169
libraries/WiFi/src/WiFiClient.h
Normal file
169
libraries/WiFi/src/WiFiClient.h
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
WiFiClient.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified by Ivan Grokhotkov, December 2014 - esp8266 support
|
||||
Hacked to tiny bits and set on fire by Earle F. Philhower, III - 2022 - Pico W support
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "WiFi.h"
|
||||
#include "Print.h"
|
||||
#include "Client.h"
|
||||
#include "IPAddress.h"
|
||||
#include "include/slist.h"
|
||||
|
||||
#ifndef TCP_MSS
|
||||
#define TCP_MSS 1460 // lwip1.4
|
||||
#endif
|
||||
|
||||
#define WIFICLIENT_MAX_PACKET_SIZE TCP_MSS
|
||||
#define WIFICLIENT_MAX_FLUSH_WAIT_MS 300
|
||||
|
||||
#define TCP_DEFAULT_KEEPALIVE_IDLE_SEC 7200 // 2 hours
|
||||
#define TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC 75 // 75 sec
|
||||
#define TCP_DEFAULT_KEEPALIVE_COUNT 9 // fault after 9 failures
|
||||
|
||||
class ClientContext;
|
||||
class WiFiServer;
|
||||
|
||||
class WiFiClient : public Client, public SList<WiFiClient> {
|
||||
protected:
|
||||
WiFiClient(ClientContext* client);
|
||||
|
||||
public:
|
||||
WiFiClient();
|
||||
virtual ~WiFiClient();
|
||||
WiFiClient(const WiFiClient&);
|
||||
WiFiClient& operator=(const WiFiClient&);
|
||||
|
||||
// b/c this is both a real class and a virtual parent of the secure client, make sure
|
||||
// there's a safe way to copy from the pointer without 'slicing' it; i.e. only the base
|
||||
// portion of a derived object will be copied, and the polymorphic behavior will be corrupted.
|
||||
//
|
||||
// this class still implements the copy and assignment though, so this is not yet enforced
|
||||
// (but, *should* be inside the Core itself, see httpclient & server)
|
||||
//
|
||||
// ref.
|
||||
// - https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-copy-virtual
|
||||
// - https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-copy
|
||||
virtual std::unique_ptr<WiFiClient> clone() const;
|
||||
|
||||
virtual uint8_t status();
|
||||
virtual int connect(IPAddress ip, uint16_t port) override;
|
||||
virtual int connect(const char *host, uint16_t port) override;
|
||||
virtual int connect(const String& host, uint16_t port);
|
||||
virtual size_t write(uint8_t) override;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) override;
|
||||
//size_t write(Stream& stream);
|
||||
|
||||
virtual int available() override;
|
||||
virtual int read() override;
|
||||
virtual int read(uint8_t* buf, size_t size) override;
|
||||
int read(char* buf, size_t size);
|
||||
|
||||
virtual int peek() override;
|
||||
virtual size_t peekBytes(uint8_t *buffer, size_t length);
|
||||
size_t peekBytes(char *buffer, size_t length) {
|
||||
return peekBytes((uint8_t *) buffer, length);
|
||||
}
|
||||
virtual void flush() override {
|
||||
(void)flush(0); // wait for all outgoing characters to be sent, output buffer should be empty after this call
|
||||
}
|
||||
virtual void stop() override {
|
||||
(void)stop(0);
|
||||
}
|
||||
bool flush(unsigned int maxWaitMs);
|
||||
bool stop(unsigned int maxWaitMs);
|
||||
virtual uint8_t connected() override;
|
||||
virtual operator bool() override;
|
||||
|
||||
IPAddress remoteIP();
|
||||
uint16_t remotePort();
|
||||
IPAddress localIP();
|
||||
uint16_t localPort();
|
||||
|
||||
static void setLocalPortStart(uint16_t port) {
|
||||
_localPort = port;
|
||||
}
|
||||
|
||||
int availableForWrite() override;
|
||||
|
||||
friend class WiFiServer;
|
||||
|
||||
using Print::write;
|
||||
|
||||
static void stopAll();
|
||||
static void stopAllExcept(WiFiClient * c);
|
||||
|
||||
void keepAlive(uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC, uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC, uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT);
|
||||
bool isKeepAliveEnabled() const;
|
||||
uint16_t getKeepAliveIdle() const;
|
||||
uint16_t getKeepAliveInterval() const;
|
||||
uint8_t getKeepAliveCount() const;
|
||||
void disableKeepAlive() {
|
||||
keepAlive(0, 0, 0);
|
||||
}
|
||||
|
||||
// default NoDelay=False (Nagle=True=!NoDelay)
|
||||
// Nagle is for shortly delaying outgoing data, to send less/bigger packets
|
||||
// Nagle should be disabled for telnet-like/interactive streams
|
||||
// Nagle is meaningless/ignored when Sync=true
|
||||
static void setDefaultNoDelay(bool noDelay);
|
||||
static bool getDefaultNoDelay();
|
||||
bool getNoDelay() const;
|
||||
void setNoDelay(bool nodelay);
|
||||
|
||||
// default Sync=false
|
||||
// When sync is true, all writes are automatically flushed.
|
||||
// This is slower but also does not allocate
|
||||
// temporary memory for sending data
|
||||
static void setDefaultSync(bool sync);
|
||||
static bool getDefaultSync();
|
||||
bool getSync() const;
|
||||
void setSync(bool sync);
|
||||
|
||||
// peek buffer API is present
|
||||
//virtual bool hasPeekBufferAPI () const override;
|
||||
|
||||
// return number of byte accessible by peekBuffer()
|
||||
//virtual size_t peekAvailable () override;
|
||||
|
||||
// return a pointer to available data buffer (size = peekAvailable())
|
||||
// semantic forbids any kind of read() before calling peekConsume()
|
||||
//virtual const char* peekBuffer () override;
|
||||
|
||||
// consume bytes after use (see peekBuffer)
|
||||
//virtual void peekConsume (size_t consume) override;
|
||||
|
||||
//virtual bool outputCanTimeout () override { return connected(); }
|
||||
//virtual bool inputCanTimeout () override { return connected(); }
|
||||
|
||||
protected:
|
||||
|
||||
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
|
||||
static void _s_err(void* arg, int8_t err);
|
||||
|
||||
int8_t _connected(void* tpcb, int8_t err);
|
||||
void _err(int8_t err);
|
||||
|
||||
ClientContext* _client;
|
||||
WiFiClient* _owned;
|
||||
static uint16_t _localPort;
|
||||
};
|
||||
220
libraries/WiFi/src/WiFiServer.cpp
Normal file
220
libraries/WiFi/src/WiFiServer.cpp
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
WiFiServer.cpp - TCP/IP server for esp8266, mostly compatible
|
||||
with Arduino WiFi shield library
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "WiFi.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include <include/ClientContext.h>
|
||||
|
||||
#ifndef MAX_PENDING_CLIENTS_PER_PORT
|
||||
#define MAX_PENDING_CLIENTS_PER_PORT 5
|
||||
#endif
|
||||
|
||||
WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port)
|
||||
: _port(port)
|
||||
, _addr(addr) {
|
||||
}
|
||||
|
||||
WiFiServer::WiFiServer(uint16_t port)
|
||||
: _port(port)
|
||||
, _addr(IP_ANY_TYPE) {
|
||||
}
|
||||
|
||||
void WiFiServer::begin() {
|
||||
begin(_port);
|
||||
}
|
||||
|
||||
void WiFiServer::begin(uint16_t port) {
|
||||
return begin(port, MAX_PENDING_CLIENTS_PER_PORT);
|
||||
}
|
||||
|
||||
void WiFiServer::begin(uint16_t port, uint8_t backlog) {
|
||||
close();
|
||||
if (!backlog) {
|
||||
return;
|
||||
}
|
||||
_port = port;
|
||||
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
|
||||
tcp_pcb* pcb = tcp_new();
|
||||
if (!pcb) {
|
||||
return;
|
||||
}
|
||||
|
||||
pcb->so_options |= SOF_REUSEADDR;
|
||||
|
||||
// (IPAddress _addr) operator-converted to (const ip_addr_t*)
|
||||
if (tcp_bind(pcb, _addr, _port) != ERR_OK) {
|
||||
tcp_close(pcb);
|
||||
return;
|
||||
}
|
||||
|
||||
tcp_pcb* listen_pcb = tcp_listen_with_backlog(pcb, backlog);
|
||||
|
||||
if (!listen_pcb) {
|
||||
tcp_close(pcb);
|
||||
return;
|
||||
}
|
||||
_listen_pcb = listen_pcb;
|
||||
_port = _listen_pcb->local_port;
|
||||
tcp_accept(listen_pcb, &WiFiServer::_s_accept);
|
||||
tcp_arg(listen_pcb, (void*) this);
|
||||
}
|
||||
|
||||
void WiFiServer::setNoDelay(bool nodelay) {
|
||||
_noDelay = nodelay ? _ndTrue : _ndFalse;
|
||||
}
|
||||
|
||||
bool WiFiServer::getNoDelay() {
|
||||
switch (_noDelay) {
|
||||
case _ndFalse: return false;
|
||||
case _ndTrue: return true;
|
||||
default: return WiFiClient::getDefaultNoDelay();
|
||||
}
|
||||
}
|
||||
|
||||
bool WiFiServer::hasClient() {
|
||||
if (_unclaimed) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t WiFiServer::hasClientData() {
|
||||
ClientContext *next = _unclaimed;
|
||||
while (next) {
|
||||
size_t s = next->getSize();
|
||||
// return the amount of data available from the first connection that has any
|
||||
if (s) {
|
||||
return s;
|
||||
}
|
||||
next = next->next();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WiFiServer::hasMaxPendingClients() {
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
return ((struct tcp_pcb_listen *)_listen_pcb)->accepts_pending >= MAX_PENDING_CLIENTS_PER_PORT;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
WiFiClient WiFiServer::available(byte* status) {
|
||||
(void) status;
|
||||
return accept();
|
||||
}
|
||||
|
||||
WiFiClient WiFiServer::accept() {
|
||||
if (_unclaimed) {
|
||||
WiFiClient result(_unclaimed);
|
||||
|
||||
// pcb can be null when peer has already closed the connection
|
||||
if (_unclaimed->getPCB()) {
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
// give permission to lwIP to accept one more peer
|
||||
tcp_backlog_accepted(_unclaimed->getPCB());
|
||||
}
|
||||
|
||||
_unclaimed = _unclaimed->next();
|
||||
result.setNoDelay(getNoDelay());
|
||||
DEBUGV("WS:av status=%d WCav=%d\r\n", result.status(), result.available());
|
||||
return result;
|
||||
}
|
||||
return WiFiClient();
|
||||
}
|
||||
|
||||
uint8_t WiFiServer::status() {
|
||||
if (!_listen_pcb) {
|
||||
return CLOSED;
|
||||
}
|
||||
return _listen_pcb->state;
|
||||
}
|
||||
|
||||
uint16_t WiFiServer::port() const {
|
||||
return _port;
|
||||
}
|
||||
|
||||
void WiFiServer::close() {
|
||||
if (!_listen_pcb) {
|
||||
return;
|
||||
}
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
tcp_close(_listen_pcb);
|
||||
_listen_pcb = nullptr;
|
||||
}
|
||||
|
||||
void WiFiServer::stop() {
|
||||
close();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* slist_append_tail(T* head, T* item) {
|
||||
if (!head) {
|
||||
return item;
|
||||
}
|
||||
T* last = head;
|
||||
while (last->next()) {
|
||||
last = last->next();
|
||||
}
|
||||
last->next(item);
|
||||
return head;
|
||||
}
|
||||
|
||||
err_t WiFiServer::_accept(tcp_pcb* apcb, err_t err) {
|
||||
(void) err;
|
||||
DEBUGV("WS:ac\r\n");
|
||||
|
||||
// always accept new PCB so incoming data can be stored in our buffers even before
|
||||
// user calls ::available()
|
||||
ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this);
|
||||
|
||||
// backlog doc:
|
||||
// http://lwip.100.n7.nabble.com/Problem-re-opening-listening-pbc-tt32484.html#a32494
|
||||
// https://www.nongnu.org/lwip/2_1_x/group__tcp__raw.html#gaeff14f321d1eecd0431611f382fcd338
|
||||
|
||||
// increase lwIP's backlog
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
tcp_backlog_delayed(apcb);
|
||||
|
||||
_unclaimed = slist_append_tail(_unclaimed, client);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void WiFiServer::_discard(ClientContext* client) {
|
||||
(void) client;
|
||||
// _discarded = slist_append_tail(_discarded, client);
|
||||
DEBUGV("WS:dis\r\n");
|
||||
}
|
||||
|
||||
err_t WiFiServer::_s_accept(void *arg, tcp_pcb* newpcb, err_t err) {
|
||||
return reinterpret_cast<WiFiServer*>(arg)->_accept(newpcb, err);
|
||||
}
|
||||
|
||||
void WiFiServer::_s_discard(void* server, ClientContext* ctx) {
|
||||
reinterpret_cast<WiFiServer*>(server)->_discard(ctx);
|
||||
}
|
||||
109
libraries/WiFi/src/WiFiServer.h
Normal file
109
libraries/WiFi/src/WiFiServer.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
WiFiServer.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified by Ivan Grokhotkov, December 2014 - esp8266 support
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wl_definitions.h>
|
||||
struct tcp_pcb;
|
||||
|
||||
#include <LWIPMutex.h>
|
||||
#include <Server.h>
|
||||
#include <IPAddress.h>
|
||||
#include <lwip/err.h>
|
||||
|
||||
// lwIP-v2 backlog facility allows to keep memory safe by limiting the
|
||||
// maximum number of incoming *pending clients*. Default number of possibly
|
||||
// simultaneously pending clients is defined in WiFiServer.cpp
|
||||
// (MAX_PENDING_CLIENTS_PER_PORT=5). User can override it at runtime from
|
||||
// sketch:
|
||||
// WiFiServer::begin(port, max-simultaneous-pending-clients);
|
||||
//
|
||||
// An "incoming pending" client is a new incoming TCP connection trying to
|
||||
// reach the TCP server. It is "pending" until lwIP acknowledges it and
|
||||
// "accepted / no more pending" when user calls WiFiServer::available().
|
||||
//
|
||||
// Before the backlog feature or with lwIP-v1.4, there was no pending
|
||||
// connections: They were immediately accepted and filling RAM.
|
||||
//
|
||||
// Several pending clients can appear during the time when one client is
|
||||
// served by a long not-async service like ESP8266WebServer. During that
|
||||
// time WiFiServer::available() cannot be called.
|
||||
//
|
||||
// Note: This *does not limit* the number of *simultaneously accepted
|
||||
// clients*. Such limit management is left to the user.
|
||||
//
|
||||
// Thus, when the maximum number of pending connections is reached, new
|
||||
// connections are delayed.
|
||||
// By "delayed", it is meant that WiFiServer(lwIP) will not answer to the
|
||||
// SYN packet until there is room for a new one: The TCP server on that port
|
||||
// will be mute. The TCP client will regularly try to connect until success
|
||||
// or a timeout occurs (72s on windows).
|
||||
//
|
||||
// When user calls WiFiServer::available(), the tcp server stops muting and
|
||||
// answers to newcomers (until the "backlog" pending list is full again).
|
||||
|
||||
class ClientContext;
|
||||
class WiFiClient;
|
||||
|
||||
class WiFiServer {
|
||||
// Secure server needs access to all the private entries here
|
||||
protected:
|
||||
uint16_t _port;
|
||||
IPAddress _addr;
|
||||
tcp_pcb* _listen_pcb = nullptr;
|
||||
|
||||
ClientContext* _unclaimed = nullptr;
|
||||
ClientContext* _discarded = nullptr;
|
||||
enum { _ndDefault, _ndFalse, _ndTrue } _noDelay = _ndDefault;
|
||||
|
||||
public:
|
||||
WiFiServer(const IPAddress& addr, uint16_t port);
|
||||
WiFiServer(uint16_t port);
|
||||
virtual ~WiFiServer() {}
|
||||
WiFiClient accept(); // https://www.arduino.cc/en/Reference/EthernetServerAccept
|
||||
WiFiClient available(uint8_t* status = NULL);
|
||||
bool hasClient();
|
||||
// hasClientData():
|
||||
// returns the amount of data available from the first client
|
||||
// or 0 if there is none
|
||||
size_t hasClientData();
|
||||
// hasMaxPendingClients():
|
||||
// returns true if the queue of pending clients is full
|
||||
bool hasMaxPendingClients();
|
||||
void begin();
|
||||
void begin(uint16_t port);
|
||||
void begin(uint16_t port, uint8_t backlog);
|
||||
void setNoDelay(bool nodelay);
|
||||
bool getNoDelay();
|
||||
uint8_t status();
|
||||
uint16_t port() const;
|
||||
void close();
|
||||
void stop();
|
||||
|
||||
using ClientType = WiFiClient;
|
||||
|
||||
protected:
|
||||
err_t _accept(tcp_pcb* newpcb, err_t err);
|
||||
void _discard(ClientContext* client);
|
||||
|
||||
static err_t _s_accept(void *arg, tcp_pcb* newpcb, err_t err);
|
||||
static void _s_discard(void* server, ClientContext* ctx);
|
||||
};
|
||||
263
libraries/WiFi/src/WiFiUdp.cpp
Normal file
263
libraries/WiFi/src/WiFiUdp.cpp
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
WiFiUdp.cpp - UDP client/server for esp8266, mostly compatible
|
||||
with Arduino WiFi shield library
|
||||
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "wl_definitions.h"
|
||||
|
||||
//#include "debug.h"
|
||||
#include "WiFi.h"
|
||||
#include "WiFiUdp.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include <include/UdpContext.h>
|
||||
|
||||
template<>
|
||||
WiFiUDP* SList<WiFiUDP>::_s_first = 0;
|
||||
|
||||
/* Constructor */
|
||||
WiFiUDP::WiFiUDP() : _ctx(0) {
|
||||
WiFiUDP::_add(this);
|
||||
}
|
||||
|
||||
WiFiUDP::WiFiUDP(const WiFiUDP& other) {
|
||||
_ctx = other._ctx;
|
||||
if (_ctx) {
|
||||
_ctx->ref();
|
||||
}
|
||||
WiFiUDP::_add(this);
|
||||
}
|
||||
|
||||
WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs) {
|
||||
_ctx = rhs._ctx;
|
||||
if (_ctx) {
|
||||
_ctx->ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
WiFiUDP::~WiFiUDP() {
|
||||
WiFiUDP::_remove(this);
|
||||
if (_ctx) {
|
||||
_ctx->unref();
|
||||
}
|
||||
}
|
||||
|
||||
/* Start WiFiUDP socket, listening at local port */
|
||||
uint8_t WiFiUDP::begin(uint16_t port) {
|
||||
if (_ctx) {
|
||||
_ctx->unref();
|
||||
_ctx = 0;
|
||||
}
|
||||
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
return (_ctx->listen(IPAddress(), port)) ? 1 : 0;
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port) {
|
||||
if (_ctx) {
|
||||
_ctx->unref();
|
||||
_ctx = 0;
|
||||
}
|
||||
|
||||
if (igmp_joingroup(interfaceAddr, multicast) != ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
ip_addr_t addr = IPADDR4_INIT(INADDR_ANY);
|
||||
if (!_ctx->listen(&addr, port)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return number of bytes available in the current packet,
|
||||
will return zero if parsePacket hasn't been called yet */
|
||||
int WiFiUDP::available() {
|
||||
int result = 0;
|
||||
|
||||
if (_ctx) {
|
||||
result = static_cast<int>(_ctx->getSize());
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
// yielding here will not make more data "available",
|
||||
// but it will prevent the system from going into WDT reset
|
||||
delay(1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Release any resources being used by this WiFiUDP instance */
|
||||
void WiFiUDP::stop() {
|
||||
if (_ctx) {
|
||||
_ctx->disconnect();
|
||||
_ctx->unref();
|
||||
}
|
||||
_ctx = 0;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacket(const char *host, uint16_t port) {
|
||||
IPAddress remote_addr;
|
||||
if (WiFi.hostByName(host, remote_addr)) {
|
||||
return beginPacket(remote_addr, port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port) {
|
||||
if (!_ctx) {
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
}
|
||||
return (_ctx->connect(ip, port)) ? 1 : 0;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port,
|
||||
IPAddress interfaceAddress, int ttl) {
|
||||
if (!_ctx) {
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
}
|
||||
if (!_ctx->connect(multicastAddress, port)) {
|
||||
return 0;
|
||||
}
|
||||
_ctx->setMulticastInterface(interfaceAddress);
|
||||
_ctx->setMulticastTTL(ttl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiUDP::endPacket() {
|
||||
if (!_ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (_ctx->send()) ? 1 : 0;
|
||||
}
|
||||
|
||||
size_t WiFiUDP::write(uint8_t byte) {
|
||||
return write(&byte, 1);
|
||||
}
|
||||
|
||||
size_t WiFiUDP::write(const uint8_t *buffer, size_t size) {
|
||||
if (!_ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ctx->append(reinterpret_cast<const char*>(buffer), size);
|
||||
}
|
||||
|
||||
int WiFiUDP::parsePacket() {
|
||||
if (!_ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_ctx->next()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ctx->getSize();
|
||||
}
|
||||
|
||||
int WiFiUDP::read() {
|
||||
if (!_ctx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _ctx->read();
|
||||
}
|
||||
|
||||
int WiFiUDP::read(unsigned char* buffer, size_t len) {
|
||||
if (!_ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ctx->read(reinterpret_cast<char*>(buffer), len);
|
||||
}
|
||||
|
||||
int WiFiUDP::peek() {
|
||||
if (!_ctx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _ctx->peek();
|
||||
}
|
||||
|
||||
void WiFiUDP::flush() {
|
||||
endPacket();
|
||||
}
|
||||
|
||||
IPAddress WiFiUDP::remoteIP() {
|
||||
if (!_ctx) {
|
||||
return INADDR_ANY;
|
||||
}
|
||||
|
||||
return _ctx->getRemoteAddress();
|
||||
}
|
||||
|
||||
uint16_t WiFiUDP::remotePort() {
|
||||
if (!_ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ctx->getRemotePort();
|
||||
}
|
||||
|
||||
IPAddress WiFiUDP::destinationIP() const {
|
||||
if (!_ctx) {
|
||||
return INADDR_ANY;
|
||||
}
|
||||
|
||||
return _ctx->getDestAddress();
|
||||
}
|
||||
|
||||
uint16_t WiFiUDP::localPort() const {
|
||||
if (!_ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ctx->getLocalPort();
|
||||
}
|
||||
|
||||
void WiFiUDP::stopAll() {
|
||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||
DEBUGV("%s %p %p\n", __func__, it, _s_first);
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiUDP::stopAllExcept(WiFiUDP * exC) {
|
||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||
if (it->_ctx != exC->_ctx) {
|
||||
DEBUGV("%s %p %p\n", __func__, it, _s_first);
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
113
libraries/WiFi/src/WiFiUdp.h
Normal file
113
libraries/WiFi/src/WiFiUdp.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
WiFiUdp.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified by Ivan Grokhotkov, January 2015 - esp8266 support
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Udp.h>
|
||||
#include <include/slist.h>
|
||||
|
||||
#define UDP_TX_PACKET_MAX_SIZE 8192
|
||||
|
||||
class UdpContext;
|
||||
|
||||
class WiFiUDP : public UDP, public SList<WiFiUDP> {
|
||||
private:
|
||||
UdpContext* _ctx;
|
||||
|
||||
public:
|
||||
WiFiUDP(); // Constructor
|
||||
WiFiUDP(const WiFiUDP& other);
|
||||
WiFiUDP& operator=(const WiFiUDP& rhs);
|
||||
virtual ~WiFiUDP();
|
||||
|
||||
operator bool() const {
|
||||
return _ctx != 0;
|
||||
}
|
||||
|
||||
// initialize, start listening on specified port.
|
||||
// Returns 1 if successful, 0 if there are no sockets available to use
|
||||
uint8_t begin(uint16_t port) override;
|
||||
// Finish with the UDP connection
|
||||
void stop() override;
|
||||
// join a multicast group and listen on the given port
|
||||
uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port);
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
int beginPacket(IPAddress ip, uint16_t port) override;
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
int beginPacket(const char *host, uint16_t port) override;
|
||||
// Start building up a packet to send to the multicast address
|
||||
// multicastAddress - multicast address to send to
|
||||
// interfaceAddress - the local IP address of the interface that should be used
|
||||
// use WiFi.localIP() or WiFi.softAPIP() depending on the interface you need
|
||||
// ttl - multicast packet TTL (default is 1)
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
virtual int beginPacketMulticast(IPAddress multicastAddress,
|
||||
uint16_t port,
|
||||
IPAddress interfaceAddress,
|
||||
int ttl = 1);
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
int endPacket() override;
|
||||
// Write a single byte into the packet
|
||||
size_t write(uint8_t) override;
|
||||
// Write size bytes from buffer into the packet
|
||||
size_t write(const uint8_t *buffer, size_t size) override;
|
||||
|
||||
using Print::write;
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
int parsePacket() override;
|
||||
// Number of bytes remaining in the current packet
|
||||
int available() override;
|
||||
// Read a single byte from the current packet
|
||||
int read() override;
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
int read(unsigned char* buffer, size_t len) override;
|
||||
// Read up to len characters from the current packet and place them into buffer
|
||||
// Returns the number of characters read, or 0 if none are available
|
||||
int read(char* buffer, size_t len) override {
|
||||
return read((unsigned char*)buffer, len);
|
||||
};
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
int peek() override;
|
||||
void flush() override; // wait for all outgoing characters to be sent, output buffer is empty after this call
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
IPAddress remoteIP() override;
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
uint16_t remotePort() override;
|
||||
// Return the destination address for incoming packets,
|
||||
// useful to distinguish multicast and ordinary packets
|
||||
IPAddress destinationIP() const;
|
||||
// Return the local port for outgoing packets
|
||||
uint16_t localPort() const;
|
||||
|
||||
static void stopAll();
|
||||
static void stopAllExcept(WiFiUDP * exC);
|
||||
|
||||
};
|
||||
300
libraries/WiFi/src/dhcpserver/dhcpserver.c
Normal file
300
libraries/WiFi/src/dhcpserver/dhcpserver.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
This file is part of the MicroPython project, http://micropython.org/
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2019 Damien P. George
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// For DHCP specs see:
|
||||
// https://www.ietf.org/rfc/rfc2131.txt
|
||||
// https://tools.ietf.org/html/rfc2132 -- DHCP Options and BOOTP Vendor Extensions
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "cyw43_config.h"
|
||||
#include "dhcpserver.h"
|
||||
#include "lwip/udp.h"
|
||||
|
||||
#define DHCPDISCOVER (1)
|
||||
#define DHCPOFFER (2)
|
||||
#define DHCPREQUEST (3)
|
||||
#define DHCPDECLINE (4)
|
||||
#define DHCPACK (5)
|
||||
#define DHCPNACK (6)
|
||||
#define DHCPRELEASE (7)
|
||||
#define DHCPINFORM (8)
|
||||
|
||||
#define DHCP_OPT_PAD (0)
|
||||
#define DHCP_OPT_SUBNET_MASK (1)
|
||||
#define DHCP_OPT_ROUTER (3)
|
||||
#define DHCP_OPT_DNS (6)
|
||||
#define DHCP_OPT_HOST_NAME (12)
|
||||
#define DHCP_OPT_REQUESTED_IP (50)
|
||||
#define DHCP_OPT_IP_LEASE_TIME (51)
|
||||
#define DHCP_OPT_MSG_TYPE (53)
|
||||
#define DHCP_OPT_SERVER_ID (54)
|
||||
#define DHCP_OPT_PARAM_REQUEST_LIST (55)
|
||||
#define DHCP_OPT_MAX_MSG_SIZE (57)
|
||||
#define DHCP_OPT_VENDOR_CLASS_ID (60)
|
||||
#define DHCP_OPT_CLIENT_ID (61)
|
||||
#define DHCP_OPT_END (255)
|
||||
|
||||
#define PORT_DHCP_SERVER (67)
|
||||
#define PORT_DHCP_CLIENT (68)
|
||||
|
||||
#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8)
|
||||
#define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds
|
||||
|
||||
#define MAC_LEN (6)
|
||||
#define MAKE_IP4(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
|
||||
|
||||
typedef struct {
|
||||
uint8_t op; // message opcode
|
||||
uint8_t htype; // hardware address type
|
||||
uint8_t hlen; // hardware address length
|
||||
uint8_t hops;
|
||||
uint32_t xid; // transaction id, chosen by client
|
||||
uint16_t secs; // client seconds elapsed
|
||||
uint16_t flags;
|
||||
uint8_t ciaddr[4]; // client IP address
|
||||
uint8_t yiaddr[4]; // your IP address
|
||||
uint8_t siaddr[4]; // next server IP address
|
||||
uint8_t giaddr[4]; // relay agent IP address
|
||||
uint8_t chaddr[16]; // client hardware address
|
||||
uint8_t sname[64]; // server host name
|
||||
uint8_t file[128]; // boot file name
|
||||
uint8_t options[312]; // optional parameters, variable, starts with magic
|
||||
} dhcp_msg_t;
|
||||
|
||||
static int dhcp_socket_new_dgram(struct udp_pcb **udp, void *cb_data, udp_recv_fn cb_udp_recv) {
|
||||
// family is AF_INET
|
||||
// type is SOCK_DGRAM
|
||||
|
||||
*udp = udp_new();
|
||||
if (*udp == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// Register callback
|
||||
udp_recv(*udp, cb_udp_recv, (void *)cb_data);
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
static void dhcp_socket_free(struct udp_pcb **udp) {
|
||||
if (*udp != NULL) {
|
||||
udp_remove(*udp);
|
||||
*udp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int dhcp_socket_bind(struct udp_pcb **udp, uint32_t ip, uint16_t port) {
|
||||
ip_addr_t addr;
|
||||
IP_ADDR4(&addr, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff);
|
||||
// TODO convert lwIP errors to errno
|
||||
return udp_bind(*udp, &addr, port);
|
||||
}
|
||||
|
||||
static int dhcp_socket_sendto(struct udp_pcb **udp, const void *buf, size_t len, uint32_t ip, uint16_t port) {
|
||||
if (len > 0xffff) {
|
||||
len = 0xffff;
|
||||
}
|
||||
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(p->payload, buf, len);
|
||||
|
||||
ip_addr_t dest;
|
||||
IP_ADDR4(&dest, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff);
|
||||
err_t err = udp_sendto(*udp, p, &dest, port);
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint8_t *opt_find(uint8_t *opt, uint8_t cmd) {
|
||||
for (int i = 0; i < 308 && opt[i] != DHCP_OPT_END;) {
|
||||
if (opt[i] == cmd) {
|
||||
return &opt[i];
|
||||
}
|
||||
i += 2 + opt[i + 1];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void opt_write_n(uint8_t **opt, uint8_t cmd, size_t n, void *data) {
|
||||
uint8_t *o = *opt;
|
||||
*o++ = cmd;
|
||||
*o++ = n;
|
||||
memcpy(o, data, n);
|
||||
*opt = o + n;
|
||||
}
|
||||
|
||||
static void opt_write_u8(uint8_t **opt, uint8_t cmd, uint8_t val) {
|
||||
uint8_t *o = *opt;
|
||||
*o++ = cmd;
|
||||
*o++ = 1;
|
||||
*o++ = val;
|
||||
*opt = o;
|
||||
}
|
||||
|
||||
static void opt_write_u32(uint8_t **opt, uint8_t cmd, uint32_t val) {
|
||||
uint8_t *o = *opt;
|
||||
*o++ = cmd;
|
||||
*o++ = 4;
|
||||
*o++ = val >> 24;
|
||||
*o++ = val >> 16;
|
||||
*o++ = val >> 8;
|
||||
*o++ = val;
|
||||
*opt = o;
|
||||
}
|
||||
|
||||
static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *src_addr, u16_t src_port) {
|
||||
dhcp_server_t *d = arg;
|
||||
(void)upcb;
|
||||
(void)src_addr;
|
||||
(void)src_port;
|
||||
|
||||
// This is around 548 bytes
|
||||
dhcp_msg_t dhcp_msg;
|
||||
|
||||
#define DHCP_MIN_SIZE (240 + 3)
|
||||
if (p->tot_len < DHCP_MIN_SIZE) {
|
||||
goto ignore_request;
|
||||
}
|
||||
|
||||
size_t len = pbuf_copy_partial(p, &dhcp_msg, sizeof(dhcp_msg), 0);
|
||||
if (len < DHCP_MIN_SIZE) {
|
||||
goto ignore_request;
|
||||
}
|
||||
|
||||
dhcp_msg.op = DHCPOFFER;
|
||||
memcpy(&dhcp_msg.yiaddr, ip_2_ip4(&d->ip), 4);
|
||||
|
||||
uint8_t *opt = (uint8_t *)&dhcp_msg.options;
|
||||
opt += 4; // assume magic cookie: 99, 130, 83, 99
|
||||
|
||||
switch (opt[2]) {
|
||||
case DHCPDISCOVER: {
|
||||
int yi = DHCPS_MAX_IP;
|
||||
for (int i = 0; i < DHCPS_MAX_IP; ++i) {
|
||||
if (memcmp(d->lease[i].mac, dhcp_msg.chaddr, MAC_LEN) == 0) {
|
||||
// MAC match, use this IP address
|
||||
yi = i;
|
||||
break;
|
||||
}
|
||||
if (yi == DHCPS_MAX_IP) {
|
||||
// Look for a free IP address
|
||||
if (memcmp(d->lease[i].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) {
|
||||
// IP available
|
||||
yi = i;
|
||||
}
|
||||
uint32_t expiry = d->lease[i].expiry << 16 | 0xffff;
|
||||
if ((int32_t)(expiry - cyw43_hal_ticks_ms()) < 0) {
|
||||
// IP expired, reuse it
|
||||
memset(d->lease[i].mac, 0, MAC_LEN);
|
||||
yi = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yi == DHCPS_MAX_IP) {
|
||||
// No more IP addresses left
|
||||
goto ignore_request;
|
||||
}
|
||||
dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi;
|
||||
opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPOFFER);
|
||||
break;
|
||||
}
|
||||
|
||||
case DHCPREQUEST: {
|
||||
uint8_t *o = opt_find(opt, DHCP_OPT_REQUESTED_IP);
|
||||
if (o == NULL) {
|
||||
// Should be NACK
|
||||
goto ignore_request;
|
||||
}
|
||||
if (memcmp(o + 2, ip_2_ip4(&d->ip), 3) != 0) {
|
||||
// Should be NACK
|
||||
goto ignore_request;
|
||||
}
|
||||
uint8_t yi = o[5] - DHCPS_BASE_IP;
|
||||
if (yi >= DHCPS_MAX_IP) {
|
||||
// Should be NACK
|
||||
goto ignore_request;
|
||||
}
|
||||
if (memcmp(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN) == 0) {
|
||||
// MAC match, ok to use this IP address
|
||||
} else if (memcmp(d->lease[yi].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) {
|
||||
// IP unused, ok to use this IP address
|
||||
memcpy(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN);
|
||||
} else {
|
||||
// IP already in use
|
||||
// Should be NACK
|
||||
goto ignore_request;
|
||||
}
|
||||
d->lease[yi].expiry = (cyw43_hal_ticks_ms() + DEFAULT_LEASE_TIME_S * 1000) >> 16;
|
||||
dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi;
|
||||
opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPACK);
|
||||
/* printf("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n",
|
||||
dhcp_msg.chaddr[0], dhcp_msg.chaddr[1], dhcp_msg.chaddr[2], dhcp_msg.chaddr[3], dhcp_msg.chaddr[4], dhcp_msg.chaddr[5],
|
||||
dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3]);*/
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
goto ignore_request;
|
||||
}
|
||||
|
||||
opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, ip_2_ip4(&d->ip));
|
||||
opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, ip_2_ip4(&d->nm));
|
||||
opt_write_n(&opt, DHCP_OPT_ROUTER, 4, ip_2_ip4(&d->ip)); // aka gateway; can have multiple addresses
|
||||
opt_write_u32(&opt, DHCP_OPT_DNS, DEFAULT_DNS); // can have multiple addresses
|
||||
opt_write_u32(&opt, DHCP_OPT_IP_LEASE_TIME, DEFAULT_LEASE_TIME_S);
|
||||
*opt++ = DHCP_OPT_END;
|
||||
dhcp_socket_sendto(&d->udp, &dhcp_msg, opt - (uint8_t *)&dhcp_msg, 0xffffffff, PORT_DHCP_CLIENT);
|
||||
|
||||
ignore_request:
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm) {
|
||||
ip_addr_copy(d->ip, *ip);
|
||||
ip_addr_copy(d->nm, *nm);
|
||||
memset(d->lease, 0, sizeof(d->lease));
|
||||
if (dhcp_socket_new_dgram(&d->udp, d, dhcp_server_process) != 0) {
|
||||
return;
|
||||
}
|
||||
dhcp_socket_bind(&d->udp, 0, PORT_DHCP_SERVER);
|
||||
}
|
||||
|
||||
void dhcp_server_deinit(dhcp_server_t *d) {
|
||||
dhcp_socket_free(&d->udp);
|
||||
}
|
||||
57
libraries/WiFi/src/dhcpserver/dhcpserver.h
Normal file
57
libraries/WiFi/src/dhcpserver/dhcpserver.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
This file is part of the MicroPython project, http://micropython.org/
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2019 Damien P. George
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H
|
||||
#define MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#define DHCPS_BASE_IP (16)
|
||||
#define DHCPS_MAX_IP (8)
|
||||
|
||||
typedef struct _dhcp_server_lease_t {
|
||||
uint8_t mac[6];
|
||||
uint16_t expiry;
|
||||
} dhcp_server_lease_t;
|
||||
|
||||
typedef struct _dhcp_server_t {
|
||||
ip_addr_t ip;
|
||||
ip_addr_t nm;
|
||||
dhcp_server_lease_t lease[DHCPS_MAX_IP];
|
||||
struct udp_pcb *udp;
|
||||
} dhcp_server_t;
|
||||
|
||||
void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm);
|
||||
void dhcp_server_deinit(dhcp_server_t *d);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
#endif // MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H
|
||||
687
libraries/WiFi/src/include/ClientContext.h
Normal file
687
libraries/WiFi/src/include/ClientContext.h
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
/*
|
||||
ClientContext.h - TCP connection handling on top of lwIP
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class ClientContext;
|
||||
class WiFiClient;
|
||||
|
||||
typedef void (*discard_cb_t)(void*, ClientContext*);
|
||||
|
||||
#include <assert.h>
|
||||
//#include <esp_priv.h>
|
||||
//#include <coredecls.h>
|
||||
|
||||
bool getDefaultPrivateGlobalSyncValue();
|
||||
|
||||
template <typename T>
|
||||
inline void esp_delay(const uint32_t timeout_ms, T&& blocked, const uint32_t intvl_ms) {
|
||||
const auto start_ms = millis();
|
||||
while ((((uint32_t)millis() - start_ms) < timeout_ms) && blocked()) {
|
||||
delay(intvl_ms);
|
||||
}
|
||||
}
|
||||
|
||||
class ClientContext {
|
||||
public:
|
||||
ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg) :
|
||||
_pcb(pcb), _rx_buf(0), _rx_buf_offset(0), _discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0),
|
||||
_sync(::getDefaultPrivateGlobalSyncValue()) {
|
||||
tcp_setprio(_pcb, TCP_PRIO_MIN);
|
||||
tcp_arg(_pcb, this);
|
||||
tcp_recv(_pcb, &_s_recv);
|
||||
tcp_sent(_pcb, &_s_acked);
|
||||
tcp_err(_pcb, &_s_error);
|
||||
tcp_poll(_pcb, &_s_poll, 1);
|
||||
|
||||
// keep-alive not enabled by default
|
||||
//keepAlive();
|
||||
}
|
||||
|
||||
tcp_pcb* getPCB() {
|
||||
return _pcb;
|
||||
}
|
||||
|
||||
err_t abort() {
|
||||
if (_pcb) {
|
||||
DEBUGV(":abort\r\n");
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
tcp_abort(_pcb);
|
||||
_pcb = nullptr;
|
||||
}
|
||||
return ERR_ABRT;
|
||||
}
|
||||
|
||||
err_t close() {
|
||||
err_t err = ERR_OK;
|
||||
if (_pcb) {
|
||||
DEBUGV(":close\r\n");
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
err = tcp_close(_pcb);
|
||||
if (err != ERR_OK) {
|
||||
DEBUGV(":tc err %d\r\n", (int) err);
|
||||
tcp_abort(_pcb);
|
||||
err = ERR_ABRT;
|
||||
}
|
||||
_pcb = nullptr;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
~ClientContext() {
|
||||
}
|
||||
|
||||
ClientContext* next() const {
|
||||
return _next;
|
||||
}
|
||||
|
||||
ClientContext* next(ClientContext* new_next) {
|
||||
_next = new_next;
|
||||
return _next;
|
||||
}
|
||||
|
||||
void ref() {
|
||||
++_refcnt;
|
||||
DEBUGV(":ref %d\r\n", _refcnt);
|
||||
}
|
||||
|
||||
void unref() {
|
||||
DEBUGV(":ur %d\r\n", _refcnt);
|
||||
if (--_refcnt == 0) {
|
||||
discard_received();
|
||||
close();
|
||||
if (_discard_cb) {
|
||||
_discard_cb(_discard_cb_arg, this);
|
||||
}
|
||||
DEBUGV(":del\r\n");
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
int connect(ip_addr_t* addr, uint16_t port) {
|
||||
// note: not using `const ip_addr_t* addr` because
|
||||
// - `ip6_addr_assign_zone()` below modifies `*addr`
|
||||
// - caller's parameter `WiFiClient::connect` is a local copy
|
||||
#if LWIP_IPV6
|
||||
// Set zone so that link local addresses use the default interface
|
||||
if (IP_IS_V6(addr) && ip6_addr_lacks_zone(ip_2_ip6(addr), IP6_UNKNOWN)) {
|
||||
ip6_addr_assign_zone(ip_2_ip6(addr), IP6_UNKNOWN, netif_default);
|
||||
}
|
||||
#endif
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
err_t err = tcp_connect(_pcb, addr, port, &ClientContext::_s_connected);
|
||||
if (err != ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
_connect_pending = true;
|
||||
_op_start_time = millis();
|
||||
// will resume on timeout or when _connected or _notify_error fires
|
||||
// give scheduled functions a chance to run (e.g. Ethernet uses recurrent)
|
||||
esp_delay(_timeout_ms, [this]() {
|
||||
return this->_connect_pending;
|
||||
}, 1);
|
||||
_connect_pending = false;
|
||||
if (!_pcb) {
|
||||
DEBUGV(":cabrt\r\n");
|
||||
return 0;
|
||||
}
|
||||
if (state() != ESTABLISHED) {
|
||||
DEBUGV(":ctmo\r\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t availableForWrite() const {
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
return _pcb ? tcp_sndbuf(_pcb) : 0;
|
||||
}
|
||||
|
||||
void setNoDelay(bool nodelay) {
|
||||
if (!_pcb) {
|
||||
return;
|
||||
}
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
if (nodelay) {
|
||||
tcp_nagle_disable(_pcb);
|
||||
} else {
|
||||
tcp_nagle_enable(_pcb);
|
||||
}
|
||||
}
|
||||
|
||||
bool getNoDelay() const {
|
||||
if (!_pcb) {
|
||||
return false;
|
||||
}
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
return tcp_nagle_disabled(_pcb);
|
||||
}
|
||||
|
||||
void setTimeout(int timeout_ms) {
|
||||
_timeout_ms = timeout_ms;
|
||||
}
|
||||
|
||||
int getTimeout() const {
|
||||
return _timeout_ms;
|
||||
}
|
||||
|
||||
const ip_addr_t* getRemoteAddress() const {
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return &_pcb->remote_ip;
|
||||
}
|
||||
|
||||
uint16_t getRemotePort() const {
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _pcb->remote_port;
|
||||
}
|
||||
|
||||
const ip_addr_t* getLocalAddress() const {
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return &_pcb->local_ip;
|
||||
}
|
||||
|
||||
uint16_t getLocalPort() const {
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _pcb->local_port;
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _rx_buf->tot_len - _rx_buf_offset;
|
||||
}
|
||||
|
||||
char read() {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char c = reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||
_consume(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t read(char* dst, size_t size) {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_size = _rx_buf->tot_len - _rx_buf_offset;
|
||||
size = (size < max_size) ? size : max_size;
|
||||
|
||||
DEBUGV(":rd %d, %d, %d\r\n", size, _rx_buf->tot_len, _rx_buf_offset);
|
||||
size_t size_read = 0;
|
||||
while (size) {
|
||||
size_t buf_size = _rx_buf->len - _rx_buf_offset;
|
||||
size_t copy_size = (size < buf_size) ? size : buf_size;
|
||||
DEBUGV(":rdi %d, %d\r\n", buf_size, copy_size);
|
||||
memcpy(dst, reinterpret_cast<char*>(_rx_buf->payload) + _rx_buf_offset, copy_size);
|
||||
dst += copy_size;
|
||||
_consume(copy_size);
|
||||
size -= copy_size;
|
||||
size_read += copy_size;
|
||||
}
|
||||
return size_read;
|
||||
}
|
||||
|
||||
char peek() const {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||
}
|
||||
|
||||
size_t peekBytes(char *dst, size_t size) const {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_size = _rx_buf->tot_len - _rx_buf_offset;
|
||||
size = (size < max_size) ? size : max_size;
|
||||
|
||||
DEBUGV(":pd %d, %d, %d\r\n", size, _rx_buf->tot_len, _rx_buf_offset);
|
||||
size_t buf_size = _rx_buf->len - _rx_buf_offset;
|
||||
size_t copy_size = (size < buf_size) ? size : buf_size;
|
||||
DEBUGV(":rpi %d, %d\r\n", buf_size, copy_size);
|
||||
memcpy(dst, reinterpret_cast<char*>(_rx_buf->payload) + _rx_buf_offset, copy_size);
|
||||
return copy_size;
|
||||
}
|
||||
|
||||
void discard_received() {
|
||||
DEBUGV(":dsrcv %d\n", _rx_buf ? _rx_buf->tot_len : 0);
|
||||
if (!_rx_buf) {
|
||||
return;
|
||||
}
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
if (_pcb) {
|
||||
tcp_recved(_pcb, (size_t) _rx_buf->tot_len);
|
||||
}
|
||||
pbuf_free(_rx_buf);
|
||||
_rx_buf = 0;
|
||||
_rx_buf_offset = 0;
|
||||
}
|
||||
|
||||
bool wait_until_acked(int max_wait_ms = WIFICLIENT_MAX_FLUSH_WAIT_MS) {
|
||||
// https://github.com/esp8266/Arduino/pull/3967#pullrequestreview-83451496
|
||||
// option 1 done
|
||||
// option 2 / _write_some() not necessary since _datasource is always nullptr here
|
||||
|
||||
if (!_pcb) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int prevsndbuf = -1;
|
||||
|
||||
// wait for peer's acks to flush lwIP's output buffer
|
||||
uint32_t last_sent = millis();
|
||||
while (1) {
|
||||
if (millis() - last_sent > (uint32_t) max_wait_ms) {
|
||||
#ifdef DEBUGV
|
||||
// wait until sent: timeout
|
||||
DEBUGV(":wustmo\n");
|
||||
#endif
|
||||
// All data was not flushed, timeout hit
|
||||
return false;
|
||||
}
|
||||
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
|
||||
// force lwIP to send what can be sent
|
||||
tcp_output(_pcb);
|
||||
|
||||
int sndbuf = tcp_sndbuf(_pcb);
|
||||
if (sndbuf != prevsndbuf) {
|
||||
// send buffer has changed (or first iteration)
|
||||
prevsndbuf = sndbuf;
|
||||
// We just sent a bit, move timeout forward
|
||||
last_sent = millis();
|
||||
}
|
||||
|
||||
// esp_yield(); // from sys or os context
|
||||
|
||||
if ((state() != ESTABLISHED) || (sndbuf == TCP_SND_BUF)) {
|
||||
// peer has closed or all bytes are sent and acked
|
||||
// ((TCP_SND_BUF-sndbuf) is the amount of un-acked bytes)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// All data flushed
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t state() const {
|
||||
if (!_pcb || _pcb->state == CLOSE_WAIT || _pcb->state == CLOSING) {
|
||||
// CLOSED for WiFIClient::status() means nothing more can be written
|
||||
return CLOSED;
|
||||
}
|
||||
|
||||
return _pcb->state;
|
||||
}
|
||||
|
||||
size_t write(const char* ds, const size_t dl) {
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
return _write_from_source(ds, dl);
|
||||
}
|
||||
|
||||
void keepAlive(uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC, uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC, uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT) {
|
||||
if (idle_sec && intv_sec && count) {
|
||||
_pcb->so_options |= SOF_KEEPALIVE;
|
||||
_pcb->keep_idle = (uint32_t)1000 * idle_sec;
|
||||
_pcb->keep_intvl = (uint32_t)1000 * intv_sec;
|
||||
_pcb->keep_cnt = count;
|
||||
} else {
|
||||
_pcb->so_options &= ~SOF_KEEPALIVE;
|
||||
}
|
||||
}
|
||||
|
||||
bool isKeepAliveEnabled() const {
|
||||
return !!(_pcb->so_options & SOF_KEEPALIVE);
|
||||
}
|
||||
|
||||
uint16_t getKeepAliveIdle() const {
|
||||
return isKeepAliveEnabled() ? (_pcb->keep_idle + 500) / 1000 : 0;
|
||||
}
|
||||
|
||||
uint16_t getKeepAliveInterval() const {
|
||||
return isKeepAliveEnabled() ? (_pcb->keep_intvl + 500) / 1000 : 0;
|
||||
}
|
||||
|
||||
uint8_t getKeepAliveCount() const {
|
||||
return isKeepAliveEnabled() ? _pcb->keep_cnt : 0;
|
||||
}
|
||||
|
||||
bool getSync() const {
|
||||
return _sync;
|
||||
}
|
||||
|
||||
void setSync(bool sync) {
|
||||
_sync = sync;
|
||||
}
|
||||
|
||||
// return a pointer to available data buffer (size = peekAvailable())
|
||||
// semantic forbids any kind of read() before calling peekConsume()
|
||||
const char* peekBuffer() {
|
||||
if (!_rx_buf) {
|
||||
return nullptr;
|
||||
}
|
||||
return (const char*)_rx_buf->payload + _rx_buf_offset;
|
||||
}
|
||||
|
||||
// return number of byte accessible by peekBuffer()
|
||||
size_t peekAvailable() {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
return _rx_buf->len - _rx_buf_offset;
|
||||
}
|
||||
|
||||
// consume bytes after use (see peekBuffer)
|
||||
void peekConsume(size_t consume) {
|
||||
_consume(consume);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool _is_timeout() {
|
||||
return millis() - _op_start_time > _timeout_ms;
|
||||
}
|
||||
|
||||
void _notify_error() {
|
||||
if (_connect_pending || _send_waiting) {
|
||||
// resume connect or _write_from_source
|
||||
_send_waiting = false;
|
||||
_connect_pending = false;
|
||||
//esp_schedule();
|
||||
}
|
||||
}
|
||||
|
||||
size_t _write_from_source(const char* ds, const size_t dl) {
|
||||
assert(_datasource == nullptr);
|
||||
assert(!_send_waiting);
|
||||
_datasource = ds;
|
||||
_datalen = dl;
|
||||
_written = 0;
|
||||
_op_start_time = millis();
|
||||
do {
|
||||
if (_write_some()) {
|
||||
_op_start_time = millis();
|
||||
}
|
||||
|
||||
if (_written == _datalen || _is_timeout() || state() == CLOSED) {
|
||||
if (_is_timeout()) {
|
||||
DEBUGV(":wtmo\r\n");
|
||||
}
|
||||
_datasource = nullptr;
|
||||
_datalen = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
_send_waiting = true;
|
||||
// will resume on timeout or when _write_some_from_cb or _notify_error fires
|
||||
// give scheduled functions a chance to run (e.g. Ethernet uses recurrent)
|
||||
esp_delay(_timeout_ms, [this]() {
|
||||
return this->_send_waiting;
|
||||
}, 1);
|
||||
_send_waiting = false;
|
||||
} while (true);
|
||||
|
||||
if (_sync) {
|
||||
wait_until_acked();
|
||||
}
|
||||
|
||||
return _written;
|
||||
}
|
||||
|
||||
bool _write_some() {
|
||||
if (!_datasource || !_pcb) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUGV(":wr %d %d\r\n", _datalen - _written, _written);
|
||||
|
||||
bool has_written = false;
|
||||
|
||||
while (_written < _datalen) {
|
||||
if (state() == CLOSED) {
|
||||
return false;
|
||||
}
|
||||
const auto remaining = _datalen - _written;
|
||||
size_t next_chunk_size;
|
||||
{
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call, just for this call
|
||||
next_chunk_size = std::min((size_t)tcp_sndbuf(_pcb), remaining);
|
||||
}
|
||||
if (!next_chunk_size) {
|
||||
break;
|
||||
}
|
||||
const char* buf = _datasource + _written;
|
||||
|
||||
uint8_t flags = 0;
|
||||
if (next_chunk_size < remaining)
|
||||
// PUSH is meant for peer, telling to give data to user app as soon as received
|
||||
// PUSH "may be set" when sender has finished sending a "meaningful" data block
|
||||
// PUSH does not break Nagle
|
||||
// #5173: windows needs this flag
|
||||
// more info: https://lists.gnu.org/archive/html/lwip-users/2009-11/msg00018.html
|
||||
{
|
||||
flags |= TCP_WRITE_FLAG_MORE; // do not tcp-PuSH (yet)
|
||||
}
|
||||
if (!_sync)
|
||||
// user data must be copied when data are sent but not yet acknowledged
|
||||
// (with sync, we wait for acknowledgment before returning to user)
|
||||
{
|
||||
flags |= TCP_WRITE_FLAG_COPY;
|
||||
}
|
||||
|
||||
err_t err = tcp_write(_pcb, buf, next_chunk_size, flags);
|
||||
|
||||
DEBUGV(":wrc %d %d %d\r\n", next_chunk_size, remaining, (int)err);
|
||||
|
||||
if (err == ERR_OK) {
|
||||
_written += next_chunk_size;
|
||||
has_written = true;
|
||||
} else {
|
||||
// ERR_MEM(-1) is a valid error meaning
|
||||
// "come back later". It leaves state() opened
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_written) {
|
||||
// lwIP's tcp_output doc: "Find out what we can send and send it"
|
||||
// *with respect to Nagle*
|
||||
// more info: https://lists.gnu.org/archive/html/lwip-users/2017-11/msg00134.html
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
tcp_output(_pcb);
|
||||
}
|
||||
|
||||
return has_written;
|
||||
}
|
||||
|
||||
void _write_some_from_cb() {
|
||||
if (_send_waiting) {
|
||||
// resume _write_from_source
|
||||
_send_waiting = false;
|
||||
//esp_schedule();
|
||||
}
|
||||
}
|
||||
|
||||
err_t _acked(tcp_pcb* pcb, uint16_t len) {
|
||||
(void) pcb;
|
||||
(void) len;
|
||||
DEBUGV(":ack %d\r\n", len);
|
||||
_write_some_from_cb();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void _consume(size_t size) {
|
||||
ptrdiff_t left = _rx_buf->len - _rx_buf_offset - size;
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
if (left > 0) {
|
||||
_rx_buf_offset += size;
|
||||
} else if (!_rx_buf->next) {
|
||||
DEBUGV(":c0 %d, %d\r\n", size, _rx_buf->tot_len);
|
||||
pbuf_free(_rx_buf);
|
||||
_rx_buf = 0;
|
||||
_rx_buf_offset = 0;
|
||||
} else {
|
||||
DEBUGV(":c %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf->tot_len);
|
||||
auto head = _rx_buf;
|
||||
_rx_buf = _rx_buf->next;
|
||||
_rx_buf_offset = 0;
|
||||
pbuf_ref(_rx_buf);
|
||||
pbuf_free(head);
|
||||
}
|
||||
if (_pcb) {
|
||||
tcp_recved(_pcb, size);
|
||||
}
|
||||
}
|
||||
|
||||
err_t _recv(tcp_pcb* pcb, pbuf* pb, err_t err) {
|
||||
(void) pcb;
|
||||
(void) err;
|
||||
if (pb == 0) {
|
||||
// connection closed by peer
|
||||
DEBUGV(":rcl pb=%p sz=%d\r\n", _rx_buf, _rx_buf ? _rx_buf->tot_len : -1);
|
||||
_notify_error();
|
||||
if (_rx_buf && _rx_buf->tot_len) {
|
||||
// there is still something to read
|
||||
return ERR_OK;
|
||||
} else {
|
||||
// nothing in receive buffer,
|
||||
// peer closed = nothing can be written:
|
||||
// closing in the legacy way
|
||||
abort();
|
||||
return ERR_ABRT;
|
||||
}
|
||||
}
|
||||
|
||||
if (_rx_buf) {
|
||||
DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
|
||||
LWIPMutex m; // Block the timer sys_check_timeouts call
|
||||
pbuf_cat(_rx_buf, pb);
|
||||
} else {
|
||||
DEBUGV(":rn %d\r\n", pb->tot_len);
|
||||
_rx_buf = pb;
|
||||
_rx_buf_offset = 0;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void _error(err_t err) {
|
||||
(void) err;
|
||||
DEBUGV(":er %d 0x%08x\r\n", (int) err, (uint32_t) _datasource);
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
_pcb = nullptr;
|
||||
_notify_error();
|
||||
}
|
||||
|
||||
err_t _connected(struct tcp_pcb *pcb, err_t err) {
|
||||
(void) err;
|
||||
(void) pcb;
|
||||
assert(pcb == _pcb);
|
||||
if (_connect_pending) {
|
||||
// resume connect
|
||||
_connect_pending = false;
|
||||
//esp_schedule();
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t _poll(tcp_pcb*) {
|
||||
_write_some_from_cb();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err) {
|
||||
return reinterpret_cast<ClientContext*>(arg)->_recv(tpcb, pb, err);
|
||||
}
|
||||
|
||||
static void _s_error(void *arg, err_t err) {
|
||||
reinterpret_cast<ClientContext*>(arg)->_error(err);
|
||||
}
|
||||
|
||||
static err_t _s_poll(void *arg, struct tcp_pcb *tpcb) {
|
||||
return reinterpret_cast<ClientContext*>(arg)->_poll(tpcb);
|
||||
}
|
||||
|
||||
static err_t _s_acked(void *arg, struct tcp_pcb *tpcb, uint16_t len) {
|
||||
return reinterpret_cast<ClientContext*>(arg)->_acked(tpcb, len);
|
||||
}
|
||||
|
||||
static err_t _s_connected(void* arg, struct tcp_pcb *pcb, err_t err) {
|
||||
return reinterpret_cast<ClientContext*>(arg)->_connected(pcb, err);
|
||||
}
|
||||
|
||||
private:
|
||||
tcp_pcb* _pcb;
|
||||
|
||||
pbuf* _rx_buf;
|
||||
size_t _rx_buf_offset;
|
||||
|
||||
discard_cb_t _discard_cb;
|
||||
void* _discard_cb_arg;
|
||||
|
||||
const char* _datasource = nullptr;
|
||||
size_t _datalen = 0;
|
||||
size_t _written = 0;
|
||||
uint32_t _timeout_ms = 5000;
|
||||
uint32_t _op_start_time = 0;
|
||||
bool _send_waiting = false;
|
||||
bool _connect_pending = false;
|
||||
|
||||
int8_t _refcnt;
|
||||
ClientContext* _next;
|
||||
|
||||
bool _sync;
|
||||
};
|
||||
581
libraries/WiFi/src/include/UdpContext.h
Normal file
581
libraries/WiFi/src/include/UdpContext.h
Normal file
|
|
@ -0,0 +1,581 @@
|
|||
/*
|
||||
UdpContext.h - UDP connection handling on top of lwIP
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef UDPCONTEXT_H
|
||||
#define UDPCONTEXT_H
|
||||
|
||||
class UdpContext;
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
#include <AddrList.h>
|
||||
//#include <PolledTimeout.h>
|
||||
|
||||
#define PBUF_ALIGNER_ADJUST 4
|
||||
#define PBUF_ALIGNER(x) ((void*)((((intptr_t)(x))+3)&~3))
|
||||
#define PBUF_HELPER_FLAG 0xff // lwIP pbuf flag: u8_t
|
||||
|
||||
class UdpContext {
|
||||
public:
|
||||
|
||||
typedef std::function<void(void)> rxhandler_t;
|
||||
|
||||
UdpContext()
|
||||
: _pcb(0)
|
||||
, _rx_buf(0)
|
||||
, _first_buf_taken(false)
|
||||
, _rx_buf_offset(0)
|
||||
, _rx_buf_size(0)
|
||||
, _refcnt(0)
|
||||
, _tx_buf_head(0)
|
||||
, _tx_buf_cur(0)
|
||||
, _tx_buf_offset(0) {
|
||||
_pcb = udp_new();
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
_mcast_ttl = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
~UdpContext() {
|
||||
udp_remove(_pcb);
|
||||
_pcb = 0;
|
||||
if (_tx_buf_head) {
|
||||
pbuf_free(_tx_buf_head);
|
||||
_tx_buf_head = 0;
|
||||
_tx_buf_cur = 0;
|
||||
_tx_buf_offset = 0;
|
||||
}
|
||||
if (_rx_buf) {
|
||||
pbuf_free(_rx_buf);
|
||||
_rx_buf = 0;
|
||||
_rx_buf_offset = 0;
|
||||
_rx_buf_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ref() {
|
||||
++_refcnt;
|
||||
}
|
||||
|
||||
void unref() {
|
||||
DEBUGV(":ur %d\r\n", _refcnt);
|
||||
if (--_refcnt == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
bool connect(const IPAddress& addr, uint16_t port) {
|
||||
_pcb->remote_ip = addr;
|
||||
_pcb->remote_port = port;
|
||||
#if LWIP_IPV6
|
||||
// Set zone so that link local addresses use the default interface
|
||||
if (IP_IS_V6(&_pcb->remote_ip) && ip6_addr_lacks_zone(ip_2_ip6(&_pcb->remote_ip), IP6_UNKNOWN)) {
|
||||
ip6_addr_assign_zone(ip_2_ip6(&_pcb->remote_ip), IP6_UNKNOWN, netif_default);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool listen(const IPAddress& addr, uint16_t port) {
|
||||
udp_recv(_pcb, &_s_recv, (void *) this);
|
||||
err_t err = udp_bind(_pcb, addr, port);
|
||||
return err == ERR_OK;
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
udp_disconnect(_pcb);
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
|
||||
void setMulticastInterface(IPAddress addr) {
|
||||
// Per 'udp_set_multicast_netif_addr()' signature and comments
|
||||
// in lwIP sources:
|
||||
// An IPv4 address designating a specific interface must be used.
|
||||
// When an IPv6 address is given, the matching IPv4 in the same
|
||||
// interface must be selected.
|
||||
|
||||
if (!addr.isV4()) {
|
||||
for (auto a : addrList)
|
||||
if (a.addr() == addr) {
|
||||
// found the IPv6 address,
|
||||
// redirect parameter to IPv4 address in this interface
|
||||
addr = a.ipv4();
|
||||
break;
|
||||
}
|
||||
assert(addr.isV4());
|
||||
}
|
||||
udp_set_multicast_netif_addr(_pcb, ip_2_ip4((const ip_addr_t*)addr));
|
||||
}
|
||||
|
||||
#else // !LWIP_IPV6
|
||||
|
||||
void setMulticastInterface(const IPAddress& addr) {
|
||||
udp_set_multicast_netif_addr(_pcb, ip_2_ip4((const ip_addr_t*)addr));
|
||||
}
|
||||
|
||||
#endif // !LWIP_IPV6
|
||||
|
||||
/*
|
||||
Add a netif (by its index) as the multicast interface
|
||||
*/
|
||||
void setMulticastInterface(netif* p_pNetIf) {
|
||||
udp_set_multicast_netif_index(_pcb, (p_pNetIf ? netif_get_index(p_pNetIf) : NETIF_NO_INDEX));
|
||||
}
|
||||
|
||||
/*
|
||||
Allow access to pcb to change eg. options
|
||||
*/
|
||||
udp_pcb* pcb(void) {
|
||||
return _pcb;
|
||||
}
|
||||
|
||||
void setMulticastTTL(int ttl) {
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
_mcast_ttl = ttl;
|
||||
#else
|
||||
udp_set_multicast_ttl(_pcb, ttl);
|
||||
#endif
|
||||
}
|
||||
|
||||
// warning: handler is called from tcp stack context
|
||||
// esp_suspend and non-reentrant functions which depend on it will fail
|
||||
void onRx(rxhandler_t handler) {
|
||||
_on_rx = handler;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ESP_CORE
|
||||
// this helper is ready to be used when debugging UDP
|
||||
void printChain(const pbuf* pb, const char* msg, size_t n) const {
|
||||
// printf the pb pbuf chain, buffered and all at once
|
||||
char buf[128];
|
||||
int l = snprintf(buf, sizeof(buf), "UDP: %s %u: ", msg, n);
|
||||
while (pb) {
|
||||
l += snprintf(&buf[l], sizeof(buf) - l, "%p(H=%d,%d<=%d)-",
|
||||
pb, pb->flags == PBUF_HELPER_FLAG, pb->len, pb->tot_len);
|
||||
pb = pb->next;
|
||||
}
|
||||
l += snprintf(&buf[l], sizeof(buf) - l, "(end)");
|
||||
DEBUGV("%s\n", buf);
|
||||
}
|
||||
#else
|
||||
void printChain(const pbuf* pb, const char* msg) const {
|
||||
(void)pb;
|
||||
(void)msg;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t getSize() const {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _rx_buf_size - _rx_buf_offset;
|
||||
}
|
||||
|
||||
size_t tell() const {
|
||||
return _rx_buf_offset;
|
||||
}
|
||||
|
||||
void seek(const size_t pos) {
|
||||
assert(isValidOffset(pos));
|
||||
_rx_buf_offset = pos;
|
||||
}
|
||||
|
||||
bool isValidOffset(const size_t pos) const {
|
||||
return (pos <= _rx_buf_size);
|
||||
}
|
||||
|
||||
netif* getInputNetif() const {
|
||||
return _currentAddr.input_netif;
|
||||
}
|
||||
|
||||
const IPAddress& getRemoteAddress() const {
|
||||
return _currentAddr.srcaddr;
|
||||
}
|
||||
|
||||
uint16_t getRemotePort() const {
|
||||
return _currentAddr.srcport;
|
||||
}
|
||||
|
||||
const IPAddress& getDestAddress() const {
|
||||
return _currentAddr.dstaddr;
|
||||
}
|
||||
|
||||
uint16_t getLocalPort() const {
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
return _pcb->local_port;
|
||||
}
|
||||
|
||||
bool next() {
|
||||
if (!_rx_buf) {
|
||||
return false;
|
||||
}
|
||||
if (!_first_buf_taken) {
|
||||
_first_buf_taken = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We have interleaved information on addresses within received pbuf chain:
|
||||
// (before ipv6 code we had: (data-pbuf) -> (data-pbuf) -> (data-pbuf) -> ... in the receiving order)
|
||||
// Now: (address-info-pbuf -> chained-data-pbuf [-> chained-data-pbuf...]) ->
|
||||
// (chained-address-info-pbuf -> chained-data-pbuf [-> chained...]) -> ...
|
||||
// _rx_buf is currently addressing a data pbuf,
|
||||
// in this function it is going to be discarded.
|
||||
|
||||
auto deleteme = _rx_buf;
|
||||
|
||||
// forward in the chain until next address-info pbuf or end of chain
|
||||
while (_rx_buf && _rx_buf->flags != PBUF_HELPER_FLAG) {
|
||||
_rx_buf = _rx_buf->next;
|
||||
}
|
||||
|
||||
if (_rx_buf) {
|
||||
assert(_rx_buf->flags == PBUF_HELPER_FLAG);
|
||||
|
||||
// copy address helper to "current address"
|
||||
auto helper = (AddrHelper*)PBUF_ALIGNER(_rx_buf->payload);
|
||||
_currentAddr = *helper;
|
||||
|
||||
// destroy the helper in the about-to-be-released pbuf
|
||||
helper->~AddrHelper();
|
||||
|
||||
// forward in rx_buf list, next one is effective data
|
||||
// current (not ref'ed) one will be pbuf_free'd
|
||||
// with the 'deleteme' pointer above
|
||||
_rx_buf = _rx_buf->next;
|
||||
|
||||
// this rx_buf is not nullptr by construction,
|
||||
assert(_rx_buf);
|
||||
// ref'ing it to prevent release from the below pbuf_free(deleteme)
|
||||
// (ref counter prevents release and will be decreased by pbuf_free)
|
||||
pbuf_ref(_rx_buf);
|
||||
}
|
||||
|
||||
// release in chain previous data, and if any:
|
||||
// current helper, but not start of current data
|
||||
pbuf_free(deleteme);
|
||||
|
||||
_rx_buf_offset = 0;
|
||||
_rx_buf_size = _processSize(_rx_buf);
|
||||
return _rx_buf != nullptr;
|
||||
}
|
||||
|
||||
int read() {
|
||||
if (!_rx_buf || _rx_buf_offset >= _rx_buf_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char c = pbuf_get_at(_rx_buf, _rx_buf_offset);
|
||||
_consume(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t read(char* dst, size_t size) {
|
||||
if (!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_size = _rx_buf_size - _rx_buf_offset;
|
||||
size = (size < max_size) ? size : max_size;
|
||||
DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf_size, _rx_buf_offset);
|
||||
|
||||
void* buf = pbuf_get_contiguous(_rx_buf, dst, size, size, _rx_buf_offset);
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf != dst) {
|
||||
memcpy(dst, buf, size);
|
||||
}
|
||||
|
||||
_consume(size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int peek() const {
|
||||
if (!_rx_buf || _rx_buf_offset == _rx_buf_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pbuf_get_at(_rx_buf, _rx_buf_offset);
|
||||
}
|
||||
|
||||
void flush() {
|
||||
//XXX this does not follow Arduino's flush definition
|
||||
if (!_rx_buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
_consume(_rx_buf_size - _rx_buf_offset);
|
||||
}
|
||||
|
||||
size_t append(const char* data, size_t size) {
|
||||
if (!_tx_buf_head || _tx_buf_head->tot_len < _tx_buf_offset + size) {
|
||||
_reserve(_tx_buf_offset + size);
|
||||
}
|
||||
if (!_tx_buf_head || _tx_buf_head->tot_len < _tx_buf_offset + size) {
|
||||
DEBUGV("failed _reserve");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t left_to_copy = size;
|
||||
while (left_to_copy) {
|
||||
// size already used in current pbuf
|
||||
size_t used_cur = _tx_buf_offset - (_tx_buf_head->tot_len - _tx_buf_cur->tot_len);
|
||||
size_t free_cur = _tx_buf_cur->len - used_cur;
|
||||
if (free_cur == 0) {
|
||||
_tx_buf_cur = _tx_buf_cur->next;
|
||||
continue;
|
||||
}
|
||||
size_t will_copy = (left_to_copy < free_cur) ? left_to_copy : free_cur;
|
||||
memcpy(reinterpret_cast<char*>(_tx_buf_cur->payload) + used_cur, data, will_copy);
|
||||
_tx_buf_offset += will_copy;
|
||||
left_to_copy -= will_copy;
|
||||
data += will_copy;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void cancelBuffer() {
|
||||
if (_tx_buf_head) {
|
||||
pbuf_free(_tx_buf_head);
|
||||
}
|
||||
_tx_buf_head = 0;
|
||||
_tx_buf_cur = 0;
|
||||
_tx_buf_offset = 0;
|
||||
}
|
||||
|
||||
bool send(const ip_addr_t* addr = 0, uint16_t port = 0) {
|
||||
return trySend(addr, port, /* don't keep buffer */false) == ERR_OK;
|
||||
}
|
||||
|
||||
bool sendTimeout(const ip_addr_t* addr, uint16_t port, uint32_t timeoutMs) {
|
||||
err_t err;
|
||||
uint32_t start = millis();
|
||||
while (((err = trySend(addr, port, /* keep buffer on error */true)) != ERR_OK) && (millis() - start < timeoutMs)) {
|
||||
delay(1);
|
||||
}
|
||||
if (err != ERR_OK) {
|
||||
cancelBuffer(); // get rid of buffer kept on error after timeout
|
||||
}
|
||||
return err == ERR_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
err_t trySend(const ip_addr_t* addr, uint16_t port, bool keepBufferOnError) {
|
||||
size_t data_size = _tx_buf_offset;
|
||||
pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM);
|
||||
if (tx_copy) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(tx_copy->payload);
|
||||
for (pbuf* p = _tx_buf_head; p; p = p->next) {
|
||||
size_t will_copy = (data_size < p->len) ? data_size : p->len;
|
||||
memcpy(dst, p->payload, will_copy);
|
||||
dst += will_copy;
|
||||
data_size -= will_copy;
|
||||
}
|
||||
}
|
||||
|
||||
if (!keepBufferOnError) {
|
||||
cancelBuffer();
|
||||
}
|
||||
|
||||
if (!tx_copy) {
|
||||
DEBUGV("failed pbuf_alloc");
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
if (!addr) {
|
||||
addr = &_pcb->remote_ip;
|
||||
port = _pcb->remote_port;
|
||||
}
|
||||
|
||||
err_t err = udp_sendto(_pcb, tx_copy, addr, port);
|
||||
if (err != ERR_OK) {
|
||||
DEBUGV(":ust rc=%d\r\n", (int) err);
|
||||
}
|
||||
|
||||
pbuf_free(tx_copy);
|
||||
|
||||
if (err == ERR_OK) {
|
||||
cancelBuffer(); // no error: get rid of buffer
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
size_t _processSize(const pbuf* pb) {
|
||||
size_t ret = 0;
|
||||
for (; pb && pb->flags != PBUF_HELPER_FLAG; pb = pb->next) {
|
||||
ret += pb->len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _reserve(size_t size) {
|
||||
const size_t pbuf_unit_size = 128;
|
||||
if (!_tx_buf_head) {
|
||||
_tx_buf_head = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM);
|
||||
if (!_tx_buf_head) {
|
||||
return;
|
||||
}
|
||||
_tx_buf_cur = _tx_buf_head;
|
||||
_tx_buf_offset = 0;
|
||||
}
|
||||
|
||||
size_t cur_size = _tx_buf_head->tot_len;
|
||||
if (size < cur_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t grow_size = size - cur_size;
|
||||
|
||||
while (grow_size) {
|
||||
pbuf* pb = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM);
|
||||
if (!pb) {
|
||||
return;
|
||||
}
|
||||
pbuf_cat(_tx_buf_head, pb);
|
||||
if (grow_size < pbuf_unit_size) {
|
||||
return;
|
||||
}
|
||||
grow_size -= pbuf_unit_size;
|
||||
}
|
||||
}
|
||||
|
||||
void _consume(size_t size) {
|
||||
_rx_buf_offset += size;
|
||||
if (_rx_buf_offset > _rx_buf_size) {
|
||||
_rx_buf_offset = _rx_buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
void _recv(udp_pcb *upcb, pbuf *pb,
|
||||
const ip_addr_t *srcaddr, u16_t srcport) {
|
||||
(void) upcb;
|
||||
// check receive pbuf chain depth
|
||||
// optimization path: cache the pbuf chain length
|
||||
{
|
||||
pbuf* p;
|
||||
int count = 0;
|
||||
for (p = _rx_buf; p && ++count < rxBufMaxDepth * 2; p = p->next);
|
||||
if (p) {
|
||||
// pbuf chain too deep, dropping
|
||||
pbuf_free(pb);
|
||||
DEBUGV(":udr\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// chain this helper pbuf first
|
||||
if (_rx_buf) {
|
||||
// there is some unread data
|
||||
// chain pbuf
|
||||
|
||||
// Addresses/ports are stored from this callback because lwIP's
|
||||
// macro are valid only now.
|
||||
//
|
||||
// When peeking data from before payload start (like it was done
|
||||
// before IPv6), there's no easy way to safely guess whether
|
||||
// packet is from v4 or v6.
|
||||
//
|
||||
// Now storing data in an intermediate chained pbuf containing
|
||||
// AddrHelper
|
||||
|
||||
// allocate new pbuf to store addresses/ports
|
||||
pbuf* pb_helper = pbuf_alloc(PBUF_RAW, sizeof(AddrHelper) + PBUF_ALIGNER_ADJUST, PBUF_RAM);
|
||||
if (!pb_helper) {
|
||||
// memory issue - discard received data
|
||||
pbuf_free(pb);
|
||||
return;
|
||||
}
|
||||
// construct in place
|
||||
new (PBUF_ALIGNER(pb_helper->payload)) AddrHelper(srcaddr, ip_current_dest_addr(), srcport, ip_current_input_netif());
|
||||
pb_helper->flags = PBUF_HELPER_FLAG; // mark helper pbuf
|
||||
// chain it
|
||||
pbuf_cat(_rx_buf, pb_helper);
|
||||
|
||||
// now chain the new data pbuf
|
||||
DEBUGV(":urch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
|
||||
pbuf_cat(_rx_buf, pb);
|
||||
} else {
|
||||
_currentAddr.srcaddr = srcaddr;
|
||||
_currentAddr.dstaddr = ip_current_dest_addr();
|
||||
_currentAddr.srcport = srcport;
|
||||
_currentAddr.input_netif = ip_current_input_netif();
|
||||
|
||||
DEBUGV(":urn %d\r\n", pb->tot_len);
|
||||
_first_buf_taken = false;
|
||||
_rx_buf = pb;
|
||||
_rx_buf_offset = 0;
|
||||
_rx_buf_size = pb->tot_len;
|
||||
}
|
||||
|
||||
if (_on_rx) {
|
||||
_on_rx();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void _s_recv(void *arg,
|
||||
udp_pcb *upcb, pbuf *p,
|
||||
const ip_addr_t *srcaddr, u16_t srcport) {
|
||||
reinterpret_cast<UdpContext*>(arg)->_recv(upcb, p, srcaddr, srcport);
|
||||
}
|
||||
|
||||
private:
|
||||
udp_pcb* _pcb;
|
||||
pbuf* _rx_buf;
|
||||
bool _first_buf_taken;
|
||||
size_t _rx_buf_offset;
|
||||
size_t _rx_buf_size;
|
||||
int _refcnt;
|
||||
pbuf* _tx_buf_head;
|
||||
pbuf* _tx_buf_cur;
|
||||
size_t _tx_buf_offset;
|
||||
rxhandler_t _on_rx;
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
uint16_t _mcast_ttl;
|
||||
#endif
|
||||
struct AddrHelper {
|
||||
IPAddress srcaddr, dstaddr;
|
||||
int16_t srcport;
|
||||
netif* input_netif;
|
||||
|
||||
AddrHelper() { }
|
||||
AddrHelper(const ip_addr_t* src, const ip_addr_t* dst, uint16_t srcport, netif* input_netif):
|
||||
srcaddr(src), dstaddr(dst), srcport(srcport), input_netif(input_netif) { }
|
||||
};
|
||||
AddrHelper _currentAddr;
|
||||
|
||||
// rx pbuf depth barrier (counter of buffered UDP received packets)
|
||||
// keep it small
|
||||
static constexpr int rxBufMaxDepth = 4;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif//UDPCONTEXT_H
|
||||
38
libraries/WiFi/src/include/slist.h
Normal file
38
libraries/WiFi/src/include/slist.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef SLIST_H
|
||||
#define SLIST_H
|
||||
|
||||
template<typename T>
|
||||
class SList {
|
||||
public:
|
||||
SList() : _next(0) { }
|
||||
|
||||
protected:
|
||||
|
||||
static void _add(T* self) {
|
||||
T* tmp = _s_first;
|
||||
_s_first = self;
|
||||
self->_next = tmp;
|
||||
}
|
||||
|
||||
static void _remove(T* self) {
|
||||
if (_s_first == self) {
|
||||
_s_first = self->_next;
|
||||
self->_next = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (T* prev = _s_first; prev->_next; prev = prev->_next) {
|
||||
if (prev->_next == self) {
|
||||
prev->_next = self->_next;
|
||||
self->_next = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static T* _s_first;
|
||||
T* _next;
|
||||
};
|
||||
|
||||
|
||||
#endif //SLIST_H
|
||||
83
libraries/WiFi/src/wl_definitions.h
Normal file
83
libraries/WiFi/src/wl_definitions.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
wl_definitions.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
wl_definitions.h
|
||||
|
||||
Created on: Mar 6, 2011
|
||||
Author: dlafauci
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// Maximum size of a SSID
|
||||
#define WL_SSID_MAX_LENGTH 32
|
||||
// Length of passphrase. Valid lengths are 8-63.
|
||||
#define WL_WPA_KEY_MAX_LENGTH 63
|
||||
// Length of key in bytes. Valid values are 5 and 13.
|
||||
#define WL_WEP_KEY_MAX_LENGTH 13
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_MAC_ADDR_LENGTH 6
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_IPV4_LENGTH 4
|
||||
// Maximum size of a SSID list
|
||||
#define WL_NETWORKS_LIST_MAXNUM 10
|
||||
// Maxmium number of socket
|
||||
#define WIFI_MAX_SOCK_NUM 10
|
||||
// Socket not available constant
|
||||
#define SOCK_NOT_AVAIL 255
|
||||
// Default state value for WiFi state field
|
||||
#define NA_STATE -1
|
||||
|
||||
typedef enum {
|
||||
WL_NO_SHIELD = 255,
|
||||
WL_NO_MODULE = WL_NO_SHIELD,
|
||||
WL_IDLE_STATUS = 0,
|
||||
WL_NO_SSID_AVAIL,
|
||||
WL_SCAN_COMPLETED,
|
||||
WL_CONNECTED,
|
||||
WL_CONNECT_FAILED,
|
||||
WL_CONNECTION_LOST,
|
||||
WL_DISCONNECTED,
|
||||
WL_AP_LISTENING,
|
||||
WL_AP_CONNECTED,
|
||||
WL_AP_FAILED,
|
||||
WL_CONNECTING
|
||||
} wl_status_t;
|
||||
|
||||
/* Encryption modes */
|
||||
enum wl_enc_type { /* Values map to 802.11 encryption suites... */
|
||||
ENC_TYPE_WEP = 5,
|
||||
ENC_TYPE_TKIP = 2,
|
||||
ENC_TYPE_CCMP = 4,
|
||||
/* ... except these two, 7 and 8 are reserved in 802.11-2007 */
|
||||
ENC_TYPE_NONE = 7,
|
||||
ENC_TYPE_AUTO = 8,
|
||||
|
||||
ENC_TYPE_UNKNOWN = 255
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
61
libraries/WiFi/src/wl_types.h
Normal file
61
libraries/WiFi/src/wl_types.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
wl_types.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2018 Arduino SA. All rights reserved.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
wl_types.h
|
||||
|
||||
Created on: Jul 30, 2010
|
||||
Author: dlafauci
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
WL_FAILURE = -1,
|
||||
WL_SUCCESS = 1,
|
||||
} wl_error_code_t;
|
||||
|
||||
/* Authentication modes */
|
||||
enum wl_auth_mode {
|
||||
AUTH_MODE_INVALID,
|
||||
AUTH_MODE_AUTO,
|
||||
AUTH_MODE_OPEN_SYSTEM,
|
||||
AUTH_MODE_SHARED_KEY,
|
||||
AUTH_MODE_WPA,
|
||||
AUTH_MODE_WPA2,
|
||||
AUTH_MODE_WPA_PSK,
|
||||
AUTH_MODE_WPA2_PSK
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
WL_PING_DEST_UNREACHABLE = -1,
|
||||
WL_PING_TIMEOUT = -2,
|
||||
WL_PING_UNKNOWN_HOST = -3,
|
||||
WL_PING_ERROR = -4
|
||||
} wl_ping_result_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
10
libraries/lwIP_CYW43/library.properties
Normal file
10
libraries/lwIP_CYW43/library.properties
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
name=lwIP_CYW43
|
||||
version=1
|
||||
author=Earle F. Philhower, III
|
||||
maintainer=Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
sentence=RP2040 Cyw43XX wifi driver
|
||||
paragraph=Driver for the raspberry Pi Pico W wireless chip, CYW43439, to integrate witrh arduino-pico
|
||||
category=Communication
|
||||
url=https://github.com/earlephilhower/arduino-pico
|
||||
architectures=rp2040
|
||||
dot_a_linkage=true
|
||||
6
libraries/lwIP_CYW43/src/lwIP_CYW43.h
Normal file
6
libraries/lwIP_CYW43/src/lwIP_CYW43.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <LwipIntfDev.h>
|
||||
#include <utility/CYW43shim.h>
|
||||
|
||||
using CYW43lwIP = LwipIntfDev<CYW43>;
|
||||
144
libraries/lwIP_CYW43/src/utility/CYW43shim.cpp
Normal file
144
libraries/lwIP_CYW43/src/utility/CYW43shim.cpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
WiFi <-> LWIP driver for the CYG43 chip on the Raspberry Pico W
|
||||
|
||||
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "CYW43shim.h"
|
||||
extern "C" {
|
||||
#include "cyw43.h"
|
||||
#include "cyw43_stats.h"
|
||||
}
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
netif *CYW43::_netif = nullptr;
|
||||
|
||||
CYW43::CYW43(int8_t cs, arduino::SPIClass& spi, int8_t intrpin) {
|
||||
(void) cs;
|
||||
(void) spi;
|
||||
(void) intrpin;
|
||||
_netif = nullptr;
|
||||
}
|
||||
|
||||
bool CYW43::begin(const uint8_t* address, netif* netif) {
|
||||
(void) address;
|
||||
_netif = netif;
|
||||
_self = &cyw43_state;
|
||||
|
||||
if (!_ap) {
|
||||
_itf = 0;
|
||||
cyw43_arch_enable_sta_mode();
|
||||
cyw43_wifi_get_mac(_self, _itf, netif->hwaddr);
|
||||
|
||||
auto authmode = CYW43_AUTH_WPA2_AES_PSK;
|
||||
if (_password == nullptr) {
|
||||
authmode = CYW43_AUTH_OPEN;
|
||||
}
|
||||
|
||||
if (cyw43_arch_wifi_connect_timeout_ms(_ssid, _password, authmode, _timeout)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
_itf = 1;
|
||||
cyw43_arch_enable_ap_mode(_ssid, _password, _password ? CYW43_AUTH_WPA2_AES_PSK : CYW43_AUTH_OPEN);
|
||||
cyw43_wifi_get_mac(_self, _itf, netif->hwaddr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CYW43::end() {
|
||||
_netif = nullptr;
|
||||
cyw43_deinit(&cyw43_state);
|
||||
}
|
||||
|
||||
|
||||
uint16_t CYW43::sendFrame(const uint8_t* data, uint16_t datalen) {
|
||||
if (0 == cyw43_send_ethernet(_self, _itf, datalen, data, false)) {
|
||||
return datalen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t CYW43::readFrame(uint8_t* buffer, uint16_t bufsize) {
|
||||
// This is the polling method, but we hand this thru the interrupts
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CB from the cyg32_driver
|
||||
extern "C" void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
|
||||
//cyw43_t *self = (cyw43_t *)cb_data
|
||||
(void) cb_data;
|
||||
(void) itf;
|
||||
struct netif *netif = CYW43::_netif; // &self->netif[itf];
|
||||
#if CYW43_NETUTILS
|
||||
if (self->trace_flags) {
|
||||
cyw43_ethernet_trace(self, netif, len, buf, NETUTILS_TRACE_NEWLINE);
|
||||
}
|
||||
#endif
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||||
struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
pbuf_take(p, buf, len);
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
CYW43_STAT_INC(PACKET_IN_COUNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
if (CYW43::_netif) {
|
||||
netif_set_link_up(CYW43::_netif);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
if (CYW43::_netif) {
|
||||
netif_set_link_down(CYW43::_netif);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int cyw43_tcpip_link_status(cyw43_t *self, int itf) {
|
||||
//if ((CYW43::_netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP))
|
||||
// Fake this since it's only used in the SDK
|
||||
if ((CYW43::_netif->flags & (NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_LINK_UP)) {
|
||||
return CYW43_LINK_UP;
|
||||
} else {
|
||||
return cyw43_wifi_link_status(self, itf);
|
||||
}
|
||||
}
|
||||
|
||||
// CBs from the SDK, not needed here as we do TCP later in the game
|
||||
extern "C" void cyw43_cb_tcpip_init(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
}
|
||||
extern "C" void cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) {
|
||||
(void) self;
|
||||
(void) itf;
|
||||
}
|
||||
|
||||
102
libraries/lwIP_CYW43/src/utility/CYW43shim.h
Normal file
102
libraries/lwIP_CYW43/src/utility/CYW43shim.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
WiFi <-> LWIP driver for the CYG43 chip on the Raspberry Pico W
|
||||
|
||||
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include "lwip/netif.h"
|
||||
extern "C" {
|
||||
#include "cyw43.h"
|
||||
#include "cyw43_stats.h"
|
||||
}
|
||||
class CYW43 {
|
||||
public:
|
||||
/**
|
||||
Constructor that uses the default hardware SPI pins
|
||||
@param cs the Arduino Chip Select / Slave Select pin (default 10)
|
||||
*/
|
||||
CYW43(int8_t cs, arduino::SPIClass& spi, int8_t intrpin);
|
||||
|
||||
/**
|
||||
Initialise the Ethernet controller
|
||||
Must be called before sending or receiving Ethernet frames
|
||||
|
||||
@param address the local MAC address for the Ethernet interface
|
||||
@return Returns true if setting up the Ethernet interface was successful
|
||||
*/
|
||||
bool begin(const uint8_t* address, netif *netif);
|
||||
|
||||
/**
|
||||
Shut down the Ethernet controlled
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
Send an Ethernet frame
|
||||
@param data a pointer to the data to send
|
||||
@param datalen the length of the data in the packet
|
||||
@return the number of bytes transmitted
|
||||
*/
|
||||
uint16_t sendFrame(const uint8_t* data, uint16_t datalen);
|
||||
|
||||
/**
|
||||
Read an Ethernet frame
|
||||
@param buffer a pointer to a buffer to write the packet to
|
||||
@param bufsize the available space in the buffer
|
||||
@return the length of the received packet
|
||||
or 0 if no packet was received
|
||||
*/
|
||||
uint16_t readFrame(uint8_t* buffer, uint16_t bufsize);
|
||||
|
||||
bool interruptIsPossible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void setSSID(const char *p) {
|
||||
_ssid = p;
|
||||
}
|
||||
void setPassword(const char *p) {
|
||||
_password = p;
|
||||
}
|
||||
|
||||
void setSTA() {
|
||||
_ap = false;
|
||||
}
|
||||
|
||||
void setAP() {
|
||||
_ap = true;
|
||||
}
|
||||
|
||||
void setTimeout(int timeout) {
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
// LWIP netif for the IRQ packet processing
|
||||
static netif *_netif;
|
||||
protected:
|
||||
int _timeout = 10000;
|
||||
bool _ap = false;
|
||||
// The WiFi driver object
|
||||
cyw43_t *_self;
|
||||
int _itf;
|
||||
const char *_ssid = nullptr;
|
||||
const char *_password = nullptr;
|
||||
};
|
||||
10
libraries/lwIP_Ethernet/library.properties
Normal file
10
libraries/lwIP_Ethernet/library.properties
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
name=lwIP-Ethernet
|
||||
version=1
|
||||
author=esp8266/Arduino
|
||||
maintainer=esp8266/Arduino
|
||||
sentence=Helper for ethernet drivers
|
||||
paragraph=Example repository for Ethernet drivers
|
||||
category=Communication
|
||||
url=https://github.com/esp8266/Arduino
|
||||
architectures=esp8266,rp2040
|
||||
dot_a_linkage=true
|
||||
256
libraries/lwIP_Ethernet/src/AddrList.h
Normal file
256
libraries/lwIP_Ethernet/src/AddrList.h
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
AddrList.h - cycle through lwIP netif's ip addresses like a c++ list
|
||||
Copyright (c) 2018 david gauchard. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
This class allows to explore all configured IP addresses
|
||||
in lwIP netifs, with that kind of c++ loop:
|
||||
|
||||
for (auto a: addrList)
|
||||
out.printf("IF='%s' index=%d legacy=%d IPv4=%d local=%d hostname='%s' addr= %s\n",
|
||||
a.iface().c_str(),
|
||||
a.ifnumber(),
|
||||
a.addr().isLegacy(),
|
||||
a.addr().isV4(),
|
||||
a.addr().isLocal(),
|
||||
a.hostname().c_str(),
|
||||
a.addr().toString().c_str());
|
||||
|
||||
This loop:
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED()) {
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
|
||||
can be replaced by:
|
||||
|
||||
for (bool configured = false; !configured; ) {
|
||||
for (auto iface: addrList)
|
||||
if ((configured = !iface.addr().isLocal())
|
||||
break;
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
|
||||
waiting for an IPv6 global address:
|
||||
|
||||
for (bool configured = false; !configured; ) {
|
||||
for (auto iface: addrList)
|
||||
if ((configured = ( !iface.addr().isV4()
|
||||
&& !iface.addr().isLocal())))
|
||||
break;
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
|
||||
waiting for an IPv6 global address, on a specific interface:
|
||||
|
||||
for (bool configured = false; !configured; ) {
|
||||
for (auto iface: addrList)
|
||||
if ((configured = ( !iface.addr().isV4()
|
||||
&& !iface.addr().isLocal()
|
||||
&& iface.ifnumber() == STATION_IF)))
|
||||
break;
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
*/
|
||||
|
||||
#ifndef __ADDRLIST_H
|
||||
#define __ADDRLIST_H
|
||||
|
||||
#include <IPAddress.h>
|
||||
#include <lwip/netif.h>
|
||||
|
||||
#if LWIP_IPV6
|
||||
#define IF_NUM_ADDRESSES (1 + LWIP_IPV6_NUM_ADDRESSES)
|
||||
#else
|
||||
#define IF_NUM_ADDRESSES (1)
|
||||
#endif
|
||||
|
||||
|
||||
namespace esp8266 {
|
||||
|
||||
namespace AddressListImplementation {
|
||||
|
||||
|
||||
struct netifWrapper {
|
||||
netifWrapper(netif* netif) : _netif(netif), _num(-1) {}
|
||||
netifWrapper(const netifWrapper& o) : _netif(o._netif), _num(o._num) {}
|
||||
|
||||
netifWrapper& operator= (const netifWrapper& o) {
|
||||
_netif = o._netif;
|
||||
_num = o._num;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool equal(const netifWrapper& o) {
|
||||
return _netif == o._netif && (!_netif || _num == o._num);
|
||||
}
|
||||
|
||||
// address properties
|
||||
IPAddress addr() const {
|
||||
return ipFromNetifNum();
|
||||
}
|
||||
bool isLegacy() const {
|
||||
return _num == 0;
|
||||
}
|
||||
bool isLocal() const {
|
||||
return addr().isLocal();
|
||||
}
|
||||
bool isV4() const {
|
||||
return addr().isV4();
|
||||
}
|
||||
bool isV6() const {
|
||||
return !addr().isV4();
|
||||
}
|
||||
String toString() const {
|
||||
return addr().toString();
|
||||
}
|
||||
|
||||
// related to legacy address (_num=0, ipv4)
|
||||
IPAddress ipv4() const {
|
||||
return _netif->ip_addr;
|
||||
}
|
||||
IPAddress netmask() const {
|
||||
return _netif->netmask;
|
||||
}
|
||||
IPAddress gw() const {
|
||||
return _netif->gw;
|
||||
}
|
||||
|
||||
// common to all addresses of this interface
|
||||
String ifname() const {
|
||||
return String(_netif->name[0]) + _netif->name[1];
|
||||
}
|
||||
const char* ifhostname() const {
|
||||
return _netif->hostname ? : "";
|
||||
}
|
||||
const char* ifmac() const {
|
||||
return (const char*)_netif->hwaddr;
|
||||
}
|
||||
int ifnumber() const {
|
||||
return _netif->num;
|
||||
}
|
||||
bool ifUp() const {
|
||||
return !!(_netif->flags & NETIF_FLAG_UP);
|
||||
}
|
||||
const netif* interface() const {
|
||||
return _netif;
|
||||
}
|
||||
|
||||
const ip_addr_t* ipFromNetifNum() const {
|
||||
#if LWIP_IPV6
|
||||
return _num ? &_netif->ip6_addr[_num - 1] : &_netif->ip_addr;
|
||||
#else
|
||||
return &_netif->ip_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// lwIP interface
|
||||
netif* _netif;
|
||||
|
||||
// address index within interface
|
||||
// 0: legacy address (IPv4)
|
||||
// n>0: (_num-1) is IPv6 index for netif->ip6_addr[]
|
||||
int _num;
|
||||
};
|
||||
|
||||
|
||||
class AddressListIterator {
|
||||
public:
|
||||
AddressListIterator(const netifWrapper& o) : netIf(o) {}
|
||||
AddressListIterator(netif* netif) : netIf(netif) {
|
||||
// This constructor is called with lwIP's global netif_list, or
|
||||
// nullptr. operator++() is designed to loop through _configured_
|
||||
// addresses. That's why netIf's _num is initialized to -1 to allow
|
||||
// returning the first usable address to AddressList::begin().
|
||||
(void)operator++();
|
||||
}
|
||||
|
||||
const netifWrapper& operator* () const {
|
||||
return netIf;
|
||||
}
|
||||
const netifWrapper* operator-> () const {
|
||||
return &netIf;
|
||||
}
|
||||
|
||||
bool operator== (AddressListIterator& o) {
|
||||
return netIf.equal(*o);
|
||||
}
|
||||
bool operator!= (AddressListIterator& o) {
|
||||
return !netIf.equal(*o);
|
||||
}
|
||||
|
||||
AddressListIterator operator++ (int) {
|
||||
AddressListIterator ret = *this;
|
||||
(void)operator++();
|
||||
return ret;
|
||||
}
|
||||
|
||||
AddressListIterator& operator++ () {
|
||||
while (netIf._netif) {
|
||||
if (++netIf._num == IF_NUM_ADDRESSES) {
|
||||
// all addresses from current interface were iterated,
|
||||
// switching to next interface
|
||||
netIf = netifWrapper(netIf._netif->next);
|
||||
continue;
|
||||
}
|
||||
if (!ip_addr_isany(netIf.ipFromNetifNum()))
|
||||
// found an initialized address
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
netifWrapper netIf;
|
||||
};
|
||||
|
||||
|
||||
class AddressList {
|
||||
public:
|
||||
using const_iterator = const AddressListIterator;
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(netif_list);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator(nullptr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline AddressList::const_iterator begin(const AddressList& a) {
|
||||
return a.begin();
|
||||
}
|
||||
inline AddressList::const_iterator end(const AddressList& a) {
|
||||
return a.end();
|
||||
}
|
||||
|
||||
|
||||
} // AddressListImplementation
|
||||
|
||||
} // esp8266
|
||||
|
||||
extern esp8266::AddressListImplementation::AddressList addrList;
|
||||
|
||||
|
||||
#endif
|
||||
14
libraries/lwIP_Ethernet/src/LwipEthernet.cpp
Normal file
14
libraries/lwIP_Ethernet/src/LwipEthernet.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
#include <LwipEthernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
//#ifndef ETHERNET_SPI_CLOCK_DIV
|
||||
//#define ETHERNET_SPI_CLOCK_DIV SPI_CLOCK_DIV4 // 4MHz (SPI.h)
|
||||
//#endif
|
||||
|
||||
void SPI4EthInit() {
|
||||
SPI.begin();
|
||||
// SPI.setClockDivider(ETHERNET_SPI_CLOCK_DIV);
|
||||
// SPI.setBitOrder(MSBFIRST);
|
||||
// SPI.setDataMode(SPI_MODE0);
|
||||
}
|
||||
50
libraries/lwIP_Ethernet/src/LwipEthernet.h
Normal file
50
libraries/lwIP_Ethernet/src/LwipEthernet.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
//#include <ESP8266WiFi.h> // tcp API
|
||||
//#include <debug.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <lwIP_CYW43.h>
|
||||
//#include <W5100lwIP.h>
|
||||
//#include <W5500lwIP.h>
|
||||
//#include <ENC28J60lwIP.h>
|
||||
|
||||
// One of them is to be declared in the main sketch
|
||||
// and passed to ethInitDHCP() or ethInitStatic():
|
||||
// Wiznet5500lwIP eth(CSPIN);
|
||||
// Wiznet5100lwIP eth(CSPIN);
|
||||
// ENC28J60lwIP eth(CSPIN);
|
||||
|
||||
void SPI4EthInit();
|
||||
|
||||
template<class EthImpl>
|
||||
bool ethInitDHCP(EthImpl& eth) {
|
||||
SPI4EthInit();
|
||||
|
||||
if (!eth.begin()) {
|
||||
// hardware not responding
|
||||
// DEBUGV("ethInitDHCP: hardware not responding\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class EthImpl>
|
||||
bool ethInitStatic(EthImpl& eth, IPAddress IP, IPAddress gateway, IPAddress netmask, IPAddress dns1,
|
||||
IPAddress dns2 = IPADDR_NONE) {
|
||||
SPI4EthInit();
|
||||
|
||||
if (!eth.config(IP, gateway, netmask, dns1, dns2)) {
|
||||
// invalid arguments
|
||||
// DEBUGV("ethInitStatic: invalid arguments\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eth.begin()) {
|
||||
// hardware not responding
|
||||
// DEBUGV("ethInitStatic: hardware not responding\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
185
libraries/lwIP_Ethernet/src/LwipIntf.cpp
Normal file
185
libraries/lwIP_Ethernet/src/LwipIntf.cpp
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
LwipIntf.cpp
|
||||
|
||||
Arduino interface for lwIP generic callbacks and functions
|
||||
|
||||
Original Copyright (c) 2020 esp8266 Arduino All rights reserved.
|
||||
This file is part of the esp8266 Arduino core environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#if LWIP_IPV6
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "LwipIntf.h"
|
||||
using arduino::IPAddress;
|
||||
using arduino::String;
|
||||
|
||||
|
||||
|
||||
// wifi_station_hostname is SDK's station(=global) hostname location
|
||||
// - It is never nullptr but wifi_station_get_hostname()
|
||||
// can return nullptr when STA is down
|
||||
// - Because WiFi is started in off mode at boot time,
|
||||
// wifi_station_set/get_hostname() is now no more used
|
||||
// because setting hostname first does not work anymore
|
||||
// - wifi_station_hostname is overwritten by SDK when wifi is
|
||||
// woken up in WiFi::mode()
|
||||
//
|
||||
char wifi_station_hostname[64] = "PicoW";
|
||||
|
||||
// args | esp order arduino order
|
||||
// ---- + --------- -------------
|
||||
// local_ip | local_ip local_ip
|
||||
// arg1 | gateway dns1
|
||||
// arg2 | netmask gateway
|
||||
// arg3 | dns1 netmask
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
|
||||
bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1,
|
||||
const IPAddress& arg2, const IPAddress& arg3, IPAddress& gateway,
|
||||
IPAddress& netmask, IPAddress& dns1) {
|
||||
// To allow compatibility, check first octet of 3rd arg. If 255, interpret as ESP order,
|
||||
// otherwise Arduino order.
|
||||
gateway = arg1;
|
||||
netmask = arg2;
|
||||
dns1 = arg3;
|
||||
|
||||
if (netmask[0] != 255) {
|
||||
// octet is not 255 => interpret as Arduino order
|
||||
gateway = arg2;
|
||||
netmask = arg3[0] == 0 ? IPAddress(255, 255, 255, 0)
|
||||
: arg3; // arg order is arduino and 4th arg not given => assign it
|
||||
// arduino default
|
||||
dns1 = arg1;
|
||||
}
|
||||
|
||||
// check whether all is IPv4 (or gateway not set)
|
||||
if (!(local_ip.isV4() && netmask.isV4() && (!gateway.isSet() || gateway.isV4()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ip and gateway must be in the same netmask
|
||||
if (gateway.isSet() && (local_ip.v4() & netmask.v4()) != (gateway.v4() & netmask.v4())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Get ESP8266 station DHCP hostname
|
||||
@return hostname
|
||||
*/
|
||||
String LwipIntf::hostname(void) {
|
||||
return wifi_station_hostname;
|
||||
}
|
||||
|
||||
/**
|
||||
Get ESP8266 station DHCP hostname
|
||||
@return hostname
|
||||
*/
|
||||
const char* LwipIntf::getHostname(void) {
|
||||
return wifi_station_hostname;
|
||||
}
|
||||
|
||||
/**
|
||||
Set ESP8266 station DHCP hostname
|
||||
@param aHostname max length:24
|
||||
@return ok
|
||||
*/
|
||||
bool LwipIntf::hostname(const char* aHostname) {
|
||||
/*
|
||||
vvvv RFC952 vvvv
|
||||
ASSUMPTIONS
|
||||
1. A "name" (Net, Host, Gateway, or Domain name) is a text string up
|
||||
to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus
|
||||
sign (-), and period (.). Note that periods are only allowed when
|
||||
they serve to delimit components of "domain style names". (See
|
||||
RFC-921, "Domain Name System Implementation Schedule", for
|
||||
background). No blank or space characters are permitted as part of a
|
||||
name. No distinction is made between upper and lower case. The first
|
||||
character must be an alpha character. The last character must not be
|
||||
a minus sign or period. A host which serves as a GATEWAY should have
|
||||
"-GATEWAY" or "-GW" as part of its name. Hosts which do not serve as
|
||||
Internet gateways should not use "-GATEWAY" and "-GW" as part of
|
||||
their names. A host which is a TAC should have "-TAC" as the last
|
||||
part of its host name, if it is a DoD host. Single character names
|
||||
or nicknames are not allowed.
|
||||
^^^^ RFC952 ^^^^
|
||||
|
||||
- 24 chars max
|
||||
- only a..z A..Z 0..9 '-'
|
||||
- no '-' as last char
|
||||
*/
|
||||
|
||||
size_t len = strlen(aHostname);
|
||||
|
||||
if (len == 0 || len > 32) {
|
||||
// nonos-sdk limit is 32
|
||||
// (dhcp hostname option minimum size is ~60)
|
||||
// DEBUGV("WiFi.(set)hostname(): empty or large(>32) name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check RFC compliance
|
||||
bool compliant = (len <= 24);
|
||||
for (size_t i = 0; compliant && i < len; i++)
|
||||
if (!isalnum(aHostname[i]) && aHostname[i] != '-') {
|
||||
compliant = false;
|
||||
}
|
||||
if (aHostname[len - 1] == '-') {
|
||||
compliant = false;
|
||||
}
|
||||
|
||||
if (!compliant) {
|
||||
// DEBUGV("hostname '%s' is not compliant with RFC952\n", aHostname);
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
|
||||
strcpy(wifi_station_hostname, aHostname);
|
||||
|
||||
// now we should inform dhcp server for this change, using lwip_renew()
|
||||
// looping through all existing interface
|
||||
// harmless for AP, also compatible with ethernet adapters (to come)
|
||||
for (netif* intf = netif_list; intf; intf = intf->next) {
|
||||
// unconditionally update all known interfaces
|
||||
intf->hostname = wifi_station_hostname;
|
||||
|
||||
if (netif_dhcp_data(intf) != nullptr) {
|
||||
// renew already started DHCP leases
|
||||
err_t lwipret = dhcp_renew(intf);
|
||||
if (lwipret != ERR_OK) {
|
||||
// DEBUGV("WiFi.hostname(%s): lwIP error %d on interface %c%c (index %d)\n",
|
||||
// intf->hostname, (int)lwipret, intf->name[0], intf->name[1], intf->num);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret && compliant;
|
||||
}
|
||||
68
libraries/lwIP_Ethernet/src/LwipIntf.h
Normal file
68
libraries/lwIP_Ethernet/src/LwipIntf.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
LwipIntf.h
|
||||
|
||||
Arduino interface for lwIP generic callbacks and functions
|
||||
|
||||
Original Copyright (c) 2020 esp8266 Arduino All rights reserved.
|
||||
This file is part of the esp8266 Arduino core environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <lwip/netif.h>
|
||||
#include <IPAddress.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
class LwipIntf {
|
||||
public:
|
||||
using CBType = std::function<void(netif*)>;
|
||||
|
||||
static bool stateUpCB(LwipIntf::CBType&& cb);
|
||||
|
||||
// reorder WiFi.config() parameters for a esp8266/official Arduino dual-compatibility API
|
||||
// args | esp order arduino order
|
||||
// ---- + --------- -------------
|
||||
// local_ip | local_ip local_ip
|
||||
// arg1 | gateway dns1
|
||||
// arg2 | netmask [Agateway
|
||||
// arg3 | dns1 netmask
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
static bool ipAddressReorder(const arduino::IPAddress& local_ip, const arduino::IPAddress& arg1,
|
||||
const arduino::IPAddress& arg2, const arduino::IPAddress& arg3, arduino::IPAddress& gateway,
|
||||
arduino::IPAddress& netmask, arduino::IPAddress& dns1);
|
||||
|
||||
arduino::String hostname();
|
||||
|
||||
bool hostname(const arduino::String& aHostname) {
|
||||
return hostname(aHostname.c_str());
|
||||
}
|
||||
|
||||
bool hostname(const char* aHostname);
|
||||
|
||||
// ESP32 API compatibility
|
||||
bool setHostname(const char* aHostName) {
|
||||
return hostname(aHostName);
|
||||
}
|
||||
|
||||
// ESP32 API compatibility
|
||||
const char* getHostname();
|
||||
|
||||
protected:
|
||||
static bool stateChangeSysCB(LwipIntf::CBType&& cb);
|
||||
};
|
||||
66
libraries/lwIP_Ethernet/src/LwipIntfCB.cpp
Normal file
66
libraries/lwIP_Ethernet/src/LwipIntfCB.cpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
LwipIntfCB.cpp
|
||||
|
||||
network generic callback implementation
|
||||
|
||||
Original Copyright (c) 2020 esp8266 Arduino All rights reserved.
|
||||
This file is part of the esp8266 Arduino core environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <LwipIntf.h>
|
||||
//#include <Schedule.h>
|
||||
//#include <debug.h>
|
||||
|
||||
#define NETIF_STATUS_CB_SIZE 3
|
||||
|
||||
static int netifStatusChangeListLength = 0;
|
||||
LwipIntf::CBType netifStatusChangeList[NETIF_STATUS_CB_SIZE];
|
||||
|
||||
extern "C" void netif_status_changed(struct netif* netif) {
|
||||
// override the default empty weak function
|
||||
for (int i = 0; i < netifStatusChangeListLength; i++) {
|
||||
netifStatusChangeList[i](netif);
|
||||
}
|
||||
}
|
||||
|
||||
bool LwipIntf::stateChangeSysCB(LwipIntf::CBType&& cb) {
|
||||
if (netifStatusChangeListLength >= NETIF_STATUS_CB_SIZE) {
|
||||
#if defined(DEBUG_ESP_CORE)
|
||||
DEBUGV("NETIF_STATUS_CB_SIZE is too low\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
netifStatusChangeList[netifStatusChangeListLength++] = cb;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LwipIntf::stateUpCB(LwipIntf::CBType&& cb) {
|
||||
(void) cb;
|
||||
return false;
|
||||
//TODO - this is not used now, but was used in LeaMDNS
|
||||
// return stateChangeSysCB(
|
||||
// [cb](netif* nif)
|
||||
// {
|
||||
// if (netif_is_up(nif))
|
||||
// schedule_function(
|
||||
// [cb, nif]()
|
||||
// {
|
||||
// cb(nif);
|
||||
// });
|
||||
// });
|
||||
}
|
||||
545
libraries/lwIP_Ethernet/src/LwipIntfDev.h
Normal file
545
libraries/lwIP_Ethernet/src/LwipIntfDev.h
Normal file
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
LwipIntfDev.h
|
||||
|
||||
Arduino network template class for generic device
|
||||
|
||||
Original Copyright (c) 2020 esp8266 Arduino All rights reserved.
|
||||
This file is part of the esp8266 Arduino core environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// TODO:
|
||||
// unchain pbufs
|
||||
|
||||
#include <LWIPMutex.h>
|
||||
|
||||
#include <netif/ethernet.h>
|
||||
#include <lwip/init.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/etharp.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/raw.h>
|
||||
#include <lwip/icmp.h>
|
||||
#include <lwip/timeouts.h>
|
||||
#include <lwip/inet_chksum.h>
|
||||
#include <lwip/apps/sntp.h>
|
||||
|
||||
//#include <user_interface.h> // wifi_get_macaddr()
|
||||
|
||||
#include "SPI.h"
|
||||
//#include "Schedule.h"
|
||||
#include "LwipIntf.h"
|
||||
#include "wl_definitions.h"
|
||||
|
||||
#ifndef DEFAULT_MTU
|
||||
#define DEFAULT_MTU 1500
|
||||
#endif
|
||||
|
||||
extern "C" void cyw43_hal_generate_laa_mac(__unused int idx, uint8_t buf[6]);
|
||||
|
||||
template<class RawDev>
|
||||
class LwipIntfDev: public LwipIntf, public RawDev {
|
||||
public:
|
||||
LwipIntfDev(int8_t cs = SS, SPIClass& spi = SPI, int8_t intr = -1) :
|
||||
RawDev(cs, spi, intr), _mtu(DEFAULT_MTU), _intrPin(intr), _started(false), _default(false) {
|
||||
memset(&_netif, 0, sizeof(_netif));
|
||||
}
|
||||
|
||||
bool config(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2,
|
||||
const IPAddress& arg3 = IPADDR_NONE, const IPAddress& dns2 = IPADDR_NONE);
|
||||
|
||||
// default mac-address is inferred from esp8266's STA interface
|
||||
bool begin(const uint8_t* macAddress = nullptr, const uint16_t mtu = DEFAULT_MTU);
|
||||
|
||||
void end();
|
||||
|
||||
netif* getNetIf() {
|
||||
return &_netif;
|
||||
}
|
||||
|
||||
IPAddress localIP() const {
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)));
|
||||
}
|
||||
IPAddress subnetMask() const {
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.netmask)));
|
||||
}
|
||||
IPAddress gatewayIP() const {
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.gw)));
|
||||
}
|
||||
|
||||
// 1. Currently when no default is set, esp8266-Arduino uses the first
|
||||
// DHCP client interface receiving a valid address and gateway to
|
||||
// become the new lwIP default interface.
|
||||
// 2. Otherwise - when using static addresses - lwIP for every packets by
|
||||
// defaults selects automatically the best suited output interface
|
||||
// matching the destination address. If several interfaces match,
|
||||
// the first one is picked. On esp8266/Arduno: WiFi interfaces are
|
||||
// checked first.
|
||||
// 3. Or, use `::setDefault(true)` to force using this interface's gateway
|
||||
// as default router.
|
||||
void setDefault(bool deflt = true);
|
||||
|
||||
// true if interface has a valid IPv4 address
|
||||
bool connected() {
|
||||
return !!ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr));
|
||||
}
|
||||
|
||||
bool routable() {
|
||||
return !ip_addr_isany(&_netif.gw);
|
||||
}
|
||||
|
||||
// ICMP echo, returns TTL
|
||||
int ping(IPAddress host, uint8_t ttl, uint32_t timeout = 5000);
|
||||
|
||||
int hostByName(const char* aHostname, IPAddress& aResult, int timeout);
|
||||
|
||||
// ESP8266WiFi API compatibility
|
||||
|
||||
wl_status_t status();
|
||||
|
||||
protected:
|
||||
err_t netif_init();
|
||||
void check_route();
|
||||
void netif_status_callback();
|
||||
|
||||
static err_t netif_init_s(netif* netif);
|
||||
static err_t linkoutput_s(netif* netif, struct pbuf* p);
|
||||
static void netif_status_callback_s(netif* netif);
|
||||
|
||||
// called on a regular basis or on interrupt
|
||||
err_t handlePackets();
|
||||
|
||||
// members
|
||||
|
||||
netif _netif;
|
||||
|
||||
uint16_t _mtu;
|
||||
int8_t _intrPin;
|
||||
uint8_t _macAddress[6];
|
||||
bool _started;
|
||||
bool _default;
|
||||
|
||||
// ICMP Ping
|
||||
int _ping_seq_num = 1;
|
||||
const int _ping_id = 0xfade;
|
||||
volatile int _ping_ttl;
|
||||
static u8_t _pingCB(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr);
|
||||
|
||||
// DNS lookup callback
|
||||
bool _dns_lookup_pending = false;
|
||||
typedef struct {
|
||||
IPAddress *ip;
|
||||
LwipIntfDev<RawDev> *wifi;
|
||||
} _dns_cb_t;
|
||||
static void _dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg);
|
||||
};
|
||||
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) {
|
||||
(void) name;
|
||||
_dns_cb_t *cb = (_dns_cb_t *)callback_arg;
|
||||
if (!cb->wifi->_dns_lookup_pending) {
|
||||
return;
|
||||
}
|
||||
if (ipaddr) {
|
||||
*(cb->ip) = IPAddress(ipaddr);
|
||||
}
|
||||
cb->wifi->_dns_lookup_pending = false; // resume hostByName
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
int LwipIntfDev<RawDev>::hostByName(const char* aHostname, IPAddress& aResult, int timeout_ms) {
|
||||
ip_addr_t addr;
|
||||
aResult = static_cast<uint32_t>(0xffffffff);
|
||||
|
||||
if (aResult.fromString(aHostname)) {
|
||||
// Host name is a IP address use it!
|
||||
return 1;
|
||||
}
|
||||
|
||||
LWIPMutex m;
|
||||
_dns_cb_t cb = { &aResult, this };
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &_dns_found_callback, &cb, LWIP_DNS_ADDRTYPE_DEFAULT);
|
||||
#else
|
||||
err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &cb);
|
||||
#endif
|
||||
if (err == ERR_OK) {
|
||||
aResult = IPAddress(&addr);
|
||||
} else if (err == ERR_INPROGRESS) {
|
||||
_dns_lookup_pending = true;
|
||||
uint32_t now = millis();
|
||||
while ((millis() - now < (uint32_t)timeout_ms) && _dns_lookup_pending) {
|
||||
sys_check_timeouts();
|
||||
delay(10);
|
||||
}
|
||||
_dns_lookup_pending = false;
|
||||
if (aResult.isSet()) {
|
||||
err = ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ERR_OK) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
u8_t LwipIntfDev<RawDev>::_pingCB(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) {
|
||||
(void) addr;
|
||||
LwipIntfDev<RawDev> *w = (LwipIntfDev<RawDev> *)arg;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
if (pbuf_header(p, -20) == 0) {
|
||||
iecho = (struct icmp_echo_hdr *)p->payload;
|
||||
if ((iecho->id == w->_ping_id) && (iecho->seqno == htons(w->_ping_seq_num))) {
|
||||
w->_ping_ttl = pcb->ttl;
|
||||
pbuf_free(p);
|
||||
return 1; // We've processed it
|
||||
}
|
||||
}
|
||||
return 0; // Wasn't ours
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
int LwipIntfDev<RawDev>::ping(IPAddress host, uint8_t ttl, uint32_t _timeout) {
|
||||
const int PING_DATA_SIZE = 32;
|
||||
struct pbuf *p;
|
||||
int ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
|
||||
|
||||
auto ping_pcb = raw_new(IP_PROTO_ICMP);
|
||||
ping_pcb->ttl = ttl;
|
||||
|
||||
LWIPMutex m;
|
||||
|
||||
raw_recv(ping_pcb, _pingCB, this);
|
||||
raw_bind(ping_pcb, IP_ADDR_ANY);
|
||||
|
||||
p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
|
||||
if (!p) {
|
||||
return 0;
|
||||
}
|
||||
if ((p->len == p->tot_len) && (p->next == nullptr)) {
|
||||
struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)p->payload;
|
||||
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
|
||||
ICMPH_CODE_SET(iecho, 0);
|
||||
iecho->chksum = 0;
|
||||
iecho->id = _ping_id;
|
||||
iecho->seqno = htons(++_ping_seq_num);
|
||||
/* fill the additional data buffer with some data */
|
||||
for (size_t i = 0; i < PING_DATA_SIZE; i++) {
|
||||
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)(i + 'A');
|
||||
}
|
||||
iecho->chksum = inet_chksum(iecho, ping_size);
|
||||
_ping_ttl = -1;
|
||||
raw_sendto(ping_pcb, p, host);
|
||||
uint32_t now = millis();
|
||||
while ((millis() - now < _timeout) && (_ping_ttl < 0)) {
|
||||
sys_check_timeouts();
|
||||
delay(10);
|
||||
}
|
||||
pbuf_free(p);
|
||||
raw_remove(ping_pcb);
|
||||
return _ping_ttl;
|
||||
} else {
|
||||
pbuf_free(p);
|
||||
raw_remove(ping_pcb);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
bool LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& gateway,
|
||||
const IPAddress& netmask, const IPAddress& dns1,
|
||||
const IPAddress& dns2) {
|
||||
if (_started) {
|
||||
DEBUGV("LwipIntfDev: use config() then begin()\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
IPAddress realGateway, realNetmask, realDns1;
|
||||
if (!ipAddressReorder(localIP, gateway, netmask, dns1, realGateway, realNetmask, realDns1)) {
|
||||
return false;
|
||||
}
|
||||
ip4_addr_set_u32(ip_2_ip4(&_netif.ip_addr), localIP.v4());
|
||||
ip4_addr_set_u32(ip_2_ip4(&_netif.gw), realGateway.v4());
|
||||
ip4_addr_set_u32(ip_2_ip4(&_netif.netmask), realNetmask.v4());
|
||||
|
||||
if (realDns1.isSet()) {
|
||||
// Set DNS1-Server
|
||||
dns_setserver(0, realDns1);
|
||||
}
|
||||
|
||||
if (dns2.isSet()) {
|
||||
// Set DNS2-Server
|
||||
dns_setserver(1, dns2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
extern char wifi_station_hostname[];
|
||||
template<class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu) {
|
||||
if (mtu) {
|
||||
_mtu = mtu;
|
||||
}
|
||||
|
||||
if (macAddress) {
|
||||
memcpy(_macAddress, macAddress, 6);
|
||||
} else {
|
||||
_netif.num = 2;
|
||||
for (auto n = netif_list; n; n = n->next)
|
||||
if (n->num >= _netif.num) {
|
||||
_netif.num = n->num + 1;
|
||||
}
|
||||
|
||||
#if 1
|
||||
// forge a new mac-address from the esp's wifi sta one
|
||||
// I understand this is cheating with an official mac-address
|
||||
cyw43_hal_generate_laa_mac(0, _macAddress);
|
||||
#else
|
||||
// https://serverfault.com/questions/40712/what-range-of-mac-addresses-can-i-safely-use-for-my-virtual-machines
|
||||
memset(_macAddress, 0, 6);
|
||||
_macAddress[0] = 0xEE;
|
||||
#endif
|
||||
_macAddress[3] += _netif.num; // alter base mac address
|
||||
_macAddress[0] &= 0xfe; // set as locally administered, unicast, per
|
||||
_macAddress[0] |= 0x02; // https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
|
||||
}
|
||||
|
||||
// setup lwIP netif
|
||||
|
||||
_netif.hwaddr_len = sizeof _macAddress;
|
||||
memcpy(_netif.hwaddr, _macAddress, sizeof _macAddress);
|
||||
|
||||
// due to netif_add() api: ...
|
||||
ip_addr_t ip_addr, netmask, gw;
|
||||
ip_addr_copy(ip_addr, _netif.ip_addr);
|
||||
ip_addr_copy(netmask, _netif.netmask);
|
||||
ip_addr_copy(gw, _netif.gw);
|
||||
|
||||
_netif.hostname = wifi_station_hostname;
|
||||
|
||||
if (!netif_add(&_netif, ip_2_ip4(&ip_addr), ip_2_ip4(&netmask), ip_2_ip4(&gw), this,
|
||||
netif_init_s, ethernet_input)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RawDev::begin(_macAddress, &_netif)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (localIP().v4() == 0) {
|
||||
// IP not set, starting DHCP
|
||||
_netif.flags |= NETIF_FLAG_UP;
|
||||
switch (dhcp_start(&_netif)) {
|
||||
case ERR_OK:
|
||||
break;
|
||||
|
||||
case ERR_IF:
|
||||
return false;
|
||||
|
||||
default:
|
||||
netif_remove(&_netif);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// IP is set, static config
|
||||
netif_set_link_up(&_netif);
|
||||
netif_set_up(&_netif);
|
||||
}
|
||||
|
||||
_started = true;
|
||||
|
||||
if (_intrPin >= 0) {
|
||||
if (RawDev::interruptIsPossible()) {
|
||||
// attachInterrupt(_intrPin, [&]() { this->handlePackets(); }, FALLING);
|
||||
} else {
|
||||
::printf((PGM_P)F(
|
||||
"lwIP_Intf: Interrupt not implemented yet, enabling transparent polling\r\n"));
|
||||
_intrPin = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (_intrPin < 0
|
||||
&& !schedule_recurrent_function_us(
|
||||
[&]() {
|
||||
this->handlePackets();
|
||||
return true;
|
||||
},
|
||||
100)) {
|
||||
netif_remove(&_netif);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::end() {
|
||||
RawDev::end();
|
||||
netif_remove(&_netif);
|
||||
memset(&_netif, 0, sizeof(_netif));
|
||||
}
|
||||
|
||||
|
||||
template<class RawDev>
|
||||
wl_status_t LwipIntfDev<RawDev>::status() {
|
||||
return _started ? (connected() ? WL_CONNECTED : WL_DISCONNECTED) : WL_NO_SHIELD;
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::linkoutput_s(netif* netif, struct pbuf* pbuf) {
|
||||
LwipIntfDev* lid = (LwipIntfDev*)netif->state;
|
||||
|
||||
if (pbuf->len != pbuf->tot_len || pbuf->next) {
|
||||
Serial.println("ERRTOT\r\n");
|
||||
}
|
||||
|
||||
uint16_t len = lid->sendFrame((const uint8_t*)pbuf->payload, pbuf->len);
|
||||
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture) {
|
||||
phy_capture(lid->_netif.num, (const char*)pbuf->payload, pbuf->len, /*out*/ 1,
|
||||
/*success*/ len == pbuf->len);
|
||||
}
|
||||
#endif
|
||||
|
||||
return len == pbuf->len ? ERR_OK : ERR_MEM;
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init_s(struct netif* netif) {
|
||||
return ((LwipIntfDev*)netif->state)->netif_init();
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback_s(struct netif* netif) {
|
||||
((LwipIntfDev*)netif->state)->netif_status_callback();
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init() {
|
||||
_netif.name[0] = 'e';
|
||||
_netif.name[1] = '0' + _netif.num;
|
||||
_netif.mtu = _mtu;
|
||||
_netif.chksum_flags = NETIF_CHECKSUM_ENABLE_ALL;
|
||||
_netif.flags = NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP;
|
||||
|
||||
// lwIP's doc: This function typically first resolves the hardware
|
||||
// address, then sends the packet. For ethernet physical layer, this is
|
||||
// usually lwIP's etharp_output()
|
||||
_netif.output = etharp_output;
|
||||
|
||||
// lwIP's doc: This function outputs the pbuf as-is on the link medium
|
||||
// (this must points to the raw ethernet driver, meaning: us)
|
||||
_netif.linkoutput = linkoutput_s;
|
||||
|
||||
_netif.status_callback = netif_status_callback_s;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback() {
|
||||
check_route();
|
||||
if (connected()) {
|
||||
sntp_stop();
|
||||
sntp_init();
|
||||
}
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::check_route() {
|
||||
if (connected()) {
|
||||
if (_default || (netif_default == nullptr && routable())) {
|
||||
// on user request,
|
||||
// or if there is no current default interface, but our gateway is valid
|
||||
netif_set_default(&_netif);
|
||||
}
|
||||
} else if (netif_default == &_netif) {
|
||||
netif_set_default(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::handlePackets() {
|
||||
int pkt = 0;
|
||||
while (1) {
|
||||
if (++pkt == 10)
|
||||
// prevent starvation
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
uint16_t tot_len = RawDev::readFrameSize();
|
||||
if (!tot_len) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
// from doc: use PBUF_RAM for TX, PBUF_POOL from RX
|
||||
// however:
|
||||
// PBUF_POOL can return chained pbuf (not in one piece)
|
||||
// and WiznetDriver does not have the proper API to deal with that
|
||||
// so in the meantime, we use PBUF_RAM instead which is currently
|
||||
// guarantying to deliver a continuous chunk of memory.
|
||||
// TODO: tweak the wiznet driver to allow copying partial chunk
|
||||
// of received data and use PBUF_POOL.
|
||||
pbuf* pbuf = pbuf_alloc(PBUF_RAW, tot_len, PBUF_RAM);
|
||||
if (!pbuf || pbuf->len < tot_len) {
|
||||
if (pbuf) {
|
||||
pbuf_free(pbuf);
|
||||
}
|
||||
RawDev::discardFrame(tot_len);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
uint16_t len = RawDev::readFrameData((uint8_t*)pbuf->payload, tot_len);
|
||||
if (len != tot_len) {
|
||||
// tot_len is given by readFrameSize()
|
||||
// and is supposed to be honoured by readFrameData()
|
||||
// todo: ensure this test is unneeded, remove the print
|
||||
pbuf_free(pbuf);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
err_t err = _netif.input(pbuf, &_netif);
|
||||
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture) {
|
||||
phy_capture(_netif.num, (const char*)pbuf->payload, tot_len, /*out*/ 0,
|
||||
/*success*/ err == ERR_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(pbuf);
|
||||
return err;
|
||||
}
|
||||
// (else) allocated pbuf is now lwIP's responsibility
|
||||
}
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::setDefault(bool deflt) {
|
||||
_default = deflt;
|
||||
check_route();
|
||||
}
|
||||
|
|
@ -20,6 +20,9 @@
|
|||
{
|
||||
"name": "Raspberry Pi Pico"
|
||||
},
|
||||
{
|
||||
"name": "Raspberry Pi Pico W"
|
||||
},
|
||||
{
|
||||
"name": "Adafruit Feather RP2040"
|
||||
},
|
||||
|
|
|
|||
2
pico-sdk
2
pico-sdk
|
|
@ -1 +1 @@
|
|||
Subproject commit e7267f99febc70486923e17a8210088af058c915
|
||||
Subproject commit 2e6142b15b8a75c1227dd3edbe839193b2bf9041
|
||||
|
|
@ -41,8 +41,9 @@ compiler.warning_flags.default=-Werror=return-type
|
|||
compiler.warning_flags.more=-Wall -Werror=return-type -Wno-ignored-qualifiers
|
||||
compiler.warning_flags.all=-Wall -Wextra -Werror=return-type -Wno-ignored-qualifiers
|
||||
|
||||
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.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/platform_inc.txt"
|
||||
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.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}/tools/libpico"
|
||||
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.libpico="{runtime.platform.path}/lib/libpico.a"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S \
|
||||
./libraries/LittleFS/src ./libraries/LittleFS/examples \
|
||||
./libraries/rp2040 ./libraries/SD ./libraries/ESP8266SdFat \
|
||||
./libraries/Servo ./libraries/SPI ./libraries/Wire; do
|
||||
./libraries/Servo ./libraries/SPI ./libraries/Wire \
|
||||
./libraries/WiFi ./libraries/lwIP_Ethernet ./libraries/lwIP_CYW43; do
|
||||
find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \;
|
||||
find $dir -type f -name "*.ino" -exec astyle --suffix=none --options=./tests/astyle_examples.conf \{\} \;
|
||||
done
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ set(CMAKE_C_STANDARD 11)
|
|||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
|
||||
# Enable PicoW driver support. Compatible with standard Pico
|
||||
set(PICO_BOARD pico_w)
|
||||
|
||||
# Initialize the SDK
|
||||
pico_sdk_init()
|
||||
|
||||
|
|
@ -17,6 +20,12 @@ target_compile_definitions(pico PUBLIC
|
|||
PICO_PRINTF_ALWAYS_INCLUDED=1
|
||||
PICO_FLASH_SIZE_BYTES=16777216
|
||||
PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64
|
||||
LWIP_IPV4=1
|
||||
LWIP_IPV6=1
|
||||
LWIP_UDP=1
|
||||
LWIP_IGMP=1
|
||||
LWIP_CHECKSUM_CTRL_PER_NETIF=1
|
||||
CYW43_WARN=//
|
||||
)
|
||||
|
||||
target_compile_options(pico PUBLIC
|
||||
|
|
@ -29,6 +38,7 @@ include_directories(BEFORE ${PICO_SDK_PATH}/../tools/libpico)
|
|||
|
||||
target_link_libraries(pico
|
||||
boot_stage2
|
||||
cyw43_driver
|
||||
hardware_adc
|
||||
hardware_base
|
||||
hardware_claim
|
||||
|
|
@ -58,11 +68,15 @@ target_link_libraries(pico
|
|||
pico_bootrom
|
||||
pico_bootsel_via_double_reset
|
||||
pico_cxx_options
|
||||
pico_cyw43_arch_none
|
||||
pico_divider
|
||||
pico_double
|
||||
pico_fix
|
||||
pico_float
|
||||
pico_int64_ops
|
||||
pico_lwip
|
||||
pico_lwip_nosys
|
||||
pico_lwip_sntp
|
||||
pico_malloc
|
||||
pico_mem_ops
|
||||
pico_multicore
|
||||
|
|
@ -74,10 +88,9 @@ target_link_libraries(pico
|
|||
pico_util
|
||||
tinyusb
|
||||
tinyusb_device_unmarked
|
||||
pico_audio
|
||||
pico_audio_i2s
|
||||
)
|
||||
|
||||
add_custom_command(TARGET pico POST_BUILD
|
||||
COMMAND ar d libpico.a stdio.c.obj stdio_usb.c.obj stdio_usb_descriptors.c.obj
|
||||
COMMAND ar d libpico.a stdio.c.obj stdio_usb.c.obj stdio_usb_descriptors.c.obj cyw43_arch_threadsafe_background.c.obj
|
||||
COMMAND ar q libpico.a pico-sdk/src/rp2_common/cyw43_driver/cyw43_resource.o
|
||||
)
|
||||
|
|
|
|||
99
tools/libpico/lwipopts.h
Normal file
99
tools/libpico/lwipopts.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H
|
||||
#define _LWIPOPTS_EXAMPLE_COMMONH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
// Critical section protection
|
||||
extern void noInterrupts();
|
||||
extern void interrupts();
|
||||
//static int lwipNoInterrupts() { noInterrupts(); return 0; }
|
||||
//static void lwipInterrupts(int ign) { interrupts(); }
|
||||
#define SYS_ARCH_DECL_PROTECT int
|
||||
#define SYS_ARCH_PROTECT(lev) noInterrupts
|
||||
#define SYS_ARCH_UNPROTECT(lev) interrupts
|
||||
|
||||
// Common settings used in most of the pico_w examples
|
||||
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
|
||||
|
||||
#define NO_SYS 1
|
||||
#define LWIP_SOCKET 0
|
||||
#define MEM_LIBC_MALLOC 0
|
||||
|
||||
|
||||
#define MEM_ALIGNMENT 4
|
||||
#define MEM_SIZE 4000
|
||||
#define MEMP_NUM_TCP_SEG 32
|
||||
#define MEMP_NUM_ARP_QUEUE 10
|
||||
#define PBUF_POOL_SIZE 24
|
||||
#define LWIP_ARP 1
|
||||
#define LWIP_ETHERNET 1
|
||||
#define LWIP_ICMP 1
|
||||
#define LWIP_RAW 1
|
||||
#define TCP_WND (8 * TCP_MSS)
|
||||
#define TCP_MSS 1460
|
||||
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
|
||||
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||
#define LWIP_NETIF_HOSTNAME 1
|
||||
#define LWIP_NETCONN 0
|
||||
#define MEM_STATS 0
|
||||
#define SYS_STATS 0
|
||||
#define MEMP_STATS 0
|
||||
#define LINK_STATS 0
|
||||
// #define ETH_PAD_SIZE 2
|
||||
#define LWIP_CHKSUM_ALGORITHM 3
|
||||
#define LWIP_DHCP 1
|
||||
#define LWIP_IPV4 1
|
||||
#define LWIP_TCP 1
|
||||
#define LWIP_UDP 1
|
||||
#define LWIP_DNS 1
|
||||
#define LWIP_TCP_KEEPALIVE 1
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||
#define DHCP_DOES_ARP_CHECK 0
|
||||
#define LWIP_DHCP_DOES_ACD_CHECK 0
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define LWIP_DEBUG 1
|
||||
#define LWIP_STATS 1
|
||||
#define LWIP_STATS_DISPLAY 1
|
||||
#endif
|
||||
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
#define NETIF_DEBUG LWIP_DBG_OFF
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
#define API_MSG_DEBUG LWIP_DBG_OFF
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
#define INET_DEBUG LWIP_DBG_OFF
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
#define IP_REASS_DEBUG LWIP_DBG_OFF
|
||||
#define RAW_DEBUG LWIP_DBG_OFF
|
||||
#define MEM_DEBUG LWIP_DBG_OFF
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
#define SYS_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RTO_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_CWND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_WND_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_FR_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
|
||||
#define TCP_RST_DEBUG LWIP_DBG_OFF
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
#define PPP_DEBUG LWIP_DBG_OFF
|
||||
#define SLIP_DEBUG LWIP_DBG_OFF
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
#endif /* __LWIPOPTS_H__ */
|
||||
|
|
@ -75,7 +75,7 @@ def BuildBoot(name):
|
|||
|
||||
def BuildUSBStack(name):
|
||||
print("%s.menu.usbstack.picosdk=Pico SDK" % (name))
|
||||
print('%s.menu.usbstack.picosdk.build.usbstack_flags="-I{runtime.platform.path}/tools/libpico"' % (name))
|
||||
print('%s.menu.usbstack.picosdk.build.usbstack_flags=' % (name))
|
||||
print("%s.menu.usbstack.tinyusb=Adafruit TinyUSB" % (name))
|
||||
print('%s.menu.usbstack.tinyusb.build.usbstack_flags=-DUSE_TINYUSB "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"' % (name))
|
||||
|
||||
|
|
@ -248,6 +248,7 @@ BuildGlobalMenuList()
|
|||
|
||||
# Raspberry Pi
|
||||
MakeBoard("rpipico", "Raspberry Pi", "Pico", "0x2e8a", "0x000a", 250, "RASPBERRY_PI_PICO", 2, "boot2_w25q080_2_padded_checksum")
|
||||
MakeBoard("rpipicow", "Raspberry Pi", "Pico W", "0x2e8a", "0xf00a", 250, "RASPBERRY_PI_PICO_W", 2, "boot2_w25q080_2_padded_checksum")
|
||||
|
||||
# Adafruit
|
||||
MakeBoard("adafruit_feather", "Adafruit", "Feather RP2040", "0x239a", "0x80f1", 250, "ADAFRUIT_FEATHER_RP2040", 8, "boot2_w25x10cl_4_padded_checksum")
|
||||
|
|
|
|||
|
|
@ -106,6 +106,13 @@ env.Append(
|
|||
"ARDUINO_ARCH_RP2040",
|
||||
("F_CPU", "$BOARD_F_CPU"),
|
||||
("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=[
|
||||
|
|
@ -164,7 +171,6 @@ def configure_usb_flags(cpp_defines):
|
|||
platform.config.set(env_section, "lib_archive", False)
|
||||
elif "PIO_FRAMEWORK_ARDUINO_NO_USB" in cpp_defines:
|
||||
env.Append(
|
||||
CPPPATH=[os.path.join(FRAMEWORK_DIR, "tools", "libpico")],
|
||||
CPPDEFINES=[
|
||||
"NO_USB",
|
||||
"DISABLE_USB_SERIAL"
|
||||
|
|
@ -173,8 +179,8 @@ def configure_usb_flags(cpp_defines):
|
|||
# do not further add more USB flags or update sizes. no USB used.
|
||||
return
|
||||
else:
|
||||
# standard Pico SDK USB stack used.
|
||||
env.Append(CPPPATH=[os.path.join(FRAMEWORK_DIR, "tools", "libpico")])
|
||||
# standard Pico SDK USB stack used, will get include path later on
|
||||
pass
|
||||
# in any case, add standard flags
|
||||
# preferably use USB information from arduino.earlephilhower section,
|
||||
# but fallback to sensible values derived from other parts otherwise.
|
||||
|
|
@ -240,6 +246,9 @@ if not "USE_TINYUSB" in cpp_defines:
|
|||
# configure USB stuff
|
||||
configure_usb_flags(cpp_defines)
|
||||
|
||||
# ensure LWIP headers are in path after any TINYUSB distributed versions, also PicoSDK USB path headers
|
||||
env.Append(CPPPATH=[os.path.join(FRAMEWORK_DIR, "tools", "libpico")])
|
||||
|
||||
# info about the filesystem is already parsed by the platform's main.py
|
||||
# script. We can just use the info here
|
||||
|
||||
|
|
|
|||
49
variants/rpipicow/picow_digital.cpp
Normal file
49
variants/rpipicow/picow_digital.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
pinMode and digitalRead/Write for the Raspberry Pi Pico W RP2040
|
||||
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <pico/cyw43_arch.h>
|
||||
|
||||
extern "C" void __pinMode(pin_size_t pin, PinMode mode);
|
||||
extern "C" void __digitalWrite(pin_size_t pin, PinStatus val);
|
||||
extern "C" PinStatus __digitalRead(pin_size_t pin);
|
||||
|
||||
extern "C" void pinMode(pin_size_t pin, PinMode mode) {
|
||||
if (pin < 32) {
|
||||
__pinMode(pin, mode);
|
||||
} else {
|
||||
// TBD - There is no GPIO direction control in the driver
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void digitalWrite(pin_size_t pin, PinStatus val) {
|
||||
if (pin < 32) {
|
||||
__digitalWrite(pin, val);
|
||||
} else {
|
||||
cyw43_arch_gpio_put(pin - 32, val == HIGH ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" PinStatus digitalRead(pin_size_t pin) {
|
||||
if (pin < 32) {
|
||||
return __digitalRead(pin);
|
||||
} else {
|
||||
return cyw43_arch_gpio_get(pin - 32) ? HIGH : LOW;
|
||||
}
|
||||
}
|
||||
25
variants/rpipicow/picow_init.cpp
Normal file
25
variants/rpipicow/picow_init.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Initialize the Pico W WiFi driver
|
||||
|
||||
Copyright (c) 2022 Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <pico/cyw43_arch.h>
|
||||
|
||||
extern "C" void initVariant() {
|
||||
cyw43_arch_init();
|
||||
}
|
||||
39
variants/rpipicow/pins_arduino.h
Normal file
39
variants/rpipicow/pins_arduino.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
// Pin definitions taken from:
|
||||
// https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf
|
||||
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED (32u)
|
||||
|
||||
// Serial
|
||||
#define PIN_SERIAL1_TX (0u)
|
||||
#define PIN_SERIAL1_RX (1u)
|
||||
|
||||
#define PIN_SERIAL2_TX (8u)
|
||||
#define PIN_SERIAL2_RX (9u)
|
||||
|
||||
// SPI
|
||||
#define PIN_SPI0_MISO (16u)
|
||||
#define PIN_SPI0_MOSI (19u)
|
||||
#define PIN_SPI0_SCK (18u)
|
||||
#define PIN_SPI0_SS (17u)
|
||||
|
||||
#define PIN_SPI1_MISO (12u)
|
||||
#define PIN_SPI1_MOSI (15u)
|
||||
#define PIN_SPI1_SCK (14u)
|
||||
#define PIN_SPI1_SS (13u)
|
||||
|
||||
// Wire
|
||||
#define PIN_WIRE0_SDA (4u)
|
||||
#define PIN_WIRE0_SCL (5u)
|
||||
|
||||
#define PIN_WIRE1_SDA (26u)
|
||||
#define PIN_WIRE1_SCL (27u)
|
||||
|
||||
#define SERIAL_HOWMANY (3u)
|
||||
#define SPI_HOWMANY (2u)
|
||||
#define WIRE_HOWMANY (2u)
|
||||
|
||||
#include "../generic/common.h"
|
||||
Loading…
Reference in a new issue