From 987cade17341faa8e2f4d5afd8173088d01dc852 Mon Sep 17 00:00:00 2001 From: hannah Date: Tue, 17 Jun 2025 08:26:50 +0000 Subject: [PATCH 1/7] Add WIZnet W55RP20-EVB-Pico --- .../boards/wiznet_w55rp20_evb_pico/board.c | 9 +++ .../wiznet_w55rp20_evb_pico/mpconfigboard.h | 30 ++++++++ .../wiznet_w55rp20_evb_pico/mpconfigboard.mk | 13 ++++ .../pico-sdk-configboard.h | 9 +++ .../boards/wiznet_w55rp20_evb_pico/pins.c | 73 +++++++++++++++++++ 5 files changed, 134 insertions(+) create mode 100755 ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/board.c create mode 100755 ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.h create mode 100755 ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk create mode 100755 ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pico-sdk-configboard.h create mode 100755 ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/board.c b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/board.c new file mode 100755 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.h b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.h new file mode 100755 index 0000000000000..b5ccfb5ffd926 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.h @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "W55RP20-EVB-Pico" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO19) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO21) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO23) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO22) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +// Wiznet HW config. +#define MICROPY_HW_WIZNET_PIO_SPI_ID (0) +#define MICROPY_HW_WIZNET_PIO_SPI_BAUDRATE (20 * 1000 * 1000) +#define MICROPY_HW_WIZNET_PIO_SPI_SCK (21) +#define MICROPY_HW_WIZNET_PIO_SPI_MOSI (23) +#define MICROPY_HW_WIZNET_PIO_SPI_MISO (22) +#define MICROPY_HW_WIZNET_PIO_PIN_CS (20) +#define MICROPY_HW_WIZNET_PIO_PIN_RST (25) +// Connecting the INTN pin enables RECV interrupt handling of incoming data. +#define MICROPY_HW_WIZNET_PIN_INTN (24) diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk new file mode 100755 index 0000000000000..12d673ce7b07b --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk @@ -0,0 +1,13 @@ +USB_VID = 0x2E8A +USB_PID = 0x0005 +USB_PRODUCT = "WIZNET W55RP20 EVB PICO" +USB_MANUFACTURER = "WIZNET" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_USB_HOST = 0 \ No newline at end of file diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pico-sdk-configboard.h b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pico-sdk-configboard.h new file mode 100755 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c new file mode 100755 index 0000000000000..c0db99042c077 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c @@ -0,0 +1,73 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_CS), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SCK), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MISO), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MOSI), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_INT), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_RST), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); From 56ffd4eca71b829ea20cff76e857c164bc15008f Mon Sep 17 00:00:00 2001 From: hannah Date: Fri, 20 Jun 2025 08:51:52 +0000 Subject: [PATCH 2/7] Add functions and define for wiznet_pio_spi support. --- ports/raspberrypi/Makefile | 29 ++ .../wiznet_w55rp20_evb_pico/mpconfigboard.mk | 5 +- .../common-hal/busio/WIZNET_PIO_SPI.c | 123 +++++ .../common-hal/busio/WIZNET_PIO_SPI.h | 25 + .../wiznet_pio_spi/wizchip_pio_spi.c | 389 ++++++++++++++ .../wiznet_pio_spi/wizchip_pio_spi.h | 43 ++ .../wiznet_pio_spi/wizchip_pio_spi.pio | 24 + py/circuitpy_defns.mk | 3 + py/circuitpy_mpconfig.mk | 3 + shared-bindings/busio/WIZNET_PIO_SPI.c | 486 ++++++++++++++++++ shared-bindings/busio/WIZNET_PIO_SPI.h | 40 ++ shared-bindings/busio/__init__.c | 7 + 12 files changed, 1175 insertions(+), 2 deletions(-) mode change 100644 => 100755 ports/raspberrypi/Makefile create mode 100755 ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c create mode 100755 ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h create mode 100755 ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c create mode 100755 ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.h create mode 100755 ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio mode change 100644 => 100755 py/circuitpy_defns.mk mode change 100644 => 100755 py/circuitpy_mpconfig.mk create mode 100755 shared-bindings/busio/WIZNET_PIO_SPI.c create mode 100755 shared-bindings/busio/WIZNET_PIO_SPI.h mode change 100644 => 100755 shared-bindings/busio/__init__.c diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile old mode 100644 new mode 100755 index 6565af79bf3e1..e1f17adb402b9 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -83,6 +83,33 @@ SRC_CYW43 := SRC_LWIP := endif +ifeq ($(CIRCUITPY_WIZNET_PIO_SPI), 1) +INC_WIZNET_PIO_SPI := \ + -isystem wiznet_pio_spi \ + +SRC_WIZNET_PIO_SPI := \ + wiznet_pio_spi/wizchip_pio_spi.c \ + +WIZNET_PIOASM = $(BUILD)/pioasm/pioasm/pioasm +.PHONY: pioasmBuild +pioasmBuild: $(WIZNET_PIOASM) + +$(WIZNET_PIOASM): + $(Q)cmake -S pioasm -B $(BUILD)/pioasm + $(MAKE) -C $(BUILD)/pioasm pioasmBuild + +$(BUILD)/wizchip_pio_spi.pio.h: wiznet_pio_spi/wizchip_pio_spi.pio $(WIZNET_PIOASM) + $(Q)$(WIZNET_PIOASM) -o c-sdk $< $@ +$(BUILD)/wiznet_pio_spi/wizchip_pio_spi.o: $(BUILD)/wizchip_pio_spi.pio.h + +$(BUILD)/genhdr/qstr.i.last: $(BUILD)/wizchip_pio_spi.pio.h + +else +INC_WIZNET_PIO_SPI := +SRC_WIZNET_PIO_SPI := + +endif + CHIP_VARIANT_LOWER = $(shell echo $(CHIP_VARIANT) | tr '[:upper:]' '[:lower:]') INC += \ @@ -155,6 +182,7 @@ INC += \ -isystem sdk/src/rp2_common/pico_time_adapter/include/ \ -isystem sdk/src/rp2_common/pico_unique_id/include/ \ $(INC_CYW43) \ + $(INC_WIZNET_PIO_SPI) \ -Isdk_config \ -I../../lib/tinyusb/src \ -I../../supervisor/shared/usb \ @@ -541,6 +569,7 @@ SRC_C += \ mphalport.c \ $(SRC_CYW43) \ $(SRC_LWIP) \ + $(SRC_WIZNET_PIO_SPI) \ ifeq ($(CIRCUITPY_USB_HOST), 1) diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk index 12d673ce7b07b..6045e5c898677 100755 --- a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk @@ -1,13 +1,14 @@ USB_VID = 0x2E8A USB_PID = 0x0005 -USB_PRODUCT = "WIZNET W55RP20 EVB PICO" -USB_MANUFACTURER = "WIZNET" +USB_PRODUCT = "W55RP20-EVB-Pico" +USB_MANUFACTURER = "WIZnet" CHIP_VARIANT = RP2040 CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" +CIRCUITPY_WIZNET_PIO_SPI = 1 CIRCUITPY__EVE = 1 CIRCUITPY_SSL = 1 CIRCUITPY_USB_HOST = 0 \ No newline at end of file diff --git a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c new file mode 100755 index 0000000000000..a90646e47aaa1 --- /dev/null +++ b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c @@ -0,0 +1,123 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/busio/WIZNET_PIO_SPI.h" + +#include "shared/runtime/interrupt_char.h" +#include "py/mperrno.h" +#include "py/runtime.h" + +#include "supervisor/board.h" +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "hardware/dma.h" +#include "hardware/gpio.h" +#include "hardware/pio.h" +#include "hardware/clocks.h" + +#include "wiznet_pio_spi/wizchip_pio_spi.h" + +#define NO_INSTANCE 0xff + +#ifndef PIO_SPI_PREFERRED_PIO +#define PIO_SPI_PREFERRED_PIO 1 +#endif + +// All wiznet spi operations must start with writing a 3 byte header + +wiznet_pio_spi_config_t wiznet_pio_spi_config; +wiznet_pio_spi_handle_t wiznet_pio_spi_handle = NULL; + +void common_hal_wiznet_pio_spi_construct(wiznet_pio_spi_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso, bool half_duplex) { + + if (half_duplex) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex); + } + + wiznet_pio_spi_config.data_in_pin = miso->number; + wiznet_pio_spi_config.data_out_pin = mosi->number; + wiznet_pio_spi_config.clock_pin = clock->number; + + if (wiznet_pio_spi_handle != NULL) { + wiznet_pio_spi_close(wiznet_pio_spi_handle); + } + + wiznet_pio_spi_handle = wiznet_pio_spi_open(&wiznet_pio_spi_config); + (*wiznet_pio_spi_handle)->set_active(wiznet_pio_spi_handle); + +} + +bool common_hal_wiznet_pio_spi_deinited(wiznet_pio_spi_obj_t *self) { + return wiznet_pio_spi_config.clock_pin == 0; +} + +void common_hal_wiznet_pio_spi_deinit(wiznet_pio_spi_obj_t *self) { + if (common_hal_wiznet_pio_spi_deinited(self)) { + return; + } + + common_hal_reset_pin(self->clock); + common_hal_reset_pin(self->MOSI); + common_hal_reset_pin(self->MISO); + + wiznet_pio_spi_config.clock_pin = 0; +} + +bool common_hal_wiznet_pio_spi_configure(wiznet_pio_spi_obj_t *self, + uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { + + uint32_t clock = clock_get_hz(clk_sys); + uint32_t clock_div = clock / baudrate; + + if (clock_div > clock / 4) { + clock_div = clock / 4; + } + + wiznet_pio_spi_config.clock_div_major = clock_div; + wiznet_pio_spi_config.clock_div_minor = 0; + + return true; +} + +bool common_hal_wiznet_pio_spi_try_lock(wiznet_pio_spi_obj_t *self) { + if (common_hal_wiznet_pio_spi_deinited(self)) { + return false; + } + + bool grabbed_lock = false; + if (!self->has_lock) { + grabbed_lock = true; + self->has_lock = true; + } + return grabbed_lock; +} + +bool common_hal_wiznet_pio_spi_has_lock(wiznet_pio_spi_obj_t *self) { + return self->has_lock; +} + +void common_hal_wiznet_pio_spi_unlock(wiznet_pio_spi_obj_t *self) { + self->has_lock = false; +} + +bool common_hal_wiznet_pio_spi_write(wiznet_pio_spi_obj_t *self, + const uint8_t *data, size_t len) { + wiznet_pio_spi_write_buffer(data, len); + return true; +} + +bool common_hal_wiznet_pio_spi_read(wiznet_pio_spi_obj_t *self, + uint8_t *data, size_t len, uint8_t write_value) { + wiznet_pio_spi_read_buffer(data, len); + return true; +} + +bool common_hal_wiznet_pio_spi_transfer(wiznet_pio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) { + return wiznet_pio_spi_transfer(data_out, len, data_in, len); +} \ No newline at end of file diff --git a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h new file mode 100755 index 0000000000000..29d077b4341e1 --- /dev/null +++ b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" + +#include "py/obj.h" + +#include "hardware/spi.h" + +#define SPI_HEADER_LEN 3 + +typedef struct { + mp_obj_base_t base; + bool has_lock; + const mcu_pin_obj_t *clock; + const mcu_pin_obj_t *MOSI; + const mcu_pin_obj_t *MISO; +} wiznet_pio_spi_obj_t; + +void reset_spi(void); \ No newline at end of file diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c new file mode 100755 index 0000000000000..564dd9191b0b7 --- /dev/null +++ b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "pico/stdlib.h" +#include "pico/error.h" + +#include "hardware/dma.h" +#include "hardware/clocks.h" + +#include "wizchip_pio_spi.h" +#include "wizchip_pio_spi.pio.h" + +#ifndef PIO_SPI_PREFERRED_PIO +#define PIO_SPI_PREFERRED_PIO 1 +#endif + +#define PADS_DRIVE_STRENGTH PADS_BANK0_GPIO0_DRIVE_VALUE_12MA +#define IRQ_SAMPLE_DELAY_NS 100 + +#define WIZNET_PIO_SPI_PROGRAM_NAME wiznet_pio_spi_write_read +#define WIZNET_PIO_SPI_PROGRAM_FUNC __CONCAT(WIZNET_PIO_SPI_PROGRAM_NAME, _program) +#define WIZNET_PIO_SPI_PROGRAM_GET_DEFAULT_CONFIG_FUNC __CONCAT(WIZNET_PIO_SPI_PROGRAM_NAME, _program_get_default_config) +#define WIZNET_PIO_SPI_OFFSET_WRITE_BITS __CONCAT(WIZNET_PIO_SPI_PROGRAM_NAME, _offset_write_bits) +#define WIZNET_PIO_SPI_OFFSET_WRITE_END __CONCAT(WIZNET_PIO_SPI_PROGRAM_NAME, _offset_write_end) +#define WIZNET_PIO_SPI_OFFSET_READ_END __CONCAT(WIZNET_PIO_SPI_PROGRAM_NAME, _offset_read_end) + +// All wiznet spi operations must start with writing a 3 byte header +#define WIZNET_PIO_SPI_HEADER_LEN 3 + +#ifndef WIZNET_PICO_PIO_SPI_INSTANCE_COUNT +#define WIZNET_PICO_PIO_SPI_INSTANCE_COUNT 1 +#endif + +typedef struct wiznet_pio_spi_state { + wiznet_pio_spi_funcs_t *funcs; + const wiznet_pio_spi_config_t *spi_config; + pio_hw_t *pio; + uint8_t pio_func_sel; + int8_t pio_offset; + int8_t pio_sm; + int8_t dma_out; + int8_t dma_in; + uint8_t spi_header[WIZNET_PIO_SPI_HEADER_LEN]; + uint8_t spi_header_count; +} wiznet_pio_spi_state_t; +static wiznet_pio_spi_state_t wiznet_pio_spi_state[WIZNET_PICO_PIO_SPI_INSTANCE_COUNT]; +static wiznet_pio_spi_state_t *active_state; + +static wiznet_pio_spi_funcs_t *get_wiznet_pio_spi_impl(void); + +// Initialise our gpios +static void wiznet_pio_spi_gpio_setup(wiznet_pio_spi_state_t *state) { + + // Setup MOSI, MISO and IRQ + gpio_init(state->spi_config->data_out_pin); + gpio_set_dir(state->spi_config->data_out_pin, GPIO_OUT); + gpio_put(state->spi_config->data_out_pin, false); + + gpio_init(state->spi_config->data_in_pin); + gpio_set_dir(state->spi_config->data_in_pin, GPIO_IN); + + // Setup CS + gpio_init(state->spi_config->cs_pin); + gpio_set_dir(state->spi_config->cs_pin, GPIO_OUT); + gpio_put(state->spi_config->cs_pin, true); + + // Setup IRQ + gpio_init(state->spi_config->irq_pin); + gpio_set_dir(state->spi_config->irq_pin, GPIO_IN); + gpio_set_pulls(state->spi_config->irq_pin, false, false); +} + +wiznet_pio_spi_handle_t wiznet_pio_spi_open(const wiznet_pio_spi_config_t *wiznet_pio_spi_config) { + wiznet_pio_spi_state_t *state; + for (size_t i = 0; i < count_of(wiznet_pio_spi_state); i++) { + if (!wiznet_pio_spi_state[i].funcs) { + state = &wiznet_pio_spi_state[i]; + break; + } + } + assert(state); + // if (!state) return NULL; + state->spi_config = wiznet_pio_spi_config; + state->funcs = get_wiznet_pio_spi_impl(); + + wiznet_pio_spi_gpio_setup(state); + + pio_hw_t *pios[2] = {pio0, pio1}; + uint pio_index = PIO_SPI_PREFERRED_PIO; + + if (!pio_can_add_program(pios[pio_index], &WIZNET_PIO_SPI_PROGRAM_FUNC)) { + pio_index ^= 1; + if (!pio_can_add_program(pios[pio_index], &WIZNET_PIO_SPI_PROGRAM_FUNC)) { + return NULL; + } + } + + state->pio = pios[pio_index]; + state->dma_in = -1; + state->dma_out = -1; + + static_assert(GPIO_FUNC_PIO1 == GPIO_FUNC_PIO0 + 1, ""); + state->pio_func_sel = GPIO_FUNC_PIO0 + pio_index; + state->pio_sm = (int8_t)pio_claim_unused_sm(state->pio, false); + if (state->pio_sm < 0) { + wiznet_pio_spi_close(&state->funcs); + return NULL; + } + + state->pio_offset = pio_add_program(state->pio, &WIZNET_PIO_SPI_PROGRAM_FUNC); + + pio_sm_config sm_config = WIZNET_PIO_SPI_PROGRAM_GET_DEFAULT_CONFIG_FUNC(state->pio_offset); + + sm_config_set_clkdiv_int_frac(&sm_config, state->spi_config->clock_div_major, state->spi_config->clock_div_minor); + hw_write_masked(&pads_bank0_hw->io[state->spi_config->clock_pin], + (uint)PADS_DRIVE_STRENGTH << PADS_BANK0_GPIO0_DRIVE_LSB, + PADS_BANK0_GPIO0_DRIVE_BITS + ); + hw_write_masked(&pads_bank0_hw->io[state->spi_config->clock_pin], + (uint)1 << PADS_BANK0_GPIO0_SLEWFAST_LSB, + PADS_BANK0_GPIO0_SLEWFAST_BITS + ); + + sm_config_set_out_pins(&sm_config, state->spi_config->data_out_pin, 1); + sm_config_set_in_pins(&sm_config, state->spi_config->data_in_pin); + sm_config_set_set_pins(&sm_config, state->spi_config->data_out_pin, 1); + sm_config_set_sideset(&sm_config, 1, false, false); + sm_config_set_sideset_pins(&sm_config, state->spi_config->clock_pin); + + sm_config_set_in_shift(&sm_config, false, true, 8); + sm_config_set_out_shift(&sm_config, false, true, 8); + hw_set_bits(&state->pio->input_sync_bypass, 1u << state->spi_config->data_in_pin); + pio_sm_set_config(state->pio, state->pio_sm, &sm_config); + pio_sm_set_consecutive_pindirs(state->pio, state->pio_sm, state->spi_config->clock_pin, 1, true); + gpio_set_function(state->spi_config->data_out_pin, state->pio_func_sel); + gpio_set_function(state->spi_config->clock_pin, state->pio_func_sel); + + // Set data pin to pull down and schmitt + gpio_set_pulls(state->spi_config->data_in_pin, false, true); + gpio_set_input_hysteresis_enabled(state->spi_config->data_in_pin, true); + + pio_sm_exec(state->pio, state->pio_sm, pio_encode_set(pio_pins, 1)); + state->dma_out = (int8_t)dma_claim_unused_channel(false); // todo: Should be able to use one dma channel? + state->dma_in = (int8_t)dma_claim_unused_channel(false); + if (state->dma_out < 0 || state->dma_in < 0) { + wiznet_pio_spi_close(&state->funcs); + return NULL; + } + return &state->funcs; +} + +void wiznet_pio_spi_close(wiznet_pio_spi_handle_t handle) { + wiznet_pio_spi_state_t *state = (wiznet_pio_spi_state_t *)handle; + if (state) { + if (state->pio_sm >= 0) { + if (state->pio_offset != -1) { + pio_remove_program(state->pio, &WIZNET_PIO_SPI_PROGRAM_FUNC, state->pio_offset); + } + + pio_sm_unclaim(state->pio, state->pio_sm); + } + if (state->dma_out >= 0) { + dma_channel_unclaim(state->dma_out); + state->dma_out = -1; + } + if (state->dma_in >= 0) { + dma_channel_unclaim(state->dma_in); + state->dma_in = -1; + } + state->funcs = NULL; + } +} + +static void cs_set(wiznet_pio_spi_state_t *state, bool value) { + gpio_put(state->spi_config->cs_pin, value); +} + +static __noinline void ns_delay(uint32_t ns) { + // cycles = ns * clk_sys_hz / 1,000,000,000 + uint32_t cycles = ns * (clock_get_hz(clk_sys) >> 16u) / (1000000000u >> 16u); + busy_wait_at_least_cycles(cycles); +} + +static void wiznet_pio_spi_frame_start(void) { + assert(active_state); + + gpio_set_function(active_state->spi_config->data_out_pin, active_state->pio_func_sel); + gpio_set_function(active_state->spi_config->clock_pin, active_state->pio_func_sel); + gpio_pull_down(active_state->spi_config->clock_pin); + + // Pull CS low + cs_set(active_state, false); +} + +static void wiznet_pio_spi_frame_end(void) { + assert(active_state); + + // from this point a positive edge will cause an IRQ to be pending + cs_set(active_state, true); + + // we need to wait a bit in case the irq line is incorrectly high + #ifdef IRQ_SAMPLE_DELAY_NS + ns_delay(IRQ_SAMPLE_DELAY_NS); + #endif +} + +// send tx then receive rx +// rx can be null if you just want to send, but tx and tx_length must be valid +bool wiznet_pio_spi_transfer(const uint8_t *tx, size_t tx_length, uint8_t *rx, size_t rx_length) { + const wiznet_pio_spi_state_t *state = active_state; + if (!state || (tx == NULL)) { + return false; + } + + if (rx != NULL && tx != NULL) { + assert(tx && tx_length && rx_length); + + pio_sm_set_enabled(state->pio, state->pio_sm, false); // disable sm + pio_sm_set_wrap(state->pio, state->pio_sm, state->pio_offset + WIZNET_PIO_SPI_OFFSET_WRITE_BITS, state->pio_offset + WIZNET_PIO_SPI_OFFSET_READ_END - 1); + pio_sm_clear_fifos(state->pio, state->pio_sm); // clear fifos from previous run + pio_sm_set_pindirs_with_mask(state->pio, state->pio_sm, 1u << state->spi_config->data_out_pin, 1u << state->spi_config->data_out_pin); + pio_sm_restart(state->pio, state->pio_sm); + pio_sm_clkdiv_restart(state->pio, state->pio_sm); + pio_sm_put(state->pio, state->pio_sm, tx_length * 8 - 1); // set x + pio_sm_exec(state->pio, state->pio_sm, pio_encode_out(pio_x, 32)); + pio_sm_put(state->pio, state->pio_sm, rx_length - 1); // set y + pio_sm_exec(state->pio, state->pio_sm, pio_encode_out(pio_y, 32)); + pio_sm_exec(state->pio, state->pio_sm, pio_encode_jmp(state->pio_offset)); // setup pc + + dma_channel_abort(state->dma_out); + dma_channel_abort(state->dma_in); + + dma_channel_config out_config = dma_channel_get_default_config(state->dma_out); + channel_config_set_dreq(&out_config, pio_get_dreq(state->pio, state->pio_sm, true)); + channel_config_set_transfer_data_size(&out_config, DMA_SIZE_8); + dma_channel_configure(state->dma_out, &out_config, &state->pio->txf[state->pio_sm], tx, tx_length, true); + + dma_channel_config in_config = dma_channel_get_default_config(state->dma_in); + channel_config_set_dreq(&in_config, pio_get_dreq(state->pio, state->pio_sm, false)); + channel_config_set_write_increment(&in_config, true); + channel_config_set_read_increment(&in_config, false); + channel_config_set_transfer_data_size(&in_config, DMA_SIZE_8); + dma_channel_configure(state->dma_in, &in_config, rx, &state->pio->rxf[state->pio_sm], rx_length, true); + + pio_sm_set_enabled(state->pio, state->pio_sm, true); + __compiler_memory_barrier(); + + dma_channel_wait_for_finish_blocking(state->dma_out); + dma_channel_wait_for_finish_blocking(state->dma_in); + + __compiler_memory_barrier(); + } else if (tx != NULL) { + assert(tx_length); + + pio_sm_set_enabled(state->pio, state->pio_sm, false); + pio_sm_set_wrap(state->pio, state->pio_sm, state->pio_offset + WIZNET_PIO_SPI_OFFSET_WRITE_BITS, state->pio_offset + WIZNET_PIO_SPI_OFFSET_WRITE_END - 1); + pio_sm_clear_fifos(state->pio, state->pio_sm); + pio_sm_restart(state->pio, state->pio_sm); + pio_sm_clkdiv_restart(state->pio, state->pio_sm); + pio_sm_put(state->pio, state->pio_sm, tx_length * 8 - 1); + pio_sm_exec(state->pio, state->pio_sm, pio_encode_out(pio_x, 32)); + pio_sm_put(state->pio, state->pio_sm, tx_length - 1); + pio_sm_exec(state->pio, state->pio_sm, pio_encode_out(pio_y, 32)); + pio_sm_exec(state->pio, state->pio_sm, pio_encode_set(pio_pins, 0)); + pio_sm_set_consecutive_pindirs(state->pio, state->pio_sm, state->spi_config->data_out_pin, 1, true); + pio_sm_exec(state->pio, state->pio_sm, pio_encode_jmp(state->pio_offset + WIZNET_PIO_SPI_OFFSET_WRITE_BITS)); + + dma_channel_abort(state->dma_out); + + dma_channel_config out_config = dma_channel_get_default_config(state->dma_out); + channel_config_set_dreq(&out_config, pio_get_dreq(state->pio, state->pio_sm, true)); + + channel_config_set_transfer_data_size(&out_config, DMA_SIZE_8); + dma_channel_configure(state->dma_out, &out_config, &state->pio->txf[state->pio_sm], tx, tx_length, true); + + const uint32_t fDebugTxStall = 1u << (PIO_FDEBUG_TXSTALL_LSB + state->pio_sm); + state->pio->fdebug = fDebugTxStall; + pio_sm_set_enabled(state->pio, state->pio_sm, true); + while (!(state->pio->fdebug & fDebugTxStall)) { + // printf("WIZNET_PIO_SPI: waiting for tx stall\n"); + tight_loop_contents(); // todo timeout + } + uint32_t timeout = 1000000; + if (timeout == 0) { + printf("ERROR: PIO TXSTALL timeout!\n"); + return false; + } + __compiler_memory_barrier(); + pio_sm_set_enabled(state->pio, state->pio_sm, false); + pio_sm_set_consecutive_pindirs(state->pio, state->pio_sm, state->spi_config->data_in_pin, 1, false); + } else if (rx != NULL) { + panic_unsupported(); // shouldn't be used + } + pio_sm_exec(state->pio, state->pio_sm, pio_encode_mov(pio_pins, pio_null)); // for next time we turn output on + + return true; +} + +// To read a byte we must first have been asked to write a 3 byte spi header +static uint8_t wiznet_pio_spi_read_byte(void) { + assert(active_state); + assert(active_state->spi_header_count == WIZNET_PIO_SPI_HEADER_LEN); + uint8_t ret; + if (!wiznet_pio_spi_transfer(active_state->spi_header, active_state->spi_header_count, &ret, 1)) { + panic("spi failed read"); + } + active_state->spi_header_count = 0; + return ret; +} + +// This is not used when the burst functions are provided +static void wiznet_pio_spi_write_byte(uint8_t wb) { + panic_unsupported(); // shouldn't be used +} + +// To read a buffer we must first have been asked to write a 3 byte spi header +void wiznet_pio_spi_read_buffer(uint8_t *pBuf, uint16_t len) { + assert(active_state); + assert(active_state->spi_header_count == WIZNET_PIO_SPI_HEADER_LEN); + if (!wiznet_pio_spi_transfer(active_state->spi_header, active_state->spi_header_count, pBuf, len)) { + panic("spi failed reading buffer"); + } + active_state->spi_header_count = 0; +} + +// If we have been asked to write a spi header already, then write it and the rest of the buffer +// or else if we've been given enough data for just the spi header, save it until the next call +// or we're writing a byte in which case we're given a buffer including the spi header +void wiznet_pio_spi_write_buffer(const uint8_t *pBuf, uint16_t len) { + assert(active_state); + + if (len < WIZNET_PIO_SPI_HEADER_LEN && active_state->spi_header_count != WIZNET_PIO_SPI_HEADER_LEN) { + memcpy(&active_state->spi_header[active_state->spi_header_count], pBuf, len); // expect another call + active_state->spi_header_count++; + } else if (len == WIZNET_PIO_SPI_HEADER_LEN && active_state->spi_header_count == 0) { + memcpy(active_state->spi_header, pBuf, WIZNET_PIO_SPI_HEADER_LEN); // expect another call + active_state->spi_header_count = WIZNET_PIO_SPI_HEADER_LEN; + } else { + if (active_state->spi_header_count == WIZNET_PIO_SPI_HEADER_LEN) { + if (!wiznet_pio_spi_transfer(active_state->spi_header, WIZNET_PIO_SPI_HEADER_LEN, NULL, 0)) { + panic("spi failed writing header"); + } + active_state->spi_header_count = 0; + } + assert(active_state->spi_header_count == 0); + if (!wiznet_pio_spi_transfer(pBuf, len, NULL, 0)) { + panic("spi failed writing buffer"); + } + } +} + +static void wiznet_pio_spi_set_active(wiznet_pio_spi_handle_t handle) { + active_state = (wiznet_pio_spi_state_t *)handle; +} + +static void wiznet_pio_spi_set_inactive(void) { + active_state = NULL; +} + +static void wiznet_pio_spi_reset(wiznet_pio_spi_handle_t handle) { + wiznet_pio_spi_state_t *state = (wiznet_pio_spi_state_t *)handle; + gpio_set_dir(state->spi_config->reset_pin, GPIO_OUT); + gpio_put(state->spi_config->reset_pin, 0); + sleep_ms(100); + gpio_put(state->spi_config->reset_pin, 1); + sleep_ms(100); +} + +static wiznet_pio_spi_funcs_t *get_wiznet_pio_spi_impl(void) { + static wiznet_pio_spi_funcs_t funcs = { + .close = wiznet_pio_spi_close, + .set_active = wiznet_pio_spi_set_active, + .set_inactive = wiznet_pio_spi_set_inactive, + .frame_start = wiznet_pio_spi_frame_start, + .frame_end = wiznet_pio_spi_frame_end, + .read_byte = wiznet_pio_spi_read_byte, + .write_byte = wiznet_pio_spi_write_byte, + .read_buffer = wiznet_pio_spi_read_buffer, + .write_buffer = wiznet_pio_spi_write_buffer, + .reset = wiznet_pio_spi_reset, + }; + return &funcs; +} diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.h b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.h new file mode 100755 index 0000000000000..841eb48c480a2 --- /dev/null +++ b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _WIZNET_PIO_SPI_H_ +#define _WIZNET_PIO_SPI_H_ + +typedef struct wiznet_pio_spi_config { + uint8_t data_in_pin; + uint8_t data_out_pin; + uint8_t cs_pin; + uint8_t clock_pin; + uint8_t irq_pin; + uint8_t reset_pin; + uint16_t clock_div_major; + uint8_t clock_div_minor; + uint8_t spi_hw_instance; +} wiznet_pio_spi_config_t; + +typedef struct wiznet_pio_spi_funcs **wiznet_pio_spi_handle_t; + +typedef struct wiznet_pio_spi_funcs { + void (*close)(wiznet_pio_spi_handle_t funcs); + void (*set_active)(wiznet_pio_spi_handle_t funcs); + void (*set_inactive)(void); + void (*frame_start)(void); + void (*frame_end)(void); + uint8_t (*read_byte)(void); + void (*write_byte)(uint8_t tx_data); + void (*read_buffer)(uint8_t *pBuf, uint16_t len); + void (*write_buffer)(const uint8_t *pBuf, uint16_t len); + void (*reset)(wiznet_pio_spi_handle_t funcs); +} wiznet_pio_spi_funcs_t; + +wiznet_pio_spi_handle_t wiznet_pio_spi_open(const wiznet_pio_spi_config_t *pio_spi_config); +void wiznet_pio_spi_close(wiznet_pio_spi_handle_t handle); +bool wiznet_pio_spi_transfer(const uint8_t *tx, size_t tx_length, uint8_t *rx, size_t rx_length); +void wiznet_pio_spi_read_buffer(uint8_t *pBuf, uint16_t len); +void wiznet_pio_spi_write_buffer(const uint8_t *pBuf, uint16_t len); + +#endif diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio new file mode 100755 index 0000000000000..092a2b589a7d1 --- /dev/null +++ b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio @@ -0,0 +1,24 @@ +; +; Copyright (c) 2023 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program wiznet_pio_spi_write_read +.side_set 1 + +public write_bits: + out pins, 1 side 0 + jmp x-- write_bits side 1 + set pins 0 side 0 +public write_end: +read_byte_delay: + set pindirs 0 side 0 +read_byte: + set x 6 side 1 +read_bits: + in pins, 1 side 0 + jmp x-- read_bits side 1 + in pins, 1 side 0 + jmp y-- read_byte side 0 +public read_end: \ No newline at end of file diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk old mode 100644 new mode 100755 index d6569bc39bd8e..de9703811c73c --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -459,6 +459,9 @@ endif ifeq ($(CIRCUITPY_WIFI),1) SRC_PATTERNS += wifi/% endif +ifeq ($(CIRCUITPY_WIZNET_PIO_SPI),1) +SRC_PATTERNS += busio/WIZNET_PIO_SPI.c busio/WIZNET_PIO_SPI.h +endif ifeq ($(CIRCUITPY_ZLIB),1) SRC_PATTERNS += zlib/% endif diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk old mode 100644 new mode 100755 index 2009c4e177da6..9fa788d6fb385 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -206,6 +206,9 @@ CFLAGS += -DCIRCUITPY_BUSIO_SPI=$(CIRCUITPY_BUSIO_SPI) CIRCUITPY_BUSIO_UART ?= $(CIRCUITPY_BUSIO) CFLAGS += -DCIRCUITPY_BUSIO_UART=$(CIRCUITPY_BUSIO_UART) +CIRCUITPY_WIZNET_PIO_SPI ?= 0 +CFLAGS += -DCIRCUITPY_WIZNET_PIO_SPI=$(CIRCUITPY_WIZNET_PIO_SPI) + CIRCUITPY_CAMERA ?= 0 CFLAGS += -DCIRCUITPY_CAMERA=$(CIRCUITPY_CAMERA) diff --git a/shared-bindings/busio/WIZNET_PIO_SPI.c b/shared-bindings/busio/WIZNET_PIO_SPI.c new file mode 100755 index 0000000000000..81a74f933d011 --- /dev/null +++ b/shared-bindings/busio/WIZNET_PIO_SPI.c @@ -0,0 +1,486 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft +// +// SPDX-License-Identifier: MIT + +// This file contains all of the Python API definitions for the +// busio.SPI class. + +#include + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busio/WIZNET_PIO_SPI.h" +#include "shared-bindings/util.h" + +#include "shared/runtime/buffer_helper.h" +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/mperrno.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +#include + + +//| class SPI: +//| """A 3-4 wire serial protocol +//| +//| SPI is a serial protocol that has exclusive pins for data in and out of the +//| main device. It is typically faster than :py:class:`~bitbangio.I2C` because a +//| separate pin is used to select a device rather than a transmitted +//| address. This class only manages three of the four SPI lines: `!clock`, +//| `!MOSI`, `!MISO`. It is up to the client to manage the appropriate +//| select line, often abbreviated `!CS` or `!SS`. (This is common because +//| multiple secondaries can share the `!clock`, `!MOSI` and `!MISO` lines +//| and therefore the hardware.) +//| +//| .. raw:: html +//| +//|

+//|

+//| Available on these boards +//|
    +//| {% for board in support_matrix_reverse["busio.SPI"] %} +//|
  • {{ board }} +//| {% endfor %} +//|
+//|
+//|

+//| +//| .. seealso:: This class acts as an SPI main (controller). +//| To act as an SPI secondary (target), use `spitarget.SPITarget`. +//| """ +//| +//| def __init__( +//| self, +//| clock: microcontroller.Pin, +//| MOSI: Optional[microcontroller.Pin] = None, +//| MISO: Optional[microcontroller.Pin] = None, +//| half_duplex: bool = False, +//| ) -> None: +//| """Construct an SPI object on the given pins. +//| +//| .. note:: The SPI peripherals allocated in order of desirability, if possible, +//| such as highest speed and not shared use first. For instance, on the nRF52840, +//| there is a single 32MHz SPI peripheral, and multiple 8MHz peripherals, +//| some of which may also be used for I2C. The 32MHz SPI peripheral is returned +//| first, then the exclusive 8MHz SPI peripheral, and finally the shared 8MHz +//| peripherals. +//| +//| .. seealso:: Using this class directly requires careful lock management. +//| Instead, use :class:`~adafruit_bus_device.SPIDevice` to +//| manage locks. +//| +//| .. seealso:: Using this class to directly read registers requires manual +//| bit unpacking. Instead, use an existing driver or make one with +//| :ref:`Register ` data descriptors. +//| +//| :param ~microcontroller.Pin clock: the pin to use for the clock. +//| :param ~microcontroller.Pin MOSI: the Main Out Selected In pin. +//| :param ~microcontroller.Pin MISO: the Main In Selected Out pin. +//| :param bool half_duplex: True when MOSI is used for bidirectional data. False when SPI is full-duplex or simplex. +//| +//| **Limitations:** ``half_duplex`` is available only on STM; other chips do not have the hardware support. +//| """ +//| ... +//| + +// TODO(tannewt): Support LSB SPI. +static mp_obj_t wiznet_pio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + #if CIRCUITPY_WIZNET_PIO_SPI + wiznet_pio_spi_obj_t *self = mp_obj_malloc(wiznet_pio_spi_obj_t, &busio_wiznet_pio_spi_type); + enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_half_duplex }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MOSI, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_MISO, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_half_duplex, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock); + const mcu_pin_obj_t *mosi = validate_obj_is_free_pin_or_none(args[ARG_MOSI].u_obj, MP_QSTR_mosi); + const mcu_pin_obj_t *miso = validate_obj_is_free_pin_or_none(args[ARG_MISO].u_obj, MP_QSTR_miso); + + if (!miso && !mosi) { + mp_raise_ValueError(MP_ERROR_TEXT("Must provide MISO or MOSI pin")); + } + + common_hal_wiznet_pio_spi_construct(self, clock, mosi, miso, args[ARG_half_duplex].u_bool); + return MP_OBJ_FROM_PTR(self); + #else + mp_raise_NotImplementedError(NULL); + #endif // CIRCUITPY_WIZNET_PIO_SPI +} + +#if CIRCUITPY_WIZNET_PIO_SPI +//| def deinit(self) -> None: +//| """Turn off the SPI bus.""" +//| ... +//| +static mp_obj_t wiznet_pio_spi_obj_deinit(mp_obj_t self_in) { + wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_wiznet_pio_spi_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_deinit_obj, wiznet_pio_spi_obj_deinit); + +//| def __enter__(self) -> SPI: +//| """No-op used by Context Managers. +//| Provided by context manager helper.""" +//| ... +//| + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + +static void check_lock(wiznet_pio_spi_obj_t *self) { + asm (""); + if (!common_hal_wiznet_pio_spi_has_lock(self)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Function requires lock")); + } +} + +static void check_for_deinit(wiznet_pio_spi_obj_t *self) { + if (common_hal_wiznet_pio_spi_deinited(self)) { + raise_deinited_error(); + } +} + +//| def configure( +//| self, *, baudrate: int = 100000, polarity: int = 0, phase: int = 0, bits: int = 8 +//| ) -> None: +//| """Configures the SPI bus. The SPI object must be locked. +//| +//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower +//| due to the granularity of available clock settings. +//| Check the `frequency` attribute for the actual clock rate. +//| :param int polarity: the base state of the clock line (0 or 1) +//| :param int phase: the edge of the clock that data is captured. First (0) +//| or second (1). Rising or falling depends on clock polarity. +//| :param int bits: the number of bits per word +//| +//| .. note:: On the SAMD21, it is possible to set the baudrate to 24 MHz, but that +//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is +//| within spec for the SAMD21. +//| +//| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz, +//| and 8MHz. +//| If you pick a a baudrate other than one of these, the nearest lower +//| baudrate will be chosen, with a minimum of 125kHz. +//| Two SPI objects may be created, except on the Circuit Playground Bluefruit, +//| which allows only one (to allow for an additional I2C object).""" +//| ... +//| + +static mp_obj_t wiznet_pio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + }; + wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + check_lock(self); + 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); + + uint8_t polarity = (uint8_t)mp_arg_validate_int_range(args[ARG_polarity].u_int, 0, 1, MP_QSTR_polarity); + uint8_t phase = (uint8_t)mp_arg_validate_int_range(args[ARG_phase].u_int, 0, 1, MP_QSTR_phase); + uint8_t bits = (uint8_t)mp_arg_validate_int_range(args[ARG_bits].u_int, 8, 9, MP_QSTR_bits); + + if (!common_hal_wiznet_pio_spi_configure(self, args[ARG_baudrate].u_int, + polarity, phase, bits)) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_configure_obj, 1, wiznet_pio_spi_configure); + +//| def try_lock(self) -> bool: +//| """Attempts to grab the SPI lock. Returns True on success. +//| +//| :return: True when lock has been grabbed +//| :rtype: bool""" +//| ... +//| + +static mp_obj_t wiznet_pio_spi_obj_try_lock(mp_obj_t self_in) { + wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_wiznet_pio_spi_try_lock(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_try_lock_obj, wiznet_pio_spi_obj_try_lock); + +//| def unlock(self) -> None: +//| """Releases the SPI lock.""" +//| ... +//| + +static mp_obj_t wiznet_pio_spi_obj_unlock(mp_obj_t self_in) { + wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_wiznet_pio_spi_unlock(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_unlock_obj, wiznet_pio_spi_obj_unlock); + +//| import sys +//| +//| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: int = sys.maxsize) -> None: +//| """Write the data contained in ``buffer``. The SPI object must be locked. +//| If the buffer is empty, nothing happens. +//| +//| If ``start`` or ``end`` is provided, then the buffer will be sliced +//| as if ``buffer[start:end]`` were passed, but without copying the data. +//| The number of bytes written will be the length of ``buffer[start:end]``. +//| +//| :param ReadableBuffer buffer: write out bytes from this buffer +//| :param int start: beginning of buffer slice +//| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` +//| """ +//| ... +//| + +static mp_obj_t wiznet_pio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer, ARG_start, ARG_end }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + }; + + wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + check_lock(self); + 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); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); + // Compute bounds in terms of elements, not bytes. + int stride_in_bytes = mp_binary_get_size('@', bufinfo.typecode, NULL); + int32_t start = args[ARG_start].u_int; + size_t length = bufinfo.len / stride_in_bytes; + normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + + // Treat start and length in terms of bytes from now on. + start *= stride_in_bytes; + length *= stride_in_bytes; + + if (length == 0) { + return mp_const_none; + } + + bool ok = common_hal_wiznet_pio_spi_write(self, ((uint8_t *)bufinfo.buf) + start, length); + + if (!ok) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_write_obj, 1, wiznet_pio_spi_write); + + +//| import sys +//| +//| def readinto( +//| self, +//| buffer: WriteableBuffer, +//| *, +//| start: int = 0, +//| end: int = sys.maxsize, +//| write_value: int = 0, +//| ) -> None: +//| """Read into ``buffer`` while writing ``write_value`` for each byte read. +//| The SPI object must be locked. +//| If the number of bytes to read is 0, nothing happens. +//| +//| If ``start`` or ``end`` is provided, then the buffer will be sliced +//| as if ``buffer[start:end]`` were passed. +//| The number of bytes read will be the length of ``buffer[start:end]``. +//| +//| :param WriteableBuffer buffer: read bytes into this buffer +//| :param int start: beginning of buffer slice +//| :param int end: end of buffer slice; if not specified, it will be the equivalent value +//| of ``len(buffer)`` and for any value provided it will take the value of +//| ``min(end, len(buffer))`` +//| :param int write_value: value to write while reading +//| """ +//| ... +//| + +static mp_obj_t wiznet_pio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + { MP_QSTR_write_value, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + check_lock(self); + 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); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE); + // Compute bounds in terms of elements, not bytes. + int stride_in_bytes = mp_binary_get_size('@', bufinfo.typecode, NULL); + int32_t start = args[ARG_start].u_int; + size_t length = bufinfo.len / stride_in_bytes; + normalize_buffer_bounds(&start, args[ARG_end].u_int, &length); + + // Treat start and length in terms of bytes from now on. + start *= stride_in_bytes; + length *= stride_in_bytes; + + if (length == 0) { + return mp_const_none; + } + + bool ok = common_hal_wiznet_pio_spi_read(self, ((uint8_t *)bufinfo.buf) + start, length, args[ARG_write_value].u_int); + if (!ok) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_readinto_obj, 1, wiznet_pio_spi_readinto); + +//| import sys +//| +//| def write_readinto( +//| self, +//| out_buffer: ReadableBuffer, +//| in_buffer: WriteableBuffer, +//| *, +//| out_start: int = 0, +//| out_end: int = sys.maxsize, +//| in_start: int = 0, +//| in_end: int = sys.maxsize, +//| ) -> None: +//| """Write out the data in ``out_buffer`` while simultaneously reading data into ``in_buffer``. +//| The SPI object must be locked. +//| +//| If ``out_start`` or ``out_end`` is provided, then the buffer will be sliced +//| as if ``out_buffer[out_start:out_end]`` were passed, but without copying the data. +//| The number of bytes written will be the length of ``out_buffer[out_start:out_end]``. +//| +//| If ``in_start`` or ``in_end`` is provided, then the input buffer will be sliced +//| as if ``in_buffer[in_start:in_end]`` were passed, +//| The number of bytes read will be the length of ``out_buffer[in_start:in_end]``. +//| +//| The lengths of the slices defined by ``out_buffer[out_start:out_end]`` +//| and ``in_buffer[in_start:in_end]`` must be equal. +//| If buffer slice lengths are both 0, nothing happens. +//| +//| :param ReadableBuffer out_buffer: write out bytes from this buffer +//| :param WriteableBuffer in_buffer: read bytes into this buffer +//| :param int out_start: beginning of ``out_buffer`` slice +//| :param int out_end: end of ``out_buffer`` slice; if not specified, use ``len(out_buffer)`` +//| :param int in_start: beginning of ``in_buffer`` slice +//| :param int in_end: end of ``in_buffer slice``; if not specified, use ``len(in_buffer)`` +//| """ +//| ... +//| + +static mp_obj_t wiznet_pio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, + }; + wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + check_lock(self); + 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); + + mp_buffer_info_t buf_out_info; + mp_get_buffer_raise(args[ARG_out_buffer].u_obj, &buf_out_info, MP_BUFFER_READ); + int out_stride_in_bytes = mp_binary_get_size('@', buf_out_info.typecode, NULL); + int32_t out_start = args[ARG_out_start].u_int; + size_t out_length = buf_out_info.len / out_stride_in_bytes; + normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length); + + mp_buffer_info_t buf_in_info; + mp_get_buffer_raise(args[ARG_in_buffer].u_obj, &buf_in_info, MP_BUFFER_WRITE); + int in_stride_in_bytes = mp_binary_get_size('@', buf_in_info.typecode, NULL); + int32_t in_start = args[ARG_in_start].u_int; + size_t in_length = buf_in_info.len / in_stride_in_bytes; + normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length); + + // Treat start and length in terms of bytes from now on. + out_start *= out_stride_in_bytes; + out_length *= out_stride_in_bytes; + in_start *= in_stride_in_bytes; + in_length *= in_stride_in_bytes; + + if (out_length != in_length) { + mp_raise_ValueError(MP_ERROR_TEXT("buffer slices must be of equal length")); + } + + if (out_length == 0) { + return mp_const_none; + } + + bool ok = common_hal_wiznet_pio_spi_transfer(self, + ((uint8_t *)buf_out_info.buf) + out_start, + ((uint8_t *)buf_in_info.buf) + in_start, + out_length); + if (!ok) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_write_readinto_obj, 1, wiznet_pio_spi_write_readinto); + +//| frequency: int +//| """The actual SPI bus frequency. This may not match the frequency requested +//| due to internal limitations.""" +//| +//| + +#endif // CIRCUITPY_WIZNET_PIO_SPI + +static const mp_rom_map_elem_t wiznet_pio_spi_locals_dict_table[] = { + #if CIRCUITPY_WIZNET_PIO_SPI + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&wiznet_pio_spi_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + + { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&wiznet_pio_spi_configure_obj) }, + { MP_ROM_QSTR(MP_QSTR_try_lock), MP_ROM_PTR(&wiznet_pio_spi_try_lock_obj) }, + { MP_ROM_QSTR(MP_QSTR_unlock), MP_ROM_PTR(&wiznet_pio_spi_unlock_obj) }, + + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&wiznet_pio_spi_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&wiznet_pio_spi_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&wiznet_pio_spi_write_readinto_obj) }, + + #endif // CIRCUITPY_WIZNET_PIO_SPI +}; +static MP_DEFINE_CONST_DICT(wiznet_pio_spi_locals_dict, wiznet_pio_spi_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + busio_wiznet_pio_spi_type, + MP_QSTR_WIZNET_PIO_SPI, + MP_TYPE_FLAG_NONE, + make_new, wiznet_pio_spi_make_new, + locals_dict, &wiznet_pio_spi_locals_dict +); + +wiznet_pio_spi_obj_t *validate_obj_is_wiznet_pio_spi_bus(mp_obj_t obj, qstr arg_name) { + return mp_arg_validate_type(obj, &busio_wiznet_pio_spi_type, arg_name); +} diff --git a/shared-bindings/busio/WIZNET_PIO_SPI.h b/shared-bindings/busio/WIZNET_PIO_SPI.h new file mode 100755 index 0000000000000..2196d1e48141c --- /dev/null +++ b/shared-bindings/busio/WIZNET_PIO_SPI.h @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/busio/WIZNET_PIO_SPI.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t busio_wiznet_pio_spi_type; + +// Construct an underlying SPI object. +extern void common_hal_wiznet_pio_spi_construct(wiznet_pio_spi_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso, bool half_duplex); + +extern void common_hal_wiznet_pio_spi_deinit(wiznet_pio_spi_obj_t *self); +extern bool common_hal_wiznet_pio_spi_deinited(wiznet_pio_spi_obj_t *self); + +extern bool common_hal_wiznet_pio_spi_configure(wiznet_pio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits); + +extern bool common_hal_wiznet_pio_spi_try_lock(wiznet_pio_spi_obj_t *self); +extern bool common_hal_wiznet_pio_spi_has_lock(wiznet_pio_spi_obj_t *self); +extern void common_hal_wiznet_pio_spi_unlock(wiznet_pio_spi_obj_t *self); + +// Writes out the given data. +extern bool common_hal_wiznet_pio_spi_write(wiznet_pio_spi_obj_t *self, const uint8_t *data, size_t len); + +// Reads in len bytes while outputting the byte write_value. +extern bool common_hal_wiznet_pio_spi_read(wiznet_pio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value); + +// Reads and write len bytes simultaneously. +extern bool common_hal_wiznet_pio_spi_transfer(wiznet_pio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len); + +extern wiznet_pio_spi_obj_t *validate_obj_is_wiznet_pio_spi_bus(mp_obj_t obj_in, qstr arg_name); diff --git a/shared-bindings/busio/__init__.c b/shared-bindings/busio/__init__.c old mode 100644 new mode 100755 index 028d73d9c368f..b4e3dff7447b1 --- a/shared-bindings/busio/__init__.c +++ b/shared-bindings/busio/__init__.c @@ -15,6 +15,10 @@ #include "shared-bindings/busio/SPI.h" #include "shared-bindings/busio/UART.h" +#if CIRCUITPY_WIZNET_PIO_SPI +#include "shared-bindings/busio/WIZNET_PIO_SPI.h" +#endif + #include "py/runtime.h" //| """Hardware accelerated external bus access @@ -69,6 +73,9 @@ static const mp_rom_map_elem_t busio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&busio_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&busio_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&busio_uart_type) }, +#if CIRCUITPY_WIZNET_PIO_SPI + { MP_ROM_QSTR(MP_QSTR_WIZNET_PIO_SPI), MP_ROM_PTR(&busio_wiznet_pio_spi_type) }, +#endif }; static MP_DEFINE_CONST_DICT(busio_module_globals, busio_module_globals_table); From a5864a1b73678fc18b070176ef2266353cc8a01c Mon Sep 17 00:00:00 2001 From: hannah Date: Tue, 24 Jun 2025 07:07:48 +0000 Subject: [PATCH 3/7] Fix undefined reference to 'busio_wiznet_pio_spi_type' and clean up code --- .../wiznet_w55rp20_evb_pico/mpconfigboard.mk | 2 +- .../common-hal/busio/WIZNET_PIO_SPI.c | 4 +- .../common-hal/busio/WIZNET_PIO_SPI.h | 2 +- .../wiznet_pio_spi/wizchip_pio_spi.c | 2 +- .../wiznet_pio_spi/wizchip_pio_spi.pio | 2 +- py/circuitpy_defns.mk | 6 +- shared-bindings/busio/WIZNET_PIO_SPI.c | 225 ++---------------- shared-bindings/busio/__init__.c | 4 +- 8 files changed, 32 insertions(+), 215 deletions(-) diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk index 6045e5c898677..a6371ece1cff8 100755 --- a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk @@ -11,4 +11,4 @@ EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY_WIZNET_PIO_SPI = 1 CIRCUITPY__EVE = 1 CIRCUITPY_SSL = 1 -CIRCUITPY_USB_HOST = 0 \ No newline at end of file +CIRCUITPY_USB_HOST = 0 diff --git a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c index a90646e47aaa1..41f08c4480c80 100755 --- a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c +++ b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c @@ -89,7 +89,7 @@ bool common_hal_wiznet_pio_spi_try_lock(wiznet_pio_spi_obj_t *self) { if (common_hal_wiznet_pio_spi_deinited(self)) { return false; } - + bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; @@ -120,4 +120,4 @@ bool common_hal_wiznet_pio_spi_read(wiznet_pio_spi_obj_t *self, bool common_hal_wiznet_pio_spi_transfer(wiznet_pio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) { return wiznet_pio_spi_transfer(data_out, len, data_in, len); -} \ No newline at end of file +} diff --git a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h index 29d077b4341e1..6fcfb452cce47 100755 --- a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h +++ b/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h @@ -22,4 +22,4 @@ typedef struct { const mcu_pin_obj_t *MISO; } wiznet_pio_spi_obj_t; -void reset_spi(void); \ No newline at end of file +void reset_spi(void); diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c index 564dd9191b0b7..ca68a0cc3727c 100755 --- a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c +++ b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c @@ -351,7 +351,7 @@ void wiznet_pio_spi_write_buffer(const uint8_t *pBuf, uint16_t len) { assert(active_state->spi_header_count == 0); if (!wiznet_pio_spi_transfer(pBuf, len, NULL, 0)) { panic("spi failed writing buffer"); - } + } } } diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio index 092a2b589a7d1..97a1c5b73d4ff 100755 --- a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio +++ b/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio @@ -21,4 +21,4 @@ read_bits: jmp x-- read_bits side 1 in pins, 1 side 0 jmp y-- read_byte side 0 -public read_end: \ No newline at end of file +public read_end: diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index de9703811c73c..571e45541921e 100755 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -460,7 +460,7 @@ ifeq ($(CIRCUITPY_WIFI),1) SRC_PATTERNS += wifi/% endif ifeq ($(CIRCUITPY_WIZNET_PIO_SPI),1) -SRC_PATTERNS += busio/WIZNET_PIO_SPI.c busio/WIZNET_PIO_SPI.h +SRC_PATTERNS += busio/WIZNET_PIO_SPI.c endif ifeq ($(CIRCUITPY_ZLIB),1) SRC_PATTERNS += zlib/% @@ -849,6 +849,10 @@ SRC_SHARED_MODULE_ALL += \ ssl/SSLSocket.c endif +ifeq ($(CIRCUITPY_WIZNET_PIO_SPI),1) +SRC_COMMON_HAL_ALL += busio/WIZNET_PIO_SPI.c +endif + ifeq ($(CIRCUITPY_KEYPAD_DEMUX),1) SRC_SHARED_MODULE_ALL += \ keypad_demux/__init__.c \ diff --git a/shared-bindings/busio/WIZNET_PIO_SPI.c b/shared-bindings/busio/WIZNET_PIO_SPI.c index 81a74f933d011..68dc53f5d6dc4 100755 --- a/shared-bindings/busio/WIZNET_PIO_SPI.c +++ b/shared-bindings/busio/WIZNET_PIO_SPI.c @@ -4,8 +4,9 @@ // // SPDX-License-Identifier: MIT +//TODO: busio.WIZNET_PIO_SPI class. // This file contains all of the Python API definitions for the -// busio.SPI class. +// busio.WIZNET_PIO_SPI class. #include @@ -20,73 +21,10 @@ #include "py/objproperty.h" #include "py/runtime.h" -#include - - -//| class SPI: -//| """A 3-4 wire serial protocol -//| -//| SPI is a serial protocol that has exclusive pins for data in and out of the -//| main device. It is typically faster than :py:class:`~bitbangio.I2C` because a -//| separate pin is used to select a device rather than a transmitted -//| address. This class only manages three of the four SPI lines: `!clock`, -//| `!MOSI`, `!MISO`. It is up to the client to manage the appropriate -//| select line, often abbreviated `!CS` or `!SS`. (This is common because -//| multiple secondaries can share the `!clock`, `!MOSI` and `!MISO` lines -//| and therefore the hardware.) -//| -//| .. raw:: html -//| -//|

-//|

-//| Available on these boards -//|
    -//| {% for board in support_matrix_reverse["busio.SPI"] %} -//|
  • {{ board }} -//| {% endfor %} -//|
-//|
-//|

-//| -//| .. seealso:: This class acts as an SPI main (controller). -//| To act as an SPI secondary (target), use `spitarget.SPITarget`. -//| """ -//| -//| def __init__( -//| self, -//| clock: microcontroller.Pin, -//| MOSI: Optional[microcontroller.Pin] = None, -//| MISO: Optional[microcontroller.Pin] = None, -//| half_duplex: bool = False, -//| ) -> None: -//| """Construct an SPI object on the given pins. -//| -//| .. note:: The SPI peripherals allocated in order of desirability, if possible, -//| such as highest speed and not shared use first. For instance, on the nRF52840, -//| there is a single 32MHz SPI peripheral, and multiple 8MHz peripherals, -//| some of which may also be used for I2C. The 32MHz SPI peripheral is returned -//| first, then the exclusive 8MHz SPI peripheral, and finally the shared 8MHz -//| peripherals. -//| -//| .. seealso:: Using this class directly requires careful lock management. -//| Instead, use :class:`~adafruit_bus_device.SPIDevice` to -//| manage locks. -//| -//| .. seealso:: Using this class to directly read registers requires manual -//| bit unpacking. Instead, use an existing driver or make one with -//| :ref:`Register ` data descriptors. -//| -//| :param ~microcontroller.Pin clock: the pin to use for the clock. -//| :param ~microcontroller.Pin MOSI: the Main Out Selected In pin. -//| :param ~microcontroller.Pin MISO: the Main In Selected Out pin. -//| :param bool half_duplex: True when MOSI is used for bidirectional data. False when SPI is full-duplex or simplex. -//| -//| **Limitations:** ``half_duplex`` is available only on STM; other chips do not have the hardware support. -//| """ -//| ... -//| - -// TODO(tannewt): Support LSB SPI. + +//TODO: class WIZNET_PIO_SPI + + static mp_obj_t wiznet_pio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_WIZNET_PIO_SPI wiznet_pio_spi_obj_t *self = mp_obj_malloc(wiznet_pio_spi_obj_t, &busio_wiznet_pio_spi_type); @@ -116,10 +54,9 @@ static mp_obj_t wiznet_pio_spi_make_new(const mp_obj_type_t *type, size_t n_args } #if CIRCUITPY_WIZNET_PIO_SPI -//| def deinit(self) -> None: -//| """Turn off the SPI bus.""" -//| ... -//| + +// TODO: def deinit + static mp_obj_t wiznet_pio_spi_obj_deinit(mp_obj_t self_in) { wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_wiznet_pio_spi_deinit(self); @@ -127,18 +64,9 @@ static mp_obj_t wiznet_pio_spi_obj_deinit(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_deinit_obj, wiznet_pio_spi_obj_deinit); -//| def __enter__(self) -> SPI: -//| """No-op used by Context Managers. -//| Provided by context manager helper.""" -//| ... -//| +// TODO: def __enter__ -//| def __exit__(self) -> None: -//| """Automatically deinitializes the hardware when exiting a context. See -//| :ref:`lifetime-and-contextmanagers` for more info.""" -//| ... -//| -// Provided by context manager helper. +// TODO: def __exit__ static void check_lock(wiznet_pio_spi_obj_t *self) { asm (""); @@ -153,31 +81,7 @@ static void check_for_deinit(wiznet_pio_spi_obj_t *self) { } } -//| def configure( -//| self, *, baudrate: int = 100000, polarity: int = 0, phase: int = 0, bits: int = 8 -//| ) -> None: -//| """Configures the SPI bus. The SPI object must be locked. -//| -//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower -//| due to the granularity of available clock settings. -//| Check the `frequency` attribute for the actual clock rate. -//| :param int polarity: the base state of the clock line (0 or 1) -//| :param int phase: the edge of the clock that data is captured. First (0) -//| or second (1). Rising or falling depends on clock polarity. -//| :param int bits: the number of bits per word -//| -//| .. note:: On the SAMD21, it is possible to set the baudrate to 24 MHz, but that -//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is -//| within spec for the SAMD21. -//| -//| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz, -//| and 8MHz. -//| If you pick a a baudrate other than one of these, the nearest lower -//| baudrate will be chosen, with a minimum of 125kHz. -//| Two SPI objects may be created, except on the Circuit Playground Bluefruit, -//| which allows only one (to allow for an additional I2C object).""" -//| ... -//| +// TODO: def configure static mp_obj_t wiznet_pio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; @@ -205,13 +109,7 @@ static mp_obj_t wiznet_pio_spi_configure(size_t n_args, const mp_obj_t *pos_args } MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_configure_obj, 1, wiznet_pio_spi_configure); -//| def try_lock(self) -> bool: -//| """Attempts to grab the SPI lock. Returns True on success. -//| -//| :return: True when lock has been grabbed -//| :rtype: bool""" -//| ... -//| +// TODO: def try_lock static mp_obj_t wiznet_pio_spi_obj_try_lock(mp_obj_t self_in) { wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -219,10 +117,7 @@ static mp_obj_t wiznet_pio_spi_obj_try_lock(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_try_lock_obj, wiznet_pio_spi_obj_try_lock); -//| def unlock(self) -> None: -//| """Releases the SPI lock.""" -//| ... -//| +// TODO: def unlock static mp_obj_t wiznet_pio_spi_obj_unlock(mp_obj_t self_in) { wiznet_pio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -232,22 +127,7 @@ static mp_obj_t wiznet_pio_spi_obj_unlock(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(wiznet_pio_spi_unlock_obj, wiznet_pio_spi_obj_unlock); -//| import sys -//| -//| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: int = sys.maxsize) -> None: -//| """Write the data contained in ``buffer``. The SPI object must be locked. -//| If the buffer is empty, nothing happens. -//| -//| If ``start`` or ``end`` is provided, then the buffer will be sliced -//| as if ``buffer[start:end]`` were passed, but without copying the data. -//| The number of bytes written will be the length of ``buffer[start:end]``. -//| -//| :param ReadableBuffer buffer: write out bytes from this buffer -//| :param int start: beginning of buffer slice -//| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` -//| """ -//| ... -//| +// TODO: def write static mp_obj_t wiznet_pio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; @@ -280,7 +160,7 @@ static mp_obj_t wiznet_pio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp } bool ok = common_hal_wiznet_pio_spi_write(self, ((uint8_t *)bufinfo.buf) + start, length); - + if (!ok) { mp_raise_OSError(MP_EIO); } @@ -288,34 +168,7 @@ static mp_obj_t wiznet_pio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp } MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_write_obj, 1, wiznet_pio_spi_write); - -//| import sys -//| -//| def readinto( -//| self, -//| buffer: WriteableBuffer, -//| *, -//| start: int = 0, -//| end: int = sys.maxsize, -//| write_value: int = 0, -//| ) -> None: -//| """Read into ``buffer`` while writing ``write_value`` for each byte read. -//| The SPI object must be locked. -//| If the number of bytes to read is 0, nothing happens. -//| -//| If ``start`` or ``end`` is provided, then the buffer will be sliced -//| as if ``buffer[start:end]`` were passed. -//| The number of bytes read will be the length of ``buffer[start:end]``. -//| -//| :param WriteableBuffer buffer: read bytes into this buffer -//| :param int start: beginning of buffer slice -//| :param int end: end of buffer slice; if not specified, it will be the equivalent value -//| of ``len(buffer)`` and for any value provided it will take the value of -//| ``min(end, len(buffer))`` -//| :param int write_value: value to write while reading -//| """ -//| ... -//| +// TODO: def readinto static mp_obj_t wiznet_pio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value }; @@ -355,42 +208,8 @@ static mp_obj_t wiznet_pio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, } MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_readinto_obj, 1, wiznet_pio_spi_readinto); -//| import sys -//| -//| def write_readinto( -//| self, -//| out_buffer: ReadableBuffer, -//| in_buffer: WriteableBuffer, -//| *, -//| out_start: int = 0, -//| out_end: int = sys.maxsize, -//| in_start: int = 0, -//| in_end: int = sys.maxsize, -//| ) -> None: -//| """Write out the data in ``out_buffer`` while simultaneously reading data into ``in_buffer``. -//| The SPI object must be locked. -//| -//| If ``out_start`` or ``out_end`` is provided, then the buffer will be sliced -//| as if ``out_buffer[out_start:out_end]`` were passed, but without copying the data. -//| The number of bytes written will be the length of ``out_buffer[out_start:out_end]``. -//| -//| If ``in_start`` or ``in_end`` is provided, then the input buffer will be sliced -//| as if ``in_buffer[in_start:in_end]`` were passed, -//| The number of bytes read will be the length of ``out_buffer[in_start:in_end]``. -//| -//| The lengths of the slices defined by ``out_buffer[out_start:out_end]`` -//| and ``in_buffer[in_start:in_end]`` must be equal. -//| If buffer slice lengths are both 0, nothing happens. -//| -//| :param ReadableBuffer out_buffer: write out bytes from this buffer -//| :param WriteableBuffer in_buffer: read bytes into this buffer -//| :param int out_start: beginning of ``out_buffer`` slice -//| :param int out_end: end of ``out_buffer`` slice; if not specified, use ``len(out_buffer)`` -//| :param int in_start: beginning of ``in_buffer`` slice -//| :param int in_end: end of ``in_buffer slice``; if not specified, use ``len(in_buffer)`` -//| """ -//| ... -//| + +// TODO: def write_readinto static mp_obj_t wiznet_pio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; @@ -447,12 +266,6 @@ static mp_obj_t wiznet_pio_spi_write_readinto(size_t n_args, const mp_obj_t *pos } MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_write_readinto_obj, 1, wiznet_pio_spi_write_readinto); -//| frequency: int -//| """The actual SPI bus frequency. This may not match the frequency requested -//| due to internal limitations.""" -//| -//| - #endif // CIRCUITPY_WIZNET_PIO_SPI static const mp_rom_map_elem_t wiznet_pio_spi_locals_dict_table[] = { diff --git a/shared-bindings/busio/__init__.c b/shared-bindings/busio/__init__.c index b4e3dff7447b1..46386faef0a0c 100755 --- a/shared-bindings/busio/__init__.c +++ b/shared-bindings/busio/__init__.c @@ -73,9 +73,9 @@ static const mp_rom_map_elem_t busio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&busio_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&busio_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&busio_uart_type) }, -#if CIRCUITPY_WIZNET_PIO_SPI + #if CIRCUITPY_WIZNET_PIO_SPI { MP_ROM_QSTR(MP_QSTR_WIZNET_PIO_SPI), MP_ROM_PTR(&busio_wiznet_pio_spi_type) }, -#endif + #endif }; static MP_DEFINE_CONST_DICT(busio_module_globals, busio_module_globals_table); From 7aa13ed1b71f6ae861ee0d087199e820192d16fb Mon Sep 17 00:00:00 2001 From: hannah Date: Mon, 14 Jul 2025 04:59:15 +0000 Subject: [PATCH 4/7] Restructure: Move Wiznet PIO SPI code to new wiznet module --- data/nvm.toml | 2 +- ports/raspberrypi/Makefile | 27 +++++++++-------- .../raspberrypi/bindings/wiznet/PIO_SPI.c | 22 +++++++------- .../raspberrypi/bindings/wiznet/PIO_SPI.h | 4 +-- ports/raspberrypi/bindings/wiznet/__init__.c | 29 +++++++++++++++++++ ports/raspberrypi/bindings/wiznet/__init__.h | 7 +++++ .../wiznet_w55rp20_evb_pico/mpconfigboard.mk | 4 +-- .../WIZNET_PIO_SPI.c => wiznet/PIO_SPI.c} | 4 +-- .../WIZNET_PIO_SPI.h => wiznet/PIO_SPI.h} | 0 .../raspberrypi/common-hal/wiznet/__init__.c | 7 +++++ .../wiznet}/wizchip_pio_spi.c | 2 +- .../wiznet}/wizchip_pio_spi.h | 0 .../wiznet}/wizchip_pio_spi.pio | 0 py/circuitpy_defns.mk | 8 ++--- py/circuitpy_mpconfig.mk | 6 ++-- shared-bindings/busio/__init__.c | 7 ----- 16 files changed, 82 insertions(+), 47 deletions(-) rename shared-bindings/busio/WIZNET_PIO_SPI.c => ports/raspberrypi/bindings/wiznet/PIO_SPI.c (96%) rename shared-bindings/busio/WIZNET_PIO_SPI.h => ports/raspberrypi/bindings/wiznet/PIO_SPI.h (94%) create mode 100755 ports/raspberrypi/bindings/wiznet/__init__.c create mode 100755 ports/raspberrypi/bindings/wiznet/__init__.h rename ports/raspberrypi/common-hal/{busio/WIZNET_PIO_SPI.c => wiznet/PIO_SPI.c} (97%) rename ports/raspberrypi/common-hal/{busio/WIZNET_PIO_SPI.h => wiznet/PIO_SPI.h} (100%) create mode 100755 ports/raspberrypi/common-hal/wiznet/__init__.c rename ports/raspberrypi/{wiznet_pio_spi => common-hal/wiznet}/wizchip_pio_spi.c (99%) rename ports/raspberrypi/{wiznet_pio_spi => common-hal/wiznet}/wizchip_pio_spi.h (100%) rename ports/raspberrypi/{wiznet_pio_spi => common-hal/wiznet}/wizchip_pio_spi.pio (100%) diff --git a/data/nvm.toml b/data/nvm.toml index 8bca037b052a4..3f3921f351ab2 160000 --- a/data/nvm.toml +++ b/data/nvm.toml @@ -1 +1 @@ -Subproject commit 8bca037b052a4a4dc46a56a25a1b802652ee3f47 +Subproject commit 3f3921f351ab206e729ad965c857b80a7ece8198 diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index e1f17adb402b9..91de903e22e04 100755 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -83,13 +83,13 @@ SRC_CYW43 := SRC_LWIP := endif -ifeq ($(CIRCUITPY_WIZNET_PIO_SPI), 1) -INC_WIZNET_PIO_SPI := \ - -isystem wiznet_pio_spi \ - -SRC_WIZNET_PIO_SPI := \ - wiznet_pio_spi/wizchip_pio_spi.c \ +ifeq ($(CIRCUITPY_WIZNET), 1) +INC_WIZNET := \ + -isystem common-hal/wiznet \ +SRC_WIZNET := \ + common-hal/wiznet/wizchip_pio_spi.c \ + WIZNET_PIOASM = $(BUILD)/pioasm/pioasm/pioasm .PHONY: pioasmBuild pioasmBuild: $(WIZNET_PIOASM) @@ -98,15 +98,15 @@ $(WIZNET_PIOASM): $(Q)cmake -S pioasm -B $(BUILD)/pioasm $(MAKE) -C $(BUILD)/pioasm pioasmBuild -$(BUILD)/wizchip_pio_spi.pio.h: wiznet_pio_spi/wizchip_pio_spi.pio $(WIZNET_PIOASM) +$(BUILD)/wizchip_pio_spi.pio.h: common-hal/wiznet/wizchip_pio_spi.pio $(WIZNET_PIOASM) $(Q)$(WIZNET_PIOASM) -o c-sdk $< $@ -$(BUILD)/wiznet_pio_spi/wizchip_pio_spi.o: $(BUILD)/wizchip_pio_spi.pio.h +$(BUILD)/common-hal/wiznet/wizchip_pio_spi.o: $(BUILD)/wizchip_pio_spi.pio.h $(BUILD)/genhdr/qstr.i.last: $(BUILD)/wizchip_pio_spi.pio.h else -INC_WIZNET_PIO_SPI := -SRC_WIZNET_PIO_SPI := +INC_WIZNET := +SRC_WIZNET := endif @@ -182,7 +182,6 @@ INC += \ -isystem sdk/src/rp2_common/pico_time_adapter/include/ \ -isystem sdk/src/rp2_common/pico_unique_id/include/ \ $(INC_CYW43) \ - $(INC_WIZNET_PIO_SPI) \ -Isdk_config \ -I../../lib/tinyusb/src \ -I../../supervisor/shared/usb \ @@ -560,6 +559,10 @@ SRC_C += \ bindings/rp2pio/__init__.c \ common-hal/rp2pio/StateMachine.c \ common-hal/rp2pio/__init__.c \ + bindings/wiznet/PIO_SPI.c \ + bindings/wiznet/__init__.c \ + common-hal/wiznet/PIO_SPI.c \ + common-hal/wiznet/__init__.c \ audio_dma.c \ background.c \ peripherals/pins.c \ @@ -569,7 +572,7 @@ SRC_C += \ mphalport.c \ $(SRC_CYW43) \ $(SRC_LWIP) \ - $(SRC_WIZNET_PIO_SPI) \ + $(SRC_WIZNET) \ ifeq ($(CIRCUITPY_USB_HOST), 1) diff --git a/shared-bindings/busio/WIZNET_PIO_SPI.c b/ports/raspberrypi/bindings/wiznet/PIO_SPI.c similarity index 96% rename from shared-bindings/busio/WIZNET_PIO_SPI.c rename to ports/raspberrypi/bindings/wiznet/PIO_SPI.c index 68dc53f5d6dc4..f628ca868b8f8 100755 --- a/shared-bindings/busio/WIZNET_PIO_SPI.c +++ b/ports/raspberrypi/bindings/wiznet/PIO_SPI.c @@ -11,7 +11,7 @@ #include #include "shared-bindings/microcontroller/Pin.h" -#include "shared-bindings/busio/WIZNET_PIO_SPI.h" +#include "bindings/wiznet/PIO_SPI.h" #include "shared-bindings/util.h" #include "shared/runtime/buffer_helper.h" @@ -26,8 +26,8 @@ static mp_obj_t wiznet_pio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - #if CIRCUITPY_WIZNET_PIO_SPI - wiznet_pio_spi_obj_t *self = mp_obj_malloc(wiznet_pio_spi_obj_t, &busio_wiznet_pio_spi_type); + #if CIRCUITPY_WIZNET + wiznet_pio_spi_obj_t *self = mp_obj_malloc(wiznet_pio_spi_obj_t, &wiznet_pio_spi_type); enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_half_duplex }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -50,10 +50,10 @@ static mp_obj_t wiznet_pio_spi_make_new(const mp_obj_type_t *type, size_t n_args return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError(NULL); - #endif // CIRCUITPY_WIZNET_PIO_SPI + #endif // CIRCUITPY_WIZNET } -#if CIRCUITPY_WIZNET_PIO_SPI +#if CIRCUITPY_WIZNET // TODO: def deinit @@ -266,10 +266,10 @@ static mp_obj_t wiznet_pio_spi_write_readinto(size_t n_args, const mp_obj_t *pos } MP_DEFINE_CONST_FUN_OBJ_KW(wiznet_pio_spi_write_readinto_obj, 1, wiznet_pio_spi_write_readinto); -#endif // CIRCUITPY_WIZNET_PIO_SPI +#endif // CIRCUITPY_WIZNET static const mp_rom_map_elem_t wiznet_pio_spi_locals_dict_table[] = { - #if CIRCUITPY_WIZNET_PIO_SPI + #if CIRCUITPY_WIZNET { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&wiznet_pio_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, @@ -282,18 +282,18 @@ static const mp_rom_map_elem_t wiznet_pio_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&wiznet_pio_spi_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&wiznet_pio_spi_write_readinto_obj) }, - #endif // CIRCUITPY_WIZNET_PIO_SPI + #endif // CIRCUITPY_WIZNET }; static MP_DEFINE_CONST_DICT(wiznet_pio_spi_locals_dict, wiznet_pio_spi_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( - busio_wiznet_pio_spi_type, - MP_QSTR_WIZNET_PIO_SPI, + wiznet_pio_spi_type, + MP_QSTR_PIO_SPI, MP_TYPE_FLAG_NONE, make_new, wiznet_pio_spi_make_new, locals_dict, &wiznet_pio_spi_locals_dict ); wiznet_pio_spi_obj_t *validate_obj_is_wiznet_pio_spi_bus(mp_obj_t obj, qstr arg_name) { - return mp_arg_validate_type(obj, &busio_wiznet_pio_spi_type, arg_name); + return mp_arg_validate_type(obj, &wiznet_pio_spi_type, arg_name); } diff --git a/shared-bindings/busio/WIZNET_PIO_SPI.h b/ports/raspberrypi/bindings/wiznet/PIO_SPI.h similarity index 94% rename from shared-bindings/busio/WIZNET_PIO_SPI.h rename to ports/raspberrypi/bindings/wiznet/PIO_SPI.h index 2196d1e48141c..0289ac0767a24 100755 --- a/shared-bindings/busio/WIZNET_PIO_SPI.h +++ b/ports/raspberrypi/bindings/wiznet/PIO_SPI.h @@ -9,10 +9,10 @@ #include "py/obj.h" #include "common-hal/microcontroller/Pin.h" -#include "common-hal/busio/WIZNET_PIO_SPI.h" +#include "common-hal/wiznet/PIO_SPI.h" // Type object used in Python. Should be shared between ports. -extern const mp_obj_type_t busio_wiznet_pio_spi_type; +extern const mp_obj_type_t wiznet_pio_spi_type; // Construct an underlying SPI object. extern void common_hal_wiznet_pio_spi_construct(wiznet_pio_spi_obj_t *self, diff --git a/ports/raspberrypi/bindings/wiznet/__init__.c b/ports/raspberrypi/bindings/wiznet/__init__.c new file mode 100755 index 0000000000000..6ed3c2886cc9d --- /dev/null +++ b/ports/raspberrypi/bindings/wiznet/__init__.c @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "bindings/wiznet/PIO_SPI.h" + +#include "py/runtime.h" + +static const mp_rom_map_elem_t wiznet_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wiznet) }, + { MP_ROM_QSTR(MP_QSTR_PIO_SPI), MP_ROM_PTR(&wiznet_pio_spi_type) }, +}; + +static MP_DEFINE_CONST_DICT(wiznet_module_globals, wiznet_module_globals_table); + +const mp_obj_module_t wiznet_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&wiznet_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_wiznet, wiznet_module); diff --git a/ports/raspberrypi/bindings/wiznet/__init__.h b/ports/raspberrypi/bindings/wiznet/__init__.h new file mode 100755 index 0000000000000..370e233985f74 --- /dev/null +++ b/ports/raspberrypi/bindings/wiznet/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk index a6371ece1cff8..5030ee88f52b2 100755 --- a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk @@ -6,9 +6,9 @@ USB_MANUFACTURER = "WIZnet" CHIP_VARIANT = RP2040 CHIP_FAMILY = rp2 -EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" +EXTERNAL_FLASH_DEVICES = "PY25Q16HB" -CIRCUITPY_WIZNET_PIO_SPI = 1 +CIRCUITPY_WIZNET = 1 CIRCUITPY__EVE = 1 CIRCUITPY_SSL = 1 CIRCUITPY_USB_HOST = 0 diff --git a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c b/ports/raspberrypi/common-hal/wiznet/PIO_SPI.c similarity index 97% rename from ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c rename to ports/raspberrypi/common-hal/wiznet/PIO_SPI.c index 41f08c4480c80..30fe8c5d25cc8 100755 --- a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.c +++ b/ports/raspberrypi/common-hal/wiznet/PIO_SPI.c @@ -4,7 +4,7 @@ // // SPDX-License-Identifier: MIT -#include "shared-bindings/busio/WIZNET_PIO_SPI.h" +#include "bindings/wiznet/PIO_SPI.h" #include "shared/runtime/interrupt_char.h" #include "py/mperrno.h" @@ -19,7 +19,7 @@ #include "hardware/pio.h" #include "hardware/clocks.h" -#include "wiznet_pio_spi/wizchip_pio_spi.h" +#include "wizchip_pio_spi.h" #define NO_INSTANCE 0xff diff --git a/ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h b/ports/raspberrypi/common-hal/wiznet/PIO_SPI.h similarity index 100% rename from ports/raspberrypi/common-hal/busio/WIZNET_PIO_SPI.h rename to ports/raspberrypi/common-hal/wiznet/PIO_SPI.h diff --git a/ports/raspberrypi/common-hal/wiznet/__init__.c b/ports/raspberrypi/common-hal/wiznet/__init__.c new file mode 100755 index 0000000000000..b3d5d23882dc8 --- /dev/null +++ b/ports/raspberrypi/common-hal/wiznet/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// No wiznet module functions. diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c b/ports/raspberrypi/common-hal/wiznet/wizchip_pio_spi.c similarity index 99% rename from ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c rename to ports/raspberrypi/common-hal/wiznet/wizchip_pio_spi.c index ca68a0cc3727c..eb04152720975 100755 --- a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.c +++ b/ports/raspberrypi/common-hal/wiznet/wizchip_pio_spi.c @@ -61,7 +61,7 @@ static void wiznet_pio_spi_gpio_setup(wiznet_pio_spi_state_t *state) { gpio_init(state->spi_config->data_out_pin); gpio_set_dir(state->spi_config->data_out_pin, GPIO_OUT); gpio_put(state->spi_config->data_out_pin, false); - + gpio_init(state->spi_config->data_in_pin); gpio_set_dir(state->spi_config->data_in_pin, GPIO_IN); diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.h b/ports/raspberrypi/common-hal/wiznet/wizchip_pio_spi.h similarity index 100% rename from ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.h rename to ports/raspberrypi/common-hal/wiznet/wizchip_pio_spi.h diff --git a/ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio b/ports/raspberrypi/common-hal/wiznet/wizchip_pio_spi.pio similarity index 100% rename from ports/raspberrypi/wiznet_pio_spi/wizchip_pio_spi.pio rename to ports/raspberrypi/common-hal/wiznet/wizchip_pio_spi.pio diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 571e45541921e..0a34e3596d3b2 100755 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -459,8 +459,8 @@ endif ifeq ($(CIRCUITPY_WIFI),1) SRC_PATTERNS += wifi/% endif -ifeq ($(CIRCUITPY_WIZNET_PIO_SPI),1) -SRC_PATTERNS += busio/WIZNET_PIO_SPI.c +ifeq ($(CIRCUITPY_WIZNET),1) +SRC_PATTERNS += wiznet/% endif ifeq ($(CIRCUITPY_ZLIB),1) SRC_PATTERNS += zlib/% @@ -849,10 +849,6 @@ SRC_SHARED_MODULE_ALL += \ ssl/SSLSocket.c endif -ifeq ($(CIRCUITPY_WIZNET_PIO_SPI),1) -SRC_COMMON_HAL_ALL += busio/WIZNET_PIO_SPI.c -endif - ifeq ($(CIRCUITPY_KEYPAD_DEMUX),1) SRC_SHARED_MODULE_ALL += \ keypad_demux/__init__.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 9fa788d6fb385..eee6c93444f9b 100755 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -206,9 +206,6 @@ CFLAGS += -DCIRCUITPY_BUSIO_SPI=$(CIRCUITPY_BUSIO_SPI) CIRCUITPY_BUSIO_UART ?= $(CIRCUITPY_BUSIO) CFLAGS += -DCIRCUITPY_BUSIO_UART=$(CIRCUITPY_BUSIO_UART) -CIRCUITPY_WIZNET_PIO_SPI ?= 0 -CFLAGS += -DCIRCUITPY_WIZNET_PIO_SPI=$(CIRCUITPY_WIZNET_PIO_SPI) - CIRCUITPY_CAMERA ?= 0 CFLAGS += -DCIRCUITPY_CAMERA=$(CIRCUITPY_CAMERA) @@ -707,6 +704,9 @@ CFLAGS += -DCIRCUITPY_WATCHDOG=$(CIRCUITPY_WATCHDOG) CIRCUITPY_WIFI ?= 0 CFLAGS += -DCIRCUITPY_WIFI=$(CIRCUITPY_WIFI) +CIRCUITPY_WIZNET ?= 0 +CFLAGS += -DCIRCUITPY_WIZNET=$(CIRCUITPY_WIZNET) + CIRCUITPY_WEB_WORKFLOW ?= $(CIRCUITPY_WIFI) CFLAGS += -DCIRCUITPY_WEB_WORKFLOW=$(CIRCUITPY_WEB_WORKFLOW) diff --git a/shared-bindings/busio/__init__.c b/shared-bindings/busio/__init__.c index 46386faef0a0c..028d73d9c368f 100755 --- a/shared-bindings/busio/__init__.c +++ b/shared-bindings/busio/__init__.c @@ -15,10 +15,6 @@ #include "shared-bindings/busio/SPI.h" #include "shared-bindings/busio/UART.h" -#if CIRCUITPY_WIZNET_PIO_SPI -#include "shared-bindings/busio/WIZNET_PIO_SPI.h" -#endif - #include "py/runtime.h" //| """Hardware accelerated external bus access @@ -73,9 +69,6 @@ static const mp_rom_map_elem_t busio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&busio_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&busio_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&busio_uart_type) }, - #if CIRCUITPY_WIZNET_PIO_SPI - { MP_ROM_QSTR(MP_QSTR_WIZNET_PIO_SPI), MP_ROM_PTR(&busio_wiznet_pio_spi_type) }, - #endif }; static MP_DEFINE_CONST_DICT(busio_module_globals, busio_module_globals_table); From a3868636e8831796cd6185121d6cf2a964a06028 Mon Sep 17 00:00:00 2001 From: hannah Date: Tue, 15 Jul 2025 04:12:31 +0000 Subject: [PATCH 5/7] fix: lower compiler optimization to -O2 for wiznet_w55rp20_evb_pico --- ports/raspberrypi/Makefile | 2 +- ports/raspberrypi/bindings/wiznet/PIO_SPI.c | 8 ++++---- .../boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index 91de903e22e04..6281e7863f149 100755 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -89,7 +89,7 @@ INC_WIZNET := \ SRC_WIZNET := \ common-hal/wiznet/wizchip_pio_spi.c \ - + WIZNET_PIOASM = $(BUILD)/pioasm/pioasm/pioasm .PHONY: pioasmBuild pioasmBuild: $(WIZNET_PIOASM) diff --git a/ports/raspberrypi/bindings/wiznet/PIO_SPI.c b/ports/raspberrypi/bindings/wiznet/PIO_SPI.c index f628ca868b8f8..1f860fc997953 100755 --- a/ports/raspberrypi/bindings/wiznet/PIO_SPI.c +++ b/ports/raspberrypi/bindings/wiznet/PIO_SPI.c @@ -4,9 +4,9 @@ // // SPDX-License-Identifier: MIT -//TODO: busio.WIZNET_PIO_SPI class. +// TODO: wiznet.PIO_SPI class. // This file contains all of the Python API definitions for the -// busio.WIZNET_PIO_SPI class. +// wiznet.PIO_SPI class. #include @@ -22,7 +22,7 @@ #include "py/runtime.h" -//TODO: class WIZNET_PIO_SPI +// TODO: class WIZNET_PIO_SPI static mp_obj_t wiznet_pio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { @@ -292,7 +292,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_TYPE_FLAG_NONE, make_new, wiznet_pio_spi_make_new, locals_dict, &wiznet_pio_spi_locals_dict -); + ); wiznet_pio_spi_obj_t *validate_obj_is_wiznet_pio_spi_bus(mp_obj_t obj, qstr arg_name) { return mp_arg_validate_type(obj, &wiznet_pio_spi_type, arg_name); diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk index 5030ee88f52b2..d43195c0f2ab8 100755 --- a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/mpconfigboard.mk @@ -12,3 +12,5 @@ CIRCUITPY_WIZNET = 1 CIRCUITPY__EVE = 1 CIRCUITPY_SSL = 1 CIRCUITPY_USB_HOST = 0 + +OPTIMIZATION_FLAGS = -O2 From 16d3353987dc2c49863d873074394f12d8a0444f Mon Sep 17 00:00:00 2001 From: hannah Date: Tue, 15 Jul 2025 05:06:39 +0000 Subject: [PATCH 6/7] Modified pin definitions for wiznet_w55rp20_evb_pico and fix pre-commit error --- ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c | 9 ++++----- shared-bindings/busio/__init__.c | 0 2 files changed, 4 insertions(+), 5 deletions(-) mode change 100755 => 100644 shared-bindings/busio/__init__.c diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c index c0db99042c077..399cc2d9b7b7a 100755 --- a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c @@ -26,6 +26,9 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO19) }, { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, @@ -47,21 +50,17 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_W5K_RST), MP_ROM_PTR(&pin_GPIO25) }, { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, - { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO26) }, { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, - { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, - { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO27) }, { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, - { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, - { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, diff --git a/shared-bindings/busio/__init__.c b/shared-bindings/busio/__init__.c old mode 100755 new mode 100644 From 8a0e31620db12fb02302643191e6b6fa2ea0fea1 Mon Sep 17 00:00:00 2001 From: hannah Date: Tue, 15 Jul 2025 05:21:44 +0000 Subject: [PATCH 7/7] Modified pin definitions --- ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c index 399cc2d9b7b7a..37ecfd3dfb111 100755 --- a/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c +++ b/ports/raspberrypi/boards/wiznet_w55rp20_evb_pico/pins.c @@ -60,7 +60,7 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, - { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) },