rp2: Integrate CYW43xx WiFi driver.
This includes: - Configuration file for the cyw43-driver. - Integration of cyw43-driver into the build, using lwIP. - Enhancements to machine.Pin to support extension IO pins provided by the CYW43xx. - More mp-hal pin helper functions. - mp_hal_get_mac_ascii MAC address helper function. - Addition of rp2.country() function to set the country code. A board can enable this driver by setting MICROPY_PY_NETWORK_CYW43 in their cmake snippet. Work done in collaboration with Graham Sanderson and Peter Harper. Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
c001cfa603
commit
50e46552c0
@ -16,6 +16,10 @@ endif()
|
||||
|
||||
# Use the local tinyusb instead of the one in pico-sdk
|
||||
set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb)
|
||||
# Use the local cyw43_driver instead of the one in pico-sdk
|
||||
set(PICO_CYW43_DRIVER_PATH ${MICROPY_DIR}/lib/cyw43-driver)
|
||||
# Use the local lwip instead of the one in pico-sdk
|
||||
set(PICO_LWIP_PATH ${MICROPY_DIR}/lib/lwip)
|
||||
|
||||
# Set the location of this port's directory.
|
||||
set(MICROPY_PORT_DIR ${CMAKE_SOURCE_DIR})
|
||||
@ -73,6 +77,7 @@ set(MICROPY_SOURCE_LIB
|
||||
${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c
|
||||
${MICROPY_DIR}/lib/oofatfs/ff.c
|
||||
${MICROPY_DIR}/lib/oofatfs/ffunicode.c
|
||||
${MICROPY_DIR}/shared/netutils/dhcpserver.c
|
||||
${MICROPY_DIR}/shared/netutils/netutils.c
|
||||
${MICROPY_DIR}/shared/netutils/trace.c
|
||||
${MICROPY_DIR}/shared/readline/readline.c
|
||||
@ -216,6 +221,30 @@ if(MICROPY_BLUETOOTH_NIMBLE)
|
||||
list(APPEND MICROPY_INC_CORE ${NIMBLE_INCLUDE})
|
||||
endif()
|
||||
|
||||
if (MICROPY_PY_NETWORK_CYW43)
|
||||
string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/cyw43-driver)
|
||||
|
||||
target_compile_definitions(${MICROPY_TARGET} PRIVATE
|
||||
MICROPY_PY_NETWORK_CYW43=1
|
||||
MICROPY_PY_NETWORK_CYW43_USE_LIB_DRIVER=1
|
||||
MICROPY_PY_SOCKET_DEFAULT_TIMEOUT_MS=30000 # default socket timeout
|
||||
)
|
||||
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
target_compile_definitions(${MICROPY_TARGET} PRIVATE
|
||||
CYW43_USE_STATS=1
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND MICROPY_SOURCE_EXTMOD
|
||||
${MICROPY_DIR}/extmod/network_cyw43.c
|
||||
)
|
||||
|
||||
target_link_libraries(${MICROPY_TARGET}
|
||||
cyw43_driver_picow
|
||||
cmsis_core
|
||||
)
|
||||
endif()
|
||||
|
||||
if (MICROPY_PY_NETWORK_NINAW10)
|
||||
target_compile_definitions(${MICROPY_TARGET} PRIVATE
|
||||
MICROPY_PY_NETWORK_NINAW10=1
|
||||
|
@ -29,9 +29,11 @@ all:
|
||||
clean:
|
||||
$(RM) -rf $(BUILD)
|
||||
|
||||
GIT_SUBMODULES += lib/mbedtls lib/pico-sdk lib/tinyusb
|
||||
GIT_SUBMODULES += lib/mbedtls lib/tinyusb
|
||||
|
||||
submodules:
|
||||
# lib/pico-sdk is required for the cmake build to function (as used for boards other than PICO below)
|
||||
$(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="lib/pico-sdk" submodules
|
||||
ifeq ($(BOARD),PICO)
|
||||
# Run the standard submodules target with minimum required submodules above
|
||||
$(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules
|
||||
|
@ -37,6 +37,13 @@ You can also build the standard CMake way. The final firmware is found in
|
||||
the top-level of the CMake build directory (`build` by default) and is
|
||||
called `firmware.uf2`.
|
||||
|
||||
If you are using a different board other than a Rasoberry Pi Pico, then you should
|
||||
pass the board name to the build; e.g. for Raspberry Pi Pico W:
|
||||
|
||||
$ make BOARD=PICO_W submodules
|
||||
$ make BOARD=PICO_W clean
|
||||
$ make BOARD=PICO_W
|
||||
|
||||
## Deploying firmware to the device
|
||||
|
||||
Firmware can be deployed to the device by putting it into bootloader mode
|
||||
|
98
ports/rp2/cyw43_configport.h
Normal file
98
ports/rp2/cyw43_configport.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022 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_RP2_CYW43_CONFIGPORT_H
|
||||
#define MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H
|
||||
|
||||
// The board-level config will be included here, so it can set some CYW43 values.
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "pendsv.h"
|
||||
|
||||
#define CYW43_IOCTL_TIMEOUT_US (1000000)
|
||||
#define CYW43_SLEEP_MAX (10)
|
||||
#define CYW43_NETUTILS (1)
|
||||
#define CYW43_USE_OTP_MAC (1)
|
||||
|
||||
#define CYW43_EPERM MP_EPERM // Operation not permitted
|
||||
#define CYW43_EIO MP_EIO // I/O error
|
||||
#define CYW43_EINVAL MP_EINVAL // Invalid argument
|
||||
#define CYW43_ETIMEDOUT MP_ETIMEDOUT // Connection timed out
|
||||
|
||||
#define CYW43_THREAD_ENTER MICROPY_PY_LWIP_ENTER
|
||||
#define CYW43_THREAD_EXIT MICROPY_PY_LWIP_EXIT
|
||||
#define CYW43_THREAD_LOCK_CHECK
|
||||
|
||||
#define CYW43_SDPCM_SEND_COMMON_WAIT __WFI();
|
||||
#define CYW43_DO_IOCTL_WAIT __WFI();
|
||||
|
||||
#define CYW43_ARRAY_SIZE(a) MP_ARRAY_SIZE(a)
|
||||
|
||||
#define CYW43_HAL_PIN_MODE_INPUT MP_HAL_PIN_MODE_INPUT
|
||||
#define CYW43_HAL_PIN_MODE_OUTPUT MP_HAL_PIN_MODE_OUTPUT
|
||||
#define CYW43_HAL_PIN_PULL_NONE MP_HAL_PIN_PULL_NONE
|
||||
#define CYW43_HAL_PIN_PULL_UP MP_HAL_PIN_PULL_UP
|
||||
#define CYW43_HAL_PIN_PULL_DOWN MP_HAL_PIN_PULL_DOWN
|
||||
|
||||
#define CYW43_HAL_MAC_WLAN0 MP_HAL_MAC_WLAN0
|
||||
|
||||
// set in SDK board header
|
||||
#define CYW43_NUM_GPIOS CYW43_WL_GPIO_COUNT
|
||||
|
||||
#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook();
|
||||
|
||||
#define cyw43_hal_ticks_us mp_hal_ticks_us
|
||||
#define cyw43_hal_ticks_ms mp_hal_ticks_ms
|
||||
|
||||
#define cyw43_hal_pin_obj_t mp_hal_pin_obj_t
|
||||
#define cyw43_hal_pin_config mp_hal_pin_config
|
||||
#define cyw43_hal_pin_read mp_hal_pin_read
|
||||
#define cyw43_hal_pin_low mp_hal_pin_low
|
||||
#define cyw43_hal_pin_high mp_hal_pin_high
|
||||
|
||||
#define cyw43_hal_get_mac mp_hal_get_mac
|
||||
#define cyw43_hal_get_mac_ascii mp_hal_get_mac_ascii
|
||||
#define cyw43_hal_generate_laa_mac mp_hal_generate_laa_mac
|
||||
|
||||
#define cyw43_schedule_internal_poll_dispatch(func) pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, func)
|
||||
|
||||
void cyw43_post_poll_hook(void);
|
||||
|
||||
static inline void cyw43_delay_us(uint32_t us) {
|
||||
uint32_t start = mp_hal_ticks_us();
|
||||
while (mp_hal_ticks_us() - start < us) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cyw43_delay_ms(uint32_t ms) {
|
||||
uint32_t us = ms * 1000;
|
||||
int32_t start = mp_hal_ticks_us();
|
||||
while (mp_hal_ticks_us() - start < us) {
|
||||
__WFI();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H
|
@ -58,9 +58,18 @@
|
||||
// Open drain behaviour is simulated.
|
||||
#define GPIO_IS_OPEN_DRAIN(id) (machine_pin_open_drain_mask & (1 << (id)))
|
||||
|
||||
#ifndef MICROPY_HW_PIN_RESERVED
|
||||
#define MICROPY_HW_PIN_RESERVED(i) (0)
|
||||
#endif
|
||||
|
||||
typedef struct _machine_pin_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint32_t id;
|
||||
uint8_t id;
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
bool is_cyw43;
|
||||
bool is_output;
|
||||
bool last_output_value;
|
||||
#endif
|
||||
} machine_pin_obj_t;
|
||||
|
||||
typedef struct _machine_pin_irq_obj_t {
|
||||
@ -104,9 +113,60 @@ STATIC const machine_pin_obj_t machine_pin_obj[NUM_BANK0_GPIOS] = {
|
||||
{{&machine_pin_type}, 29},
|
||||
};
|
||||
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
#include "lib/cyw43-driver/src/cyw43.h"
|
||||
#define CYW43_PIN_NAME_PREFIX "WL_GPIO"
|
||||
STATIC machine_pin_obj_t cyw43_pin_obj[MICROPY_HW_PIN_CYW43_COUNT];
|
||||
#endif
|
||||
|
||||
#define LED_PIN_NAME "LED"
|
||||
|
||||
#ifndef MICROPY_HW_PIN_ENABLE_LED_PIN
|
||||
#if defined(MICROPY_HW_PIN_CYW43_LED_PIN_NUM) || defined(PICO_DEFAULT_LED_PIN)
|
||||
#define MICROPY_HW_PIN_ENABLE_LED_PIN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MICROPY_HW_PIN_ENABLE_LED_PIN
|
||||
#ifdef MICROPY_HW_PIN_CYW43_LED_PIN_NUM
|
||||
STATIC machine_pin_obj_t *led_pin_obj = &cyw43_pin_obj[MICROPY_HW_PIN_CYW43_LED_PIN_NUM];
|
||||
#elif defined(MICROPY_HW_PIN_LED_PIN_NUM)
|
||||
STATIC machine_pin_obj_t *led_pin_obj = &machine_pin_obj[MICROPY_HW_PIN_LED_PIN_NUM];
|
||||
#elif defined(PICO_DEFAULT_LED_PIN)
|
||||
STATIC const machine_pin_obj_t *led_pin_obj = &machine_pin_obj[PICO_DEFAULT_LED_PIN];
|
||||
#else
|
||||
#error MICROPY_HW_PIN_ENABLE_LED_PIN defined but there is no LED pin
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Mask with "1" indicating that the corresponding pin is in simulated open-drain mode.
|
||||
uint32_t machine_pin_open_drain_mask;
|
||||
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
STATIC inline bool is_cyw43_pin(__unused const machine_pin_obj_t *self) {
|
||||
return self->is_cyw43;
|
||||
}
|
||||
#else
|
||||
#define is_cyw43_pin(x) false
|
||||
#endif
|
||||
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
STATIC inline void update_cyw43_value(__unused machine_pin_obj_t *self, bool value) {
|
||||
if (value != self->last_output_value || !self->is_output) {
|
||||
cyw43_gpio_set(&cyw43_state, self->id, value);
|
||||
}
|
||||
self->last_output_value = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
STATIC inline bool get_cyw43_value(__unused machine_pin_obj_t *self) {
|
||||
bool value = false;
|
||||
cyw43_gpio_get(&cyw43_state, self->id, &value);
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void gpio_irq(void) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
uint32_t intr = iobank0_hw->intr[i];
|
||||
@ -129,15 +189,24 @@ STATIC void gpio_irq(void) {
|
||||
|
||||
void machine_pin_init(void) {
|
||||
memset(MP_STATE_PORT(machine_pin_irq_obj), 0, sizeof(MP_STATE_PORT(machine_pin_irq_obj)));
|
||||
irq_set_exclusive_handler(IO_IRQ_BANK0, gpio_irq);
|
||||
irq_add_shared_handler(IO_IRQ_BANK0, gpio_irq, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
|
||||
irq_set_enabled(IO_IRQ_BANK0, true);
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
for (uint i = 0; i < count_of(cyw43_pin_obj); i++) {
|
||||
cyw43_pin_obj[i].id = i;
|
||||
cyw43_pin_obj[i].base.type = &machine_pin_type;
|
||||
cyw43_pin_obj[i].is_cyw43 = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void machine_pin_deinit(void) {
|
||||
for (int i = 0; i < NUM_BANK0_GPIOS; ++i) {
|
||||
if (MICROPY_HW_PIN_RESERVED(i)) {
|
||||
continue;
|
||||
}
|
||||
gpio_set_irq_enabled(i, GPIO_IRQ_ALL, false);
|
||||
}
|
||||
irq_set_enabled(IO_IRQ_BANK0, false);
|
||||
irq_remove_handler(IO_IRQ_BANK0, gpio_irq);
|
||||
}
|
||||
|
||||
@ -145,45 +214,112 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
|
||||
machine_pin_obj_t *self = self_in;
|
||||
uint funcsel = GPIO_GET_FUNCSEL(self->id);
|
||||
qstr mode_qst;
|
||||
if (funcsel == GPIO_FUNC_SIO) {
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
mode_qst = MP_QSTR_OPEN_DRAIN;
|
||||
} else if (GPIO_IS_OUT(self->id)) {
|
||||
mode_qst = MP_QSTR_OUT;
|
||||
if (!is_cyw43_pin(self)) {
|
||||
if (funcsel == GPIO_FUNC_SIO) {
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
mode_qst = MP_QSTR_OPEN_DRAIN;
|
||||
} else if (GPIO_IS_OUT(self->id)) {
|
||||
mode_qst = MP_QSTR_OUT;
|
||||
} else {
|
||||
mode_qst = MP_QSTR_IN;
|
||||
}
|
||||
} else {
|
||||
mode_qst = MP_QSTR_IN;
|
||||
mode_qst = MP_QSTR_ALT;
|
||||
}
|
||||
mp_printf(print, "Pin(%u, mode=%q", self->id, mode_qst);
|
||||
bool pull_up = false;
|
||||
if (GPIO_IS_PULL_UP(self->id)) {
|
||||
mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP);
|
||||
pull_up = true;
|
||||
}
|
||||
if (GPIO_IS_PULL_DOWN(self->id)) {
|
||||
if (pull_up) {
|
||||
mp_printf(print, "|%q", MP_QSTR_PULL_DOWN);
|
||||
} else {
|
||||
mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN);
|
||||
}
|
||||
}
|
||||
if (funcsel != GPIO_FUNC_SIO) {
|
||||
mp_printf(print, ", alt=%u", funcsel);
|
||||
}
|
||||
} else {
|
||||
mode_qst = MP_QSTR_ALT;
|
||||
}
|
||||
mp_printf(print, "Pin(%u, mode=%q", self->id, mode_qst);
|
||||
bool pull_up = false;
|
||||
if (GPIO_IS_PULL_UP(self->id)) {
|
||||
mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP);
|
||||
pull_up = true;
|
||||
}
|
||||
if (GPIO_IS_PULL_DOWN(self->id)) {
|
||||
if (pull_up) {
|
||||
mp_printf(print, "|%q", MP_QSTR_PULL_DOWN);
|
||||
} else {
|
||||
mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN);
|
||||
}
|
||||
}
|
||||
if (funcsel != GPIO_FUNC_SIO) {
|
||||
mp_printf(print, ", alt=%u", funcsel);
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
mode_qst = self->is_output ? MP_QSTR_OUT : MP_QSTR_IN;
|
||||
mp_printf(print, "Pin(%s%u, mode=%q", CYW43_PIN_NAME_PREFIX, self->id, mode_qst);
|
||||
#endif
|
||||
}
|
||||
mp_printf(print, ")");
|
||||
}
|
||||
|
||||
enum {
|
||||
ARG_mode, ARG_pull, ARG_value, ARG_alt
|
||||
};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
|
||||
{MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
|
||||
{MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
|
||||
{MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}},
|
||||
};
|
||||
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
// pin.init(mode, pull=None, *, value=None, alt=FUNC_SIO)
|
||||
STATIC mp_obj_t machine_pin_cyw43_obj_init_helper(machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
if (args[ARG_pull].u_obj != mp_const_none) {
|
||||
int pull = mp_obj_get_int(args[ARG_pull].u_obj);
|
||||
if (pull) {
|
||||
mp_raise_ValueError("Pulls are not supported for this pin");
|
||||
}
|
||||
}
|
||||
|
||||
if (args[ARG_alt].u_int != GPIO_FUNC_SIO) {
|
||||
mp_raise_ValueError("Alternate functions are not supported for this pin");
|
||||
}
|
||||
|
||||
int value = -1;
|
||||
if (args[ARG_value].u_obj != mp_const_none) {
|
||||
value = mp_obj_is_true(args[ARG_value].u_obj);
|
||||
}
|
||||
|
||||
if (args[ARG_mode].u_obj != mp_const_none) {
|
||||
mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj);
|
||||
if (mode == GPIO_MODE_IN) {
|
||||
if (self->is_output) {
|
||||
// todo need to disable output
|
||||
}
|
||||
self->is_output = false;
|
||||
} else if (mode == GPIO_MODE_OUT) {
|
||||
if (!self->is_output) {
|
||||
// todo need to enable output
|
||||
// for now we just set the value
|
||||
if (value == -1) {
|
||||
value = self->last_output_value;
|
||||
}
|
||||
self->last_output_value = !self->last_output_value; // defeat shortcircuit
|
||||
update_cyw43_value(self, value);
|
||||
self->is_output = true;
|
||||
}
|
||||
} else {
|
||||
mp_raise_ValueError("only Pin.OUT and Pin.IN are supported for this pin");
|
||||
}
|
||||
}
|
||||
|
||||
if (value != -1) {
|
||||
if (self->is_output) {
|
||||
update_cyw43_value(self, value);
|
||||
} else {
|
||||
// figure if you pass a value to IN it should still remember it (this is what regular GPIO does)
|
||||
self->last_output_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
#endif
|
||||
|
||||
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) {
|
||||
enum { ARG_mode, ARG_pull, ARG_value, ARG_alt };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
|
||||
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
|
||||
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
|
||||
{ MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}},
|
||||
};
|
||||
|
||||
// parse args
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
@ -216,7 +352,6 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
|
||||
pull = mp_obj_get_int(args[ARG_pull].u_obj);
|
||||
}
|
||||
gpio_set_pulls(self->id, pull & GPIO_PULL_UP, pull & GPIO_PULL_DOWN);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
@ -224,21 +359,57 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
|
||||
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) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// get the wanted pin object
|
||||
int wanted_pin = mp_obj_get_int(args[0]);
|
||||
if (!(0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj))) {
|
||||
mp_raise_ValueError("invalid pin");
|
||||
}
|
||||
const machine_pin_obj_t *self = &machine_pin_obj[wanted_pin];
|
||||
|
||||
const machine_pin_obj_t *self = NULL;
|
||||
if (mp_obj_is_str(args[0])) {
|
||||
const char *name = mp_obj_str_get_str(args[0]);
|
||||
#if MICROPY_HW_PIN_ENABLE_LED_PIN
|
||||
if (!strcmp(name, LED_PIN_NAME)) {
|
||||
self = led_pin_obj;
|
||||
}
|
||||
#endif
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
static_assert(MICROPY_HW_PIN_CYW43_COUNT < 10, ""); // makes parsing name easy!
|
||||
if (!self && !strncmp(name, CYW43_PIN_NAME_PREFIX, strlen(CYW43_PIN_NAME_PREFIX)) && strlen(name) == strlen(CYW43_PIN_NAME_PREFIX) + 1) {
|
||||
int num = name[strlen(CYW43_PIN_NAME_PREFIX)] - '0';
|
||||
if (num < MICROPY_HW_PIN_CYW43_COUNT) {
|
||||
self = &cyw43_pin_obj[num];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!self) {
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Unknown named pin \"%s\""), name);
|
||||
}
|
||||
}
|
||||
if (!self) {
|
||||
// get the wanted pin object
|
||||
int wanted_pin = mp_obj_get_int(args[0]);
|
||||
if (!(0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj))) {
|
||||
mp_raise_ValueError("invalid pin");
|
||||
}
|
||||
self = &machine_pin_obj[wanted_pin];
|
||||
}
|
||||
// note we have different init args based on the type of pin. so Pin("LED", Pin.OUT) may not always make sense
|
||||
if (!is_cyw43_pin(self)) {
|
||||
if (n_args > 1 || n_kw > 0) {
|
||||
// pin mode given, so configure this GPIO
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
if (n_args > 1 || n_kw > 0) {
|
||||
// pin mode given, so configure this GPIO
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args);
|
||||
// The regular Pins are const, but the CYW43 pins are mutable.
|
||||
machine_pin_obj_t *mutable_self = (machine_pin_obj_t *)self;
|
||||
machine_pin_cyw43_obj_init_helper(mutable_self, n_args - 1, args + 1, &kw_args);
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
#endif
|
||||
}
|
||||
|
||||
// fast method for getting/setting pin value
|
||||
@ -247,23 +418,39 @@ STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
|
||||
machine_pin_obj_t *self = self_in;
|
||||
if (n_args == 0) {
|
||||
// get pin
|
||||
return MP_OBJ_NEW_SMALL_INT(gpio_get(self->id));
|
||||
if (!is_cyw43_pin(self)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(gpio_get(self->id));
|
||||
}
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
return MP_OBJ_NEW_SMALL_INT(get_cyw43_value(self));
|
||||
#endif
|
||||
} else {
|
||||
// set pin
|
||||
bool value = mp_obj_is_true(args[0]);
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
MP_STATIC_ASSERT(GPIO_IN == 0 && GPIO_OUT == 1);
|
||||
gpio_set_dir(self->id, 1 - value);
|
||||
} else {
|
||||
gpio_put(self->id, value);
|
||||
if (!is_cyw43_pin(self)) {
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
MP_STATIC_ASSERT(GPIO_IN == 0 && GPIO_OUT == 1);
|
||||
gpio_set_dir(self->id, 1 - value);
|
||||
} else {
|
||||
gpio_put(self->id, value);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
return mp_const_none;
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
update_cyw43_value(self, value);
|
||||
#endif
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// pin.init(mode, pull)
|
||||
STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
if (!is_cyw43_pin(args[0])) {
|
||||
return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
}
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
return machine_pin_cyw43_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
#endif
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
|
||||
|
||||
@ -276,40 +463,59 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_
|
||||
// pin.low()
|
||||
STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) {
|
||||
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
gpio_set_dir(self->id, GPIO_OUT);
|
||||
} else {
|
||||
gpio_clr_mask(1u << self->id);
|
||||
if (!is_cyw43_pin(self)) {
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
gpio_set_dir(self->id, GPIO_OUT);
|
||||
} else {
|
||||
gpio_clr_mask(1u << self->id);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
update_cyw43_value(self, 0);
|
||||
return mp_const_none;
|
||||
#endif
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low);
|
||||
|
||||
// pin.high()
|
||||
STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
|
||||
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
gpio_set_dir(self->id, GPIO_IN);
|
||||
} else {
|
||||
gpio_set_mask(1u << self->id);
|
||||
if (!is_cyw43_pin(self)) {
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
gpio_set_dir(self->id, GPIO_IN);
|
||||
} else {
|
||||
gpio_set_mask(1u << self->id);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
update_cyw43_value(self, 1);
|
||||
return mp_const_none;
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
|
||||
|
||||
// pin.toggle()
|
||||
STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
|
||||
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
if (GPIO_IS_OUT(self->id)) {
|
||||
gpio_set_dir(self->id, GPIO_IN);
|
||||
if (!is_cyw43_pin(self)) {
|
||||
if (GPIO_IS_OPEN_DRAIN(self->id)) {
|
||||
if (GPIO_IS_OUT(self->id)) {
|
||||
gpio_set_dir(self->id, GPIO_IN);
|
||||
} else {
|
||||
gpio_set_dir(self->id, GPIO_OUT);
|
||||
}
|
||||
} else {
|
||||
gpio_set_dir(self->id, GPIO_OUT);
|
||||
gpio_xor_mask(1u << self->id);
|
||||
}
|
||||
} else {
|
||||
gpio_xor_mask(1u << self->id);
|
||||
return mp_const_none;
|
||||
}
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
update_cyw43_value(self, self->last_output_value ^ 1);
|
||||
return mp_const_none;
|
||||
#endif
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle);
|
||||
|
||||
@ -357,6 +563,10 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
|
||||
};
|
||||
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
if (is_cyw43_pin(self)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin"));
|
||||
}
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
@ -400,16 +610,31 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i
|
||||
(void)errcode;
|
||||
machine_pin_obj_t *self = self_in;
|
||||
|
||||
if (!is_cyw43_pin(self)) {
|
||||
switch (request) {
|
||||
case MP_PIN_READ: {
|
||||
return gpio_get(self->id);
|
||||
}
|
||||
case MP_PIN_WRITE: {
|
||||
gpio_put(self->id, arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if MICROPY_HW_PIN_CYW43_COUNT
|
||||
switch (request) {
|
||||
case MP_PIN_READ: {
|
||||
return gpio_get(self->id);
|
||||
return get_cyw43_value(self);
|
||||
}
|
||||
case MP_PIN_WRITE: {
|
||||
gpio_put(self->id, arg);
|
||||
update_cyw43_value(self, arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC const mp_pin_p_t pin_pin_p = {
|
||||
@ -457,5 +682,8 @@ mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin"));
|
||||
}
|
||||
machine_pin_obj_t *pin = MP_OBJ_TO_PTR(obj);
|
||||
if (is_cyw43_pin(pin)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin"));
|
||||
}
|
||||
return pin->id;
|
||||
}
|
||||
|
@ -46,12 +46,16 @@
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "pico/unique_id.h"
|
||||
#include "hardware/rtc.h"
|
||||
#include "hardware/structs/rosc.h"
|
||||
#if MICROPY_PY_LWIP
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/apps/mdns.h"
|
||||
#endif
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
#include "lib/cyw43-driver/src/cyw43.h"
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_GC_HEAP_SIZE
|
||||
#if MICROPY_PY_LWIP
|
||||
@ -90,6 +94,10 @@ int main(int argc, char **argv) {
|
||||
mp_thread_init();
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
stdio_init_all();
|
||||
#endif
|
||||
|
||||
// Start and initialise the RTC
|
||||
datetime_t t = {
|
||||
.year = 2021,
|
||||
@ -118,6 +126,27 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
{
|
||||
cyw43_init(&cyw43_state);
|
||||
cyw43_irq_init();
|
||||
cyw43_post_poll_hook(); // enable the irq
|
||||
uint8_t buf[8];
|
||||
memcpy(&buf[0], "PICO", 4);
|
||||
|
||||
// MAC isn't loaded from OTP yet, so use unique id to generate the default AP ssid.
|
||||
const char hexchr[16] = "0123456789ABCDEF";
|
||||
pico_unique_board_id_t pid;
|
||||
pico_get_unique_board_id(&pid);
|
||||
buf[4] = hexchr[pid.id[7] >> 4];
|
||||
buf[5] = hexchr[pid.id[6] & 0xf];
|
||||
buf[6] = hexchr[pid.id[5] >> 4];
|
||||
buf[7] = hexchr[pid.id[4] & 0xf];
|
||||
cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf);
|
||||
cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"picoW123");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
|
||||
// Initialise MicroPython runtime.
|
||||
|
@ -28,6 +28,28 @@
|
||||
#include "drivers/dht/dht.h"
|
||||
#include "modrp2.h"
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
#include "lib/cyw43-driver/src/cyw43_country.h"
|
||||
|
||||
extern uint32_t cyw43_country_code;
|
||||
|
||||
STATIC mp_obj_t rp2_country(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
char code[2] = {cyw43_country_code, cyw43_country_code >> 8};
|
||||
return mp_obj_new_str(code, 2);
|
||||
} else {
|
||||
size_t len;
|
||||
const char *str = mp_obj_str_get_data(args[0], &len);
|
||||
if (len != 2) {
|
||||
mp_raise_ValueError(NULL);
|
||||
}
|
||||
cyw43_country_code = CYW43_COUNTRY(str[0], str[1], 0);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_country_obj, 0, 1, rp2_country);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t rp2_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rp2) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&rp2_flash_type) },
|
||||
@ -35,6 +57,10 @@ STATIC const mp_rom_map_elem_t rp2_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_StateMachine), MP_ROM_PTR(&rp2_state_machine_type) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
{ MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&rp2_country_obj) },
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(rp2_module_globals, rp2_module_globals_table);
|
||||
|
||||
|
@ -154,6 +154,20 @@ struct _mp_bluetooth_nimble_malloc_t;
|
||||
#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
extern const struct _mp_obj_type_t mp_network_cyw43_type;
|
||||
#define MICROPY_HW_NIC_CYW43 \
|
||||
{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(CYW43_LINK_DOWN) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(CYW43_LINK_JOIN) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(CYW43_LINK_BADAUTH) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(CYW43_LINK_NONET) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(CYW43_LINK_FAIL) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(CYW43_LINK_UP) },
|
||||
#else
|
||||
#define MICROPY_HW_NIC_CYW43
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_NETWORK_NINAW10
|
||||
// This Network interface requires the extended socket state.
|
||||
#ifndef MICROPY_PY_USOCKET_EXTENDED_STATE
|
||||
@ -184,6 +198,7 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k;
|
||||
#endif
|
||||
|
||||
#define MICROPY_PORT_NETWORK_INTERFACES \
|
||||
MICROPY_HW_NIC_CYW43 \
|
||||
MICROPY_HW_NIC_NINAW10 \
|
||||
MICROPY_HW_NIC_WIZNET5K \
|
||||
MICROPY_BOARD_NETWORK_INTERFACES \
|
||||
@ -258,3 +273,10 @@ typedef intptr_t mp_off_t;
|
||||
extern uint32_t rosc_random_u32(void);
|
||||
extern void lwip_lock_acquire(void);
|
||||
extern void lwip_lock_release(void);
|
||||
|
||||
extern uint32_t cyw43_country_code;
|
||||
extern void cyw43_irq_init(void);
|
||||
extern void cyw43_post_poll_hook(void);
|
||||
|
||||
#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook();
|
||||
#define MICROPY_CYW43_COUNTRY cyw43_country_code
|
||||
|
@ -35,6 +35,10 @@
|
||||
#include "hardware/rtc.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
#include "lib/cyw43-driver/src/cyw43.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_ENABLE_USBDEV
|
||||
|
||||
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
|
||||
@ -168,6 +172,9 @@ uint64_t mp_hal_time_ns(void) {
|
||||
|
||||
// Generate a random locally administered MAC address (LAA)
|
||||
void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) {
|
||||
#ifndef NDEBUG
|
||||
printf("Warning: No MAC in OTP, generating MAC from board id\n");
|
||||
#endif
|
||||
pico_unique_board_id_t pid;
|
||||
pico_get_unique_board_id(&pid);
|
||||
buf[0] = 0x02; // LAA range
|
||||
@ -180,5 +187,21 @@ void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) {
|
||||
|
||||
// A board can override this if needed
|
||||
MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) {
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
// The mac should come from cyw43 otp when CYW43_USE_OTP_MAC is defined
|
||||
// This is loaded into the state after the driver is initialised
|
||||
// cyw43_hal_generate_laa_mac is only called by the driver to generate a mac if otp is not set
|
||||
memcpy(buf, cyw43_state.mac, 6);
|
||||
#else
|
||||
mp_hal_generate_laa_mac(idx, buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) {
|
||||
static const char hexchr[16] = "0123456789ABCDEF";
|
||||
uint8_t mac[6];
|
||||
mp_hal_get_mac(idx, mac);
|
||||
for (; chr_len; ++chr_off, --chr_len) {
|
||||
*dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf];
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "pico/time.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/structs/systick.h"
|
||||
#include "RP2040.h" // cmsis, for __WFI
|
||||
|
||||
#define SYSTICK_MAX (0xffffff)
|
||||
|
||||
@ -74,6 +75,11 @@ static inline mp_uint_t mp_hal_get_cpu_freq(void) {
|
||||
|
||||
#define MP_HAL_PIN_FMT "%u"
|
||||
#define mp_hal_pin_obj_t uint
|
||||
#define MP_HAL_PIN_MODE_INPUT (GPIO_IN)
|
||||
#define MP_HAL_PIN_MODE_OUTPUT (GPIO_OUT)
|
||||
#define MP_HAL_PIN_PULL_NONE (0)
|
||||
#define MP_HAL_PIN_PULL_UP (1)
|
||||
#define MP_HAL_PIN_PULL_DOWN (2)
|
||||
|
||||
extern uint32_t machine_pin_open_drain_mask;
|
||||
|
||||
@ -102,6 +108,12 @@ static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
|
||||
machine_pin_open_drain_mask |= 1 << pin;
|
||||
}
|
||||
|
||||
static inline void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt) {
|
||||
assert((mode == MP_HAL_PIN_MODE_INPUT || mode == MP_HAL_PIN_MODE_OUTPUT) && alt == 0);
|
||||
gpio_set_dir(pin, mode);
|
||||
gpio_set_pulls(pin, pull == MP_HAL_PIN_PULL_UP, pull == MP_HAL_PIN_PULL_DOWN);
|
||||
}
|
||||
|
||||
static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) {
|
||||
return gpio_get(pin);
|
||||
}
|
||||
@ -143,6 +155,7 @@ enum {
|
||||
};
|
||||
|
||||
void mp_hal_get_mac(int idx, uint8_t buf[6]);
|
||||
void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest);
|
||||
void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]);
|
||||
|
||||
#endif // MICROPY_INCLUDED_RP2_MPHALPORT_H
|
||||
|
@ -38,6 +38,41 @@
|
||||
|
||||
static alarm_id_t lwip_alarm_id = -1;
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
#include "lib/cyw43-driver/src/cyw43.h"
|
||||
#include "lib/cyw43-driver/src/cyw43_country.h"
|
||||
#include "lib/cyw43-driver/src/cyw43_stats.h"
|
||||
#include "hardware/irq.h"
|
||||
|
||||
#define CYW43_IRQ_LEVEL GPIO_IRQ_LEVEL_HIGH
|
||||
#define CYW43_SHARED_IRQ_HANDLER_PRIORITY PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY
|
||||
|
||||
uint32_t cyw43_country_code = CYW43_COUNTRY_WORLDWIDE;
|
||||
|
||||
static void gpio_irq_handler(void) {
|
||||
uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE);
|
||||
if (events & CYW43_IRQ_LEVEL) {
|
||||
// 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, CYW43_IRQ_LEVEL, false);
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll);
|
||||
CYW43_STAT_INC(IRQ_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
void cyw43_irq_init(void) {
|
||||
gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_SHARED_IRQ_HANDLER_PRIORITY);
|
||||
irq_set_enabled(IO_IRQ_BANK0, true);
|
||||
NVIC_SetPriority(PendSV_IRQn, PICO_LOWEST_IRQ_PRIORITY);
|
||||
}
|
||||
|
||||
void cyw43_post_poll_hook(void) {
|
||||
gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||
void wiznet5k_poll(void);
|
||||
void wiznet5k_deinit(void);
|
||||
|
@ -28,6 +28,10 @@
|
||||
#include "pendsv.h"
|
||||
#include "RP2040.h"
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
#include "lib/cyw43-driver/src/cyw43_stats.h"
|
||||
#endif
|
||||
|
||||
static pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS];
|
||||
static int pendsv_lock;
|
||||
|
||||
@ -54,12 +58,21 @@ void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
|
||||
pendsv_dispatch_table[slot] = f;
|
||||
if (pendsv_lock == 0) {
|
||||
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
||||
} else {
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// PendSV interrupt handler to perform background processing.
|
||||
void PendSV_Handler(void) {
|
||||
assert(pendsv_lock == 0);
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
CYW43_STAT_INC(PENDSV_RUN_COUNT);
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) {
|
||||
if (pendsv_dispatch_table[i] != NULL) {
|
||||
pendsv_dispatch_t f = pendsv_dispatch_table[i];
|
||||
|
@ -32,6 +32,9 @@ enum {
|
||||
#if MICROPY_PY_LWIP
|
||||
PENDSV_DISPATCH_LWIP,
|
||||
#endif
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
PENDSV_DISPATCH_CYW43,
|
||||
#endif
|
||||
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||
PENDSV_DISPATCH_WIZNET,
|
||||
#endif
|
||||
|
@ -103,8 +103,13 @@ STATIC void pio1_irq0(void) {
|
||||
|
||||
void rp2_pio_init(void) {
|
||||
// Reset all PIO instruction memory.
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
// TODO: cannot reset PIO memory when CYW43 driver is enabled and active
|
||||
// because it uses a PIO for the bus interface.
|
||||
#else
|
||||
pio_clear_instruction_memory(pio0);
|
||||
pio_clear_instruction_memory(pio1);
|
||||
#endif
|
||||
|
||||
// Set up interrupts.
|
||||
memset(MP_STATE_PORT(rp2_pio_irq_obj), 0, sizeof(MP_STATE_PORT(rp2_pio_irq_obj)));
|
||||
|
Loading…
Reference in New Issue
Block a user