Compare commits
@@ -9,21 +9,21 @@ jobs:
|
||||
name: Update master JSON file
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
# - name: Cache PlatformIO
|
||||
# uses: actions/cache@v3
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: ~/.platformio
|
||||
# key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
|
||||
@@ -15,11 +15,11 @@ jobs:
|
||||
name: Package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Build package JSON
|
||||
|
||||
@@ -202,11 +202,14 @@ Under Windows a local admin user should be able to access the Picoprobe port aut
|
||||
|
||||
To set up user-level access to Picoprobes on Ubuntu (and other OSes which use `udev`):
|
||||
````
|
||||
echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", GROUP="users", MODE="0666"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="0666"' | sudo tee -a /etc/udev/rules.d/98-PicoProbe.rules
|
||||
sudo udevadm control --reload
|
||||
sudo udevadm trigger -w -s usb
|
||||
````
|
||||
|
||||
The first line creates a file with the USB vendor and ID of the Picoprobe and tells UDEV to give users full access to it. The second causes `udev` to load this new rule. Note that you will need to unplug and re-plug in your device the first time you create this file, to allow udev to make the device node properly.
|
||||
The first line creates a device file in `/dev` matching the USB vendor and product ID of the Picoprobe, and it enables global read+write permissions. The second line causes `udev` to load this new rule. The third line requests the kernel generate "device change" events that will cause our new `udev` rule to run.
|
||||
|
||||
If for some reason the device file does not appear, manually unplug and re-plug the USB connection and check again. The output from `dmesg` can reveal useful diagnostics if the device file remains absent.
|
||||
|
||||
Once Picoprobe permissions are set up properly, then select the board "Raspberry Pi Pico (Picoprobe)" in the Tools menu and upload as normal.
|
||||
|
||||
@@ -215,13 +218,16 @@ Once Picoprobe permissions are set up properly, then select the board "Raspberry
|
||||
|
||||
Under Windows and macOS, any user should be able to access pico-debug automatically, but under Linux `udev` must be told about the device and to allow normal users access.
|
||||
|
||||
To set up user-level access to all CMSIS-DAP adapters on Ubuntu (and other OSes which use `udev`):
|
||||
To set up group-level access to all CMSIS-DAP adapters on Ubuntu (and other OSes which use `udev`):
|
||||
````
|
||||
echo 'ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev"' | sudo tee -a /etc/udev/rules.d/98-CMSIS-DAP.rules
|
||||
sudo udevadm control --reload
|
||||
sudo udevadm trigger -w -s usb
|
||||
````
|
||||
|
||||
The first line creates a file that recognizes all CMSIS-DAP adapters and tells UDEV to give users full access to it. The second causes `udev` to load this new rule. Note that you will need to unplug and re-plug in your device the first time you create this file, to allow udev to make the device node properly.
|
||||
The first line creates a device file in `/dev` that matches all CMSIS-DAP adapters, and it enables read+write permissions for members of the `plugdev` group. The second line causes `udev` to load this new rule. The third line requests the kernel generate "device change" events that will cause our new `udev` rule to run.
|
||||
|
||||
If for some reason the device file does not appear, manually unplug and re-plug the USB connection and check again. The output from `dmesg` can reveal useful diagnostics if the device file remains absent.
|
||||
|
||||
Once CMSIS-DAP permissions are set up properly, then select the board "Raspberry Pi Pico (pico-debug)" in the Tools menu.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define ARDUINO_PICO_MAJOR 3
|
||||
#define ARDUINO_PICO_MINOR 7
|
||||
#define ARDUINO_PICO_REVISION 0
|
||||
#define ARDUINO_PICO_VERSION_STR "3.7.0"
|
||||
#define ARDUINO_PICO_REVISION 2
|
||||
#define ARDUINO_PICO_VERSION_STR "3.7.2"
|
||||
|
||||
@@ -33,12 +33,17 @@
|
||||
|
||||
extern void ethernet_arch_lwip_begin() __attribute__((weak));
|
||||
extern void ethernet_arch_lwip_end() __attribute__((weak));
|
||||
extern void ethernet_arch_lwip_gpio_mask() __attribute__((weak));
|
||||
extern void ethernet_arch_lwip_gpio_unmask() __attribute__((weak));
|
||||
|
||||
auto_init_recursive_mutex(__lwipMutex); // Only for case with no Ethernet or PicoW, but still doing LWIP (PPP?)
|
||||
|
||||
class LWIPMutex {
|
||||
public:
|
||||
LWIPMutex() {
|
||||
if (ethernet_arch_lwip_gpio_mask) {
|
||||
ethernet_arch_lwip_gpio_mask();
|
||||
}
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
if (rp2040.isPicoW()) {
|
||||
cyw43_arch_lwip_begin();
|
||||
@@ -56,13 +61,18 @@ public:
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
if (rp2040.isPicoW()) {
|
||||
cyw43_arch_lwip_end();
|
||||
return;
|
||||
} else {
|
||||
#endif
|
||||
if (ethernet_arch_lwip_end) {
|
||||
ethernet_arch_lwip_end();
|
||||
} else {
|
||||
recursive_mutex_exit(&__lwipMutex);
|
||||
}
|
||||
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
|
||||
}
|
||||
#endif
|
||||
if (ethernet_arch_lwip_end) {
|
||||
ethernet_arch_lwip_end();
|
||||
} else {
|
||||
recursive_mutex_exit(&__lwipMutex);
|
||||
if (ethernet_arch_lwip_gpio_unmask) {
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -79,7 +89,7 @@ extern "C" {
|
||||
extern void __real_lwip_init();
|
||||
void __wrap_lwip_init() {
|
||||
if (!_lwip_rng) {
|
||||
_lwip_rng = new XoshiroCpp::Xoshiro256PlusPlus(get_rand_64());
|
||||
_lwip_rng = new XoshiroCpp::Xoshiro256PlusPlus(micros() * rp2040.getCycleCount());
|
||||
__real_lwip_init();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -54,9 +54,9 @@ author = u'Earle F. Philhower, III'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'3.7.0'
|
||||
version = u'3.7.2'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'3.7.0'
|
||||
release = u'3.7.2'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
+15
-2
@@ -86,6 +86,19 @@ Pico may not have enough time to service the Ethernet port before the timer fire
|
||||
leading to a lock up and hang.
|
||||
|
||||
|
||||
Using Interrupt-Driven Handling
|
||||
-------------------------------
|
||||
|
||||
The WizNet and ENC28J60 devices support generating an interrupt when a packet is received,
|
||||
removing the need for polling and decreasing latency. Simply specify the SPI object to use and the
|
||||
interrupt pin when instantiating the Ethernet object:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include <W5100lwIP.h>
|
||||
Wiznet5100lwIP eth(SS /* Chip Select*/, SPI /* SPI interface */, 17 /* Interrupt GPIO */ );
|
||||
|
||||
|
||||
Adjusting SPI Speed
|
||||
-------------------
|
||||
|
||||
@@ -114,12 +127,12 @@ For example, to set the W5500 to use a 30MHZ clock:
|
||||
Using the WIZnet W5100S-EVB-Pico
|
||||
--------------------------------
|
||||
|
||||
You can use the onboard Ethernet chip with these drivers by utilizing the following options:
|
||||
You can use the onboard Ethernet chip with these drivers, in interrupt mode, by utilizing the following options:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
#include <W5100lwIP.h>
|
||||
Wiznet5100lwIP eth(17); // Note chip select is **17**
|
||||
Wiznet5100lwIP eth(17, SPI, 21); // Note chip select is **17**
|
||||
|
||||
void setup() {
|
||||
// Set SPI to the onboard Wiznet chip
|
||||
|
||||
+3
-7
@@ -1,15 +1,11 @@
|
||||
IDE Menus
|
||||
=========
|
||||
|
||||
Model
|
||||
Board
|
||||
-----
|
||||
Use the boards menu to select your model of RP2040 board. There will be two
|
||||
options: `Boardname` and `Boardname (Picoprobe)`. If you want to use a
|
||||
Picoprobe to upload your sketches and not the default automatic UF2 upload,
|
||||
use the `(Picoprobe)` option, otherwise use the normal name. No functional
|
||||
or code changes are done because of this.
|
||||
Use the boards menu to select your model of RP2040 board.
|
||||
|
||||
There is also a `Generic` board which allows you to individually select
|
||||
There is also a `Generic RP2040` board which allows you to individually select
|
||||
things such as flash size or boot2 flash type. Use this if your board isn't
|
||||
yet fully supported and isn't working with the normal `Raspberry Pi Pico`
|
||||
option.
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ diagram for your board, or it won't work.
|
||||
Other than that, the API is compatible with the Arduino standard.
|
||||
Both master and slave operation are supported.
|
||||
|
||||
Master transmissions are buffered (up to 128 bytes) and only performed
|
||||
Master transmissions are buffered (up to 256 bytes) and only performed
|
||||
on ``endTransmission``, as is standard with modern Arduino Wire implementations.
|
||||
|
||||
For more detailed information, check the `Arduino Wire documentation <https://www.arduino.cc/en/reference/wire>`_ .
|
||||
|
||||
@@ -165,14 +165,14 @@ static void __no_inline_not_in_flash_func(IdleThisCore)(void *param) {
|
||||
(void) param;
|
||||
while (true) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
portDISABLE_INTERRUPTS();
|
||||
vTaskPreemptionDisable(nullptr);
|
||||
portDISABLE_INTERRUPTS();
|
||||
__otherCoreIdled = true;
|
||||
while (__otherCoreIdled) {
|
||||
/* noop */
|
||||
}
|
||||
vTaskPreemptionEnable(nullptr);
|
||||
portENABLE_INTERRUPTS();
|
||||
vTaskPreemptionEnable(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +188,9 @@ extern "C" void __no_inline_not_in_flash_func(__freertos_idle_other_core)() {
|
||||
|
||||
extern "C" void __no_inline_not_in_flash_func(__freertos_resume_other_core)() {
|
||||
__otherCoreIdled = false;
|
||||
portENABLE_INTERRUPTS();
|
||||
xTaskResumeAll();
|
||||
vTaskPreemptionEnable(nullptr);
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ PWMAudio::PWMAudio(pin_size_t pin, bool stereo) {
|
||||
_buffers = 8;
|
||||
_bufferWords = 0;
|
||||
_stereo = stereo;
|
||||
_sampleRate = 48000;
|
||||
_pacer = -1;
|
||||
}
|
||||
|
||||
PWMAudio::~PWMAudio() {
|
||||
@@ -63,7 +65,7 @@ bool PWMAudio::setStereo(bool stereo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PWMAudio::setFrequency(int newFreq) {
|
||||
bool PWMAudio::setPWMFrequency(int newFreq) {
|
||||
_freq = newFreq;
|
||||
|
||||
// Figure out the scale factor for PWM values
|
||||
@@ -92,6 +94,17 @@ bool PWMAudio::setFrequency(int newFreq) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PWMAudio::setFrequency(int frequency) {
|
||||
if (_pacer < 0) {
|
||||
return false;
|
||||
}
|
||||
uint16_t _pacer_D, _pacer_N;
|
||||
/*Flip fraction(N for D, D for N) because we are using it as sys_clk * fraction(mechanic of dma_timer_set_fraction) for smaller than sys_clk values*/
|
||||
find_pacer_fraction(frequency, &_pacer_D, &_pacer_N);
|
||||
dma_timer_set_fraction(_pacer, _pacer_N, _pacer_D);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PWMAudio::onTransmit(void(*fn)(void)) {
|
||||
_cb = fn;
|
||||
if (_running) {
|
||||
@@ -117,12 +130,25 @@ bool PWMAudio::begin() {
|
||||
_bufferWords = 16;
|
||||
}
|
||||
|
||||
setFrequency(_freq);
|
||||
setPWMFrequency(_freq);
|
||||
|
||||
/*Calculate and set the DMA pacer timer. This timer will pull data on a fixed sample rate. So the actual PWM frequency can be higher or lower.*/
|
||||
_pacer = dma_claim_unused_timer(false);
|
||||
/*When no unused timer is found, return*/
|
||||
if (_pacer < 0) {
|
||||
return false;
|
||||
}
|
||||
uint16_t _pacer_D = 0;
|
||||
uint16_t _pacer_N = 0;
|
||||
/*Flip fraction(N for D, D for N) because we are using it as sys_clk * fraction(mechanic of dma_timer_set_fraction) for smaller than sys_clk values*/
|
||||
find_pacer_fraction(_sampleRate, &_pacer_D, &_pacer_N);
|
||||
dma_timer_set_fraction(_pacer, _pacer_N, _pacer_D);
|
||||
int _pacer_dreq = dma_get_timer_dreq(_pacer);
|
||||
|
||||
uint32_t ccAddr = PWM_BASE + PWM_CH0_CC_OFFSET + pwm_gpio_to_slice_num(_pin) * 20;
|
||||
|
||||
_arb = new AudioBufferManager(_buffers, _bufferWords, 0x80008000, OUTPUT, DMA_SIZE_32);
|
||||
if (!_arb->begin(pwm_get_dreq(pwm_gpio_to_slice_num(_pin)), (volatile void*)ccAddr)) {
|
||||
if (!_arb->begin(_pacer_dreq, (volatile void*)ccAddr)) {
|
||||
_running = false;
|
||||
delete _arb;
|
||||
_arb = nullptr;
|
||||
@@ -143,6 +169,9 @@ void PWMAudio::end() {
|
||||
}
|
||||
delete _arb;
|
||||
_arb = nullptr;
|
||||
|
||||
dma_timer_unclaim(_pacer);
|
||||
_pacer = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,3 +248,44 @@ size_t PWMAudio::write(const uint8_t *buffer, size_t size) {
|
||||
}
|
||||
return writtenSize;
|
||||
}
|
||||
|
||||
void PWMAudio::find_pacer_fraction(int target, uint16_t *numerator, uint16_t *denominator) {
|
||||
const uint16_t max = 0xFFFF;
|
||||
|
||||
/*Cache last results so we dont have to recalculate*/
|
||||
static int last_target;
|
||||
static uint16_t bestNum;
|
||||
static uint16_t bestDenom;
|
||||
/*Check if we can load the previous values*/
|
||||
if (target == last_target) {
|
||||
*numerator = bestNum;
|
||||
*denominator = bestDenom;
|
||||
return;
|
||||
}
|
||||
|
||||
float targetRatio = (float)F_CPU / target;
|
||||
float lowestError = HUGE_VALF;
|
||||
|
||||
for (uint16_t denom = 1; denom < max; denom++) {
|
||||
uint16_t num = (int)((targetRatio * denom) + 0.5f); /*Calculate numerator, rounding to nearest integer*/
|
||||
|
||||
/*Check if numerator is within bounds*/
|
||||
if (num > 0 && num < max) {
|
||||
float actualRatio = (float)num / denom;
|
||||
float error = fabsf(actualRatio - targetRatio);
|
||||
|
||||
if (error < lowestError) {
|
||||
bestNum = num;
|
||||
bestDenom = denom;
|
||||
lowestError = error;
|
||||
if (error == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_target = target;
|
||||
*numerator = bestNum;
|
||||
*denominator = bestDenom;
|
||||
}
|
||||
@@ -29,12 +29,21 @@ public:
|
||||
virtual ~PWMAudio();
|
||||
|
||||
bool setBuffers(size_t buffers, size_t bufferWords);
|
||||
bool setFrequency(int newFreq);
|
||||
/*Sets the frequency of the PWM in hz*/
|
||||
bool setPWMFrequency(int newFreq);
|
||||
/*Sets the sample rate frequency in hz*/
|
||||
bool setFrequency(int frequency);
|
||||
bool setPin(pin_size_t pin);
|
||||
bool setStereo(bool stereo = true);
|
||||
|
||||
bool begin(long sampleRate) {
|
||||
setFrequency(sampleRate);
|
||||
_sampleRate = sampleRate;
|
||||
return begin();
|
||||
}
|
||||
|
||||
bool begin(long sampleRate, long PWMfrequency) {
|
||||
setPWMFrequency(PWMfrequency);
|
||||
_sampleRate = sampleRate;
|
||||
return begin();
|
||||
}
|
||||
|
||||
@@ -70,6 +79,9 @@ private:
|
||||
bool _stereo;
|
||||
|
||||
int _freq;
|
||||
int _sampleRate;
|
||||
|
||||
int _pacer;
|
||||
|
||||
size_t _buffers;
|
||||
size_t _bufferWords;
|
||||
@@ -84,4 +96,7 @@ private:
|
||||
void (*_cb)();
|
||||
|
||||
AudioBufferManager *_arb;
|
||||
|
||||
/*An accurate but brute force method to find 16bit numerator and denominator.*/
|
||||
void find_pacer_fraction(int target, uint16_t *numerator, uint16_t *denominator);
|
||||
};
|
||||
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
}
|
||||
|
||||
String softAPmacAddress(void) {
|
||||
uint8_t mac[8];
|
||||
uint8_t mac[6];
|
||||
macAddress(mac);
|
||||
char buff[32];
|
||||
sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
@@ -240,7 +240,7 @@ public:
|
||||
*/
|
||||
uint8_t* macAddress(uint8_t* mac);
|
||||
String macAddress(void) {
|
||||
uint8_t mac[8];
|
||||
uint8_t mac[6];
|
||||
macAddress(mac);
|
||||
char buff[32];
|
||||
sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
WiFi <-> LWIP for ESPHost library in RP2040 Core
|
||||
WiFi <-> LWIP for ESPHost library in RP2040 Core
|
||||
|
||||
Copyright (c) 2024 Juraj Andrassy
|
||||
Copyright (c) 2024 Juraj Andrassy
|
||||
|
||||
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 "ESPHost.h"
|
||||
#include "CEspControl.h"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ void ESPHostLwIP::setSSID(const char *ssid) {
|
||||
}
|
||||
|
||||
void ESPHostLwIP::setBSSID(const uint8_t *bssid) {
|
||||
if (bssid == nullptr) {
|
||||
if (bssid == nullptr || !(bssid[0] | bssid[1] | bssid[2] | bssid[3] | bssid[4] | bssid[5])) {
|
||||
ap.bssid[0] = 0;
|
||||
} else {
|
||||
memcpy(ap.bssid, bssid, sizeof(ap.bssid));
|
||||
snprintf((char *)ap.bssid, sizeof(ap.bssid), "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,14 +95,16 @@ int ESPHostLwIP::disconnectEventCb(CCtrlMsgWrapper *resp) {
|
||||
}
|
||||
|
||||
bool ESPHostLwIP::initHW() {
|
||||
if (wifiHwInitialized)
|
||||
if (wifiHwInitialized) {
|
||||
return true;
|
||||
}
|
||||
instance = this;
|
||||
|
||||
CEspControl::getInstance().listenForStationDisconnectEvent(disconnectEventCb);
|
||||
CEspControl::getInstance().listenForInitEvent(initEventCb);
|
||||
if (CEspControl::getInstance().initSpiDriver() != 0)
|
||||
if (CEspControl::getInstance().initSpiDriver() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t start = millis();
|
||||
while (!wifiHwInitialized && (millis() - start < timeout)) {
|
||||
@@ -117,8 +119,9 @@ bool ESPHostLwIP::initHW() {
|
||||
}
|
||||
|
||||
bool ESPHostLwIP::begin() {
|
||||
if (!initHW())
|
||||
if (!initHW()) {
|
||||
return false;
|
||||
}
|
||||
ethernet_arch_lwip_begin();
|
||||
if (!apMode) {
|
||||
CEspControl::getInstance().setWifiMode(WIFI_MODE_STA);
|
||||
@@ -131,7 +134,7 @@ bool ESPHostLwIP::begin() {
|
||||
} else {
|
||||
CEspControl::getInstance().setWifiMode(WIFI_MODE_AP);
|
||||
if (softAP.channel == 0 || softAP.channel > MAX_CHNL_NO) {
|
||||
softAP.channel = 1;
|
||||
softAP.channel = 1;
|
||||
}
|
||||
softAP.max_connections = MAX_SOFTAP_CONNECTION_DEF;
|
||||
softAP.encryption_mode = softAP.pwd[0] == 0 ? WIFI_AUTH_OPEN : WIFI_AUTH_WPA_WPA2_PSK;
|
||||
@@ -198,8 +201,9 @@ uint8_t ESPHostLwIP::status() {
|
||||
}
|
||||
|
||||
uint8_t* ESPHostLwIP::macAddress(bool apMode, uint8_t *mac) {
|
||||
if (!initHW())
|
||||
if (!initHW()) {
|
||||
return mac;
|
||||
}
|
||||
WifiMac_t MAC;
|
||||
MAC.mode = apMode ? WIFI_MODE_AP : WIFI_MODE_STA;
|
||||
ethernet_arch_lwip_begin();
|
||||
@@ -220,8 +224,9 @@ int ESPHostLwIP::channel() {
|
||||
}
|
||||
|
||||
int32_t ESPHostLwIP::RSSI() {
|
||||
if (!joined)
|
||||
if (!joined) {
|
||||
return 0;
|
||||
}
|
||||
ethernet_arch_lwip_begin();
|
||||
CEspControl::getInstance().getAccessPointConfig(ap);
|
||||
ethernet_arch_lwip_end();
|
||||
@@ -254,15 +259,18 @@ uint8_t ESPHostLwIP::encryptionType() {
|
||||
}
|
||||
|
||||
int8_t ESPHostLwIP::scanNetworks(bool async) {
|
||||
(void) async;
|
||||
accessPoints.clear();
|
||||
if (!initHW())
|
||||
if (!initHW()) {
|
||||
return -1;
|
||||
}
|
||||
ethernet_arch_lwip_begin();
|
||||
int res = CEspControl::getInstance().getAccessPointScanList(accessPoints);
|
||||
ethernet_arch_lwip_end();
|
||||
wifiStatus = WL_SCAN_COMPLETED;
|
||||
if (res != ESP_CONTROL_OK)
|
||||
if (res != ESP_CONTROL_OK) {
|
||||
return -1;
|
||||
}
|
||||
return accessPoints.size();
|
||||
}
|
||||
|
||||
@@ -310,8 +318,9 @@ int32_t ESPHostLwIP::RSSI(uint8_t networkItem) {
|
||||
}
|
||||
|
||||
void ESPHostLwIP::lowPowerMode() {
|
||||
if (!initHW())
|
||||
if (!initHW()) {
|
||||
return;
|
||||
}
|
||||
ethernet_arch_lwip_begin();
|
||||
CEspControl::getInstance().setPowerSaveMode(1);
|
||||
ethernet_arch_lwip_end();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -72,6 +72,45 @@ void __removeEthernetPacketHandler(int id) {
|
||||
ethernet_arch_lwip_end();
|
||||
}
|
||||
|
||||
#define GPIOSTACKSIZE 8
|
||||
static uint32_t gpioMaskStack[GPIOSTACKSIZE][4];
|
||||
static uint32_t gpioMask[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
|
||||
|
||||
void ethernet_arch_lwip_gpio_mask() {
|
||||
noInterrupts();
|
||||
memmove(gpioMaskStack[1], gpioMaskStack[0], 4 * sizeof(uint32_t) * (GPIOSTACKSIZE - 1)); // Push down the stack
|
||||
io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
gpioMaskStack[0][i] = irq_ctrl_base->inte[i];
|
||||
irq_ctrl_base->inte[i] = irq_ctrl_base->inte[i] & gpioMask[i];
|
||||
}
|
||||
interrupts();
|
||||
}
|
||||
|
||||
void ethernet_arch_lwip_gpio_unmask() {
|
||||
noInterrupts();
|
||||
io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
irq_ctrl_base->inte[i] = gpioMaskStack[0][i];
|
||||
}
|
||||
memmove(gpioMaskStack[0], gpioMaskStack[1], 4 * sizeof(uint32_t) * (GPIOSTACKSIZE - 1)); // Pop up the stack
|
||||
interrupts();
|
||||
}
|
||||
|
||||
// To be called after IRQ is set, so we can just rad from the IOREG instead of duplicating the calculation
|
||||
void __addEthernetGPIO(int pin) {
|
||||
int idx = pin / 8;
|
||||
int off = (pin % 8) * 4;
|
||||
gpioMask[idx] &= ~(0xf << off);
|
||||
}
|
||||
|
||||
void __removeEthernetGPIO(int pin) {
|
||||
int idx = pin / 8;
|
||||
int off = (pin % 8) * 4;
|
||||
gpioMask[idx] |= 0xf << off;
|
||||
}
|
||||
|
||||
|
||||
static volatile bool _dns_lookup_pending = false;
|
||||
|
||||
static void _dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) {
|
||||
@@ -134,6 +173,7 @@ static uint32_t _pollingPeriod = 20;
|
||||
static void ethernet_timeout_reached(__unused async_context_t *context, __unused async_at_time_worker_t *worker) {
|
||||
assert(worker == ðernet_timeout_worker);
|
||||
__ethernet_timeout_reached_calls++;
|
||||
ethernet_arch_lwip_gpio_mask(); // Ensure non-polled devices won't interrupt us
|
||||
for (auto handlePacket : _handlePacketList) {
|
||||
handlePacket.second();
|
||||
}
|
||||
@@ -144,6 +184,7 @@ static void ethernet_timeout_reached(__unused async_context_t *context, __unused
|
||||
#else
|
||||
sys_check_timeouts();
|
||||
#endif
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
}
|
||||
|
||||
static void update_next_timeout(async_context_t *context, async_when_pending_worker_t *worker) {
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
|
||||
void ethernet_arch_lwip_begin() __attribute__((weak));
|
||||
void ethernet_arch_lwip_end() __attribute__((weak));
|
||||
void ethernet_arch_lwip_gpio_mask() __attribute__((weak));
|
||||
void ethernet_arch_lwip_gpio_unmask() __attribute__((weak));
|
||||
|
||||
void __addEthernetGPIO(int pin);
|
||||
void __removeEthernetGPIO(int pin);
|
||||
|
||||
// Internal Ethernet helper functions
|
||||
void __startEthernetContext();
|
||||
|
||||
@@ -144,6 +144,7 @@ public:
|
||||
return _packetsSent;
|
||||
}
|
||||
|
||||
|
||||
// ESP8266WiFi API compatibility
|
||||
|
||||
wl_status_t status();
|
||||
@@ -156,6 +157,7 @@ protected:
|
||||
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);
|
||||
static void _irq(void *param);
|
||||
public:
|
||||
// called on a regular basis or on interrupt
|
||||
err_t handlePackets();
|
||||
@@ -358,7 +360,9 @@ bool LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_phID = __addEthernetPacketHandler([this] { this->handlePackets(); });
|
||||
if (_intrPin < 0) {
|
||||
_phID = __addEthernetPacketHandler([this] { this->handlePackets(); });
|
||||
}
|
||||
|
||||
if (localIP().v4() == 0) {
|
||||
// IP not set, starting DHCP
|
||||
@@ -393,7 +397,11 @@ bool LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu) {
|
||||
|
||||
if (_intrPin >= 0) {
|
||||
if (RawDev::interruptIsPossible()) {
|
||||
// attachInterrupt(_intrPin, [&]() { this->handlePackets(); }, FALLING);
|
||||
noInterrupts(); // Ensure this is atomically set up
|
||||
pinMode(_intrPin, INPUT);
|
||||
attachInterruptParam(_intrPin, _irq, LOW, (void*)this);
|
||||
__addEthernetGPIO(_intrPin);
|
||||
interrupts();
|
||||
} else {
|
||||
::printf((PGM_P)F(
|
||||
"lwIP_Intf: Interrupt not implemented yet, enabling transparent polling\r\n"));
|
||||
@@ -406,7 +414,12 @@ bool LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu) {
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::end() {
|
||||
__removeEthernetPacketHandler(_phID);
|
||||
if (_intrPin < 0) {
|
||||
__removeEthernetPacketHandler(_phID);
|
||||
} else {
|
||||
detachInterrupt(_intrPin);
|
||||
__removeEthernetGPIO(_intrPin);
|
||||
}
|
||||
|
||||
RawDev::end();
|
||||
|
||||
@@ -415,6 +428,14 @@ void LwipIntfDev<RawDev>::end() {
|
||||
_started = false;
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::_irq(void *param) {
|
||||
LwipIntfDev *d = static_cast<LwipIntfDev*>(param);
|
||||
ethernet_arch_lwip_begin();
|
||||
d->handlePackets();
|
||||
sys_check_timeouts();
|
||||
ethernet_arch_lwip_end();
|
||||
}
|
||||
|
||||
template<class RawDev>
|
||||
wl_status_t LwipIntfDev<RawDev>::status() {
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
#define ECON2_AUTOINC 0x80
|
||||
#define ECON2_PKTDEC 0x40
|
||||
|
||||
#define EIE_PKTIE 0x40
|
||||
#define EIE_INTIE 0x80
|
||||
|
||||
#define EIR_TXIF 0x08
|
||||
|
||||
#define ERXTX_BANK 0x00
|
||||
@@ -153,8 +156,7 @@
|
||||
// The ENC28J60 SPI Interface supports clock speeds up to 20 MHz
|
||||
static const SPISettings spiSettings(20000000, MSBFIRST, SPI_MODE0);
|
||||
|
||||
ENC28J60::ENC28J60(int8_t cs, SPIClass& spi, int8_t intr) : _bank(ERXTX_BANK), _cs(cs), _spi(spi) {
|
||||
(void)intr;
|
||||
ENC28J60::ENC28J60(int8_t cs, SPIClass& spi, int8_t intr) : _bank(ERXTX_BANK), _cs(cs), _intr(intr), _spi(spi) {
|
||||
}
|
||||
|
||||
void ENC28J60::enc28j60_arch_spi_select(void) {
|
||||
@@ -488,6 +490,12 @@ bool ENC28J60::reset(void) {
|
||||
/* Turn on autoincrement for buffer access */
|
||||
setregbitfield(ECON2, ECON2_AUTOINC);
|
||||
|
||||
/* Enable interrupt on packet receive if desired */
|
||||
if (_intr >= 0) {
|
||||
setregbitfield(EIE, EIE_PKTIE);
|
||||
setregbitfield(EIE, EIE_INTIE);
|
||||
}
|
||||
|
||||
/* Turn on reception */
|
||||
writereg(ECON1, ECON1_RXEN);
|
||||
|
||||
@@ -511,6 +519,8 @@ bool ENC28J60::begin(const uint8_t* address, netif *net) {
|
||||
uint16_t ENC28J60::sendFrame(const uint8_t* data, uint16_t datalen) {
|
||||
uint16_t dataend;
|
||||
|
||||
ethernet_arch_lwip_gpio_mask(); // So we don't fire an IRQ and interrupt the send w/a receive!
|
||||
|
||||
/*
|
||||
1. Appropriately program the ETXST pointer to point to an unused
|
||||
location in memory. It will point to the per packet control
|
||||
@@ -582,6 +592,8 @@ uint16_t ENC28J60::sendFrame(const uint8_t* data, uint16_t datalen) {
|
||||
}
|
||||
#endif
|
||||
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
|
||||
// sent_packets++;
|
||||
// PRINTF("enc28j60: sent_packets %d\n", sent_packets);
|
||||
return datalen;
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
netif *_netif;
|
||||
protected:
|
||||
static constexpr bool interruptIsPossible() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,6 +154,7 @@ private:
|
||||
|
||||
uint8_t _bank;
|
||||
int8_t _cs;
|
||||
int8_t _intr;
|
||||
SPIClass& _spi;
|
||||
|
||||
const uint8_t* _localMac;
|
||||
|
||||
@@ -8,14 +8,21 @@
|
||||
const char* host = "djxmmx.net";
|
||||
const uint16_t port = 17;
|
||||
|
||||
#ifdef ARDUINO_WIZNET_5100S_EVB_PICO
|
||||
// To use Interrupt-driven mode, pass in an SPI object and an IRQ pin like so:
|
||||
Wiznet5100lwIP eth(17, SPI, 21);
|
||||
#else
|
||||
Wiznet5100lwIP eth(1 /* chip select */);
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
#ifndef ARDUINO_WIZNET_5100S_EVB_PICO
|
||||
// Set up SPI pinout to match your HW
|
||||
SPI.setRX(0);
|
||||
SPI.setCS(1);
|
||||
SPI.setSCK(2);
|
||||
SPI.setTX(3);
|
||||
#endif
|
||||
|
||||
Serial.begin(115200);
|
||||
delay(5000);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <SPI.h>
|
||||
#include "w5100.h"
|
||||
#include <LwipEthernet.h>
|
||||
|
||||
uint8_t Wiznet5100::wizchip_read(uint16_t address) {
|
||||
uint8_t ret;
|
||||
@@ -178,8 +179,7 @@ void Wiznet5100::wizchip_sw_reset() {
|
||||
setSHAR(_mac_address);
|
||||
}
|
||||
|
||||
Wiznet5100::Wiznet5100(int8_t cs, SPIClass& spi, int8_t intr) : _spi(spi), _cs(cs) {
|
||||
(void)intr;
|
||||
Wiznet5100::Wiznet5100(int8_t cs, SPIClass& spi, int8_t intr) : _spi(spi), _cs(cs), _intr(intr) {
|
||||
}
|
||||
|
||||
bool Wiznet5100::begin(const uint8_t* mac_address, netif *net) {
|
||||
@@ -189,13 +189,6 @@ bool Wiznet5100::begin(const uint8_t* mac_address, netif *net) {
|
||||
pinMode(_cs, OUTPUT);
|
||||
wizchip_cs_deselect();
|
||||
|
||||
#if 0
|
||||
_spi.begin();
|
||||
_spi.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz?
|
||||
_spi.setBitOrder(MSBFIRST);
|
||||
_spi.setDataMode(SPI_MODE0);
|
||||
#endif
|
||||
|
||||
wizchip_sw_reset();
|
||||
|
||||
// Set the size of the Rx and Tx buffers
|
||||
@@ -213,6 +206,11 @@ bool Wiznet5100::begin(const uint8_t* mac_address, netif *net) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_intr >= 0) {
|
||||
setSn_IR(0xff); // Clear everything
|
||||
setIMR(IM_IR0);
|
||||
}
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
@@ -245,6 +243,8 @@ uint16_t Wiznet5100::readFrame(uint8_t* buffer, uint16_t bufsize) {
|
||||
}
|
||||
|
||||
uint16_t Wiznet5100::readFrameSize() {
|
||||
setSn_IR(Sn_IR_RECV);
|
||||
|
||||
uint16_t len = getSn_RX_RSR();
|
||||
|
||||
if (len == 0) {
|
||||
@@ -273,25 +273,18 @@ uint16_t Wiznet5100::readFrameData(uint8_t* buffer, uint16_t framesize) {
|
||||
wizchip_recv_data(buffer, framesize);
|
||||
setSn_CR(Sn_CR_RECV);
|
||||
|
||||
#if 1
|
||||
// let lwIP deal with mac address filtering
|
||||
return framesize;
|
||||
#else
|
||||
// W5100 doesn't have any built-in MAC address filtering
|
||||
if ((buffer[0] & 0x01) || memcmp(&buffer[0], _mac_address, 6) == 0) {
|
||||
// Addressed to an Ethernet multicast address or our unicast address
|
||||
return framesize;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t Wiznet5100::sendFrame(const uint8_t* buf, uint16_t len) {
|
||||
ethernet_arch_lwip_gpio_mask(); // So we don't fire an IRQ and interrupt the send w/a receive!
|
||||
|
||||
// Wait for space in the transmit buffer
|
||||
while (1) {
|
||||
uint16_t freesize = getSn_TX_FSR();
|
||||
if (getSn_SR() == SOCK_CLOSED) {
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
return -1;
|
||||
}
|
||||
if (len <= freesize) {
|
||||
@@ -311,9 +304,11 @@ uint16_t Wiznet5100::sendFrame(const uint8_t* buf, uint16_t len) {
|
||||
} else if (tmp & Sn_IR_TIMEOUT) {
|
||||
setSn_IR(Sn_IR_TIMEOUT);
|
||||
// There was a timeout
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
netif *_netif;
|
||||
protected:
|
||||
static constexpr bool interruptIsPossible() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,6 +144,7 @@ private:
|
||||
|
||||
SPIClass& _spi;
|
||||
int8_t _cs;
|
||||
int8_t _intr;
|
||||
uint8_t _mac_address[6];
|
||||
|
||||
/**
|
||||
@@ -308,6 +309,17 @@ private:
|
||||
MR_IND = 0x01, ///< Indirect Bus Interface mode
|
||||
};
|
||||
|
||||
/** Interrupt Mask register values */
|
||||
enum {
|
||||
IM_IR0 = 0x01, ///< Occurrence of Socket 0 Socket Interrupt Enable
|
||||
IM_IR1 = 0x02, ///< Occurrence of Socket 1 Socket Interrupt Enable
|
||||
IM_IR2 = 0x04, ///< Occurrence of Socket 2 Socket Interrupt Enable
|
||||
IM_IR3 = 0x08, ///< Occurrence of Socket 3 Socket Interrupt Enable
|
||||
IM_IR5 = 0x20, ///< PPPoE Close Enable
|
||||
IM_IR6 = 0x40, ///< Destination unreachable Enable
|
||||
IM_IR7 = 0x80, ///< IP Conflict Enable
|
||||
};
|
||||
|
||||
/** Socket Mode Register values @ref Sn_MR */
|
||||
enum {
|
||||
Sn_MR_CLOSE = 0x00, ///< Unused socket
|
||||
@@ -375,6 +387,24 @@ private:
|
||||
return wizchip_read(MR);
|
||||
}
|
||||
|
||||
/**
|
||||
Set Interrupt Mask Register
|
||||
@param (uint8_t)mr The value to be set.
|
||||
@sa geIMR()
|
||||
*/
|
||||
inline void setIMR(uint8_t mode) {
|
||||
wizchip_write(IMR, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
Get Mode Register
|
||||
@return uint8_t. The value of Mode register.
|
||||
@sa setIMR()
|
||||
*/
|
||||
inline uint8_t getIMR() {
|
||||
return wizchip_read(IMR);
|
||||
}
|
||||
|
||||
/**
|
||||
Set local MAC address
|
||||
@param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <SPI.h>
|
||||
#include "w5500.h"
|
||||
#include <LwipEthernet.h>
|
||||
|
||||
uint8_t Wiznet5500::wizchip_read(uint8_t block, uint16_t address) {
|
||||
uint8_t ret;
|
||||
@@ -238,8 +239,7 @@ int8_t Wiznet5500::wizphy_setphypmode(uint8_t pmode) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Wiznet5500::Wiznet5500(int8_t cs, SPIClass& spi, int8_t intr) : _spi(spi), _cs(cs) {
|
||||
(void)intr;
|
||||
Wiznet5500::Wiznet5500(int8_t cs, SPIClass& spi, int8_t intr) : _spi(spi), _cs(cs), _intr(intr) {
|
||||
}
|
||||
|
||||
bool Wiznet5500::begin(const uint8_t* mac_address, netif *net) {
|
||||
@@ -249,13 +249,6 @@ bool Wiznet5500::begin(const uint8_t* mac_address, netif *net) {
|
||||
pinMode(_cs, OUTPUT);
|
||||
wizchip_cs_deselect();
|
||||
|
||||
#if 0
|
||||
_spi.begin();
|
||||
_spi.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz?
|
||||
_spi.setBitOrder(MSBFIRST);
|
||||
_spi.setDataMode(SPI_MODE0);
|
||||
#endif
|
||||
|
||||
wizchip_sw_reset();
|
||||
|
||||
// Use the full 16Kb of RAM for Socket 0
|
||||
@@ -273,6 +266,11 @@ bool Wiznet5500::begin(const uint8_t* mac_address, netif *net) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_intr >= 0) {
|
||||
setSn_IR(0xff); // Clear everything
|
||||
setSIMR(1);
|
||||
}
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
@@ -305,6 +303,8 @@ uint16_t Wiznet5500::readFrame(uint8_t* buffer, uint16_t bufsize) {
|
||||
}
|
||||
|
||||
uint16_t Wiznet5500::readFrameSize() {
|
||||
setSn_IR(Sn_IR_RECV);
|
||||
|
||||
uint16_t len = getSn_RX_RSR();
|
||||
|
||||
if (len == 0) {
|
||||
@@ -333,26 +333,18 @@ uint16_t Wiznet5500::readFrameData(uint8_t* buffer, uint16_t framesize) {
|
||||
wizchip_recv_data(buffer, framesize);
|
||||
setSn_CR(Sn_CR_RECV);
|
||||
|
||||
#if 1
|
||||
// let lwIP deal with mac address filtering
|
||||
return framesize;
|
||||
#else
|
||||
// Had problems with W5500 MAC address filtering (the Sn_MR_MFEN option)
|
||||
// Do it in software instead:
|
||||
if ((buffer[0] & 0x01) || memcmp(&buffer[0], _mac_address, 6) == 0) {
|
||||
// Addressed to an Ethernet multicast address or our unicast address
|
||||
return framesize;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t Wiznet5500::sendFrame(const uint8_t* buf, uint16_t len) {
|
||||
ethernet_arch_lwip_gpio_mask(); // So we don't fire an IRQ and interrupt the send w/a receive!
|
||||
|
||||
// Wait for space in the transmit buffer
|
||||
while (1) {
|
||||
uint16_t freesize = getSn_TX_FSR();
|
||||
if (getSn_SR() == SOCK_CLOSED) {
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
return -1;
|
||||
}
|
||||
if (len <= freesize) {
|
||||
@@ -372,9 +364,11 @@ uint16_t Wiznet5500::sendFrame(const uint8_t* buf, uint16_t len) {
|
||||
} else if (tmp & Sn_IR_TIMEOUT) {
|
||||
setSn_IR(Sn_IR_TIMEOUT);
|
||||
// There was a timeout
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ethernet_arch_lwip_gpio_unmask();
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
|
||||
protected:
|
||||
static constexpr bool interruptIsPossible() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +152,7 @@ private:
|
||||
|
||||
SPIClass& _spi;
|
||||
int8_t _cs;
|
||||
int8_t _intr;
|
||||
uint8_t _mac_address[6];
|
||||
|
||||
/**
|
||||
@@ -319,7 +320,7 @@ private:
|
||||
IR = 0x0015, ///< Interrupt Register (R/W)
|
||||
_IMR_ = 0x0016, ///< Interrupt mask register (R/W)
|
||||
SIR = 0x0017, ///< Socket Interrupt Register (R/W)
|
||||
SIMR = 0x0018, ///< Socket Interrupt Mask Register (R/W)
|
||||
_SIMR_ = 0x0018, ///< Socket Interrupt Mask Register (R/W)
|
||||
_RTR_ = 0x0019, ///< Timeout register address (1 is 100us) (R/W)
|
||||
_RCR_ = 0x001B, ///< Retry count register (R/W)
|
||||
UIPR = 0x0028, ///< Unreachable IP register address in UDP mode (R)
|
||||
@@ -520,6 +521,24 @@ private:
|
||||
return wizchip_read(BlockSelectCReg, IR) & 0xF0;
|
||||
}
|
||||
|
||||
/**
|
||||
Set @ref SIR register
|
||||
@param (uint8_t)ir Value to set @ref SIR register.
|
||||
@sa getSIR()
|
||||
*/
|
||||
inline void setSIR(uint8_t ir) {
|
||||
wizchip_write(BlockSelectCReg, SIR, ir);
|
||||
}
|
||||
|
||||
/**
|
||||
Get @ref SIR register
|
||||
@return uint8_t. Value of @ref SIR register.
|
||||
@sa setSIR()
|
||||
*/
|
||||
inline uint8_t getSIR() {
|
||||
return wizchip_read(BlockSelectCReg, SIR);
|
||||
}
|
||||
|
||||
/**
|
||||
Set @ref _IMR_ register
|
||||
@param (uint8_t)imr Value to set @ref _IMR_ register.
|
||||
@@ -538,6 +557,24 @@ private:
|
||||
return wizchip_read(BlockSelectCReg, _IMR_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set @ref _SIMR_ register
|
||||
@param (uint8_t)imr Value to set @ref _SIMR_ register.
|
||||
@sa getIMR()
|
||||
*/
|
||||
inline void setSIMR(uint8_t imr) {
|
||||
wizchip_write(BlockSelectCReg, _SIMR_, imr);
|
||||
}
|
||||
|
||||
/**
|
||||
Get @ref _SIMR_ register
|
||||
@return uint8_t. Value of @ref _SIMR_ register.
|
||||
@sa setSIMR()
|
||||
*/
|
||||
inline uint8_t getSIMR() {
|
||||
return wizchip_read(BlockSelectCReg, _SIMR_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set @ref PHYCFGR register
|
||||
@param (uint8_t)phycfgr Value to set @ref PHYCFGR register.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "framework-arduinopico",
|
||||
"version": "1.30700.0",
|
||||
"version": "1.30702.0",
|
||||
"description": "Arduino Wiring-based Framework (RPi Pico RP2040)",
|
||||
"keywords": [
|
||||
"framework",
|
||||
|
||||
@@ -314,10 +314,10 @@
|
||||
},
|
||||
{
|
||||
"host": "i686-mingw32",
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/2.2.0/i686-w64-mingw32.picotool-f6fe6b7.240125.zip",
|
||||
"archiveFileName": "i686-w64-mingw32.picotool-f6fe6b7.240125.zip",
|
||||
"checksum": "SHA-256:f8a1ea6f0ea863b74a26b155fca780f24403f1069921e965f904ceac3d328dd5",
|
||||
"size": "292401"
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/2.2.0/i686-w64-mingw32.picotool-f6fe6b7.240125a.zip",
|
||||
"archiveFileName": "i686-w64-mingw32.picotool-f6fe6b7.240125a.zip",
|
||||
"checksum": "SHA-256:75a6672f56972bdc95cd6422a4709c372cd84e08ac07eefd8b1c2842b8617d99",
|
||||
"size": "291095"
|
||||
},
|
||||
{
|
||||
"host": "x86_64-apple-darwin",
|
||||
@@ -335,10 +335,10 @@
|
||||
},
|
||||
{
|
||||
"host": "x86_64-mingw32",
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/2.2.0/x86_64-w64-mingw32.picotool-f6fe6b7.240125.zip",
|
||||
"archiveFileName": "x86_64-w64-mingw32.picotool-f6fe6b7.240125.zip",
|
||||
"checksum": "SHA-256:0e75f683223b5237051d1a1e47917f2b37b2b3a8ac11e516a0020dffbd49d3bd",
|
||||
"size": "277241"
|
||||
"url": "https://github.com/earlephilhower/pico-quick-toolchain/releases/download/2.2.0/x86_64-w64-mingw32.picotool-f6fe6b7.240125a.zip",
|
||||
"archiveFileName": "x86_64-w64-mingw32.picotool-f6fe6b7.240125a.zip",
|
||||
"checksum": "SHA-256:79a68e3d3d080cacfafc9c1546a3675ce5c7f858e6e85c690584251e63a2bee3",
|
||||
"size": "276468"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
|
||||
|
||||
name=Raspberry Pi RP2040 Boards
|
||||
version=3.7.0
|
||||
version=3.7.2
|
||||
|
||||
# Required discoveries and monitors
|
||||
# ---------------------------------
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S ./libraries/SingleF
|
||||
./libraries/MouseBT ./libraries/SerialBT ./libraries/HID_Bluetooth \
|
||||
./libraries/JoystickBLE ./libraries/KeyboardBLE ./libraries/MouseBLE \
|
||||
./libraries/lwIP_w5500 ./libraries/lwIP_w5100 ./libraries/lwIP_enc28j60 \
|
||||
./libraries/SPISlave ; do
|
||||
./libraries/SPISlave ./libraries/lwIP_ESPHost; 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
|
||||
|
||||
+1
-1
@@ -261,7 +261,7 @@ def get_drives():
|
||||
print("Unable to build drive list");
|
||||
sys.exit(1)
|
||||
for line in to_str(r).split('\n'):
|
||||
words = re.split('\s+', line)
|
||||
words = re.split(r'\s+', line)
|
||||
if len(words) >= 3 and words[1] == "2" and words[2] == "FAT":
|
||||
drives.append(words[0])
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user