From 9d6ae8ffab93aa6defb3c08b895499332738f09e Mon Sep 17 00:00:00 2001 From: Jon Escombe Date: Fri, 21 Jun 2024 17:07:19 +0100 Subject: [PATCH] Improved MAC address handling for onboard Ethernet First three bytes are ST OUI prefix, but with LAA bit set. Last three bytes from a CRC32 hash of the 96 bit chip UID. Optional new setting ($535) for overriding address. --- LWIP/Target/ethernetif.c | 9 +++++-- Src/driver.c | 56 +++++++++++++++++++++++++++++++++++++++- Src/enet.c | 43 +++++++++++++++++++++++++----- 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/LWIP/Target/ethernetif.c b/LWIP/Target/ethernetif.c index bd464e2..6827aff 100644 --- a/LWIP/Target/ethernetif.c +++ b/LWIP/Target/ethernetif.c @@ -33,7 +33,7 @@ /* Within 'USER CODE' section, code will be kept by default at each generation */ /* USER CODE BEGIN 0 */ - +#include "networking/networking.h" /* USER CODE END 0 */ /* Private define ------------------------------------------------------------*/ @@ -161,7 +161,7 @@ static void low_level_init(struct netif *netif) HAL_StatusTypeDef hal_eth_init_status = HAL_OK; /* Start ETH HAL Init */ - uint8_t MACAddr[6] ; + uint8_t MACAddr[6] ; heth.Instance = ETH; MACAddr[0] = 0x00; MACAddr[1] = 0x80; @@ -177,6 +177,11 @@ static void low_level_init(struct netif *netif) /* USER CODE BEGIN MACADDRESS */ + uint8_t mac[6]; + + if(bmac_eth_get(mac)) + heth.Init.MACAddr = &mac[0]; + /* USER CODE END MACADDRESS */ hal_eth_init_status = HAL_ETH_Init(&heth); diff --git a/Src/driver.c b/Src/driver.c index 970743f..5841f68 100644 --- a/Src/driver.c +++ b/Src/driver.c @@ -1848,6 +1848,60 @@ void setPeriphPinDescription (const pin_function_t function, const pin_group_t g } while(ppin); } + +#if ETHERNET_ENABLE + +uint32_t crc32_bitwise(const void* data, size_t length) +{ + const uint32_t polynomial = 0xEDB88320; + uint32_t crc = 0xFFFFFFFF; + unsigned char* current = (unsigned char*) data; + while (length--) + { + crc ^= *current++; + for (unsigned int j = 0; j < 8; j++) + if (crc & 1) + crc = (crc >> 1) ^ polynomial; + else + crc = crc >> 1; + } + return ~crc; +} + +bool bmac_eth_get (uint8_t mac[6]) +{ +#if defined(_WIZCHIP_) + // WizNet OUI prefix + mac[0] = 0x00; + mac[1] = 0x08; + mac[2] = 0xDC; +#else + // ST OUI prefix + mac[0] = 0x00; + mac[1] = 0x80; + mac[2] = 0xE1; +#endif + + // Set LAA bit + mac[0] |= 0x02; + + // Get 96 bit unique device identifier + uint32_t uid[3]; + uid[0] = HAL_GetUIDw0(); + uid[1] = HAL_GetUIDw1(); + uid[2] = HAL_GetUIDw2(); + + // Generate 32bit CRC from 96 bit UID + uint32_t crc = crc32_bitwise(uid, 12); + + // Copy first 24bits of the CRC into the MAC address + memcpy(&mac[3], &crc, 3); + + return true; +} + +#endif // ETHERNET_ENABLE + // Initializes MCU peripherals for Grbl use static bool driver_setup (settings_t *settings) { @@ -2112,7 +2166,7 @@ bool driver_init (void) hal.info = "STM32H743"; #endif - hal.driver_version = "240522"; + hal.driver_version = "240624"; hal.driver_url = "https://github.com/dresco/STM32H7xx"; #ifdef BOARD_NAME hal.board = BOARD_NAME; diff --git a/Src/enet.c b/Src/enet.c index 8e13fc1..e226898 100644 --- a/Src/enet.c +++ b/Src/enet.c @@ -3,20 +3,20 @@ Part of grblHAL - Copyright (c) 2021-2023 Terje Io + Copyright (c) 2021-2024 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - Grbl is distributed in the hope that it will be useful, + grblHAL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with Grbl. If not, see . + along with grblHAL. If not, see . */ #include "driver.h" @@ -93,8 +93,15 @@ static void report_options (bool newopt) hal.stream.write(",SSDP"); #endif } else { + + network_info_t *network = networking_get_info(); + + hal.stream.write("[MAC:"); + hal.stream.write(network->mac); + hal.stream.write("]" ASCII_EOL); + hal.stream.write("[IP:"); - hal.stream.write(IPAddress); + hal.stream.write(network->status.ip); hal.stream.write("]" ASCII_EOL); if(active_stream == StreamType_Telnet || active_stream == StreamType_WebSocket) { @@ -141,7 +148,7 @@ network_info_t *networking_get_info (void) ip4addr_ntoa_r(netif_ip_netmask4(netif), info.status.mask, IP4ADDR_STRLEN_MAX); } - sprintf(info.mac, MAC_FORMAT_STRING, netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); + strcpy(info.mac, networking_mac_to_string(netif->hwaddr)); } #if MQTT_ENABLE @@ -381,6 +388,18 @@ static char *ethernet_get_ip (setting_id_t setting); static status_code_t ethernet_set_services (setting_id_t setting, uint_fast16_t int_value); static uint32_t ethernet_get_services (setting_id_t id); +#ifdef HAS_MAC_SETTING +static status_code_t ethernet_set_mac (setting_id_t setting, char *value) +{ + return networking_string_to_mac(value, ethernet.mac) ? Status_OK : Status_InvalidStatement; +} + +static char *ethernet_get_mac (setting_id_t setting) +{ + return networking_mac_to_string(ethernet.mac); +} +#endif + static const setting_group_detail_t ethernet_groups [] = { { Group_Root, Group_Networking, "Networking" } }; @@ -392,6 +411,9 @@ static const setting_detail_t ethernet_settings[] = { { Setting_IpAddress, Group_Networking, "IP Address", NULL, Format_IPv4, NULL, NULL, NULL, Setting_NonCoreFn, ethernet_set_ip, ethernet_get_ip, NULL, { .reboot_required = On } }, { Setting_Gateway, Group_Networking, "Gateway", NULL, Format_IPv4, NULL, NULL, NULL, Setting_NonCoreFn, ethernet_set_ip, ethernet_get_ip, NULL, { .reboot_required = On } }, { Setting_NetMask, Group_Networking, "Netmask", NULL, Format_IPv4, NULL, NULL, NULL, Setting_NonCoreFn, ethernet_set_ip, ethernet_get_ip, NULL, { .reboot_required = On } }, +#ifdef HAS_MAC_SETTING + { Setting_NetworkMAC, Group_Networking, "MAC Address", NULL , Format_String, "x(17)", "17", "17", Setting_NonCoreFn, ethernet_set_mac, ethernet_get_mac, NULL, { .allow_null = On, .reboot_required = On } }, +#endif { Setting_TelnetPort, Group_Networking, "Telnet port", NULL, Format_Int16, "####0", "1", "65535", Setting_NonCore, ðernet.telnet_port, NULL, NULL, { .reboot_required = On } }, #if FTP_ENABLE { Setting_FtpPort, Group_Networking, "FTP port", NULL, Format_Int16, "####0", "1", "65535", Setting_NonCore, ðernet.ftp_port, NULL, NULL, { .reboot_required = On } }, @@ -417,6 +439,9 @@ static const setting_descr_t ethernet_settings_descr[] = { { Setting_IpAddress, "Static IP address." }, { Setting_Gateway, "Static gateway address." }, { Setting_NetMask, "Static netmask." }, +#ifdef HAS_MAC_SETTING + { Setting_NetworkMAC, "Optional MAC address. Tip: get from an unused device, e.g an old router." }, +#endif { Setting_TelnetPort, "(Raw) Telnet port number listening for incoming connections." }, #if FTP_ENABLE { Setting_FtpPort, "FTP port number listening for incoming connections." }, @@ -561,6 +586,10 @@ void ethernet_settings_restore (void) set_addr(ethernet.mask, &addr); #endif +#ifdef HAS_MAC_SETTING + bmac_eth_get(ethernet.mac); +#endif + ethernet.ftp_port = NETWORK_FTP_PORT; ethernet.telnet_port = NETWORK_TELNET_PORT; ethernet.http_port = NETWORK_HTTP_PORT;