8000 Pico W: implement more things by jepler · Pull Request #6960 · adafruit/circuitpython · GitHub
[go: up one dir, main page]

Skip to content

Pico W: implement more things #6960

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ def autoapi_prepare_jinja_env(jinja_env):
"ports/nrf/peripherals",
"ports/nrf/usb",
"ports/raspberrypi/sdk",
"ports/raspberrypi/lib",
"ports/stm/st_driver",
"ports/stm/packages",
"ports/stm/peripherals",
Expand Down
17 changes: 1 addition & 16 deletions
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ INC_CYW43 := \
-isystem sdk/src/rp2_common/pico_cyw43_arch/include/ \
-isystem sdk/src/rp2_common/pico_lwip/include/ \

CFLAGS_CYW43 := -DCYW43_LWIP=1 -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_USE_SPI -DIGNORE_GPIO25 -DCYW43_LOGIC_DEBUG=0
CFLAGS_CYW43 := -DCYW43_LWIP=1 -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_USE_SPI -DIGNORE_GPIO25 -DIGNORE_GPIO23 -DCYW43_LOGIC_DEBUG=0
SRC_SDK_CYW43 := \
src/common/pico_sync/sem.c \
src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.c \
Expand Down Expand Up @@ -110,21 +110,6 @@ $(BUILD)/cyw43_resource.o: lib/cyw43-driver/firmware/$(CYW43_FIRMWARE_BIN)
--redefine-sym _binary_lib_cyw43_driver_firmware_43439A0_7_95_49_00_combined_end=fw_43439A0_7_95_49_00_end \
$< $@
OBJ_CYW43 := $(BUILD)/cyw43_resource.o
# need to do the equivalent of this in cmake
### # cyw43_resource.o contains the WiFi and BT firmware as a binary blob
### add_custom_command(
### OUTPUT ${CYW43_FIRMWARE_OBJ}
### DEPENDS ${PICO_CYW43_DRIVER_PATH}/firmware/${CYW43_FIRMWARE_BIN}
### WORKING_DIRECTORY ${PICO_CYW43_DRIVER_PATH}/firmware
### COMMAND ${CMAKE_OBJCOPY} -I binary -O elf32-littlearm -B arm
### --readonly-text
### --rename-section .data=${RESOURCE_SECNAME},${RESOURCE_SECFLAGS}
### --redefine-sym _binary_${CYW43_FIRMWARE_BIN_}_start=${CYW43_FIRMWARE_PRETTY}_start
### --redefine-sym _binary_${CYW43_FIRMWARE_BIN_}_end=${CYW43_FIRMWARE_PRETTY}_end
### --redefine-sym _binary_${CYW43_FIRMWARE_BIN_}_size=${CYW43_FIRMWARE_PRETTY}_size
### ${CYW43_FIRMWARE_BIN} ${CYW43_FIRMWARE_OBJ}
### )
###
else
INC_CYW43 :=
CFLAGS_CYW43 :=
Expand Down
23 changes: 23 additions & 0 deletions ports/raspberrypi/bindings/cyw43/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "bindings/cyw43/__init__.h"

//| class CywPin:
//| """A class that represents a GPIO pin attached to the wifi chip.
//|
//| Cannot be constructed at runtime, but may be the type of a pin object
//| in :py:mod:`board`. A `CywPin` can be used as a DigitalInOut, but not with other
//| peripherals such as `PWMOut`."""
const mp_obj_type_t cyw43_pin_type = {
{ &mp_type_type },
.flags = MP_TYPE_FLAG_EXTENDED,
Expand All @@ -42,6 +48,22 @@ const mp_obj_type_t cyw43_pin_type = {
)
};

//| def set_power_management(value: int) -> None:
//| """Set the power management register
//|
//| According to Raspberry Pi documentation, the value 0xa11140
//| increases responsiveness at the cost of higher power usage.
//|
//| Besides this value, there appears to be no other public documentation
//| of the values that can be used.
//| """
STATIC mp_obj_t cyw43_set_power_management(const mp_obj_t value_in) {
mp_int_t value = mp_obj_get_int(value_in);
cyw43_wifi_pm(&cyw43_state, value);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(cyw43_set_power_management_obj, cyw43_set_power_management);

const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj) {
if (!mp_obj_is_type(obj, &mcu_pin_type) && !mp_obj_is_type(obj, &cyw43_pin_type)) {
mp_raise_TypeError_varg(translate("Expected a %q or %q"), mcu_pin_type.name, cyw43_pin_type.name);
Expand All @@ -58,6 +80,7 @@ const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj) {
STATIC const mp_rom_map_elem_t cyw43_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cyw43) },
{ MP_ROM_QSTR(MP_QSTR_CywPin), MP_ROM_QSTR(MP_QSTR_CywPin) },
{ MP_ROM_QSTR(MP_QSTR_set_power_management), &cyw43_set_power_management_obj },
};

STATIC MP_DEFINE_CONST_DICT(cyw43_module_globals, cyw43_module_globals_table);
Expand Down
4 changes: 2 additions & 2 deletions ports/raspberrypi/boards/raspberry_pi_pico_w/pins.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) },

{ MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_CYW1) },
{ MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_CYW1) },

{ MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) },
Expand Down
5 changes: 5 additions & 0 deletions ports/raspberrypi/common-hal/digitalio/DigitalInOut.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ void common_hal_digitalio_digitalinout_set_value(

bool common_hal_digitalio_digitalinout_get_value(
digitalio_digitalinout_obj_t *self) {
#if CIRCUITPY_CYW43
if (IS_CYW(self)) {
return cyw43_arch_gpio_get(self->pin->number);
}
#endif
return gpio_get(self->pin->number);
}

Expand Down
3 changes: 3 additions & 0 deletions ports/raspberrypi/common-hal/microcontroller/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT] = {
{ MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_PTR(&pin_GPIO22) },
#if !defined(IGNORE_GPIO23)
{ MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_PTR(&pin_GPIO23) },
#endif
{ MP_ROM_QSTR(MP_QSTR_GPIO24), MP_ROM_PTR(&pin_GPIO24) },
#if !defined(IGNORE_GPIO25)
{ MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_PTR(&pin_GPIO25) },
Expand All @@ -184,6 +186,7 @@ const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT] = {
{ MP_ROM_QSTR(MP_QSTR_GPIO29), MP_ROM_PTR(&pin_GPIO29) },
#if CIRCUITPY_CYW43
{ MP_ROM_QSTR(MP_QSTR_CYW0), MP_ROM_PTR(&pin_CYW0) },
{ MP_ROM_QSTR(MP_QSTR_CYW1), MP_ROM_PTR(&pin_CYW1) },
#endif
};
MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table);
146 changes: 140 additions & 6 deletions ports/raspberrypi/common-hal/socketpool/Socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "py/stream.h"
#include "shared-bindings/socketpool/SocketPool.h"
#include "shared/runtime/interrupt_char.h"
#include "shared/netutils/netutils.h"
#include "supervisor/port.h"
#include "supervisor/shared/tick.h"
#include "supervisor/workflow.h"
Expand Down Expand Up @@ -115,6 +116,10 @@ static inline void poll_sockets(void) {
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK;
#else
RUN_BACKGROUND_TASKS;
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
mp_handle_pending(true);
}
mp_hal_delay_ms(1);
#endif
}
Expand Down Expand Up @@ -739,14 +744,117 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, uint8_t *ip, uint32_
return -MP_EBADF;
}

socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self,
socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *socket,
uint8_t *ip, uint32_t *port) {
mp_raise_NotImplementedError(NULL);
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
mp_raise_OSError(MP_EOPNOTSUPP);
}

// Create new socket object, do it here because we must not raise an out-of-memory
// exception when the LWIP concurrency lock is held
socketpool_socket_obj_t *socket2 = m_new_ll_obj_with_finaliser(socketpool_socket_obj_t);
socket2->base.type = &socketpool_socket_type;

MICROPY_PY_LWIP_ENTER

if (socket->pcb.tcp == NULL) {
MICROPY_PY_LWIP_EXIT
m_del_obj(socketpool_socket_obj_t, socket2);
mp_raise_OSError(MP_EBADF);
}

// I need to do this because "tcp_accepted", later, is a macro.
struct tcp_pcb *listener = socket->pcb.tcp;
if (listener->state != LISTEN) {
MICROPY_PY_LWIP_EXIT
m_del_obj(socketpool_socket_obj_t, socket2);
mp_raise_OSError(MP_EINVAL);
}

// accept incoming connection
struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget];
if (*incoming_connection == NULL) {
if (socket->timeout == 0) {
MICROPY_PY_LWIP_EXIT
m_del_obj(socketpool_socket_obj_t, socket2);
mp_raise_OSError(MP_EAGAIN);
} else if (socket->timeout != -1) {
mp_uint_t retries = socket->timeout / 100;
while (*incoming_connection == NULL) {
MICROPY_PY_LWIP_EXIT
if (retries-- == 0) {
m_del_obj(socketpool_socket_obj_t, socket2);
mp_raise_OSError(MP_ETIMEDOUT);
}
mp_hal_delay_ms(100);
MICROPY_PY_LWIP_REENTER
}
} else {
while (*incoming_connection == NULL) {
MICROPY_PY_LWIP_EXIT
poll_sockets();
MICROPY_PY_LWIP_REENTER
}
}
}

// We get a new pcb handle...
socket2->pcb.tcp = *incoming_connection;
if (++socket->incoming.connection.iget >= socket->incoming.connection.alloc) {
socket->incoming.connection.iget = 0;
}
*incoming_connection = NULL;

// ...and set up the new socket for it.
socket2->domain = MOD_NETWORK_AF_INET;
socket2->type = MOD_NETWORK_SOCK_STREAM;
socket2->incoming.pbuf = NULL;
socket2->timeout = socket->timeout;
socket2->state = STATE_CONNECTED;
socket2->recv_offset = 0;
socket2->callback = MP_OBJ_NULL;
tcp_arg(socket2->pcb.tcp, (void *)socket2);
tcp_err(socket2->pcb.tcp, _lwip_tcp_error);
tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv);

tcp_accepted(listener);

MICROPY_PY_LWIP_EXIT

// output values
memcpy(ip, &(socket2->pcb.tcp->remote_ip), NETUTILS_IPV4ADDR_BUFSIZE);
*port = (mp_uint_t)socket2->pcb.tcp->remote_port;
return MP_OBJ_FROM_PTR(socket2);
}

bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self,
bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t *socket,
const char *host, size_t hostlen, uint32_t port) {
mp_raise_NotImplementedError(NULL);
uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE];

// get address
ip_addr_t bind_addr;
int error = socketpool_resolve_host(socket->pool, host, &bind_addr);
if (error != 0) {
mp_raise_OSError(EHOSTUNREACH);
}

err_t err = ERR_ARG;
switch (socket->type) {
case MOD_NETWORK_SOCK_STREAM: {
err = tcp_bind(socket->pcb.tcp, &bind_addr, port);
break;
}
case MOD_NETWORK_SOCK_DGRAM: {
err = udp_bind(socket->pcb.udp, &bind_addr, port);
break;
}
}

if (err != ERR_OK) {
mp_raise_OSError(error_lookup_table[-err]);
}

return mp_const_none;
}

STATIC err_t _lwip_tcp_close_poll(void *arg, struct tcp_pcb *pcb) {
Expand Down Expand Up @@ -891,8 +999,34 @@ bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t *socket)
return socket->state == STATE_CONNECTED;
}

bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int backlog) {
mp_raise_NotImplementedError(NULL);
bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *socket, int backlog) {
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
mp_raise_OSError(MP_EOPNOTSUPP);
}

struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
if (new_pcb == NULL) {
mp_raise_OSError(MP_ENOMEM);
}
socket->pcb.tcp = new_pcb;

// Allocate memory for the backlog of connections
if (backlog <= 1) {
socket->incoming.connection.alloc = 0;
socket->incoming.connection.tcp.item = NULL;
} else {
socket->incoming.connection.alloc = backlog;
socket->incoming.connection.tcp.array = m_new0(struct tcp_pcb *, backlog);
}
socket->incoming.connection.iget = 0;
socket->incoming.connection.iput = 0;

tcp_accept(new_pcb, _lwip_tcp_accept);

// Socket is no longer considered "new" for purposes of polling
socket->state = STATE_LISTENING;

return mp_const_none;
}

mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *socket,
Expand Down
29 changes: 25 additions & 4 deletions ports/raspberrypi/common-hal/wifi/Radio.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@
#define NETIF_STA (&cyw43_state.netif[CYW43_ITF_STA])
#define NETIF_AP (&cyw43_state.netif[CYW43_ITF_AP])

static inline uint32_t nw_get_le32(const uint8_t *buf) {
return buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
}

static inline void nw_put_le32(uint8_t *buf, uint32_t x) {
buf[0] = x;
buf[1] = x >> 8;
buf[2] = x >> 16;
buf[3] = x >> 24;
}

NORETURN static void ro_attribute(int attr) {
mp_raise_msg_varg(&mp_type_AttributeError, MP_ERROR_TEXT("'%s' object has no attribute '%q'"), "Radio", attr);
}
Expand All @@ -81,7 +92,10 @@ mp_obj_t common_hal_wifi_radio_get_hostname(wifi_radio_obj_t *self) {
}

void common_hal_wifi_radio_set_hostname(wifi_radio_obj_t *self, const char *hostname) {
ro_attribute(MP_QSTR_hostname);
assert(strlen(hostname) < MP_ARRAY_SIZE(self->hostname));
memcpy(self->hostname, hostname, strlen(hostname));
netif_set_hostname(NETIF_STA, self->hostname);
netif_set_hostname(NETIF_AP, self->hostname);
}

mp_obj_t common_hal_wifi_radio_get_mac_address(wifi_radio_obj_t *self) {
Expand All @@ -93,12 +107,19 @@ void common_hal_wifi_radio_set_mac_address(wifi_radio_obj_t *self, const uint8_t
}

mp_float_t common_hal_wifi_radio_get_tx_power(wifi_radio_obj_t *self) {
return MICROPY_FLOAT_CONST(0.);
uint8_t buf[13];
memcpy(buf, "qtxpower\x00\x00\x00\x00\x00", 13);
cyw43_ioctl(&cyw43_state, CYW43_IOCTL_GET_VAR, 13, buf, CYW43_ITF_STA);
return nw_get_le32(buf) * MICROPY_FLOAT_CONST(0.25);
}

void common_hal_wifi_radio_set_tx_power(wifi_radio_obj_t *self, const mp_float_t tx_power) {
ro_attribute(MP_QSTR_tx_power);

mp_int_t dbm_times_four = (int)(4 * tx_power);
uint8_t buf[9 + 4];
memcpy(buf, "qtxpower\x00", 9);
nw_put_le32(buf + 9, dbm_times_four);
cyw43_ioctl(&cyw43_state, CYW43_IOCTL_SET_VAR, 9 + 4, buf, CYW43_ITF_STA);
cyw43_ioctl(&cyw43_state, CYW43_IOCTL_SET_VAR, 9 + 4, buf, CYW43_ITF_AP);
}

mp_obj_t common_hal_wifi_radio_get_mac_address_ap(wifi_radio_obj_t *self) {
Expand Down
1 change: 1 addition & 0 deletions ports/raspberrypi/common-hal/wifi/Radio.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

typedef struct {
mp_obj_base_t base;
char hostname[254]; // hostname max is 253 chars, + 1 for trailing NUL
wifi_scannednetworks_obj_t *current_scan;
} wifi_radio_obj_t;

Expand Down
1 change: 1 addition & 0 deletions ports/raspberrypi/peripherals/pins.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,5 @@ PIN(28);
PIN(29);
#if CIRCUITPY_CYW43
CYW_PIN(0);
CYW_PIN(1);
#endif
1 change: 1 addition & 0 deletions ports/raspberrypi/peripherals/pins.h
Original file line number Diff line number Diff line cha 1241 nge
Expand Up @@ -72,6 +72,7 @@ extern const mcu_pin_obj_t pin_GPIO29;

#if CIRCUITPY_CYW43
extern const mcu_pin_obj_t pin_CYW0;
extern const mcu_pin_obj_t pin_CYW1;
#endif

#endif // MICROPY_INCLUDED_RASPBERRYPI_PERIPHERALS_PINS_H
0