1
+ /* Copyright (c) 2025 Jamie Smith
2
+ * SPDX-License-Identifier: Apache-2.0
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #pragma once
18
+
19
+ #include " device.h"
20
+ #include " CompositeEMAC.h"
21
+ #include " MbedCRC.h"
22
+
23
+ // Figure out the Ethernet IP version in use
24
+ #ifdef TARGET_STM32H5 || TARGET_STM32H7
25
+ #define ETH_IP_VERSION_V2
26
+ #else
27
+ #define ETH_IP_VERSION_V1
28
+ #endif
29
+
30
+ namespace mbed
31
+ {
32
+ constexpr auto MDIO_TRANSACTION_TIMEOUT = std::chrono::milliseconds(1 ); // used by STMicro HAL
33
+
34
+ inline constexpr size_t NUM_PERFECT_FILTER_REGS = 3 ;
35
+ static const std::pair<volatile uint32_t *, volatile uint32_t *> MAC_ADDR_PERF_FILTER_REGS[NUM_PERFECT_FILTER_REGS] = {
36
+ {Ð->MACA1HR , Ð->MACA1LR },
37
+ {Ð->MACA2HR , Ð->MACA2LR },
38
+ {Ð->MACA3HR , Ð->MACA3LR }
39
+ };
40
+
41
+ // / Write a MAC address into the given registers with the needed encoding
42
+ static inline void writeMACAddress (const CompositeEMAC::MACAddress & mac, volatile uint32_t *addrHighReg, volatile uint32_t *addrLowReg)
43
+ {
44
+ /* Set MAC addr bits 32 to 47 */
45
+ *addrHighReg = (static_cast <uint32_t >(mac[5 ]) << 8 ) | static_cast <uint32_t >(mac[4 ]) | ETH_MACA1HR_AE_Msk;
46
+ /* Set MAC addr bits 0 to 31 */
47
+ *addrLowReg = (static_cast <uint32_t >(mac[3 ]) << 24 ) | (static_cast <uint32_t >(mac[2 ]) << 16 ) |
48
+ (static_cast <uint32_t >(mac[1 ]) << 8 ) | static_cast <uint32_t >(mac[0 ]);
49
+ }
50
+
51
+ // / Add a MAC address to the multicast hash filter.
52
+ void addHashFilterMAC (ETH_TypeDef * base, const CompositeEMAC::MACAddress & mac) {
53
+ #if defined(ETH_IP_VERSION_V2)
54
+ uint32_t volatile * hashRegs[] = {
55
+ &base->MACHT0R ,
56
+ &base->MACHT1R
57
+ };
58
+ #else
59
+ uint32_t volatile * hashRegs[] = {
60
+ &base->MACHTLR ,
61
+ &base->MACHTHR
62
+ };
63
+ #endif
64
+
65
+ // Note: as always, the datasheet description of how to do this CRC was vague and slightly wrong.
66
+ // This forum thread figured it out: https://community.st.com/t5/stm32-mcus-security/calculating-ethernet-multicast-filter-hash-value/td-p/416984
67
+ // What the datasheet SHOULD say is:
68
+ // Compute the Ethernet CRC-32 of the MAC address, with initial value of 1s, final XOR of ones, and input reflection on but output reflection off
69
+ // Then, take the upper 6 bits and use that to index the hash table.
70
+
71
+ mbed::MbedCRC<POLY_32BIT_ANSI> crcCalc (0xFFFFFFFF , 0xFFFFFFFF , true , false );
72
+
73
+ // Compute Ethernet CRC-32 of the MAC address
74
+ uint32_t crc;
75
+ crcCalc.compute (mac.data (), mac.size (), &crc);
76
+
77
+ // Take upper 6 bits
78
+ uint32_t hashVal = crc >> 26 ;
79
+
80
+ // Set correct bit in hash filter
81
+ *hashRegs[hashVal >> 5 ] |= (1 << (hashVal & 0x1F ));
82
+ }
83
+
84
+ }
0 commit comments