在STM32F107环境下实现如下功能:
-以太网接口用作串口使用(区别于C / S模型);
-以太网接口接收全部的网内数据;
-对网内数据过滤,仅接收本相关数据包及包广播;
工具:
anysend.exe:Anysend是基于Winpcap自组开发的数据包,实现接口发送任意数据包的工具,各位请自行寻找下载;
wirehark.exe:网络抓捕工具
如果你是一个嵌入式开发人员,
MDK:嵌入式集成开发环境;
开发板:载stm32f107处理器+的开发板;
简要说下开发板外设:
开发外设
接口:使用SMI(MDC、MDIO)接口物理接口,参见下图的指引:
DMA发送占用(占用资源略):
相关接口的配置,主要关注MAC和DMA接口:
可能到的、DMA相关
接口如下:MAC地址如下:
部分资源:
接收数据处理程序:
/**
* @brief Called when a frame is received
* @param None
* @retval None
*/
void ETH_RxPkt_Handle(void)
{
u8 *buffer;
u16 len;
FrameTypeDef frame;
frame = ETH_RxPkt_ChainMode();
/* Obtain the size of the packet and put it into the “len”
variable. */
len = frame.length;
buffer= (u8*)frame.buffer;
memcpy(buff_rx,(u8*)&buffer[0], len);
/* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA
设置Rx描述符Status的 OWN位*/
frame.descriptor-》Status = ETH_DMARxDesc_OWN;
/* When Rx Buffer unavailable flag is set: clear it and resume reception
Rx缓冲区不可用时,清除ETH_DMASR_RBUS并且恢复接收*/
if ((ETH-》DMASR & ETH_DMASR_RBUS) != (u32)RESET)
{
/* Clear RBUS ETHERNET DMA flag */
ETH-》DMASR = ETH_DMASR_RBUS;
/* Resume DMA reception */
ETH-》DMARPDR = 0;
}
//ETH_DMA_test();
}
获取接收到的数据信息(DMA描述符)
/*******************************************************************************
* Function Name : ETH_RxPkt_ChainMode
* Description : 获取接收到的数据信息(DMA描述符)
* Input : None
* Output : None
* Return : frame: farme size and location
*******************************************************************************/
FrameTypeDef ETH_RxPkt_ChainMode(void)
{
u32 framelength = 0;
FrameTypeDef frame = {0,0};
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset)
检查这个描述符在被谁占用,DMA? CPU?*/
if((DMARxDescToGet-》Status & ETH_DMARxDesc_OWN) != (u32)RESET)
{ //不等于0,表示DMA正在使用描述符对应的缓冲区, 0==CPU占有,1==DMA占有,
frame.length = ETH_ERROR;
if ((ETH-》DMASR & ETH_DMASR_RBUS) != (u32)RESET)
{
/* Clear RBUS ETHERNET DMA flag */
ETH-》DMASR = ETH_DMASR_RBUS;
/* Resume DMA reception */
ETH-》DMARPDR = 0;
}
/* Return error: OWN bit set */
return frame;
}
if(((DMARxDescToGet-》Status & ETH_DMARxDesc_ES) == (u32)RESET) && //无相关错误
((DMARxDescToGet-》Status & ETH_DMARxDesc_LS) != (u32)RESET) && //这个描述符指向的缓冲区是帧的最后一个缓冲区
((DMARxDescToGet-》Status & ETH_DMARxDesc_FS) != (u32)RESET)) //这个描述符包含帧的第一个缓冲区
{
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC
获取接收数据包的长度,需要减掉4字节的CRC*/
framelength = ((DMARxDescToGet-》Status & ETH_DMARxDesc_FL) 》》 ETH_DMARxDesc_FrameLengthShift) - 4;
/* Get the addrees of the actual buffer */
frame.buffer = DMARxDescToGet-》Buffer1Addr;
}
else
{
/* Return ERROR */
framelength = ETH_ERROR;
}
frame.length = framelength;
frame.descriptor = DMARxDescToGet;
/* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor
更新DMA全局Rx描述符成为下一个Rx描述符*/
/* Chained Mode ==链表模式*/
/* Selects the next DMA Rx descriptor list for next buffer to read
选择下一个DMA Rx描述符链表为下一个缓冲区去读*/
DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet-》Buffer2NextDescAddr);
/* Return Frame */
return (frame);
}
发送数据包的处理程序:
err_t ETH_TxPkt_Handle(u8* buff,u16 len)
{
int l = 0;
u8 *buffer = (u8 *)ETH_GetCurrentTxBuffer();//获取当前的发送缓冲区地址
memcpy((u8*)&buffer[l], buff, len);
while(ETH_ERROR== ETH_TxPkt_ChainMode(len));
return 0;
}
更新DMA发送长度:
/*******************************************************************************
* Function Name : ETH_TxPkt_ChainMode
* Description : Transmits a packet, from application buffer, pointed by ppkt.
* Input : - FrameLength: Tx Packet size.
* Output : None
* Return : ETH_ERROR: in case of Tx desc owned by DMA
* ETH_SUCCESS: for correct transmission
*******************************************************************************/
u32 ETH_TxPkt_ChainMode(u16 FrameLength)
{
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
if((DMATxDescToSet-》Status & ETH_DMATxDesc_OWN) != (u32)RESET)
{ //被DMA占用
/* Return ERROR: OWN bit set */
return ETH_ERROR;
}
/* Setting the Frame Length: bits[12:0]
设置帧长*/
DMATxDescToSet-》ControlBufferSize = (FrameLength & ETH_DMATxDesc_TBS1);
/* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
DMATxDescToSet-》Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
DMATxDescToSet-》Status |= ETH_DMATxDesc_OWN;
/* When Tx Buffer unavailable flag is set: clear it and resume transmission */
if ((ETH-》DMASR & ETH_DMASR_TBUS) != (u32)RESET)
{
/* Clear TBUS ETHERNET DMA flag */
ETH-》DMASR = ETH_DMASR_TBUS;
/* Resume DMA transmission*/
ETH-》DMATPDR = 0;
}
/* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */
/* Chained Mode */
/* Selects the next DMA Tx descriptor list for next buffer to send */
DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet-》Buffer2NextDescAddr);
/* Return SUCCESS */
return ETH_SUCCESS;
}
应用:
接口接口接口使用(于C接口/S模型):
在MAC帧过滤过滤接口上文章:
ETH_InitStruc.ETH_ReceiveAll = ETH_ReceiveAll_Enable;//
关于发送数据接口,可以发送以太网II协议,不能检测发送IEEE802.3帧,问题寻找中;
接收接口接收全部的网内数据:
同上…
对网内数据包过滤,仅接收本机相关数据包及广播包;
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;//关闭接收所有的帧,来实现过滤掉 非本机为目的地址的数据
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;//允许接收所有广播帧
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable; //关闭混合模式的地址过滤
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;//对于组播地址使用完美地址过滤
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;//对单播地址使用完美地址过滤
在STM32F107环境下实现如下功能:
-以太网接口用作串口使用(区别于C / S模型);
-以太网接口接收全部的网内数据;
-对网内数据过滤,仅接收本相关数据包及包广播;
工具:
anysend.exe:Anysend是基于Winpcap自组开发的数据包,实现接口发送任意数据包的工具,各位请自行寻找下载;
wirehark.exe:网络抓捕工具
如果你是一个嵌入式开发人员,
MDK:嵌入式集成开发环境;
开发板:载stm32f107处理器+的开发板;
简要说下开发板外设:
开发外设
接口:使用SMI(MDC、MDIO)接口物理接口,参见下图的指引:
DMA发送占用(占用资源略):
相关接口的配置,主要关注MAC和DMA接口:
可能到的、DMA相关
接口如下:MAC地址如下:
部分资源:
接收数据处理程序:
/**
* @brief Called when a frame is received
* @param None
* @retval None
*/
void ETH_RxPkt_Handle(void)
{
u8 *buffer;
u16 len;
FrameTypeDef frame;
frame = ETH_RxPkt_ChainMode();
/* Obtain the size of the packet and put it into the “len”
variable. */
len = frame.length;
buffer= (u8*)frame.buffer;
memcpy(buff_rx,(u8*)&buffer[0], len);
/* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA
设置Rx描述符Status的 OWN位*/
frame.descriptor-》Status = ETH_DMARxDesc_OWN;
/* When Rx Buffer unavailable flag is set: clear it and resume reception
Rx缓冲区不可用时,清除ETH_DMASR_RBUS并且恢复接收*/
if ((ETH-》DMASR & ETH_DMASR_RBUS) != (u32)RESET)
{
/* Clear RBUS ETHERNET DMA flag */
ETH-》DMASR = ETH_DMASR_RBUS;
/* Resume DMA reception */
ETH-》DMARPDR = 0;
}
//ETH_DMA_test();
}
获取接收到的数据信息(DMA描述符)
/*******************************************************************************
* Function Name : ETH_RxPkt_ChainMode
* Description : 获取接收到的数据信息(DMA描述符)
* Input : None
* Output : None
* Return : frame: farme size and location
*******************************************************************************/
FrameTypeDef ETH_RxPkt_ChainMode(void)
{
u32 framelength = 0;
FrameTypeDef frame = {0,0};
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset)
检查这个描述符在被谁占用,DMA? CPU?*/
if((DMARxDescToGet-》Status & ETH_DMARxDesc_OWN) != (u32)RESET)
{ //不等于0,表示DMA正在使用描述符对应的缓冲区, 0==CPU占有,1==DMA占有,
frame.length = ETH_ERROR;
if ((ETH-》DMASR & ETH_DMASR_RBUS) != (u32)RESET)
{
/* Clear RBUS ETHERNET DMA flag */
ETH-》DMASR = ETH_DMASR_RBUS;
/* Resume DMA reception */
ETH-》DMARPDR = 0;
}
/* Return error: OWN bit set */
return frame;
}
if(((DMARxDescToGet-》Status & ETH_DMARxDesc_ES) == (u32)RESET) && //无相关错误
((DMARxDescToGet-》Status & ETH_DMARxDesc_LS) != (u32)RESET) && //这个描述符指向的缓冲区是帧的最后一个缓冲区
((DMARxDescToGet-》Status & ETH_DMARxDesc_FS) != (u32)RESET)) //这个描述符包含帧的第一个缓冲区
{
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC
获取接收数据包的长度,需要减掉4字节的CRC*/
framelength = ((DMARxDescToGet-》Status & ETH_DMARxDesc_FL) 》》 ETH_DMARxDesc_FrameLengthShift) - 4;
/* Get the addrees of the actual buffer */
frame.buffer = DMARxDescToGet-》Buffer1Addr;
}
else
{
/* Return ERROR */
framelength = ETH_ERROR;
}
frame.length = framelength;
frame.descriptor = DMARxDescToGet;
/* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor
更新DMA全局Rx描述符成为下一个Rx描述符*/
/* Chained Mode ==链表模式*/
/* Selects the next DMA Rx descriptor list for next buffer to read
选择下一个DMA Rx描述符链表为下一个缓冲区去读*/
DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet-》Buffer2NextDescAddr);
/* Return Frame */
return (frame);
}
发送数据包的处理程序:
err_t ETH_TxPkt_Handle(u8* buff,u16 len)
{
int l = 0;
u8 *buffer = (u8 *)ETH_GetCurrentTxBuffer();//获取当前的发送缓冲区地址
memcpy((u8*)&buffer[l], buff, len);
while(ETH_ERROR== ETH_TxPkt_ChainMode(len));
return 0;
}
更新DMA发送长度:
/*******************************************************************************
* Function Name : ETH_TxPkt_ChainMode
* Description : Transmits a packet, from application buffer, pointed by ppkt.
* Input : - FrameLength: Tx Packet size.
* Output : None
* Return : ETH_ERROR: in case of Tx desc owned by DMA
* ETH_SUCCESS: for correct transmission
*******************************************************************************/
u32 ETH_TxPkt_ChainMode(u16 FrameLength)
{
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
if((DMATxDescToSet-》Status & ETH_DMATxDesc_OWN) != (u32)RESET)
{ //被DMA占用
/* Return ERROR: OWN bit set */
return ETH_ERROR;
}
/* Setting the Frame Length: bits[12:0]
设置帧长*/
DMATxDescToSet-》ControlBufferSize = (FrameLength & ETH_DMATxDesc_TBS1);
/* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
DMATxDescToSet-》Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
DMATxDescToSet-》Status |= ETH_DMATxDesc_OWN;
/* When Tx Buffer unavailable flag is set: clear it and resume transmission */
if ((ETH-》DMASR & ETH_DMASR_TBUS) != (u32)RESET)
{
/* Clear TBUS ETHERNET DMA flag */
ETH-》DMASR = ETH_DMASR_TBUS;
/* Resume DMA transmission*/
ETH-》DMATPDR = 0;
}
/* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */
/* Chained Mode */
/* Selects the next DMA Tx descriptor list for next buffer to send */
DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet-》Buffer2NextDescAddr);
/* Return SUCCESS */
return ETH_SUCCESS;
}
应用:
接口接口接口使用(于C接口/S模型):
在MAC帧过滤过滤接口上文章:
ETH_InitStruc.ETH_ReceiveAll = ETH_ReceiveAll_Enable;//
关于发送数据接口,可以发送以太网II协议,不能检测发送IEEE802.3帧,问题寻找中;
接收接口接收全部的网内数据:
同上…
对网内数据包过滤,仅接收本机相关数据包及广播包;
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;//关闭接收所有的帧,来实现过滤掉 非本机为目的地址的数据
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;//允许接收所有广播帧
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable; //关闭混合模式的地址过滤
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;//对于组播地址使用完美地址过滤
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;//对单播地址使用完美地址过滤
举报