前景描述
$ x A% V$ n& W+ m4 w- Q我司的以太网实现是LAN8720搭配片上MAC层做的,协议栈用LWIP
$ a6 T2 ? `" k8 y
1 r8 [: O, ]8 @这种做法应该还是蛮常见的,反正不是LAN8720就是DP83864,再不然就是硬件协议栈的W5500了
7 Z" i" m* D! D' u$ Z# u# A: E; D# U! T% {" f
想想还是有MAC层过滤比较好,随手翻了翻它的手册,W5500好像是没得MAC层过滤的
0 t: I3 v9 A; K. @3 y- [) ?; @# K( W6 ]0 O; n9 i7 Y
假如数据速率比较高,数据量大,而且外面还有乱七八糟无关的数据往板卡送,我也不知道用这个片子到底好不好
, {; t# Y! }; K. I3 d; { |6 O( A9 `. g1 J+ O4 N7 ]) D
LAN8720也不好改了,就继续用吧
, e( S2 U+ v; C# K, ~3 G5 x5 o9 }+ r& s" L
好好在,发给板卡的数据的MAC还是有特征的,我只需要过滤发送方MAC地址的前3个字节,也就是特定的厂家那段5 Z& l( J+ Z; J2 y$ {: p* |
. B9 _9 e4 X- ? J8 v# K j
MAC地址的科普知识这里就不过多描述了,我们直奔主题
, Z7 U$ M# P8 V" X% {. i6 l
; A/ D# O2 m! i) }$ i2 C1 ]" x怎么用STM32 F7的片上MAC做MAC层过滤
' `' K7 p8 g9 A- S7 b
) N" C+ P2 p$ O" |写这个的目的,就是我搜了搜,没看见有人写这个MAC层过滤功能,具体代码怎么写才能用0 p: k+ d' R% N5 I2 t& N0 @
9 k! w \ |- C C. S, g知识科普-STM32的片上MAC* _- k" W4 Q/ B$ F9 D
STM32 F7的MAC层过滤方式有三种(说人话的直白解释,中文手册其实也翻译的不好)
) d2 G# i) R+ ^3 q. d. f7 I精确过滤(手册上叫单播目标/源地址过滤)& T6 A1 O# q3 }; i( V) @
粗糙过滤(手册上叫Hash表过滤)' ]( ?* g+ x* ]9 q4 L
特殊过滤(广播,组播过滤等等特殊的过滤)
" k, s- j# n9 f' W6 B我这里着重说第1种和第3种0 S2 C) U; i1 l; r
+ P& W6 {+ y6 Q( V1 V! Y& N& OSTM32 F7可以存4个MAC地址
# J s/ z& r2 b其中MAC地址0是自己的MAC,其他三个可以用来做过滤: x/ M9 H5 i& ]; H Z, r
; o" z) _' O/ T+ n4 Z7 t: u网络数据包通过PHY进入STM32的MAC,MAC层是可以对目的地址/源地址检查并过滤掉没得用的数据的,默认的HAL库库函数HAL_ETH_Init中, U, x" E+ Z) ~. A5 @4 J) f
有一个static的函数
& q. ^' i/ _4 g+ gstatic void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err); r" j H7 v; j" h* o) n& X3 b
会帮你在初始化网络功能时初始化默认的MAC层功能: y: H; H2 c0 V4 t& M! G E
关闭源地址过滤
- C2 p9 N) |. m$ R% F0 H不接收所有数据
0 n8 S# ^$ j1 J3 f- i f/ h/ i接收广播帧6 v R1 N8 t: ]+ M# _/ N- ]
打开目的地地址过滤1 @8 i, C8 |! ]# c& @
单播数据精确过滤
9 ~: k2 u' U( g9 ]2 l% a7 `: S4 p组播数据精确过滤 D O2 t4 s, m- A. X% ]
Hash表过滤关闭
) I. C3 [" K9 }
7 z0 k: a+ j/ M其他的功能自行研究,我这里捡重要的说; D+ {0 ]# y& Q/ w+ x X! P: I5 K! T
- static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)
! l) V8 {( k, C - {' V2 c/ w" [* ?; z! e5 B
- ETH_MACInitTypeDef macinit;3 `- s: n1 `$ o: h# d+ e6 M5 B; H9 L
- ETH_DMAInitTypeDef dmainit;
0 Z# T2 V: X6 O( K; `( @' e - uint32_t tmpreg = 0;
0 E4 e% _ ?, R( a9 R
6 u8 e+ u5 Z4 \6 C. G9 [- if (err != ETH_SUCCESS) /* Auto-negotiation failed */6 Z( C M6 x0 }9 c# _* Y
- {; ^4 d V% ]7 R
- /* Set Ethernet duplex mode to Full-duplex */
& E9 f! M" _5 c - (heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;5 m i$ H) a1 ]! p
- ' H' _6 t1 S0 |$ `! Y5 ^
- /* Set Ethernet speed to 100M */
; I% B5 J9 `% B) K- R2 t. m$ n - (heth->Init).Speed = ETH_SPEED_100M;
@1 Q; N3 k! [5 p/ Q# _ - }7 W# g. |6 P$ J! a8 Z3 Z. X+ ^# d
- & h9 s: C8 k% |* g- w' L
- /* Ethernet MAC default initialization **************************************/
9 u" e% W5 O2 H; Y9 w - macinit.Watchdog = ETH_WATCHDOG_ENABLE;3 u, m% c$ x6 C' B1 R
- macinit.Jabber = ETH_JABBER_ENABLE;! \/ n+ c4 p4 p- L
- macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;5 S* M# [0 v, d: q& o Z5 P
- macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;( v5 h5 I9 b% | ?9 `3 T# l
- macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
" ^, S. V' }3 Y5 B8 A6 J+ T, b9 T9 m - macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;* e0 ?1 @* J2 @ q$ G6 J
- if(heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)) ]+ i7 R' r! z7 o: C
- {
0 g8 p3 D) V# N) O0 ] - macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
& A7 W y& }1 m! C& f" J- V; D( } - }2 Q. V w# I" e0 T2 @1 V
- else
# u+ k& n( U6 d" A M9 l: | - { J; n+ \! q j: X
- macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;5 C/ c$ S3 f; P* s2 s* Y( d: K' H) M
- }
9 `! u( x" r% [: \, z5 I - //这一段是MAC层过滤的设置,下面是DMA的,那个用默认的就可以
) ] ]/ W% m/ M3 \% Q# u P - macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE;: n5 j3 Q) E) p9 _
- macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;
; \0 h6 ^+ P# Q1 ?9 q5 ~9 a0 M/ E2 W - macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;
0 [: y0 P3 h( ?+ ^ D$ G) O% N4 X - macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
- S$ U: c! X6 G* k1 c5 a( P2 ` - macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE;1 N, W, I4 z2 g& M, w, `
- macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE;' c3 V/ O, k; M& O, b* ^
- macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;3 Q+ Z* S/ z+ I N- Y4 G
- macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;
3 |9 s# N1 L% G6 f! q1 {2 e- w - macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL;% K( {+ N( _1 J/ M* P9 [% h" G
- macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;
8 y$ ?1 p! n# _6 i, r% ?# `9 G - macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT;
1 E6 G- F: _! S Z4 R' ?+ D/ h- p5 B - macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;
- r! k# Q. a# J. ` - macinit.HashTableHigh = 0x0;' s I) v' u9 C: E! {
- macinit.HashTableLow = 0x0;
4 q' N# E- y* t7 T - macinit.PauseTime = 0x0;
; U' ^1 P( n- z0 b - macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;
& Y" Z8 c8 ^* e- W2 `2 D) Q( o - macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;
6 V/ x& \. E9 C - macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE;% F9 Y/ }/ d$ ]3 s. Q' ~3 ^$ h
- macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE;
$ `0 Z; c( K2 c. D" A* P/ L* I( e - macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE;
3 B0 }! L$ t% H* Z& r - macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;2 Z" Q8 u( I$ X0 j
- macinit.VLANTagIdentifier = 0x0;+ H8 e* i* _( y( g/ p( h
. W) _6 E. y. o' O; D% o X- /*------------------------ ETHERNET MACCR Configuration --------------------*/; L' t9 ~ ^; i) Z& l! }
- /* Get the ETHERNET MACCR value */0 Y. }$ k2 j" m; H* O4 P
- tmpreg = (heth->Instance)->MACCR;
9 e5 A3 F& I! G! k' ? - /* Clear WD, PCE, PS, TE and RE bits */
7 l5 |3 p' m) s0 I0 B# A - tmpreg &= ETH_MACCR_CLEAR_MASK;2 K% ]; N$ B2 y4 N& z' p& U
- /* Set the WD bit according to ETH Watchdog value */
7 i. Z6 G+ ` j g* T - /* Set the JD: bit according to ETH Jabber value */
/ g* w6 ~; O7 O- E3 ~; J - /* Set the IFG bit according to ETH InterFrameGap value */
9 ?$ a+ v+ h0 Y - /* Set the DCRS bit according to ETH CarrierSense value */
/ p" D* Y: }7 U - /* Set the FES bit according to ETH Speed value */
* ]( k4 i% H: i3 O, W* o: ]* V - /* Set the DO bit according to ETH ReceiveOwn value */' A- o4 t( o1 ?- p' }. Y' q
- /* Set the LM bit according to ETH LoopbackMode value */
: P. L4 j/ {- q# ~2 Q2 e$ J - /* Set the DM bit according to ETH Mode value */. a2 f! z9 e/ [' ^5 s. z {5 g
- /* Set the IPCO bit according to ETH ChecksumOffload value */
+ {4 J6 t+ D' W - /* Set the DR bit according to ETH RetryTransmission value */$ N) o* z3 O ^- t6 K! @
- /* Set the ACS bit according to ETH AutomaticPadCRCStrip value */
. c3 [8 o. d' ^! f0 n$ n - /* Set the BL bit according to ETH BackOffLimit value */4 P6 E$ ~7 w A* V3 c& b
- /* Set the DC bit according to ETH DeferralCheck value */" ^- P1 `) q8 n# B$ T1 [
- tmpreg |= (uint32_t)(macinit.Watchdog |- ^) M7 F( A& u
- macinit.Jabber |
: B4 d0 M4 d1 C3 ]7 r z - macinit.InterFrameGap |' T$ @ x1 \9 q( j
- macinit.CarrierSense |
: `( w% X" i W( ]2 X7 k6 ] - (heth->Init).Speed |
6 G7 M) W W0 [7 @ e H - macinit.ReceiveOwn |7 x6 Z1 p6 X2 P) Q
- macinit.LoopbackMode |2 ]! m% x; p1 `1 o |% y
- (heth->Init).DuplexMode |
: E4 H& ~ l2 ~6 m% [ - macinit.ChecksumOffload |. K9 W, v' Y3 F2 K! v
- macinit.RetryTransmission |
; [- S' d. T$ D [ - macinit.AutomaticPadCRCStrip |# ?6 B3 M! p% l1 B$ ^) q
- macinit.BackOffLimit |
/ e- @2 \, q& {) I4 ]3 q* w7 a - macinit.DeferralCheck);9 B; M4 |( k" J; V5 U
1 C; r' K6 C+ w U" {, [+ [/ \- /* Write to ETHERNET MACCR */
3 c; Z% }. H5 D) k( E - (heth->Instance)->MACCR = (uint32_t)tmpreg;: g9 n+ q5 A% ?8 ~% ?
- ; `5 W+ }6 `9 b" f3 o1 s0 T
- /* Wait until the write operation will be taken into account:1 U) V' ]* D" C# H: S" |) T
- at least four TX_CLK/RX_CLK clock cycles */0 \) Y# m1 j, s5 ^' a
- tmpreg = (heth->Instance)->MACCR;
3 `7 B% h8 S `9 l+ Y% x7 D - HAL_Delay(ETH_REG_WRITE_DELAY);
( F7 J* ?9 u- l d5 q) c% z - (heth->Instance)->MACCR = tmpreg;) d0 T2 T# Q/ {4 O+ ^' L- r+ g& o
- 4 l1 s; k& R, ^5 I5 P
- /*----------------------- ETHERNET MACFFR Configuration --------------------*/
1 A( p6 O' A* x+ s0 n) v* [ - /* Set the RA bit according to ETH ReceiveAll value */6 k. i. A0 s# w" {& F" [( g
- /* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */' L6 T B8 `2 e% b
- /* Set the PCF bit according to ETH PassControlFrames value */
8 f) q# |4 x+ I2 B- M5 U3 G - /* Set the DBF bit according to ETH BroadcastFramesReception value */" m5 C4 r+ g& f
- /* Set the DAIF bit according to ETH DestinationAddrFilter value */
. B% h) e+ o: _5 _" } - /* Set the PR bit according to ETH PromiscuousMode value */
; l5 t8 N) w1 O( ^! B" V - /* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */
p) F& [0 _9 Q - /* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */+ ~( ~# s; @2 h9 ~' s* F3 X P
- /* Write to ETHERNET MACFFR */
- q& V, P% ~5 u& U/ e+ V7 v - (heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll |
; H: Y# b+ o/ y' N. B7 ^ z3 k: u - macinit.SourceAddrFilter |
" o- l1 u+ U2 ^8 c6 M7 @# K3 K - macinit.PassControlFrames |/ W( U( U, u$ S# a
- macinit.BroadcastFramesReception |6 N/ n& e+ S6 a9 t% O8 ^8 ~5 S
- macinit.DestinationAddrFilter |6 K6 O: L3 Q4 c5 l) r- h! a
- macinit.PromiscuousMode |4 o# R* ^* L" l, b. N$ a+ ?
- macinit.MulticastFramesFilter |
7 M: j, J1 V: D4 ]4 v! l - macinit.UnicastFramesFilter);
" D/ k3 y& t. E$ m0 M
) n c& W; Z, \; @- /* Wait until the write operation will be taken into account:% m" B" k6 p( i f+ D3 M. g/ J* D2 X
- at least four TX_CLK/RX_CLK clock cycles */
" \* B0 h$ q+ m: i& h5 v - tmpreg = (heth->Instance)->MACFFR;
# _) }# U$ s* d! E3 ^3 L3 z - HAL_Delay(ETH_REG_WRITE_DELAY);
7 n- M' Z r" Q" D$ n - (heth->Instance)->MACFFR = tmpreg;
) n, r1 Y+ i: \( x - $ n* h; F# S: _9 K3 y- C
- /*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*/
% S9 }3 h$ }% w9 v4 {6 L9 C; ~ - /* Write to ETHERNET MACHTHR */
' t9 [0 X5 I B3 d - (heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh;
0 y% P5 F3 I6 g; x4 t$ M, v2 t5 f - ) F" j) @# p6 J
- /* Write to ETHERNET MACHTLR */
$ Y9 d( a% e; B% Z0 @1 l4 f/ k - (heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow;$ A4 g8 ^) q% u
- /*----------------------- ETHERNET MACFCR Configuration -------------------*/8 y- h' u8 |* A$ t6 r/ f1 Y1 q j
; ?: d; u- X& O; C! I0 i& \1 ?1 ]# B5 C- /* Get the ETHERNET MACFCR value */' t H5 G' F( g0 \; P; Q
- tmpreg = (heth->Instance)->MACFCR;
: _3 R% T8 z' ^. L9 ^* L& H - /* Clear xx bits */! L2 q8 Q) z: z7 ?9 W
- tmpreg &= ETH_MACFCR_CLEAR_MASK;
9 k+ m6 i5 Q4 A! K) Q - 9 G' ^3 k, Z9 g/ ~' g4 {2 d* @
- /* Set the PT bit according to ETH PauseTime value */9 y* h& [3 Q7 A3 C5 L
- /* Set the DZPQ bit according to ETH ZeroQuantaPause value */' n( m" m( O2 u
- /* Set the PLT bit according to ETH PauseLowThreshold value */
8 N8 N+ E/ J. G6 ` - /* Set the UP bit according to ETH UnicastPauseFrameDetect value */0 B# [, b& ?2 _1 c+ W
- /* Set the RFE bit according to ETH ReceiveFlowControl value */
1 b. b% m. j% y3 a/ H) [! O - /* Set the TFE bit according to ETH TransmitFlowControl value */
/ _& z$ h& _% \7 {6 @6 w - tmpreg |= (uint32_t)((macinit.PauseTime Instance)->MACFCR = (uint32_t)tmpreg;
7 r. s7 i l5 t X/ c, M& s
& M F( O5 B4 ^' w; s1 V- /* Wait until the write operation will be taken into account:
[# M, P$ m8 s1 b - at least four TX_CLK/RX_CLK clock cycles */* C% [. U/ S& z) S
- tmpreg = (heth->Instance)->MACFCR;
3 K9 W4 ~. i8 N2 }" i+ U0 ~! h - HAL_Delay(ETH_REG_WRITE_DELAY);; Z/ U8 m8 t5 F2 u! c2 k6 Z! V \
- (heth->Instance)->MACFCR = tmpreg;
9 s% L' ]3 d1 D5 Z' E, i; G* f. B
/ a) a# w) T8 S- /*----------------------- ETHERNET MACVLANTR Configuration ----------------*/
( B4 p0 I' k# h0 C, n) R - /* Set the ETV bit according to ETH VLANTagComparison value */
* x+ v* e7 o6 R& w) y - /* Set the VL bit according to ETH VLANTagIdentifier value */
# d% J4 \& Y$ j- K0 `! _ - (heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison |
! x: ^1 {$ s8 m! m! L - macinit.VLANTagIdentifier);4 e" g6 _$ O! v$ x' ]& W4 f4 I
- " o) c5 K% D3 L( B* V' m
- /* Wait until the write operation will be taken into account:( i; t& f. w& |
- at least four TX_CLK/RX_CLK clock cycles */% c" z% [5 a4 K5 g7 d1 [% l
- tmpreg = (heth->Instance)->MACVLANTR;
1 P! x/ O( d% U; v3 v" ^1 [ - HAL_Delay(ETH_REG_WRITE_DELAY);
$ u" n# |/ p+ K% M9 k - (heth->Instance)->MACVLANTR = tmpreg;: Y1 o3 H7 |. h
- 1 W+ G2 h* z, F7 o: v* L! ?
- /* Ethernet DMA default initialization ************************************/& J; |4 [9 N% j5 r, {: k. \
- dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
- r3 Y3 A9 ^* t/ {, C9 ` - dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;
# R/ V/ q5 Z2 F U$ f - dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;
6 V% R# {2 q" C9 x) m - dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;/ J: ]% ~ P9 \! A2 g) U
- dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;5 ]# [. B7 j* [, O. { }
- dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
; M0 U K V9 @3 U - dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;2 @' y0 f; s4 M( \1 P7 E, c
- dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;
# ^# Q& Z2 m5 K4 G) m' x7 C - dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;
. H' x: R* s5 G* C1 X+ P9 ]) w; O - dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
0 A3 O+ h- O, o% L8 |% c7 U, k - dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;
. ^$ D7 K7 s c# h: k" S- p - dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
j: _( D J [8 U - dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;0 V9 p' a" j5 P4 W, _
- dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE;8 v# s$ j+ e# L: h$ L; j
- dmainit.DescriptorSkipLength = 0x0;2 O' {3 M8 U0 ~+ z! s
- dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;. P) S1 y# Y8 C Z$ ?5 j6 b+ \: C
7 V+ \+ a1 X7 w3 [. I" m- /* Get the ETHERNET DMAOMR value */* d$ A0 s J' l2 D! n
- tmpreg = (heth->Instance)->DMAOMR;0 i7 R& t F8 S) O* H
- /* Clear xx bits */- O( S( Z, o% Z9 p" L* y6 S
- tmpreg &= ETH_DMAOMR_CLEAR_MASK;- t4 n- x. r' G2 U6 w) X8 ]
; A4 l9 o7 S# y: v6 g. _1 j- /* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */' U% c# _! I" l- z3 u
- /* Set the RSF bit according to ETH ReceiveStoreForward value */7 h9 N2 \1 x! T4 }
- /* Set the DFF bit according to ETH FlushReceivedFrame value */
8 l; s* Q1 z- N7 Y! Z* j5 G - /* Set the TSF bit according to ETH TransmitStoreForward value */
# @ B( A' u! y2 R - /* Set the TTC bit according to ETH TransmitThresholdControl value */" T: u. V3 T/ |( a q
- /* Set the FEF bit according to ETH ForwardErrorFrames value */- V+ }1 T2 I2 Q1 [ p
- /* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */1 u& I7 s- t( ^! R4 v7 \
- /* Set the RTC bit according to ETH ReceiveThresholdControl value */& ^7 K' `- u- Y& r9 k& d$ p
- /* Set the OSF bit according to ETH SecondFrameOperate value */
6 `1 w; f# r- m1 u& Q - tmpreg |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame |2 K( C% {4 ~2 a
- dmainit.ReceiveStoreForward |
$ l# j" }& K7 A7 t" h5 R - dmainit.FlushReceivedFrame |2 w9 z1 Y# k/ q- ^
- dmainit.TransmitStoreForward |
" \) r; o3 Z2 F5 x/ c - dmainit.TransmitThresholdControl |
9 j7 P$ { E0 Q, E( N9 t1 M& @. w - dmainit.ForwardErrorFrames |" E9 t3 \8 w$ J1 h7 Y& j
- dmainit.ForwardUndersizedGoodFrames |
' F6 S, ?6 W" b8 W( J! ? - dmainit.ReceiveThresholdControl |
: H0 e: E' L: ^' G - dmainit.SecondFrameOperate);
: ?" k% h/ O$ {6 ^ - / Q1 s1 X; z! n8 T3 C* y
- /* Write to ETHERNET DMAOMR */
. j7 M( @, c" }6 ]2 j7 @* j9 `# v - (heth->Instance)->DMAOMR = (uint32_t)tmpreg;
9 {+ @/ P+ ]; k/ T4 |) }$ M- p - 3 U: R+ |5 i# T
- /* Wait until the write operation will be taken into account:9 y8 b2 n: g' F9 U
- at least four TX_CLK/RX_CLK clock cycles */, F) t8 T6 y9 S3 d
- tmpreg = (heth->Instance)->DMAOMR;
0 T9 ^0 P, W$ e - HAL_Delay(ETH_REG_WRITE_DELAY);
4 F% e% ?5 C q: r$ s5 F F- X - (heth->Instance)->DMAOMR = tmpreg;
0 G1 S( u% [4 i. ? - a# \8 l. p! g! D7 d3 o
- /*----------------------- ETHERNET DMABMR Configuration ------------------*/3 B3 F: C# q) Q( p
- /* Set the AAL bit according to ETH AddressAlignedBeats value */. ~: G( r" R$ l) S2 {
- /* Set the FB bit according to ETH FixedBurst value */
( {6 x: g( o) A5 J/ Z' x! S - /* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */; m$ W) G% b% E- y2 |. F
- /* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */# G% E* O! X8 y) G
- /* Set the Enhanced DMA descriptors bit according to ETH EnhancedDescriptorFormat value*/7 z( S/ t# o C% z+ [* T
- /* Set the DSL bit according to ETH DesciptorSkipLength value */
, A( z8 p! s+ a* ?* w - /* Set the PR and DA bits according to ETH DMAArbitration value */+ a' z' v% i6 O2 K; L5 u
- (heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats |
2 N! _* J! t! j/ _( s; z, { - dmainit.FixedBurst |
7 i% q% V5 _& h- ?, l0 R - dmainit.RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */
. G/ J! e/ _5 { - dmainit.TxDMABurstLength |
% @2 |! G# D1 ~3 b) c1 K - dmainit.EnhancedDescriptorFormat |
; h7 B) y7 F* B6 D) A1 M: U2 u - (dmainit.DescriptorSkipLength Instance)->DMABMR; c7 `% Y% Y9 `9 Q+ N2 ]$ [
- HAL_Delay(ETH_REG_WRITE_DELAY);7 {( ]' D3 Z0 j) D
- (heth->Instance)->DMABMR = tmpreg;
, K L$ {7 q7 [3 k0 h - 1 ?8 u5 e9 }5 q3 A
- if((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)- i+ e0 F8 }2 c3 j2 }
- { _# Z& w' i* k; E+ N
- /* Enable the Ethernet Rx Interrupt */
" I$ {; Z% Z* N W) } - __HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);
% `( a0 v/ u. V, z( m' u - }
( e1 i* j3 G2 h
" x6 h5 S' `3 y) n1 a& t- /* Initialize MAC address in ethernet MAC */
; \/ D% h& Q+ F4 y - ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
/ V( k. ]: E" u" v+ K& M - }
复制代码 1 E1 i* O( C$ z1 o; R
这里我就要稍微吐槽一下HAL库了" G; c- z$ D. a$ T6 \6 T" i
MAC层过滤的设置没有预留接口出来,有设置MAC地址的函数8 q$ c9 d6 ^! @9 F+ x# p1 n
8 V9 T+ A! ]* s- }& v- I! A; k
static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr)
" u; Q1 `( j' B, ?5 u0 b* B- g7 ~5 y+ `4 A6 F# w4 H2 t
就不多做一个设置MAC层过滤的函数嘛,连后面用到的宏定义都有~~" r: B* ?# k- _' i% Q
8 f& C# C& P6 r& C5 B& x+ i2 F8 d木有办法,自己编一个初始化MAC层过滤的函数吧
$ ?, a. A5 m3 M c3 j# `& R7 |& U, T- [! w T+ A- d3 o
其实也就是把上面这个ETH_MACDMAConfig函数分离成两个单独的设置函数,再编一个设置MAC层过滤的函数( Y+ L0 x, P3 h% {- [
) G7 }1 `7 k8 b+ J. H) W
开启MAC层过滤的初始化代码
" A ?6 u# j7 M0 W1 D- uint8_t ETH_MAC_Setting(ETH_HandleTypeDef *heth), a/ \& p2 R, q% F, A
- {$ Y' e, t8 @, J7 T" x
- ETH_MACInitTypeDef macinit;3 Z9 R" x/ l+ n0 ?* w+ \6 H' r
- /* Ethernet MAC default initialization **************************************/
/ n2 s4 L! V" Z - macinit.Watchdog = ETH_WATCHDOG_ENABLE;! t% g$ q6 `+ F
- macinit.Jabber = ETH_JABBER_ENABLE;
$ \( @% }1 \, t& i3 [* e$ l0 i - macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;& a. t7 q) n& ] W) S8 F+ k% M
- macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;
, n$ N0 |: @& T* f - macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
- g6 A- x+ e- Y" A& g8 \/ A - macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;
1 [ c8 W* I% | N4 F/ q8 b5 V - if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)6 T5 U* R( m8 q. P
- {$ }" L: \# R9 l. a& y h
- macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
1 g# z1 n. [- \( X9 A5 w/ L$ \6 |" s - }5 |, R# D) |2 W. O; r# {4 w
- else" |! |4 s$ ~9 J
- {
2 v& ^2 L- W. _* F- w9 ] - macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
1 N& y5 Z2 }) J; t+ V) a/ f$ V - }
0 X2 X0 p' e( [0 J( I& @8 j; l - macinit.RetryTransmission = ETH_RETRYTRANSMISSION_ENABLE; //使能重传! t" r7 v R% r+ Q$ `9 R1 ?# b
- macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_ENABLE; //使能自动去除
$ u* n& B+ z7 r - macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;
3 L4 p- H) d1 \5 Y4 j* W! o - macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
3 `3 }% X' [; i. |$ M - macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; ///不接收所有包, K7 O2 \& ~1 X ]: K
- macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_NORMAL_ENABLE; //源地址过滤
4 q# F' ]* t1 U8 ~9 ]0 w - macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;
) R3 n2 V1 ?! D3 G! [6 K - macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; //广播不接收
; G4 S. C/ ^3 R5 j - macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; //目的地址过滤5 {2 e) ?, |# m) ^; s% i+ k
- macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; //混乱模式& G2 |9 `. I' Q
- macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; //多播过滤- [, ]7 N* c4 ^( a2 ]. X
- macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; //单播过滤$ ~" i, A0 I, ]
- macinit.HashTableHigh = 0x0; //Hash表高位
* \5 ?4 K8 y1 g2 C T' z - macinit.HashTableLow = 0x0; //Hash表低位
, O+ r# Y! v$ I8 l6 j - macinit.PauseTime = 0x0;
6 I9 e9 x( G* P' h - macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;
. F0 L0 }/ ?3 s2 e1 T - macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;, x1 u- Q1 W' t+ z+ G
- macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_ENABLE;' M8 e$ u! _4 E6 S; ], _1 s
- macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; //接收流控
' |# q& i% e f, h. H" J - macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; //发送流控% F8 y$ {3 Z F5 S/ M1 m+ m- P
- macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;, A U: r- V3 |
- macinit.VLANTagIdentifier = 0x0;
) V3 h3 S; o4 z7 R. y - " R" |# i6 W7 f: b
- return HAL_ETH_ConfigMAC(heth, &macinit);$ g: ?/ e0 |" O- U- Z
- }
复制代码 ; w- ~4 Y2 C$ I7 r8 d; g4 o( G
默认的MAC层 DMA初始化函数
; Q" p; ?9 _$ N: j+ A1 k w- uint8_t ETH_DMA_Setting(ETH_HandleTypeDef *heth)& J) i& a3 T" M+ [
- {0 W4 L! g8 [+ r2 s9 _
- ETH_DMAInitTypeDef dmainit;
" K" b5 {* E/ l! N1 @0 L - /* Ethernet DMA default initialization ************************************/& k) T6 B' Z: d6 J- r) K: ?
- dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
6 U/ T7 `5 Q. F0 R$ M - dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;, Z P; A+ }/ I8 D
- dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;: I' Q7 _# Q3 }3 A6 O
- dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;2 h. o" B7 p( J
- dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;
; D5 C b5 v" L. B - dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
9 | t b$ r0 q" j - dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;
6 \; p: l1 S: ]; A' | - dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;+ p* q& W, N# C; \6 Z5 e- ?0 t
- dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;7 }5 ?: |' @" j8 ?0 Q
- dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
( C" O" o. \. ? - dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;9 r9 v3 E( [5 ^9 ]6 S0 Y0 U- S, N
- dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
6 g% y5 P' H* H - dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
' R! W, s" J, } - dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE;
7 w7 z. P) V8 @ - dmainit.DescriptorSkipLength = 0x0;
& F# S; F: E+ m6 S9 E+ ] - dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;2 o. g8 `* n2 q5 f* r% ?( {
- uint8_t res = HAL_ETH_ConfigDMA(heth, &dmainit);
! B: n% W" v! n0 m* o - if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)
/ m- R' f. e) A) V - {
7 ]7 C1 H4 Z" ]3 ? - /* Enable the Ethernet Rx Interrupt */: n7 m7 H' M9 n! N. ?
- __HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);6 E+ O B$ p Y% p2 l
- }
% V" O: A. w) A, B |4 v - return res;. Z: r$ J4 \& ?) @- m
- }
复制代码 / I8 ^; z4 F1 b- k: {. K
用来设置MAC地址的函数(其实就是把库函数的static函数取出来直接用了)- <blockquote>//heth: HAL句柄
复制代码 & g0 c# ] m& t q
然后到最最重要的MAC层过滤设置4 ]" O6 R: r6 w7 k* [3 y
以MAC1为例
: q0 L+ E$ U" U- `& t4 I. |/ a0 w
* E+ m( P$ K6 Z' `; D/ J
, R& K: g) V- R3 G
/ _8 l6 L# G" j- K( T- f, l \: e# G$ d5 u6 e$ K& T$ P; c; n
- K" j; C5 f- M" p3 |" K+ j2 f" u注意看红框的描述
1 p- M" ?% U1 d; H$ u功能很好用,可以过滤源地址/目的地址,还可以做掩码功能
2 K) Y1 o4 [" a E2 {设置MAC层过滤的代码
- x/ X; [: o$ d3 M- static void ETH_MAC_Filter_Setting(ETH_HandleTypeDef *heth,ST_ETH_PAR * para): @0 m6 H/ I4 }4 {/ Z/ B' G: n3 W
- {. n+ ] g: C7 L; \% x
- //设置本机MAC地址
' s- X& Y& I/ g4 M% S - ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
( z$ }( \) p( w* i# A# L2 |: g, h - //设置UDP-A的对方MAC地址1 N. ^9 V6 B$ f5 F% t; f
- ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS1,para->UDP_A_MAC);
) L! S: T% A- o! R% B. i, R' ~2 ]8 @ - (heth->Instance)->MACA1HR|=0xC0000000;//需要完全匹配UDP-A的对方MAC才接收
' c4 s" c9 @# P7 A - //设置UDP-B的对方MAC地址
# L- c6 h" W8 A, {3 ^3 x4 i - ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS2,para->UDP_B_MAC);* o8 D8 e, C2 p% h4 E) Q
- (heth->Instance)->MACA2HR|=0xC0000000;//需要完全匹配UDP-A的对方MAC才接收
$ E; s9 G' e5 u' b$ N4 t - }
复制代码
) o, n1 O! E; b' q我这里是希望为我的两个UDP精确过滤接收到的源地址, x# X* o/ a7 Q' r
所以AE位设置为1,SA设置为1,MBC全部为0(MAC地址全部检查)
" k8 A2 Y6 K* n$ }2 e! v5 c/ E* l; |# E& _# ]+ k6 b7 R8 R
假如我希望过滤MAC中特定的厂家字段- ]; p- t3 P8 v, G3 n
例如某个MAC地址/ ^6 B7 e5 i' G& z' G
01-02-03-04-05-06
; Z1 {, J( j% r( I2 k/ `8 |& z. ]其中01-02-03就是厂家字段
5 j' ~! c, `# m Z8 S( z$ S
4 k( _1 H1 r: U, | a4 H& S. ]那么代码要这样修改(MBC的第29位,28位,27位置1)
@ ^; T! N2 \" O7 I) z这样MAC层就不会检查MAC地址里后3个字节(04-05-06)
; \3 R7 ^ c; V& R; Z$ @但是会检查前3个字节,也就是厂家字段3 P' f; E0 C+ V/ x, ~! f
这里需要注意MAC地址的字节序
$ t$ ^& d+ O$ S( T" a, N- static void ETH_MAC_Filter_Setting(ETH_HandleTypeDef *heth,ST_ETH_PAR * para)" O+ ^( x. u& A; ?1 H
- {8 y: f3 l& P, S+ E9 k E4 t
- //设置本机MAC地址
9 V% [6 b% k, c. b0 B) M - ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);2 s7 q# ?' [* z
- //设置UDP-A的对方MAC地址( v8 r# C3 @5 I1 k% W9 U% t
- ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS1,para->UDP_A_MAC);
$ v0 }: r% W1 I" q- R3 X - (heth->Instance)->MACA1HR|=0xF8000000;//需要匹配厂家字段
7 k$ n' F" D5 F. }: { - //设置UDP-B的对方MAC地址
0 D5 U1 O0 A0 b! c+ r% _0 R: K - ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS2,para->UDP_B_MAC);# w3 I3 M" w6 v F
- (heth->Instance)->MACA2HR|=0xF8000000;//需要匹配厂家字段/ h# x& B) n( U
- }
复制代码
* u- H+ L% U! l( s$ M) |; [然后这些函数的调用顺序按:7 P+ `! a9 T: s8 Z7 X
1. HAL_ETH_Init0 J) {& z u% \/ J- T
2. ETH_MAC_Setting q) j2 f, t& s; U& l3 y2 y
3. ETH_DMA_Setting
" g3 d+ v9 S' Z5 e# q3 y4. ETH_MAC_Filter_Setting0 K* U, J {2 E' K3 e
2 @+ l9 l/ q( Y: o4 V/ R
用你希望过滤的MAC传递到一个Hash计算函数里,得到一个值,通过这个值产生“映射”关系来过滤MAC地址,所以这个并不是精确的,因为可能会重复~~ c% S6 Y/ D" O3 Q
* w3 Q5 Z; K) E; RHASH函数
2 F7 g. u1 b. ^, `: z函数 M2 q( U9 Z* c" }. |6 U
- / STM32 MACHASH - Copyright (C) 2014-2018 Clive Turvey (<a href="mailto:sourcer32@gmail.com">sourcer32@gmail.com</a>)
z& P% f5 r4 g- z! w: T - // All Rights Reserved
) [8 d0 W( ]$ n2 p& M( Z0 k( a8 f7 h
* |. x3 x! ~! T8 j- #include <windows.h>$ {/ Z: I: a8 j: r
- ( h. m; y$ g6 p3 H7 j
- #include <stdio.h>6 A5 x" Z" J4 B3 {& b% `) ^
- #include <stdlib.h> Y7 x8 ^4 F( ?. q: Q5 Y
- / c1 u9 n. h% {+ \
- typedef unsigned char uint8_t;
& {5 S5 A# ~* Z- |4 w - typedef unsigned long uint32_t;! X0 m3 B- s4 H7 c; R$ X+ C
( m6 v: i" ?# y/ R- uint32_t Rev32(uint32_t x)
) L3 o( Y! @7 W1 p - {" }* e! a ~: e% R: p; l: V
- uint32_t y;+ v( }4 ^4 n/ r1 y' z/ E/ C( `
- int i;
! M% L8 i# R9 v- B
7 \& ~5 Q. K; W2 L( {/ A$ [- y = 0;
3 C% M0 B" b' a; y( E
& J7 G( e2 ~# g- for(i=0; i<32; i++)
+ y: z a* Q6 k+ W: Y - if (x & (1 << i))7 X# z9 s, B6 V7 Z {" L
- y |= 1 << (31 - i);2 r/ O% R9 S* [' x
; N* V! l; O& \. {- return(y);
( C! ^1 M( u$ {/ D# _% {1 P S - }0 R s% u2 d% w g2 P
( a9 X# Y- G/ K) Q/ ]& ~& D- uint32_t MacHash(const uint8_t *Mac) // <a href="mailto:sourcer32@gmail.com">sourcer32@gmail.com</a>
5 B. d+ A0 J" x' O( ^/ r$ ?3 ~ - {; f$ x1 ]" g& G5 b
- int i, j;
8 C. k, l& v3 a! c - uint32_t Crc;5 g B( Q9 r2 F P; r
- ( ?9 p' q: j% w6 S' I' u
- Crc = 0xFFFFFFFF;6 ~6 S! k/ q6 F' I
4 s. j: O( ^1 l+ r: z% U- for(j=0; j<6; j++)
( {9 ?% }# `: @9 B" x: B: B6 ^/ b6 b - {
; s' t" u% h- [+ j - Crc = Crc ^ (uint32_t)Mac[j];
- |( l/ f( S2 `( d- N: A
i2 U( f% W8 W' k- for(i=0; i<8; i++)& w: ~+ x M" o3 b
- if (Crc & 1)3 e4 G% L* i# ?; U% g- Q
- Crc = (Crc >> 1) ^ 0xEDB88320; // Reversed 0x04C11DB7% g( d/ @3 Y. z* e; l: C% d
- else
+ v) m( X1 k3 Q - Crc = (Crc >> 1);
: [2 [, ?" ?- _ n1 K: U+ e! f# m6 t; e - }
2 j- P7 |. ]. K+ @! j/ n
$ B: w: u4 v( h4 e- return(Rev32(~Crc) >> 26); // Get High order 6-bit in reversed/inverted CRC( A1 o8 N7 s% {! I, E
- }) @& s1 Q$ V( Y. G3 z2 \% ~
- 4 A; l; h5 r4 g$ L# V
- uint32_t MacHashFast(const uint8_t *Mac) // <a href="mailto:sourcer32@gmail.com">sourcer32@gmail.com</a>% h6 r+ l+ a3 a9 _5 P
- {2 w5 T: S/ s' e3 t! P, E* c! C
- static const uint32_t Rev6Tbl[] = {
( h/ w6 n) u6 Y! N7 V0 R' ^( O; F - 0x00,0x20,0x10,0x30,0x08,0x28,0x18,0x38,
# [: y2 {( f& `: H4 N$ L; A - 0x04,0x24,0x14,0x34,0x0C,0x2C,0x1C,0x3C,
8 K1 T O h' C) P - 0x02,0x22,0x12,0x32,0x0A,0x2A,0x1A,0x3A,& P/ i/ K* G5 g/ A
- 0x06,0x26,0x16,0x36,0x0E,0x2E,0x1E,0x3E,
( ?* q+ ]2 G) b8 O% H - 0x01,0x21,0x11,0x31,0x09,0x29,0x19,0x39,0 y0 @) }# i$ R3 w- r. a
- 0x05,0x25,0x15,0x35,0x0D,0x2D,0x1D,0x3D,
/ h$ n" h3 N7 ?6 Z) ?5 e9 X, N - 0x03,0x23,0x13,0x33,0x0B,0x2B,0x1B,0x3B,
$ Q; z; v( D" k! M1 s - 0x07,0x27,0x17,0x37,0x0F,0x2F,0x1F,0x3F };6 b; T: E6 `1 T2 O. C5 {3 Q
, y* ?/ X% G) t# s, f2 q8 s4 T! W- static const uint32_t Crc32Tbl[] = {0 w! S8 M" N* o
- 0x4DBDF21C, 0x500AE278, 0x76D3D2D4, 0x6B64C2B0,
% W8 a+ ?( j. m; q* Z+ K7 k - 0x3B61B38C, 0x26D6A3E8, 0x000F9344, 0x1DB88320,5 ^- q9 m* a+ Y# E
- 0xA005713C, 0xBDB26158, 0x9B6B51F4, 0x86DC4190,
( h1 j: K+ e7 ~& c3 M+ p% b - 0xD6D930AC, 0xCB6E20C8, 0xEDB71064, 0xF0000000 };
! @% h8 r" A3 f0 N) C( E
/ I4 v( H3 W% x8 o+ s' \- int i;
; X+ r3 O' ]7 x4 D S - uint32_t Crc;
$ h7 y: X' X5 z; J" C* {
/ q" P( l8 a2 L: \# m0 P: F- Crc = 0;
: U& @) X& Z, y: I! { - + Y- U* h ~/ b
- for(i=0; i<6; i++)
9 G3 `8 M8 h* N2 u& U8 d0 e) | - {2 F0 k6 k& e* V
- Crc = Crc ^ (uint32_t)Mac<i>;
2 c$ ?: W% `9 Z) M - ; C' u3 }8 A+ Y+ ]/ j
- </i> Crc = (Crc >> 4) ^ Crc32Tbl[Crc & 0x0F]; /* lower nibble */
" i Q! [6 E& Q' u" g - Crc = (Crc >> 4) ^ Crc32Tbl[Crc & 0x0F]; /* upper nibble */
5 l7 C$ ]/ D6 L5 r - }
& f" L( _! y$ j1 p; b- f - % o- x; u- Q6 g
- return(Rev6Tbl[Crc & 0x3F]);
1 s& b0 l: `8 b" H, @ - }
9 T7 f/ q# F+ m- j$ ]
9 c8 R& Z) g3 k% e4 p. D! s- int main(int argc, char **argv)" y: x( \; E* n o6 W- z* U
- {/ }' f, ^5 k) f9 U/ t O& X
- static const uint8_t Test1[] = { 0x1F, 0x52, 0x41, 0x9C, 0xB6, 0xAF }; // 0x2C
; g4 ~& N: J' I+ l9 [9 M4 U6 } - static const uint8_t Test2[] = { 0xA0, 0x0A, 0x98, 0x00, 0x00, 0x45 }; // 0x07
; A/ p! e6 g" A7 b+ R1 y - static const uint8_t Test3[] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x21 }; // 0x24
" W+ o6 @& U0 l: v# @ - 8 D8 M$ I" o c6 `6 h
- printf("MacHash %02X\n", MacHash(Test1));
$ X# m# d8 x& _& }0 [- A - printf("MacHash %02X\n", MacHash(Test2));
$ [; i6 O9 \" k( O( x - printf("MacHash %02X\n", MacHash(Test3));, V& a9 E2 o- W3 c5 B8 L; f1 o+ _
- / d2 L2 ]. a. |1 ^$ S
- printf("MacHashFast %02X\n", MacHashFast(Test1));
- D7 s/ S; P! F0 t& C - printf("MacHashFast %02X\n", MacHashFast(Test2));
! Y* ?) L& z- a7 v, M - printf("MacHashFast %02X\n", MacHashFast(Test3));/ I H* N( k4 W1 b6 A/ C: d
# ^. _# R8 P5 `% K! a- return(1);
4 Q* b! }, \$ s, q2 J - }
复制代码
8 \2 K, h: ]$ b1 y% M0 O7 k( ]/ f0 D- W2 m- ], t" o
回到手册$ X+ p6 I1 {0 Q& z/ x- z" [1 P
! s9 x% o/ h5 D! }8 X$ E& ]+ T& g* i
6 K7 i: `+ |% F- S: A8 o# Z
1 l% h+ C w" y
; K/ w/ [! y% P. {) |# V: z. W5 D9 |
上面的函数算出来一个数,假如是手册上的那个0x2c,二进制为101100B
7 z- C* s; r* Z5 k/ G3 t换句看得懂的人话···就是:2 j- G7 M q) G% |) z2 }' ?+ W0 p, x
算出来的数先看第6位+ S3 z/ G# t. Y1 |0 j
是1的话说明用到的是HASH表高位寄存器
3 y, {1 n2 ]- W0 |: k& [" g( a6 X否则用到的是HASH表低位寄存器3 F" q' u& {& }% U
然后剩下的5位,转成十进制不是12嘛1 v5 K" J9 [( n9 }
如果你希望过滤这个MAC
# g! J' O: O8 {1 \% a3 Z J9 \那么你就把对应的HASH表高/低位寄存器的对应位置1,否则置08 m8 ~( i3 I* B3 [ U. ]
这里的0x2c就是要把
4 t7 R7 B( y" r; P$ C/ j0 L4 CHASH表高位寄存器的第12位置1# f$ N$ H. P' z" r
就可以过滤这条MAC了9 M6 t7 \0 l5 B/ h. j' h- n
然后把你希望的MAC地址都按照上面说的方法弄完
' {. \) U6 [: e, M4 U- a3 J s* l" @$ a( C; i; W) E$ _# V
回到这个函数稍微改一下; l8 O5 \& n3 i# k6 m* f- c% c
- uint8_t ETH_MAC_Setting(ETH_HandleTypeDef *heth)1 p' W4 }* m! s4 r& _
- {
( C) A, T, U! d3 K$ N - ETH_MACInitTypeDef macinit;
* b( B& H$ O c - /* Ethernet MAC default initialization **************************************/
$ e5 t5 N) L! Q3 L - macinit.Watchdog = ETH_WATCHDOG_ENABLE;( l: x( r( Y5 J: D) t0 P. U
- macinit.Jabber = ETH_JABBER_ENABLE;8 M) {1 m- O1 S
- macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;/ x. b3 C- k0 h1 K1 d
- macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE; c- R4 X) ~2 |9 \' X9 U! |
- macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
, U8 F# Y# T$ f - macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;* ^' {2 V8 i9 C& F+ K# i- {
- if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE), V( F3 H- @$ o% l3 U! q
- {
: M! h. k; h" ~6 t2 }; h% y3 d - macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;2 d6 Q4 L+ k0 ~3 m$ ]' ~8 a
- }
4 K! D2 @6 n7 `. r/ @: t4 K - else/ k1 r: y6 H! N# A+ V# c% m. G8 {! v
- {
, T9 Z: D/ b6 }+ y7 H - macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;9 [" K2 @# F& @
- }
( [7 G0 d6 V7 A% F+ U/ b. O - macinit.RetryTransmission = ETH_RETRYTRANSMISSION_ENABLE; //使能重传
4 _: M( F6 ^; I: A% H3 S- h - macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_ENABLE; //使能自动去除% U3 c0 B2 t) N: h' M$ X
- macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;: @ H$ ^; v8 `+ b
- macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
) X/ H. a: o. ` - macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; ///不接收所有包" s8 h' P4 P3 H
- macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_NORMAL_ENABLE; //源地址过滤
. s" O6 N8 Q6 R6 ]+ k7 S - macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;
4 x _: B3 [! [1 O: h* f3 ~ - macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; //广播不接收
" n2 Q* O! G( `2 a3 g6 O - macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; //目的地址过滤
" [) w6 ^3 @# C! A+ J$ g: ]& T; _; l - macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; //混乱模式2 j$ E p* F: }& H5 h
- macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE; //!!多播HASH完美过滤3 |& q) z, B! ]1 H5 W
- macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE; //!!单播HASH完美过滤5 U- T q3 z# Z9 e) i
- macinit.HashTableHigh = 0x0; //!!填你最后算完的Hash表高位1 Y# `7 A Z5 v. g8 d2 t% U
- macinit.HashTableLow = 0x0; //!!填你最后算完的Hash表低位9 v3 v' z2 g) D% H* B
- macinit.PauseTime = 0x0;! `, R T* a) y2 s2 ~7 I( x
- macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;; }7 k _6 p4 h
- macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;. x) y) Z" z$ f1 w) W
- macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_ENABLE;
1 t) g8 r2 a1 C, K: q3 x - macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; //接收流控* a! E7 C) {& g4 n. _* z
- macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; //发送流控
1 \) j9 S1 S' y5 m' H& h7 Y# | R - macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;
6 r9 Z5 v3 `2 x Y - macinit.VLANTagIdentifier = 0x0;2 W6 Q1 J- E( V& \# w, I! J
- 9 ^! v1 U6 ?3 K. ^! r+ @" A" s" I
- return HAL_ETH_ConfigMAC(heth, &macinit);9 _1 c2 D" _1 d$ y, d
- }
复制代码 3 g. z! |5 h9 J( ?; {
大概MAC层过滤就这些东西了; d5 F, j9 Q" S0 Q3 p0 I3 _! p
如果有条件弄MAC层过滤真的强烈建议开启,可以大幅减轻协议栈的处理负担,板卡不会因为处理大量无用的数据而白白浪费处理性能。/ v" I0 S& K+ }6 S4 d! K
- H" Z6 ?- ~9 c* |& l- g O) l
2 o6 q) ? B: l" m6 o
& V% D/ R0 a1 q; w$ f
, ^2 p$ E' j. I7 @4 K |