📄 fec.c
字号:
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 );}voideth_input( struct netif *netif, struct pbuf *p ){ struct eth_hdr *eth_hdr = p->payload; LWIP_ASSERT( "eth_input: p != NULL ", p != NULL ); switch ( htons( eth_hdr->type ) ) { case ETHTYPE_IP: /* Pass to ARP layer. */ etharp_ip_input( netif, p ); /* Skip Ethernet header. */ pbuf_header( p, ( s16_t ) - sizeof( struct eth_hdr ) ); /* Pass to network layer. */ netif->input( p, netif ); break; case ETHTYPE_ARP: /* Pass to ARP layer. */ etharp_arp_input( netif, ( struct eth_addr * )netif->hwaddr, p ); break; default: pbuf_free( p ); break; }}voidmcf523xfec_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 );}voidmcf523xfec_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 );}voidmcf523xfec_get_mac( mcf523xfec_if_t * hw, struct eth_addr *mac ){ int i; static const struct eth_addr mac_default = { {0x00, 0xCF, 0x52, 0x35, 0x00, 0x01} }; ( void )hw; for( i = 0; i < ETH_ADDR_LEN; i++ ) { mac->addr[i] = mac_default.addr[i]; }}voidmcf523xfec_enable( mcf523xfec_if_t * fecif ){ ( void )fecif; int old_ipl = asm_set_ipl( 7 ); /* Configure I/O pins for the FEC. */ MCF_GPIO_PAR_FECI2C = ( MCF_GPIO_PAR_FECI2C_PAR_EMDC_FEC | MCF_GPIO_PAR_FECI2C_PAR_EMDIO_FEC ); /* Allow interrupts by setting IMR register */ MCF_FEC_EIMR = MCF_FEC_EIMR_RXF; /* Configure the interrupt controller. */ MCF_INTC0_ICR27 = ( MCF_INTC0_ICRn_IL( MCF_FEC_INT_LEVEL ) | MCF_INTC0_ICRn_IP( MCF_FEC_INT_PRIORITY ) ); MCF_INTC0_IMRL &= ~( MCF_INTC0_IMRL_INT_MASK27 | MCF_INTC0_IMRL_MASKALL ); /* Enable FEC */ MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN; /* Indicate that there have been empty receive buffers produced */ MCF_FEC_RDAR = 1; ( void )asm_set_ipl( old_ipl );}voidmcf523xfec_disable( mcf523xfec_if_t * fecif ){ ( void )fecif; int old_ipl = asm_set_ipl( 7 ); /* Set the Graceful Transmit Stop bit */ MCF_FEC_TCR = ( MCF_FEC_TCR | MCF_FEC_TCR_GTS ); /* Wait for the current transmission to complete */ while( !( MCF_FEC_EIR & MCF_FEC_EIR_GRA ) ); /* Clear the GRA event */ MCF_FEC_EIR = MCF_FEC_EIR_GRA; /* Disable the FEC */ MCF_FEC_ECR = 0; /* Disable all FEC interrupts by clearing the IMR register */ MCF_FEC_EIMR = 0; /* Unconfigure the interrupt controller. */ MCF_INTC0_ICR27 = MCF_INTC0_ICRn_IL( 0 ) | MCF_INTC0_ICRn_IP( 0 ); MCF_INTC0_IMRL |= MCF_INTC0_IMRL_INT_MASK27; /* Clear the GTS bit so frames can be tranmitted when restarted */ MCF_FEC_TCR = ( MCF_FEC_TCR & ~MCF_FEC_TCR_GTS ); /* Disable I/O pins used by the FEC. */ MCF_GPIO_PAR_FECI2C &= ~( MCF_GPIO_PAR_FECI2C_PAR_EMDC_FEC | MCF_GPIO_PAR_FECI2C_PAR_EMDIO_FEC ); ( void )asm_set_ipl( old_ipl );}err_tmcf523xfec_init( struct netif *netif ){ err_t res; mcf523xfec_if_t *fecif = mem_malloc( sizeof( mcf523xfec_if_t ) ); if( fecif != NULL ) { /* Global copy used in ISR. */ fecif_g = fecif; fecif->self = ( struct eth_addr * )&netif->hwaddr[0]; fecif->netif = netif; fecif->tx_sem = NULL; fecif->rx_sem = NULL; if( ( fecif->tx_sem = sys_sem_new( 1 ) ) == NULL ) { res = ERR_MEM; } else if( ( fecif->rx_sem = sys_sem_new( 0 ) ) == NULL ) { res = ERR_MEM; } else if( sys_thread_new( mcf523xfec_rx_task, fecif, TASK_PRIORITY ) == NULL ) { res = ERR_MEM; } else { netif->state = fecif; netif->name[0] = 'C'; netif->name[1] = 'F'; netif->hwaddr_len = ETH_ADDR_LEN; netif->mtu = MCF_FEC_MTU; netif->flags = NETIF_FLAG_BROADCAST; netif->output = mcf523xfec_output; netif->linkoutput = mcf523xfec_output_raw; nbuf_init( ); mcf523xfec_get_mac( fecif, fecif->self ); mcf523xfec_reset( fecif ); mcf523xfec_enable( fecif ); etharp_init( ); sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL ); res = ERR_OK; } if( res != ERR_OK ) { free( fecif ); if( fecif->tx_sem != NULL ) { mem_free( fecif->tx_sem ); } if( fecif->rx_sem != NULL ) { mem_free( fecif->rx_sem ); } } } else { res = ERR_MEM; } return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -