Skip to content

Commit 997ae9c

Browse files
Start on MAC v1 driver
1 parent eb03e12 commit 997ae9c

File tree

12 files changed

+593
-261
lines changed

12 files changed

+593
-261
lines changed

connectivity/drivers/emac/TARGET_STM/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,12 @@ if("STM32H7" IN_LIST MBED_TARGET_LABELS OR "STM32H5" IN_LIST MBED_TARGET_LABELS)
2525
)
2626
endif()
2727

28+
if("STM32F2" IN_LIST MBED_TARGET_LABELS OR "STM32F4" IN_LIST MBED_TARGET_LABELS OR "STM32F7" IN_LIST MBED_TARGET_LABELS)
29+
target_sources(mbed-emac
30+
PRIVATE
31+
STM32EthMACv1.cpp
32+
)
33+
endif()
34+
35+
2836
target_compile_options(mbed-emac PRIVATE -Wno-packed-bitfield-compat)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
{&ETH->MACA1HR, &ETH->MACA1LR},
37+
{&ETH->MACA2HR, &ETH->MACA2LR},
38+
{&ETH->MACA3HR, &ETH->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

Comments
 (0)