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