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