📄 bl_enet.c
字号:
g_pConn->rport = HTONS(TFTP_PORT);
//
// Send a TFTP read request.
//
SendTFTPGet();
//
// Since the first TFTP read request will result in an ARP request, delay
// for just a bit and then re-issue the TFTP read request.
//
PT_YIELD(&g_sThread);
//
// Resend the TFTP read request. If the ARP request has already been
// answered, this will go out as is and avoid the two second timeout below.
//
SendTFTPGet();
//
// Start the TFTP transfer from block one.
//
g_ulTFTPBlock = 1;
//
// Loop forever. This loop is explicitly exited when the TFTP transfer has
// completed.
//
while(1)
{
//
// Set the amount of time to wait for the TFTP data packet.
//
g_ulTarget = g_ulTicks + (SYSTICKHZ * 2);
//
// Wait until a packet is received or the timeout has occurred.
//
PT_WAIT_UNTIL(&g_sThread, uip_newdata() || (g_ulTicks > g_ulTarget));
//
// See if a packet has been received.
//
if(uip_newdata())
{
//
// Clear the new data flag so that this packet will only be
// examined one time.
//
uip_flags &= ~(UIP_NEWDATA);
//
// See if this is a TFTP data packet.
//
if(ParseTFTPData() == 1)
{
break;
}
}
else
{
//
// The transfer timed out, so send a new TFTP read request.
//
SendTFTPGet();
//
// Start the TFTP transfer from block one.
//
g_ulTFTPBlock = 1;
}
}
//
// Wait for a bit to make sure that the final ACK packet is transmitted.
//
g_ulTarget = g_ulTicks + (SYSTICKHZ / 4);
while(g_ulTicks < g_ulTarget)
{
PT_YIELD(&g_sThread);
}
//
// Perform a software reset request. This will cause the microcontroller
// to reset; no further code will be executed.
//
HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ;
//
// The microcontroller should have reset, so this should never be reached.
// Just in case, loop forever.
//
while(1)
{
}
//
// End the proto-thread.
//
PT_END(&g_sThread);
}
//*****************************************************************************
//
//! Configures the Ethernet controller.
//!
//! This function configures the Ethernet controller, preparing it for use by
//! the boot loader.
//!
//! This function is contained in <tt>bl_enet.c</tt>.
//!
//! \return None.
//
//*****************************************************************************
void
ConfigureEnet(void)
{
//
// Turn the LDO voltage up to 2.75V if configured to do so. This is a
// workaround for errata in revision A2 of Fury-class devices that allows
// the PLL to operate reliably.
//
#ifdef BOOST_LDO_VOLTAGE
HWREG(SYSCTL_LDOPCTL) = SYSCTL_LDOPCTL_2_75V;
#endif
//
// Enable the main oscillator.
//
HWREG(SYSCTL_RCC) &= ~(SYSCTL_RCC_MOSCDIS);
//
// Delay while the main oscillator starts up.
//
Delay(524288);
//
// Set the crystal frequency, switch to the main oscillator, and enable the
// PLL.
//
#if CRYSTAL_FREQ == 3579545
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_3_57MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 3686400
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_3_68MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 4000000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_4MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 4096000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_4_09MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 4915200
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_4_91MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 5000000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_5MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 5120000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_5_12MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 6000000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_6MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 6144000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_6_14MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 7372800
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_7_37MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 8000000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_8MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
#if CRYSTAL_FREQ == 8192000
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_8_19MHZ | SYSCTL_RCC_OSCSRC_MAIN);
#endif
//
// Delay while the PLL locks.
//
Delay(524288);
//
// Disable the PLL bypass so that the part is clocked from the PLL, and set
// sysdiv to 16.
//
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) & ~(SYSCTL_RCC_BYPASS)) |
SYSCTL_RCC_SYSDIV_16);
//
// Enable the Ethernet controller, along with the LEDs if requested.
//
#ifdef ENET_ENABLE_LEDS
HWREG(SYSCTL_RCGC2) = (SYSCTL_RCGC2_EPHY0 | SYSCTL_RCGC2_EMAC0 |
SYSCTL_RCGC2_GPIOF);
#else
HWREG(SYSCTL_RCGC2) = SYSCTL_RCGC2_EPHY0 | SYSCTL_RCGC2_EMAC0;
#endif
//
// Enable the Ethernet LED outputs if requested.
//
#ifdef ENET_ENABLE_LEDS
HWREG(GPIO_PORTF_BASE + GPIO_O_DEN) = (1 << 2) | (1 << 3);
HWREG(GPIO_PORTF_BASE + GPIO_O_AFSEL) = (1 << 2) | (1 << 3);
#endif
//
// Set the Ethernet management clock divider based on the 3.125 MHz system
// clock.
//
HWREG(ETH_BASE + MAC_O_MDV) = (200000000 / 16) / 2 / 2500000;
//
// Setup the Ethernet transmit and receive control registers.
//
HWREG(ETH_BASE + MAC_O_TCTL) = (MAC_TCTL_DUPLEX | MAC_TCTL_CRC |
MAC_TCTL_PADEN | MAC_TCTL_TXEN);
HWREG(ETH_BASE + MAC_O_RCTL) = (MAC_RCTL_RSTFIFO | MAC_RCTL_AMUL |
MAC_RCTL_RXEN);
}
//*****************************************************************************
//
//! Starts the update process via BOOTP.
//!
//! This function starts the Ethernet firmware update process. The BOOTP
//! (as defined by RFC951 at http://tools.ietf.org/html/rfc951) and TFTP (as
//! defined by RFC1350 at http://tools.ietf.org/html/rfc1350) protocols are
//! used to transfer the firmware image over Ethernet.
//!
//! This function is contained in <tt>bl_enet.c</tt>.
//!
//! \return Never returns.
//
//*****************************************************************************
void
UpdateBOOTP(void)
{
unsigned long ulTemp;
uip_ipaddr_t sAddr;
//
// Set sysdiv to 16.
//
HWREG(SYSCTL_RCC) |= SYSCTL_RCC_SYSDIV_16;
//
// Set the flash programming based on the 3.125 MHz system clock.
//
HWREG(FLASH_USECRL) = 3;
//
// Get the size of flash.
//
g_ulFlashEnd = ((HWREG(SYSCTL_DC0) & SYSCTL_DC0_FLASHSZ_M) + 1) * 2048;
#ifdef FLASH_RSVD_SPACE
g_ulFlashEnd -= FLASH_RSVD_SPACE;
#endif
//
// Setup SysTick.
//
HWREG(NVIC_ST_RELOAD) = ((200000000 / 16) / SYSTICKHZ) - 1;
HWREG(NVIC_ST_CTRL) = (NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN |
NVIC_ST_CTRL_ENABLE);
//
// If a static MAC address is not being used, then get the MAC address from
// the flash user registers.
//
#ifndef ENET_MAC_ADDR0
ulTemp = HWREG(FLASH_USERREG0);
g_sMACAddr.addr[0] = ulTemp & 0xff;
g_sMACAddr.addr[1] = (ulTemp >> 8) & 0xff;
g_sMACAddr.addr[2] = (ulTemp >> 16) & 0xff;
ulTemp = HWREG(FLASH_USERREG1);
g_sMACAddr.addr[3] = ulTemp & 0xff;
g_sMACAddr.addr[4] = (ulTemp >> 8) & 0xff;
g_sMACAddr.addr[5] = (ulTemp >> 16) & 0xff;
#endif
//
// Seed the random number generator from the MAC address.
//
g_ulRandomSeed = *(unsigned long *)(g_sMACAddr.addr + 2);
//
// Initialize the uIP stack.
//
uip_init();
uip_arp_init();
//
// Program the MAC address.
//
HWREG(ETH_BASE + MAC_O_IA0) = *((unsigned long *)g_sMACAddr.addr);
HWREG(ETH_BASE + MAC_O_IA1) = *((unsigned short *)(g_sMACAddr.addr + 4));
uip_setethaddr(g_sMACAddr);
//
// Initialize the proto-thread used by the BOOTP protocol handler.
//
PT_INIT(&g_sThread);
//
// Create a UDP socket for sending requests to the BOOTP server. After the
// BOOTP portion of the protocol has been handled, this socket will be
// reused to communicate with the TFTP server.
//
*((unsigned long *)(void *)(&sAddr)) = 0xffffffff;
g_pConn = uip_udp_new(&sAddr, HTONS(BOOTP_SERVER_PORT));
uip_udp_bind(g_pConn, HTONS(BOOTP_CLIENT_PORT));
//
// Reset the counters that are incremented by SysTick.
//
g_ulTicks = 0;
g_ulPeriodicTimer = 0;
g_ulARPTimer = 0;
//
// Main Application Loop.
//
while(1)
{
//
// See if there is a packet waiting to be read.
//
if((HWREG(ETH_BASE + MAC_O_NP) & MAC_NP_NPR_M) != 0)
{
//
// Read the packet from the Ethernet controller.
//
EnetReadPacket();
//
// See if this is an IP packet.
//
if((uip_len != 0) &&
(((struct uip_eth_hdr *)&uip_buf[0])->type ==
HTONS(UIP_ETHTYPE_IP)))
{
//
// Update the ARP tables based on this packet.
//
uip_arp_ipin();
//
// Process this packet.
//
uip_input();
//
// See if the processing of this packet resulted in a packet to
// be sent.
//
if(uip_len > 0)
{
//
// Update the ARP tables based on the packet to be sent.
//
uip_arp_out();
//
// Send the packet.
//
EnetWritePacket();
//
// Indicate that the packet has been sent.
//
uip_len = 0;
}
}
//
// See if this is an ARP packet.
//
else if((uip_len != 0) &&
(((struct uip_eth_hdr *)&uip_buf[0])->type ==
HTONS(UIP_ETHTYPE_ARP)))
{
//
// Process this packet.
//
uip_arp_arpin();
//
// See if the processing of this packet resulted in a packet to
// be sent.
//
if(uip_len > 0)
{
//
// Send the packet.
//
EnetWritePacket();
//
// Indicate that the packet has been sent.
//
uip_len = 0;
}
}
}
//
// See if the periodic timer has expired.
//
if(g_ulPeriodicTimer > UIP_PERIODIC_TIMER_MS)
{
//
// Reset the periodic timer.
//
g_ulPeriodicTimer = 0;
//
// Loop through the UDP connections.
//
for(ulTemp = 0; ulTemp < UIP_UDP_CONNS; ulTemp++)
{
//
// Perform the periodic processing on this UDP connection.
//
uip_udp_periodic(ulTemp);
//
// See if the periodic processing of this connection resulted
// in a packet to be sent.
//
if(uip_len > 0)
{
//
// Update the ARP tables based on the packet to be sent.
//
uip_arp_out();
//
// Send the packet.
//
EnetWritePacket();
//
// Indicate that the packet has been sent.
//
uip_len = 0;
}
}
}
//
// See if the ARP timer has expired.
//
if(g_ulARPTimer > UIP_ARP_TIMER_MS)
{
//
// Reset the ARP timer.
//
g_ulARPTimer = 0;
//
// Perform periodic processing on the ARP table.
//
uip_arp_timer();
}
}
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -