Skip to content

Commit bf68bb9

Browse files
robert-hhdpgeorge
authored andcommitted
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 <[email protected]>
1 parent 085e324 commit bf68bb9

File tree

7 files changed

+171
-31
lines changed

7 files changed

+171
-31
lines changed

Diff for: ports/stm32/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ SRC_C += \
251251
pyb_can.c \
252252
usb.c \
253253
eth.c \
254+
eth_phy.c \
254255
gccollect.c \
255256
help.c \
256257
machine_bitstream.c \

Diff for: ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void PORTENTA_board_early_init(void) {
115115
mp_hal_pin_write(pyb_pin_ETH_RST, 1);
116116

117117
// Put Eth in low-power mode
118-
eth_init(&eth_instance, MP_HAL_MAC_ETH0, 0);
118+
eth_init(&eth_instance, MP_HAL_MAC_ETH0, 0, ETH_PHY_LAN8742);
119119
eth_low_power_mode(&eth_instance, true);
120120

121121
#if MICROPY_HW_USB_HS_ULPI3320

Diff for: ports/stm32/eth.c

+25-27
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "extmod/modnetwork.h"
3333
#include "mpu.h"
3434
#include "eth.h"
35+
#include "eth_phy.h"
3536

3637
#if defined(MICROPY_HW_ETH_MDC)
3738

@@ -40,26 +41,6 @@
4041
#include "lwip/dhcp.h"
4142
#include "netif/ethernet.h"
4243

43-
// ETH PHY register definitions (for LAN8742 and LAN8720/LAN8710)
44-
#undef PHY_BCR
45-
#define PHY_BCR (0x0000)
46-
#define PHY_BCR_SOFT_RESET (0x8000)
47-
#define PHY_BCR_AUTONEG_EN (0x1000)
48-
#define PHY_BCR_POWER_DOWN (0x0800U)
49-
50-
#undef PHY_BSR
51-
#define PHY_BSR (0x0001)
52-
#define PHY_BSR_LINK_STATUS (0x0004)
53-
#define PHY_BSR_AUTONEG_DONE (0x0020)
54-
55-
#define PHY_SCSR (0x001f)
56-
#define PHY_SCSR_SPEED_Pos (2)
57-
#define PHY_SCSR_SPEED_Msk (7 << PHY_SCSR_SPEED_Pos)
58-
#define PHY_SCSR_SPEED_10HALF (1 << PHY_SCSR_SPEED_Pos)
59-
#define PHY_SCSR_SPEED_10FULL (5 << PHY_SCSR_SPEED_Pos)
60-
#define PHY_SCSR_SPEED_100HALF (2 << PHY_SCSR_SPEED_Pos)
61-
#define PHY_SCSR_SPEED_100FULL (6 << PHY_SCSR_SPEED_Pos)
62-
6344
// ETH DMA RX and TX descriptor definitions
6445
#if defined(STM32H5)
6546
#define RX_DESCR_3_OWN_Pos (31)
@@ -137,6 +118,7 @@ typedef struct _eth_t {
137118
struct netif netif;
138119
struct dhcp dhcp_struct;
139120
uint32_t phy_addr;
121+
int16_t (*phy_get_link_status)(uint32_t phy_addr);
140122
} eth_t;
141123

142124
static eth_dma_t eth_dma __attribute__((aligned(16384)));
@@ -146,7 +128,7 @@ eth_t eth_instance;
146128
static void eth_mac_deinit(eth_t *self);
147129
static void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf);
148130

149-
static void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
131+
void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
150132
#if defined(STM32H5) || defined(STM32H7)
151133
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
152134
}
@@ -174,7 +156,7 @@ static void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
174156
#endif
175157
}
176158

177-
static uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
159+
uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
178160
#if defined(STM32H5) || defined(STM32H7)
179161
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
180162
}
@@ -202,10 +184,17 @@ static uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
202184
#endif
203185
}
204186

205-
void eth_init(eth_t *self, int mac_idx, uint32_t phy_addr) {
187+
int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type) {
206188
mp_hal_get_mac(mac_idx, &self->netif.hwaddr[0]);
207189
self->netif.hwaddr_len = 6;
208190
self->phy_addr = phy_addr;
191+
if (phy_type == ETH_PHY_DP83825 || phy_type == ETH_PHY_DP83848) {
192+
self->phy_get_link_status = eth_phy_dp838xx_get_link_status;
193+
} else if (phy_type == ETH_PHY_LAN8720 || phy_type == ETH_PHY_LAN8742) {
194+
self->phy_get_link_status = eth_phy_lan87xx_get_link_status;
195+
} else {
196+
return -1;
197+
}
209198

210199
// Configure GPIO
211200
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) {
230219
#else
231220
__HAL_RCC_ETH_CLK_ENABLE();
232221
#endif
222+
return 0;
233223
}
234224

235225
void eth_set_trace(eth_t *self, uint32_t value) {
@@ -381,6 +371,14 @@ static int eth_mac_init(eth_t *self) {
381371
break;
382372
case 1:
383373
if (bsr & PHY_BSR_LINK_STATUS) {
374+
// Announce all modes
375+
eth_phy_write(self->phy_addr, PHY_ANAR,
376+
PHY_ANAR_SPEED_10HALF |
377+
PHY_ANAR_SPEED_10FULL |
378+
PHY_ANAR_SPEED_100HALF |
379+
PHY_ANAR_SPEED_100FULL |
380+
PHY_ANAR_IEEE802_3);
381+
// Start autonegotiate.
384382
eth_phy_write(self->phy_addr, PHY_BCR, PHY_BCR_AUTONEG_EN);
385383
phy_state = 2;
386384
}
@@ -396,7 +394,7 @@ static int eth_mac_init(eth_t *self) {
396394
}
397395

398396
// Get register with link status
399-
uint16_t phy_scsr = eth_phy_read(self->phy_addr, PHY_SCSR);
397+
uint16_t phy_scsr = self->phy_get_link_status(self->phy_addr);
400398

401399
// Burst mode configuration
402400
#if defined(STM32H5) || defined(STM32H7)
@@ -505,9 +503,9 @@ static int eth_mac_init(eth_t *self) {
505503

506504
// Set main MAC control register
507505
ETH->MACCR =
508-
(phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_10FULL ? ETH_MACCR_DM
509-
: (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100HALF ? ETH_MACCR_FES
510-
: (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM)
506+
phy_scsr == PHY_SPEED_10FULL ? ETH_MACCR_DM
507+
: phy_scsr == PHY_SPEED_100HALF ? ETH_MACCR_FES
508+
: phy_scsr == PHY_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM)
511509
: 0
512510
;
513511
mp_hal_delay_ms(2);

Diff for: ports/stm32/eth.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,17 @@
2626
#ifndef MICROPY_INCLUDED_STM32_ETH_H
2727
#define MICROPY_INCLUDED_STM32_ETH_H
2828

29+
enum {
30+
ETH_PHY_LAN8742 = 0,
31+
ETH_PHY_LAN8720,
32+
ETH_PHY_DP83848,
33+
ETH_PHY_DP83825
34+
};
35+
2936
typedef struct _eth_t eth_t;
3037
extern eth_t eth_instance;
3138

32-
void eth_init(eth_t *self, int mac_idx, uint32_t phy_addr);
39+
int eth_init(eth_t *self, int mac_idx, uint32_t phy_addr, int phy_type);
3340
void eth_set_trace(eth_t *self, uint32_t value);
3441
struct netif *eth_netif(eth_t *self);
3542
int eth_link_status(eth_t *self);

Diff for: ports/stm32/eth_phy.c

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2019 Damien P. George
7+
* Copyright (c) 2024 Robert Hammelrath
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#include "py/mphal.h"
29+
#include "eth_phy.h"
30+
31+
#if defined(MICROPY_HW_ETH_MDC)
32+
33+
#define PHY_SCSR_LAN87XX (0x001f)
34+
#define PHY_SCSR_LAN87XX_SPEED_Pos (2)
35+
#define PHY_SCSR_LAN87XX_SPEED_Msk (7)
36+
37+
#define PHY_SCSR_DP838XX (0x0010)
38+
#define PHY_RECR_DP838XX (0x0015)
39+
#define PHY_SCSR_DP838XX_DUPLEX_Msk (4)
40+
#define PHY_SCSR_DP838XX_10M_Msk (2)
41+
42+
int16_t eth_phy_lan87xx_get_link_status(uint32_t phy_addr) {
43+
// Get the link mode & speed
44+
int16_t scsr = eth_phy_read(phy_addr, PHY_SCSR_LAN87XX);
45+
return (scsr >> PHY_SCSR_LAN87XX_SPEED_Pos) & PHY_SCSR_LAN87XX_SPEED_Msk;
46+
}
47+
48+
int16_t eth_phy_dp838xx_get_link_status(uint32_t phy_addr) {
49+
int16_t scsr = 0;
50+
// Get the link mode & speed
51+
uint16_t temp = eth_phy_read(phy_addr, PHY_SCSR_DP838XX);
52+
scsr = (temp & PHY_SCSR_DP838XX_10M_Msk) ? PHY_SPEED_10HALF : PHY_SPEED_100HALF;
53+
if (temp & PHY_SCSR_DP838XX_DUPLEX_Msk) {
54+
scsr |= PHY_DUPLEX;
55+
}
56+
return scsr;
57+
}
58+
59+
#endif

Diff for: ports/stm32/eth_phy.h

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2019 Damien P. George
7+
* Copyright (c) 2024 Robert Hammelrath
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#ifndef MICROPY_INCLUDED_STM32_PHY_H
29+
#define MICROPY_INCLUDED_STM32_PYH_H
30+
31+
#if defined(MICROPY_HW_ETH_MDC)
32+
33+
// Common ETH PHY register definitions
34+
#undef PHY_BCR
35+
#define PHY_BCR (0x0000)
36+
#define PHY_BCR_SOFT_RESET (0x8000)
37+
#define PHY_BCR_AUTONEG_EN (0x1000)
38+
#define PHY_BCR_POWER_DOWN (0x0800U)
39+
40+
#undef PHY_BSR
41+
#define PHY_BSR (0x0001)
42+
#define PHY_BSR_LINK_STATUS (0x0004)
43+
#define PHY_BSR_AUTONEG_DONE (0x0020)
44+
45+
#undef PHY_ANAR
46+
#define PHY_ANAR (0x0004)
47+
#define PHY_ANAR_SPEED_10HALF (0x0020)
48+
#define PHY_ANAR_SPEED_10FULL (0x0040)
49+
#define PHY_ANAR_SPEED_100HALF (0x0080)
50+
#define PHY_ANAR_SPEED_100FULL (0x0100)
51+
#define PHY_ANAR_IEEE802_3 (0x0001)
52+
53+
#define PHY_SPEED_10HALF (1)
54+
#define PHY_SPEED_10FULL (5)
55+
#define PHY_SPEED_100HALF (2)
56+
#define PHY_SPEED_100FULL (6)
57+
#define PHY_DUPLEX (4)
58+
59+
uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg);
60+
void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val);
61+
62+
int16_t eth_phy_lan87xx_get_link_status(uint32_t phy_addr);
63+
int16_t eth_phy_dp838xx_get_link_status(uint32_t phy_addr);
64+
65+
#endif
66+
67+
#endif // MICROPY_INCLUDED_STM32_PHY_H

Diff for: ports/stm32/network_lan.c

+10-2
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,19 @@ static void network_lan_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
5454
}
5555

5656
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) {
57-
enum { ARG_phy_addr};
57+
enum { ARG_phy_addr, ARG_phy_type};
5858
static const mp_arg_t allowed_args[] = {
5959
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
60+
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ETH_PHY_LAN8742} },
6061
};
6162
// Parse args.
6263
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
6364
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
6465

6566
const network_lan_obj_t *self = &network_lan_eth0;
66-
eth_init(self->eth, MP_HAL_MAC_ETH0, args[ARG_phy_addr].u_int);
67+
if (eth_init(self->eth, MP_HAL_MAC_ETH0, args[ARG_phy_addr].u_int, args[ARG_phy_type].u_int) != 0) {
68+
mp_raise_ValueError(MP_ERROR_TEXT("invalid phy_type"));
69+
}
6770
return MP_OBJ_FROM_PTR(self);
6871
}
6972

@@ -162,6 +165,11 @@ static const mp_rom_map_elem_t network_lan_locals_dict_table[] = {
162165
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_lan_ifconfig_obj) },
163166
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_lan_status_obj) },
164167
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_lan_config_obj) },
168+
169+
{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8742), MP_ROM_INT(ETH_PHY_LAN8742) },
170+
{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(ETH_PHY_LAN8720) },
171+
{ MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(ETH_PHY_DP83848) },
172+
{ MP_ROM_QSTR(MP_QSTR_PHY_DP83825), MP_ROM_INT(ETH_PHY_DP83825) },
165173
};
166174
static MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table);
167175

0 commit comments

Comments
 (0)