kopia lustrzana https://github.com/micropython/micropython
stm32/network_lan: Add the phy_type=x keyword option to network.LAN().
With LAN8742, LAN8720, LAN83825 and DP83848 as possible options, and the symbols PHY_LAN8720, PHY_LAN8742, PHY_DP83825 and PHY_DP8348. The default is PHY_LAN8742 which is the existing behaviour. The eth_init() parameters for the Portenta H7 board are set to phy_addr=0 and phy_type=LAN8742, which matches the previous defaults and the schematics. Tested with LAN8720 and DP83848 breakout boards at 10M Duplex and 100M Duplex modes. Signed-off-by: robert-hh <robert@hammelrath.com>pull/13630/head
rodzic
085e3244f0
commit
bf68bb95f9
|
@ -251,6 +251,7 @@ SRC_C += \
|
|||
pyb_can.c \
|
||||
usb.c \
|
||||
eth.c \
|
||||
eth_phy.c \
|
||||
gccollect.c \
|
||||
help.c \
|
||||
machine_bitstream.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(ð_instance, MP_HAL_MAC_ETH0, 0);
|
||||
eth_init(ð_instance, MP_HAL_MAC_ETH0, 0, ETH_PHY_LAN8742);
|
||||
eth_low_power_mode(ð_instance, true);
|
||||
|
||||
#if MICROPY_HW_USB_HS_ULPI3320
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue