lwip用iperf测试速率的时候会卡死,无法接收发送数据了,也不能识别网线插入了.
我使用了lwip好几个版本了,都是一样的结果。
主控芯片是用AT32F407RG 网络芯片IP101GR。
我DEBUG发现程序会卡在接收的pbuf_alloc这个接口上,不知道是什么原因造成的。
看看哪位大神能帮忙指导一下
以下是以太网驱动的收发接口
rt_err_t rt_at32_emac_tx(rt_device_t dev, struct pbuf p)
{
// struct pbuf q;
// rt_uint32_t offset;
if(p == RT_NULL){
LOG_E("rt_at32_emac_tx:p == RT_NULL");
return ERR_ARG;
}
while ((dma_tx_desc_to_set->status & EMAC_DMATXDESC_OWN) != RESET)
{
rt_err_t result;
rt_uint32_t level;
level = rt_hw_interrupt_disable();
tx_is_waiting = RT_TRUE;
rt_hw_interrupt_enable(level);
/ it's own bit set, wait it /
result = rt_sem_take(&tx_wait, RT_WAITING_FOREVER);
if (result == RT_EOK) break;
if (result == -RT_ERROR) return -RT_ERROR;
}
if(p->tot_len > EMAC_MAX_PACKET_LENGTH){
LOG_E("rt_at32_emac_tx:p->tot_len > EMAC_MAX_PACKET_LENGTH");
return ERR_ARG;
}
pbuf_copy_partial(p, (uint8_t)(dma_tx_desc_to_set->buf1addr), EMAC_MAX_PACKET_LENGTH, 0);
// offset = 0;
// for (q = p; q != NULL; q = q->next)
// {
// uint8_t buffer;
//
// / copy the frame to be sent into memory pointed by the current ethernet dma tx descriptor /
// buffer = (uint8_t)((dma_tx_desc_to_set->buf1addr) + offset);
// SMEMCPY(buffer, q->payload, q->len);
// offset += q->len;
// }
#ifdef EMAC_TX_DUMP
dump_hex(p->payload, p->tot_len);
#endif
/ prepare transmit descriptors to give to dma /
LOG_D("transmit frame length :%d", p->tot_len);
/ setting the frame length: bits[12:0] /
dma_tx_desc_to_set->controlsize = (p->tot_len & EMAC_DMATXDESC_TBS1);
/ Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) /
dma_tx_desc_to_set->status |= EMAC_DMATXDESC_LS | EMAC_DMATXDESC_FS;
/ enable tx completion interrupt /
dma_tx_desc_to_set->status |= EMAC_DMATXDESC_IC;
/ set own bit of the tx descriptor status: gives the buffer back to ethernet dma /
dma_tx_desc_to_set->status |= EMAC_DMATXDESC_OWN;
/ When Tx Buffer unavailable flag is set: clear it and resume transmission /
if(emac_dma_flag_get(EMAC_DMA_TBU_FLAG) != RESET)
{
emac_dma_flag_clear(EMAC_DMA_TBU_FLAG);
emac_dma_poll_demand_set(EMAC_DMA_TRANSMIT, 0);
}
/ selects the next dma tx descriptor list for next buffer to send /
dma_tx_desc_to_set = (emac_dma_desc_type) (dma_tx_desc_to_set->buf2nextdescaddr);
return ERR_OK;
}
/**
[url=home.php?mod=space&uid=2666770]@Brief[/url] receive data
*/
struct pbuf *rt_at32_emac_rx(rt_device_t dev)
{
struct pbuf p = NULL;
// struct pbuf q = NULL;
// rt_uint32_t offset = 0;
uint16_t len = 0;
// uint8_t buffer;
/ get received frame /
len = emac_received_packet_size_get();
if(len > 0)
{
LOG_D("receive frame len : %d", len);
/ we allocate a pbuf chain of pbufs from the lwip buffer pool /
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if(p != NULL)
{
pbuf_take(p, (uint8_t )dma_rx_desc_to_get->buf1addr, len);
// for (q = p; q != RT_NULL; q= q->next)
// {
// / get rx buffer /
// buffer = (uint8_t )(dma_rx_desc_to_get->buf1addr);
//#ifdef EMAC_RX_DUMP
// dump_hex(buffer, len);
//#endif
// / copy the received frame into buffer from memory pointed by the current ethernet dma rx descriptor /
// SMEMCPY(q->payload, (buffer + offset), q->len);
// offset += q->len;
// }
}
}
else
{
return p;
}
/ release descriptors to dma /
dma_rx_desc_to_get->status |= EMAC_DMARXDESC_OWN;
/ when rx buffer unavailable flag is set: clear it and resume reception /
if(emac_dma_flag_get(EMAC_DMA_RBU_FLAG) != RESET)
{
/ clear rbu ethernet dma flag /
emac_dma_flag_clear(EMAC_DMA_RBU_FLAG);
/ resume dma reception /
emac_dma_poll_demand_set(EMAC_DMA_RECEIVE, 0);
}
/ update the ethernet dma global rx descriptor with next rx decriptor /
/ chained mode /
if((dma_rx_desc_to_get->controlsize & EMAC_DMARXDESC_RCH) != RESET)
{
/ selects the next dma rx descriptor list for next buffer to read /
dma_rx_desc_to_get = (emac_dma_desc_type) (dma_rx_desc_to_get->buf2nextdescaddr);
}
/ ring mode /
else
{
if((dma_rx_desc_to_get->controlsize & EMAC_DMARXDESC_RER) != RESET)
{
/ selects the first dma rx descriptor for next buffer to read: last rx descriptor was used /
dma_rx_desc_to_get = (emac_dma_desc_type) (EMAC_DMA->rdladdr);
}
else
{
/ selects the next dma rx descriptor list for next buffer to read /
dma_rx_desc_to_get = (emac_dma_desc_type) ((uint32_t)dma_rx_desc_to_get + 0x10 + ((EMAC_DMA->bm & 0x0000007C) >> 2));
}
}
return p;
}
rt_err_t rt_at32_emac_tx(rt_device_t dev, struct pbuf p)
{
// struct pbuf q;
// rt_uint32_t offset;
if(p == RT_NULL){
LOG_E("rt_at32_emac_tx:p == RT_NULL");
return ERR_ARG;
}
while ((dma_tx_desc_to_set->status & EMAC_DMATXDESC_OWN) != RESET)
{
rt_err_t result;
rt_uint32_t level;
level = rt_hw_interrupt_disable();
tx_is_waiting = RT_TRUE;
rt_hw_interrupt_enable(level);
/ it's own bit set, wait it /
result = rt_sem_take(&tx_wait, RT_WAITING_FOREVER);
if (result == RT_EOK) break;
if (result == -RT_ERROR) return -RT_ERROR;
}
if(p->tot_len > EMAC_MAX_PACKET_LENGTH){
LOG_E("rt_at32_emac_tx:p->tot_len > EMAC_MAX_PACKET_LENGTH");
return ERR_ARG;
}
pbuf_copy_partial(p, (uint8_t)(dma_tx_desc_to_set->buf1addr), EMAC_MAX_PACKET_LENGTH, 0);
// offset = 0;
// for (q = p; q != NULL; q = q->next)
// {
// uint8_t buffer;
//
// / copy the frame to be sent into memory pointed by the current ethernet dma tx descriptor /
// buffer = (uint8_t)((dma_tx_desc_to_set->buf1addr) + offset);
// SMEMCPY(buffer, q->payload, q->len);
// offset += q->len;
// }
#ifdef EMAC_TX_DUMP
dump_hex(p->payload, p->tot_len);
#endif
/ prepare transmit descriptors to give to dma /
LOG_D("transmit frame length :%d", p->tot_len);
/ setting the frame length: bits[12:0] /
dma_tx_desc_to_set->controlsize = (p->tot_len & EMAC_DMATXDESC_TBS1);
/ Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) /
dma_tx_desc_to_set->status |= EMAC_DMATXDESC_LS | EMAC_DMATXDESC_FS;
/ enable tx completion interrupt /
dma_tx_desc_to_set->status |= EMAC_DMATXDESC_IC;
/ set own bit of the tx descriptor status: gives the buffer back to ethernet dma /
dma_tx_desc_to_set->status |= EMAC_DMATXDESC_OWN;
/ When Tx Buffer unavailable flag is set: clear it and resume transmission /
if(emac_dma_flag_get(EMAC_DMA_TBU_FLAG) != RESET)
{
emac_dma_flag_clear(EMAC_DMA_TBU_FLAG);
emac_dma_poll_demand_set(EMAC_DMA_TRANSMIT, 0);
}
/ selects the next dma tx descriptor list for next buffer to send /
dma_tx_desc_to_set = (emac_dma_desc_type) (dma_tx_desc_to_set->buf2nextdescaddr);
return ERR_OK;
}
/
@brief receive data
*/
struct pbuf *rt_at32_emac_rx(rt_device_t dev)
{
struct pbuf *p = NULL;
// struct pbuf *q = NULL;
// rt_uint32_t offset = 0;
uint16_t len = 0;
// uint8_t buffer;
/ get received frame /
len = emac_received_packet_size_get();
if(len > 0)
{
LOG_D("receive frame len : %d", len);
/ we allocate a pbuf chain of pbufs from the lwip buffer pool /
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if(p != NULL)
{
pbuf_take(p, (uint8_t )dma_rx_desc_to_get->buf1addr, len);
// for (q = p; q != RT_NULL; q= q->next)
// {
// / get rx buffer /
// buffer = (uint8_t )(dma_rx_desc_to_get->buf1addr);
//#ifdef EMAC_RX_DUMP
// dump_hex(buffer, len);
//#endif
// / copy the received frame into buffer from memory pointed by the current ethernet dma rx descriptor /
// SMEMCPY(q->payload, (buffer + offset), q->len);
// offset += q->len;
// }
}
}
else
{
return p;
}
/ release descriptors to dma /
dma_rx_desc_to_get->status |= EMAC_DMARXDESC_OWN;
/ when rx buffer unavailable flag is set: clear it and resume reception /
if(emac_dma_flag_get(EMAC_DMA_RBU_FLAG) != RESET)
{
/ clear rbu ethernet dma flag /
emac_dma_flag_clear(EMAC_DMA_RBU_FLAG);
/ resume dma reception /
emac_dma_poll_demand_set(EMAC_DMA_RECEIVE, 0);
}
/ update the ethernet dma global rx descriptor with next rx decriptor /
/ chained mode /
if((dma_rx_desc_to_get->controlsize & EMAC_DMARXDESC_RCH) != RESET)
{
/ selects the next dma rx descriptor list for next buffer to read /
dma_rx_desc_to_get = (emac_dma_desc_type) (dma_rx_desc_to_get->buf2nextdescaddr);
}
/ ring mode /
else
{
if((dma_rx_desc_to_get->controlsize & EMAC_DMARXDESC_RER) != RESET)
{
/ selects the first dma rx descriptor for next buffer to read: last rx descriptor was used /
dma_rx_desc_to_get = (emac_dma_desc_type) (EMAC_DMA->rdladdr);
}
else
{
/ selects the next dma rx descriptor list for next buffer to read /
dma_rx_desc_to_get = (emac_dma_desc_type) ((uint32_t)dma_rx_desc_to_get + 0x10 + ((EMAC_DMA->bm & 0x0000007C) >> 2));
}
}
return p;
}