void mcf523xfec_rx_irq( void ) { static portBASE_TYPE xNeedSwitch = pdFALSE; /* Workaround GCC if frame pointers are enabled. This is an ISR and * we must not modify the stack before portENTER_SWITCHING_ISR( ) * has been called. */ #if _GCC_USES_FP == 1 asm volatile ( "unlk %fp\n\t" ); #endif /* This ISR can cause a context switch, so the first statement must be * a call to the portENTER_SWITCHING_ISR() macro. */ portENTER_SWITCHING_ISR( ); /* Set Debug PIN to high to measure RX latency. */ FEC_DEBUG_RX_TIMING( 1 ); /* Clear FEC RX Event from the Event Register (by writing 1) */ if( MCF_FEC_EIR & ( MCF_FEC_EIR_RXB | MCF_FEC_EIR_RXF ) ) { /* Clear interrupt from EIR register immediately */ MCF_FEC_EIR = ( MCF_FEC_EIR_RXB | MCF_FEC_EIR_RXF ); xNeedSwitch = xSemaphoreGiveFromISR( fecif_g->rx_sem, pdFALSE ); } portEXIT_SWITCHING_ISR( xNeedSwitch ); }
void mcf523xfec_reset( mcf523xfec_if_t * fecif ) { extern void ( *__RAMVEC[] ) ( ); int old_ipl = asm_set_ipl( 7 ); /* Reset the FEC - equivalent to a hard reset */ MCF_FEC_ECR = MCF_FEC_ECR_RESET; /* Wait for the reset sequence to complete */ while( MCF_FEC_ECR & MCF_FEC_ECR_RESET ); /* Disable all FEC interrupts by clearing the EIMR register */ MCF_FEC_EIMR = 0; /* Clear any interrupts by setting all bits in the EIR register */ MCF_FEC_EIR = 0xFFFFFFFFUL; /* Configure Interrupt vectors. */ __RAMVEC[MCF_FEC_VEC_RXF] = mcf523xfec_rx_irq; /* Set the source address for the controller */ MCF_FEC_PALR = ( fecif->self->addr[0] << 24U ) | ( fecif->self->addr[1] << 16U ) | ( fecif->self->addr[2] << 8U ) | ( fecif->self->addr[3] << 0U ); MCF_FEC_PAUR = ( fecif->self->addr[4] << 24U ) | ( fecif->self->addr[5] << 16U ); /* Initialize the hash table registers */ MCF_FEC_IAUR = 0; MCF_FEC_IALR = 0; /* Set Receive Buffer Size */ #if RX_BUFFER_SIZE != 2048 #error "RX_BUFFER_SIZE must be set to 2048 for safe FEC operation." #endif MCF_FEC_EMRBR = RX_BUFFER_SIZE - 1; /* Point to the start of the circular Rx buffer descriptor queue */ MCF_FEC_ERDSR = nbuf_get_start( NBUF_RX ); /* Point to the start of the circular Tx buffer descriptor queue */ MCF_FEC_ETDSR = nbuf_get_start( NBUF_TX ); /* Set the tranceiver interface to MII mode */ MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL( MCF_FEC_MTU ) | MCF_FEC_RCR_MII_MODE; /* Set MII Speed Control Register for 2.5Mhz */ MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED( FSYS_2 / ( 2UL * 2500000UL ) ); /* Only operate in half-duplex, no heart beat control */ MCF_FEC_TCR = 0; /* Enable Debug support */ FEC_DEBUG_INIT; FEC_DEBUG_RX_TIMING( 0 ); FEC_DEBUG_TX_TIMING( 0 ); ( void )asm_set_ipl( old_ipl ); }
/** * Reset MAC controller * * @param MAC controller descriptor * @return none */ void MAC_Reset( mcf5xxxfec_if_t * fecif ) { portENTER_CRITICAL(); /* Set the source address for the controller */ FEC_ResetProcessing(fecif->self->addr); /* Enable Debug support */ FEC_DEBUG_INIT; FEC_DEBUG_RX_TIMING( 0 ); FEC_DEBUG_TX_TIMING( 0 ); portEXIT_CRITICAL(); }
/** * FEC ISR * * @param none * @return none */ void MAC_ISR(void) { portBASE_TYPE xHighPriorityTaskWoken; xHighPriorityTaskWoken = pdFALSE; /* Set Debug PIN to high to measure RX latency. */ FEC_DEBUG_RX_TIMING( 1 ); /* Clear FEC RX Event from the Event Register (by writing 1) */ if( FEC_GetAvailableReadyRX() ) { /* ACK interrupt flag */ FEC_ackRX(); xSemaphoreGiveFromISR( fecif_g->rx_sem, &xHighPriorityTaskWoken ); } portEND_SWITCHING_ISR( xHighPriorityTaskWoken ); }
void mcf523xfec_rx_task( void *arg ) { mcf523xfec_if_t *fecif = arg; struct pbuf *p, *q; nbuf_t *pNBuf; uint8 *pPayLoad; do { sys_sem_wait( fecif->rx_sem ); while( nbuf_rx_next_ready( ) ) { pNBuf = nbuf_rx_allocate( ); if( pNBuf != NULL ) { LWIP_ASSERT( "mcf523xfec_rx_task: pNBuf->status & RX_BD_L ", pNBuf->status & RX_BD_L ); /* This flags indicate that the frame has been damaged. In * this case we must update the link stats if enabled and * remove the frame from the FEC. */ if( pNBuf->status & ( RX_BD_LG | RX_BD_NO | RX_BD_CR | RX_BD_OV ) ) { #ifdef LINK_STATS lwip_stats.link.drop++; if( pNBuf->status & RX_BD_LG ) { lwip_stats.link.lenerr++; } else if( pNBuf->status & ( RX_BD_NO | RX_BD_OV ) ) { lwip_stats.link.err++; } else { lwip_stats.link.chkerr++; } #endif } else { /* The frame must no be valid. Perform some checks to see if the FEC * driver is working correctly. */ LWIP_ASSERT( "mcf523xfec_rx_task: pNBuf->length != 0", pNBuf->length != 0 ); p = pbuf_alloc( PBUF_RAW, pNBuf->length, PBUF_POOL ); if( p != NULL ) { #if ETH_PAD_SIZE pbuf_header( p, -ETH_PAD_SIZE ); #endif pPayLoad = pNBuf->data; for( q = p; q != NULL; q = q->next ) { memcpy( q->payload, pPayLoad, q->len ); pPayLoad += q->len; } #if ETH_PAD_SIZE pbuf_header( p, ETH_PAD_SIZE ); #endif /* Ethernet frame received. Handling it is not device * dependent and therefore done in another function. */ eth_input( fecif->netif, p ); } } nbuf_rx_release( pNBuf ); /* Tell the HW that there are new free RX buffers. */ MCF_FEC_RDAR = 1; } else { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif } } /* Set RX Debug PIN to low since handling of next frame is possible. */ FEC_DEBUG_RX_TIMING( 0 ); } while( 1 ); }
/** * Ethernet rx task being called periodically by FreeRTOS * * @param MAC interface descriptor * @return none */ void MAC_Rx_Task(void *arg ) { mcf5xxxfec_if_t *fecif; struct pbuf *p, *q; nbuf_t *pNBuf; uint8 *pPayLoad; fecif = (mcf5xxxfec_if_t *)arg; do { sys_sem_wait( fecif->rx_sem ); while( NBUF_ReadyRX( ) ) { pNBuf = NBUF_AllocRX( ); if( pNBuf != NULL ) { /*FSL: removed to avoid get stuck if a BABR happens*/ //LWIP_ASSERT( "MAC_Rx_Task: pNBuf->status & RX_BD_L ", // pNBuf->status & RX_BD_L ); /* This flags indicate that the frame has been damaged. In * this case we must update the link stats if enabled and * remove the frame from the FEC. */ //if ( pNBuf->status & RX_ERROR_ALL_FLAGS ) // FIXME: turn off CRC checking for now... it is throwing error even when I manually check the received packet // as byte-for-byte correct if ( pNBuf->status & (RX_ERROR_ALL_FLAGS & ~RX_ERROR_CHKSM_FLAG) ) { #if LINK_STATS lwip_stats.link.drop++; if ( pNBuf->status & RX_ERROR_LENGTH_FLAG ) { lwip_stats.link.lenerr++; } else if ( pNBuf->status & RX_ERROR_CHKSM_FLAG ) { lwip_stats.link.chkerr++; } else { lwip_stats.link.err++; } #endif } else { /* The frame must now be valid. Perform some checks to see if the FEC * driver is working correctly. */ LWIP_ASSERT( "MAC_Rx_Task: pNBuf->length != 0", pNBuf->length != 0 ); p = pbuf_alloc( PBUF_RAW, pNBuf->length, PBUF_POOL ); if( p != NULL ) { #if ETH_PAD_SIZE pbuf_header( p, -ETH_PAD_SIZE ); #endif pPayLoad = pNBuf->data; for( q = p; q != NULL; q = q->next ) { memcpy( q->payload, pPayLoad, q->len ); pPayLoad += q->len; } #if ETH_PAD_SIZE pbuf_header( p, ETH_PAD_SIZE ); #endif /* Ethernet frame received. Handling it is not device * dependent and therefore done in another function. */ eth_input( fecif->netif, p ); } } /*release the buffer under any circumstance*/ /*now we can release buffer*/ NBUF_ReleaseRX( pNBuf ); /* Tell the HW that there are new free RX buffers. */ FEC_ReadyRX(); } else { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif } } /* Set RX Debug PIN to low since handling of next frame is possible. */ FEC_DEBUG_RX_TIMING( 0 ); } while( 1 ); }