⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bl_enet.c

📁 ARM-CORTEX LM3S系列远程下载更新程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -