你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 F7的MAC层过滤使用+实例代码

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:15
前景描述
我司的以太网实现是LAN8720搭配片上MAC层做的,协议栈用LWIP

这种做法应该还是蛮常见的,反正不是LAN8720就是DP83864,再不然就是硬件协议栈的W5500了

想想还是有MAC层过滤比较好,随手翻了翻它的手册,W5500好像是没得MAC层过滤的

假如数据速率比较高,数据量大,而且外面还有乱七八糟无关的数据往板卡送,我也不知道用这个片子到底好不好

LAN8720也不好改了,就继续用吧

好好在,发给板卡的数据的MAC还是有特征的,我只需要过滤发送方MAC地址的前3个字节,也就是特定的厂家那段

MAC地址的科普知识这里就不过多描述了,我们直奔主题

怎么用STM32 F7的片上MAC做MAC层过滤

写这个的目的,就是我搜了搜,没看见有人写这个MAC层过滤功能,具体代码怎么写才能用

知识科普-STM32的片上MAC
STM32 F7的MAC层过滤方式有三种(说人话的直白解释,中文手册其实也翻译的不好)
精确过滤(手册上叫单播目标/源地址过滤)
粗糙过滤(手册上叫Hash表过滤)
特殊过滤(广播,组播过滤等等特殊的过滤)
我这里着重说第1种和第3种

STM32 F7可以存4个MAC地址
其中MAC地址0是自己的MAC,其他三个可以用来做过滤

网络数据包通过PHY进入STM32的MAC,MAC层是可以对目的地址/源地址检查并过滤掉没得用的数据的,默认的HAL库库函数HAL_ETH_Init中
有一个static的函数
static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)
会帮你在初始化网络功能时初始化默认的MAC层功能:
关闭源地址过滤
不接收所有数据
接收广播帧
打开目的地地址过滤
单播数据精确过滤
组播数据精确过滤
Hash表过滤关闭

其他的功能自行研究,我这里捡重要的说
  1. static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)
  2. {
  3. ETH_MACInitTypeDef macinit;
  4. ETH_DMAInitTypeDef dmainit;
  5. uint32_t tmpreg = 0;

  6. if (err != ETH_SUCCESS) /* Auto-negotiation failed */
  7. {
  8. /* Set Ethernet duplex mode to Full-duplex */
  9. (heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;

  10. /* Set Ethernet speed to 100M */
  11. (heth->Init).Speed = ETH_SPEED_100M;
  12. }

  13. /* Ethernet MAC default initialization **************************************/
  14. macinit.Watchdog = ETH_WATCHDOG_ENABLE;
  15. macinit.Jabber = ETH_JABBER_ENABLE;
  16. macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;
  17. macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;
  18. macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
  19. macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;
  20. if(heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)
  21. {
  22. macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
  23. }
  24. else
  25. {
  26. macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
  27. }
  28. //这一段是MAC层过滤的设置,下面是DMA的,那个用默认的就可以
  29. macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE;
  30. macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;
  31. macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;
  32. macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
  33. macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE;
  34. macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE;
  35. macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;
  36. macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;
  37. macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL;
  38. macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;
  39. macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT;
  40. macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;
  41. macinit.HashTableHigh = 0x0;
  42. macinit.HashTableLow = 0x0;
  43. macinit.PauseTime = 0x0;
  44. macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;
  45. macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;
  46. macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE;
  47. macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE;
  48. macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE;
  49. macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;
  50. macinit.VLANTagIdentifier = 0x0;

  51. /*------------------------ ETHERNET MACCR Configuration --------------------*/
  52. /* Get the ETHERNET MACCR value */
  53. tmpreg = (heth->Instance)->MACCR;
  54. /* Clear WD, PCE, PS, TE and RE bits */
  55. tmpreg &= ETH_MACCR_CLEAR_MASK;
  56. /* Set the WD bit according to ETH Watchdog value */
  57. /* Set the JD: bit according to ETH Jabber value */
  58. /* Set the IFG bit according to ETH InterFrameGap value */
  59. /* Set the DCRS bit according to ETH CarrierSense value */
  60. /* Set the FES bit according to ETH Speed value */
  61. /* Set the DO bit according to ETH ReceiveOwn value */
  62. /* Set the LM bit according to ETH LoopbackMode value */
  63. /* Set the DM bit according to ETH Mode value */
  64. /* Set the IPCO bit according to ETH ChecksumOffload value */
  65. /* Set the DR bit according to ETH RetryTransmission value */
  66. /* Set the ACS bit according to ETH AutomaticPadCRCStrip value */
  67. /* Set the BL bit according to ETH BackOffLimit value */
  68. /* Set the DC bit according to ETH DeferralCheck value */
  69. tmpreg |= (uint32_t)(macinit.Watchdog |
  70. macinit.Jabber |
  71. macinit.InterFrameGap |
  72. macinit.CarrierSense |
  73. (heth->Init).Speed |
  74. macinit.ReceiveOwn |
  75. macinit.LoopbackMode |
  76. (heth->Init).DuplexMode |
  77. macinit.ChecksumOffload |
  78. macinit.RetryTransmission |
  79. macinit.AutomaticPadCRCStrip |
  80. macinit.BackOffLimit |
  81. macinit.DeferralCheck);

  82. /* Write to ETHERNET MACCR */
  83. (heth->Instance)->MACCR = (uint32_t)tmpreg;

  84. /* Wait until the write operation will be taken into account:
  85. at least four TX_CLK/RX_CLK clock cycles */
  86. tmpreg = (heth->Instance)->MACCR;
  87. HAL_Delay(ETH_REG_WRITE_DELAY);
  88. (heth->Instance)->MACCR = tmpreg;

  89. /*----------------------- ETHERNET MACFFR Configuration --------------------*/
  90. /* Set the RA bit according to ETH ReceiveAll value */
  91. /* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */
  92. /* Set the PCF bit according to ETH PassControlFrames value */
  93. /* Set the DBF bit according to ETH BroadcastFramesReception value */
  94. /* Set the DAIF bit according to ETH DestinationAddrFilter value */
  95. /* Set the PR bit according to ETH PromiscuousMode value */
  96. /* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */
  97. /* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */
  98. /* Write to ETHERNET MACFFR */
  99. (heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll |
  100. macinit.SourceAddrFilter |
  101. macinit.PassControlFrames |
  102. macinit.BroadcastFramesReception |
  103. macinit.DestinationAddrFilter |
  104. macinit.PromiscuousMode |
  105. macinit.MulticastFramesFilter |
  106. macinit.UnicastFramesFilter);

  107. /* Wait until the write operation will be taken into account:
  108. at least four TX_CLK/RX_CLK clock cycles */
  109. tmpreg = (heth->Instance)->MACFFR;
  110. HAL_Delay(ETH_REG_WRITE_DELAY);
  111. (heth->Instance)->MACFFR = tmpreg;

  112. /*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*/
  113. /* Write to ETHERNET MACHTHR */
  114. (heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh;

  115. /* Write to ETHERNET MACHTLR */
  116. (heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow;
  117. /*----------------------- ETHERNET MACFCR Configuration -------------------*/

  118. /* Get the ETHERNET MACFCR value */
  119. tmpreg = (heth->Instance)->MACFCR;
  120. /* Clear xx bits */
  121. tmpreg &= ETH_MACFCR_CLEAR_MASK;

  122. /* Set the PT bit according to ETH PauseTime value */
  123. /* Set the DZPQ bit according to ETH ZeroQuantaPause value */
  124. /* Set the PLT bit according to ETH PauseLowThreshold value */
  125. /* Set the UP bit according to ETH UnicastPauseFrameDetect value */
  126. /* Set the RFE bit according to ETH ReceiveFlowControl value */
  127. /* Set the TFE bit according to ETH TransmitFlowControl value */
  128. tmpreg |= (uint32_t)((macinit.PauseTime Instance)->MACFCR = (uint32_t)tmpreg;

  129. /* Wait until the write operation will be taken into account:
  130. at least four TX_CLK/RX_CLK clock cycles */
  131. tmpreg = (heth->Instance)->MACFCR;
  132. HAL_Delay(ETH_REG_WRITE_DELAY);
  133. (heth->Instance)->MACFCR = tmpreg;

  134. /*----------------------- ETHERNET MACVLANTR Configuration ----------------*/
  135. /* Set the ETV bit according to ETH VLANTagComparison value */
  136. /* Set the VL bit according to ETH VLANTagIdentifier value */
  137. (heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison |
  138. macinit.VLANTagIdentifier);

  139. /* Wait until the write operation will be taken into account:
  140.    at least four TX_CLK/RX_CLK clock cycles */
  141. tmpreg = (heth->Instance)->MACVLANTR;
  142. HAL_Delay(ETH_REG_WRITE_DELAY);
  143. (heth->Instance)->MACVLANTR = tmpreg;

  144. /* Ethernet DMA default initialization ************************************/
  145. dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
  146. dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;
  147. dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;
  148. dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;
  149. dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;
  150. dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
  151. dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;
  152. dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;
  153. dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;
  154. dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
  155. dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;
  156. dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
  157. dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
  158. dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE;
  159. dmainit.DescriptorSkipLength = 0x0;
  160. dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;

  161. /* Get the ETHERNET DMAOMR value */
  162. tmpreg = (heth->Instance)->DMAOMR;
  163. /* Clear xx bits */
  164. tmpreg &= ETH_DMAOMR_CLEAR_MASK;

  165. /* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */
  166. /* Set the RSF bit according to ETH ReceiveStoreForward value */
  167. /* Set the DFF bit according to ETH FlushReceivedFrame value */
  168. /* Set the TSF bit according to ETH TransmitStoreForward value */
  169. /* Set the TTC bit according to ETH TransmitThresholdControl value */
  170. /* Set the FEF bit according to ETH ForwardErrorFrames value */
  171. /* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */
  172. /* Set the RTC bit according to ETH ReceiveThresholdControl value */
  173. /* Set the OSF bit according to ETH SecondFrameOperate value */
  174. tmpreg |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame |
  175.                      dmainit.ReceiveStoreForward |
  176.                      dmainit.FlushReceivedFrame |
  177.                      dmainit.TransmitStoreForward |
  178.                      dmainit.TransmitThresholdControl |
  179.                      dmainit.ForwardErrorFrames |
  180.                      dmainit.ForwardUndersizedGoodFrames |
  181.                      dmainit.ReceiveThresholdControl |
  182.                      dmainit.SecondFrameOperate);

  183. /* Write to ETHERNET DMAOMR */
  184. (heth->Instance)->DMAOMR = (uint32_t)tmpreg;

  185. /* Wait until the write operation will be taken into account:
  186.    at least four TX_CLK/RX_CLK clock cycles */
  187. tmpreg = (heth->Instance)->DMAOMR;
  188. HAL_Delay(ETH_REG_WRITE_DELAY);
  189. (heth->Instance)->DMAOMR = tmpreg;

  190. /*----------------------- ETHERNET DMABMR Configuration ------------------*/
  191. /* Set the AAL bit according to ETH AddressAlignedBeats value */
  192. /* Set the FB bit according to ETH FixedBurst value */
  193. /* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */
  194. /* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */
  195. /* Set the Enhanced DMA descriptors bit according to ETH EnhancedDescriptorFormat value*/
  196. /* Set the DSL bit according to ETH DesciptorSkipLength value */
  197. /* Set the PR and DA bits according to ETH DMAArbitration value */
  198. (heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats |
  199.                                       dmainit.FixedBurst |
  200.                                       dmainit.RxDMABurstLength |    /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */
  201.                                       dmainit.TxDMABurstLength |
  202.                                       dmainit.EnhancedDescriptorFormat |
  203.                                       (dmainit.DescriptorSkipLength Instance)->DMABMR;
  204. HAL_Delay(ETH_REG_WRITE_DELAY);
  205. (heth->Instance)->DMABMR = tmpreg;

  206. if((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)
  207. {
  208.    /* Enable the Ethernet Rx Interrupt */
  209.    __HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);
  210. }

  211. /* Initialize MAC address in ethernet MAC */
  212. ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
  213. }
复制代码

这里我就要稍微吐槽一下HAL库了
MAC层过滤的设置没有预留接口出来,有设置MAC地址的函数

static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr)

就不多做一个设置MAC层过滤的函数嘛,连后面用到的宏定义都有~~

木有办法,自己编一个初始化MAC层过滤的函数吧

其实也就是把上面这个ETH_MACDMAConfig函数分离成两个单独的设置函数,再编一个设置MAC层过滤的函数

开启MAC层过滤的初始化代码

  1. uint8_t ETH_MAC_Setting(ETH_HandleTypeDef *heth)
  2. {
  3. ETH_MACInitTypeDef macinit;
  4. /* Ethernet MAC default initialization **************************************/
  5. macinit.Watchdog = ETH_WATCHDOG_ENABLE;
  6. macinit.Jabber = ETH_JABBER_ENABLE;
  7. macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;
  8. macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;
  9. macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
  10. macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;
  11. if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)
  12. {
  13. macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
  14. }
  15. else
  16. {
  17. macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
  18. }
  19. macinit.RetryTransmission = ETH_RETRYTRANSMISSION_ENABLE;          //使能重传
  20. macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_ENABLE;          //使能自动去除
  21. macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;
  22. macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
  23. macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; ///不接收所有包
  24. macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_NORMAL_ENABLE; //源地址过滤
  25. macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;
  26. macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; //广播不接收
  27. macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; //目的地址过滤
  28. macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; //混乱模式
  29. macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; //多播过滤
  30. macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; //单播过滤
  31. macinit.HashTableHigh = 0x0; //Hash表高位
  32. macinit.HashTableLow = 0x0; //Hash表低位
  33. macinit.PauseTime = 0x0;
  34. macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;
  35. macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;
  36. macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_ENABLE;
  37. macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; //接收流控
  38. macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; //发送流控
  39. macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;
  40. macinit.VLANTagIdentifier = 0x0;

  41. return HAL_ETH_ConfigMAC(heth, &macinit);
  42. }
复制代码

默认的MAC层 DMA初始化函数
  1. uint8_t ETH_DMA_Setting(ETH_HandleTypeDef *heth)
  2. {
  3. ETH_DMAInitTypeDef dmainit;
  4. /* Ethernet DMA default initialization ************************************/
  5. dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
  6. dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;
  7. dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;
  8. dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;
  9. dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;
  10. dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
  11. dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;
  12. dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;
  13. dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;
  14. dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
  15. dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;
  16. dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
  17. dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
  18. dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE;
  19. dmainit.DescriptorSkipLength = 0x0;
  20. dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;
  21. uint8_t res =  HAL_ETH_ConfigDMA(heth, &dmainit);
  22. if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)
  23. {
  24. /* Enable the Ethernet Rx Interrupt */
  25. __HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);
  26. }
  27. return res;
  28. }
复制代码

用来设置MAC地址的函数(其实就是把库函数的static函数取出来直接用了)
  1. <blockquote>//heth: HAL句柄
复制代码

然后到最最重要的MAC层过滤设置

以MAC1为例

20191124093921254.png


20191124094439199.png


注意看红框的描述

功能很好用,可以过滤源地址/目的地址,还可以做掩码功能
设置MAC层过滤的代码
  1. static void ETH_MAC_Filter_Setting(ETH_HandleTypeDef *heth,ST_ETH_PAR * para)
  2. {
  3.     //设置本机MAC地址
  4.     ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
  5.     //设置UDP-A的对方MAC地址
  6.     ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS1,para->UDP_A_MAC);
  7.     (heth->Instance)->MACA1HR|=0xC0000000;//需要完全匹配UDP-A的对方MAC才接收
  8.     //设置UDP-B的对方MAC地址
  9.     ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS2,para->UDP_B_MAC);
  10.     (heth->Instance)->MACA2HR|=0xC0000000;//需要完全匹配UDP-A的对方MAC才接收
  11. }
复制代码

我这里是希望为我的两个UDP精确过滤接收到的源地址
所以AE位设置为1,SA设置为1,MBC全部为0(MAC地址全部检查)

假如我希望过滤MAC中特定的厂家字段
例如某个MAC地址

01-02-03-04-05-06
其中01-02-03就是厂家字段

那么代码要这样修改(MBC的第29位,28位,27位置1)
这样MAC层就不会检查MAC地址里后3个字节(04-05-06)
但是会检查前3个字节,也就是厂家字段
这里需要注意MAC地址的字节序
  1. static void ETH_MAC_Filter_Setting(ETH_HandleTypeDef *heth,ST_ETH_PAR * para)
  2. {
  3.     //设置本机MAC地址
  4.     ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
  5.     //设置UDP-A的对方MAC地址
  6.     ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS1,para->UDP_A_MAC);
  7.     (heth->Instance)->MACA1HR|=0xF8000000;//需要匹配厂家字段
  8.     //设置UDP-B的对方MAC地址
  9.     ETH_MAC_ADDR_Config(heth, ETH_MAC_ADDRESS2,para->UDP_B_MAC);
  10.     (heth->Instance)->MACA2HR|=0xF8000000;//需要匹配厂家字段
  11. }
复制代码

然后这些函数的调用顺序按:
1. HAL_ETH_Init
2. ETH_MAC_Setting
3. ETH_DMA_Setting
4. ETH_MAC_Filter_Setting

用你希望过滤的MAC传递到一个Hash计算函数里,得到一个值,通过这个值产生“映射”关系来过滤MAC地址,所以这个并不是精确的,因为可能会重复~~

HASH函数
函数
  1. / STM32 MACHASH - Copyright (C) 2014-2018 Clive Turvey (<a href="mailto:sourcer32@gmail.com">sourcer32@gmail.com</a>)
  2. //  All Rights Reserved

  3. #include <windows.h>

  4. #include <stdio.h>
  5. #include <stdlib.h>

  6. typedef unsigned char uint8_t;
  7. typedef unsigned long uint32_t;

  8. uint32_t Rev32(uint32_t x)
  9. {
  10.   uint32_t y;
  11.   int i;

  12.   y = 0;

  13.   for(i=0; i<32; i++)
  14.     if (x & (1 << i))
  15.       y |= 1 << (31 - i);

  16.   return(y);
  17. }

  18. uint32_t MacHash(const uint8_t *Mac) // <a href="mailto:sourcer32@gmail.com">sourcer32@gmail.com</a>
  19. {
  20.   int i, j;
  21.   uint32_t Crc;

  22.   Crc = 0xFFFFFFFF;

  23.   for(j=0; j<6; j++)
  24.   {
  25.     Crc = Crc ^ (uint32_t)Mac[j];

  26.     for(i=0; i<8; i++)
  27.       if (Crc & 1)
  28.         Crc = (Crc >> 1) ^ 0xEDB88320; // Reversed 0x04C11DB7
  29.       else
  30.         Crc = (Crc >> 1);
  31.   }

  32.   return(Rev32(~Crc) >> 26); // Get High order 6-bit in reversed/inverted CRC
  33. }

  34. uint32_t MacHashFast(const uint8_t *Mac) // <a href="mailto:sourcer32@gmail.com">sourcer32@gmail.com</a>
  35. {
  36.   static const uint32_t Rev6Tbl[] = {
  37.     0x00,0x20,0x10,0x30,0x08,0x28,0x18,0x38,
  38.     0x04,0x24,0x14,0x34,0x0C,0x2C,0x1C,0x3C,
  39.     0x02,0x22,0x12,0x32,0x0A,0x2A,0x1A,0x3A,
  40.     0x06,0x26,0x16,0x36,0x0E,0x2E,0x1E,0x3E,
  41.     0x01,0x21,0x11,0x31,0x09,0x29,0x19,0x39,
  42.     0x05,0x25,0x15,0x35,0x0D,0x2D,0x1D,0x3D,
  43.     0x03,0x23,0x13,0x33,0x0B,0x2B,0x1B,0x3B,
  44.     0x07,0x27,0x17,0x37,0x0F,0x2F,0x1F,0x3F };

  45.   static const uint32_t Crc32Tbl[] = {
  46.     0x4DBDF21C, 0x500AE278, 0x76D3D2D4, 0x6B64C2B0,
  47.     0x3B61B38C, 0x26D6A3E8, 0x000F9344, 0x1DB88320,
  48.     0xA005713C, 0xBDB26158, 0x9B6B51F4, 0x86DC4190,
  49.     0xD6D930AC, 0xCB6E20C8, 0xEDB71064, 0xF0000000 };

  50.   int i;
  51.   uint32_t Crc;

  52.   Crc = 0;

  53.   for(i=0; i<6; i++)
  54.   {
  55.     Crc = Crc ^ (uint32_t)Mac<i>;

  56. </i>   Crc = (Crc >> 4) ^ Crc32Tbl[Crc & 0x0F];  /* lower nibble */
  57.     Crc = (Crc >> 4) ^ Crc32Tbl[Crc & 0x0F];  /* upper nibble */
  58.   }

  59.   return(Rev6Tbl[Crc & 0x3F]);
  60. }

  61. int main(int argc, char **argv)
  62. {
  63.   static const uint8_t Test1[] = { 0x1F, 0x52, 0x41, 0x9C, 0xB6, 0xAF }; // 0x2C
  64.   static const uint8_t Test2[] = { 0xA0, 0x0A, 0x98, 0x00, 0x00, 0x45 }; // 0x07
  65.   static const uint8_t Test3[] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x21 }; // 0x24

  66.   printf("MacHash %02X\n", MacHash(Test1));
  67.   printf("MacHash %02X\n", MacHash(Test2));
  68.   printf("MacHash %02X\n", MacHash(Test3));

  69.   printf("MacHashFast %02X\n", MacHashFast(Test1));
  70.   printf("MacHashFast %02X\n", MacHashFast(Test2));
  71.   printf("MacHashFast %02X\n", MacHashFast(Test3));

  72.   return(1);
  73. }
复制代码


回到手册

20191124100604140.png


20191124100636882.png



上面的函数算出来一个数,假如是手册上的那个0x2c,二进制为101100B
换句看得懂的人话···就是:
算出来的数先看第6位
是1的话说明用到的是HASH表高位寄存器
否则用到的是HASH表低位寄存器
然后剩下的5位,转成十进制不是12嘛
如果你希望过滤这个MAC
那么你就把对应的HASH表高/低位寄存器的对应位置1,否则置0
这里的0x2c就是要把
HASH表高位寄存器的第12位置1
就可以过滤这条MAC了
然后把你希望的MAC地址都按照上面说的方法弄完

回到这个函数稍微改一下
  1. uint8_t ETH_MAC_Setting(ETH_HandleTypeDef *heth)
  2. {
  3.     ETH_MACInitTypeDef macinit;
  4.     /* Ethernet MAC default initialization **************************************/
  5.     macinit.Watchdog = ETH_WATCHDOG_ENABLE;
  6.     macinit.Jabber = ETH_JABBER_ENABLE;
  7.     macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;
  8.     macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;
  9.     macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
  10.     macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;
  11.     if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)
  12.     {
  13.         macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
  14.     }
  15.     else
  16.     {
  17.         macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
  18.     }
  19.     macinit.RetryTransmission = ETH_RETRYTRANSMISSION_ENABLE;          //使能重传
  20.     macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_ENABLE;          //使能自动去除
  21.     macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;
  22.     macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
  23.     macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; ///不接收所有包
  24.     macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_NORMAL_ENABLE; //源地址过滤
  25.     macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;
  26.     macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; //广播不接收
  27.     macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; //目的地址过滤
  28.     macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; //混乱模式
  29.     macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE; //!!多播HASH完美过滤
  30.     macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE; //!!单播HASH完美过滤
  31.     macinit.HashTableHigh = 0x0; //!!填你最后算完的Hash表高位
  32.     macinit.HashTableLow = 0x0; //!!填你最后算完的Hash表低位
  33.     macinit.PauseTime = 0x0;
  34.     macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;
  35.     macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;
  36.     macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_ENABLE;
  37.     macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; //接收流控
  38.     macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; //发送流控
  39.     macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;
  40.     macinit.VLANTagIdentifier = 0x0;

  41.     return HAL_ETH_ConfigMAC(heth, &macinit);
  42. }
复制代码

大概MAC层过滤就这些东西了
如果有条件弄MAC层过滤真的强烈建议开启,可以大幅减轻协议栈的处理负担,板卡不会因为处理大量无用的数据而白白浪费处理性能。




收藏 评论0 发布时间:2021-12-14 10:15

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版