mimxrt/eth: Improve Dual Ethernet configuration.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
This commit is contained in:
Andrew Leech
2025-11-20 13:52:09 +11:00
committed by Damien George
parent 5021137f32
commit 77e62f627a
5 changed files with 103 additions and 41 deletions

View File

@@ -167,9 +167,7 @@
{ IOMUXC_GPIO_AD_33_ENET_MDIO, 0, 0x06u }, \
{ IOMUXC_GPIO_AD_32_ENET_MDC, 0, 0x06u },
// A second ETH port is present.
#define ENET_DUAL_PORT (1)
// 1G Transceiver Phy Parameters
// 1G Transceiver Phy Parameters (second ETH port)
#define ENET_1_PHY_ADDRESS (1)
#define ENET_1_PHY RTL8211F
#define ENET_1_PHY_OPS phyrtl8211f_ops

View File

@@ -31,7 +31,7 @@
#include "py/mperrno.h"
#include "ticks.h"
#if defined(IOMUX_TABLE_ENET)
#if defined(ENET_PHY_ADDRESS) || defined(ENET_1_PHY_ADDRESS)
#include "pin.h"
#include "shared/netutils/netutils.h"
@@ -75,6 +75,8 @@ typedef struct _iomux_table_t {
uint32_t configValue;
} iomux_table_t;
#if defined(ENET_PHY_ADDRESS)
// ETH0 buffers and handles
static AT_NONCACHEABLE_SECTION_ALIGN(enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM], ENET_BUFF_ALIGNMENT);
static AT_NONCACHEABLE_SECTION_ALIGN(enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM], ENET_BUFF_ALIGNMENT);
@@ -111,7 +113,9 @@ static const iomux_table_t iomux_table_enet[] = {
static uint8_t hw_addr[6]; // The MAC address field
#if defined(ENET_DUAL_PORT)
#endif // defined(ENET_PHY_ADDRESS)
#if defined(ENET_1_PHY_ADDRESS)
// ETH1 buffers and handles
static AT_NONCACHEABLE_SECTION_ALIGN(enet_rx_bd_struct_t g_rxBuffDescrip_1[ENET_RXBD_NUM], ENET_BUFF_ALIGNMENT);
@@ -148,17 +152,14 @@ static const iomux_table_t iomux_table_enet_1[] = {
static uint8_t hw_addr_1[6]; // The MAC address field
#endif
#if defined(ENET_DUAL_PORT)
// Define ENET_1 to the appropriate controller for this hardware
#if defined MIMXRT117x_SERIES
#define ENET_1 ENET_1G
#else
#define ENET_1 ENET2
#endif
#else
#define ENET_1 ENET
#endif
#endif // defined(ENET_1_PHY_ADDRESS)
#define PHY_AUTONEGO_TIMEOUT_US (5000000)
#define PHY_SETTLE_TIME_US (1000)
@@ -357,6 +358,8 @@ static void eth_phy_init(phy_handle_t *phyHandle, phy_config_t *phy_config,
mp_hal_delay_us(phy_settle_time);
}
#if defined(ENET_PHY_ADDRESS)
// eth_init: Set up GPIO and the transceiver
void eth_init_0(eth_t *self, int eth_id, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock) {
// Configuration values
@@ -411,7 +414,9 @@ void eth_init_0(eth_t *self, int eth_id, const phy_operations_t *phy_ops, int ph
ENET_ActiveRead(ENET);
}
#if defined(ENET_DUAL_PORT)
#endif // defined(ENET_PHY_ADDRESS)
#if defined(ENET_1_PHY_ADDRESS)
// eth_init: Set up GPIO and the transceiver
void eth_init_1(eth_t *self, int eth_id, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock) {
@@ -474,7 +479,8 @@ void eth_init_1(eth_t *self, int eth_id, const phy_operations_t *phy_ops, int ph
ENET_ActiveRead(ENET_1);
}
#endif
#endif // defined(ENET_1_PHY_ADDRESS)
// Initialize the phy interface
static int eth_mac_init(eth_t *self) {
return 0;
@@ -512,14 +518,26 @@ static err_t eth_send_frame_blocking(ENET_Type *base, enet_handle_t *handle, uin
static err_t eth_netif_output(struct netif *netif, struct pbuf *p) {
// This function should always be called from a context where PendSV-level IRQs are disabled
status_t status;
ENET_Type *enet = ENET;
enet_handle_t *handle = &g_handle;
ENET_Type *enet;
enet_handle_t *handle;
#if defined ENET_DUAL_PORT
#if defined(ENET_PHY_ADDRESS) && defined(ENET_1_PHY_ADDRESS)
// Dual port: select based on netif->state
if (netif->state == &eth_instance1) {
enet = ENET_1;
handle = &g_handle_1;
} else {
enet = ENET;
handle = &g_handle;
}
#elif defined(ENET_1_PHY_ADDRESS)
// Only ENET_1 available
enet = ENET_1;
handle = &g_handle_1;
#else
// Only ENET available
enet = ENET;
handle = &g_handle;
#endif
eth_trace(netif->state, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE);
@@ -562,15 +580,18 @@ static void eth_lwip_init(eth_t *self) {
ip_addr_t ipconfig[4];
self->netif.hwaddr_len = 6;
#if defined(ENET_PHY_ADDRESS)
if (self == &eth_instance0) {
memcpy(self->netif.hwaddr, hw_addr, 6);
IP4_ADDR(&ipconfig[0], 192, 168, 0, 2);
#if defined ENET_DUAL_PORT
} else {
}
#endif
#if defined(ENET_1_PHY_ADDRESS)
if (self == &eth_instance1) {
memcpy(self->netif.hwaddr, hw_addr_1, 6);
IP4_ADDR(&ipconfig[0], 192, 168, 0, 3);
#endif
}
#endif
IP4_ADDR(&ipconfig[1], 255, 255, 255, 0);
IP4_ADDR(&ipconfig[2], 192, 168, 0, 1);
IP4_ADDR(&ipconfig[3], 8, 8, 8, 8);
@@ -578,7 +599,11 @@ static void eth_lwip_init(eth_t *self) {
MICROPY_PY_LWIP_ENTER
n->name[0] = 'e';
#if defined(ENET_PHY_ADDRESS)
n->name[1] = (self == &eth_instance0 ? '0' : '1');
#else
n->name[1] = '1';
#endif
netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, eth_netif_init, ethernet_input);
netif_set_hostname(n, mod_network_hostname_data);
netif_set_default(n);
@@ -620,8 +645,10 @@ int eth_link_status(eth_t *self) {
}
} else {
bool link;
#if defined ENET_DUAL_PORT
#if defined(ENET_PHY_ADDRESS) && defined(ENET_1_PHY_ADDRESS)
PHY_GetLinkStatus(self == &eth_instance0 ? &phyHandle : &phyHandle_1, &link);
#elif defined(ENET_1_PHY_ADDRESS)
PHY_GetLinkStatus(&phyHandle_1, &link);
#else
PHY_GetLinkStatus(&phyHandle, &link);
#endif
@@ -654,10 +681,12 @@ int eth_stop(eth_t *self) {
}
void eth_low_power_mode(eth_t *self, bool enable) {
#if defined ENET_DUAL_PORT
#if defined(ENET_PHY_ADDRESS) && defined(ENET_1_PHY_ADDRESS)
ENET_EnableSleepMode(self == &eth_instance0 ? ENET : ENET_1, enable);
#elif defined(ENET_1_PHY_ADDRESS)
ENET_EnableSleepMode(ENET_1, enable);
#else
ENET_EnableSleepMode(ENET, enable);
#endif
}
#endif // defined(IOMUX_TABLE_ENET)
#endif // defined(ENET_PHY_ADDRESS) || defined(ENET_1_PHY_ADDRESS)

View File

@@ -28,11 +28,14 @@
#define MICROPY_INCLUDED_MIMXRT_ETH_H
typedef struct _eth_t eth_t;
extern eth_t eth_instance0;
extern eth_t eth_instance1;
void eth_init_0(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock);
#if defined(ENET_DUAL_PORT)
#if defined(ENET_PHY_ADDRESS)
extern eth_t eth_instance0;
void eth_init_0(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock);
#endif
#if defined(ENET_1_PHY_ADDRESS)
extern eth_t eth_instance1;
void eth_init_1(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock);
#endif

View File

@@ -179,7 +179,7 @@ uint32_t trng_random_u32(void);
// Hooks to add builtins
#if defined(IOMUX_TABLE_ENET)
#if defined(ENET_PHY_ADDRESS) || defined(ENET_1_PHY_ADDRESS)
extern const struct _mp_obj_type_t network_lan_type;
#define MICROPY_HW_NIC_ETH { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&network_lan_type) },
#else

View File

@@ -28,7 +28,7 @@
#include "py/mphal.h"
#include "extmod/modnetwork.h"
#if defined(IOMUX_TABLE_ENET)
#if defined(ENET_PHY_ADDRESS) || defined(ENET_1_PHY_ADDRESS)
#include "fsl_phy.h"
#include "eth.h"
@@ -55,9 +55,13 @@ typedef struct _network_lan_obj_t {
eth_t *eth;
} network_lan_obj_t;
// Forward declaration of the type
extern const mp_obj_type_t network_lan_type;
#if defined(ENET_PHY_ADDRESS)
static const network_lan_obj_t network_lan_eth0 = { { &network_lan_type }, &eth_instance0 };
#if defined(ENET_DUAL_PORT)
#endif
#if defined(ENET_1_PHY_ADDRESS)
static const network_lan_obj_t network_lan_eth1 = { { &network_lan_type }, &eth_instance1 };
#endif
@@ -65,8 +69,19 @@ static void network_lan_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
network_lan_obj_t *self = MP_OBJ_TO_PTR(self_in);
struct netif *netif = eth_netif(self->eth);
int status = eth_link_status(self->eth);
int eth_id = 0;
#if defined(ENET_PHY_ADDRESS)
if (self->eth == &eth_instance0) {
eth_id = 0;
}
#endif
#if defined(ENET_1_PHY_ADDRESS)
if (self->eth == &eth_instance1) {
eth_id = 1;
}
#endif
mp_printf(print, "<ETH%d status=%u ip=%u.%u.%u.%u>",
self->eth == &eth_instance0 ? 0 : 1,
eth_id,
status,
netif->ip_addr.addr & 0xff,
netif->ip_addr.addr >> 8 & 0xff,
@@ -77,8 +92,18 @@ 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_id, ARG_phy_type, ARG_phy_addr, ARG_ref_clk_mode};
// Default to port 0 if ENET available, else port 1 if only ENET_1 available
#if defined(ENET_PHY_ADDRESS)
#define DEFAULT_ETH_ID 0
#elif defined(ENET_1_PHY_ADDRESS)
#define DEFAULT_ETH_ID 1
#else
#error "No Ethernet PHY configured"
#endif
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_id, MP_ARG_INT, {.u_int = DEFAULT_ETH_ID} },
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_ref_clk_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
@@ -92,18 +117,21 @@ static mp_obj_t network_lan_make_new(const mp_obj_type_t *type, size_t n_args, s
bool phy_clock;
int mac_id = args[ARG_id].u_int;
// set default
// set default based on which interface is being used
#if defined(ENET_PHY_ADDRESS)
if (mac_id == 0) {
phy_ops = &ENET_PHY_OPS;
phy_addr = ENET_PHY_ADDRESS;
phy_clock = ENET_TX_CLK_OUTPUT;
#if defined(ENET_DUAL_PORT)
} else {
}
#endif
#if defined(ENET_1_PHY_ADDRESS)
if (mac_id == 1) {
phy_ops = &ENET_1_PHY_OPS;
phy_addr = ENET_1_PHY_ADDRESS;
phy_clock = ENET_1_TX_CLK_OUTPUT;
#endif
}
#endif
// Select PHY driver
int phy_type = args[ARG_phy_type].u_int;
@@ -132,17 +160,21 @@ static mp_obj_t network_lan_make_new(const mp_obj_type_t *type, size_t n_args, s
phy_clock = args[ARG_ref_clk_mode].u_int;
}
// Prepare for two ETH interfaces.
const network_lan_obj_t *self;
// Initialize the appropriate ETH interface
const network_lan_obj_t *self = NULL;
#if defined(ENET_PHY_ADDRESS)
if (mac_id == 0) {
self = &network_lan_eth0;
eth_init_0(self->eth, MP_HAL_MAC_ETH0, phy_ops, phy_addr, phy_clock);
#if defined(ENET_DUAL_PORT)
} else if (mac_id == 1) {
}
#endif
#if defined(ENET_1_PHY_ADDRESS)
if (mac_id == 1) {
self = &network_lan_eth1;
eth_init_1(self->eth, MP_HAL_MAC_ETH1, phy_ops, phy_addr, phy_clock);
}
#endif
} else {
if (self == NULL) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid LAN interface %d"), mac_id);
}
@@ -275,4 +307,4 @@ MP_DEFINE_CONST_OBJ_TYPE(
);
#endif // defined(IOMUX_TABLE_ENET)
#endif // defined(ENET_PHY_ADDRESS) || defined(ENET_1_PHY_ADDRESS)