Skip to content

Commit af20cee

Browse files
committed
stm32/ethernet: Add the phy_type=x keyword option to network.LAN().
With LAN8742, LAN8720 and DP83848 as initial selection and the symbols PHY_LAN8720, PHY_LAN8742 and PHY_DP8348. The default is PHY_LAN8742. Tested with LAN8720 and DP83848 breakout boards at 10M Duplex and 100M Duplex modes. Signed-off-by: robert-hh <robert@hammelrath.com>
1 parent 80e92f7 commit af20cee

File tree

6 files changed

+166
-30
lines changed

6 files changed

+166
-30
lines changed

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+
phy.c \
254255
gccollect.c \
255256
help.c \
256257
machine_bitstream.c \

ports/stm32/eth.c

+25-27
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@
2626

2727
#include <string.h>
2828
#include "py/mphal.h"
29+
#include "py/runtime.h"
2930
#include "py/mperrno.h"
3031
#include "shared/netutils/netutils.h"
3132
#include "pin_static_af.h"
3233
#include "extmod/modnetwork.h"
3334
#include "mpu.h"
3435
#include "eth.h"
36+
#include "phy.h"
3537

3638
#if defined(MICROPY_HW_ETH_MDC)
3739

@@ -40,26 +42,6 @@
4042
#include "lwip/dhcp.h"
4143
#include "netif/ethernet.h"
4244

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-
6345
// ETH DMA RX and TX descriptor definitions
6446
#if defined(STM32H5)
6547
#define RX_DESCR_3_OWN_Pos (31)
@@ -137,6 +119,7 @@ typedef struct _eth_t {
137119
struct netif netif;
138120
struct dhcp dhcp_struct;
139121
uint32_t phy_addr;
122+
int16_t (*phy_get_link_status)(uint32_t phy_addr);
140123
} eth_t;
141124

142125
static eth_dma_t eth_dma __attribute__((aligned(16384)));
@@ -146,7 +129,7 @@ eth_t eth_instance;
146129
STATIC void eth_mac_deinit(eth_t *self);
147130
STATIC void eth_process_frame(eth_t *self, size_t len, const uint8_t *buf);
148131

149-
STATIC void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
132+
void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
150133
#if defined(STM32H5) || defined(STM32H7)
151134
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
152135
}
@@ -172,7 +155,7 @@ STATIC void eth_phy_write(uint32_t phy_addr, uint32_t reg, uint32_t val) {
172155
#endif
173156
}
174157

175-
STATIC uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
158+
uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
176159
#if defined(STM32H5) || defined(STM32H7)
177160
while (ETH->MACMDIOAR & ETH_MACMDIOAR_MB) {
178161
}
@@ -198,10 +181,17 @@ STATIC uint32_t eth_phy_read(uint32_t phy_addr, uint32_t reg) {
198181
#endif
199182
}
200183

201-
void eth_init(eth_t *self, int mac_idx, int phy_addr) {
184+
void eth_init(eth_t *self, int mac_idx, int phy_addr, int phy_type) {
202185
mp_hal_get_mac(mac_idx, &self->netif.hwaddr[0]);
203186
self->netif.hwaddr_len = 6;
204187
self->phy_addr = phy_addr;
188+
if (phy_type == PHY_DP83848) {
189+
self->phy_get_link_status = phy_dp83848_get_link_status;
190+
} else if (phy_type == PHY_LAN8720 || phy_type == PHY_LAN8742) {
191+
self->phy_get_link_status = phy_lan87xx_get_link_status;
192+
} else {
193+
mp_raise_ValueError(MP_ERROR_TEXT("Invalid phy_type"));
194+
}
205195

206196
// Configure GPIO
207197
mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDC);
@@ -377,6 +367,14 @@ STATIC int eth_mac_init(eth_t *self) {
377367
break;
378368
case 1:
379369
if (bsr & PHY_BSR_LINK_STATUS) {
370+
// Announce all modes
371+
eth_phy_write(self->phy_addr, PHY_ANAR,
372+
PHY_ANAR_SPEED_10HALF |
373+
PHY_ANAR_SPEED_10FULL |
374+
PHY_ANAR_SPEED_100HALF |
375+
PHY_ANAR_SPEED_100FULL |
376+
PHY_ANAR_IEEE802_3);
377+
// Start autonegotiate.
380378
eth_phy_write(self->phy_addr, PHY_BCR, PHY_BCR_AUTONEG_EN);
381379
phy_state = 2;
382380
}
@@ -392,7 +390,7 @@ STATIC int eth_mac_init(eth_t *self) {
392390
}
393391

394392
// Get register with link status
395-
uint16_t phy_scsr = eth_phy_read(self->phy_addr, PHY_SCSR);
393+
uint16_t phy_scsr = self->phy_get_link_status(self->phy_addr);
396394

397395
// Burst mode configuration
398396
#if defined(STM32H5) || defined(STM32H7)
@@ -501,9 +499,9 @@ STATIC int eth_mac_init(eth_t *self) {
501499

502500
// Set main MAC control register
503501
ETH->MACCR =
504-
(phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_10FULL ? ETH_MACCR_DM
505-
: (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100HALF ? ETH_MACCR_FES
506-
: (phy_scsr & PHY_SCSR_SPEED_Msk) == PHY_SCSR_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM)
502+
phy_scsr == PHY_SPEED_10FULL ? ETH_MACCR_DM
503+
: phy_scsr == PHY_SPEED_100HALF ? ETH_MACCR_FES
504+
: phy_scsr == PHY_SPEED_100FULL ? (ETH_MACCR_FES | ETH_MACCR_DM)
507505
: 0
508506
;
509507
mp_hal_delay_ms(2);

ports/stm32/eth.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@
2929
typedef struct _eth_t eth_t;
3030
extern eth_t eth_instance;
3131

32-
void eth_init(eth_t *self, int mac_idx, int phy_addr);
32+
void eth_init(eth_t *self, int mac_idx, int phy_addr, int phy_type);
3333
void eth_set_trace(eth_t *self, uint32_t value);
3434
struct netif *eth_netif(eth_t *self);
3535
int eth_link_status(eth_t *self);
3636
int eth_start(eth_t *self);
3737
int eth_stop(eth_t *self);
3838
void eth_low_power_mode(eth_t *self, bool enable);
3939

40+
enum {
41+
PHY_DP83848 = 0,
42+
PHY_LAN8720,
43+
PHY_LAN8742,
44+
};
45+
4046
#endif // MICROPY_INCLUDED_STM32_ETH_H

ports/stm32/network_lan.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,17 @@ 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 = 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+
eth_init(self->eth, MP_HAL_MAC_ETH0, args[ARG_phy_addr].u_int, args[ARG_phy_type].u_int);
6768
return MP_OBJ_FROM_PTR(self);
6869
}
6970

@@ -162,6 +163,10 @@ STATIC const mp_rom_map_elem_t network_lan_locals_dict_table[] = {
162163
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_lan_ifconfig_obj) },
163164
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_lan_status_obj) },
164165
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_lan_config_obj) },
166+
167+
{ MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(PHY_DP83848) },
168+
{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) },
169+
{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8742), MP_ROM_INT(PHY_LAN8742) },
165170
};
166171
STATIC MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table);
167172

ports/stm32/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 "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_DP83848 (0x0010)
38+
#define PHY_RECR_DP83848 (0x0015)
39+
#define PHY_SCSR_DP83848_DUPLEX_Msk (4)
40+
#define PHY_SCSR_DP83848_10M_Msk (2)
41+
42+
int16_t 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 phy_dp83848_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_DP83848);
52+
scsr = (temp & PHY_SCSR_DP83848_10M_Msk) ? PHY_SPEED_10HALF : PHY_SPEED_100HALF;
53+
if (temp & PHY_SCSR_DP83848_DUPLEX_Msk) {
54+
scsr |= PHY_DUPLEX;
55+
}
56+
return scsr;
57+
}
58+
59+
#endif

ports/stm32/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 phy_lan87xx_get_link_status(uint32_t phy_addr);
63+
int16_t phy_dp83848_get_link_status(uint32_t phy_addr);
64+
65+
#endif
66+
67+
#endif // MICROPY_INCLUDED_STM32_PHY_H

0 commit comments

Comments
 (0)