📄 bl_enet.c
字号:
//*****************************************************************************
//
// bl_enet.c - Functions to update via Ethernet.
//
// Copyright (c) 2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 1928 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************
#include "../hw_ethernet.h"
#include "../hw_flash.h"
#include "../hw_gpio.h"
#include "../hw_memmap.h"
#include "../hw_nvic.h"
#include "../hw_sysctl.h"
#include "../hw_types.h"
#include "bl_config.h"
#include "bl_decrypt.h"
//*****************************************************************************
//
// If using Ethernet update, make sure that the crystal frequency is defined.
//
//*****************************************************************************
#if defined(ENET_ENABLE_UPDATE) && !defined(CRYSTAL_FREQ)
#error ERROR: CRYSTAL_FREQ must be defined for Ethernet update!
#endif
//*****************************************************************************
//
// If using Ethernet update, issue a warning if boot loader update is enabled
// (it is not supported via BOOTP given that there is no way to distinguish
// between a normal firmware image and a boot loader update image).
//
//*****************************************************************************
#if defined(ENET_ENABLE_UPDATE) && defined(ENABLE_BL_UPDATE)
#error ERROR: Updating the boot loader is not supported over Ethernet!
#endif
//*****************************************************************************
//
// Directly include the uIP code if using Ethernet for the update. This allows
// non-Ethernet boot loader builds to not have to supply the uip-conf.h file
// that would otherwise be required.
//
//*****************************************************************************
#if defined(ENET_ENABLE_UPDATE)
#include "../third_party/uip-1.0/uip/pt.h"
#include "../third_party/uip-1.0/uip/uip_arp.c"
#undef BUF
#include "../third_party/uip-1.0/uip/uip.c"
#endif
//*****************************************************************************
//
//! \addtogroup boot_loader_api
//! @{
//
//*****************************************************************************
#if defined(ENET_ENABLE_UPDATE) || defined(DOXYGEN)
//*****************************************************************************
//
// A prototype for the function (in the startup code) for a predictable length
// delay.
//
//*****************************************************************************
extern void Delay(unsigned long ulCount);
//*****************************************************************************
//
// Defines for setting up the system clock.
//
//*****************************************************************************
#define SYSTICKHZ 100
#define SYSTICKMS (1000 / SYSTICKHZ)
//*****************************************************************************
//
// UIP Timers (in ms)
//
//*****************************************************************************
#define UIP_PERIODIC_TIMER_MS 50
#define UIP_ARP_TIMER_MS 10000
//*****************************************************************************
//
// This structure defines the fields in a BOOTP request/reply packet.
//
//*****************************************************************************
typedef struct
{
//
// The operation; 1 is a request, 2 is a reply.
//
unsigned char ucOp;
//
// The hardware type; 1 is Ethernet.
//
unsigned char ucHType;
//
// The hardware address length; for Ethernet this will be 6, the length of
// the MAC address.
//
unsigned char ucHLen;
//
// Hop count, used by gateways for cross-gateway booting.
//
unsigned char ucHops;
//
// The transaction ID.
//
unsigned long ulXID;
//
// The number of seconds elapsed since the client started trying to boot.
//
unsigned short usSecs;
//
// The BOOTP flags.
//
unsigned short usFlags;
//
// The client's IP address, if it knows it.
//
unsigned long ulCIAddr;
//
// The client's IP address, as assigned by the BOOTP server.
//
unsigned long ulYIAddr;
//
// The TFTP server's IP address.
//
unsigned long ulSIAddr;
//
// The gateway IP address, if booting cross-gateway.
//
unsigned long ulGIAddr;
//
// The hardware address; for Ethernet this is the MAC address.
//
unsigned char pucCHAddr[16];
//
// The name, or nickname, of the server that should handle this BOOTP
// request.
//
char pcSName[64];
//
// The name of the boot file to be loaded via TFTP.
//
char pcFile[128];
//
// Optional vendor-specific area; not used for BOOTP.
//
unsigned char pucVend[64];
}
tBOOTPPacket;
//*****************************************************************************
//
// The BOOTP commands.
//
//*****************************************************************************
#define BOOTP_REQUEST 1
#define BOOTP_REPLY 2
//*****************************************************************************
//
// The TFTP commands.
//
//*****************************************************************************
#define TFTP_RRQ 1
#define TFTP_WRQ 2
#define TFTP_DATA 3
#define TFTP_ACK 4
#define TFTP_ERROR 5
//*****************************************************************************
//
// The UDP ports used by the BOOTP protocol.
//
//*****************************************************************************
#define BOOTP_SERVER_PORT 67
#define BOOTP_CLIENT_PORT 68
//*****************************************************************************
//
// The UDP port for the TFTP server.
//
//*****************************************************************************
#define TFTP_PORT 69
//*****************************************************************************
//
// The MAC address of the Ethernet interface.
//
//*****************************************************************************
#ifdef ENET_MAC_ADDR0
static struct uip_eth_addr g_sMACAddr =
{
{
ENET_MAC_ADDR0,
ENET_MAC_ADDR1,
ENET_MAC_ADDR2,
ENET_MAC_ADDR3,
ENET_MAC_ADDR4,
ENET_MAC_ADDR5
}
};
#else
static struct uip_eth_addr g_sMACAddr;
#endif
//*****************************************************************************
//
// The number of SysTick interrupts since the start of the boot loader.
//
//*****************************************************************************
static unsigned long g_ulTicks;
//*****************************************************************************
//
// The seed for the random number generator.
//
//*****************************************************************************
static unsigned long g_ulRandomSeed;
//*****************************************************************************
//
// The number of milliseconds since the last call to uip_udp_periodic().
//
//*****************************************************************************
static volatile unsigned long g_ulPeriodicTimer;
//*****************************************************************************
//
// The number of milliseconds since the last call to uip_arp_timer().
//
//*****************************************************************************
static volatile unsigned long g_ulARPTimer;
//*****************************************************************************
//
// The transaction ID of the most recently sent out BOOTP request.
//
//*****************************************************************************
static unsigned long g_ulXID;
//*****************************************************************************
//
// The state for the proto-thread that handles the BOOTP process.
//
//*****************************************************************************
static struct pt g_sThread;
//*****************************************************************************
//
// The amount of time to wait for a BOOTP reply before sending out a new BOOTP
// request.
//
//*****************************************************************************
static unsigned long g_ulDelay;
//*****************************************************************************
//
// The target time (relative to g_ulTicks) when the next timeout occurs.
//
//*****************************************************************************
static unsigned long g_ulTarget;
//*****************************************************************************
//
// The IP address of the TFTP server.
//
//*****************************************************************************
static uip_ipaddr_t g_sServerAddr;
//*****************************************************************************
//
// The name of the file to be read from the TFTP server.
//
//*****************************************************************************
static char g_pcFilename[128];
//*****************************************************************************
//
// The end of flash. If there is not a reserved block at the end of flash,
// this is the real end of flash. If there is a reserved block, this is the
// start of the reserved block (i.e. the virtual end of flash).
//
//*****************************************************************************
static unsigned long g_ulFlashEnd;
//*****************************************************************************
//
// The current block being read from the TFTP server.
//
//*****************************************************************************
static unsigned long g_ulTFTPBlock;
//*****************************************************************************
//
// The UDP socket used to communicate with the BOOTP and TFTP servers (in
// sequence).
//
//*****************************************************************************
struct uip_udp_conn *g_pConn;
//*****************************************************************************
//
// uIP uses memset, so a simple one is provided here. This is not as efficient
// as the one in the C library (from an execution time perspective), but it is
// much smaller.
//
//*****************************************************************************
void *
memset(void *pvDest, int iChar, size_t lLength)
{
char *pcBuf = (char *)pvDest;
//
// Fill the buffer with the given character.
//
while(lLength--)
{
*pcBuf++ = iChar;
}
//
// Return a pointer to the beginning of the buffer.
//
return(pvDest);
}
//*****************************************************************************
//
// uIP uses memcpy, so a simple one is provided here. This is not as efficient
// as the one in the C library (from an execution time perspective), but it is
// much smaller.
//
//*****************************************************************************
void *
memcpy(void *pvDest, const void *pvSrc, size_t lLength)
{
const char *pcSrc = (const char *)pvSrc;
char *pcDest = (char *)pvDest;
//
// Copy bytes from the source buffer to the destination buffer.
//
while(lLength--)
{
*pcDest++ = *pcSrc++;
}
//
// Return a pointer to the beginning of the destination buffer.
//
return(pvDest);
}
//*****************************************************************************
//
//! Handles the SysTick interrupt.
//!
//! This function is called when the SysTick interrupt occurs. It simply
//! keeps a running count of interrupts, used as a time basis for the BOOTP and
//! TFTP protocols.
//!
//! This function is contained in <tt>bl_enet.c</tt>.
//!
//! \return None.
//
//*****************************************************************************
void
SysTickIntHandler(void)
{
//
// Increment the tick count.
//
g_ulTicks++;
g_ulPeriodicTimer += SYSTICKMS;
g_ulARPTimer += SYSTICKMS;
}
//*****************************************************************************
//
//! Computes a new random number.
//!
//! This function computes a new pseudo-random number, using a linear
//! congruence random number generator. Note that if the entire 32-bits of the
//! produced random number are not being used, the upper N bits should be used
//! instead of the lower N bits as they are much more random (for example, use
//! ``RandomNumber() >> 28'' instead of ``RandomNumber() & 15'').
//!
//! This function is contained in <tt>bl_enet.c</tt>.
//!
//! \return Returns a 32-bit pseudo-random number.
//
//*****************************************************************************
static unsigned long
RandomNumber(void)
{
//
// Generate a new pseudo-random number with a linear congruence random
// number generator. This new random number becomes the seed for the next
// random number.
//
g_ulRandomSeed = (g_ulRandomSeed * 1664525) + 1013904223;
//
// Return the new random number.
//
return(g_ulRandomSeed);
}
//*****************************************************************************
//
//! Reads a packet from the Ethernet controller.
//!
//! This function reads a packet from the Ethernet controller into the uIP
//! packet buffer. It assumes that a packet is available to be read.
//!
//! This function is contained in <tt>bl_enet.c</tt>.
//!
//! \return None.
//
//*****************************************************************************
static void
EnetReadPacket(void)
{
unsigned long ulTemp;
long lIdx, lCount;
//
// Read the first word from the FIFO.
//
ulTemp = HWREG(ETH_BASE + MAC_O_DATA);
//
// Extract the size of the remainder of the packet.
//
lCount = (ulTemp & 0xffff) - 4;
//
// See if the packet will fit into the data buffer.
//
if(lCount > (sizeof(uip_buf) + 2))
{
//
// The packet will not fit into the data buffer, so read the rest of
// the data and throw it away.
//
while(lCount > 0)
{
HWREG(ETH_BASE + MAC_O_DATA);
lCount -= 4;
}
//
// There is no packet for uIP to process.
//
uip_len = 0;
//
// Return without any further processing.
//
return;
}
//
// Copy the first two bytes into the packet buffer.
//
*(unsigned short *)uip_buf = ulTemp >> 16;
//
// Save the packet length for uIP's use.
//
uip_len = lCount - 2;
//
// Read the remainder of the packet data into uIP's buffer.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -