我正在尝试使用 lwIP Demo 4.0.0作为新固件的基础。 但是,在向其发送大约60个 UDP 数据包后,由于 CURR_BD->NEXT 中的 NULL 指针(CURR_BD 是 hdkif[0]->state->rxch->active_head),中断处理程序中的代码会更精确地在函数 hdkif_rx_inthandler 处停止。 尝试在函数循环中检查该指针可防止中断、但不会再发出中断。
我目前正在 将 CCS 11.1.0.00011与 TI 编译器 v20.2.7.LTS 搭配使用。 为方便参考、我将粘贴以下中断处理程序、并进行了一些修改以尝试隔离问题:
/**
* Handler for Receive interrupt. Packet processing is done in this
* interrupt handler itself.
*
* @param netif the lwip network interface structure for this ethernetif
* @return none
*/
uint32 last_curr_bd, last_next_bd;
uint32 no_prob_last = 1;
void
hdkif_rx_inthandler(struct netif *netif) {
struct hdkif *hdkif;
struct rxch *rxch;
volatile struct emac_rx_bdp *curr_bd, *processed_bd, *curr_tail, *last_bd;
volatile struct pbuf *pbuf, *q, *new_pbuf;
uint32 ex_len = 0, len_to_alloc = 0;
uint16 tot_len;
hdkif = netif->state;
rxch = &(hdkif->rxch);
/* Get the bd which contains the earliest filled data */
curr_bd = rxch->active_head;
last_bd = rxch->active_tail;
/**
* Process the descriptors as long as data is available
* when the DMA is receiving data, SOP flag will be set
*/
while((hdkif_swizzle_data(curr_bd->flags_pktlen) & EMAC_BUF_DESC_SOP)
&& (curr_bd != NULL)) {
ex_len = 0;
len_to_alloc = 0;
/* Start processing once the packet is loaded */
if((hdkif_swizzle_data(curr_bd->flags_pktlen) & EMAC_BUF_DESC_OWNER)
!= EMAC_BUF_DESC_OWNER) {
if(rxch->free_head == NULL) {
/* this bd chain will be freed after processing */
rxch->free_head = curr_bd;
}
/* Get the total length of the packet. curr_bd points to the start
* of the packet.
*/
tot_len = hdkif_swizzle_data(curr_bd->flags_pktlen) & 0xFFFF;
/* Get the start of the pbuf queue */
q = curr_bd->pbuf;
do {
/* Get the pbuf pointer which is associated with the current bd */
pbuf = curr_bd->pbuf;
/* If the earlier pbuf ended, update the chain */
if(pbuf->next == NULL) {
pbuf->next = (struct pbuf*)hdkif_swizzle_rxp(curr_bd->next)->pbuf;
}
len_to_alloc += pbuf->len;
/* Update the len and tot_len fields for the pbuf in the chain*/
pbuf->len = hdkif_swizzle_data(curr_bd->bufoff_len) & 0xFFFF;
pbuf->tot_len = tot_len - ex_len ;
processed_bd = curr_bd;
ex_len += pbuf->len;
/* if(hdkif_swizzle_rxp(curr_bd->next) == NULL){ */
/* break; */
/* }else{ */
curr_bd = hdkif_swizzle_rxp(curr_bd->next);
/* } */
} while((hdkif_swizzle_data(processed_bd->flags_pktlen) & EMAC_BUF_DESC_EOP)
!= EMAC_BUF_DESC_EOP);
/**
* Close the chain for this pbuf. A full packet is received in
* this pbuf chain. Now this pbuf can be given to upper layers for
* processing. The start of the pbuf chain is now 'q'.
*/
pbuf->next = NULL;
/* Adjust the link statistics */
LINK_STATS_INC(link.recv);
/* Process the packet */
if(ethernet_input((struct pbuf *)q, netif) != ERR_OK) {
/* Adjust the link statistics */
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
}
/* Acknowledge that this packet is processed */
EMACRxCPWrite(hdkif->emac_base, 0, (unsigned int)processed_bd);
rxch->active_head = curr_bd;
/**
* The earlier pbuf chain is freed from the upper layer. So, we need to
* allocate a new pbuf chain and update the descriptors with the pbuf info.
* To support chaining, the total length freed by the upper layer is tracked.
* Care should be taken even if the allocation fails.
*/
/**
* now len_to_alloc will contain the length of the pbuf which was freed
* from the upper layer
*/
rxch->freed_pbuf_len += len_to_alloc;
new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
/* Write the descriptors with the pbuf info till either of them expires */
if(new_pbuf != NULL) {
curr_bd = rxch->free_head;
for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {
curr_bd->bufptr = hdkif_swizzle_data((uint32)(q->payload));
/* no support for buf_offset. RXBUFFEROFFEST register is 0 */
curr_bd->bufoff_len = hdkif_swizzle_data((q->len) & 0xFFFF);
curr_bd->flags_pktlen = hdkif_swizzle_data(EMAC_BUF_DESC_OWNER);
rxch->freed_pbuf_len -= q->len;
/* Save the pbuf */
curr_bd->pbuf = q;
last_bd = curr_bd;
curr_bd = hdkif_swizzle_rxp(curr_bd->next);
}
/**
* At this point either pbuf expired or no rxbd to allocate. If
* there are no, enough rx bds to allocate all pbufs in the chain,
* free the rest of the pbuf
*/
if(q != NULL) {
pbuf_free((struct pbuf *)q);
}
curr_tail = rxch->active_tail;
last_bd->next = NULL;
curr_tail->next = hdkif_swizzle_rxp(rxch->free_head);
/**
* Check if the reception has ended. If the EOQ flag is set, the NULL
* Pointer is taken by the DMA engine. So we need to write the RX HDP
* with the next descriptor.
*/
if(hdkif_swizzle_data(curr_tail->flags_pktlen) & EMAC_BUF_DESC_EOQ) {
EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32)(rxch->free_head), 0);
}
rxch->free_head = curr_bd;
rxch->active_tail = last_bd;
}
}
curr_bd = rxch->active_head;
}
EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
}