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