Skip to content

Commit d92c102

Browse files
Update to SDK 1.5, add alpha-level BT support, use Pico-SDK CYW43 infrastructure (#1167)
* Update to Pico-SDK v1.5 * Hook in pico_rand, use ioctl to set ipv6 allmulti * Move into PicoSDK LWIP mutex, hack timer sizes * Utilize much of the PicoSDK infrastructure for WiFi * Add WiFi::begin(ssid, pass, bssid) * WiFiMulti to use BSSID, make more robust WiFiMulti will now be more aggressive and try all matching SSIDs, in order of RSSI, using the BSSID to identify individual APs in a mesh. Before, if the highest RSSI AP didn't connect, it would fail immediately. Now, it will go down the list, ordered by RSSI, to attempt to get a link. * Add Bluetooth support from Pico-SDK Able to build and run the HID Keyboard Demo from the Arduino IDE, almost as-is. Will probably need to make BT configurable. Enabling BT on a plain WiFi sketch uses 50KB of flash and 16KB of RAM even if no BT is used. * Separate picow libs, BT through menus, example Build normal Pico.a and 4 different options for PicoW IP/BT configuration. Use IP=>IP/Bluetooth menu to select between options. * CMakefile rationalization * Move BT TLV(pairing) out of last 2 flash sectors The pairing keys for BT are stored at the end of flash by default, but we use the last sector of flash for EPROM and the penultimate one for the filesystem. Overwriting those in BT could cause some real exciting crashes down the line. Move the store to an app-build specific address using a dummy const array to allocate space in the application image itself. * PicoBluetoothHID with BT Mouse, Joystick, Keyboard Add simple Bluetooth Classic HID helper function and port the existing USB HID devices to it. Port their examples. * Protect BT key storage from multicore * Add short-n-sweet Bluetooth documents * Add Bluetooth Serial port library * Turn off BT when the BT libraries exit
1 parent de55db1 commit d92c102

File tree

79 files changed

+5423
-918
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+5423
-918
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ The installed tools include a version of OpenOCD (in the pqt-openocd directory)
163163
164164
# Features
165165
* Adafruit TinyUSB Arduino (USB mouse, keyboard, flash drive, generic HID, CDC Serial, MIDI, WebUSB, others)
166-
* Generic Arduino USB Serial, Keyboard, and Mouse emulation
166+
* Bluetooth on the PicoW (Classic and BLE) with Keyboard, Mouse, Joystick, and Virtual Serial
167+
* Generic Arduino USB Serial, Keyboard, Joystick, and Mouse emulation
167168
* WiFi (Pico W)
168169
* HTTP client and server (WebServer)
169170
* SSL/TLS/HTTPS

boards.txt

Lines changed: 601 additions & 301 deletions
Large diffs are not rendered by default.

cores/rp2040/RP2040Support.h

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <hardware/structs/rosc.h>
2828
#include <hardware/structs/systick.h>
2929
#include <pico/multicore.h>
30+
#include <pico/rand.h>
3031
#include <pico/util/queue.h>
3132
#include "CoreMutex.h"
3233
#include "ccount.pio.h"
@@ -341,26 +342,8 @@ class RP2040 {
341342
_MFIFO fifo;
342343

343344

344-
// TODO - Not so great HW random generator. 32-bits wide. Cryptographers somewhere are crying
345345
uint32_t hwrand32() {
346-
// Try and whiten the HW ROSC bit
347-
uint32_t r = 0;
348-
for (int k = 0; k < 32; k++) {
349-
unsigned long int b;
350-
do {
351-
b = rosc_hw->randombit & 1;
352-
if (b != (rosc_hw->randombit & 1)) {
353-
break;
354-
}
355-
} while (true);
356-
r <<= 1;
357-
r |= b;
358-
}
359-
// Stir using the cycle count LSBs. In any WiFi use case this will be a random # since the connection time is not cycle-accurate
360-
uint64_t rr = (((uint64_t)~r) << 32LL) | r;
361-
rr >>= rp2040.getCycleCount() & 32LL;
362-
363-
return (uint32_t)rr;
346+
return get_rand_32();
364347
}
365348

366349
bool isPicoW() {

cores/rp2040/cyw43_wrappers.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
CYW43 TCP/Ethernet wrappers
3+
Copyright (c) 2023 Earle F. Philhower, III <[email protected]>
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
21+
22+
#include "lwip/netif.h"
23+
extern "C" {
24+
#include "cyw43.h"
25+
#include "cyw43_stats.h"
26+
}
27+
#include "pico/cyw43_arch.h"
28+
#include <Arduino.h>
29+
30+
// From cyw43_ctrl.c
31+
#define WIFI_JOIN_STATE_KIND_MASK (0x000f)
32+
#define WIFI_JOIN_STATE_ACTIVE (0x0001)
33+
#define WIFI_JOIN_STATE_FAIL (0x0002)
34+
#define WIFI_JOIN_STATE_NONET (0x0003)
35+
#define WIFI_JOIN_STATE_BADAUTH (0x0004)
36+
#define WIFI_JOIN_STATE_AUTH (0x0200)
37+
#define WIFI_JOIN_STATE_LINK (0x0400)
38+
#define WIFI_JOIN_STATE_KEYED (0x0800)
39+
#define WIFI_JOIN_STATE_ALL (0x0e01)
40+
41+
// The core can't directly call a library, so put in a dummy weak one to be overridden by one in lwip_cyw43 library
42+
extern struct netif *__getCYW43Netif() __attribute__((weak));
43+
struct netif *__getCYW43Netif() {
44+
return nullptr;
45+
}
46+
47+
// CB from the cyw43 driver
48+
extern "C" void __wrap_cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
49+
(void) cb_data;
50+
(void) itf;
51+
struct netif *netif = __getCYW43Netif();
52+
if (netif && (netif->flags & NETIF_FLAG_LINK_UP)) {
53+
struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
54+
if (p != nullptr) {
55+
pbuf_take(p, buf, len);
56+
if ((netif->input(p, netif) != ERR_OK)) {
57+
pbuf_free(p);
58+
}
59+
CYW43_STAT_INC(PACKET_IN_COUNT);
60+
}
61+
}
62+
}
63+
64+
extern "C" void __wrap_cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
65+
(void) self;
66+
(void) itf;
67+
struct netif *netif = __getCYW43Netif();
68+
if (netif) {
69+
netif_set_link_up(netif);
70+
}
71+
}
72+
73+
extern "C" void __wrap_cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
74+
(void) self;
75+
(void) itf;
76+
struct netif *netif = __getCYW43Netif();
77+
if (netif) {
78+
netif_set_link_down(netif);
79+
}
80+
self->wifi_join_state &= ~WIFI_JOIN_STATE_ACTIVE;
81+
}
82+
83+
extern "C" int __wrap_cyw43_tcpip_link_status(cyw43_t *self, int itf) {
84+
struct netif *netif = __getCYW43Netif();
85+
//if ((CYW43::_netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP))
86+
// Fake this since it's only used in the SDK
87+
if (netif && ((netif->flags & (NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_LINK_UP))) {
88+
return CYW43_LINK_UP;
89+
} else {
90+
return cyw43_wifi_link_status(self, itf);
91+
}
92+
}
93+
94+
// CBs from the SDK, not needed here as we do TCP later in the game
95+
extern "C" void __wrap_cyw43_cb_tcpip_init(cyw43_t *self, int itf) {
96+
(void) self;
97+
(void) itf;
98+
}
99+
extern "C" void __wrap_cyw43_cb_tcpip_deinit(cyw43_t *self, int itf) {
100+
(void) self;
101+
(void) itf;
102+
}
103+
104+
#endif

cores/rp2040/lwip_wrap.cpp

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,45 +18,25 @@
1818
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1919
*/
2020

21-
#include "pico/mutex.h"
22-
#include "lwip/pbuf.h"
23-
#include "lwip/udp.h"
24-
#include "lwip/tcp.h"
25-
#include "lwip/dns.h"
26-
#include "lwip/raw.h"
27-
#include "lwip/timeouts.h"
28-
29-
// Global indicator that we're inside an LWIP block
30-
extern "C" {
31-
volatile bool __inLWIP = false;
32-
}
33-
34-
auto_init_recursive_mutex(__mtxLWIP);
21+
#include <pico/mutex.h>
22+
#include <lwip/pbuf.h>
23+
#include <lwip/udp.h>
24+
#include <lwip/tcp.h>
25+
#include <lwip/dns.h>
26+
#include <lwip/raw.h>
27+
#include <lwip/timeouts.h>
28+
#include <pico/cyw43_arch.h>
3529

3630
class LWIPMutex {
3731
public:
3832
LWIPMutex() {
39-
noInterrupts();
40-
recursive_mutex_enter_blocking(&__mtxLWIP);
41-
__inLWIP = true;
42-
_ref++;
43-
interrupts();
33+
cyw43_arch_lwip_begin();
4434
}
4535

4636
~LWIPMutex() {
47-
noInterrupts();
48-
if (0 == --_ref) {
49-
__inLWIP = false;
50-
}
51-
recursive_mutex_exit(&__mtxLWIP);
52-
interrupts();
37+
cyw43_arch_lwip_end();
5338
}
54-
55-
private:
56-
static int _ref;
5739
};
58-
int LWIPMutex::_ref = 0;
59-
6040

6141
extern "C" {
6242

@@ -275,10 +255,15 @@ extern "C" {
275255
return __real_udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
276256
}
277257

258+
// sys_check_timeouts is special case because the async process will call it. If we're already in a timeout check, just do a noop
259+
auto_init_mutex(__sys_check_timeouts_mtx);
278260
extern void __real_sys_check_timeouts(void);
279261
void __wrap_sys_check_timeouts(void) {
280-
LWIPMutex m;
281-
__real_sys_check_timeouts();
262+
uint32_t owner;
263+
if (mutex_try_enter(&__sys_check_timeouts_mtx, &owner)) {
264+
__real_sys_check_timeouts();
265+
mutex_exit(&__sys_check_timeouts_mtx);
266+
}
282267
}
283268

284269
extern err_t __real_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg);

0 commit comments

Comments
 (0)