OpenEdv-开源电子网

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

F4以太网驱动发送逻辑有问题?

[复制链接]

6

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2018-11-26
在线时间
21 小时
发表于 2020-2-13 14:52:47 | 显示全部楼层 |阅读模式
1金钱

我在分析正点原子F4探索者的LWIP源码的时候,发现以太网底层驱动发送的数据的时候,发现没有检查DMA描述符是否是能够被CPU使用的,就拷贝数据到了描述符的缓冲区中,怎么看都感觉不是很合理(以下代码的红色部分)。但是在ETH_Tx_Packet函数中,一进函数的时候就检查了描述符是否是能够被CPU使用的。感觉有点先斩后奏的意思。还请大佬们指教,我自己的理解是,在拷贝数据到描述符的缓冲区之前,就应该先检查描述符是否能够被CPU访问,不是的话,直接返回错误就行,能够被访问的时候才去拷贝数据,设置长度和标志位等后续的操作。

  1. <div><div>//用于发送数据包的最底层函数(lwip通过netif->linkoutput指向该函数)</div><div>//netif:网卡结构体指针</div><div>//p:pbuf数据结构体指针</div><div>//返回值:ERR_OK,发送正常</div><div>//       ERR_MEM,发送失败</div><div>static err_t low_level_output(struct netif *netif, struct pbuf *p)</div><div>{</div><div><span style="white-space:pre">        </span>u8 res;</div><div><span style="white-space:pre">        </span>struct pbuf *q;</div><div><span style="white-space:pre">        </span>int l = 0;</div><div><font color="#ff0000"><span style="white-space:pre">        </span>u8 *buffer=(u8 *)ETH_GetCurrentTxBuffer(); </font></div><div><font color="#ff0000"><span style="white-space:pre">        </span>for(q=p;q!=NULL;q=q->next) </font></div><div><font color="#ff0000"><span style="white-space:pre">        </span>{</font></div><div><font color="#ff0000"><span style="white-space:pre">                </span>memcpy((u8_t*)&buffer[l], q->payload, q->len);</font></div><div><font color="#ff0000"><span style="white-space:pre">                </span>l=l+q->len;</font></div><div><font color="#ff0000"><span style="white-space:pre">        </span>} </font></div><div><span style="white-space:pre">        </span>res=ETH_Tx_Packet(l); </div><div><span style="white-space:pre">        </span>if(res==ETH_ERROR)return ERR_MEM;//返回错误状态</div><div><span style="white-space:pre">        </span>return ERR_OK;</div><div>}  </div></div><div>
  2. </div><div><div>//发送一个网卡数据包</div><div>//FrameLength:数据包长度</div><div>//返回值:ETH_ERROR,发送失败(0)</div><div>//<span style="white-space:pre">                </span>ETH_SUCCESS,发送成功(1)</div><div>u8 ETH_Tx_Packet(u16 FrameLength)</div><div>{   </div><div><font color="#8b0000"><span style="white-space:pre">        </span>//检查当前描述符,是否属于ETHERNET DMA(设置的时候)/CPU(复位的时候)</font></div><div><font color="#8b0000"><span style="white-space:pre">        </span>if((DMATxDescToSet->Status&ETH_DMATxDesc_OWN)!=(u32)RESET)</font></div><div><font color="#8b0000"><span style="white-space:pre">                </span>return ETH_ERROR;//错误,OWN位被设置了 </font></div><div> <span style="white-space:pre">        </span></div><div><span style="white-space:pre">        </span>DMATxDescToSet->ControlBufferSize=(FrameLength&ETH_DMATxDesc_TBS1);//设置帧长度,bits[12:0]</div><div><span style="white-space:pre">        </span>DMATxDescToSet->Status|=ETH_DMATxDesc_LS|ETH_DMATxDesc_FS;//设置最后一个和第一个位段置位(1个描述符传输一帧)</div><div>        DMATxDescToSet->Status|=ETH_DMATxDesc_OWN;//设置Tx描述符的OWN位,buffer重归ETH DMA</div><div><span style="white-space:pre">        </span></div><div><span style="white-space:pre">        </span>if((ETH->DMASR&ETH_DMASR_TBUS)!=(u32)RESET)//当Tx Buffer不可用位(TBUS)被设置的时候,重置它.恢复传输</div><div><span style="white-space:pre">        </span>{ </div><div><span style="white-space:pre">                </span>ETH->DMASR=ETH_DMASR_TBUS;//重置ETH DMA TBUS位 </div><div><span style="white-space:pre">                </span>ETH->DMATPDR=0;//恢复DMA发送</div><div><span style="white-space:pre">        </span>} </div><div><span style="white-space:pre">        </span>//更新ETH DMA全局Tx描述符为下一个Tx描述符</div><div><span style="white-space:pre">        </span>//为下一次buffer发送设置下一个DMA Tx描述符 </div><div><span style="white-space:pre">        </span>DMATxDescToSet=(ETH_DMADESCTypeDef*)(DMATxDescToSet->Buffer2NextDescAddr);    </div><div><span style="white-space:pre">        </span>return ETH_SUCCESS;   </div><div>}</div></div>
复制代码


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

使用道具 举报

6

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2018-11-26
在线时间
21 小时
 楼主| 发表于 2020-2-13 14:56:27 | 显示全部楼层

RE: F4以太网驱动发送逻辑有问题?

格式乱了,我重新贴一下代码。

我在分析正点原子F4探索者的LWIP源码的时候,发现以太网底层驱动发送的数据的时候,发现没有检查DMA描述符是否是能够被CPU使用的,就拷贝数据到了描述符的缓冲区中,怎么看都感觉不是很合理(以下代码的红色部分)。但是在ETH_Tx_Packet函数中,一进函数的时候就检查了描述符是否是能够被CPU使用的。感觉有点先斩后奏的意思。还请大佬们指教,我自己的理解是,在拷贝数据到描述符的缓冲区之前,就应该先检查描述符是否能够被CPU访问,不是的话,直接返回错误就行,能够被访问的时候才去拷贝数据,设置长度和标志位等后续的操作。

static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
        u8 res;
        struct pbuf *q;
        int l = 0;
        u8 *buffer=(u8 *)ETH_GetCurrentTxBuffer();
        for(q=p;q!=NULL;q=q->next)
        {
                memcpy((u8_t*)&buffer[l], q->payload, q->len);
                l=l+q->len;
        }

        res=ETH_Tx_Packet(l);
        if(res==ETH_ERROR)return ERR_MEM;//返回错误状态
        return ERR_OK;
}  

u8 ETH_Tx_Packet(u16 FrameLength)
{   
        //检查当前描述符,是否属于ETHERNET DMA(设置的时候)/CPU(复位的时候)
        if((DMATxDescToSet->Status&ETH_DMATxDesc_OWN)!=(u32)RESET)
                return ETH_ERROR;//错误,OWN位被设置了

       
        DMATxDescToSet->ControlBufferSize=(FrameLength&ETH_DMATxDesc_TBS1);//设置帧长度,bits[12:0]
        DMATxDescToSet->Status|=ETH_DMATxDesc_LS|ETH_DMATxDesc_FS;//设置最后一个和第一个位段置位(1个描述符传输一帧)
  DMATxDescToSet->Status|=ETH_DMATxDesc_OWN;//设置Tx描述符的OWN位,buffer重归ETH DMA
       
        if((ETH->DMASR&ETH_DMASR_TBUS)!=(u32)RESET)//当Tx Buffer不可用位(TBUS)被设置的时候,重置它.恢复传输
        {
                ETH->DMASR=ETH_DMASR_TBUS;//重置ETH DMA TBUS位
                ETH->DMATPDR=0;//恢复DMA发送
        }
        //更新ETH DMA全局Tx描述符为下一个Tx描述符
        //为下一次buffer发送设置下一个DMA Tx描述符
        DMATxDescToSet=(ETH_DMADESCTypeDef*)(DMATxDescToSet->Buffer2NextDescAddr);   
        return ETH_SUCCESS;   
}
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-24 16:22

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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