6565#endif
6666
6767/* Interrupt events to process: reception, transmission and error handling. */
68- #define EMAC_IF_RX_EVENT 1UL
69- #define EMAC_IF_TX_EVENT 2UL
70- #define EMAC_IF_ERR_EVENT 4UL
68+ #define EMAC_IF_RX_EVENT 1UL
69+ #define EMAC_IF_TX_EVENT 2UL
70+ #define EMAC_IF_ERR_EVENT 4UL
7171
72+ /*
73+ * Enable either Hash or Perfect Filter, Multicast filter - None,
74+ * Enable Hash Multicast (HMC), and Enable Hash Unicast (HUC).
75+ */
76+ #define ENABLE_HASH_FILTER_SETTINGS ( ( uint32_t ) 0x00000416U )
7277
7378#ifndef niEMAC_HANDLER_TASK_NAME
7479 #define niEMAC_HANDLER_TASK_NAME "EMAC-task"
@@ -205,33 +210,91 @@ const PhyProperties_t xPHYProperties =
205210};
206211/*-----------------------------------------------------------*/
207212
208- static void prvMACAddressConfig ( ETH_HandleTypeDef * heth ,
209- uint32_t ulIndex ,
210- const uint8_t * Addr )
213+ /* Reverse the bits of a 32 bit unsigned integer */
214+ static uint32_t prvRevBits32 ( uint32_t ulValue )
211215{
212- uint32_t ulTempReg ;
213- uint32_t ulETH_MAC_ADDR_HBASE = ( uint32_t ) & ( heth -> Instance -> MACA0HR );
214- uint32_t ulETH_MAC_ADDR_LBASE = ( uint32_t ) & ( heth -> Instance -> MACA0LR );
216+ uint32_t ulRev32 ;
217+ int iIndex ;
215218
216- /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */
217- configASSERT ( ulIndex >= ETH_MAC_ADDRESS1 );
219+ ulRev32 = 0 ;
218220
219- /* STM32Hxx devices support 4 MAC address registers
220- * (ETH_MAC_ADDRESS0 - ETH_MAC_ADDRESS3), make sure ulIndex is not
221- * more than that. */
222- configASSERT ( ulIndex <= ETH_MAC_ADDRESS3 );
221+ for ( iIndex = 0 ; iIndex < 32 ; iIndex ++ )
222+ {
223+ if ( ulValue & ( 1 << iIndex ) )
224+ {
225+ {
226+ ulRev32 |= 1 << ( 31 - iIndex );
227+ }
228+ }
229+ }
223230
224- /* Calculate the selected MAC address high register. */
225- ulTempReg = 0xBF000000ul | ( ( uint32_t ) Addr [ 5 ] << 8 ) | ( uint32_t ) Addr [ 4 ];
231+ return ulRev32 ;
232+ }
233+
234+ /* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */
235+ static uint32_t prvComputeCRC32_MAC ( const uint8_t * pucMAC )
236+ {
237+ int iiIndex , ijIndex ;
238+ uint32_t ulCRC32 = 0xFFFFFFFF ;
226239
227- /* Load the selected MAC address high register. */
228- ( * ( __IO uint32_t * ) ( ( uint32_t ) ( ulETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg ;
240+ for ( ijIndex = 0 ; ijIndex < 6 ; ijIndex ++ )
241+ {
242+ ulCRC32 = ulCRC32 ^ ( uint32_t ) pucMAC [ ijIndex ];
229243
230- /* Calculate the selected MAC address low register. */
231- ulTempReg = ( ( uint32_t ) Addr [ 3 ] << 24 ) | ( ( uint32_t ) Addr [ 2 ] << 16 ) | ( ( uint32_t ) Addr [ 1 ] << 8 ) | Addr [ 0 ];
244+ for ( iiIndex = 0 ; iiIndex < 8 ; iiIndex ++ )
245+ {
246+ if ( ulCRC32 & 1 )
247+ {
248+ ulCRC32 = ( ulCRC32 >> 1 ) ^ prvRevBits32 ( 0x04C11DB7 ); /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */
249+ }
250+ else
251+ {
252+ ulCRC32 = ( ulCRC32 >> 1 );
253+ }
254+ }
255+ }
232256
233- /* Load the selected MAC address low register */
234- ( * ( __IO uint32_t * ) ( ( uint32_t ) ( ulETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg ;
257+ ulCRC32 = ~( ulCRC32 );
258+ return ulCRC32 ;
259+ }
260+
261+ /* Compute the hash value of a given MAC address to index the bits in the Hash Table
262+ * Registers (ETH_MACHT0R and ETH_MACHT1R) */
263+ static uint32_t prvComputeEthernet_MACHash ( const uint8_t * pucMAC )
264+ {
265+ uint32_t ulCRC32 ;
266+ uint32_t ulHash ;
267+
268+ /* Calculate the 32-bit CRC for the MAC */
269+ ulCRC32 = prvComputeCRC32_MAC ( pucMAC );
270+
271+ /* Perform bitwise reversal on the CRC32 */
272+ ulHash = prvRevBits32 ( ulCRC32 );
273+
274+ /* Take the upper 6 bits of the above result */
275+ return ( ulHash >> 26 );
276+ }
277+
278+ /* Update the Hash Table Registers
279+ * (ETH_MACHT0R and ETH_MACHT1R) with hash value of the given MAC address */
280+ static void prvSetMAC_HashFilter ( ETH_HandleTypeDef * pxEthHandle ,
281+ const uint8_t * pucMAC )
282+ {
283+ uint32_t ulHash ;
284+
285+ /* Compute the hash */
286+ ulHash = prvComputeEthernet_MACHash ( pucMAC );
287+
288+ /* Use the upper (MACHT1R) or lower (MACHT0R) Hash Table Registers
289+ * to set the required bit based on the ulHash */
290+ if ( ulHash < 32 )
291+ {
292+ pxEthHandle -> Instance -> MACHT0R |= ( 1 << ulHash );
293+ }
294+ else
295+ {
296+ pxEthHandle -> Instance -> MACHT1R |= ( 1 << ( ulHash % 32 ) );
297+ }
235298}
236299
237300/*-----------------------------------------------------------*/
@@ -264,7 +327,6 @@ static BaseType_t xSTM32H_NetworkInterfaceInitialise( NetworkInterface_t * pxInt
264327 NetworkEndPoint_t * pxEndPoint ;
265328 HAL_StatusTypeDef xHalEthInitStatus ;
266329 size_t uxIndex = 0 ;
267- BaseType_t xMACEntry = ETH_MAC_ADDRESS1 ; /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */
268330
269331 if ( xMacInitStatus == eMACInit )
270332 {
@@ -294,6 +356,9 @@ static BaseType_t xSTM32H_NetworkInterfaceInitialise( NetworkInterface_t * pxInt
294356 /* Only for inspection by debugger. */
295357 ( void ) xHalEthInitStatus ;
296358
359+ /* Update MAC filter settings */
360+ xEthHandle .Instance -> MACPFR |= ENABLE_HASH_FILTER_SETTINGS ;
361+
297362 /* Configuration for HAL_ETH_Transmit(_IT). */
298363 memset ( & ( xTxConfig ), 0 , sizeof ( ETH_TxPacketConfig ) );
299364 xTxConfig .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD ;
@@ -340,27 +405,23 @@ static BaseType_t xSTM32H_NetworkInterfaceInitialise( NetworkInterface_t * pxInt
340405 #if ( ipconfigUSE_MDNS == 1 )
341406 {
342407 /* Program the MDNS address. */
343- prvMACAddressConfig ( & xEthHandle , xMACEntry , ( uint8_t * ) xMDNS_MacAddress .ucBytes );
344- xMACEntry += 8 ;
408+ prvSetMAC_HashFilter ( & xEthHandle , ( uint8_t * ) xMDNS_MacAddress .ucBytes );
345409 }
346410 #endif
347411 #if ( ( ipconfigUSE_MDNS == 1 ) && ( ipconfigUSE_IPv6 != 0 ) )
348412 {
349- prvMACAddressConfig ( & xEthHandle , xMACEntry , ( uint8_t * ) xMDNS_MACAddressIPv6 .ucBytes );
350- xMACEntry += 8 ;
413+ prvSetMAC_HashFilter ( & xEthHandle , ( uint8_t * ) xMDNS_MacAddressIPv6 .ucBytes );
351414 }
352415 #endif
353416 #if ( ipconfigUSE_LLMNR == 1 )
354417 {
355418 /* Program the LLMNR address. */
356- prvMACAddressConfig ( & xEthHandle , xMACEntry , ( uint8_t * ) xLLMNR_MacAddress .ucBytes );
357- xMACEntry += 8 ;
419+ prvSetMAC_HashFilter ( & xEthHandle , ( uint8_t * ) xLLMNR_MacAddress .ucBytes );
358420 }
359421 #endif
360422 #if ( ( ipconfigUSE_LLMNR == 1 ) && ( ipconfigUSE_IPv6 != 0 ) )
361423 {
362- prvMACAddressConfig ( & xEthHandle , xMACEntry , ( uint8_t * ) xLLMNR_MacAddressIPv6 .ucBytes );
363- xMACEntry += 8 ;
424+ prvSetMAC_HashFilter ( & xEthHandle , ( uint8_t * ) xLLMNR_MacAddressIPv6 .ucBytes );
364425 }
365426 #endif
366427
@@ -377,8 +438,7 @@ static BaseType_t xSTM32H_NetworkInterfaceInitialise( NetworkInterface_t * pxInt
377438
378439 if ( xEthHandle .Init .MACAddr != ( uint8_t * ) pxEndPoint -> xMACAddress .ucBytes )
379440 {
380- prvMACAddressConfig ( & xEthHandle , xMACEntry , pxEndPoint -> xMACAddress .ucBytes );
381- xMACEntry += 8 ;
441+ prvSetMAC_HashFilter ( & xEthHandle , pxEndPoint -> xMACAddress .ucBytes );
382442 }
383443 break ;
384444 #endif /* ( ipconfigUSE_IPv4 != 0 ) */
@@ -394,8 +454,7 @@ static BaseType_t xSTM32H_NetworkInterfaceInitialise( NetworkInterface_t * pxInt
394454
395455 /* Allow traffic destined to Solicited-Node multicast address of this endpoint
396456 * for Duplicate Address Detection (DAD) */
397- prvMACAddressConfig ( & xEthHandle , xMACEntry , ucMACAddress );
398- xMACEntry += 8 ;
457+ prvSetMAC_HashFilter ( & xEthHandle , ucMACAddress );
399458 }
400459 break ;
401460 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
@@ -404,25 +463,14 @@ static BaseType_t xSTM32H_NetworkInterfaceInitialise( NetworkInterface_t * pxInt
404463 /* MISRA 16.4 Compliance */
405464 break ;
406465 }
407-
408- if ( xMACEntry > ( BaseType_t ) ETH_MAC_ADDRESS3 )
409- {
410- /* No more locations available. */
411- break ;
412- }
413466 }
414467 }
415468
416469 #if ( ipconfigUSE_IPv6 != 0 )
417470 {
418- if ( xMACEntry <= ( BaseType_t ) ETH_MAC_ADDRESS3 )
419- {
420- /* Allow traffic destined to IPv6 all nodes multicast MAC 33:33:00:00:00:01 */
421- uint8_t ucMACAddress [ 6 ] = { 0x33 , 0x33 , 0 , 0 , 0 , 0x01 };
422-
423- prvMACAddressConfig ( & xEthHandle , xMACEntry , ucMACAddress );
424- xMACEntry += 8 ;
425- }
471+ /* Allow traffic destined to IPv6 all nodes multicast MAC 33:33:00:00:00:01 */
472+ const uint8_t ucMACAddress [ 6 ] = { 0x33 , 0x33 , 0 , 0 , 0 , 0x01 };
473+ prvSetMAC_HashFilter ( & xEthHandle , ucMACAddress );
426474 }
427475 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
428476
0 commit comments