Esempio n. 1
0
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 );
}
Esempio n. 2
0
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 );
}
Esempio n. 3
0
/**
 * 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();
    

}
Esempio n. 4
0
/**
 * 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 );	
}
Esempio n. 5
0
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 );
}
Esempio n. 6
0
/**
 * 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 );
}