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