Skip to content

Commit

Permalink
Improved MAC address handling for onboard Ethernet
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dresco committed Jun 25, 2024
1 parent 874cf6d commit 9d6ae8f
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 10 deletions.
9 changes: 7 additions & 2 deletions LWIP/Target/ethernetif.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ------------------------------------------------------------*/
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
56 changes: 55 additions & 1 deletion Src/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down
43 changes: 36 additions & 7 deletions Src/enet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/

#include "driver.h"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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" }
};
Expand All @@ -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, &ethernet.telnet_port, NULL, NULL, { .reboot_required = On } },
#if FTP_ENABLE
{ Setting_FtpPort, Group_Networking, "FTP port", NULL, Format_Int16, "####0", "1", "65535", Setting_NonCore, &ethernet.ftp_port, NULL, NULL, { .reboot_required = On } },
Expand All @@ -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." },
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 9d6ae8f

Please sign in to comment.