📄 5272fec.c
字号:
{
mcf5272->txbd_a[i].flags = (u16_t) (MCF5272_FEC_TX_BD_R |
(mcf5272->txbd_a[i].flags & MCF5272_FEC_TX_BD_W) |
((i == tx_insert_eof) ? (MCF5272_FEC_TX_BD_L | MCF5272_FEC_TX_BD_TC) : 0));
if (i != tx_insert_sof)
DEC_TX_BD_INDEX(i);
else
break;
} while (1);
INC_TX_BD_INDEX(tx_insert_eof);
mcf5272->tx_insert = tx_insert_eof;
#ifdef LINK_STATS
lwip_stats.link.xmit++;
#endif
/* Indicate that there has been a transmit buffer produced */
MCF5272_WR_FEC_TDAR(imm,1);
sys_arch_unprotect(old_level);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
eth_input(struct pbuf *p, struct netif *netif)
{
/* Ethernet protocol layer */
struct eth_hdr *ethhdr;
mcf5272if_t *mcf5272 = netif->state;
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
etharp_ip_input(netif, p);
pbuf_header(p, -14);
netif->input(p, netif);
break;
case ETHTYPE_ARP:
etharp_arp_input(netif, mcf5272->ethaddr, p);
break;
default:
pbuf_free(p);
break;
}
}
/*-----------------------------------------------------------------------------------*/
static void
arp_timer(void *arg)
{
etharp_tmr();
sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*
* Function called by receive LISR to disable fec rx interrupt
*-----------------------------------------------------------------------------------*/
static void
mcf5272_dis_rx_int(void)
{
mcf5272if_t *mcf5272 = mcf5272if;
MCF5272_IMM *imm = mcf5272->imm;
u32_t value;
value = MCF5272_RD_FEC_IMR(imm);
/* Clear rx interrupt bit */
MCF5272_WR_FEC_IMR(imm, (value & ~MCF5272_FEC_IMR_RXFEN));
return;
}
/*-----------------------------------------------------------------------------------*/
static void
mcf5272fec_rx(void)
{
/* This is the receive ISR. It is written to be a high-level ISR. */
u32_t old_level;
mcf5272if_t *mcf5272 = mcf5272if;
MCF5272_IMM *imm = mcf5272->imm;
u32_t value;
u16_t flags;
unsigned int rx_remove_sof;
unsigned int rx_remove_eof;
struct pbuf *p;
rx_remove_sof = rx_remove_eof = mcf5272->rx_remove;
/* Loop, looking for filled buffers at eof */
while ((((flags = mcf5272->rxbd_a[rx_remove_eof].flags) & MCF5272_FEC_RX_BD_E) == 0) &&
(mcf5272->rx_pbuf_a[rx_remove_eof] != 0))
{
/* See if this is last buffer in frame */
if ((flags & MCF5272_FEC_RX_BD_L) != 0)
{
/* This frame is ready to go. Start at first descriptor in frame. */
p = 0;
do
{
/* Adjust pbuf length if this is last buffer in frame */
if (rx_remove_sof == rx_remove_eof)
{
mcf5272->rx_pbuf_a[rx_remove_sof]->tot_len =
mcf5272->rx_pbuf_a[rx_remove_sof]->len = (u16_t)
(mcf5272->rxbd_a[rx_remove_sof].data_len - (p ? p->tot_len : 0));
}
else
mcf5272->rx_pbuf_a[rx_remove_sof]->len =
mcf5272->rx_pbuf_a[rx_remove_sof]->tot_len = mcf5272->rxbd_a[rx_remove_sof].data_len;
/* Chain pbuf */
if (p == 0)
{
p = mcf5272->rx_pbuf_a[rx_remove_sof]; // First in chain
p->tot_len = p->len; // Important since len might have changed
} else {
pbuf_chain(p, mcf5272->rx_pbuf_a[rx_remove_sof]);
pbuf_free(mcf5272->rx_pbuf_a[rx_remove_sof]);
}
/* Clear pointer to mark descriptor as free */
mcf5272->rx_pbuf_a[rx_remove_sof] = 0;
mcf5272->rxbd_a[rx_remove_sof].p_buf = 0;
if (rx_remove_sof != rx_remove_eof)
INC_RX_BD_INDEX(rx_remove_sof);
else
break;
} while (1);
INC_RX_BD_INDEX(rx_remove_sof);
/* Check error status of frame */
if (flags & (MCF5272_FEC_RX_BD_LG |
MCF5272_FEC_RX_BD_NO |
MCF5272_FEC_RX_BD_CR |
MCF5272_FEC_RX_BD_OV))
{
#ifdef LINK_STATS
lwip_stats.link.drop++;
if (flags & MCF5272_FEC_RX_BD_LG)
lwip_stats.link.lenerr++; //Jumbo gram
else
if (flags & (MCF5272_FEC_RX_BD_NO | MCF5272_FEC_RX_BD_OV))
lwip_stats.link.err++;
else
if (flags & MCF5272_FEC_RX_BD_CR)
lwip_stats.link.chkerr++; // CRC errors
#endif
/* Drop errored frame */
pbuf_free(p);
} else {
/* Good frame. increment stat */
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif
eth_input(p, mcf5272->netif);
}
}
INC_RX_BD_INDEX(rx_remove_eof);
}
mcf5272->rx_remove = rx_remove_sof;
/* clear interrupt status for rx interrupt */
old_level = sys_arch_protect();
MCF5272_WR_FEC_EIR(imm, MCF5272_FEC_EIR_RXF);
value = MCF5272_RD_FEC_IMR(imm);
/* Set rx interrupt bit again */
MCF5272_WR_FEC_IMR(imm, (value | MCF5272_FEC_IMR_RXFEN));
/* Now we can re-enable higher priority interrupts again */
sys_arch_unprotect(old_level);
/* Fill up empty descriptor rings */
fill_rx_ring(mcf5272);
/* Tell fec that we have filled up her ring */
MCF5272_WR_FEC_RDAR(imm, 1);
return;
}
/*-----------------------------------------------------------------------------------*/
static void
low_level_init(struct netif *netif)
{
mcf5272if_t *mcf5272;
MCF5272_IMM *imm;
VOID (*old_lisr)(INT); /* old LISR */
u32_t value;
u32_t old_level;
struct pbuf *p;
int i;
mcf5272 = netif->state;
imm = mcf5272->imm;
/* Initialize our ethernet address */
sys_get_eth_addr(mcf5272->ethaddr);
/* First disable fec */
disable_fec(mcf5272);
/* Plug appropriate low level interrupt vectors */
sys_setvect(MCF5272_VECTOR_ERx, mcf5272fec_rx, mcf5272_dis_rx_int);
sys_setvect(MCF5272_VECTOR_ETx, mcf5272fec_tx_hisr, mcf5272_dis_tx_int);
//sys_setvect(MCF5272_VECTOR_ENTC, mcf5272fec_ntc);
/* Set the I_MASK register to enable only rx & tx frame interrupts */
MCF5272_WR_FEC_IMR(imm, MCF5272_FEC_IMR_TXFEN | MCF5272_FEC_IMR_RXFEN);
/* Clear I_EVENT register */
MCF5272_WR_FEC_EIR(imm,0xFFFFFFFF);
/* Set up the appropriate interrupt levels */
/* Disable interrupts, since this is a read/modify/write operation */
old_level = sys_arch_protect();
value = MCF5272_RD_SIM_ICR3(imm);
MCF5272_WR_SIM_ICR3(imm, value | MCF5272_SIM_ICR_ERX_IL(FEC_LEVEL) |
MCF5272_SIM_ICR_ETX_IL(FEC_LEVEL));
sys_arch_unprotect(old_level);
/* Set the source address for the controller */
MCF5272_WR_FEC_MALR(imm,0
| (mcf5272->ethaddr->addr[0] <<24)
| (mcf5272->ethaddr->addr[1] <<16)
| (mcf5272->ethaddr->addr[2] <<8)
| (mcf5272->ethaddr->addr[3] <<0));
MCF5272_WR_FEC_MAUR(imm,0
| (mcf5272->ethaddr->addr[4] <<24)
| (mcf5272->ethaddr->addr[5] <<16));
/* Initialize the hash table registers */
/* We are not supporting multicast addresses */
MCF5272_WR_FEC_HTUR(imm,0);
MCF5272_WR_FEC_HTLR(imm,0);
/* Set Receive Buffer Size. We subtract 16 because the start of the receive
* buffer MUST be divisible by 16, so depending on where the payload really
* starts in the pbuf, we might be increasing the start point by up to 15 bytes.
* See the alignment code in fill_rx_ring() */
/* There might be an offset to the payload address and we should subtract
* that offset */
p = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
i = 0;
if (p)
{
struct pbuf *q = p;
while ((q = q->next) != 0)
i += q->len;
mcf5272->rx_buf_len = PBUF_POOL_BUFSIZE-16-i;
pbuf_free(p);
}
MCF5272_WR_FEC_EMRBR(imm, (u16_t) mcf5272->rx_buf_len);
/* Point to the start of the circular Rx buffer descriptor queue */
MCF5272_WR_FEC_ERDSR(imm, ((u32_t) &mcf5272->rxbd_a[0]));
/* Point to the start of the circular Tx buffer descriptor queue */
MCF5272_WR_FEC_ETDSR(imm, ((u32_t) &mcf5272->txbd_a[0]));
/* Set the tranceiver interface to MII mode */
MCF5272_WR_FEC_RCR(imm, 0
| MCF5272_FEC_RCR_MII_MODE
| MCF5272_FEC_RCR_DRT); /* half duplex */
/* Only operate in half-duplex, no heart beat control */
MCF5272_WR_FEC_TCR(imm, 0);
/* Set the maximum frame length (MTU) */
MCF5272_WR_FEC_MFLR(imm, MTU_FEC);
/* Set MII bus speed */
MCF5272_WR_FEC_MSCR(imm, 0x0a);
/* Enable fec i/o pins */
value = MCF5272_RD_GPIO_PBCNT(imm);
MCF5272_WR_GPIO_PBCNT(imm, ((value & 0x0000ffff) | 0x55550000));
/* Clear MII interrupt status */
MCF5272_WR_FEC_EIR(imm, MCF5272_FEC_IMR_MIIEN);
/* /\* Read phy ID *\/ */
/* MCF5272_WR_FEC_MMFR(imm, 0x600a0000); */
/* while (1) */
/* { */
/* value = MCF5272_RD_FEC_EIR(imm); */
/* if ((value & MCF5272_FEC_IMR_MIIEN) != 0) */
/* { */
/* MCF5272_WR_FEC_EIR(imm, MCF5272_FEC_IMR_MIIEN); */
/* break; */
/* } */
/* } */
/* phy = MCF5272_RD_FEC_MMFR(imm); */
/* Enable FEC */
enable_fec(mcf5272);
/* THIS IS FOR LEVEL ONE/INTEL PHY ONLY!!! */
/* Program Phy LED 3 to tell us transmit status */
MCF5272_WR_FEC_MMFR(imm, 0x50520412);
}
/*-----------------------------------------------------------------------------------*
* etharp timer thread
* It's only job is to initialize the timer, create a semaphore and wait on it
* forever. We need a special task to handle the arp timer.
*-----------------------------------------------------------------------------------*/
static void
etharp_timer_thread(void *arg)
{
sys_sem_t *psem = (sys_sem_t *) arg;
/* Create timeout timer */
sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
/* Signal previous task that it can go */
sys_sem_signal(*psem);
tx_sem = sys_sem_new(0);
while (1)
{
sys_sem_wait(tx_sem);
mcf5272fec_tx_cleanup();
}
}
/*-----------------------------------------------------------------------------------*/
static void
etharp_timer_init(void *arg)
{
sys_thread_new(DEFAULT_THREAD_NAME, (void *)etharp_timer_thread, arg, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
}
/*-----------------------------------------------------------------------------------*/
/*
* mcf5272fecif_init(struct netif *netif):
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* Note that there is only one fec in a 5272!
*
*/
err_t
mcf5272fecif_init(struct netif *netif)
{
sys_sem_t sem;
/* Allocate our interface control block */
/* IMPORTANT NOTE: This works for 5272, but if you are using a cpu with data cache
* then you need to make sure you get this memory from non-cachable memory. */
mcf5272if = (mcf5272if_t *) calloc(1, sizeof(mcf5272if_t));
if (mcf5272if)
{
netif->state = mcf5272if;
mcf5272if->netif = netif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = etharp_output;
netif->linkoutput = low_level_output;
netif->mtu = MTU_FEC - 18; // mtu without ethernet header and crc
mcf5272if->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
netif->hwaddr_len = 6; /* Ethernet interface */
mcf5272if->imm = mcf5272_get_immp();
low_level_init(netif);
etharp_init();
sem = sys_sem_new(0);
etharp_timer_init(&sem);
sys_sem_wait(sem);
sys_sem_free(sem);
return ERR_OK;
}
else
return ERR_MEM;
}
/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -