Other Parts Discussed in Thread: DP83848YB
Hello,
I'm using the EMAC module C0 receive channel 0 with RX interrupts enabled. When an interrupt is received it signals a receive RTOS task with a semaphore, then the RX0 interrupts are disabled. The receive task checks for the semaphore, then reads the owner bit to start processing the packet. When it finished it the RX0 interrupt has been re-enabled. Everything works fine, I print out the address of the current buffer descriptor and the RX header pointer. If multiple packets are received all of them are processed, then the task exits with enabling the interrupt. But I know for sure that some of the pockets are missing, not even an interrupt generated for these. In wireshark I can see the packet sent from my computer, but it does not appear on the receive side.
Do anyone experienced something similar whit the emac interface? Is there something that I am still missing that could cause this issue?
I have uploaded my partial code, maybe someone can spot out what I am missing.
Thanks!
#pragma INTERRUPT(emacRxInterrupt, IRQ) void emacRxInterrupt(void) { disableEmacInterrupts(); ///< According to Technical Reference Manual 32.2.17.3 Proper Interrupt Processing hdkif_t * const hdkif = &mHdkifData[0u]; // Disable RX0 interrupt EMACRxIntPulseDisable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32_t)EMAC_CHANNELNUMBER, (uint32_t)EMAC_CHANNELNUMBER); mEmacRxBdIntGenerated = (uint32_t)HWREG(hdkif->emac_base + EMAC_RXCP(EMAC_CHANNELNUMBER)); EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX); ///< Acknowledge RX interrupt mEmacRxIntCounter++; semaphore_give(&mEmacRxSemaphore); enableEmacInterrupts(); } void rx_task(void) { while (1) { if (isOk(semaphore_take(&mEmacRxSemaphore, mEmacTaskRxBlockTime))) { LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Start! Semaphore Received! Int count: %d, Int BD: %x", mEmacRxIntCounter, mEmacRxBdIntGenerated)); while ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_OWNER) != EMAC_BUF_DESC_OWNER ) { LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: SOP set! Current BD: %x", currentBufferDescriptor)); // Start processing the received packet only after SOP(Start Of Packet) received and we have the ownership if ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_SOP) == EMAC_BUF_DESC_SOP) { if ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_DSC_FLAG_ERROR_MASK) == 0) { // Check received packet size packetSize = BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & 0xffffu; // Invalidate cache, to not to interfere with new packets in memory _dcacheInvalidateRange_(BYTE_SWAP(currentBufferDescriptor->bufptr), BYTE_SWAP(currentBufferDescriptor->bufptr) + packetSize); LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Packet arrived, BD: %x, RXHP: %x size: %d\r\n", currentBufferDescriptor, HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)), packetSize)); if ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_EOP) != EMAC_BUF_DESC_EOP) { LWIP_DEBUGF(NETIF_DEBUG, ("EMACRX: NO EOP: %x, RXHP: %x\r\n", currentBufferDescriptor, HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)))); } if (packetSize > 0u && packetSize <= ETH_MAX_FRAME_SIZE) { pbuf_t *p; p = pbuf_alloc(PBUF_RAW, packetSize, PBUF_POOL); ///< We allocate a pbuf chain of pbufs from the pool. LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Packet processing!")); if (NN(p)) { memcpy(p->payload, (void *)(BYTE_SWAP(currentBufferDescriptor->bufptr)), packetSize); eth_hdr_t *ethhdr; ethhdr = p->payload; switch (htons(ethhdr->type)) { // IP or ARP packet? case ETHTYPE_ARP: case ETHTYPE_IP: // full packet send to tcpip_thread to process if (mLwipRuntimeData.netif.input(p, &mLwipRuntimeData.netif) != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ifx_netif_input: IP input error\n")); pbuf_free(p); p = NULL; } break; default: LWIP_DEBUGF(NETIF_DEBUG, ("ifx_netif_input: type unknown\n")); pbuf_free(p); p = NULL; break; } } else { LWIP_DEBUGF(NETIF_DEBUG, ("EMACRX: pbuf allocation error\n")); } } else { LWIP_DEBUGF(NETIF_IN_DEBUG, ("Too large: %d\n", packetSize)); } mEmacRxBdAcknowledged = (uint32_t)currentBufferDescriptor; HWREG(hdkif->emac_base + EMAC_RXCP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor; ///< To acknowledge BD LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Acknowledged BD[1]: %x", mEmacRxBdAcknowledged)); volatile emac_rx_bd_t *currentBufferDesListStart = currentBufferDescriptor; while((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_EOP) != EMAC_BUF_DESC_EOP) { currentBufferDescriptor->bufoff_len = BYTE_SWAP(ETH_MAX_FRAME_SIZE); currentBufferDescriptor->flags_pktlen = BYTE_SWAP(EMAC_BUF_DESC_OWNER); currentBufferDescriptor = (emac_rx_bd_t *)BYTE_SWAP((uint32_t)currentBufferDescriptor->next); mEmacRxBdAcknowledged = (uint32_t)currentBufferDescriptor; HWREG(hdkif->emac_base + EMAC_RXCP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor; ///< To acknowledge BD LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Acknowledged BD[2]: %x", mEmacRxBdAcknowledged)); } // free up the current BD currentBufferDescriptor->bufoff_len = BYTE_SWAP(ETH_MAX_FRAME_SIZE); currentBufferDescriptor->flags_pktlen = BYTE_SWAP(EMAC_BUF_DESC_OWNER); volatile emac_rx_bd_t *currentBufferDescTemp = (emac_rx_bd_t *)BYTE_SWAP((uint32_t)currentBufferDescriptor->next); currentBufferDescriptor->next = NULL; // update the linked list tailBufferDescriptor->next = (emac_rx_bd_t *)BYTE_SWAP((uint32_t)currentBufferDesListStart); // Check if we are at the end of queue if ((BYTE_SWAP(tailBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_EOQ) == EMAC_BUF_DESC_EOQ) { while (HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) != 0u) { task_sleep((sysTimeDuration_t)DURATION_MS(1)); } // Restart EMAC reception with updating the head pointer HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor; LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: RX restarted at BD: %x\r\n", currentBufferDescriptor)); } tailBufferDescriptor = currentBufferDescriptor; currentBufferDescriptor = currentBufferDescTemp; LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: End of packet!")); } else { LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Packet error!")); } } else { LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: BD no SOP found!")); break; } } // Re-enable RX0 interrupt EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32_t)EMAC_CHANNELNUMBER, (uint32_t)EMAC_CHANNELNUMBER); LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: End!")); } else { // We didn't receive semaphore inside the given blocking time, but the head pointer is on the next location -> IRQ lost if (HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) == 0u) { // Restart EMAC reception with updating the head pointer HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor; LWIP_DEBUGF(NETIF_DEBUG, ("EMACRX: IRQ lost RX restarted at BD: %x\r\n", currentBufferDescriptor)); } } } }