mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik lwip MAC Adresse ändern


Autor: user (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,

auf meinem Mikrocontroller läuft eine Ethernetkommunikation mit dem lwip 
Stack. In der Applikation soll die MAC Adresse abgeändert werden können.
Für die Initialisierung der MAC Adresse gibt es eine Funktion mit dem 
Namen
"low_level_init".

Ausschnitt von der Funktion "low_level_init":
static void
low_level_init(struct netif *netif)
{
  XMC_ETH_MAC_PORT_CTRL_t port_control;
  XMC_GPIO_CONFIG_t gpio_config;

  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;

  /* set MAC hardware address */
  netif->hwaddr[0] =  MAC_ADDR0;
  netif->hwaddr[1] =  MAC_ADDR1;
  netif->hwaddr[2] =  MAC_ADDR2;
  netif->hwaddr[3] =  MAC_ADDR3;
  netif->hwaddr[4] =  MAC_ADDR4;
  netif->hwaddr[5] =  MAC_ADDR5;

...

Die MAC Adresse liegt als define in der Datei ethernetif.c vor wo sich 
auch die obige Funktion befindet. Wie könnte eine andere MAC Adresse von 
der Hauptapplikation dieser Funktion übergeben werden?

Autor: TK (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wie könnte eine andere MAC Adresse von
>der Hauptapplikation dieser Funktion übergeben werden?
Evtl. indem man nach Aufruf der oben gezeigen Funktion
das Array hwaddr[0]..[5] nochmal neu belegt.
ODER
Indem man die Funktion so abändert, dass eine MAC-Adr als Parameter
an diese übergeben wird. Und dann werden nicht mehr die DEFINES
zugewiesen, sondern der Übergabeparameter.

Gruß
TK

Autor: Matthias F. (frank91)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Beitrag ist schon etwas älter.
Ich hatte allerdings gerade das selbe Problem.
Da hier noch kein Beispiel gezeigt wurde poste ich hier nun eines.

>>Wie könnte eine andere MAC Adresse von
>>der Hauptapplikation dieser Funktion übergeben werden?
> Evtl. indem man nach Aufruf der oben gezeigen Funktion
> das Array hwaddr[0]..[5] nochmal neu belegt.

Nach dem Initialisieren, also zur Laufzeit die Mac Adresse ändern ist 
denke ich schlecht. Ich weiß nicht ob DHCP dann richtig arbeiten kann.

Funktionierende Lösung:
static void low_level_init(struct netif *netif)
{ 
  uint32_t regvalue = 0;
  HAL_StatusTypeDef hal_eth_init_status;
  
/* Init ETH */

   uint8_t MACAddr[6] ;
  heth.Instance = ETH;
  heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
  heth.Init.Speed = ETH_SPEED_100M;
  heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
  heth.Init.PhyAddress = DP83848_PHY_ADDRESS;
  MACAddr[0] = 0x00;
  MACAddr[1] = 0x80;
  MACAddr[2] = 0xE1;
  MACAddr[3] = 0x00;
  MACAddr[4] = 0x00;
  MACAddr[5] = 0x00;
  heth.Init.MACAddr = &MACAddr[0];
  heth.Init.RxMode = ETH_RXPOLLING_MODE;
  heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
  heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;

  /* USER CODE BEGIN MACADDRESS */
  MACAddr[0] = EEPROM_Daten.macAdresse[0];
  MACAddr[1] = EEPROM_Daten.macAdresse[1];
  MACAddr[2] = EEPROM_Daten.macAdresse[2];
  MACAddr[3] = EEPROM_Daten.macAdresse[3];
  MACAddr[4] = EEPROM_Daten.macAdresse[4];
  MACAddr[5] = EEPROM_Daten.macAdresse[5];
  /* USER CODE END MACADDRESS */

  hal_eth_init_status = HAL_ETH_Init(&heth);

Autor: Ruediger A. (Firma: keine) (rac)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uhm, wird hier etwas im Nebel gestochert?

Die MAC Adresse wird an ZWEI Stellen gebraucht:

1. Bei der Konfiguration des MAC, damit er auf die Adresse filtern kann
  (es werden, solange der MAC nicht im promiscuous mode fährt)
   nur Broadcasts (Ziel MAC ff:ff:ff:ff:ff:ff) und die MAC Adresse
   des Interfaces zum DMA Rx Ringbuffer weitergeleitet).
   Das passiert beim Standard Cortex Treiber z.B. in
   ETH_MacAddressConfig(), indem dem POD die MAC
   ins passende Register geschrieben wird.
2. Im Software Layer, damit der u.A. jedes ausgehende Paket mit der
   MAC Adresse des Interfaces prefixen kann. Das wird i.d. Regel
   in low_level_init() über netif->hwaddr gemacht.

Man muss unbedingt in beiden Stellen parallel immer dieselbe Adresse 
vorhalten. Was passiert, wenn man das nur an einer Stelle macht, ist 
eine Denkaufgabe fürs erste Semester.

In deinem Codefragment fehlt die Zuweisung in 2. oben, aber ich vermute, 
dass Du die nach  HAL_ETH_Init() machst, und zwar indem Du netif->hwaddr 
auf MACAddr setzt. Dann bist Du natürlich wieder synchron, und alles ist 
gut. Würdest Du aber das Patchen von MACAddr hinter HAL_ETH_Init aber 
vor dem Setzen von netif->hwaddr machen, würde es nicht gehen.

Man kann zur Laufzeit die MAC Adresse ändern (solange man das an beiden 
Stellen synchron macht; bei manchen MACs wird ausserdem eine 
Reiniaitliserung des MAC interfaces nötig), aber dann lassen sich 
keinerlei Annamhmen mehr über das Verhalten von momentan offenen 
Netzwerkverbindungen machen. Am saubersten ist ein komplettes 
herunterfahren und Neuafsetzen des Interfaces in Software.

DHCP Server werden sich in der Regel nicht dran stören, wenn ein Client 
eine neue MAC Adresse dynamisch bekommt; der Client wird dann aber einen 
neuen DHCP request absetzen müssen und im Zweifelsfall eine neue IP 
Adresse bekommen. Hast Du allerdings eine statische IP Adresse, dann 
werden alle Maschinen, die offene Verbindungen mit deinem Gerät hatten, 
nicht mehr damit kommunizieren können, bis der Entry im ARP cache 
geflusht und ein neuer ARP request abgesetzt wurde. Wie lange das 
dauert, hängt von der Konfiguration der Maschinen ab. Können gut 24 
Stunden sein, in denen ARP Einträge vorgehalten werden.

Ausserdem gibt es viele Router, die Port Monitoring betrieben und den 
Port sofort zumachen, wenn eine andere MAC Adresse dort auftaucht.

: Bearbeitet durch User
Autor: Matthias F. (frank91)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier das komplette Unterprogramm.
wenn ich dich richtig verstanden habe, habe ich so alles richtig 
gemacht?

"ETH_MACAddressConfig" befindet sich ein wenig verschachtelt in der 
"HAL_ETH_Init".
"netif->hwaddr" kommt nach "HAL_ETH_Init".


Im Endeffekt habe ich den Original Code komplett beibehalten. Lediglich 
in
/* USER CODE BEGIN MACADDRESS */
  /* USER CODE END MACADDRESS */
habe ich etwas eingefügt.


Wenn ich am PC über die Konsole die Mac Adresse des Controllers auslese, 
erhalte ich dort auch die gewünschte Adresse.
/*******************************************************************************
                       LL Driver Interface ( LwIP stack --> ETH) 
*******************************************************************************/
/**
 * In this function, the hardware should be initialized.
 * Called from ethernetif_init().
 *
 * @param netif the already initialized lwip network interface structure
 *        for this ethernetif
 */
static void low_level_init(struct netif *netif)
{ 
  uint32_t regvalue = 0;
  HAL_StatusTypeDef hal_eth_init_status;
  
/* Init ETH */

   uint8_t MACAddr[6] ;
  heth.Instance = ETH;
  heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
  heth.Init.Speed = ETH_SPEED_100M;
  heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
  heth.Init.PhyAddress = DP83848_PHY_ADDRESS;
  MACAddr[0] = 0x00;
  MACAddr[1] = 0x80;
  MACAddr[2] = 0xE1;
  MACAddr[3] = 0x00;
  MACAddr[4] = 0x00;
  MACAddr[5] = 0x00;
  heth.Init.MACAddr = &MACAddr[0];
  heth.Init.RxMode = ETH_RXPOLLING_MODE;
  heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
  heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;

  /* USER CODE BEGIN MACADDRESS */
  MACAddr[0] = EEPROM_Daten.macAdresse[0];
  MACAddr[1] = EEPROM_Daten.macAdresse[1];
  MACAddr[2] = EEPROM_Daten.macAdresse[2];
  MACAddr[3] = EEPROM_Daten.macAdresse[3];
  MACAddr[4] = EEPROM_Daten.macAdresse[4];
  MACAddr[5] = EEPROM_Daten.macAdresse[5];
  /* USER CODE END MACADDRESS */

  hal_eth_init_status = HAL_ETH_Init(&heth);

  if (hal_eth_init_status == HAL_OK)
  {
    /* Set netif link flag */  
    netif->flags |= NETIF_FLAG_LINK_UP;
  }
  /* Initialize Tx Descriptors list: Chain Mode */
  HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
     
  /* Initialize Rx Descriptors list: Chain Mode  */
  HAL_ETH_DMARxDescListInit(&heth, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
 
#if LWIP_ARP || LWIP_ETHERNET 

  /* set MAC hardware address length */
  netif->hwaddr_len = ETH_HWADDR_LEN;
  
  /* set MAC hardware address */
  netif->hwaddr[0] =  heth.Init.MACAddr[0];
  netif->hwaddr[1] =  heth.Init.MACAddr[1];
  netif->hwaddr[2] =  heth.Init.MACAddr[2];
  netif->hwaddr[3] =  heth.Init.MACAddr[3];
  netif->hwaddr[4] =  heth.Init.MACAddr[4];
  netif->hwaddr[5] =  heth.Init.MACAddr[5];
  
  /* maximum transfer unit */
  netif->mtu = 1500;
  
  /* Accept broadcast address and ARP traffic */
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  #if LWIP_ARP
    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
  #else 
    netif->flags |= NETIF_FLAG_BROADCAST;
  #endif /* LWIP_ARP */
  
  /* Enable MAC and DMA transmission and reception */
  HAL_ETH_Start(&heth);

/* USER CODE BEGIN PHY_PRE_CONFIG */ 
    
/* USER CODE END PHY_PRE_CONFIG */
  
  /**** Configure PHY to generate an interrupt when Eth Link state changes ****/
  /* Read Register Configuration */
  HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, &regvalue);
  
  regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);

  /* Enable Interrupts */
  HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue );
  
  /* Read Register Configuration */
  HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, &regvalue);
  
  regvalue |= PHY_MISR_LINK_INT_EN;
    
  /* Enable Interrupt on change of link status */
  HAL_ETH_WritePHYRegister(&heth, PHY_MISR, regvalue);

/* USER CODE BEGIN PHY_POST_CONFIG */ 
    
/* USER CODE END PHY_POST_CONFIG */

#endif /* LWIP_ARP || LWIP_ETHERNET */

/* USER CODE BEGIN LOW_LEVEL_INIT */ 
    
/* USER CODE END LOW_LEVEL_INIT */
}


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.