OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4343|回复: 1

关于STM32F767 以太网接收处理流程的问题

[复制链接]

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2012-4-21
在线时间
7 小时
发表于 2022-8-9 16:13:32 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 alvin1991 于 2022-8-9 16:27 编辑

复制代码
  1. /**
  2.   * @brief  Checks for received frames.
  3.   * @param  heth: pointer to a ETH_HandleTypeDef structure that contains
  4.   *         the configuration information for ETHERNET module
  5.   * @retval HAL status
  6.   */
  7. HAL_StatusTypeDef HAL_ETH_GetReceivedFrame(ETH_HandleTypeDef *heth)
  8. {
  9.   uint32_t framelength = 0;
  10.   
  11.   /* Process Locked */
  12.   __HAL_LOCK(heth);
  13.   
  14.   /* Check the ETH state to BUSY */
  15.   heth->State = HAL_ETH_STATE_BUSY;
  16.   
  17.   /* Check if segment is not owned by DMA */
  18.   /* (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && ((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET)) */
  19.   if(((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET))
  20.   {
  21.     /* Check if last segment */
  22.     if(((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET))
  23.     {
  24.       /* increment segment count */
  25.       (heth->RxFrameInfos).SegCount++;
  26.       
  27.       /* Check if last segment is first segment: one segment contains the frame */
  28.       if ((heth->RxFrameInfos).SegCount == 1)
  29.       {
  30.         (heth->RxFrameInfos).FSRxDesc =heth->RxDesc;
  31.       }
  32.       
  33.       heth->RxFrameInfos.LSRxDesc = heth->RxDesc;
  34.       
  35.       /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  36.       framelength = (((heth->RxDesc)->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4;
  37.       heth->RxFrameInfos.length = framelength;
  38.       
  39.       /* Get the address of the buffer start address */
  40.       heth->RxFrameInfos.buffer = ((heth->RxFrameInfos).FSRxDesc)->Buffer1Addr;
  41.       /* point to next descriptor */
  42.       heth->RxDesc = (ETH_DMADescTypeDef*) ((heth->RxDesc)->Buffer2NextDescAddr);
  43.       
  44.       /* Set HAL State to Ready */
  45.       heth->State = HAL_ETH_STATE_READY;
  46.       
  47.       /* Process Unlocked */
  48.       __HAL_UNLOCK(heth);
  49.       
  50.       /* Return function status */
  51.       return HAL_OK;
  52.     }
  53.     /* Check if first segment */
  54.     else if((heth->RxDesc->Status & ETH_DMARXDESC_FS) != (uint32_t)RESET)
  55.     {
  56.       (heth->RxFrameInfos).FSRxDesc = heth->RxDesc;
  57.       (heth->RxFrameInfos).LSRxDesc = NULL;
  58.       (heth->RxFrameInfos).SegCount = 1;
  59.       /* Point to next descriptor */
  60.       heth->RxDesc = (ETH_DMADescTypeDef*) (heth->RxDesc->Buffer2NextDescAddr);
  61.     }
  62.     /* Check if intermediate segment */
  63.     else
  64.     {
  65.       (heth->RxFrameInfos).SegCount++;
  66.       /* Point to next descriptor */
  67.       heth->RxDesc = (ETH_DMADescTypeDef*) (heth->RxDesc->Buffer2NextDescAddr);
  68.     }
  69.   }
  70.   
  71.   /* Set ETH HAL State to Ready */
  72.   heth->State = HAL_ETH_STATE_READY;
  73.   
  74.   /* Process Unlocked */
  75.   __HAL_UNLOCK(heth);
  76.   
  77.   /* Return function status */
  78.   return HAL_ERROR;
  79. }

  80. static struct pbuf * low_level_input(struct netif *netif)
  81. {  
  82.         struct pbuf *p = NULL;
  83.     struct pbuf *q;
  84.     uint16_t len;
  85.     uint8_t *buffer;
  86.     __IO ETH_DMADescTypeDef *dmarxdesc;
  87.     uint32_t bufferoffset=0;
  88.     uint32_t payloadoffset=0;
  89.     uint32_t byteslefttocopy=0;
  90.     uint32_t i=0;
  91.   
  92.     if(HAL_ETH_GetReceivedFrame(D_Handler)!=HAL_OK)  //判断是否接收到数据
  93.     return NULL;
  94.    
  95.     len=ETH_Handler.RxFrameInfos.length;                //获取接收到的以太网帧长度
  96.     buffer=(uint8_t *)ETH_Handler.RxFrameInfos.buffer;  //获取接收到的以太网帧的数据buffer
  97.   
  98.     if(len>0) p=pbuf_alloc(PBUF_RAW,len,PBUF_POOL);     //申请pbuf
  99.     if(p!=NULL)                                        //pbuf申请成功
  100.     {
  101.         dmarxdesc=ETH_Handler.RxFrameInfos.FSRxDesc;    //获取接收描述符链表中的第一个描述符
  102.         bufferoffset = 0;
  103.         for(q=p;q!=NULL;q=q->next)                     
  104.         {
  105.             byteslefttocopy=q->len;                  
  106.             payloadoffset=0;
  107.             //将接收描述符中Rx Buffer的数据拷贝到pbuf中
  108.             while((byteslefttocopy+bufferoffset)>ETH_RX_BUF_SIZE )
  109.             {
  110.                 //将数据拷贝到pbuf中
  111.                 memcpy((uint8_t*)((uint8_t*)q->payload+payloadoffset),(uint8_t*)((uint8_t*)buffer+bufferoffset),(ETH_RX_BUF_SIZE-bufferoffset));
  112.                  //dmarxdesc向下一个接收描述符
  113.                 dmarxdesc=(ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
  114.                 //更新buffer地址,指向新的接收描述符的Rx Buffer
  115.                 buffer=(uint8_t *)(dmarxdesc->Buffer1Addr);

  116.                 byteslefttocopy=byteslefttocopy-(ETH_RX_BUF_SIZE-bufferoffset);
  117.                 payloadoffset=payloadoffset+(ETH_RX_BUF_SIZE-bufferoffset);
  118.                 bufferoffset=0;
  119.             }
  120.             //拷贝剩余的数据
  121.             memcpy((uint8_t*)((uint8_t*)q->payload+payloadoffset),(uint8_t*)((uint8_t*)buffer+bufferoffset),byteslefttocopy);
  122.             bufferoffset=bufferoffset+byteslefttocopy;
  123.         }
  124.     }   
  125.     //释放DMA描述符
  126.     dmarxdesc=ETH_Handler.RxFrameInfos.FSRxDesc;
  127.     for(i=0;i<ETH_Handler.RxFrameInfos.SegCount; i++)
  128.     {  
  129.         dmarxdesc->Status|=ETH_DMARXDESC_OWN;       //标记描述符归DMA所有
  130.         dmarxdesc=(ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
  131.     }
  132.     ETH_Handler.RxFrameInfos.SegCount =0;           //清除段计数器
  133.     if((ETH_Handler.Instance->DMASRD_DMASR_RBUS)!=(uint32_t)RESET)  //接收缓冲区不可用
  134.     {
  135.         //清除接收缓冲区不可用标志
  136.         ETH_Handler.Instance->DMASR = ETH_DMASR_RBUS;
  137.         //当接收缓冲区不可用的时候RxDMA会进去挂起状态,通过向DMARPDR写入任意一个值来唤醒Rx DMA
  138.         ETH_Handler.Instance->DMARPDR=0;
  139.     }
  140.     return p;
  141. }
复制代码

各位坛友,在STM32F767上进行以太网测试时发现,当硬件(MAC)接收到一帧以太网数据帧时,在处理过程中分为了三种情况:
  • line22:当前数据帧是否为最后一帧数据
  • line54:当前数据帧是否是第一帧数据
  • line63:当前数据处于第一帧和最后一帧数据之间

代码中在对第2、3种情况,只是记录了SegCount ,并没有对descriptor中的数据进行任何处理。是不是意味着如果出现多帧数据时,只会处理最后一帧数据呢?

有没有大佬能帮忙解答下,谢谢!!!




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2012-4-21
在线时间
7 小时
 楼主| 发表于 2022-8-9 16:16:12 | 显示全部楼层
本帖最后由 alvin1991 于 2022-8-9 16:27 编辑
  1.    if(HAL_ETH_GetReceivedFrame(D_Handler)!=HAL_OK)  //判断是否接收到数据
  2.     return NULL;
复制代码
实际的调用的过程中,只有最后一帧数据才返回HAL_OK,所以从代码俩看,应该是没有进行相应的处理。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-25 09:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表