关于以太网(Ethernet II)这个网络的个人理解以及应用(2)
2016-09-26 00:17
666 查看
惩戒上篇文章,这里说下实际的开发应用,
在stm32f107环境下实现如下功能:
- 以太网接口用作串口使用(区别于C/S模型);
- 以太网接口接收全部的网内数据;
- 对网内数据包过滤,仅接收本机相关数据包及广播包;
wireshark.exe:网络抓包工具
如果你是一个嵌入式开发人员,
MDK:嵌入式集成开发环境;
开发板:板载stm32f107处理器+PHY的开发板;
关于发送数据环节,只能发送Ethernet II协议侦,不能发送IEEE802.3帧,问题查找中;
链接: http://pan.baidu.com/s/1qXFVzze 密码: gkka
这块说的比较笼统,毕竟以太网很庞大,本人理解有限,想说出来更加费劲,,,,大伙有情况再一块儿分析,,,,
在stm32f107环境下实现如下功能:
- 以太网接口用作串口使用(区别于C/S模型);
- 以太网接口接收全部的网内数据;
- 对网内数据包过滤,仅接收本机相关数据包及广播包;
工具:
anysend.exe:Anysend是基于Winpcap驱动开发的,实现以太网接口发送任意自组数据包的工具,各位请自行查找下载;wireshark.exe:网络抓包工具
如果你是一个嵌入式开发人员,
MDK:嵌入式集成开发环境;
开发板:板载stm32f107处理器+PHY的开发板;
简要说下以太网外设:
以太网外设框图:
使用SMI接口(MDC、MDIO)读写PHY寄存器,参见下图的指引:
DMA发送描述符(接收描述符–略):
相关寄存器的配置,主要关注MAC寄存器和DMA寄存器:
可能用到的MAC、DMA相关寄存器如下:
源码流程图如下:
部分源码:
接收数据处理程序:
/** * @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_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable;//
关于发送数据环节,只能发送Ethernet 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;//对单播地址使用完美地址过滤
源码参考:
对网内数据包过滤,仅接收本机相关数据包及广播包”应用源码见网盘:链接: http://pan.baidu.com/s/1qXFVzze 密码: gkka
这块说的比较笼统,毕竟以太网很庞大,本人理解有限,想说出来更加费劲,,,,大伙有情况再一块儿分析,,,,
相关文章推荐
- 关于以太网(Ethernet II)这个网络的个人理解以及应用(1)
- 关于OC中消息转发机制的理解以及在项目中的实际应用
- 关于回调函数应用的理解以及小例子
- 关于JAVA面向对象基础整理以及个人的理解(适合初学者阅读)
- redis 个人理解和常用命令以及应用场景
- 个人理解的VueJS生命周期以及其中钩子函数的实际应用
- 关于wordpress的$post全局变量,以及主循环the loop的一些个人理解。
- 关于数据库中FK的简单理解以及应用
- 关于DataRow和DataColumn的一点个人简单理解-.NET教程,数据库应用
- 关于property,以及python oop的个人理解
- 关于coordinatorLayout的应用的个人理解
- 关于OC中消息转发机制的理解以及在项目中的实际应用
- 关于SQL SERVER 公用表达式CTE应用递归时的模型个人的理解
- Struts新用法以及关于理解
- 关于FLASH与XML交互应用中的理解
- silverlight应用以及发展前景,个人看好Silverlight 所以收集点资料供大家参考
- 关于XML在与FLASH交互应用中的理解
- 个人对网络协议的一点理解(原创)
- 关于快速开发和设计应用系统的一些个人的意见
- 关于学好J2SE有啥用的个人理解