stm32/network_lan: Allow defining phy_addr in the LAN constructor.
The default value is 0, which is compatible with the existing behaviour. Implementing that required changes to eth.c as well. The value of phy_addr is added to the eth_t data type. Tested with a STM32F767 and a STM32H750 device. Signed-off-by: robert-hh <robert@hammelrath.com>
This commit is contained in:
@@ -115,7 +115,7 @@ void PORTENTA_board_early_init(void) {
|
|||||||
mp_hal_pin_write(pyb_pin_ETH_RST, 1);
|
mp_hal_pin_write(pyb_pin_ETH_RST, 1);
|
||||||
|
|
||||||
// Put Eth in low-power mode
|
// Put Eth in low-power mode
|
||||||
eth_init(ð_instance, MP_HAL_MAC_ETH0);
|
eth_init(ð_instance, MP_HAL_MAC_ETH0, 0);
|
||||||
eth_low_power_mode(ð_instance, true);
|
eth_low_power_mode(ð_instance, true);
|
||||||
|
|
||||||
#if MICROPY_HW_USB_HS_ULPI3320
|
#if MICROPY_HW_USB_HS_ULPI3320
|
||||||
|
|||||||
@@ -40,8 +40,7 @@
|
|||||||
#include "lwip/dhcp.h"
|
#include "lwip/dhcp.h"
|
||||||
#include "netif/ethernet.h"
|
#include "netif/ethernet.h"
|
||||||
|
|
||||||
// ETH PHY register definitions (for LAN8742)
|
// ETH PHY register definitions (for LAN8742 and LAN8720/LAN8710)
|
||||||
|
|
||||||
#undef PHY_BCR
|
#undef PHY_BCR
|
||||||
#define PHY_BCR (0x0000)
|
#define PHY_BCR (0x0000)
|
||||||
#define PHY_BCR_SOFT_RESET (0x8000)
|
#define PHY_BCR_SOFT_RESET (0x8000)
|
||||||
@@ -137,6 +136,7 @@ typedef struct _eth_t {
|
|||||||
uint32_t trace_flags;
|
uint32_t trace_flags;
|
||||||
struct netif netif;
|
struct netif netif;
|
||||||
struct dhcp dhcp_struct;
|
struct dhcp dhcp_struct;
|
||||||
|
uint32_t phy_addr;
|
||||||
} eth_t;
|
} eth_t;
|
||||||
|
|
||||||
static eth_dma_t eth_dma __attribute__((aligned(16384)));
|
static eth_dma_t eth_dma __attribute__((aligned(16384)));
|
||||||
@@ -146,11 +146,13 @@ eth_t eth_instance;
|
|||||||
static void eth_mac_deinit(eth_t *self);
|
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_process_frame(eth_t *self, size_t len, const uint8_t *buf);
|
||||||
|
|
||||||
static void eth_phy_write(uint32_t reg, uint32_t val) {
|
static void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
|
||||||
#if defined(STM32H5) || defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
||||||
}
|
}
|
||||||
uint32_t ar = ETH->MACMDIOAR;
|
uint32_t ar = ETH->MACMDIOAR;
|
||||||
|
ar &= ~ETH_MACMDIOAR_PA_Msk;
|
||||||
|
ar |= (phy_addr << ETH_MACMDIOAR_PA_Pos);
|
||||||
ar &= ~ETH_MACMDIOAR_RDA_Msk;
|
ar &= ~ETH_MACMDIOAR_RDA_Msk;
|
||||||
ar |= reg << ETH_MACMDIOAR_RDA_Pos;
|
ar |= reg << ETH_MACMDIOAR_RDA_Pos;
|
||||||
ar &= ~ETH_MACMDIOAR_MOC_Msk;
|
ar &= ~ETH_MACMDIOAR_MOC_Msk;
|
||||||
@@ -165,18 +167,20 @@ static void eth_phy_write(uint32_t reg, uint32_t val) {
|
|||||||
}
|
}
|
||||||
ETH->MACMIIDR = val;
|
ETH->MACMIIDR = val;
|
||||||
uint32_t ar = ETH->MACMIIAR;
|
uint32_t ar = ETH->MACMIIAR;
|
||||||
ar = reg << ETH_MACMIIAR_MR_Pos | (ar & ETH_MACMIIAR_CR_Msk) | ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
|
ar = (phy_addr << ETH_MACMIIAR_PA_Pos) | (reg << ETH_MACMIIAR_MR_Pos) | (ar & ETH_MACMIIAR_CR_Msk) | ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
|
||||||
ETH->MACMIIAR = ar;
|
ETH->MACMIIAR = ar;
|
||||||
while (ETH->MACMIIAR & ETH_MACMIIAR_MB) {
|
while (ETH->MACMIIAR & ETH_MACMIIAR_MB) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t eth_phy_read(uint32_t reg) {
|
static uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
|
||||||
#if defined(STM32H5) || defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
|
||||||
}
|
}
|
||||||
uint32_t ar = ETH->MACMDIOAR;
|
uint32_t ar = ETH->MACMDIOAR;
|
||||||
|
ar &= ~ETH_MACMDIOAR_PA_Msk;
|
||||||
|
ar |= (phy_addr << ETH_MACMDIOAR_PA_Pos);
|
||||||
ar &= ~ETH_MACMDIOAR_RDA_Msk;
|
ar &= ~ETH_MACMDIOAR_RDA_Msk;
|
||||||
ar |= reg << ETH_MACMDIOAR_RDA_Pos;
|
ar |= reg << ETH_MACMDIOAR_RDA_Pos;
|
||||||
ar &= ~ETH_MACMDIOAR_MOC_Msk;
|
ar &= ~ETH_MACMDIOAR_MOC_Msk;
|
||||||
@@ -190,7 +194,7 @@ static uint32_t eth_phy_read(uint32_t reg) {
|
|||||||
while (ETH->MACMIIAR & ETH_MACMIIAR_MB) {
|
while (ETH->MACMIIAR & ETH_MACMIIAR_MB) {
|
||||||
}
|
}
|
||||||
uint32_t ar = ETH->MACMIIAR;
|
uint32_t ar = ETH->MACMIIAR;
|
||||||
ar = reg << ETH_MACMIIAR_MR_Pos | (ar & ETH_MACMIIAR_CR_Msk) | ETH_MACMIIAR_MB;
|
ar = (phy_addr << ETH_MACMIIAR_PA_Pos) | (reg << ETH_MACMIIAR_MR_Pos) | (ar & ETH_MACMIIAR_CR_Msk) | ETH_MACMIIAR_MB;
|
||||||
ETH->MACMIIAR = ar;
|
ETH->MACMIIAR = ar;
|
||||||
while (ETH->MACMIIAR & ETH_MACMIIAR_MB) {
|
while (ETH->MACMIIAR & ETH_MACMIIAR_MB) {
|
||||||
}
|
}
|
||||||
@@ -198,9 +202,10 @@ static uint32_t eth_phy_read(uint32_t reg) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void eth_init(eth_t *self, int mac_idx) {
|
void eth_init(eth_t *self, int mac_idx, uint32_t phy_addr) {
|
||||||
mp_hal_get_mac(mac_idx, &self->netif.hwaddr[0]);
|
mp_hal_get_mac(mac_idx, &self->netif.hwaddr[0]);
|
||||||
self->netif.hwaddr_len = 6;
|
self->netif.hwaddr_len = 6;
|
||||||
|
self->phy_addr = phy_addr;
|
||||||
|
|
||||||
// Configure GPIO
|
// 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);
|
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDC);
|
||||||
@@ -362,7 +367,7 @@ static int eth_mac_init(eth_t *self) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reset the PHY
|
// Reset the PHY
|
||||||
eth_phy_write(PHY_BCR, PHY_BCR_SOFT_RESET);
|
eth_phy_write(self->phy_addr, PHY_BCR, PHY_BCR_SOFT_RESET);
|
||||||
mp_hal_delay_ms(50);
|
mp_hal_delay_ms(50);
|
||||||
|
|
||||||
// Wait for the PHY link to be established
|
// Wait for the PHY link to be established
|
||||||
@@ -373,8 +378,8 @@ static int eth_mac_init(eth_t *self) {
|
|||||||
eth_mac_deinit(self);
|
eth_mac_deinit(self);
|
||||||
return -MP_ETIMEDOUT;
|
return -MP_ETIMEDOUT;
|
||||||
}
|
}
|
||||||
uint16_t bcr = eth_phy_read(0);
|
uint16_t bcr = eth_phy_read(self->phy_addr, PHY_BCR);
|
||||||
uint16_t bsr = eth_phy_read(1);
|
uint16_t bsr = eth_phy_read(self->phy_addr, PHY_BSR);
|
||||||
switch (phy_state) {
|
switch (phy_state) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!(bcr & PHY_BCR_SOFT_RESET)) {
|
if (!(bcr & PHY_BCR_SOFT_RESET)) {
|
||||||
@@ -383,7 +388,7 @@ static int eth_mac_init(eth_t *self) {
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (bsr & PHY_BSR_LINK_STATUS) {
|
if (bsr & PHY_BSR_LINK_STATUS) {
|
||||||
eth_phy_write(PHY_BCR, PHY_BCR_AUTONEG_EN);
|
eth_phy_write(self->phy_addr, PHY_BCR, PHY_BCR_AUTONEG_EN);
|
||||||
phy_state = 2;
|
phy_state = 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -398,7 +403,7 @@ static int eth_mac_init(eth_t *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get register with link status
|
// Get register with link status
|
||||||
uint16_t phy_scsr = eth_phy_read(PHY_SCSR);
|
uint16_t phy_scsr = eth_phy_read(self->phy_addr, PHY_SCSR);
|
||||||
|
|
||||||
// Burst mode configuration
|
// Burst mode configuration
|
||||||
#if defined(STM32H5) || defined(STM32H7)
|
#if defined(STM32H5) || defined(STM32H7)
|
||||||
@@ -845,7 +850,7 @@ int eth_link_status(eth_t *self) {
|
|||||||
return 2; // link no-ip;
|
return 2; // link no-ip;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (eth_phy_read(PHY_BSR) & PHY_BSR_LINK_STATUS) {
|
if (eth_phy_read(self->phy_addr, PHY_BSR) & PHY_BSR_LINK_STATUS) {
|
||||||
return 1; // link up
|
return 1; // link up
|
||||||
} else {
|
} else {
|
||||||
return 0; // link down
|
return 0; // link down
|
||||||
@@ -883,10 +888,10 @@ void eth_low_power_mode(eth_t *self, bool enable) {
|
|||||||
__HAL_RCC_ETH_CLK_ENABLE();
|
__HAL_RCC_ETH_CLK_ENABLE();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t bcr = eth_phy_read(PHY_BCR);
|
uint16_t bcr = eth_phy_read(self->phy_addr, PHY_BCR);
|
||||||
if (enable) {
|
if (enable) {
|
||||||
// Enable low-power mode.
|
// Enable low-power mode.
|
||||||
eth_phy_write(PHY_BCR, bcr | PHY_BCR_POWER_DOWN);
|
eth_phy_write(self->phy_addr, PHY_BCR, bcr | PHY_BCR_POWER_DOWN);
|
||||||
// Disable eth clock.
|
// Disable eth clock.
|
||||||
#if defined(STM32H7)
|
#if defined(STM32H7)
|
||||||
__HAL_RCC_ETH1MAC_CLK_DISABLE();
|
__HAL_RCC_ETH1MAC_CLK_DISABLE();
|
||||||
@@ -895,7 +900,7 @@ void eth_low_power_mode(eth_t *self, bool enable) {
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// Disable low-power mode.
|
// Disable low-power mode.
|
||||||
eth_phy_write(PHY_BCR, bcr & (~PHY_BCR_POWER_DOWN));
|
eth_phy_write(self->phy_addr, PHY_BCR, bcr & (~PHY_BCR_POWER_DOWN));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // defined(MICROPY_HW_ETH_MDC)
|
#endif // defined(MICROPY_HW_ETH_MDC)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
typedef struct _eth_t eth_t;
|
typedef struct _eth_t eth_t;
|
||||||
extern eth_t eth_instance;
|
extern eth_t eth_instance;
|
||||||
|
|
||||||
void eth_init(eth_t *self, int mac_idx);
|
void eth_init(eth_t *self, int mac_idx, uint32_t phy_addr);
|
||||||
void eth_set_trace(eth_t *self, uint32_t value);
|
void eth_set_trace(eth_t *self, uint32_t value);
|
||||||
struct netif *eth_netif(eth_t *self);
|
struct netif *eth_netif(eth_t *self);
|
||||||
int eth_link_status(eth_t *self);
|
int eth_link_status(eth_t *self);
|
||||||
|
|||||||
@@ -53,10 +53,17 @@ 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 *args) {
|
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) {
|
||||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
enum { ARG_phy_addr};
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||||
|
};
|
||||||
|
// 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;
|
const network_lan_obj_t *self = &network_lan_eth0;
|
||||||
eth_init(self->eth, MP_HAL_MAC_ETH0);
|
eth_init(self->eth, MP_HAL_MAC_ETH0, args[ARG_phy_addr].u_int);
|
||||||
return MP_OBJ_FROM_PTR(self);
|
return MP_OBJ_FROM_PTR(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user