8000 rp2: Dynamic cyw43 config. · peterharperuk/micropython@2172c8f · GitHub
[go: up one dir, main page]

Skip to content

Commit 2172c8f

Browse files
committed
rp2: Dynamic cyw43 config.
Allow cyw43 pins and clock to be configured at runtime. Move cyw43 init code from main. e.g. wlan = network.WLAN(network.STA_IF, pin_on=2, pin_cs=3, pin_dat=4, pin_clock=5, div_int=3) ble = bluetooth.BLE(pin_on=2, pin_cs=3, pin_dat=4, pin_clock=5, div_int=3) ext_led = Pin('WL_GPIO0', Pin.OUT, pin_on=2, pin_cs=3, pin_dat=4, pin_clock=5, div_int=3) Signed-off-by: Peter Harper <peter.harper@raspberrypi.com>
1 parent d82809b commit 2172c8f

File tree

8 files changed

+233
-42
lines changed

8 files changed

+233
-42
lines changed

extmod/modbluetooth.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,24 @@ MP_DEFINE_CONST_OBJ_TYPE(
257257
// Bluetooth object: General
258258
// ----------------------------------------------------------------------------
259259

260+
// Allow the port to add extra parameters
261+
#ifdef MICROPY_PY_BLUETOOTH_OBJ_INIT_ARGS
262+
#define EXTRA_ARGS MICROPY_PY_BLUETOOTH_OBJ_INIT_ARGS
263+
#else
264+
#define EXTRA_ARGS
265+
#endif
266+
267+
MP_WEAK void bluetooth_ble_obj_init(mp_arg_val_t *args) {
268+
}
269+
260270
static mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
261-
(void)type;
262-
(void)n_args;
263-
(void)n_kw;
264-
(void)all_args;
271+
const mp_arg_t allowed_args[] = {
272+
EXTRA_ARGS
273+
};
274+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
275+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
276+
bluetooth_ble_obj_init(args);
277+
265278
if (MP_STATE_VM(bluetooth) == MP_OBJ_NULL) {
266279
mp_obj_bluetooth_ble_t *o = m_new0(mp_obj_bluetooth_ble_t, 1);
267280
o->base.type = &mp_type_bluetooth_ble;

extmod/network_cyw43.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,35 @@ static void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
9393
);
9494
}
9595

96-
static mp_obj_t network_cyw43_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
97-
mp_arg_check_num(n_args, n_kw, 0, 1, false);
98-
if (n_args == 0 || mp_obj_get_int(args[0]) == MOD_NETWORK_STA_IF) {
96+
// Allow the port to add extra parameters
97+
#ifdef MICROPY_PY_NETWORK_CYW43_OBJ_INIT_ARGS
98+
#define EXTRA_ARGS MICROPY_PY_NETWORK_CYW43_OBJ_INIT_ARGS
99+
#else
100+
#define EXTRA_ARGS
101+
#endif
102+
103+
MP_WEAK void network_cyw43_obj_init(mp_arg_val_t *args) {
104+
}
105+
106+
static mp_obj_t network_cyw43_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
107+
enum { ARG_interface, ARG_last };
108+
const mp_arg_t allowed_args[] = {
109+
{ MP_QSTR_interface, MP_ARG_INT, {.u_int = MOD_NETWORK_STA_IF} },
110+
EXTRA_ARGS
111+
};
112+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
113+
mp_map_t kw_args;
114+
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
115+
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
116+
117+
network_cyw43_obj_init(args + ARG_last);
118+
if (args[ARG_interface].u_int == MOD_NETWORK_STA_IF) {
99119
return MP_OBJ_FROM_PTR(&network_cyw43_wl_sta);
100120
} else {
101121
return MP_OBJ_FROM_PTR(&network_cyw43_wl_ap);
102122
}
103123
}
124+
#undef EXTRA_ARGS
104125

105126
static mp_obj_t network_cyw43_send_ethernet(mp_obj_t self_in, mp_obj_t buf_in) {
106127
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);

ports/rp2/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ set(MICROPY_SOURCE_QSTR
195195
${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c
196196
)
197197

198+
if (MICROPY_PY_NETWORK_CYW43)
199+
list(APPEND MICROPY_SOURCE_QSTR
200+
${MICROPY_PORT_DIR}/rp2_init_cyw43.c
201+
)
202+
endif()
203+
198204
set(PICO_SDK_COMPONENTS
199205
boot_bootrom_headers
200206
hardware_adc
@@ -403,6 +409,7 @@ if (MICROPY_PY_NETWORK_CYW43)
403409

404410
list(APPEND MICROPY_SOURCE_PORT
405411
machine_pin_cyw43.c
412+
rp2_init_cyw43.c
406413
)
407414

408415
target_link_libraries(${MICROPY_TARGET}

ports/rp2/machine_pin.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -242,17 +242,25 @@ static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
242242
mp_printf(print, ")");
243243
}
244244

245-
enum {
246-
ARG_mode, ARG_pull, ARG_value, ARG_alt
247-
};
248-
static const mp_arg_t allowed_args[] = {
249-
{MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
250-
{MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
251-
{MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
252-
{MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}},
253-
};
245+
// Allow the port to add extra parameters
246+
#ifdef MICROPY_HW_PIN_EXT_OBJ_INIT_ARGS
247+
#define EXTRA_ARGS MICROPY_HW_PIN_EXT_OBJ_INIT_ARGS
248+
#else
249+
#define EXTRA_ARGS
250+
#endif
251+
252+
MP_WEAK void machine_pin_ext_obj_init(mp_arg_val_t *args) {
253+
}
254254

255255
static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
256+
enum { ARG_mode, ARG_pull, ARG_value, ARG_alt, ARG_last };
257+
const mp_arg_t allowed_args[] = {
258+
{MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
259+
{MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
260+
{MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
261+
{MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}},
262+
EXTRA_ARGS
263+
};
256264

257265
// parse args
258266
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -277,6 +285,10 @@ static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
277285
mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj);
278286
if (is_ext_pin(self)) {
279287
#if MICROPY_HW_PIN_EXT_COUNT
288+
289+
// called in case the port needs some initialisation before using an external pin
290+
machine_pin_ext_obj_init(args + ARG_last);
291+
280292
// The regular Pins are const, but the external pins are mutable.
281293
machine_pin_obj_t *mutable_self = (machine_pin_obj_t *)self;
282294
machine_pin_ext_config(mutable_self, mode, value);
@@ -312,6 +324,7 @@ static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
312324
}
313325
return mp_const_none;
314326
}
327+
#undef EXTRA_ARGS
315328

316329
// constructor(id, ...)
317330
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {

ports/rp2/main.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,11 @@
4949

5050
#include "pico/stdlib.h"
5151
#include "pico/binary_info.h"
52-
#include "pico/unique_id.h"
5352
#include "hardware/structs/rosc.h"
5453
#if MICROPY_PY_LWIP
5554
#include "lwip/init.h"
5655
#include "lwip/apps/mdns.h"
5756
#endif
58-
#if MICROPY_PY_NETWORK_CYW43
59-
#include "lib/cyw43-driver/src/cyw43.h"
60-
#endif
6157
#if PICO_RP2040
6258
#include "RP2040.h" // cmsis, for PendSV_IRQn and SCB/SCB_SCR_SEVONPEND_Msk
6359
#elif PICO_RP2350 && PICO_ARM
@@ -132,28 +128,6 @@ int main(int argc, char **argv) {
132128
#endif
133129
#endif
134130

135-
#if MICROPY_PY_NETWORK_CYW43 || MICROPY_PY_BLUETOOTH_CYW43
136-
{
137-
cyw43_init(&cyw43_state);
138-
cyw43_irq_init();
139-
cyw43_post_poll_hook(); // enable the irq
140-
uint8_t buf[8];
141-
memcpy(&buf[0], "PICO", 4);
142-
143-
// MAC isn't loaded from OTP yet, so use unique id to generate the default AP ssid.
144-
const char hexchr[16] = "0123456789ABCDEF";
145-
pico_unique_board_id_t pid;
146-
pico_get_unique_board_id(&pid);
147-
buf[4] = hexchr[pid.id[7] >> 4];
148-
buf[5] = hexchr[pid.id[6] & 0xf];
149-
buf[6] = hexchr[pid.id[5] >> 4];
150-
buf[7] = hexchr[pid.id[4] & 0xf];
151-
cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf);
152-
cyw43_wifi_ap_set_auth(&cyw43_state, CYW43_AUTH_WPA2_AES_PSK);
153-
cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"picoW123");
154-
}
155-
#endif
156-
157131
// Hook for setting up anything that can wait until after other hardware features are initialised.
158132
MICROPY_BOARD_EARLY_INIT();
159133

ports/rp2/mpconfigport.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,40 @@ extern void lwip_lock_release(void);
316316
#ifndef MICROPY_BOARD_END_SOFT_RESET
317317
#define MICROPY_BOARD_END_SOFT_RESET()
318318
#endif
319+
320+
#if MICROPY_PY_NETWORK_CYW43
321+
// Array of allowed arguments needed to initialise cyw43 pins
322+
#if CYW43_PIN_WL_DYNAMIC
323+
#define CYW43_INIT_PINS_ALLOWED_ARGS \
324+
{ MP_QSTR_pin_on, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, \
325+
{ MP_QSTR_pin_out, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, \
326+
{ MP_QSTR_pin_in, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, \
327+
{ MP_QSTR_pin_wake, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, \
328+
{ MP_QSTR_pin_clock, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, \
329+
{ MP_QSTR_pin_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, \
330+
{ MP_QSTR_pin_dat, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
331+
#else
332+
#define CYW43_INIT_PINS_ALLOWED_ARGS
333+
#endif // CYW43_PIN_WL_DYNAMIC
334+
335+
// Array of allowed arguments needed to initialise cyw43 pio clock
336+
#if CYW43_PIO_CLOCK_DIV_DYNAMIC
337+
#define CYW43_INIT_CLOCK_ALLOWED_ARGS \
338+
{ MP_QSTR_div_int, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, \
339+
{ MP_QSTR_div_frac, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } },
340+
#else
341+
#define CYW43_INIT_CLOCK_ALLOWED_ARGS
342+
#endif // CYW43_PIO_CLOCK_DIV_DYNAMIC
343+
344+
// Array of allowed arguments needed to initialise cyw43
345+
#define MICROPY_HW_PIN_EXT_OBJ_INIT_ARGS \
346+
CYW43_INIT_PINS_ALLOWED_ARGS \
347+
CYW43_INIT_CLOCK_ALLOWED_ARGS
348+
#define MICROPY_PY_NETWORK_CYW43_OBJ_INIT_ARGS \
349+
CYW43_INIT_PINS_ALLOWED_ARGS \
350+
CYW43_INIT_CLOCK_ALLOWED_ARGS
351+
#define MICROPY_PY_BLUETOOTH_OBJ_INIT_ARGS \
352+
CYW43_INIT_PINS_ALLOWED_ARGS \
353+
CYW43_INIT_CLOCK_ALLOWED_ARGS
354+
355+
#endif // MICROPY_PY_NETWORK_CYW43

ports/rp2/mpnetworkport.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ void cyw43_irq_init(void) {
8181
#endif
8282
}
8383

84+
void cyw43_irq_deinit(void) {
85+
gpio_remove_raw_irq_handler(CYW43_PIN_WL_HOST_WAKE, gpio_irq_handler);
86+
}
87+
8488
void cyw43_post_poll_hook(void) {
8589
cyw43_has_pending = 0;
8690
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, true);

ports/rp2/rp2_init_cyw43.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#include "py/runtime.h"
2+
#include "extmod/network_cyw43.h"
3+
#include "extmod/modnetwork.h"
4+
#include "lib/cyw43-driver/src/cyw43.h"
5+
#include "pico/unique_id.h"
6+
7+
void cyw43_irq_deinit(void);
8+
void cyw43_irq_init(void);
9+
10+
#if CYW43_PIN_WL_DYNAMIC
11+
// Defined in cyw43_bus_pio_spi.c
12+
int cyw43_set_pins_wl(uint pins[CYW43_PIN_INDEX_WL_COUNT]);
13+
#endif
14+
15+
#if CYW43_PIO_CLOCK_DIV_DYNAMIC
16+
// Defined in cyw43_bus_pio_spi.c
17+
void cyw43_set_pio_clkdiv_int_frac8(uint32_t clock_div_int, uint8_t clock_div_frac8);
18+
#endif
19+
20+
// enums for the arguments needed to initialise cyw43
21+
#define CYW43_INIT_ARG_ENUM \
22+
ARG_pin_on, ARG_pin_out, ARG_pin_in, ARG_pin_wake, ARG_pin_clock, ARG_pin_cs, ARG_pin_dat, ARG_div_int, ARG_div_frac
23+
24+
// Builds an array of pins needed by cyw43_set_pins_wl from function arguments
25+
// order defined by cyw43_pin_index_t
26+
#if CYW43_PIN_WL_DYNAMIC
27+
#define SET_CYW43_PIN_ARG(ARG_ENUM, DEFAULT) args[ARG_ENUM].u_obj != MP_OBJ_NULL ? mp_hal_get_pin_obj(args[ARG_ENUM].u_obj) : (DEFAULT)
28+
#define CYW43_PIN_ARRAY \
29+
SET_CYW43_PIN_ARG(ARG_pin_on, NUM_BANK0_GPIOS), \
30+
SET_CYW43_PIN_ARG(ARG_pin_out, SET_CYW43_PIN_ARG(ARG_pin_dat, NUM_BANK0_GPIOS)), \
31+
SET_CYW43_PIN_ARG(ARG_pin_in, SET_CYW43_PIN_ARG(ARG_pin_dat, NUM_BANK0_GPIOS)), \
32+
SET_CYW43_PIN_ARG(ARG_pin_wake, SET_CYW43_PIN_ARG(ARG_pin_dat, NUM_BANK0_GPIOS)), \
33+
SET_CYW43_PIN_ARG(ARG_pin_clock, NUM_BANK0_GPIOS), \
34+
SET_CYW43_PIN_ARG(ARG_pin_cs, NUM_BANK0_GPIOS),
35+
#else
36+
#define CYW43_PIN_ARRAY 0
37+
#endif
38+
39+
static void rp2_cyw43_init(uint *pins, uint32_t clock_div_int, uint8_t clock_div_frac8) {
40+
static bool cyw43_init_done;
41+
if (!cyw43_init_done) {
42+
cyw43_init(&cyw43_state);
43+
cyw43_irq_init();
44+
cyw43_post_poll_hook(); // enable the irq
45+
cyw43_init_done = true;
46+
uint8_t buf[8];
47+
memcpy(&buf[0], "PICO", 4);
48+
49+
// Use unique id to generate the default AP ssid.
50+
const char hexchr[16] = "0123456789ABCDEF";
51+
pico_unique_board_id_t pid;
52+
pico_get_unique_board_id(&pid);
53+
buf[4] = hexchr[pid.id[7] >> 4];
54+
buf[5] = hexchr[pid.id[6] & 0xf];
55+
buf[6] = hexchr[pid.id[5] >> 4];
56+
buf[7] = hexchr[pid.id[4] & 0xf];
57+
cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf);
58+
cyw43_wifi_ap_set_auth(&cyw43_state, CYW43_AUTH_WPA2_AES_PSK);
59+
cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"picoW123");
60+
}
61+
62+
#if CYW43_PIN_WL_DYNAMIC
63+
assert(pins);
64+
// Set unspecified pins
65+
for (int i = 0; i < CYW43_PIN_INDEX_WL_COUNT; i++) {
66+
if (pins[i] == NUM_BANK0_GPIOS) {
67+
pins[i] = cyw43_get_pin_wl(i);
68+
}
69+
}
70+
// check if the pins have actually changed
71+
for (int i = 0; i < CYW43_PIN_INDEX_WL_COUNT; i++) {
72+
if (pins[i] != cyw43_get_pin_wl(i)) {
73+
// re-initialise cyw43. This can fail if the pins are invalid (gpio base is incompatible) or the pio is in use
74+
int error = cyw43_set_pins_wl(pins);
75+
if (error == PICO_ERROR_RESOURCE_IN_USE) {
76+
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("wifi in use"));
77+
} else if (error != PICO_OK) {
78+
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("wifi pins invalid"));
79+
}
80+
cyw43_irq_deinit();
81+
cyw43_irq_init();
82+
break;
83+
}
84+
}
85+
#endif // CYW43_PIN_WL_DYNAMIC
86+
#if CYW43_PIO_CLOCK_DIV_DYNAMIC
87+
// set the pio clock divisor - has no effect if the pio is in use
88+
if (clock_div_int > 0) {
89+
cyw43_set_pio_clkdiv_int_frac8(clock_div_int, clock_div_frac8);
90+
}
91+
#endif // CYW43_PIO_CLOCK_DIV_DYNAMIC
92+
}
93+
94+
static void cyw43_obj_init(mp_arg_val_t *args) {
95+
assert(args);
96+
enum { CYW43_INIT_ARG_ENUM };
97+
uint pins[] = {
98+
CYW43_PIN_ARRAY
99+
};
100+
101+
uint32_t clock_div_int = 0;
102+
uint8_t clock_div_frac8 = 0;
103+
#if CYW43_PIO_CLOCK_DIV_DYNAMIC
104+
clock_div_int = args[ARG_div_int].u_int;
105+
clock_div_frac8 = (uint8_t)args[ARG_div_frac].u_int;
106+
#endif
107+
108+
rp2_cyw43_init(pins, clock_div_int, clock_div_frac8);
109+
}
110+
111+
void network_cyw43_obj_init(mp_arg_val_t *args) {
112+
cyw43_obj_init(args);
113+
}
114+
115+
void bluetooth_ble_obj_init(mp_arg_val_t *args) {
116+
cyw43_obj_init(args);
117+
}
118+
119+
// perform extra initialisation in machine_pin_obj_init_helper
120+
void machine_pin_ext_obj_init(mp_arg_val_t *args) {
121+
cyw43_obj_init(args);
122+
}

0 commit comments

Comments
 (0)
0