From bca816f5ac36609212ab087789ee028d1d5d534d Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 5 May 2022 17:26:16 +1000 Subject: [PATCH] rp2: Add support for using Wiznet hardware as an Ethernet NIC. Uses the extmod/network_wiznet5k driver to provide network connectivity. Signed-off-by: Andrew Leech --- ports/rp2/CMakeLists.txt | 47 +++++++++++++++++++++++++++++++++++++++ ports/rp2/machine_spi.c | 9 ++++++++ ports/rp2/modmachine.h | 2 ++ ports/rp2/mpconfigport.h | 13 +++++++++++ ports/rp2/mphalport.c | 18 +++++++++++++++ ports/rp2/mphalport.h | 9 ++++++++ ports/rp2/mpnetworkport.c | 32 ++++++++++++++++++++++++++ 7 files changed, 130 insertions(+) diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index d9e485f70238..31284c8405fb 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -244,6 +244,53 @@ if (MICROPY_PY_NETWORK_NINAW10) ) endif() +if (MICROPY_PY_WIZNET5K) + target_compile_definitions(${MICROPY_TARGET} PRIVATE + MICROPY_PY_WIZNET5K=1 + WIZCHIP_PREFIXED_EXPORTS=1 + _WIZCHIP_=${MICROPY_PY_WIZNET5K} + WIZCHIP_YIELD=mpy_wiznet_yield + ) + + if (MICROPY_PY_LWIP) + target_compile_definitions(${MICROPY_TARGET} PRIVATE + # When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket + WIZCHIP_USE_MAX_BUFFER=1 + ) + endif() + + target_include_directories(${MICROPY_TARGET} PRIVATE + ${MICROPY_DIR}/lib/wiznet5k/ + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/ + ) + + list(APPEND MICROPY_SOURCE_LIB + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5100/w5100.c + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5100S/w5100s.c + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5200/w5200.c + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5300/w5300.c + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5500/w5500.c + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/socket.c + ${MICROPY_DIR}/lib/wiznet5k/Ethernet/wizchip_conf.c + ${MICROPY_DIR}/lib/wiznet5k/Internet/DNS/dns.c + ${MICROPY_DIR}/lib/wiznet5k/Internet/DHCP/dhcp.c + ) + + list(APPEND MICROPY_SOURCE_EXTMOD + ${MICROPY_DIR}/extmod/modnetwork.c + ${MICROPY_DIR}/extmod/modusocket.c + ${MICROPY_DIR}/extmod/network_wiznet5k.c + ) + + list(APPEND MICROPY_SOURCE_QSTR + ${MICROPY_DIR}/extmod/modnetwork.c + ${MICROPY_DIR}/extmod/modusocket.c + ${MICROPY_DIR}/extmod/network_wiznet5k.c + ) + + string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/wiznet5k) +endif() + # Define mpy-cross flags set(MICROPY_CROSS_FLAGS -march=armv7m) diff --git a/ports/rp2/machine_spi.c b/ports/rp2/machine_spi.c index 332f44694548..742a3cfddf44 100644 --- a/ports/rp2/machine_spi.c +++ b/ports/rp2/machine_spi.c @@ -269,6 +269,15 @@ STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8 } } +machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o) { + if (mp_obj_is_type(o, &machine_spi_type)) { + machine_spi_obj_t *self = MP_OBJ_TO_PTR(o); + return self; + } else { + mp_raise_TypeError(MP_ERROR_TEXT("expecting an SPI object")); + } +} + STATIC const mp_machine_spi_p_t machine_spi_p = { .init = machine_spi_init, .transfer = machine_spi_transfer, diff --git a/ports/rp2/modmachine.h b/ports/rp2/modmachine.h index af02cd193dff..0635ff248706 100644 --- a/ports/rp2/modmachine.h +++ b/ports/rp2/modmachine.h @@ -17,4 +17,6 @@ void machine_pin_init(void); void machine_pin_deinit(void); void machine_i2s_init0(void); +struct _machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o); + #endif // MICROPY_INCLUDED_RP2_MODMACHINE_H diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 4cadc261749c..e2d0ffd2246e 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -77,6 +77,7 @@ #define MICROPY_PY_SYS_PLATFORM "rp2" #define MICROPY_PY_THREAD (1) #define MICROPY_PY_THREAD_GIL (0) +#define MICROPY_THREAD_YIELD() mp_handle_pending(true) // Extended modules #define MICROPY_EPOCH_IS_1970 (1) @@ -163,12 +164,24 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_nina; #define MICROPY_PORT_ROOT_POINTER_NINAW10 #endif +#if MICROPY_PY_WIZNET5K +#if MICROPY_PY_LWIP +extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k; +#else +extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; +#endif +#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) }, +#else +#define MICROPY_HW_NIC_WIZNET5K +#endif + #ifndef MICROPY_BOARD_NETWORK_INTERFACES #define MICROPY_BOARD_NETWORK_INTERFACES #endif #define MICROPY_PORT_NETWORK_INTERFACES \ MICROPY_HW_NIC_NINAW10 \ + MICROPY_HW_NIC_WIZNET5K \ MICROPY_BOARD_NETWORK_INTERFACES \ #ifndef MICROPY_BOARD_ROOT_POINTERS diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index 4a5221caec99..4ed648de0751 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -33,6 +33,7 @@ #include "tusb.h" #include "uart.h" #include "hardware/rtc.h" +#include "pico/unique_id.h" #if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_ENABLE_USBDEV @@ -164,3 +165,20 @@ uint64_t mp_hal_time_ns(void) { uint64_t s = timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.min, t.sec); return s * 1000000000ULL; } + +// Generate a random locally administered MAC address (LAA) +void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) { + pico_unique_board_id_t pid; + pico_get_unique_board_id(&pid); + buf[0] = 0x02; // LAA range + buf[1] = (pid.id[7] << 4) | (pid.id[6] & 0xf); + buf[2] = (pid.id[5] << 4) | (pid.id[4] & 0xf); + buf[3] = (pid.id[3] << 4) | (pid.id[2] & 0xf); + buf[4] = pid.id[1]; + buf[5] = (pid.id[0] << 2) | idx; +} + +// A board can override this if needed +MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { + mp_hal_generate_laa_mac(idx, buf); +} diff --git a/ports/rp2/mphalport.h b/ports/rp2/mphalport.h index 0aebf7d74724..88eef1308dcd 100644 --- a/ports/rp2/mphalport.h +++ b/ports/rp2/mphalport.h @@ -136,4 +136,13 @@ enum mp_hal_pin_interrupt_trigger { void mp_hal_pin_interrupt(mp_hal_pin_obj_t pin, mp_obj_t handler, mp_uint_t trigger, bool hard); +enum { + MP_HAL_MAC_WLAN0 = 0, + MP_HAL_MAC_BDADDR, + MP_HAL_MAC_ETH0, +}; + +void mp_hal_get_mac(int idx, uint8_t buf[6]); +void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]); + #endif // MICROPY_INCLUDED_RP2_MPHALPORT_H diff --git a/ports/rp2/mpnetworkport.c b/ports/rp2/mpnetworkport.c index 1f59e28ea58d..7ee10bb03e0f 100644 --- a/ports/rp2/mpnetworkport.c +++ b/ports/rp2/mpnetworkport.c @@ -39,6 +39,13 @@ static alarm_id_t lwip_alarm_id = -1; static bool lwip_can_poll = true; static bool lwip_poll_pending = false; +#if MICROPY_PY_WIZNET5K +static bool wiznet_poll_pending = false; + +void wiznet5k_poll(void); +void wiznet5k_deinit(void); +#endif + u32_t sys_now(void) { // Used by LwIP return mp_hal_ticks_ms(); @@ -57,6 +64,13 @@ void lwip_lock_acquire(void) { void lwip_lock_release(void) { lwip_can_poll = false; + #if MICROPY_PY_WIZNET5K + if (wiznet_poll_pending) { + wiznet5k_poll(); + wiznet_poll_pending = false; + } + #endif + if (lwip_poll_pending) { lwip_poll(); lwip_poll_pending = false; @@ -76,11 +90,29 @@ uint32_t lwip_try_poll(void) { return ret; } +#if MICROPY_PY_WIZNET5K +void wiznet5k_try_poll(void) { + if (lwip_can_poll) { + lwip_can_poll = false; + wiznet5k_poll(); + lwip_can_poll = true; + } else { + wiznet_poll_pending = true; + } +} +#endif + STATIC int64_t alarm_callback(alarm_id_t id, void *user_data) { + #if MICROPY_PY_WIZNET5K + wiznet5k_try_poll(); + #endif return lwip_try_poll(); } void mod_network_lwip_init(void) { + #if MICROPY_PY_WIZNET5K + wiznet5k_deinit(); + #endif if (lwip_alarm_id != -1) { cancel_alarm(lwip_alarm_id); }