summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/Makefile1
-rw-r--r--ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c2
-rw-r--r--ports/stm32/eth.c52
-rw-r--r--ports/stm32/eth.h9
-rw-r--r--ports/stm32/eth_phy.c59
-rw-r--r--ports/stm32/eth_phy.h67
-rw-r--r--ports/stm32/network_lan.c12
7 files changed, 171 insertions, 31 deletions
diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile
index 19f6f420e..d1694426d 100644
--- a/ports/stm32/Makefile
+++ b/ports/stm32/Makefile
@@ -251,6 +251,7 @@ SRC_C += \
pyb_can.c \
usb.c \
eth.c \
+ eth_phy.c \
gccollect.c \
help.c \
machine_bitstream.c \
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c
index ad275ef87..04fa3b9bc 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c
@@ -115,7 +115,7 @@ void PORTENTA_board_early_init(void) {
mp_hal_pin_write(pyb_pin_ETH_RST, 1);
// Put Eth in low-power mode
- eth_init(&eth_instance, MP_HAL_MAC_ETH0, 0);
+ eth_init(&eth_instance, MP_HAL_MAC_ETH0, 0, ETH_PHY_LAN8742);
eth_low_power_mode(&eth_instance, true);
#if MICROPY_HW_USB_HS_ULPI3320
diff --git a/ports/stm32/eth.c b/ports/stm32/eth.c
index f5bdcc152..fd46bde23 100644
--- a/ports/stm32/eth.c
+++ b/ports/stm32/eth.c
@@ -32,6 +32,7 @@
#include "extmod/modnetwork.h"
#include "mpu.h"
#include "eth.h"
+#include "eth_phy.h"
#if defined(MICROPY_HW_ETH_MDC)
@@ -40,26 +41,6 @@
#include "lwip/dhcp.h"
#include "netif/ethernet.h"
-// ETH PHY register definitions (for LAN8742 and LAN8720/LAN8710)
-#undef PHY_BCR
-#define PHY_BCR (0x0000)
-#define PHY_BCR_SOFT_RESET (0x8000)
-#define PHY_BCR_AUTONEG_EN (0x1000)
-#define PHY_BCR_POWER_DOWN (0x0800U)
-
-#undef PHY_BSR
-#define PHY_BSR (0x0001)
-#define PHY_BSR_LINK_STATUS (0x0004)
-#define PHY_BSR_AUTONEG_DONE (0x0020)
-
-#define PHY_SCSR (0x001f)
-#define PHY_SCSR_SPEED_Pos (2)
-#define PHY_SCSR_SPEED_Msk (7 << PHY_SCSR_SPEED_Pos)
-#define PHY_SCSR_SPEED_10HALF (1 << PHY_SCSR_SPEED_Pos)
-#define PHY_SCSR_SPEED_10FULL (5 << PHY_SCSR_SPEED_Pos)
-#define PHY_SCSR_SPEED_100HALF (2 << PHY_SCSR_SPEED_Pos)
-#define PHY_SCSR_SPEED_100FULL (6 << PHY_SCSR_SPEED_Pos)
-
// ETH DMA RX and TX descriptor definitions
#if defined(STM32H5)
#define RX_DESCR_3_OWN_Pos (31)
@@ -137,6 +118,7 @@ typedef struct _eth_t {
struct netif netif;
struct dhcp dhcp_struct;
uint32_t phy_addr;
+ int16_t (*phy_get_link_status)(uint32_t phy_addr);
} eth_t;
static eth_dma_t eth_dma __attribute__((aligned(16384)));
@@ -146,7 +128,7 @@ eth_t eth_instance;
static void eth_mac_deinit(eth_t *self);
static void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf);
-static void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
+void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
#if defined(STM32H5) || defined(STM32H7)
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
}
@@ -174,7 +156,7 @@ static void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
#endif
}
-static uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
+uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
#if defined(STM32H5) || defined(STM32H7)
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
}
@@ -202,10 +184,17 @@ static uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
#endif
}
-void eth_init(eth_t *self, int mac_idx, uint32_t phy_addr) {
+int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type) {
mp_hal_get_mac(mac_idx, &self->netif.hwaddr[0]);
self->netif.hwaddr_len = 6;
self->phy_addr = phy_addr;
+ if (phy_type == ETH_PHY_DP83825 || phy_type == ETH_PHY_DP83848) {
+ self->phy_get_link_status = eth_phy_dp838xx_get_link_status;
+ } else if (phy_type == ETH_PHY_LAN8720 || phy_type == ETH_PHY_LAN8742) {
+ self->phy_get_link_status = eth_phy_lan87xx_get_link_status;
+ } else {
+ return -1;
+ }
// Configure GPIO
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDC);
@@ -230,6 +219,7 @@ void eth_init(eth_t *self, int mac_idx, uint32_t phy_addr) {
#else
__HAL_RCC_ETH_CLK_ENABLE();
#endif
+ return 0;
}
void eth_set_trace(eth_t *self, uint32_t value) {
@@ -381,6 +371,14 @@ static int eth_mac_init(eth_t *self) {
break;
case 1:
if (bsr & PHY_BSR_LINK_STATUS) {
+ // Announce all modes
+ eth_phy_write(self->phy_addr, PHY_ANAR,
+ PHY_ANAR_SPEED_10HALF |
+ PHY_ANAR_SPEED_10FULL |
+ PHY_ANAR_SPEED_100HALF |
+ PHY_ANAR_SPEED_100FULL |
+ PHY_ANAR_IEEE802_3);
+ // Start autonegotiate.
eth_phy_write(self->phy_addr, PHY_BCR, PHY_BCR_AUTONEG_EN);
phy_state = 2;
}
@@ -396,7 +394,7 @@ static int eth_mac_init(eth_t *self) {
}
// Get register with link status
- uint16_t phy_scsr = eth_phy_read(self->phy_addr, PHY_SCSR);
+ uint16_t phy_scsr = self->phy_get_link_status(self->phy_addr);
// Burst mode configuration
#if defined(STM32H5) || defined(STM32H7)
@@ -505,9 +503,9 @@ static int eth_mac_init(eth_t *self) {
// Set main MAC control register
ETH->MACCR =
- (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_10FULL ? ETH_MACCR_DM
- : (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100HALF ? ETH_MACCR_FES
- : (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM)
+ phy_scsr == PHY_SPEED_10FULL ? ETH_MACCR_DM
+ : phy_scsr == PHY_SPEED_100HALF ? ETH_MACCR_FES
+ : phy_scsr == PHY_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM)
: 0
;
mp_hal_delay_ms(2);
diff --git a/ports/stm32/eth.h b/ports/stm32/eth.h
index 45c385a25..564744969 100644
--- a/ports/stm32/eth.h
+++ b/ports/stm32/eth.h
@@ -26,10 +26,17 @@
#ifndef MICROPY_INCLUDED_STM32_ETH_H
#define MICROPY_INCLUDED_STM32_ETH_H
+enum {
+ ETH_PHY_LAN8742 = 0,
+ ETH_PHY_LAN8720,
+ ETH_PHY_DP83848,
+ ETH_PHY_DP83825
+};
+
typedef struct _eth_t eth_t;
extern eth_t eth_instance;
-void eth_init(eth_t *self, int mac_idx, uint32_t phy_addr);
+int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type);
void eth_set_trace(eth_t *self, uint32_t value);
struct netif *eth_netif(eth_t *self);
int eth_link_status(eth_t *self);
diff --git a/ports/stm32/eth_phy.c b/ports/stm32/eth_phy.c
new file mode 100644
index 000000000..56cddba9c
--- /dev/null
+++ b/ports/stm32/eth_phy.c
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Damien P. George
+ * Copyright (c) 2024 Robert Hammelrath
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/mphal.h"
+#include "eth_phy.h"
+
+#if defined(MICROPY_HW_ETH_MDC)
+
+#define PHY_SCSR_LAN87XX (0x001f)
+#define PHY_SCSR_LAN87XX_SPEED_Pos (2)
+#define PHY_SCSR_LAN87XX_SPEED_Msk (7)
+
+#define PHY_SCSR_DP838XX (0x0010)
+#define PHY_RECR_DP838XX (0x0015)
+#define PHY_SCSR_DP838XX_DUPLEX_Msk (4)
+#define PHY_SCSR_DP838XX_10M_Msk (2)
+
+int16_t eth_phy_lan87xx_get_link_status(uint32_t phy_addr) {
+ // Get the link mode & speed
+ int16_t scsr = eth_phy_read(phy_addr, PHY_SCSR_LAN87XX);
+ return (scsr >> PHY_SCSR_LAN87XX_SPEED_Pos) & PHY_SCSR_LAN87XX_SPEED_Msk;
+}
+
+int16_t eth_phy_dp838xx_get_link_status(uint32_t phy_addr) {
+ int16_t scsr = 0;
+ // Get the link mode & speed
+ uint16_t temp = eth_phy_read(phy_addr, PHY_SCSR_DP838XX);
+ scsr = (temp & PHY_SCSR_DP838XX_10M_Msk) ? PHY_SPEED_10HALF : PHY_SPEED_100HALF;
+ if (temp & PHY_SCSR_DP838XX_DUPLEX_Msk) {
+ scsr |= PHY_DUPLEX;
+ }
+ return scsr;
+}
+
+#endif
diff --git a/ports/stm32/eth_phy.h b/ports/stm32/eth_phy.h
new file mode 100644
index 000000000..5036905c1
--- /dev/null
+++ b/ports/stm32/eth_phy.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Damien P. George
+ * Copyright (c) 2024 Robert Hammelrath
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_STM32_PHY_H
+#define MICROPY_INCLUDED_STM32_PYH_H
+
+#if defined(MICROPY_HW_ETH_MDC)
+
+// Common ETH PHY register definitions
+#undef PHY_BCR
+#define PHY_BCR (0x0000)
+#define PHY_BCR_SOFT_RESET (0x8000)
+#define PHY_BCR_AUTONEG_EN (0x1000)
+#define PHY_BCR_POWER_DOWN (0x0800U)
+
+#undef PHY_BSR
+#define PHY_BSR (0x0001)
+#define PHY_BSR_LINK_STATUS (0x0004)
+#define PHY_BSR_AUTONEG_DONE (0x0020)
+
+#undef PHY_ANAR
+#define PHY_ANAR (0x0004)
+#define PHY_ANAR_SPEED_10HALF (0x0020)
+#define PHY_ANAR_SPEED_10FULL (0x0040)
+#define PHY_ANAR_SPEED_100HALF (0x0080)
+#define PHY_ANAR_SPEED_100FULL (0x0100)
+#define PHY_ANAR_IEEE802_3 (0x0001)
+
+#define PHY_SPEED_10HALF (1)
+#define PHY_SPEED_10FULL (5)
+#define PHY_SPEED_100HALF (2)
+#define PHY_SPEED_100FULL (6)
+#define PHY_DUPLEX (4)
+
+uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg);
+void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val);
+
+int16_t eth_phy_lan87xx_get_link_status(uint32_t phy_addr);
+int16_t eth_phy_dp838xx_get_link_status(uint32_t phy_addr);
+
+#endif
+
+#endif // MICROPY_INCLUDED_STM32_PHY_H
diff --git a/ports/stm32/network_lan.c b/ports/stm32/network_lan.c
index efdd354fb..27f3e1337 100644
--- a/ports/stm32/network_lan.c
+++ b/ports/stm32/network_lan.c
@@ -54,16 +54,19 @@ static void network_lan_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
}
static mp_obj_t network_lan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
- enum { ARG_phy_addr};
+ enum { ARG_phy_addr, ARG_phy_type};
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ETH_PHY_LAN8742} },
};
// Parse args.
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 network_lan_obj_t *self = &network_lan_eth0;
- eth_init(self->eth, MP_HAL_MAC_ETH0, args[ARG_phy_addr].u_int);
+ if (eth_init(self->eth, MP_HAL_MAC_ETH0, args[ARG_phy_addr].u_int, args[ARG_phy_type].u_int) != 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid phy_type"));
+ }
return MP_OBJ_FROM_PTR(self);
}
@@ -162,6 +165,11 @@ static const mp_rom_map_elem_t network_lan_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_lan_ifconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_lan_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_lan_config_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_PHY_LAN8742), MP_ROM_INT(ETH_PHY_LAN8742) },
+ { MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(ETH_PHY_LAN8720) },
+ { MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(ETH_PHY_DP83848) },
+ { MP_ROM_QSTR(MP_QSTR_PHY_DP83825), MP_ROM_INT(ETH_PHY_DP83825) },
};
static MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table);