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