Rewrite from scratch a TCP/IP stack for mbed. So far the following parts are usable: Drivers: - EMAC driver (from CMSIS 2.0) Protocols: - Ethernet protocol - ARP over ethernet for IPv4 - IPv4 over Ethernet - ICMPv4 over IPv4 - UDPv4 over IPv4 APIs: - Sockets for UDPv4 The structure of this stack is designed to be very modular. Each protocol can register one or more protocol to handle its payload, and in each protocol, an API can be hooked (like Sockets for example). This is an early release.
Revision 1:f4040665bc61, committed 2011-06-12
- Comitter:
- Benoit
- Date:
- Sun Jun 12 19:17:11 2011 +0000
- Parent:
- 0:19f5f51584de
- Child:
- 2:3d1c0fbd10e6
- Commit message:
- Frames are now received using an interrupt handler
Changed in this revision
--- a/ARP.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,565 +0,0 @@ -/* - * $Id: ARP.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "ARP.h" -#include "Ethernet.h" -#include "Debug.h" -#include "IPv4.h" -#include <string.h> - - -#define DEBUG_CURRENT_MODULE_NAME "ARP" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ARP - - -enum ARP_EntryStatus -{ - ARP_Entry_Free = 0, - ARP_Entry_PendingReply, - ARP_Entry_Dynamic, - ARP_Entry_Expired, - ARP_Entry_Static, - ARP_Entry_Count, -}; -typedef enum ARP_EntryStatus ARP_EntryStatus_t; - - -const char *arpEntryStatusText[ARP_Entry_Count] = -{ - "free", - "pending", - "dynamic", - "expired", - "static", -}; - -struct ARP_CacheEntry -{ - IPv4_Addr_t ipv4Addr; - Ethernet_Addr_t ethernetAddr; - NetIF_t *netIF; - uint16_t age; - ARP_EntryStatus_t status; - RTOS_Mutex_t mutex; -}; -typedef struct ARP_CacheEntry ARP_CacheEntry_t; - - -#pragma push -#pragma pack(1) -static struct -{ - Ethernet_Header_t ethernetHeader; - ARP_Header_t arpHeader; - ARP_IPv4Data_t ipv4ARPData; -} arp_FullIPv4Packet; -#pragma pop - - -static void Init(void); -static void Handler(NetIF_t *netIF, Packet_t *packet); -static void PeriodicFunction(void); -static ARP_CacheEntry_t *GetReusableEntry(void); -static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address); - - -static ARP_CacheEntry_t arp_CacheTable[ARP_CACHE_MAX_ENTRIES]; - - -Protocol_Handler_t arp = -{ - PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ - Protocol_ID_ARP, /* Protocol ID */ - htons(ETHERNET_PROTO_ARP), /* Protocol number */ - Init, /* Protocol initialisation function */ - Handler, /* Protocol handler */ - NULL, /* Protocol registration function */ - NULL, /* API registration function */ -}; - - -static void Init(void) -{ - int32_t index; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ARP layer")); - memset(arp_CacheTable, 0, sizeof(arp_CacheTable)); - for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) - { - arp_CacheTable[index].mutex = RTOS_MUTEX_CREATE(); - } - NetIF_RegisterPeriodicFunction("ARP cache", PeriodicFunction, ARP_FUNCTION_PERIOD); -} - - -static void Handler(NetIF_t *netIF, Packet_t *packet) -{ - ARP_Type_t type; - ARP_Protocol_t protocol; - ARP_Operation_t operation; - ARP_IPv4Data_t *ipv4ARP; - ARP_Header_t *arpHeader = (ARP_Header_t *)packet->data; - Ethernet_Addr_t *ourHWAddress; - Ethernet_Header_t *ethernetHeader; - ARP_CacheEntry_t *entry; - - - type = ntohs(arpHeader->type); - protocol = ntohs(arpHeader->protocol); - operation = ntohs(arpHeader->operation); - - if (type != ARP_HW_TYPE_ENET) goto Exit; /* not an ethernet ARP, ignore */ - if (protocol != ETHERNET_PROTO_IPV4) goto Exit; /* Not an IPv4 ARP, ignore */ - - ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1); - - switch(operation) - { - case ARP_OPERATION_REQUEST: - if (ipv4ARP->ipDest.addr == netIF->ipv4Address.addr) /* Does it match our hw address? */ - { - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - ARP_DumpHeader("Got ", arpHeader); - } - - ourHWAddress = (Ethernet_Addr_t *)netIF->driverParameter; - - arpHeader->operation = htons(ARP_OPERATION_REPLY); - - ipv4ARP->hwDest = ipv4ARP->hwSource; - ipv4ARP->ipDest.addr = ipv4ARP->ipSource.addr; - ipv4ARP->hwSource = *ourHWAddress; - ipv4ARP->ipSource = netIF->ipv4Address; - - NetIF_ProtoPop(packet); - - ethernetHeader = (Ethernet_Header_t *)packet->data; - ethernetHeader->destination = ethernetHeader->source; - ethernetHeader->source = *ourHWAddress; - - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - ARP_DumpHeader("Replying ", arpHeader); - } - - netIF->driver->Write(packet->data, packet->length); - } - - break; - - case ARP_OPERATION_REPLY: - /* Check if it matches an entry we requested */ - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - ARP_DumpHeader("Got ", arpHeader); - } - - entry = GetEntryByIPv4Address(ipv4ARP->ipSource); - if (entry == NULL) break; /* fake arp request */ - - entry->status = ARP_Entry_Dynamic; - entry->ethernetAddr = ipv4ARP->hwSource; - entry->netIF = netIF; - entry->age = 0; - - RTOS_MUTEX_UNLOCK(entry->mutex); - - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - DEBUG_RAW(("Adding entry %d.%d.%d.%d at %02x:%02x:%02x:%02x:%02x:%02x", - ipv4ARP->ipSource.IP0, - ipv4ARP->ipSource.IP1, - ipv4ARP->ipSource.IP2, - ipv4ARP->ipSource.IP3, - ipv4ARP->hwSource.MA0, - ipv4ARP->hwSource.MA1, - ipv4ARP->hwSource.MA2, - ipv4ARP->hwSource.MA3, - ipv4ARP->hwSource.MA4, - ipv4ARP->hwSource.MA5 - )); - } - break; - } - -Exit: - return; -} - - -static void PeriodicFunction(void) -{ - int32_t index; - ARP_CacheEntry_t *entry; - - for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) - { - entry = arp_CacheTable + index; - RTOS_MUTEX_LOCK(entry->mutex); - switch(entry->status) - { - case ARP_Entry_Dynamic: - entry->age += ARP_FUNCTION_PERIOD; - if (entry->age > ARP_MAX_ENTRY_AGE) - { - entry->status = ARP_Entry_Expired; - entry->age = 0; - } - break; - - case ARP_Entry_PendingReply: - entry->age += ARP_FUNCTION_PERIOD; - if (entry->age > ARP_MAX_ENTRY_AGE) - { - entry->status = ARP_Entry_Free; - entry->age = 0; - } - break; - } - RTOS_MUTEX_UNLOCK(entry->mutex); - } -} - - -static ARP_CacheEntry_t *GetReusableEntry(void) -{ - int32_t index, - oldestEntryIndex, oldestEntryAge; - ARP_CacheEntry_t *entry; - - /* First look for a free entry */ - for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) - { - entry = arp_CacheTable + index; - RTOS_MUTEX_LOCK(entry->mutex); - - if (entry->status == ARP_Entry_Free) - { - break; - } - - RTOS_MUTEX_UNLOCK(entry->mutex); - entry = NULL; - } - - if (entry != NULL) goto Exit; /* A free entry was found, return it */ - - /* Now look for an expired entry */ - oldestEntryIndex = -1; - oldestEntryAge = -1; - for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) - { - entry = arp_CacheTable + index; - RTOS_MUTEX_LOCK(entry->mutex); - - if (entry->age > oldestEntryAge) - { - oldestEntryIndex = index; - oldestEntryAge = entry->age; - } - - if (entry->status == ARP_Entry_Expired) - { - break; - } - - RTOS_MUTEX_UNLOCK(entry->mutex); - entry = NULL; - } - - if (entry != NULL) goto Exit; /* An expired entry was found, return it */ - - /* Last possibility, return the oldest non static entry */ - entry = arp_CacheTable + oldestEntryIndex; - RTOS_MUTEX_LOCK(entry->mutex); - -Exit: - return entry; -} - - -static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address) -{ - int32_t index; - ARP_CacheEntry_t *entry = NULL; - - for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) - { - entry = arp_CacheTable + index; - RTOS_MUTEX_LOCK(entry->mutex); - - if (entry->ipv4Addr.addr == address.addr) - { - break; - } - RTOS_MUTEX_UNLOCK(entry->mutex); - entry = NULL; - } - - return entry; -} - - -int32_t ARP_ResolveIPv4Address(NetIF_t *netIF, IPv4_Addr_t address, Ethernet_Addr_t *ethernetAddr) -{ - int32_t result = -1; - Ethernet_Addr_t *hwAddress; - ARP_CacheEntry_t *entry; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Resolving %d.%d.%d.%d", - address.IP0, - address.IP1, - address.IP2, - address.IP3 - )); - - /* Look if entry is already available in table */ - entry = GetEntryByIPv4Address(address); - if (entry != NULL) /* Found entry, look its status */ - { - switch(entry->status) - { - case ARP_Entry_Static: - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found static entry")); - if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; - RTOS_MUTEX_UNLOCK(entry->mutex); - result = 0; - break; - - case ARP_Entry_Dynamic: - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found dynamic entry")); - if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; - entry->age = 0; - RTOS_MUTEX_UNLOCK(entry->mutex); - result = 0; - break; - - case ARP_Entry_Expired: - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found expired entry, reactivating it")); - if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; - entry->status = ARP_Entry_Dynamic; - entry->age = 0; - RTOS_MUTEX_UNLOCK(entry->mutex); - result = 0; - break; - - case ARP_Entry_PendingReply: - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found pending entry")); - entry->age = 0; - RTOS_MUTEX_UNLOCK(entry->mutex); - break; - - default: - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Default?!")); - break; - } - } - - if (result == 0) goto Exit; /* Resolution was successfull, exit */ - - - /* Entry not found, send a request */ - result = -1; - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Sending ARP resolution request for %d.%d.%d.%d", - address.IP0, - address.IP1, - address.IP2, - address.IP3 - )); - - /* Update entry, setting its status to Pending reply */ - entry = GetReusableEntry(); - if (entry != NULL) - { - entry->status = ARP_Entry_PendingReply; - entry->ipv4Addr.addr = address.addr; - entry->netIF = netIF; - entry->age = 0; - RTOS_MUTEX_UNLOCK(entry->mutex); - } - /* Send ARP who-has */ - hwAddress = (Ethernet_Addr_t *)netIF->driverParameter; - - arp_FullIPv4Packet.ethernetHeader.destination = ethernet_Addr_Broadcast; - arp_FullIPv4Packet.ethernetHeader.source = *hwAddress; - arp_FullIPv4Packet.ethernetHeader.protocol = htons(ETHERNET_PROTO_ARP); - - arp_FullIPv4Packet.arpHeader.type = htons(ARP_HW_TYPE_ENET); - arp_FullIPv4Packet.arpHeader.protocol = htons(ETHERNET_PROTO_IPV4); - arp_FullIPv4Packet.arpHeader.operation = htons(ARP_OPERATION_REQUEST); - arp_FullIPv4Packet.arpHeader.hardAddrLen = 6; - arp_FullIPv4Packet.arpHeader.protoAddrLen = 4; - - arp_FullIPv4Packet.ipv4ARPData.hwSource = *hwAddress; - arp_FullIPv4Packet.ipv4ARPData.ipSource = netIF->ipv4Address; - arp_FullIPv4Packet.ipv4ARPData.hwDest = ethernet_Addr_Null; - arp_FullIPv4Packet.ipv4ARPData.ipDest = address; - - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - ARP_DumpHeader("Sending ", &arp_FullIPv4Packet.arpHeader); - } - - netIF->driver->Write((uint8_t *)&arp_FullIPv4Packet, sizeof(arp_FullIPv4Packet)); - -Exit: - return result; -} - - -int32_t ARP_AddStaticEntry(NetIF_t *netIF, IPv4_Addr_t address, const Ethernet_Addr_t *ethernetAddr) -{ - int32_t result = 0; - ARP_CacheEntry_t *entry; - - entry = GetReusableEntry(); - if (entry == NULL) - { - result = -1; - goto Exit; - } - entry->netIF = netIF; - entry->status = ARP_Entry_Static; - entry->ipv4Addr.addr = address.addr; - entry->ethernetAddr = *ethernetAddr; - entry->age = 0; - RTOS_MUTEX_UNLOCK(entry->mutex); - -Exit: - return result; -} - - -int32_t ARP_RemoveEntry(const NetIF_t *netIF, IPv4_Addr_t address) -{ - int32_t result = 0; - - - - return result; -} - - -void ARP_InvalidateCache(Bool_t flushStaticEntries) -{ - int32_t index; - ARP_CacheEntry_t *entry; - - for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) - { - entry = arp_CacheTable + index; - RTOS_MUTEX_LOCK(entry->mutex); - if ((entry->status == ARP_Entry_Static) && (!flushStaticEntries)) - { - RTOS_MUTEX_UNLOCK(entry->mutex); - continue; - } - entry->status = ARP_Entry_Free; - RTOS_MUTEX_UNLOCK(entry->mutex); - } -} - - -void ARP_DisplayCache(void) -{ - int32_t index; - ARP_CacheEntry_t *entry = NULL; - - DEBUG_RAW(("ARP cache")); - DEBUG_RAW(("index dev MAC address type age IPv4 address")); - DEBUG_RAW(("----------------------------------------------------------")); - /* en0 00:11:22:33:44:55 dyn 10 163.157.128.131 */ - for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) - { - entry = arp_CacheTable + index; - - DEBUG_RAW(("%2d %s%c %02x:%02x:%02x:%02x:%02x:%02x %8s %4d %d.%d.%d.%d", - index, - entry->status != ARP_Entry_Free ? entry->netIF->name : "--", - entry->status != ARP_Entry_Free ? entry->netIF->index + '0' : '-', - entry->ethernetAddr.MA0, - entry->ethernetAddr.MA1, - entry->ethernetAddr.MA2, - entry->ethernetAddr.MA3, - entry->ethernetAddr.MA4, - entry->ethernetAddr.MA5, - - arpEntryStatusText[entry->status], - entry->age, - - entry->ipv4Addr.IP0, - entry->ipv4Addr.IP1, - entry->ipv4Addr.IP2, - entry->ipv4Addr.IP3 - )); - } -} - -void ARP_DumpHeader(const char *prefix, ARP_Header_t *arpHeader) -{ - ARP_IPv4Data_t *ipv4ARP = NULL; - - if (arpHeader->protocol == htons(ETHERNET_PROTO_IPV4)) - { - ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1); - - switch(ntohs(arpHeader->operation)) - { - case ARP_OPERATION_REQUEST: - DEBUG_RAW(("%sARP who-has %d.%d.%d.%d tell %02x:%02x:%02x:%02x:%02x:%02x", - prefix != NULL ? prefix : "", - - ipv4ARP->ipDest.IP0, - ipv4ARP->ipDest.IP1, - ipv4ARP->ipDest.IP2, - ipv4ARP->ipDest.IP3, - - ipv4ARP->hwSource.MA0, - ipv4ARP->hwSource.MA1, - ipv4ARP->hwSource.MA2, - ipv4ARP->hwSource.MA3, - ipv4ARP->hwSource.MA4, - ipv4ARP->hwSource.MA5 - )); - break; - - case ARP_OPERATION_REPLY: - DEBUG_RAW(("%sARP %d.%d.%d.%d is-at %02x:%02x:%02x:%02x:%02x:%02x", - prefix != NULL ? prefix : "", - - ipv4ARP->ipSource.IP0, - ipv4ARP->ipSource.IP1, - ipv4ARP->ipSource.IP2, - ipv4ARP->ipSource.IP3, - - ipv4ARP->hwSource.MA0, - ipv4ARP->hwSource.MA1, - ipv4ARP->hwSource.MA2, - ipv4ARP->hwSource.MA3, - ipv4ARP->hwSource.MA4, - ipv4ARP->hwSource.MA5 - )); - break; - - default: - break; - } - } - else - { - DEBUG_RAW(("%sARP: unsupported protocol %d", - prefix != NULL ? prefix : "", - arpHeader->protocol - )); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ARP.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,568 @@ +/* + * $Id: ARP.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "ARP.h" +#include "Ethernet.h" +#include "Debug.h" +#include "IPv4.h" +#include <string.h> + + +#define DEBUG_CURRENT_MODULE_NAME "ARP" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ARP + + +enum ARP_EntryStatus +{ + ARP_Entry_Free = 0, + ARP_Entry_PendingReply, + ARP_Entry_Dynamic, + ARP_Entry_Expired, + ARP_Entry_Static, + ARP_Entry_Count, +}; +typedef enum ARP_EntryStatus ARP_EntryStatus_t; + + +const char *arpEntryStatusText[ARP_Entry_Count] = +{ + "free", + "pending", + "dynamic", + "expired", + "static", +}; + +struct ARP_CacheEntry +{ + IPv4_Addr_t ipv4Addr; + Ethernet_Addr_t ethernetAddr; + NetIF_t *netIF; + uint16_t age; + ARP_EntryStatus_t status; + RTOS_Mutex_t mutex; +}; +typedef struct ARP_CacheEntry ARP_CacheEntry_t; + + +#pragma push +#pragma pack(1) +static struct +{ + Ethernet_Header_t ethernetHeader; + ARP_Header_t arpHeader; + ARP_IPv4Data_t ipv4ARPData; +} arp_FullIPv4Packet; +#pragma pop + + +static void Init(void); +static void Handler(NetIF_t *netIF, Packet_t *packet); +static void PeriodicFunction(void); +static ARP_CacheEntry_t *GetReusableEntry(void); +static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address); + + +static ARP_CacheEntry_t arp_CacheTable[ARP_CACHE_MAX_ENTRIES]; + + +Protocol_Handler_t arp = +{ + PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ + Protocol_ID_ARP, /* Protocol ID */ + htons(ETHERNET_PROTO_ARP), /* Protocol number */ + Init, /* Protocol initialisation function */ + Handler, /* Protocol handler */ + NULL, /* Protocol registration function */ + NULL, /* API registration function */ +}; + + +static void Init(void) +{ + int32_t index; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ARP layer")); + memset(arp_CacheTable, 0, sizeof(arp_CacheTable)); + for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) + { + arp_CacheTable[index].mutex = RTOS_MUTEX_CREATE(); + } + NetIF_RegisterPeriodicFunction("ARP cache", PeriodicFunction, ARP_FUNCTION_PERIOD); +} + + +static void Handler(NetIF_t *netIF, Packet_t *packet) +{ + static ARP_Type_t type; + static ARP_Protocol_t protocol; + static ARP_Operation_t operation; + static ARP_IPv4Data_t *ipv4ARP; + static ARP_Header_t *arpHeader; + static Ethernet_Addr_t *ourHWAddress; + static Ethernet_Header_t *ethernetHeader; + static ARP_CacheEntry_t *entry; + + arpHeader = (ARP_Header_t *)packet->data; + type = ntohs(arpHeader->type); + protocol = ntohs(arpHeader->protocol); + operation = ntohs(arpHeader->operation); + + if (type != ARP_HW_TYPE_ENET) goto Exit; /* not an ethernet ARP, ignore */ + if (protocol != ETHERNET_PROTO_IPV4) goto Exit; /* Not an IPv4 ARP, ignore */ + + ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1); + + switch(operation) + { + case ARP_OPERATION_REQUEST: + if (ipv4ARP->ipDest.addr == netIF->ipv4Address.addr) /* Does it match our hw address? */ + { + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + ARP_DumpHeader("Got ", arpHeader); + } + + ourHWAddress = (Ethernet_Addr_t *)netIF->driverParameter; + + arpHeader->operation = htons(ARP_OPERATION_REPLY); + + ipv4ARP->hwDest = ipv4ARP->hwSource; + ipv4ARP->ipDest.addr = ipv4ARP->ipSource.addr; + ipv4ARP->hwSource = *ourHWAddress; + ipv4ARP->ipSource = netIF->ipv4Address; + + NetIF_ProtoPop(packet); + + ethernetHeader = (Ethernet_Header_t *)packet->data; + ethernetHeader->destination = ethernetHeader->source; + ethernetHeader->source = *ourHWAddress; + + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + ARP_DumpHeader("Replying ", arpHeader); + } + + netIF->driver->Write(packet->data, packet->length); + } + + break; + + case ARP_OPERATION_REPLY: + /* Check if it matches an entry we requested */ + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + ARP_DumpHeader("Got ", arpHeader); + } + + entry = GetEntryByIPv4Address(ipv4ARP->ipSource); + if (entry == NULL) break; /* fake arp request */ + + entry->status = ARP_Entry_Dynamic; + entry->ethernetAddr = ipv4ARP->hwSource; + entry->netIF = netIF; + entry->age = 0; + + RTOS_MUTEX_UNLOCK(entry->mutex); + + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + DEBUG_RAW(("Adding entry %d.%d.%d.%d at %02x:%02x:%02x:%02x:%02x:%02x", + ipv4ARP->ipSource.IP0, + ipv4ARP->ipSource.IP1, + ipv4ARP->ipSource.IP2, + ipv4ARP->ipSource.IP3, + ipv4ARP->hwSource.MA0, + ipv4ARP->hwSource.MA1, + ipv4ARP->hwSource.MA2, + ipv4ARP->hwSource.MA3, + ipv4ARP->hwSource.MA4, + ipv4ARP->hwSource.MA5 + )); + } + break; + } + +Exit: + return; +} + + +static void PeriodicFunction(void) +{ + int32_t index; + ARP_CacheEntry_t *entry; + + for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) + { + entry = arp_CacheTable + index; + RTOS_MUTEX_LOCK(entry->mutex); + switch(entry->status) + { + case ARP_Entry_Dynamic: + entry->age += ARP_FUNCTION_PERIOD; + if (entry->age > ARP_MAX_ENTRY_AGE) + { + entry->status = ARP_Entry_Expired; + entry->age = 0; + } + break; + + case ARP_Entry_PendingReply: + entry->age += ARP_FUNCTION_PERIOD; + if (entry->age > ARP_MAX_ENTRY_AGE) + { + entry->status = ARP_Entry_Free; + entry->age = 0; + } + break; + } + RTOS_MUTEX_UNLOCK(entry->mutex); + } +} + + +static ARP_CacheEntry_t *GetReusableEntry(void) +{ + int32_t index, + oldestEntryIndex, oldestEntryAge; + ARP_CacheEntry_t *entry; + + /* First look for a free entry */ + for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) + { + entry = arp_CacheTable + index; + RTOS_MUTEX_LOCK(entry->mutex); + + if (entry->status == ARP_Entry_Free) + { + break; + } + + RTOS_MUTEX_UNLOCK(entry->mutex); + entry = NULL; + } + + if (entry != NULL) goto Exit; /* A free entry was found, return it */ + + /* Now look for an expired entry */ + oldestEntryIndex = -1; + oldestEntryAge = -1; + for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) + { + entry = arp_CacheTable + index; + RTOS_MUTEX_LOCK(entry->mutex); + + if (entry->age > oldestEntryAge) + { + oldestEntryIndex = index; + oldestEntryAge = entry->age; + } + + if (entry->status == ARP_Entry_Expired) + { + break; + } + + RTOS_MUTEX_UNLOCK(entry->mutex); + entry = NULL; + } + + if (entry != NULL) goto Exit; /* An expired entry was found, return it */ + + /* Last possibility, return the oldest non static entry */ + entry = arp_CacheTable + oldestEntryIndex; + RTOS_MUTEX_LOCK(entry->mutex); + +Exit: + return entry; +} + + +static ARP_CacheEntry_t *GetEntryByIPv4Address(IPv4_Addr_t address) +{ + int32_t index; + ARP_CacheEntry_t *entry = NULL; + + for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) + { + entry = arp_CacheTable + index; + RTOS_MUTEX_LOCK(entry->mutex); + + if (entry->ipv4Addr.addr == address.addr) + { + break; + } + RTOS_MUTEX_UNLOCK(entry->mutex); + entry = NULL; + } + + return entry; +} + + +int32_t ARP_ResolveIPv4Address(NetIF_t *netIF, IPv4_Addr_t address, Ethernet_Addr_t *ethernetAddr) +{ + int32_t result = -1; + Ethernet_Addr_t *hwAddress; + ARP_CacheEntry_t *entry; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Resolving %d.%d.%d.%d", + address.IP0, + address.IP1, + address.IP2, + address.IP3 + )); + + /* Look if entry is already available in table */ + entry = GetEntryByIPv4Address(address); + if (entry != NULL) /* Found entry, look its status */ + { + switch(entry->status) + { + case ARP_Entry_Static: + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found static entry")); + if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; + RTOS_MUTEX_UNLOCK(entry->mutex); + result = 0; + break; + + case ARP_Entry_Dynamic: + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found dynamic entry")); + if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; + entry->age = 0; + RTOS_MUTEX_UNLOCK(entry->mutex); + result = 0; + break; + + case ARP_Entry_Expired: + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found expired entry, reactivating it")); + if (ethernetAddr != NULL) *ethernetAddr = entry->ethernetAddr; + entry->status = ARP_Entry_Dynamic; + entry->age = 0; + RTOS_MUTEX_UNLOCK(entry->mutex); + result = 0; + break; + + case ARP_Entry_PendingReply: + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Found pending entry")); + entry->age = 0; + RTOS_MUTEX_UNLOCK(entry->mutex); + break; + + default: + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Default?!")); + break; + } + } + + if (result == 0) goto Exit; /* Resolution was successfull, exit */ + + + /* Entry not found, send a request */ + result = -1; + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Sending ARP resolution request for %d.%d.%d.%d", + address.IP0, + address.IP1, + address.IP2, + address.IP3 + )); + + /* Update entry, setting its status to Pending reply */ + entry = GetReusableEntry(); + if (entry != NULL) + { + entry->status = ARP_Entry_PendingReply; + entry->ipv4Addr.addr = address.addr; + entry->netIF = netIF; + entry->age = 0; + RTOS_MUTEX_UNLOCK(entry->mutex); + } + /* Send ARP who-has */ + hwAddress = (Ethernet_Addr_t *)netIF->driverParameter; + + arp_FullIPv4Packet.ethernetHeader.destination = ethernet_Addr_Broadcast; + arp_FullIPv4Packet.ethernetHeader.source = *hwAddress; + arp_FullIPv4Packet.ethernetHeader.protocol = htons(ETHERNET_PROTO_ARP); + + arp_FullIPv4Packet.arpHeader.type = htons(ARP_HW_TYPE_ENET); + arp_FullIPv4Packet.arpHeader.protocol = htons(ETHERNET_PROTO_IPV4); + arp_FullIPv4Packet.arpHeader.operation = htons(ARP_OPERATION_REQUEST); + arp_FullIPv4Packet.arpHeader.hardAddrLen = 6; + arp_FullIPv4Packet.arpHeader.protoAddrLen = 4; + + arp_FullIPv4Packet.ipv4ARPData.hwSource = *hwAddress; + arp_FullIPv4Packet.ipv4ARPData.ipSource = netIF->ipv4Address; + arp_FullIPv4Packet.ipv4ARPData.hwDest = ethernet_Addr_Null; + arp_FullIPv4Packet.ipv4ARPData.ipDest = address; + + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + ARP_DumpHeader("Sending ", &arp_FullIPv4Packet.arpHeader); + } + + netIF->driver->Write((uint8_t *)&arp_FullIPv4Packet, sizeof(arp_FullIPv4Packet)); + +Exit: + return result; +} + + +int32_t ARP_AddStaticEntry(NetIF_t *netIF, IPv4_Addr_t address, const Ethernet_Addr_t *ethernetAddr) +{ + int32_t result = 0; + ARP_CacheEntry_t *entry; + + entry = GetReusableEntry(); + if (entry == NULL) + { + result = -1; + goto Exit; + } + entry->netIF = netIF; + entry->status = ARP_Entry_Static; + entry->ipv4Addr.addr = address.addr; + entry->ethernetAddr = *ethernetAddr; + entry->age = 0; + RTOS_MUTEX_UNLOCK(entry->mutex); + +Exit: + return result; +} + + +int32_t ARP_RemoveEntry(const NetIF_t *netIF, IPv4_Addr_t address) +{ + int32_t result = 0; + + + + return result; +} + + +void ARP_FlushCache(Bool_t flushStaticEntries) +{ + int32_t index; + ARP_CacheEntry_t *entry; + + for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) + { + entry = arp_CacheTable + index; + RTOS_MUTEX_LOCK(entry->mutex); + if ((entry->status == ARP_Entry_Static) && (!flushStaticEntries)) + { + RTOS_MUTEX_UNLOCK(entry->mutex); + continue; + } + entry->status = ARP_Entry_Free; + entry->ipv4Addr = ipv4_Addr_Any; + entry->ethernetAddr = ethernet_Addr_Null; + entry->age = 0; + RTOS_MUTEX_UNLOCK(entry->mutex); + } +} + + +void ARP_DisplayCache(void) +{ + int32_t index; + ARP_CacheEntry_t *entry = NULL; + + DEBUG_RAW(("ARP cache")); + DEBUG_RAW(("index dev MAC address type age IPv4 address")); + DEBUG_RAW(("----------------------------------------------------------")); + /* en0 00:11:22:33:44:55 dyn 10 163.157.128.131 */ + for (index = 0; index < ARP_CACHE_MAX_ENTRIES; index++) + { + entry = arp_CacheTable + index; + + DEBUG_RAW(("%2d %s%c %02x:%02x:%02x:%02x:%02x:%02x %8s %4d %d.%d.%d.%d", + index, + entry->status != ARP_Entry_Free ? entry->netIF->name : "--", + entry->status != ARP_Entry_Free ? entry->netIF->index + '0' : '-', + entry->ethernetAddr.MA0, + entry->ethernetAddr.MA1, + entry->ethernetAddr.MA2, + entry->ethernetAddr.MA3, + entry->ethernetAddr.MA4, + entry->ethernetAddr.MA5, + + arpEntryStatusText[entry->status], + entry->age, + + entry->ipv4Addr.IP0, + entry->ipv4Addr.IP1, + entry->ipv4Addr.IP2, + entry->ipv4Addr.IP3 + )); + } +} + +void ARP_DumpHeader(const char *prefix, ARP_Header_t *arpHeader) +{ + ARP_IPv4Data_t *ipv4ARP = NULL; + + if (arpHeader->protocol == htons(ETHERNET_PROTO_IPV4)) + { + ipv4ARP = (ARP_IPv4Data_t *)(arpHeader + 1); + + switch(ntohs(arpHeader->operation)) + { + case ARP_OPERATION_REQUEST: + DEBUG_RAW(("%sARP who-has %d.%d.%d.%d tell %02x:%02x:%02x:%02x:%02x:%02x", + prefix != NULL ? prefix : "", + + ipv4ARP->ipDest.IP0, + ipv4ARP->ipDest.IP1, + ipv4ARP->ipDest.IP2, + ipv4ARP->ipDest.IP3, + + ipv4ARP->hwSource.MA0, + ipv4ARP->hwSource.MA1, + ipv4ARP->hwSource.MA2, + ipv4ARP->hwSource.MA3, + ipv4ARP->hwSource.MA4, + ipv4ARP->hwSource.MA5 + )); + break; + + case ARP_OPERATION_REPLY: + DEBUG_RAW(("%sARP %d.%d.%d.%d is-at %02x:%02x:%02x:%02x:%02x:%02x", + prefix != NULL ? prefix : "", + + ipv4ARP->ipSource.IP0, + ipv4ARP->ipSource.IP1, + ipv4ARP->ipSource.IP2, + ipv4ARP->ipSource.IP3, + + ipv4ARP->hwSource.MA0, + ipv4ARP->hwSource.MA1, + ipv4ARP->hwSource.MA2, + ipv4ARP->hwSource.MA3, + ipv4ARP->hwSource.MA4, + ipv4ARP->hwSource.MA5 + )); + break; + + default: + break; + } + } + else + { + DEBUG_RAW(("%sARP: unsupported protocol %d", + prefix != NULL ? prefix : "", + arpHeader->protocol + )); + } +}
--- a/ARP.h Sun Jun 12 11:23:03 2011 +0000 +++ b/ARP.h Sun Jun 12 19:17:11 2011 +0000 @@ -59,12 +59,12 @@ extern Protocol_Handler_t arp; -CAPI int32_t ARP_ResolveIPv4Address(NetIF_t *netIF, IPv4_Addr_t address, Ethernet_Addr_t *ethernetAddr); -CAPI int32_t ARP_AddStaticEntry(NetIF_t *netIF, IPv4_Addr_t address, const Ethernet_Addr_t *ethernetAddr); -CAPI int32_t ARP_RemoveEntry(const NetIF_t *netIF, IPv4_Addr_t address); -CAPI void ARP_InvalidateCache(Bool_t flushStaticEntries); -CAPI void ARP_Timer(void); -CAPI void ARP_DisplayCache(void); -CAPI void ARP_DumpHeader(const char *prefix, ARP_Header_t *arpHeader); +int32_t ARP_ResolveIPv4Address(NetIF_t *netIF, IPv4_Addr_t address, Ethernet_Addr_t *ethernetAddr); +int32_t ARP_AddStaticEntry(NetIF_t *netIF, IPv4_Addr_t address, const Ethernet_Addr_t *ethernetAddr); +int32_t ARP_RemoveEntry(const NetIF_t *netIF, IPv4_Addr_t address); +void ARP_FlushCache(Bool_t flushStaticEntries); +void ARP_Timer(void); +void ARP_DisplayCache(void); +void ARP_DumpHeader(const char *prefix, ARP_Header_t *arpHeader); #endif /* __ARP_H__ */
--- a/Debug.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * $Id: Debug.c 26 2011-06-09 10:24:02Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-09 12:24:02 +0200 (jeu., 09 juin 2011) $ - * $Rev: 26 $ - * - * - * - * - * - */ - -#include "Debug.h" - - -Debug_LevelMask_t debug_LevelMask = DEBUG_LEVEL_WARNING | DEBUG_LEVEL_ERROR | DEBUG_LEVEL_PANIC; -Debug_ModuleMask_t debug_ModuleMask = DEBUG_MODULE_ALL; - - -void Debug_SetMasks(Debug_ModuleMask_t moduleMask, Debug_LevelMask_t levelMask) -{ - debug_LevelMask = levelMask; - debug_ModuleMask = moduleMask; -} - -const char *Debug_GetText(uint32_t level) -{ - char *result; - - switch(level) - { - case DEBUG_LEVEL_INFO: - result = "INFO"; - break; - - case DEBUG_LEVEL_WARNING: - result = "WARNING"; - break; - - case DEBUG_LEVEL_ERROR: - result = "ERROR"; - break; - - case DEBUG_LEVEL_PANIC: - result = "PANIC"; - break; - - case DEBUG_LEVEL_VERBOSE0: - result = "VERBOSE0"; - break; - - case DEBUG_LEVEL_VERBOSE1: - result = "VERBOSE1"; - break; - - case DEBUG_LEVEL_VERBOSE2: - result = "VERBOSE2"; - break; - - default: - result = "<unknown>"; - break; - } - - return result; -} - - -void Debug_DumpBufferHex(uint8_t *buffer, int32_t length) -{ - int32_t i, address, index, tmpIndex; - - index = 0; - address = 0; - while(index < length) - { - /* Print buffer relative address */ - DEBUG_RAW_NOCRLF(("%03X ", address)); - - /* Print hex bytes */ - for (i = 0; i < DEBUG_BUFFER_DUMP_LINE_LEN; i++) - { - tmpIndex = index + i; - if (tmpIndex < length) - { - DEBUG_RAW_NOCRLF(("%02X ", buffer[tmpIndex])); - } - else - { - DEBUG_RAW_NOCRLF((" ")); - } - } - - DEBUG_RAW_NOCRLF((" - ")); - - /* Print ascii chars */ - for (i = 0; i < DEBUG_BUFFER_DUMP_LINE_LEN; i++) - { - tmpIndex = index + i; - if (tmpIndex < length) - { - DEBUG_RAW_NOCRLF(("%c", buffer[tmpIndex] >= 32 ? buffer[tmpIndex] : '.')); - } - } - - index += DEBUG_BUFFER_DUMP_LINE_LEN; - address += DEBUG_BUFFER_DUMP_LINE_LEN; - - DEBUG_RAW_NOCRLF(("\r\n")); - } - -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Debug.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,113 @@ +/* + * $Id: Debug.c 26 2011-06-09 10:24:02Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-09 12:24:02 +0200 (jeu., 09 juin 2011) $ + * $Rev: 26 $ + * + * + * + * + * + */ + +#include "Debug.h" + + +Debug_LevelMask_t debug_LevelMask = DEBUG_LEVEL_WARNING | DEBUG_LEVEL_ERROR | DEBUG_LEVEL_PANIC; +Debug_ModuleMask_t debug_ModuleMask = DEBUG_MODULE_ALL; + + +void Debug_SetMasks(Debug_ModuleMask_t moduleMask, Debug_LevelMask_t levelMask) +{ + debug_LevelMask = levelMask; + debug_ModuleMask = moduleMask; +} + +const char *Debug_GetText(uint32_t level) +{ + char *result; + + switch(level) + { + case DEBUG_LEVEL_INFO: + result = "INFO"; + break; + + case DEBUG_LEVEL_WARNING: + result = "WARNING"; + break; + + case DEBUG_LEVEL_ERROR: + result = "ERROR"; + break; + + case DEBUG_LEVEL_PANIC: + result = "PANIC"; + break; + + case DEBUG_LEVEL_VERBOSE0: + result = "VERBOSE0"; + break; + + case DEBUG_LEVEL_VERBOSE1: + result = "VERBOSE1"; + break; + + case DEBUG_LEVEL_VERBOSE2: + result = "VERBOSE2"; + break; + + default: + result = "<unknown>"; + break; + } + + return result; +} + + +void Debug_DumpBufferHex(uint8_t *buffer, int32_t length) +{ + int32_t i, address, index, tmpIndex; + + index = 0; + address = 0; + while(index < length) + { + /* Print buffer relative address */ + DEBUG_RAW_NOCRLF(("%03X ", address)); + + /* Print hex bytes */ + for (i = 0; i < DEBUG_BUFFER_DUMP_LINE_LEN; i++) + { + tmpIndex = index + i; + if (tmpIndex < length) + { + DEBUG_RAW_NOCRLF(("%02X ", buffer[tmpIndex])); + } + else + { + DEBUG_RAW_NOCRLF((" ")); + } + } + + DEBUG_RAW_NOCRLF((" - ")); + + /* Print ascii chars */ + for (i = 0; i < DEBUG_BUFFER_DUMP_LINE_LEN; i++) + { + tmpIndex = index + i; + if (tmpIndex < length) + { + DEBUG_RAW_NOCRLF(("%c", buffer[tmpIndex] >= 32 ? buffer[tmpIndex] : '.')); + } + } + + index += DEBUG_BUFFER_DUMP_LINE_LEN; + address += DEBUG_BUFFER_DUMP_LINE_LEN; + + DEBUG_RAW_NOCRLF(("\r\n")); + } + +} +
--- a/Debug.h Sun Jun 12 11:23:03 2011 +0000 +++ b/Debug.h Sun Jun 12 19:17:11 2011 +0000 @@ -91,8 +91,8 @@ -CAPI const char *Debug_GetText(uint32_t level); -CAPI void Debug_DumpBufferHex(uint8_t *buffer, int32_t length); -CAPI void Debug_SetMasks(Debug_ModuleMask_t moduleMask, Debug_LevelMask_t levelMask); +const char *Debug_GetText(uint32_t level); +void Debug_DumpBufferHex(uint8_t *buffer, int32_t length); +void Debug_SetMasks(Debug_ModuleMask_t moduleMask, Debug_LevelMask_t levelMask); #endif /* __DEBUG_H__ */
--- a/Ethernet.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * $Id: Ethernet.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "Ethernet.h" -#include "Debug.h" -#include <string.h> - - -#define DEBUG_CURRENT_MODULE_NAME "Ethernet" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ETHERNET - - -static void Init(void); -static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler); -static int32_t RegisterAPI(Net_API_t *api); - -void Ethernet_Handler(NetIF_t *netIF, Packet_t *packet); - - -static Protocol_Handler_t *protocolHandlerTable[ETHERNET_PROTOCOL_MAX_COUNT]; -static int32_t protocolHandlerCount = 0; - -const Ethernet_Addr_t ethernet_Addr_Broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -const Ethernet_Addr_t ethernet_Addr_Null = {0, 0, 0, 0, 0, 0}; - - -Protocol_Handler_t ethernet = -{ - PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ - Protocol_ID_Ethernet, /* Protocol ID */ - PROTOCOL_NUMBER_NONE, /* Protocol number */ - Init, /* Protocol initialisation function */ - Ethernet_Handler, /* Protocol handler */ - RegisterProtocol, /* Protocol registration function */ - RegisterAPI, /* API registration function */ -}; - - -static Net_API_t *netAPITable[NET_API_PER_PROTOCOL_MAX_COUNT]; -static int32_t netAPICount = 0; - - -static void Init(void) -{ - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ethernet layer")); - memset(protocolHandlerTable, 0, sizeof(protocolHandlerTable)); - protocolHandlerCount = 0; - memset(netAPITable, 0, sizeof(netAPITable)); - netAPICount = 0; -} - - -static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler) -{ - int32_t result = 0; - - if (protocolHandlerCount >= ETHERNET_PROTOCOL_MAX_COUNT) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many protocols")); - result = -1; - mbedNet_LastError = mbedNetResult_TooManyRegisteredProtocols; - goto Exit; - } - - protocolHandlerTable[protocolHandlerCount] = protocolHandler; - protocolHandler->index = protocolHandlerCount; - protocolHandler->Init(); - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registered protocol %04X ethernet/%s", - ntohs(protocolHandler->protocolNumber), - protocol_IDNames[protocolHandler->protocolID] - )); - - protocolHandlerCount++; - -Exit: - return result; -} - - -static int32_t RegisterAPI(Net_API_t *netAPI) -{ - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registering %s API", api_IDNames[netAPI->apiID])); - netAPI->InitAPI(); - netAPITable[netAPICount] = netAPI; - netAPICount++; - return -1; -} - - -void Ethernet_Handler(NetIF_t *netIF, Packet_t *packet) -{ - int32_t protocolIndex, index; - Ethernet_Proto_t protocolNumber; - Protocol_Handler_t *protocolHandler; - Ethernet_Header_t *ethernetHeader = (Ethernet_Header_t *)packet->data; - - protocolNumber = ethernetHeader->protocol; - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("frame of %d bytes for protocol %04X (payload + %02d)", packet->length, ntohs(protocolNumber), sizeof(Ethernet_Header_t))); - //Debug_DumpBufferHex(packet, length); - - /* Process API if any */ - for (index = 0; index < netAPICount; index++) - { - netAPITable[index]->Hook(netIF, Protocol_ID_Ethernet, packet); - } - - for (protocolIndex = 0; protocolIndex < protocolHandlerCount; protocolIndex++) - { - protocolHandler = protocolHandlerTable[protocolIndex]; - if (protocolHandler->protocolNumber == protocolNumber) - { - DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE2, ("'%s' frame of %d bytes", protocol_IDNames[protocolHandler->protocolID], packet->length)); - NetIF_ProtoPush(packet, sizeof(Ethernet_Header_t), Protocol_ID_Ethernet); - protocolHandler->HandlePacket(netIF, packet); - goto Exit; - } - } - -Exit: - return; -} - -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ethernet.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,131 @@ +/* + * $Id: Ethernet.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "Ethernet.h" +#include "Debug.h" +#include <string.h> + + +#define DEBUG_CURRENT_MODULE_NAME "Ethernet" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ETHERNET + + +static void Init(void); +static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler); +static int32_t RegisterAPI(Net_API_t *api); +static void Handler(NetIF_t *netIF, Packet_t *packet); + + +static Protocol_Handler_t *protocolHandlerTable[ETHERNET_PROTOCOL_MAX_COUNT]; +static int32_t protocolHandlerCount = 0; + +const Ethernet_Addr_t ethernet_Addr_Broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const Ethernet_Addr_t ethernet_Addr_Null = {0, 0, 0, 0, 0, 0}; + + +Protocol_Handler_t ethernet = +{ + PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ + Protocol_ID_Ethernet, /* Protocol ID */ + PROTOCOL_NUMBER_NONE, /* Protocol number */ + Init, /* Protocol initialisation function */ + Handler, /* Protocol handler */ + RegisterProtocol, /* Protocol registration function */ + RegisterAPI, /* API registration function */ +}; + + +static Net_API_t *netAPITable[NET_API_PER_PROTOCOL_MAX_COUNT]; +static int32_t netAPICount = 0; + + +static void Init(void) +{ + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ethernet layer")); + memset(protocolHandlerTable, 0, sizeof(protocolHandlerTable)); + protocolHandlerCount = 0; + memset(netAPITable, 0, sizeof(netAPITable)); + netAPICount = 0; +} + + +static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler) +{ + int32_t result = 0; + + if (protocolHandlerCount >= ETHERNET_PROTOCOL_MAX_COUNT) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many protocols")); + result = -1; + mbedNet_LastError = mbedNetResult_TooManyRegisteredProtocols; + goto Exit; + } + + protocolHandlerTable[protocolHandlerCount] = protocolHandler; + protocolHandler->index = protocolHandlerCount; + protocolHandler->Init(); + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registered protocol %04X ethernet/%s", + ntohs(protocolHandler->protocolNumber), + protocol_IDNames[protocolHandler->protocolID] + )); + + protocolHandlerCount++; + +Exit: + return result; +} + + +static int32_t RegisterAPI(Net_API_t *netAPI) +{ + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registering %s API", api_IDNames[netAPI->apiID])); + netAPI->InitAPI(); + netAPITable[netAPICount] = netAPI; + netAPICount++; + return -1; +} + + +void Handler(NetIF_t *netIF, Packet_t *packet) +{ + int32_t protocolIndex, index; + Ethernet_Proto_t protocolNumber; + Protocol_Handler_t *protocolHandler; + Ethernet_Header_t *ethernetHeader; + + ethernetHeader = (Ethernet_Header_t *)packet->data; + protocolNumber = ethernetHeader->protocol; + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("frame of %d bytes for protocol %04X (payload + %02d)", packet->length, ntohs(protocolNumber), sizeof(Ethernet_Header_t))); + //Debug_DumpBufferHex(packet, length); + + /* Process API if any */ + for (index = 0; index < netAPICount; index++) + { + netAPITable[index]->Hook(netIF, Protocol_ID_Ethernet, packet); + } + + for (protocolIndex = 0; protocolIndex < protocolHandlerCount; protocolIndex++) + { + protocolHandler = protocolHandlerTable[protocolIndex]; + if (protocolHandler->protocolNumber == protocolNumber) + { + DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE0, ("'%s' frame of %d bytes", protocol_IDNames[protocolHandler->protocolID], packet->length)); + NetIF_ProtoPush(packet, sizeof(Ethernet_Header_t), Protocol_ID_Ethernet); + protocolHandler->HandlePacket(netIF, packet); + break; + } + } + return; +} + +
--- a/ICMPv4.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * $Id: ICMPv4.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "ICMPv4.h" -#include "Ethernet.h" -#include "Debug.h" - - -#define DEBUG_CURRENT_MODULE_NAME "ICMPv4" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ICMPV4 - - -static void Init(void); -static void Handler(NetIF_t *netIF, Packet_t *packet); - - -Protocol_Handler_t icmpv4 = -{ - PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ - Protocol_ID_ICMPv4, /* Protocol ID */ - IPV4_PROTO_ICMPV4, /* Protocol number */ - Init, /* Protocol initialisation function */ - Handler, /* Protocol handler */ - NULL, /* Protocol registration function */ - NULL, /* API registration function */ -}; - - -static void Init(void) -{ - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ICMPv4 layer")); -} - - -static void Handler(NetIF_t *netIF, Packet_t *packet) -{ - ICMPv4_Header_t *icmpv4Packet; - ICMPv4_Type_t type; - ICMPv4_Code_t code; - IPv4_Header_t *ipv4Header; - Ethernet_Header_t *ethernetHeader; - int32_t depth, lengthToSend; - - //Debug_DumpBufferHex(packet, length); - - - icmpv4Packet = (ICMPv4_Header_t *)packet->data; - type = icmpv4Packet->type; - code = icmpv4Packet->code; - code = code; - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("icmpv4 frame of %d bytes icmpv4(%02x, %02x) frame of %d bytes", - packet->length, - icmpv4Packet->type, - icmpv4Packet->code, - packet->length - )); - depth = packet->depth; - ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth]; - ethernetHeader = (Ethernet_Header_t *)packet->headerPtrTable[depth - 1]; - - switch(type) - { - case ICMPV4_TYPE_ECHO_REQUEST: - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - ICMPv4_DumpHeader("Got ", ipv4Header); - } - - ipv4Header->dest.addr = ipv4Header->source.addr; - ipv4Header->source.addr = netIF->ipv4Address.addr; - ethernetHeader->destination = ethernetHeader->source; - ethernetHeader->source = *((Ethernet_Addr_t *)netIF->driverParameter); - icmpv4Packet->type = ICMPV4_TYPE_ECHO_REPLY; - lengthToSend = packet->headerLenTable[depth - 1] + packet->headerLenTable[depth - 1] + ntohs(ipv4Header->totalLength); - icmpv4Packet->crc = 0; - icmpv4Packet->crc = ICMPv4_ComputeCRC(icmpv4Packet, ntohs(ipv4Header->totalLength) - packet->headerLenTable[depth]); - - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - ICMPv4_DumpHeader("Replying ", ipv4Header); - } - - netIF->driver->Write((uint8_t *)ethernetHeader, lengthToSend ); - - break; - - default: - break; - } -} - - -uint16_t ICMPv4_ComputeCRC(ICMPv4_Header_t *packet, int32_t length) -{ - uint32_t crc = 0, size = length; - uint16_t *data = (uint16_t *)packet, tmp; - - while(size > 1) - { - tmp = ntohs(*data); - crc += tmp; - data++; - size -= sizeof(uint16_t); - } - - if (size > 0) - { - tmp = (*((uint8_t *)data)) << 8; - crc += tmp; - } - - crc = (crc >> 16) + (crc & 0xFFFF); - if (crc & 0xFFFF0000) crc = (crc >> 16) + (crc & 0xFFFF); - - return htons((~crc) & 0xFFFF); -} - - -Bool_t ICMPv4_CheckCRC(ICMPv4_Header_t *packet, int32_t length) -{ - return True; -} - - -void ICMPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header) -{ - ICMPv4_Header_t *icmpv4Header = (ICMPv4_Header_t *)(ipv4Header + 1); - - switch(icmpv4Header->type) - { - case ICMPV4_TYPE_ECHO_REQUEST: - DEBUG_RAW(( - "%sICMPv4 echo request from %d.%d.%d.%d", - prefix != NULL ? prefix : "", - ipv4Header->source.IP0, - ipv4Header->source.IP1, - ipv4Header->source.IP2, - ipv4Header->source.IP3 - )); - break; - - case ICMPV4_TYPE_ECHO_REPLY: - DEBUG_RAW(( - "%sICMPv4 echo reply to %d.%d.%d.%d", - prefix != NULL ? prefix : "", - ipv4Header->dest.IP0, - ipv4Header->dest.IP1, - ipv4Header->dest.IP2, - ipv4Header->dest.IP3 - )); - break; - - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ICMPv4.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,162 @@ +/* + * $Id: ICMPv4.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "ICMPv4.h" +#include "Ethernet.h" +#include "Debug.h" + + +#define DEBUG_CURRENT_MODULE_NAME "ICMPv4" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_ICMPV4 + + +static void Init(void); +static void Handler(NetIF_t *netIF, Packet_t *packet); + + +Protocol_Handler_t icmpv4 = +{ + PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ + Protocol_ID_ICMPv4, /* Protocol ID */ + IPV4_PROTO_ICMPV4, /* Protocol number */ + Init, /* Protocol initialisation function */ + Handler, /* Protocol handler */ + NULL, /* Protocol registration function */ + NULL, /* API registration function */ +}; + + +static void Init(void) +{ + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing ICMPv4 layer")); +} + + +static void Handler(NetIF_t *netIF, Packet_t *packet) +{ + ICMPv4_Header_t *icmpv4Packet; + ICMPv4_Type_t type; + ICMPv4_Code_t code; + IPv4_Header_t *ipv4Header; + Ethernet_Header_t *ethernetHeader; + int32_t depth, lengthToSend; + + //Debug_DumpBufferHex(packet, length); + + icmpv4Packet = (ICMPv4_Header_t *)packet->data; + type = icmpv4Packet->type; + code = icmpv4Packet->code; + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("icmpv4 frame of %d bytes icmpv4(%02x, %02x) frame of %d bytes", + packet->length, + type, + code, + packet->length + )); + depth = packet->depth; + ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth]; + ethernetHeader = (Ethernet_Header_t *)packet->headerPtrTable[depth - 1]; + + switch(type) + { + case ICMPV4_TYPE_ECHO_REQUEST: + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + ICMPv4_DumpHeader("Got ", ipv4Header); + } + + ipv4Header->dest.addr = ipv4Header->source.addr; + ipv4Header->source.addr = netIF->ipv4Address.addr; + ethernetHeader->destination = ethernetHeader->source; + ethernetHeader->source = *((Ethernet_Addr_t *)netIF->driverParameter); + icmpv4Packet->type = ICMPV4_TYPE_ECHO_REPLY; + lengthToSend = packet->headerLenTable[depth - 1] + packet->headerLenTable[depth - 1] + ntohs(ipv4Header->totalLength); + icmpv4Packet->crc = 0; + icmpv4Packet->crc = ICMPv4_ComputeCRC(icmpv4Packet, ntohs(ipv4Header->totalLength) - packet->headerLenTable[depth]); + + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + ICMPv4_DumpHeader("Replying ", ipv4Header); + } + + netIF->driver->Write((uint8_t *)ethernetHeader, lengthToSend ); + + break; + + default: + break; + } +} + + +uint16_t ICMPv4_ComputeCRC(ICMPv4_Header_t *packet, int32_t length) +{ + uint32_t crc = 0, size = length; + uint16_t *data = (uint16_t *)packet, tmp; + + while(size > 1) + { + tmp = ntohs(*data); + crc += tmp; + data++; + size -= sizeof(uint16_t); + } + + if (size > 0) + { + tmp = (*((uint8_t *)data)) << 8; + crc += tmp; + } + + crc = (crc >> 16) + (crc & 0xFFFF); + if (crc & 0xFFFF0000) crc = (crc >> 16) + (crc & 0xFFFF); + + return htons((~crc) & 0xFFFF); +} + + +Bool_t ICMPv4_CheckCRC(ICMPv4_Header_t *packet, int32_t length) +{ + return True; +} + + +void ICMPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header) +{ + ICMPv4_Header_t *icmpv4Header = (ICMPv4_Header_t *)(ipv4Header + 1); + + switch(icmpv4Header->type) + { + case ICMPV4_TYPE_ECHO_REQUEST: + DEBUG_RAW(( + "%sICMPv4 echo request from %d.%d.%d.%d", + prefix != NULL ? prefix : "", + ipv4Header->source.IP0, + ipv4Header->source.IP1, + ipv4Header->source.IP2, + ipv4Header->source.IP3 + )); + break; + + case ICMPV4_TYPE_ECHO_REPLY: + DEBUG_RAW(( + "%sICMPv4 echo reply to %d.%d.%d.%d", + prefix != NULL ? prefix : "", + ipv4Header->dest.IP0, + ipv4Header->dest.IP1, + ipv4Header->dest.IP2, + ipv4Header->dest.IP3 + )); + break; + + } +}
--- a/ICMPv4.h Sun Jun 12 11:23:03 2011 +0000 +++ b/ICMPv4.h Sun Jun 12 19:17:11 2011 +0000 @@ -50,8 +50,8 @@ extern Protocol_Handler_t icmpv4; -CAPI uint16_t ICMPv4_ComputeCRC(ICMPv4_Header_t *packet, int32_t length); -CAPI Bool_t ICMPv4_CheckCRC(ICMPv4_Header_t *packet, int32_t length); -CAPI void ICMPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header); +uint16_t ICMPv4_ComputeCRC(ICMPv4_Header_t *packet, int32_t length); +Bool_t ICMPv4_CheckCRC(ICMPv4_Header_t *packet, int32_t length); +void ICMPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header); #endif /* __ICMPV4_H__ */
--- a/IPv4.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -/* - * $Id: IPv4.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "IPv4.h" -#include "Ethernet.h" -#include "Debug.h" -#include <string.h> - - -#define DEBUG_CURRENT_MODULE_NAME "IPv4" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_IPV4 - - -static void Init(void); -static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler); -static void Handler(NetIF_t *netIF, Packet_t *packet); - - -static Protocol_Handler_t *protocolHandlerTable[IPV4_PROTOCOL_MAX_COUNT]; -static int32_t protocolHandlerCount = 0; - - -const IPv4_Addr_t ipv4_Addr_Broadcast = { 255, 255, 255, 255 }; -const IPv4_Addr_t ipv4_Addr_Any = { 0, 0, 0, 0}; - - -Protocol_Handler_t ipv4 = -{ - PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ - Protocol_ID_IPv4, /* Protocol ID */ - htons(ETHERNET_PROTO_IPV4), /* Protocol number */ - Init, /* Protocol initialisation function */ - Handler, /* Protocol handler */ - RegisterProtocol, /* Protocol registration function */ - NULL, /* API registration function */ -}; - - -static void Init(void) -{ - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing IPv4 layer")); - protocolHandlerCount = 0; - memset(protocolHandlerTable, 0, sizeof(protocolHandlerTable)); -} - - -static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler) -{ - int32_t result = 0; - - if (protocolHandlerCount >= IPV4_PROTOCOL_MAX_COUNT) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many protocols")); - result = -1; - mbedNet_LastError = mbedNetResult_TooManyRegisteredProtocols; - goto Exit; - } - - protocolHandlerTable[protocolHandlerCount] = protocolHandler; - protocolHandler->index = protocolHandlerCount; - protocolHandler->Init(); - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registered protocol %2d ipv4/%s", - protocolHandler->protocolNumber, - protocol_IDNames[protocolHandler->protocolID] - )); - - protocolHandlerCount++; - -Exit: - return result; -} - - -static void Handler(NetIF_t *netIF, Packet_t *packet) -{ - int32_t protocolIndex, - payloadOffset; - Protocol_Number_t protocolNumber; - Protocol_Handler_t *protocolHandler; - IPv4_Header_t *ipv4Packet = (IPv4_Header_t *)packet->data; - - protocolNumber = ipv4Packet->protocol; - payloadOffset = ipv4Packet->ihl << 2; - - if ((ipv4Packet->dest.addr != netIF->ipv4Address.addr) && (ipv4Packet->dest.addr != netIF->ipv4Broadcast.addr)) - { - #if DEBUG_IPV4 - IPV4_DumpIPv4Header("Not for us ", ipv4Packet); - #endif /* DEBUG_IPV4 */ - goto Exit; - } - - #if DEBUG_IPV4 - IPv4_DumpIPv4Header("processing ", ipv4Packet); - #endif /* DEBUG_IPV4 */ - - //Debug_DumpBufferHex(packet, length); - for (protocolIndex = 0; protocolIndex < protocolHandlerCount; protocolIndex++) - { - protocolHandler = protocolHandlerTable[protocolIndex]; - if (protocolHandler->protocolNumber == protocolNumber) - { - NetIF_ProtoPush(packet, payloadOffset, Protocol_ID_IPv4); - protocolHandler->HandlePacket(netIF, packet); - goto Exit; - } - } - - #if DEBUG_IPV4 - IPV4_DumpIPv4Header("Not handled ", ipv4Packet); - #endif /* DEBUG_IPV4 */ - - -Exit: - return; -} - - -void IPv4_DumpIPv4Header(const char *prefix, IPv4_Header_t *ipv4Packet) -{ - DEBUG_RAW(("%sIPv4 %d.%d.%d.%d --> %d.%d.%d.%d ver:%01X ihl:%01X tos:%03d totlen:%04d id:%04X flags:%1d frag:%05d ttl:%3d proto:%03d crc:%04X" , - prefix != NULL ? prefix : "", - ipv4Packet->source.IP0, - ipv4Packet->source.IP1, - ipv4Packet->source.IP2, - ipv4Packet->source.IP3, - ipv4Packet->dest.IP0, - ipv4Packet->dest.IP1, - ipv4Packet->dest.IP2, - ipv4Packet->dest.IP3, - ipv4Packet->version, - ipv4Packet->ihl, - ipv4Packet->tos, - ntohs(ipv4Packet->totalLength), - ntohs(ipv4Packet->id), - (ntohs(ipv4Packet->fragmentFlags) & 0x1FFF) >> 13, - ntohs(ipv4Packet->fragmentFlags), - ipv4Packet->ttl, - ipv4Packet->protocol, - ntohs(ipv4Packet->crc) - )); -} - - -uint16_t IPv4_ComputeCRC(IPv4_Header_t *ipv4Header) -{ - uint32_t crc = 0, - length; - uint16_t *data; - - data = (uint16_t *)ipv4Header; - length = ipv4Header->ihl * 4; - - while(length > 1) - { - crc += *data; - data++; - length -= 2; - } - if (length) - { - crc += *(uint8_t *)(data); - } - - crc = (crc >> 16) + (crc & 0xFFFF); - crc = crc + (crc >> 16); - - return (uint16_t)(~crc); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IPv4.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,166 @@ +/* + * $Id: IPv4.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "IPv4.h" +#include "Ethernet.h" +#include "Debug.h" +#include <string.h> + + +#define DEBUG_CURRENT_MODULE_NAME "IPv4" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_IPV4 + + +static void Init(void); +static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler); +static void Handler(NetIF_t *netIF, Packet_t *packet); + + +static Protocol_Handler_t *protocolHandlerTable[IPV4_PROTOCOL_MAX_COUNT]; +static int32_t protocolHandlerCount = 0; + + +const IPv4_Addr_t ipv4_Addr_Broadcast = { 255, 255, 255, 255 }; +const IPv4_Addr_t ipv4_Addr_Any = { 0, 0, 0, 0}; + + +Protocol_Handler_t ipv4 = +{ + PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ + Protocol_ID_IPv4, /* Protocol ID */ + htons(ETHERNET_PROTO_IPV4), /* Protocol number */ + Init, /* Protocol initialisation function */ + Handler, /* Protocol handler */ + RegisterProtocol, /* Protocol registration function */ + NULL, /* API registration function */ +}; + + +static void Init(void) +{ + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing IPv4 layer")); + protocolHandlerCount = 0; + memset(protocolHandlerTable, 0, sizeof(protocolHandlerTable)); +} + + +static int32_t RegisterProtocol(Protocol_Handler_t *protocolHandler) +{ + int32_t result = 0; + + if (protocolHandlerCount >= IPV4_PROTOCOL_MAX_COUNT) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many protocols")); + result = -1; + mbedNet_LastError = mbedNetResult_TooManyRegisteredProtocols; + goto Exit; + } + + protocolHandlerTable[protocolHandlerCount] = protocolHandler; + protocolHandler->index = protocolHandlerCount; + protocolHandler->Init(); + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registered protocol %2d ipv4/%s", + protocolHandler->protocolNumber, + protocol_IDNames[protocolHandler->protocolID] + )); + + protocolHandlerCount++; + +Exit: + return result; +} + + +static void Handler(NetIF_t *netIF, Packet_t *packet) +{ + int32_t protocolIndex, + payloadOffset; + Protocol_Number_t protocolNumber; + Protocol_Handler_t *protocolHandler; + IPv4_Header_t *ipv4Packet; + + + ipv4Packet = (IPv4_Header_t *)packet->data; + protocolNumber = ipv4Packet->protocol; + payloadOffset = ipv4Packet->ihl << 2; + + + if ((ipv4Packet->dest.addr == netIF->ipv4Address.addr) || (ipv4Packet->dest.addr == netIF->ipv4Broadcast.addr)) + { + for (protocolIndex = 0; protocolIndex < protocolHandlerCount; protocolIndex++) + { + protocolHandler = protocolHandlerTable[protocolIndex]; + if (protocolHandler->protocolNumber == protocolNumber) + { + NetIF_ProtoPush(packet, payloadOffset, Protocol_ID_IPv4); + protocolHandler->HandlePacket(netIF, packet); + break; + } + } + } + + return; +} + + +void IPv4_DumpIPv4Header(const char *prefix, IPv4_Header_t *ipv4Packet) +{ + DEBUG_RAW(("%sIPv4 %d.%d.%d.%d --> %d.%d.%d.%d ver:%01X ihl:%01X tos:%03d totlen:%04d id:%04X flags:%1d frag:%05d ttl:%3d proto:%03d crc:%04X" , + prefix != NULL ? prefix : "", + ipv4Packet->source.IP0, + ipv4Packet->source.IP1, + ipv4Packet->source.IP2, + ipv4Packet->source.IP3, + ipv4Packet->dest.IP0, + ipv4Packet->dest.IP1, + ipv4Packet->dest.IP2, + ipv4Packet->dest.IP3, + ipv4Packet->version, + ipv4Packet->ihl, + ipv4Packet->tos, + ntohs(ipv4Packet->totalLength), + ntohs(ipv4Packet->id), + (ntohs(ipv4Packet->fragmentFlags) & 0x1FFF) >> 13, + ntohs(ipv4Packet->fragmentFlags), + ipv4Packet->ttl, + ipv4Packet->protocol, + ntohs(ipv4Packet->crc) + )); +} + + +uint16_t IPv4_ComputeCRC(IPv4_Header_t *ipv4Header) +{ + uint32_t crc = 0, + length; + uint16_t *data; + + data = (uint16_t *)ipv4Header; + length = ipv4Header->ihl * 4; + + while(length > 1) + { + crc += *data; + data++; + length -= 2; + } + if (length) + { + crc += *(uint8_t *)(data); + } + + crc = (crc >> 16) + (crc & 0xFFFF); + crc = crc + (crc >> 16); + + return (uint16_t)(~crc); +}
--- a/IPv4.h Sun Jun 12 11:23:03 2011 +0000 +++ b/IPv4.h Sun Jun 12 19:17:11 2011 +0000 @@ -51,8 +51,8 @@ extern Protocol_Handler_t ipv4; -CAPI void IPv4_DumpIPv4Header(const char *prefix, IPv4_Header_t *ipv4Packet); -CAPI uint16_t IPv4_ComputeCRC(IPv4_Header_t *ipv4Header); +void IPv4_DumpIPv4Header(const char *prefix, IPv4_Header_t *ipv4Packet); +uint16_t IPv4_ComputeCRC(IPv4_Header_t *ipv4Header); #endif /* __IPV4_H__ */
--- a/NetIF.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,428 +0,0 @@ -/* - * $Id: NetIF.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "NetIF.h" -#include "Ethernet.h" -#include "ARP.h" -#include "Debug.h" -#include <string.h> - - -#define DEBUG_CURRENT_MODULE_NAME "NetIF" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_NETIF - - -struct PeriodicFunctionTimer -{ - char *name; - PeriodicFunction_t function; - FunctionPeriod_t period; - int32_t age; -}; -typedef struct PeriodicFunctionTimer PeriodicFunctionTimer_t; - - -static NetIF_t netIF_Table[NETIF_MAX_COUNT]; -static int32_t netIF_Count = 0; -static RTOS_Mutex_t netIF_TableMutex; - -static PeriodicFunctionTimer_t netIF_PeriodicFunctionTable[NET_PERIODIC_FUNCTION_MAX_COUNT]; -static int32_t netIF_PeriodicFunctionCount = 0; -static RTOS_Mutex_t netIF_PeriodicFunctionTableMutex; - -static Bool_t netIFLayerInitialized = False; -static Packet_t rxPacket, - txPacket; -static int32_t gatewayNetIFIndex = -1; - - -static void NetIF_Init(void); - - -mbedNetResult_t mbedNet_LastError; -const char *protocol_IDNames[Protocol_ID_Count] = -{ - "Ethernet", - "ARP", - "IPv4", - "ICMPv4", - "UDPv4", - "TCPv4", -}; - - -const char *api_IDNames[API_ID_Count] = -{ - "sockets" -}; - - -static void NetIF_Init(void) -{ - mbedNet_LastError = mbedNetResult_Success; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing NetIF layer")); - - netIF_Count = 0; - memset(netIF_Table, 0, sizeof(netIF_Table)); - netIF_TableMutex = RTOS_MUTEX_CREATE(); - - netIF_PeriodicFunctionCount = 0; - memset(netIF_PeriodicFunctionTable, 0, sizeof(netIF_PeriodicFunctionTable)); - netIF_PeriodicFunctionTableMutex = RTOS_MUTEX_CREATE(); - - memset(&rxPacket, 0, sizeof(rxPacket)); - memset(&txPacket, 0, sizeof(txPacket)); - - gatewayNetIFIndex = -1; - - netIFLayerInitialized = True; -} - - -NetIF_t *NetIF_RegisterInterface(IPv4_Addr_t *address, IPv4_Addr_t *netmask, IPv4_Addr_t *gateway, NetIF_Driver_t *driver , void *driverParameter) -{ - NetIF_t *netIF = NULL; - - if (netIFLayerInitialized == False) - { - NetIF_Init(); - } - - if (netIF_Count >= NETIF_MAX_COUNT) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many interfaces registered")); - mbedNet_LastError = mbedNetResult_TooManyInterfaces; - goto Exit; - } - - if (driver == NULL) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Invalid driver specified")); - mbedNet_LastError = mbedNetResult_InvalidDriver; - goto Exit; - } - - RTOS_MUTEX_LOCK(netIF_TableMutex); - netIF = netIF_Table + netIF_Count; - netIF->index = netIF_Count; - netIF->name = "en"; - netIF->ipv4Address = *address; - netIF->ipv4Netmask = *netmask; - netIF->ipv4Network.addr = address->addr & netmask->addr; - netIF->ipv4Gateway = *gateway; - netIF->ipv4Broadcast.addr = (address->addr & netmask->addr) | (~netmask->addr); - netIF->driverParameter = driverParameter; - netIF->driver = driver; - netIF->driver->Init(netIF); - netIF->driver->protocolHandler->Init(); - - if (gateway != NULL) - { - gatewayNetIFIndex = netIF_Count; - } - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Interface '%s%d' registered (%d.%d.%d.%d/%d.%d.%d.%d gw %d.%d.%d.%d) using driver '%s'", - netIF->name, - netIF_Count, - netIF->ipv4Address.IP0, netIF->ipv4Address.IP1, netIF->ipv4Address.IP2, netIF->ipv4Address.IP3, - netIF->ipv4Netmask.IP0, netIF->ipv4Netmask.IP1, netIF->ipv4Netmask.IP2, netIF->ipv4Netmask.IP3, - netIF->ipv4Gateway.IP0, netIF->ipv4Gateway.IP1, netIF->ipv4Gateway.IP2, netIF->ipv4Gateway.IP3, - netIF->driver->name - )); - - netIF_Count++; - RTOS_MUTEX_UNLOCK(netIF_TableMutex); - -Exit: - return netIF; -} - - -int32_t NetIF_ProcessFrames(void) -{ - NetIF_Index_t netIFIndex; - NetIF_t *netIF; - int32_t result = 0, - readResult; - - DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE2, ("enter")); - RTOS_MUTEX_LOCK(netIF_TableMutex); - for (netIFIndex = 0; netIFIndex < netIF_Count; netIFIndex++) - { - netIF = netIF_Table + netIFIndex; - readResult = netIF->driver->Read(&rxPacket.data, &rxPacket.length); - if (readResult == 0) - { - rxPacket.depth = -1; - netIF->driver->protocolHandler->HandlePacket(netIF, &rxPacket); - } - } - RTOS_MUTEX_UNLOCK(netIF_TableMutex); - - DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE2, ("leave")); - return result; -} - - -int32_t NetIF_RegisterPeriodicFunction(char *name, PeriodicFunction_t function, FunctionPeriod_t period) -{ - int32_t result = 0; - PeriodicFunctionTimer_t *timerEntry; - - if (netIF_PeriodicFunctionCount >= NET_PERIODIC_FUNCTION_MAX_COUNT) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many periodic functions registered")); - mbedNet_LastError = mbedNetResult_TooManyPeriodicFunctions; - goto Exit; - } - - RTOS_MUTEX_LOCK(netIF_PeriodicFunctionTableMutex); - timerEntry = netIF_PeriodicFunctionTable + netIF_PeriodicFunctionCount; - timerEntry->name = name; - timerEntry->function = function; - timerEntry->period = period; - timerEntry->age = 0; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registered periodic function '%s' with period %d seconds", - name, - period - )); - - netIF_PeriodicFunctionCount++; - RTOS_MUTEX_UNLOCK(netIF_PeriodicFunctionTableMutex); - -Exit: - return result; -} - - -int32_t NetIF_ProcessTimers(int32_t elapsedTime) -{ - int32_t result = 0, - timerIndex; - PeriodicFunctionTimer_t *timerEntry; - static int64_t seconds = 0; - - seconds++; - - RTOS_MUTEX_LOCK(netIF_PeriodicFunctionTableMutex); - for (timerIndex = 0; timerIndex < netIF_PeriodicFunctionCount; timerIndex++) - { - timerEntry = netIF_PeriodicFunctionTable + timerIndex; - if (elapsedTime == 0) - { - timerEntry->age = 0; - continue; - } - - timerEntry->age += elapsedTime; - if (timerEntry->age >= timerEntry->period) - { - timerEntry->age = 0; - timerEntry->function(); - } - } - RTOS_MUTEX_UNLOCK(netIF_PeriodicFunctionTableMutex); - - return result; -} - - -int32_t NetIF_SendIPv4Packet(IPv4_Header_t *ipv4Header) -{ - int32_t result = -1, - mtu, - lengthToSend; - NetIF_Index_t netIFIndex; - NetIF_t *netIF = NULL; - Ethernet_Header_t *ethernetHeader; - Bool_t useGateway = False; - - RTOS_MUTEX_LOCK(netIF_TableMutex); - - /* Look for netif having same network */ - for (netIFIndex = 0; netIFIndex < netIF_Count; netIFIndex++) - { - netIF = netIF_Table + netIFIndex; - if ((netIF->ipv4Netmask.addr & ipv4Header->dest.addr) == netIF->ipv4Network.addr) break; - netIF = NULL; - } - - /* if not found, use gateway netif */ - if ((netIF == NULL) && (gatewayNetIFIndex >= 0)) - { - netIF = netIF_Table + gatewayNetIFIndex; - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("using gateway %d.%d.%d.%d to talk to %d.%d.%d.%d", - netIF->ipv4Gateway.IP0, - netIF->ipv4Gateway.IP1, - netIF->ipv4Gateway.IP2, - netIF->ipv4Gateway.IP3, - - ipv4Header->dest.IP0, - ipv4Header->dest.IP1, - ipv4Header->dest.IP2, - ipv4Header->dest.IP3 - )); - useGateway = True; - } - - /* Still no interface able to send, then return error */ - if (netIF == NULL) - { - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("No route to host")); - mbedNet_LastError = mbedNetResult_NoRouteToHost; - goto Exit; - } - - /* Prepare to send the IPv4 packet */ - mtu = netIF->driver->mtu; - - lengthToSend = (sizeof(Ethernet_Header_t) + ntohs(ipv4Header->totalLength)); - /* Check that total length doesn't exceed MTU */ - if (lengthToSend > mtu) - { - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Too much data: %d bytes", lengthToSend)); - mbedNet_LastError = mbedNetResult_TooMuchData; - goto Exit; - } - - /* Set source address and compute checksum of IPv4 header */ - ipv4Header->source.addr = netIF->ipv4Address.addr; - ipv4Header->crc = 0; - ipv4Header->crc = IPv4_ComputeCRC(ipv4Header); - - /* Prepare packet with ethernet data */ - txPacket.depth = -1; - txPacket.length = lengthToSend; - txPacket.data = netIF->driver->GetTxBuffer(); - ethernetHeader = (Ethernet_Header_t *)txPacket.data; - - /* Copy destination MAC address */ - if (useGateway) - { - while (ARP_ResolveIPv4Address(netIF, netIF->ipv4Gateway, ðernetHeader->destination) == -1) - { - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("%d.%d.%d.%d not in ARP cache", - netIF->ipv4Gateway.IP0, - netIF->ipv4Gateway.IP1, - netIF->ipv4Gateway.IP2, - netIF->ipv4Gateway.IP3 - )); - NetIF_ProcessFrames(); - } - } - else - { - while (ARP_ResolveIPv4Address(netIF, ipv4Header->dest, ðernetHeader->destination)) - { - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("%d.%d.%d.%d not in ARP cache", - ipv4Header->dest.IP0, - ipv4Header->dest.IP1, - ipv4Header->dest.IP2, - ipv4Header->dest.IP3 - )); - NetIF_ProcessFrames(); - } - } - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("IPv4 sending %d bytes %d.%d.%d.%d --> %d.%d.%d.%d using %s%d", - ntohs(ipv4Header->totalLength), - - ipv4Header->source.IP0, - ipv4Header->source.IP1, - ipv4Header->source.IP2, - ipv4Header->source.IP3, - - ipv4Header->dest.IP0, - ipv4Header->dest.IP1, - ipv4Header->dest.IP2, - ipv4Header->dest.IP3, - - netIF->name, - netIF->index - - )); - - /* Copy source MAC address */ - memcpy(ðernetHeader->source, (uint8_t *)netIF->driverParameter, 6); - ethernetHeader->protocol = htons(ETHERNET_PROTO_IPV4); - NetIF_ProtoPush(&txPacket, sizeof(Ethernet_Header_t), Protocol_ID_Ethernet); - - /* Copy ethernet payload */ - //ipv4Header = (IPv4_Header_t *)txPacket.data; - memcpy(txPacket.data, ipv4Header, ntohs(ipv4Header->totalLength)); - NetIF_ProtoPop(&txPacket); - - /* Send packet */ - result = netIF->driver->Write(txPacket.data, txPacket.length); - -Exit: - RTOS_MUTEX_UNLOCK(netIF_TableMutex); - return result; -} - - -void NetIF_ProtoPop(Packet_t *packet) -{ - int32_t depth, headerSize, index; - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); - if (packet->depth >= 0) - { - depth = packet->depth; - headerSize = packet->headerLenTable[depth]; - - packet->data -= headerSize; - packet->length += headerSize; - - packet->depth--; - } - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > Decapsulate: ")); - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE1) - { - for (index = 0; index <= packet->depth; index++) - { - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > %d %s header:%d bytes", index, protocol_IDNames[packet->protocolTable[index]], packet->headerLenTable[index])); - } - } - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); -} - - -void NetIF_ProtoPush(Packet_t *packet, int32_t headerSize, Protocol_ID_t protocol) -{ - int32_t depth, index; - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); - - packet->depth++; - depth = packet->depth; - - packet->headerPtrTable[depth] = packet->data; - packet->headerLenTable[depth] = headerSize; - packet->protocolTable[depth] = protocol; - packet->data += headerSize; - packet->length -= headerSize; - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > Encapsulate: ")); - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE1) - { - for (index = 0; index <= depth; index++) - { - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > %d %s header:%d bytes", index, protocol_IDNames[packet->protocolTable[index]], packet->headerLenTable[index])); - } - } - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NetIF.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,466 @@ +/* + * $Id: NetIF.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "NetIF.h" +#include "Ethernet.h" +#include "ARP.h" +#include "Debug.h" +#include <string.h> + + +#define DEBUG_CURRENT_MODULE_NAME "NetIF" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_NETIF + + +struct PeriodicFunctionTimer +{ + char *name; + PeriodicFunction_t function; + FunctionPeriod_t period; + int32_t age; +}; +typedef struct PeriodicFunctionTimer PeriodicFunctionTimer_t; + + +static NetIF_t netIF_Table[NETIF_MAX_COUNT]; +static int32_t netIF_Count = 0; +static RTOS_Mutex_t netIF_TableMutex; + +static PeriodicFunctionTimer_t netIF_PeriodicFunctionTable[NET_PERIODIC_FUNCTION_MAX_COUNT]; +static int32_t netIF_PeriodicFunctionCount = 0; +static RTOS_Mutex_t netIF_PeriodicFunctionTableMutex; + +static Bool_t netIFLayerInitialized = False; +static Packet_t rxPacket, + txPacket; +static int32_t gatewayNetIFIndex = -1; + + +static void NetIF_Init(void); + + +mbedNetResult_t mbedNet_LastError; +const char *protocol_IDNames[Protocol_ID_Count] = +{ + "Ethernet", + "ARP", + "IPv4", + "ICMPv4", + "UDPv4", + "TCPv4", +}; + + +const char *api_IDNames[API_ID_Count] = +{ + "sockets" +}; + + +static void NetIF_Init(void) +{ + mbedNet_LastError = mbedNetResult_Success; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing NetIF layer")); + + netIF_Count = 0; + memset(netIF_Table, 0, sizeof(netIF_Table)); + netIF_TableMutex = RTOS_MUTEX_CREATE(); + + netIF_PeriodicFunctionCount = 0; + memset(netIF_PeriodicFunctionTable, 0, sizeof(netIF_PeriodicFunctionTable)); + netIF_PeriodicFunctionTableMutex = RTOS_MUTEX_CREATE(); + + memset(&rxPacket, 0, sizeof(rxPacket)); + memset(&txPacket, 0, sizeof(txPacket)); + + gatewayNetIFIndex = -1; + + netIFLayerInitialized = True; +} + + +NetIF_t *NetIF_RegisterInterface(IPv4_Addr_t *address, IPv4_Addr_t *netmask, IPv4_Addr_t *gateway, NetIF_Driver_t *driver , void *driverParameter) +{ + NetIF_t *netIF = NULL; + + if (netIFLayerInitialized == False) + { + NetIF_Init(); + } + + if (netIF_Count >= NETIF_MAX_COUNT) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many interfaces registered")); + mbedNet_LastError = mbedNetResult_TooManyInterfaces; + goto Exit; + } + + if (driver == NULL) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Invalid driver specified")); + mbedNet_LastError = mbedNetResult_InvalidDriver; + goto Exit; + } + + RTOS_MUTEX_LOCK(netIF_TableMutex); + netIF = netIF_Table + netIF_Count; + netIF->index = netIF_Count; + netIF->name = "en"; + netIF->ipv4Address = *address; + netIF->ipv4Netmask = *netmask; + netIF->ipv4Network.addr = address->addr & netmask->addr; + netIF->ipv4Gateway = *gateway; + netIF->ipv4Broadcast.addr = (address->addr & netmask->addr) | (~netmask->addr); + netIF->driverParameter = driverParameter; + netIF->driver = driver; + netIF->driver->Init(netIF); + netIF->driver->protocolHandler->Init(); + + if (gateway != NULL) + { + gatewayNetIFIndex = netIF_Count; + } + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Interface '%s%d' registered (%d.%d.%d.%d/%d.%d.%d.%d gw %d.%d.%d.%d) using driver '%s'", + netIF->name, + netIF_Count, + netIF->ipv4Address.IP0, netIF->ipv4Address.IP1, netIF->ipv4Address.IP2, netIF->ipv4Address.IP3, + netIF->ipv4Netmask.IP0, netIF->ipv4Netmask.IP1, netIF->ipv4Netmask.IP2, netIF->ipv4Netmask.IP3, + netIF->ipv4Gateway.IP0, netIF->ipv4Gateway.IP1, netIF->ipv4Gateway.IP2, netIF->ipv4Gateway.IP3, + netIF->driver->name + )); + + netIF_Count++; + RTOS_MUTEX_UNLOCK(netIF_TableMutex); + +Exit: + return netIF; +} + + +int32_t NetIF_ProcessFrames(void) +{ + NetIF_Index_t netIFIndex; + NetIF_t *netIF; + int32_t result = 0, + readResult; + + DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE2, ("enter")); + RTOS_MUTEX_LOCK(netIF_TableMutex); + for (netIFIndex = 0; netIFIndex < netIF_Count; netIFIndex++) + { + netIF = netIF_Table + netIFIndex; + readResult = netIF->driver->Read(&rxPacket.data, &rxPacket.length); + if (readResult == 0) + { + rxPacket.depth = -1; + netIF->driver->protocolHandler->HandlePacket(netIF, &rxPacket); + } + } + RTOS_MUTEX_UNLOCK(netIF_TableMutex); + + DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE2, ("leave")); + return result; +} + + +int32_t NetIF_RegisterPeriodicFunction(char *name, PeriodicFunction_t function, FunctionPeriod_t period) +{ + int32_t result = 0; + PeriodicFunctionTimer_t *timerEntry; + + if (netIF_PeriodicFunctionCount >= NET_PERIODIC_FUNCTION_MAX_COUNT) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Too many periodic functions registered")); + mbedNet_LastError = mbedNetResult_TooManyPeriodicFunctions; + goto Exit; + } + + RTOS_MUTEX_LOCK(netIF_PeriodicFunctionTableMutex); + timerEntry = netIF_PeriodicFunctionTable + netIF_PeriodicFunctionCount; + timerEntry->name = name; + timerEntry->function = function; + timerEntry->period = period; + timerEntry->age = 0; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registered periodic function '%s' with period %d seconds", + name, + period + )); + + netIF_PeriodicFunctionCount++; + RTOS_MUTEX_UNLOCK(netIF_PeriodicFunctionTableMutex); + +Exit: + return result; +} + + +int32_t NetIF_ProcessTimers(int32_t elapsedTime) +{ + int32_t result = 0, + timerIndex; + PeriodicFunctionTimer_t *timerEntry; + static int64_t seconds = 0; + + seconds++; + + RTOS_MUTEX_LOCK(netIF_PeriodicFunctionTableMutex); + for (timerIndex = 0; timerIndex < netIF_PeriodicFunctionCount; timerIndex++) + { + timerEntry = netIF_PeriodicFunctionTable + timerIndex; + if (elapsedTime == 0) + { + timerEntry->age = 0; + continue; + } + + timerEntry->age += elapsedTime; + if (timerEntry->age >= timerEntry->period) + { + timerEntry->age = 0; + timerEntry->function(); + } + } + RTOS_MUTEX_UNLOCK(netIF_PeriodicFunctionTableMutex); + + return result; +} + + +int32_t NetIF_SendIPv4Packet(IPv4_Header_t *ipv4Header) +{ + int32_t result = -1, + mtu, + lengthToSend; + NetIF_Index_t netIFIndex; + NetIF_t *netIF = NULL; + Ethernet_Header_t *ethernetHeader; + Bool_t useGateway = False; + + RTOS_MUTEX_LOCK(netIF_TableMutex); + + /* Look for netif having same network */ + for (netIFIndex = 0; netIFIndex < netIF_Count; netIFIndex++) + { + netIF = netIF_Table + netIFIndex; + if ( (netIF->up) && ((netIF->ipv4Netmask.addr & ipv4Header->dest.addr) == netIF->ipv4Network.addr)) break; + netIF = NULL; + } + + /* if not found, use gateway netif */ + if ((netIF == NULL) && (gatewayNetIFIndex >= 0)) + { + netIF = netIF_Table + gatewayNetIFIndex; + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("using gateway %d.%d.%d.%d to talk to %d.%d.%d.%d", + netIF->ipv4Gateway.IP0, + netIF->ipv4Gateway.IP1, + netIF->ipv4Gateway.IP2, + netIF->ipv4Gateway.IP3, + + ipv4Header->dest.IP0, + ipv4Header->dest.IP1, + ipv4Header->dest.IP2, + ipv4Header->dest.IP3 + )); + useGateway = True; + } + + /* Still no interface able to send, then return error */ + if (netIF == NULL) + { + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("No route to host")); + mbedNet_LastError = mbedNetResult_NoRouteToHost; + goto Exit; + } + + /* Prepare to send the IPv4 packet */ + mtu = netIF->driver->mtu; + + lengthToSend = (sizeof(Ethernet_Header_t) + ntohs(ipv4Header->totalLength)); + /* Check that total length doesn't exceed MTU */ + if (lengthToSend > mtu) + { + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Too much data: %d bytes", lengthToSend)); + mbedNet_LastError = mbedNetResult_TooMuchData; + goto Exit; + } + + /* Set source address and compute checksum of IPv4 header */ + ipv4Header->source.addr = netIF->ipv4Address.addr; + ipv4Header->crc = 0; + ipv4Header->crc = IPv4_ComputeCRC(ipv4Header); + + /* Prepare packet with ethernet data */ + txPacket.depth = -1; + txPacket.length = lengthToSend; + txPacket.data = netIF->driver->GetTxBuffer(); + ethernetHeader = (Ethernet_Header_t *)txPacket.data; + + /* Copy destination MAC address */ + if (useGateway) + { + while (ARP_ResolveIPv4Address(netIF, netIF->ipv4Gateway, ðernetHeader->destination) == -1) + { + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("%d.%d.%d.%d not in ARP cache", + netIF->ipv4Gateway.IP0, + netIF->ipv4Gateway.IP1, + netIF->ipv4Gateway.IP2, + netIF->ipv4Gateway.IP3 + )); + NetIF_ProcessFrames(); + } + } + else + { + while (ARP_ResolveIPv4Address(netIF, ipv4Header->dest, ðernetHeader->destination)) + { + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("%d.%d.%d.%d not in ARP cache", + ipv4Header->dest.IP0, + ipv4Header->dest.IP1, + ipv4Header->dest.IP2, + ipv4Header->dest.IP3 + )); + NetIF_ProcessFrames(); + } + } + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("IPv4 sending %d bytes %d.%d.%d.%d --> %d.%d.%d.%d using %s%d", + ntohs(ipv4Header->totalLength), + + ipv4Header->source.IP0, + ipv4Header->source.IP1, + ipv4Header->source.IP2, + ipv4Header->source.IP3, + + ipv4Header->dest.IP0, + ipv4Header->dest.IP1, + ipv4Header->dest.IP2, + ipv4Header->dest.IP3, + + netIF->name, + netIF->index + + )); + + /* Copy source MAC address */ + memcpy(ðernetHeader->source, (uint8_t *)netIF->driverParameter, 6); + ethernetHeader->protocol = htons(ETHERNET_PROTO_IPV4); + NetIF_ProtoPush(&txPacket, sizeof(Ethernet_Header_t), Protocol_ID_Ethernet); + + /* Copy ethernet payload */ + //ipv4Header = (IPv4_Header_t *)txPacket.data; + memcpy(txPacket.data, ipv4Header, ntohs(ipv4Header->totalLength)); + NetIF_ProtoPop(&txPacket); + + /* Send packet */ + result = netIF->driver->Write(txPacket.data, txPacket.length); + +Exit: + RTOS_MUTEX_UNLOCK(netIF_TableMutex); + return result; +} + + +int32_t NetIF_Up(NetIF_t *netIF) +{ + int32_t result = 0; + + if (netIF->up) + { + result = -1; + mbedNet_LastError = mbedNetResult_InterfaceAlreadyUp; + goto Exit; + } + + netIF->driver->Enable(); + netIF->up = True; + +Exit: + return result; +} + + +int32_t NetIF_Down(NetIF_t *netIF) +{ + int32_t result = 0; + + if (!netIF->up) + { + result = -1; + mbedNet_LastError = mbedNetResult_InterfaceAlreadyDown; + goto Exit; + } + + netIF->driver->Disable(); + netIF->up = False; + +Exit: + return result; +} + + +void NetIF_ProtoPop(Packet_t *packet) +{ + static int32_t depth, headerSize, index; + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); + if (packet->depth >= 0) + { + depth = packet->depth; + headerSize = packet->headerLenTable[depth]; + + packet->data -= headerSize; + packet->length += headerSize; + + packet->depth--; + } + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > Decapsulate: ")); + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE1) + { + for (index = 0; index <= packet->depth; index++) + { + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > %d %s header:%d bytes", index, protocol_IDNames[packet->protocolTable[index]], packet->headerLenTable[index])); + } + } + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); +} + + +void NetIF_ProtoPush(Packet_t *packet, int32_t headerSize, Protocol_ID_t protocol) +{ + static int32_t depth, index; + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); + + packet->depth++; + depth = packet->depth; + + packet->headerPtrTable[depth] = packet->data; + packet->headerLenTable[depth] = headerSize; + packet->protocolTable[depth] = protocol; + packet->data += headerSize; + packet->length -= headerSize; + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > Encapsulate: ")); + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE1) + { + for (index = 0; index <= depth; index++) + { + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (" > %d %s header:%d bytes", index, protocol_IDNames[packet->protocolTable[index]], packet->headerLenTable[index])); + } + } + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, (">>> Packet depth %d with %d bytes", packet->depth, packet->length)); +} +
--- a/NetIF.h Sun Jun 12 11:23:03 2011 +0000 +++ b/NetIF.h Sun Jun 12 19:17:11 2011 +0000 @@ -20,10 +20,14 @@ typedef struct IPv4_Header IPv4_Header_t; struct NetIF; typedef struct NetIF NetIF_t; -typedef CAPI int32_t (*enet_drv_init_t)(NetIF_t *); -typedef CAPI int32_t (*enet_drv_read_t)(uint8_t **, int32_t *); -typedef CAPI int32_t (*enet_drv_write_t)(uint8_t *, int32_t); -typedef CAPI uint8_t *(*enet_drv_get_tx_buffer_t)(void); +struct Protocol_Handler; +typedef struct Protocol_Handler Protocol_Handler_t; +typedef int32_t (*enet_drv_init_t)(NetIF_t *); +typedef int32_t (*enet_drv_read_t)(uint8_t **, int32_t *); +typedef int32_t (*enet_drv_write_t)(uint8_t *, int32_t); +typedef void (*enet_drv_enable_t)(void); +typedef void (*enet_drv_disable_t)(void); +typedef uint8_t *(*enet_drv_get_tx_buffer_t)(void); @@ -69,13 +73,11 @@ typedef struct Net_API Net_API_t; -struct Protocol_Handler; -typedef struct Protocol_Handler Protocol_Handler_t; -typedef CAPI int32_t (*Protocol_RegisterFunction_t)(Protocol_Handler_t *); -typedef CAPI void (*Protocol_HandlerFunction_t)(NetIF_t *, Packet_t *); -typedef CAPI void (*Protocol_InitFunction_t)(void); -typedef CAPI int32_t (*API_RegisterFunction_t)(Net_API_t *); -typedef CAPI void (*PeriodicFunction_t)(void); +typedef int32_t (*Protocol_RegisterFunction_t)(Protocol_Handler_t *); +typedef void (*Protocol_HandlerFunction_t)(NetIF_t *, Packet_t *); +typedef void (*Protocol_InitFunction_t)(void); +typedef int32_t (*API_RegisterFunction_t)(Net_API_t *); +typedef void (*PeriodicFunction_t)(void); typedef int16_t FunctionPeriod_t; @@ -83,11 +85,13 @@ struct NetIF_Driver { char *name; - enet_drv_init_t Init; - enet_drv_read_t Read; + enet_drv_init_t Init; + enet_drv_read_t Read; enet_drv_write_t Write; + enet_drv_enable_t Enable; + enet_drv_disable_t Disable; enet_drv_get_tx_buffer_t GetTxBuffer; - Protocol_Handler_t *protocolHandler; + Protocol_Handler_t *protocolHandler; uint16_t mtu; }; typedef struct NetIF_Driver NetIF_Driver_t; @@ -114,15 +118,16 @@ typedef int32_t NetIF_Index_t; struct NetIF { - NetIF_Index_t index; + NetIF_Index_t index; const char *name; IPv4_Addr_t ipv4Address; IPv4_Addr_t ipv4Netmask; IPv4_Addr_t ipv4Network; IPv4_Addr_t ipv4Gateway; IPv4_Addr_t ipv4Broadcast; - NetIF_Driver_t *driver; - void *driverParameter; + NetIF_Driver_t *driver; + void *driverParameter; + Bool_t up; }; @@ -130,14 +135,14 @@ extern const char *protocol_IDNames[Protocol_ID_Count]; -CAPI NetIF_t *NetIF_RegisterInterface(IPv4_Addr_t *address, IPv4_Addr_t *netmask, IPv4_Addr_t *gateway, NetIF_Driver_t *driver, void *driverParameter); -CAPI int32_t NetIF_ProcessFrames(void); -CAPI int32_t NetIF_RegisterPeriodicFunction(char *name, PeriodicFunction_t function, FunctionPeriod_t period); -CAPI int32_t NetIF_ProcessTimers(int32_t elapsedTime); -CAPI int32_t NetIF_SendIPv4Packet(IPv4_Header_t *ipv4Header); -CAPI int32_t NetIF_Enable(NetIF_t *netIF); -CAPI int32_t NetIF_Disable(NetIF_t *netIF); -CAPI void NetIF_ProtoPop(Packet_t *packet); -CAPI void NetIF_ProtoPush(Packet_t *packet, int32_t headerSize, Protocol_ID_t protocol); +NetIF_t *NetIF_RegisterInterface(IPv4_Addr_t *address, IPv4_Addr_t *netmask, IPv4_Addr_t *gateway, NetIF_Driver_t *driver, void *driverParameter); +int32_t NetIF_ProcessFrames(void); +int32_t NetIF_RegisterPeriodicFunction(char *name, PeriodicFunction_t function, FunctionPeriod_t period); +int32_t NetIF_ProcessTimers(int32_t elapsedTime); +int32_t NetIF_SendIPv4Packet(IPv4_Header_t *ipv4Header); +int32_t NetIF_Up(NetIF_t *netIF); +int32_t NetIF_Down(NetIF_t *netIF); +void NetIF_ProtoPop(Packet_t *packet); +void NetIF_ProtoPush(Packet_t *packet, int32_t headerSize, Protocol_ID_t protocol); #endif /* __NETIF_H__ */
--- a/Queue.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * $Id: Queue.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "Queue.h" -#include "Debug.h" -#include <stdlib.h> -#include <string.h> - - -#define DEBUG_CURRENT_MODULE_NAME "Queue" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_QUEUE - - -Queue_t *Queue_Alloc(int16_t size) -{ - Queue_t *queue; - - queue = (Queue_t *)malloc(sizeof(Queue_t)); - if (queue == NULL) - { - DEBUG_MODULE(DEBUG_LEVEL_WARNING, ("Not enough memory")); - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - goto Exit; - } - memset(queue, 0, sizeof(Queue_t)); - - queue->size = size + 1; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Allocated queue of %d items", queue->popIndex, queue->pushIndex, size)); - -Exit: - return queue; -} - - -int32_t Queue_Push(Queue_t *queue, void *entry) -{ - int32_t result = 0; - int16_t index; - - if (queue->popIndex == ((queue->pushIndex + 1) % queue->size)) - { - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Queue is full", queue->popIndex, queue->pushIndex)); - result = -1; - mbedNet_LastError = mbedNetResult_QueueFull; - goto Exit; - } - - index = queue->pushIndex; - queue->entries[index] = entry; - index++; - if (index == queue->size) index = 0; - queue->pushIndex = index; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Pushing one entry from queue", queue->popIndex, queue->pushIndex)); - -Exit: - return result; -} - - -int32_t Queue_Pop(Queue_t *queue, void **entry) -{ - int32_t result = 0; - int16_t index; - - if (queue->popIndex == queue->pushIndex) - { - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Queue is empty", queue->popIndex, queue->pushIndex)); - result = -1; - mbedNet_LastError = mbedNetResult_QueueEmpty; - goto Exit; - } - - - index = queue->popIndex; - *entry = queue->entries[index]; - index++; - if (index == queue->size) index = 0; - queue->popIndex = index; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Popping one entry from queue", queue->popIndex, queue->pushIndex)); - -Exit: - return result; -} - - -int32_t Queue_Peek(Queue_t *queue, void **entry) -{ - int32_t result = 0; - int16_t index; - - if (queue->popIndex == queue->pushIndex) - { - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Queue is empty", queue->popIndex, queue->pushIndex)); - result = -1; - mbedNet_LastError = mbedNetResult_QueueEmpty; - goto Exit; - } - - index = queue->popIndex; - *entry = queue->entries[index]; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Peeking first entry from queue", queue->popIndex, queue->pushIndex)); - -Exit: - return result; -} - - -int32_t Queue_Free(Queue_t *queue) -{ - int32_t result = 0; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Free queue", queue->popIndex, queue->pushIndex)); - free(queue); - - return result; -} - - -Bool_t Queue_IsEmpty(const Queue_t *queue) -{ - return (queue->popIndex == queue->pushIndex) ? True : False; -} - - -Bool_t Queue_IsFull(const Queue_t *queue) -{ - return (queue->popIndex == ((queue->pushIndex + 1) % queue->size)) ? True : False; -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Queue.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,142 @@ +/* + * $Id: Queue.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "Queue.h" +#include "Debug.h" +#include <stdlib.h> +#include <string.h> + + +#define DEBUG_CURRENT_MODULE_NAME "Queue" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_QUEUE + + +Queue_t *Queue_Alloc(int16_t size) +{ + Queue_t *queue; + + queue = (Queue_t *)malloc(sizeof(Queue_t)); + if (queue == NULL) + { + DEBUG_MODULE(DEBUG_LEVEL_WARNING, ("Not enough memory")); + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + goto Exit; + } + memset(queue, 0, sizeof(Queue_t)); + + queue->size = size + 1; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Allocated queue of %d items", queue->popIndex, queue->pushIndex, size)); + +Exit: + return queue; +} + + +int32_t Queue_Push(Queue_t *queue, void *entry) +{ + int32_t result = 0; + int16_t index; + + if (queue->popIndex == ((queue->pushIndex + 1) % queue->size)) + { + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Queue is full", queue->popIndex, queue->pushIndex)); + result = -1; + mbedNet_LastError = mbedNetResult_QueueFull; + goto Exit; + } + + index = queue->pushIndex; + queue->entries[index] = entry; + index++; + if (index == queue->size) index = 0; + queue->pushIndex = index; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Pushing one entry from queue", queue->popIndex, queue->pushIndex)); + +Exit: + return result; +} + + +int32_t Queue_Pop(Queue_t *queue, void **entry) +{ + int32_t result = 0; + int16_t index; + + if (queue->popIndex == queue->pushIndex) + { + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Queue is empty", queue->popIndex, queue->pushIndex)); + result = -1; + mbedNet_LastError = mbedNetResult_QueueEmpty; + goto Exit; + } + + + index = queue->popIndex; + *entry = queue->entries[index]; + index++; + if (index == queue->size) index = 0; + queue->popIndex = index; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Popping one entry from queue", queue->popIndex, queue->pushIndex)); + +Exit: + return result; +} + + +int32_t Queue_Peek(Queue_t *queue, void **entry) +{ + int32_t result = 0; + int16_t index; + + if (queue->popIndex == queue->pushIndex) + { + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Queue is empty", queue->popIndex, queue->pushIndex)); + result = -1; + mbedNet_LastError = mbedNetResult_QueueEmpty; + goto Exit; + } + + index = queue->popIndex; + *entry = queue->entries[index]; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Peeking first entry from queue", queue->popIndex, queue->pushIndex)); + +Exit: + return result; +} + + +int32_t Queue_Free(Queue_t *queue) +{ + int32_t result = 0; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("%d-%d Free queue", queue->popIndex, queue->pushIndex)); + free(queue); + + return result; +} + + +Bool_t Queue_IsEmpty(const Queue_t *queue) +{ + return (queue->popIndex == queue->pushIndex) ? True : False; +} + + +Bool_t Queue_IsFull(const Queue_t *queue) +{ + return (queue->popIndex == ((queue->pushIndex + 1) % queue->size)) ? True : False; +} +
--- a/Queue.h Sun Jun 12 11:23:03 2011 +0000 +++ b/Queue.h Sun Jun 12 19:17:11 2011 +0000 @@ -27,13 +27,13 @@ typedef struct Queue Queue_t; -CAPI Queue_t *Queue_Alloc(int16_t size); -CAPI int32_t Queue_Push(Queue_t *queue, void *entry); -CAPI int32_t Queue_Pop(Queue_t *queue, void **entry); -CAPI int32_t Queue_Peek(Queue_t *queue, void **entry); -CAPI int32_t Queue_Free(Queue_t *queue); -CAPI Bool_t Queue_IsEmpty(const Queue_t *queue); -CAPI Bool_t Queue_IsFull(const Queue_t *queue); +Queue_t *Queue_Alloc(int16_t size); +int32_t Queue_Push(Queue_t *queue, void *entry); +int32_t Queue_Pop(Queue_t *queue, void **entry); +int32_t Queue_Peek(Queue_t *queue, void **entry); +int32_t Queue_Free(Queue_t *queue); +Bool_t Queue_IsEmpty(const Queue_t *queue); +Bool_t Queue_IsFull(const Queue_t *queue); #endif /* __QUEUE_H__ */
--- a/Sockets.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,607 +0,0 @@ -/* - * $Id: Sockets.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "NetIF.h" -#include "Sockets.h" -#include "IPv4.h" -#include "UDPv4.h" -#include "Debug.h" -#include "Queue.h" -#include <string.h> -#include <stdlib.h> - - -#define DEBUG_CURRENT_MODULE_NAME "sockets" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_SOCKETS - - -#define UDPV4_DATA_OFFSET 8 - - -struct DataBlock -{ - uint8_t *dataPtr, - *readPtr; - int16_t totalSize, - remainingSize; -}; -typedef struct DataBlock DataBlock_t; - - -enum State -{ - State_Close = 0, - State_Open, - State_Bound, -}; -typedef enum State State_t; - - -struct Socket_Entry -{ - //Bool_t inUse; - Socket_Family_t family; - Socket_Protocol_t protocol; - int32_t options; - State_t state; - Socket_Addr_t *localAddr, - *remoteAddr; - Queue_t *dataQueue; - int32_t index; -}; -typedef struct Socket_Entry Socket_Entry_t; - - -static Socket_Entry_t socketEntryTable[SOCKET_MAX_COUNT]; -static Bool_t socketAPIInitialized = False; - - -static void Init(void); -static int32_t Hook(NetIF_t *netIF, Protocol_ID_t protocolID, Packet_t *packet); -static void Hook_UDPv4(NetIF_t *netIF, Packet_t *packet, Socket_Entry_t *entry); -static Socket_Entry_t *GetSocketEntry(Socket_t socket); -static int32_t BindUDPv4(Socket_Entry_t *entry, Socket_AddrIn_t *addrIn); -static int32_t Recv_Data(Socket_Entry_t *entry, uint8_t *data, int32_t length); -static int32_t SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddr); - - -Net_API_t sockets = -{ - API_ID_Sockets, - Init, - Hook -}; - - -static void Init(void) -{ - if (socketAPIInitialized) goto Exit; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing")); - memset(socketEntryTable, 0, sizeof(socketEntryTable)); - socketAPIInitialized = True; - -Exit: - return; -} - - -static int32_t Hook(NetIF_t *netIF, Protocol_ID_t protocolID, Packet_t *packet) -{ - int32_t index = 0; - Socket_Entry_t *entry = NULL; - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Hook(%s%d, %s, %d bytes)", - netIF->name, - netIF->index, - protocol_IDNames[protocolID], - packet->length - )); - - for (index = 0; index < SOCKET_MAX_COUNT; index++) - { - entry = socketEntryTable + index; - if (entry->state != State_Bound) continue; - switch(protocolID) - { - case Protocol_ID_UDPv4: - if (entry->protocol == SOCK_DGRAM) Hook_UDPv4(netIF, packet, entry); - break; - - default: - continue; - } - } - - return 0; -} - -static void Hook_UDPv4(NetIF_t *netIF, Packet_t *packet, Socket_Entry_t *entry) -{ - IPv4_Header_t *ipv4Header; - UDPv4_Header_t *udpv4Header; - Socket_AddrIn_t *localAddrIn, *remoteAddrIn; - int32_t depth; - DataBlock_t *dataBlock; - - - depth = packet->depth; - ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth]; - udpv4Header = (UDPv4_Header_t *)(ipv4Header + 1); - localAddrIn = (Socket_AddrIn_t *)entry->localAddr; - remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr; - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("ports: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d size:%d", - ipv4Header->source.IP0, - ipv4Header->source.IP1, - ipv4Header->source.IP2, - ipv4Header->source.IP3, - ntohs(udpv4Header->destPort), - localAddrIn->address.IP0, - localAddrIn->address.IP1, - localAddrIn->address.IP2, - localAddrIn->address.IP3, - ntohs(localAddrIn->port), - ntohs(udpv4Header->length) - )); - if ((localAddrIn->port == udpv4Header->destPort) && ( (localAddrIn->address.addr == IPADDR_ANY) || (ipv4Header->dest.addr == localAddrIn->address.addr) ) ) - { - if (!Queue_IsFull(entry->dataQueue)) - { - remoteAddrIn->address = ipv4Header->source; - remoteAddrIn->port = udpv4Header->sourcePort; - dataBlock = (DataBlock_t *)malloc(sizeof(DataBlock_t)); - if (dataBlock == NULL) - { - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - goto Exit; - } - dataBlock->totalSize = ntohs(udpv4Header->length) - sizeof(UDPv4_Header_t); - dataBlock->remainingSize = dataBlock->totalSize; - dataBlock->dataPtr = (uint8_t *)malloc(dataBlock->totalSize); - if (dataBlock->dataPtr == NULL) - { - free(dataBlock); - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - goto Exit; - } - dataBlock->readPtr = dataBlock->dataPtr; - memcpy(dataBlock->dataPtr, packet->data + sizeof(UDPv4_Header_t), dataBlock->totalSize); - Queue_Push(entry->dataQueue, (void *)dataBlock); - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Added block of %d bytes to socket %d", dataBlock->totalSize, entry->index)); - } - } - -Exit: - return; -} - -static int32_t BindUDPv4(Socket_Entry_t *entry, Socket_AddrIn_t *addrIn) -{ - int32_t result = -1; - Socket_AddrIn_t *localAddrIn, - *remoteAddrIn; - - entry->localAddr = (Socket_Addr_t *)malloc(sizeof(Socket_AddrIn_t)); - if (entry->localAddr == NULL) - { - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - goto Exit; - } - entry->remoteAddr = (Socket_Addr_t *)malloc(sizeof(Socket_AddrIn_t)); - if (entry->remoteAddr == NULL) - { - free(entry->localAddr); - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - goto Exit; - } - localAddrIn = (Socket_AddrIn_t *)entry->localAddr; - remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr; - memcpy(localAddrIn, addrIn, sizeof(Socket_AddrIn_t)); - memset(remoteAddrIn, 0, sizeof(Socket_AddrIn_t)); - remoteAddrIn->family = addrIn->family; - remoteAddrIn->len = addrIn->len; - localAddrIn->port = addrIn->port; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Binding socket %d to %d.%d.%d.%d:%d", - entry->index, - addrIn->address.IP0, - addrIn->address.IP1, - addrIn->address.IP2, - addrIn->address.IP3, - ntohs(addrIn->port) - )); - -Exit: - return result; -} - - -static int32_t Recv_Data(Socket_Entry_t *entry, uint8_t *data, int32_t length) -{ - int32_t count = 0; - DataBlock_t *dataBlock = NULL; - - Queue_Peek(entry->dataQueue, (void **)&dataBlock); - if (dataBlock->remainingSize <= length) - { - count = dataBlock->remainingSize; - Queue_Pop(entry->dataQueue, (void **)&dataBlock); - memcpy(data, dataBlock->readPtr, count); - free(dataBlock->dataPtr); - free(dataBlock); - } - else - { - count = length; - memcpy(data, dataBlock->readPtr, count); - dataBlock->readPtr += count; - dataBlock->remainingSize -= count; - } - return count; -} - - -static int32_t SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddr) -{ - int32_t count = -1, - totalLength; - IPv4_Header_t *ipv4Header; - UDPv4_Header_t *udpv4Header; - Socket_AddrIn_t *localAddrIn, - *remoteAddrIn; - - localAddrIn = (Socket_AddrIn_t *)entry->localAddr; - remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr; - totalLength = length + sizeof(UDPv4_Header_t) + sizeof(IPv4_Header_t); - ipv4Header = (IPv4_Header_t *)malloc(totalLength); - if (ipv4Header == NULL) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Not enough memory (needed %d bytes)", totalLength)); - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - goto Exit; - } - - memset(ipv4Header, 0, totalLength); - - DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE0, ("UDPv4 sending %d bytes to %d.%d.%d.%d:%d", - length, - remoteAddr->address.IP0, - remoteAddr->address.IP1, - remoteAddr->address.IP2, - remoteAddr->address.IP3, - ntohs(remoteAddr->port) - - )); - - udpv4Header = (UDPv4_Header_t *)(ipv4Header + 1); - - ipv4Header->ihl = 5; - ipv4Header->version = IPV4_VERSION; - ipv4Header->tos = 0; - ipv4Header->totalLength = htons(5 * 4 + totalLength); - ipv4Header->id = 0; - ipv4Header->fragmentFlags = 0; - ipv4Header->ttl = NET_DEFAULT_TTL; - ipv4Header->protocol = IPV4_PROTO_UDPV4; - ipv4Header->dest = remoteAddr->address; - - udpv4Header->sourcePort = localAddrIn->port; - udpv4Header->destPort = remoteAddrIn->port; - udpv4Header->length = htons(length + sizeof(UDPv4_Header_t)); - - memcpy(udpv4Header + 1, data, length); - - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - IPv4_DumpIPv4Header("Sockets:", ipv4Header); - } - - count = NetIF_SendIPv4Packet(ipv4Header); - free(ipv4Header); - -Exit: - return count; -} - - -Socket_t Sockets_Open(Socket_Family_t family, Socket_Protocol_t protocol, int32_t options) -{ - int32_t result = 0, - index = 0; - Socket_Entry_t *entry = NULL; - - if (family != AF_INET) - { - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol family not supported")); - mbedNet_LastError = mbedNetResult_NotIplemented; - result = -1; - goto Exit; - } - - for (index = 0; index < SOCKET_MAX_COUNT; index++) - { - if (socketEntryTable[index].state != State_Close) continue; - entry = socketEntryTable + index; - break; - } - - if (entry == NULL) - { - DEBUG_MODULE(DEBUG_LEVEL_WARNING, ("Too many open sockets")); - mbedNet_LastError = mbedNetResult_TooManyOpenSockets; - result = -1; - goto Exit; - } - - entry->family = family; - entry->protocol = protocol; - entry->options = options; - entry->state = State_Open; - entry->dataQueue = NULL; - entry->index = index; - result = index; - -Exit: - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("opened socket %d", index)); - return result; -} - - -int32_t Sockets_Bind(Socket_t socket, Socket_Addr_t *addr, int32_t addrLen) -{ - int32_t result = -1; - Socket_Entry_t *entry; - - if ((entry = GetSocketEntry(socket)) == NULL) goto Exit; - - if (entry == NULL) - { - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Socket %d not found", socket)); - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - result = -1; - goto Exit; - } - - /* Allocate address entry */ - switch(entry->family) - { - case AF_INET: - switch(entry->protocol) - { - case SOCK_DGRAM: - if (addrLen != sizeof(Socket_AddrIn_t)) - { - mbedNet_LastError = mbedNetResult_InvalidParameter; - result = -1; - goto Exit; - } - result = BindUDPv4(entry, (Socket_AddrIn_t *)addr); - break; - - case SOCK_STREAM: - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol not supported")); - mbedNet_LastError = mbedNetResult_NotIplemented; - result = -1; - goto Exit; - - case SOCK_RAW: - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol not supported")); - mbedNet_LastError = mbedNetResult_NotIplemented; - result = -1; - goto Exit; - - default: - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Unknown socket protocol")); - mbedNet_LastError = mbedNetResult_InvalidParameter; - result = -1; - goto Exit; - } - break; - - default: - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol family not supported")); - mbedNet_LastError = mbedNetResult_NotIplemented; - result = -1; - goto Exit; - } - - entry->dataQueue = Queue_Alloc(SOCKET_DATAQUEUE_ENTRY_COUNT); - - if (entry == NULL) - { - free(entry->localAddr); - free(entry->remoteAddr); - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Not enough memory to allocate data queue")); - mbedNet_LastError = mbedNetResult_NotEnoughMemory; - result = -1; - goto Exit; - } - - entry->state = State_Bound; - - result = 0; - -Exit: - return result; -} - - -int32_t Sockets_Send(Socket_t socket, uint8_t *data, int32_t length, int32_t flags) -{ - int32_t count = -1; - Socket_Entry_t *entry; - - entry = GetSocketEntry(socket); - if (entry == NULL) goto Exit; - - if (entry->protocol == SOCK_DGRAM) - { - mbedNet_LastError = mbedNetResult_DestinationAddressRequired; - goto Exit; - } - - mbedNet_LastError = mbedNetResult_NotIplemented; - -Exit: - return count; -} - - -int32_t Sockets_SendTo(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, const Socket_Addr_t *remoteAddr, int32_t addrLen) -{ - int32_t count = -1; - Socket_Entry_t *entry; - - - entry = GetSocketEntry(socket); - if (entry == NULL) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("socket not found!")); - goto Exit; - } - - switch(entry->family) - { - case AF_INET: - switch(entry->protocol) - { - case SOCK_DGRAM: - if (addrLen != sizeof(Socket_AddrIn_t)) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Invalid socket address length")); - mbedNet_LastError = mbedNetResult_InvalidParameter; - goto Exit; - } - count = SendToUDPv4(entry, data, length, (Socket_AddrIn_t *)remoteAddr); - break; - - default: - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Protocol not implemented")); - mbedNet_LastError = mbedNetResult_NotIplemented; - goto Exit; - } - break; - - default: - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Protocol family not implemented")); - mbedNet_LastError = mbedNetResult_NotIplemented; - goto Exit; - } - -Exit: - return count; -} - - -int32_t Sockets_Recv(Socket_t socket, uint8_t *data, int32_t length, int32_t flags) -{ - int32_t count = -1; - Socket_Entry_t *entry; - - entry = GetSocketEntry(socket); - if (entry == NULL) goto Exit; - - if (Queue_IsEmpty(entry->dataQueue)) - { - mbedNet_LastError = mbedNetResult_WouldBlock; - goto Exit; - } - - count = Recv_Data(entry, data, length); - -Exit: - return count; -} - - -int32_t Sockets_RecvFrom(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, Socket_Addr_t *remoteAddr, int32_t *addrLen) -{ - int32_t count = -1; - Socket_Entry_t *entry; - - entry = GetSocketEntry(socket); - if (entry == NULL) goto Exit; - - if (Queue_IsEmpty(entry->dataQueue)) - { - mbedNet_LastError = mbedNetResult_WouldBlock; - goto Exit; - } - - if (remoteAddr != NULL) - { - if (entry->localAddr->len > *addrLen) - { - mbedNet_LastError = mbedNetResult_BufferTooSmall; - goto Exit; - } - memcpy(remoteAddr, entry->remoteAddr, entry->remoteAddr->len); - } - - count = Recv_Data(entry, data, length); - -Exit: - return count; -} - - -int32_t Sockets_Close(Socket_t socket) -{ - int32_t result = -1; - Socket_Entry_t *entry; - void *ptr; - - if ((entry = GetSocketEntry(socket)) == NULL) goto Exit; - - entry->state = State_Close; - free(entry->localAddr); - entry->localAddr = NULL; - free(entry->remoteAddr); - entry->remoteAddr = NULL; - /* Free pending data blocks */ - while(Queue_Peek(entry->dataQueue, &ptr) != -1) - { - free(ptr); - } - Queue_Free(entry->dataQueue); - entry->dataQueue = NULL; - result = 0; - -Exit: - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("closed socket %d", socket)); - return result; -} - - - -static Socket_Entry_t *GetSocketEntry(Socket_t socket) -{ - Socket_Entry_t *entry = NULL; - - if ((socket < 0) || (socket >= SOCKET_MAX_COUNT)) - { - DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Invalid socket handle")); - mbedNet_LastError = mbedNetResult_InvalidSocketHandle; - goto Exit; - } - entry = socketEntryTable + socket; - - if (entry->state == State_Close) - { - DEBUG_MODULE(DEBUG_LEVEL_WARNING, ("Socket already closed")); - mbedNet_LastError = mbedNetResult_SocketAlreadyClosed; - entry = NULL; - goto Exit; - } -Exit: - return entry; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sockets.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,607 @@ +/* + * $Id: Sockets.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "NetIF.h" +#include "Sockets.h" +#include "IPv4.h" +#include "UDPv4.h" +#include "Debug.h" +#include "Queue.h" +#include <string.h> +#include <stdlib.h> + + +#define DEBUG_CURRENT_MODULE_NAME "sockets" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_SOCKETS + + +#define UDPV4_DATA_OFFSET 8 + + +struct DataBlock +{ + uint8_t *dataPtr, + *readPtr; + int16_t totalSize, + remainingSize; +}; +typedef struct DataBlock DataBlock_t; + + +enum State +{ + State_Close = 0, + State_Open, + State_Bound, +}; +typedef enum State State_t; + + +struct Socket_Entry +{ + //Bool_t inUse; + Socket_Family_t family; + Socket_Protocol_t protocol; + int32_t options; + State_t state; + Socket_Addr_t *localAddr, + *remoteAddr; + Queue_t *dataQueue; + int32_t index; +}; +typedef struct Socket_Entry Socket_Entry_t; + + +static Socket_Entry_t socketEntryTable[SOCKET_MAX_COUNT]; +static Bool_t socketAPIInitialized = False; + + +static void Init(void); +static int32_t Hook(NetIF_t *netIF, Protocol_ID_t protocolID, Packet_t *packet); +static void Hook_UDPv4(NetIF_t *netIF, Packet_t *packet, Socket_Entry_t *entry); +static Socket_Entry_t *GetSocketEntry(Socket_t socket); +static int32_t BindUDPv4(Socket_Entry_t *entry, Socket_AddrIn_t *addrIn); +static int32_t Recv_Data(Socket_Entry_t *entry, uint8_t *data, int32_t length); +static int32_t SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddr); + + +Net_API_t sockets = +{ + API_ID_Sockets, + Init, + Hook +}; + + +static void Init(void) +{ + if (socketAPIInitialized) goto Exit; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing")); + memset(socketEntryTable, 0, sizeof(socketEntryTable)); + socketAPIInitialized = True; + +Exit: + return; +} + + +static int32_t Hook(NetIF_t *netIF, Protocol_ID_t protocolID, Packet_t *packet) +{ + int32_t index = 0; + Socket_Entry_t *entry = NULL; + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Hook(%s%d, %s, %d bytes)", + netIF->name, + netIF->index, + protocol_IDNames[protocolID], + packet->length + )); + + for (index = 0; index < SOCKET_MAX_COUNT; index++) + { + entry = socketEntryTable + index; + if (entry->state != State_Bound) continue; + switch(protocolID) + { + case Protocol_ID_UDPv4: + if (entry->protocol == SOCK_DGRAM) Hook_UDPv4(netIF, packet, entry); + break; + + default: + continue; + } + } + + return 0; +} + +static void Hook_UDPv4(NetIF_t *netIF, Packet_t *packet, Socket_Entry_t *entry) +{ + IPv4_Header_t *ipv4Header; + UDPv4_Header_t *udpv4Header; + Socket_AddrIn_t *localAddrIn, *remoteAddrIn; + int32_t depth; + DataBlock_t *dataBlock; + + + depth = packet->depth; + ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth]; + udpv4Header = (UDPv4_Header_t *)(ipv4Header + 1); + localAddrIn = (Socket_AddrIn_t *)entry->localAddr; + remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr; + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("ports: %d.%d.%d.%d:%d to %d.%d.%d.%d:%d size:%d", + ipv4Header->source.IP0, + ipv4Header->source.IP1, + ipv4Header->source.IP2, + ipv4Header->source.IP3, + ntohs(udpv4Header->destPort), + localAddrIn->address.IP0, + localAddrIn->address.IP1, + localAddrIn->address.IP2, + localAddrIn->address.IP3, + ntohs(localAddrIn->port), + ntohs(udpv4Header->length) + )); + if ((localAddrIn->port == udpv4Header->destPort) && ( (localAddrIn->address.addr == IPADDR_ANY) || (ipv4Header->dest.addr == localAddrIn->address.addr) ) ) + { + if (!Queue_IsFull(entry->dataQueue)) + { + remoteAddrIn->address = ipv4Header->source; + remoteAddrIn->port = udpv4Header->sourcePort; + dataBlock = (DataBlock_t *)malloc(sizeof(DataBlock_t)); + if (dataBlock == NULL) + { + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + goto Exit; + } + dataBlock->totalSize = ntohs(udpv4Header->length) - sizeof(UDPv4_Header_t); + dataBlock->remainingSize = dataBlock->totalSize; + dataBlock->dataPtr = (uint8_t *)malloc(dataBlock->totalSize); + if (dataBlock->dataPtr == NULL) + { + free(dataBlock); + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + goto Exit; + } + dataBlock->readPtr = dataBlock->dataPtr; + memcpy(dataBlock->dataPtr, packet->data + sizeof(UDPv4_Header_t), dataBlock->totalSize); + Queue_Push(entry->dataQueue, (void *)dataBlock); + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE0, ("Added block of %d bytes to socket %d", dataBlock->totalSize, entry->index)); + } + } + +Exit: + return; +} + +static int32_t BindUDPv4(Socket_Entry_t *entry, Socket_AddrIn_t *addrIn) +{ + int32_t result = -1; + Socket_AddrIn_t *localAddrIn, + *remoteAddrIn; + + entry->localAddr = (Socket_Addr_t *)malloc(sizeof(Socket_AddrIn_t)); + if (entry->localAddr == NULL) + { + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + goto Exit; + } + entry->remoteAddr = (Socket_Addr_t *)malloc(sizeof(Socket_AddrIn_t)); + if (entry->remoteAddr == NULL) + { + free(entry->localAddr); + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + goto Exit; + } + localAddrIn = (Socket_AddrIn_t *)entry->localAddr; + remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr; + memcpy(localAddrIn, addrIn, sizeof(Socket_AddrIn_t)); + memset(remoteAddrIn, 0, sizeof(Socket_AddrIn_t)); + remoteAddrIn->family = addrIn->family; + remoteAddrIn->len = addrIn->len; + localAddrIn->port = addrIn->port; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Binding socket %d to %d.%d.%d.%d:%d", + entry->index, + addrIn->address.IP0, + addrIn->address.IP1, + addrIn->address.IP2, + addrIn->address.IP3, + ntohs(addrIn->port) + )); + +Exit: + return result; +} + + +static int32_t Recv_Data(Socket_Entry_t *entry, uint8_t *data, int32_t length) +{ + int32_t count = 0; + DataBlock_t *dataBlock = NULL; + + Queue_Peek(entry->dataQueue, (void **)&dataBlock); + if (dataBlock->remainingSize <= length) + { + count = dataBlock->remainingSize; + Queue_Pop(entry->dataQueue, (void **)&dataBlock); + memcpy(data, dataBlock->readPtr, count); + free(dataBlock->dataPtr); + free(dataBlock); + } + else + { + count = length; + memcpy(data, dataBlock->readPtr, count); + dataBlock->readPtr += count; + dataBlock->remainingSize -= count; + } + return count; +} + + +static int32_t SendToUDPv4(Socket_Entry_t *entry, uint8_t *data, int32_t length, Socket_AddrIn_t *remoteAddr) +{ + int32_t count = -1, + totalLength; + IPv4_Header_t *ipv4Header; + UDPv4_Header_t *udpv4Header; + Socket_AddrIn_t *localAddrIn, + *remoteAddrIn; + + localAddrIn = (Socket_AddrIn_t *)entry->localAddr; + remoteAddrIn = (Socket_AddrIn_t *)entry->remoteAddr; + totalLength = length + sizeof(UDPv4_Header_t) + sizeof(IPv4_Header_t); + ipv4Header = (IPv4_Header_t *)malloc(totalLength); + if (ipv4Header == NULL) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Not enough memory (needed %d bytes)", totalLength)); + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + goto Exit; + } + + memset(ipv4Header, 0, totalLength); + + DEBUG_SOURCE(DEBUG_LEVEL_VERBOSE0, ("UDPv4 sending %d bytes to %d.%d.%d.%d:%d", + length, + remoteAddr->address.IP0, + remoteAddr->address.IP1, + remoteAddr->address.IP2, + remoteAddr->address.IP3, + ntohs(remoteAddr->port) + + )); + + udpv4Header = (UDPv4_Header_t *)(ipv4Header + 1); + + ipv4Header->ihl = 5; + ipv4Header->version = IPV4_VERSION; + ipv4Header->tos = 0; + ipv4Header->totalLength = htons(5 * 4 + totalLength); + ipv4Header->id = 0; + ipv4Header->fragmentFlags = 0; + ipv4Header->ttl = NET_DEFAULT_TTL; + ipv4Header->protocol = IPV4_PROTO_UDPV4; + ipv4Header->dest = remoteAddr->address; + + udpv4Header->sourcePort = localAddrIn->port; + udpv4Header->destPort = remoteAddrIn->port; + udpv4Header->length = htons(length + sizeof(UDPv4_Header_t)); + + memcpy(udpv4Header + 1, data, length); + + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + IPv4_DumpIPv4Header("Sockets:", ipv4Header); + } + + count = NetIF_SendIPv4Packet(ipv4Header); + free(ipv4Header); + +Exit: + return count; +} + + +Socket_t Sockets_Open(Socket_Family_t family, Socket_Protocol_t protocol, int32_t options) +{ + int32_t result = 0, + index = 0; + Socket_Entry_t *entry = NULL; + + if (family != AF_INET) + { + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol family not supported")); + mbedNet_LastError = mbedNetResult_NotIplemented; + result = -1; + goto Exit; + } + + for (index = 0; index < SOCKET_MAX_COUNT; index++) + { + if (socketEntryTable[index].state != State_Close) continue; + entry = socketEntryTable + index; + break; + } + + if (entry == NULL) + { + DEBUG_MODULE(DEBUG_LEVEL_WARNING, ("Too many open sockets")); + mbedNet_LastError = mbedNetResult_TooManyOpenSockets; + result = -1; + goto Exit; + } + + entry->family = family; + entry->protocol = protocol; + entry->options = options; + entry->state = State_Open; + entry->dataQueue = NULL; + entry->index = index; + result = index; + +Exit: + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("opened socket %d", index)); + return result; +} + + +int32_t Sockets_Bind(Socket_t socket, Socket_Addr_t *addr, int32_t addrLen) +{ + int32_t result = -1; + Socket_Entry_t *entry; + + if ((entry = GetSocketEntry(socket)) == NULL) goto Exit; + + if (entry == NULL) + { + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Socket %d not found", socket)); + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + result = -1; + goto Exit; + } + + /* Allocate address entry */ + switch(entry->family) + { + case AF_INET: + switch(entry->protocol) + { + case SOCK_DGRAM: + if (addrLen != sizeof(Socket_AddrIn_t)) + { + mbedNet_LastError = mbedNetResult_InvalidParameter; + result = -1; + goto Exit; + } + result = BindUDPv4(entry, (Socket_AddrIn_t *)addr); + break; + + case SOCK_STREAM: + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol not supported")); + mbedNet_LastError = mbedNetResult_NotIplemented; + result = -1; + goto Exit; + + case SOCK_RAW: + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol not supported")); + mbedNet_LastError = mbedNetResult_NotIplemented; + result = -1; + goto Exit; + + default: + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Unknown socket protocol")); + mbedNet_LastError = mbedNetResult_InvalidParameter; + result = -1; + goto Exit; + } + break; + + default: + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Protocol family not supported")); + mbedNet_LastError = mbedNetResult_NotIplemented; + result = -1; + goto Exit; + } + + entry->dataQueue = Queue_Alloc(SOCKET_DATAQUEUE_ENTRY_COUNT); + + if (entry == NULL) + { + free(entry->localAddr); + free(entry->remoteAddr); + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Not enough memory to allocate data queue")); + mbedNet_LastError = mbedNetResult_NotEnoughMemory; + result = -1; + goto Exit; + } + + entry->state = State_Bound; + + result = 0; + +Exit: + return result; +} + + +int32_t Sockets_Send(Socket_t socket, uint8_t *data, int32_t length, int32_t flags) +{ + int32_t count = -1; + Socket_Entry_t *entry; + + entry = GetSocketEntry(socket); + if (entry == NULL) goto Exit; + + if (entry->protocol == SOCK_DGRAM) + { + mbedNet_LastError = mbedNetResult_DestinationAddressRequired; + goto Exit; + } + + mbedNet_LastError = mbedNetResult_NotIplemented; + +Exit: + return count; +} + + +int32_t Sockets_SendTo(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, const Socket_Addr_t *remoteAddr, int32_t addrLen) +{ + int32_t count = -1; + Socket_Entry_t *entry; + + + entry = GetSocketEntry(socket); + if (entry == NULL) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("socket not found!")); + goto Exit; + } + + switch(entry->family) + { + case AF_INET: + switch(entry->protocol) + { + case SOCK_DGRAM: + if (addrLen != sizeof(Socket_AddrIn_t)) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Invalid socket address length")); + mbedNet_LastError = mbedNetResult_InvalidParameter; + goto Exit; + } + count = SendToUDPv4(entry, data, length, (Socket_AddrIn_t *)remoteAddr); + break; + + default: + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Protocol not implemented")); + mbedNet_LastError = mbedNetResult_NotIplemented; + goto Exit; + } + break; + + default: + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Protocol family not implemented")); + mbedNet_LastError = mbedNetResult_NotIplemented; + goto Exit; + } + +Exit: + return count; +} + + +int32_t Sockets_Recv(Socket_t socket, uint8_t *data, int32_t length, int32_t flags) +{ + int32_t count = -1; + Socket_Entry_t *entry; + + entry = GetSocketEntry(socket); + if (entry == NULL) goto Exit; + + if (Queue_IsEmpty(entry->dataQueue)) + { + mbedNet_LastError = mbedNetResult_WouldBlock; + goto Exit; + } + + count = Recv_Data(entry, data, length); + +Exit: + return count; +} + + +int32_t Sockets_RecvFrom(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, Socket_Addr_t *remoteAddr, int32_t *addrLen) +{ + int32_t count = -1; + Socket_Entry_t *entry; + + entry = GetSocketEntry(socket); + if (entry == NULL) goto Exit; + + if (Queue_IsEmpty(entry->dataQueue)) + { + mbedNet_LastError = mbedNetResult_WouldBlock; + goto Exit; + } + + if (remoteAddr != NULL) + { + if (entry->localAddr->len > *addrLen) + { + mbedNet_LastError = mbedNetResult_BufferTooSmall; + goto Exit; + } + memcpy(remoteAddr, entry->remoteAddr, entry->remoteAddr->len); + } + + count = Recv_Data(entry, data, length); + +Exit: + return count; +} + + +int32_t Sockets_Close(Socket_t socket) +{ + int32_t result = -1; + Socket_Entry_t *entry; + void *ptr; + + if ((entry = GetSocketEntry(socket)) == NULL) goto Exit; + + entry->state = State_Close; + free(entry->localAddr); + entry->localAddr = NULL; + free(entry->remoteAddr); + entry->remoteAddr = NULL; + /* Free pending data blocks */ + while(Queue_Peek(entry->dataQueue, &ptr) != -1) + { + free(ptr); + } + Queue_Free(entry->dataQueue); + entry->dataQueue = NULL; + result = 0; + +Exit: + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("closed socket %d", socket)); + return result; +} + + + +static Socket_Entry_t *GetSocketEntry(Socket_t socket) +{ + Socket_Entry_t *entry = NULL; + + if ((socket < 0) || (socket >= SOCKET_MAX_COUNT)) + { + DEBUG_MODULE(DEBUG_LEVEL_ERROR, ("Invalid socket handle")); + mbedNet_LastError = mbedNetResult_InvalidSocketHandle; + goto Exit; + } + entry = socketEntryTable + socket; + + if (entry->state == State_Close) + { + DEBUG_MODULE(DEBUG_LEVEL_WARNING, ("Socket already closed")); + mbedNet_LastError = mbedNetResult_SocketAlreadyClosed; + entry = NULL; + goto Exit; + } +Exit: + return entry; +}
--- a/Sockets.h Sun Jun 12 11:23:03 2011 +0000 +++ b/Sockets.h Sun Jun 12 19:17:11 2011 +0000 @@ -66,13 +66,13 @@ extern Net_API_t sockets; -CAPI Socket_t Sockets_Open(Socket_Family_t family, Socket_Protocol_t protocol, int32_t options); -CAPI int32_t Sockets_Bind(Socket_t socket, Socket_Addr_t *addr, int32_t addrLen); -CAPI int32_t Sockets_Send(Socket_t socket, uint8_t *data, int32_t length, int32_t flags); -CAPI int32_t Sockets_SendTo(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, const Socket_Addr_t *remoteAddr, int32_t addrLen); -CAPI int32_t Sockets_Recv(Socket_t socket, uint8_t *data, int32_t length, int32_t flags); -CAPI int32_t Sockets_RecvFrom(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, Socket_Addr_t *remoteAddr, int32_t *addrLen); -CAPI int32_t Sockets_Close(Socket_t socket); +Socket_t Sockets_Open(Socket_Family_t family, Socket_Protocol_t protocol, int32_t options); +int32_t Sockets_Bind(Socket_t socket, Socket_Addr_t *addr, int32_t addrLen); +int32_t Sockets_Send(Socket_t socket, uint8_t *data, int32_t length, int32_t flags); +int32_t Sockets_SendTo(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, const Socket_Addr_t *remoteAddr, int32_t addrLen); +int32_t Sockets_Recv(Socket_t socket, uint8_t *data, int32_t length, int32_t flags); +int32_t Sockets_RecvFrom(Socket_t socket, uint8_t *data, int32_t length, int32_t flags, Socket_Addr_t *remoteAddr, int32_t *addrLen); +int32_t Sockets_Close(Socket_t socket); #endif /* __SOCKET_H__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TCPv4.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,98 @@ +/* + * $Id: TCPv4.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "TCPv4.h" +#include "Debug.h" + + +#define DEBUG_CURRENT_MODULE_NAME "TCPv4" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_TCPV4 + + +static void Init(void); +static void Handler(NetIF_t *netIF, Packet_t *packet); +static int32_t RegisterAPI(Net_API_t *api); + + +Protocol_Handler_t tcpv4 = +{ + PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ + Protocol_ID_TCPv4, /* Protocol ID */ + IPV4_PROTO_TCPV4, /* Protocol number */ + Init, /* Protocol initialisation function */ + Handler, /* Protocol handler */ + NULL, /* Protocol registration function */ + RegisterAPI, /* API registration function */ +}; + + +static void Init(void) +{ + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing TCPv4 layer")); +} + + +static void Handler(NetIF_t *netIF, Packet_t *packet) +{ + //TCPv4_Header_t *tcpv4Header; + IPv4_Header_t *ipv4Header; + int32_t depth; + + depth = packet->depth; + //tcpv4Header = (TCPv4_Header_t *)packet->data; + ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth]; + + TCPv4_DumpHeader(NULL, ipv4Header); + Debug_DumpBufferHex((uint8_t *)ipv4Header, 52); +} + + +static int32_t RegisterAPI(Net_API_t *api) +{ + return -1; +} + + +void TCPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header) +{ + TCPv4_Header_t *tcpv4Header = (TCPv4_Header_t *)(ipv4Header + 1); + + DEBUG_RAW(("%sTCPv4 %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d seq:%ld ack:%ld off:%d flags:%c%c%c%c%c%c window:%d crc:%04X ptr:%d", + prefix != NULL ? prefix : "", + ipv4Header->source.IP0, + ipv4Header->source.IP1, + ipv4Header->source.IP2, + ipv4Header->source.IP3, + ntohs(tcpv4Header->sourcePort), + ipv4Header->dest.IP0, + ipv4Header->dest.IP1, + ipv4Header->dest.IP2, + ipv4Header->dest.IP3, + ntohs(tcpv4Header->destPort), + ntohs(tcpv4Header->sequence), + ntohs(tcpv4Header->ack), + tcpv4Header->offset, + + tcpv4Header->URG ? 'U' : '-', + tcpv4Header->ACK ? 'A' : '-', + tcpv4Header->PSH ? 'P' : '-', + tcpv4Header->RST ? 'R' : '-', + tcpv4Header->SYN ? 'S' : '-', + tcpv4Header->FIN ? 'F' : '-', + + ntohs(tcpv4Header->window), + ntohs(tcpv4Header->crc), + ntohs(tcpv4Header->pointer) + + )); +} +
--- a/UDPv4.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * $Id: UDPv4.c 29 2011-06-11 14:53:08Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ - * $Rev: 29 $ - * - * - * - * - * - */ - -#include "UDPv4.h" -#include "NetIF.h" -#include "Debug.h" -#include <string.h> - -#define DEBUG_CURRENT_MODULE_NAME "UDPv4" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_UDPV4 - - -static void Init(void); -static void Handler(NetIF_t *netIF, Packet_t *packet); -static int32_t RegisterAPI(Net_API_t *api); - - -Protocol_Handler_t udpv4 = -{ - PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ - Protocol_ID_UDPv4, /* Protocol ID */ - IPV4_PROTO_UDPV4, /* Protocol number */ - Init, /* Protocol initialisation function */ - Handler, /* Protocol handler */ - NULL, /* Protocol registration function */ - RegisterAPI, /* API registration function */ -}; - - -static Net_API_t *netAPITable[NET_API_PER_PROTOCOL_MAX_COUNT]; -static int32_t netAPICount = 0; - - -static void Init(void) -{ - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing UDPv4 layer")); - memset(netAPITable, 0, sizeof(netAPITable)); - netAPICount = 0; -} - - -static void Handler(NetIF_t *netIF, Packet_t *packet) -{ - IPv4_Header_t *ipv4Header; - int32_t depth, index; - - for (index = 0; index < netAPICount; index++) - { - netAPITable[index]->Hook(netIF, Protocol_ID_UDPv4, packet); - } - - depth = packet->depth; - ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth]; - - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE1) - { - UDPv4_DumpHeader(NULL, ipv4Header); - } -} - - -static int32_t RegisterAPI(Net_API_t *netAPI) -{ - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registering %s API", api_IDNames[netAPI->apiID])); - netAPI->InitAPI(); - netAPITable[netAPICount] = netAPI; - netAPICount++; - return -1; -} - - -void UDPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header) -{ - UDPv4_Header_t *udpv4Header = (UDPv4_Header_t *)(ipv4Header + 1); - - DEBUG_RAW(("%sUDPv4 %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d length:%d crc:%04X" , - prefix != NULL ? prefix : "", - ipv4Header->source.IP0, - ipv4Header->source.IP1, - ipv4Header->source.IP2, - ipv4Header->source.IP3, - ntohs(udpv4Header->sourcePort), - ipv4Header->dest.IP0, - ipv4Header->dest.IP1, - ipv4Header->dest.IP2, - ipv4Header->dest.IP3, - ntohs(udpv4Header->destPort), - ntohs(udpv4Header->length), - ntohs(udpv4Header->crc) - )); - -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UDPv4.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,102 @@ +/* + * $Id: UDPv4.c 29 2011-06-11 14:53:08Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-11 16:53:08 +0200 (sam., 11 juin 2011) $ + * $Rev: 29 $ + * + * + * + * + * + */ + +#include "UDPv4.h" +#include "NetIF.h" +#include "Debug.h" +#include <string.h> + +#define DEBUG_CURRENT_MODULE_NAME "UDPv4" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_UDPV4 + + +static void Init(void); +static void Handler(NetIF_t *netIF, Packet_t *packet); +static int32_t RegisterAPI(Net_API_t *api); + + +Protocol_Handler_t udpv4 = +{ + PROTOCOL_INDEX_NOT_INITIALIZED, /* Always PROTOCOL_INDEX_NOT_INITIALIZED at initialization */ + Protocol_ID_UDPv4, /* Protocol ID */ + IPV4_PROTO_UDPV4, /* Protocol number */ + Init, /* Protocol initialisation function */ + Handler, /* Protocol handler */ + NULL, /* Protocol registration function */ + RegisterAPI, /* API registration function */ +}; + + +static Net_API_t *netAPITable[NET_API_PER_PROTOCOL_MAX_COUNT]; +static int32_t netAPICount = 0; + + +static void Init(void) +{ + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing UDPv4 layer")); + memset(netAPITable, 0, sizeof(netAPITable)); + netAPICount = 0; +} + + +static void Handler(NetIF_t *netIF, Packet_t *packet) +{ + IPv4_Header_t *ipv4Header; + int32_t depth, index; + + for (index = 0; index < netAPICount; index++) + { + netAPITable[index]->Hook(netIF, Protocol_ID_UDPv4, packet); + } + + depth = packet->depth; + ipv4Header = (IPv4_Header_t *)packet->headerPtrTable[depth]; + + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE1) + { + UDPv4_DumpHeader(NULL, ipv4Header); + } +} + + +static int32_t RegisterAPI(Net_API_t *netAPI) +{ + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Registering %s API", api_IDNames[netAPI->apiID])); + netAPI->InitAPI(); + netAPITable[netAPICount] = netAPI; + netAPICount++; + return -1; +} + + +void UDPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header) +{ + UDPv4_Header_t *udpv4Header = (UDPv4_Header_t *)(ipv4Header + 1); + + DEBUG_RAW(("%sUDPv4 %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d length:%d crc:%04X" , + prefix != NULL ? prefix : "", + ipv4Header->source.IP0, + ipv4Header->source.IP1, + ipv4Header->source.IP2, + ipv4Header->source.IP3, + ntohs(udpv4Header->sourcePort), + ipv4Header->dest.IP0, + ipv4Header->dest.IP1, + ipv4Header->dest.IP2, + ipv4Header->dest.IP3, + ntohs(udpv4Header->destPort), + ntohs(udpv4Header->length), + ntohs(udpv4Header->crc) + )); + +} +
--- a/UDPv4.h Sun Jun 12 11:23:03 2011 +0000 +++ b/UDPv4.h Sun Jun 12 19:17:11 2011 +0000 @@ -34,7 +34,7 @@ extern Protocol_Handler_t udpv4; -CAPI void UDPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header); +void UDPv4_DumpHeader(const char *prefix, IPv4_Header_t *ipv4Header); #endif /* __UDPV4_H__ */
--- a/lpc17xx_clkpwr.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,338 +0,0 @@ -/***********************************************************************//** - * @file lpc17xx_clkpwr.c - * @brief Contains all functions support for Clock and Power Control - * firmware library on LPC17xx - * @version 3.0 - * @date 18. June. 2010 - * @author NXP MCU SW Application Team - ************************************************************************** - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * products. This software is supplied "AS IS" without any warranties. - * NXP Semiconductors assumes no responsibility or liability for the - * use of the software, conveys no license or title under any patent, - * copyright, or mask work right to the product. NXP Semiconductors - * reserves the right to make changes in the software without - * notification. NXP Semiconductors also make no representation or - * warranty that such application will be suitable for the specified - * use without further testing or modification. - **********************************************************************/ - -/* Peripheral group ----------------------------------------------------------- */ -/** @addtogroup CLKPWR - * @{ - */ - -/* Includes ------------------------------------------------------------------- */ -#include "lpc17xx_clkpwr.h" - - -/* Public Functions ----------------------------------------------------------- */ -/** @addtogroup CLKPWR_Public_Functions - * @{ - */ - -/*********************************************************************//** - * @brief Set value of each Peripheral Clock Selection - * @param[in] ClkType Peripheral Clock Selection of each type, - * should be one of the following: - * - CLKPWR_PCLKSEL_WDT : WDT - - CLKPWR_PCLKSEL_TIMER0 : Timer 0 - - CLKPWR_PCLKSEL_TIMER1 : Timer 1 - - CLKPWR_PCLKSEL_UART0 : UART 0 - - CLKPWR_PCLKSEL_UART1 : UART 1 - - CLKPWR_PCLKSEL_PWM1 : PWM 1 - - CLKPWR_PCLKSEL_I2C0 : I2C 0 - - CLKPWR_PCLKSEL_SPI : SPI - - CLKPWR_PCLKSEL_SSP1 : SSP 1 - - CLKPWR_PCLKSEL_DAC : DAC - - CLKPWR_PCLKSEL_ADC : ADC - - CLKPWR_PCLKSEL_CAN1 : CAN 1 - - CLKPWR_PCLKSEL_CAN2 : CAN 2 - - CLKPWR_PCLKSEL_ACF : ACF - - CLKPWR_PCLKSEL_QEI : QEI - - CLKPWR_PCLKSEL_PCB : PCB - - CLKPWR_PCLKSEL_I2C1 : I2C 1 - - CLKPWR_PCLKSEL_SSP0 : SSP 0 - - CLKPWR_PCLKSEL_TIMER2 : Timer 2 - - CLKPWR_PCLKSEL_TIMER3 : Timer 3 - - CLKPWR_PCLKSEL_UART2 : UART 2 - - CLKPWR_PCLKSEL_UART3 : UART 3 - - CLKPWR_PCLKSEL_I2C2 : I2C 2 - - CLKPWR_PCLKSEL_I2S : I2S - - CLKPWR_PCLKSEL_RIT : RIT - - CLKPWR_PCLKSEL_SYSCON : SYSCON - - CLKPWR_PCLKSEL_MC : MC - - * @param[in] DivVal Value of divider, should be: - * - CLKPWR_PCLKSEL_CCLK_DIV_4 : PCLK_peripheral = CCLK/4 - * - CLKPWR_PCLKSEL_CCLK_DIV_1 : PCLK_peripheral = CCLK/1 - * - CLKPWR_PCLKSEL_CCLK_DIV_2 : PCLK_peripheral = CCLK/2 - * - * @return none - **********************************************************************/ -void CLKPWR_SetPCLKDiv (uint32_t ClkType, uint32_t DivVal) -{ - uint32_t bitpos; - - bitpos = (ClkType < 32) ? (ClkType) : (ClkType - 32); - - /* PCLKSEL0 selected */ - if (ClkType < 32) - { - /* Clear two bit at bit position */ - LPC_SC->PCLKSEL0 &= (~(CLKPWR_PCLKSEL_BITMASK(bitpos))); - - /* Set two selected bit */ - LPC_SC->PCLKSEL0 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal)); - } - /* PCLKSEL1 selected */ - else - { - /* Clear two bit at bit position */ - LPC_SC->PCLKSEL1 &= ~(CLKPWR_PCLKSEL_BITMASK(bitpos)); - - /* Set two selected bit */ - LPC_SC->PCLKSEL1 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal)); - } -} - - -/*********************************************************************//** - * @brief Get current value of each Peripheral Clock Selection - * @param[in] ClkType Peripheral Clock Selection of each type, - * should be one of the following: - * - CLKPWR_PCLKSEL_WDT : WDT - - CLKPWR_PCLKSEL_TIMER0 : Timer 0 - - CLKPWR_PCLKSEL_TIMER1 : Timer 1 - - CLKPWR_PCLKSEL_UART0 : UART 0 - - CLKPWR_PCLKSEL_UART1 : UART 1 - - CLKPWR_PCLKSEL_PWM1 : PWM 1 - - CLKPWR_PCLKSEL_I2C0 : I2C 0 - - CLKPWR_PCLKSEL_SPI : SPI - - CLKPWR_PCLKSEL_SSP1 : SSP 1 - - CLKPWR_PCLKSEL_DAC : DAC - - CLKPWR_PCLKSEL_ADC : ADC - - CLKPWR_PCLKSEL_CAN1 : CAN 1 - - CLKPWR_PCLKSEL_CAN2 : CAN 2 - - CLKPWR_PCLKSEL_ACF : ACF - - CLKPWR_PCLKSEL_QEI : QEI - - CLKPWR_PCLKSEL_PCB : PCB - - CLKPWR_PCLKSEL_I2C1 : I2C 1 - - CLKPWR_PCLKSEL_SSP0 : SSP 0 - - CLKPWR_PCLKSEL_TIMER2 : Timer 2 - - CLKPWR_PCLKSEL_TIMER3 : Timer 3 - - CLKPWR_PCLKSEL_UART2 : UART 2 - - CLKPWR_PCLKSEL_UART3 : UART 3 - - CLKPWR_PCLKSEL_I2C2 : I2C 2 - - CLKPWR_PCLKSEL_I2S : I2S - - CLKPWR_PCLKSEL_RIT : RIT - - CLKPWR_PCLKSEL_SYSCON : SYSCON - - CLKPWR_PCLKSEL_MC : MC - - * @return Value of Selected Peripheral Clock Selection - **********************************************************************/ -uint32_t CLKPWR_GetPCLKSEL (uint32_t ClkType) -{ - uint32_t bitpos, retval; - - if (ClkType < 32) - { - bitpos = ClkType; - retval = LPC_SC->PCLKSEL0; - } - else - { - bitpos = ClkType - 32; - retval = LPC_SC->PCLKSEL1; - } - - retval = CLKPWR_PCLKSEL_GET(bitpos, retval); - return retval; -} - - - -/*********************************************************************//** - * @brief Get current value of each Peripheral Clock - * @param[in] ClkType Peripheral Clock Selection of each type, - * should be one of the following: - * - CLKPWR_PCLKSEL_WDT : WDT - - CLKPWR_PCLKSEL_TIMER0 : Timer 0 - - CLKPWR_PCLKSEL_TIMER1 : Timer 1 - - CLKPWR_PCLKSEL_UART0 : UART 0 - - CLKPWR_PCLKSEL_UART1 : UART 1 - - CLKPWR_PCLKSEL_PWM1 : PWM 1 - - CLKPWR_PCLKSEL_I2C0 : I2C 0 - - CLKPWR_PCLKSEL_SPI : SPI - - CLKPWR_PCLKSEL_SSP1 : SSP 1 - - CLKPWR_PCLKSEL_DAC : DAC - - CLKPWR_PCLKSEL_ADC : ADC - - CLKPWR_PCLKSEL_CAN1 : CAN 1 - - CLKPWR_PCLKSEL_CAN2 : CAN 2 - - CLKPWR_PCLKSEL_ACF : ACF - - CLKPWR_PCLKSEL_QEI : QEI - - CLKPWR_PCLKSEL_PCB : PCB - - CLKPWR_PCLKSEL_I2C1 : I2C 1 - - CLKPWR_PCLKSEL_SSP0 : SSP 0 - - CLKPWR_PCLKSEL_TIMER2 : Timer 2 - - CLKPWR_PCLKSEL_TIMER3 : Timer 3 - - CLKPWR_PCLKSEL_UART2 : UART 2 - - CLKPWR_PCLKSEL_UART3 : UART 3 - - CLKPWR_PCLKSEL_I2C2 : I2C 2 - - CLKPWR_PCLKSEL_I2S : I2S - - CLKPWR_PCLKSEL_RIT : RIT - - CLKPWR_PCLKSEL_SYSCON : SYSCON - - CLKPWR_PCLKSEL_MC : MC - - * @return Value of Selected Peripheral Clock - **********************************************************************/ -uint32_t CLKPWR_GetPCLK (uint32_t ClkType) -{ - uint32_t retval, div; - - retval = SystemCoreClock; - div = CLKPWR_GetPCLKSEL(ClkType); - - switch (div) - { - case 0: - div = 4; - break; - - case 1: - div = 1; - break; - - case 2: - div = 2; - break; - - case 3: - div = 8; - break; - } - retval /= div; - - return retval; -} - - - -/*********************************************************************//** - * @brief Configure power supply for each peripheral according to NewState - * @param[in] PPType Type of peripheral used to enable power, - * should be one of the following: - * - CLKPWR_PCONP_PCTIM0 : Timer 0 - - CLKPWR_PCONP_PCTIM1 : Timer 1 - - CLKPWR_PCONP_PCUART0 : UART 0 - - CLKPWR_PCONP_PCUART1 : UART 1 - - CLKPWR_PCONP_PCPWM1 : PWM 1 - - CLKPWR_PCONP_PCI2C0 : I2C 0 - - CLKPWR_PCONP_PCSPI : SPI - - CLKPWR_PCONP_PCRTC : RTC - - CLKPWR_PCONP_PCSSP1 : SSP 1 - - CLKPWR_PCONP_PCAD : ADC - - CLKPWR_PCONP_PCAN1 : CAN 1 - - CLKPWR_PCONP_PCAN2 : CAN 2 - - CLKPWR_PCONP_PCGPIO : GPIO - - CLKPWR_PCONP_PCRIT : RIT - - CLKPWR_PCONP_PCMC : MC - - CLKPWR_PCONP_PCQEI : QEI - - CLKPWR_PCONP_PCI2C1 : I2C 1 - - CLKPWR_PCONP_PCSSP0 : SSP 0 - - CLKPWR_PCONP_PCTIM2 : Timer 2 - - CLKPWR_PCONP_PCTIM3 : Timer 3 - - CLKPWR_PCONP_PCUART2 : UART 2 - - CLKPWR_PCONP_PCUART3 : UART 3 - - CLKPWR_PCONP_PCI2C2 : I2C 2 - - CLKPWR_PCONP_PCI2S : I2S - - CLKPWR_PCONP_PCGPDMA : GPDMA - - CLKPWR_PCONP_PCENET : Ethernet - - CLKPWR_PCONP_PCUSB : USB - * - * @param[in] NewState New state of Peripheral Power, should be: - * - ENABLE : Enable power for this peripheral - * - DISABLE : Disable power for this peripheral - * - * @return none - **********************************************************************/ -void CLKPWR_ConfigPPWR (uint32_t PPType, FunctionalState NewState) -{ - if (NewState == ENABLE) - { - LPC_SC->PCONP |= PPType & CLKPWR_PCONP_BITMASK; - } - else if (NewState == DISABLE) - { - LPC_SC->PCONP &= (~PPType) & CLKPWR_PCONP_BITMASK; - } -} - - -/*********************************************************************//** - * @brief Enter Sleep mode with co-operated instruction by the Cortex-M3. - * @param[in] None - * @return None - **********************************************************************/ -void CLKPWR_Sleep(void) -{ - LPC_SC->PCON = 0x00; - /* Sleep Mode*/ - __WFI(); -} - - -/*********************************************************************//** - * @brief Enter Deep Sleep mode with co-operated instruction by the Cortex-M3. - * @param[in] None - * @return None - **********************************************************************/ -void CLKPWR_DeepSleep(void) -{ - /* Deep-Sleep Mode, set SLEEPDEEP bit */ - SCB->SCR = 0x4; - LPC_SC->PCON = 0x8; - /* Deep Sleep Mode*/ - __WFI(); -} - - -/*********************************************************************//** - * @brief Enter Power Down mode with co-operated instruction by the Cortex-M3. - * @param[in] None - * @return None - **********************************************************************/ -void CLKPWR_PowerDown(void) -{ - /* Deep-Sleep Mode, set SLEEPDEEP bit */ - SCB->SCR = 0x4; - LPC_SC->PCON = 0x09; - /* Power Down Mode*/ - __WFI(); -} - - -/*********************************************************************//** - * @brief Enter Deep Power Down mode with co-operated instruction by the Cortex-M3. - * @param[in] None - * @return None - **********************************************************************/ -void CLKPWR_DeepPowerDown(void) -{ - /* Deep-Sleep Mode, set SLEEPDEEP bit */ - SCB->SCR = 0x4; - LPC_SC->PCON = 0x03; - /* Deep Power Down Mode*/ - __WFI(); -} - -/** - * @} - */ - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lpc17xx_clkpwr.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,338 @@ +/***********************************************************************//** + * @file lpc17xx_clkpwr.c + * @brief Contains all functions support for Clock and Power Control + * firmware library on LPC17xx + * @version 3.0 + * @date 18. June. 2010 + * @author NXP MCU SW Application Team + ************************************************************************** + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * products. This software is supplied "AS IS" without any warranties. + * NXP Semiconductors assumes no responsibility or liability for the + * use of the software, conveys no license or title under any patent, + * copyright, or mask work right to the product. NXP Semiconductors + * reserves the right to make changes in the software without + * notification. NXP Semiconductors also make no representation or + * warranty that such application will be suitable for the specified + * use without further testing or modification. + **********************************************************************/ + +/* Peripheral group ----------------------------------------------------------- */ +/** @addtogroup CLKPWR + * @{ + */ + +/* Includes ------------------------------------------------------------------- */ +#include "lpc17xx_clkpwr.h" + + +/* Public Functions ----------------------------------------------------------- */ +/** @addtogroup CLKPWR_Public_Functions + * @{ + */ + +/*********************************************************************//** + * @brief Set value of each Peripheral Clock Selection + * @param[in] ClkType Peripheral Clock Selection of each type, + * should be one of the following: + * - CLKPWR_PCLKSEL_WDT : WDT + - CLKPWR_PCLKSEL_TIMER0 : Timer 0 + - CLKPWR_PCLKSEL_TIMER1 : Timer 1 + - CLKPWR_PCLKSEL_UART0 : UART 0 + - CLKPWR_PCLKSEL_UART1 : UART 1 + - CLKPWR_PCLKSEL_PWM1 : PWM 1 + - CLKPWR_PCLKSEL_I2C0 : I2C 0 + - CLKPWR_PCLKSEL_SPI : SPI + - CLKPWR_PCLKSEL_SSP1 : SSP 1 + - CLKPWR_PCLKSEL_DAC : DAC + - CLKPWR_PCLKSEL_ADC : ADC + - CLKPWR_PCLKSEL_CAN1 : CAN 1 + - CLKPWR_PCLKSEL_CAN2 : CAN 2 + - CLKPWR_PCLKSEL_ACF : ACF + - CLKPWR_PCLKSEL_QEI : QEI + - CLKPWR_PCLKSEL_PCB : PCB + - CLKPWR_PCLKSEL_I2C1 : I2C 1 + - CLKPWR_PCLKSEL_SSP0 : SSP 0 + - CLKPWR_PCLKSEL_TIMER2 : Timer 2 + - CLKPWR_PCLKSEL_TIMER3 : Timer 3 + - CLKPWR_PCLKSEL_UART2 : UART 2 + - CLKPWR_PCLKSEL_UART3 : UART 3 + - CLKPWR_PCLKSEL_I2C2 : I2C 2 + - CLKPWR_PCLKSEL_I2S : I2S + - CLKPWR_PCLKSEL_RIT : RIT + - CLKPWR_PCLKSEL_SYSCON : SYSCON + - CLKPWR_PCLKSEL_MC : MC + + * @param[in] DivVal Value of divider, should be: + * - CLKPWR_PCLKSEL_CCLK_DIV_4 : PCLK_peripheral = CCLK/4 + * - CLKPWR_PCLKSEL_CCLK_DIV_1 : PCLK_peripheral = CCLK/1 + * - CLKPWR_PCLKSEL_CCLK_DIV_2 : PCLK_peripheral = CCLK/2 + * + * @return none + **********************************************************************/ +void CLKPWR_SetPCLKDiv (uint32_t ClkType, uint32_t DivVal) +{ + uint32_t bitpos; + + bitpos = (ClkType < 32) ? (ClkType) : (ClkType - 32); + + /* PCLKSEL0 selected */ + if (ClkType < 32) + { + /* Clear two bit at bit position */ + LPC_SC->PCLKSEL0 &= (~(CLKPWR_PCLKSEL_BITMASK(bitpos))); + + /* Set two selected bit */ + LPC_SC->PCLKSEL0 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal)); + } + /* PCLKSEL1 selected */ + else + { + /* Clear two bit at bit position */ + LPC_SC->PCLKSEL1 &= ~(CLKPWR_PCLKSEL_BITMASK(bitpos)); + + /* Set two selected bit */ + LPC_SC->PCLKSEL1 |= (CLKPWR_PCLKSEL_SET(bitpos, DivVal)); + } +} + + +/*********************************************************************//** + * @brief Get current value of each Peripheral Clock Selection + * @param[in] ClkType Peripheral Clock Selection of each type, + * should be one of the following: + * - CLKPWR_PCLKSEL_WDT : WDT + - CLKPWR_PCLKSEL_TIMER0 : Timer 0 + - CLKPWR_PCLKSEL_TIMER1 : Timer 1 + - CLKPWR_PCLKSEL_UART0 : UART 0 + - CLKPWR_PCLKSEL_UART1 : UART 1 + - CLKPWR_PCLKSEL_PWM1 : PWM 1 + - CLKPWR_PCLKSEL_I2C0 : I2C 0 + - CLKPWR_PCLKSEL_SPI : SPI + - CLKPWR_PCLKSEL_SSP1 : SSP 1 + - CLKPWR_PCLKSEL_DAC : DAC + - CLKPWR_PCLKSEL_ADC : ADC + - CLKPWR_PCLKSEL_CAN1 : CAN 1 + - CLKPWR_PCLKSEL_CAN2 : CAN 2 + - CLKPWR_PCLKSEL_ACF : ACF + - CLKPWR_PCLKSEL_QEI : QEI + - CLKPWR_PCLKSEL_PCB : PCB + - CLKPWR_PCLKSEL_I2C1 : I2C 1 + - CLKPWR_PCLKSEL_SSP0 : SSP 0 + - CLKPWR_PCLKSEL_TIMER2 : Timer 2 + - CLKPWR_PCLKSEL_TIMER3 : Timer 3 + - CLKPWR_PCLKSEL_UART2 : UART 2 + - CLKPWR_PCLKSEL_UART3 : UART 3 + - CLKPWR_PCLKSEL_I2C2 : I2C 2 + - CLKPWR_PCLKSEL_I2S : I2S + - CLKPWR_PCLKSEL_RIT : RIT + - CLKPWR_PCLKSEL_SYSCON : SYSCON + - CLKPWR_PCLKSEL_MC : MC + + * @return Value of Selected Peripheral Clock Selection + **********************************************************************/ +uint32_t CLKPWR_GetPCLKSEL (uint32_t ClkType) +{ + uint32_t bitpos, retval; + + if (ClkType < 32) + { + bitpos = ClkType; + retval = LPC_SC->PCLKSEL0; + } + else + { + bitpos = ClkType - 32; + retval = LPC_SC->PCLKSEL1; + } + + retval = CLKPWR_PCLKSEL_GET(bitpos, retval); + return retval; +} + + + +/*********************************************************************//** + * @brief Get current value of each Peripheral Clock + * @param[in] ClkType Peripheral Clock Selection of each type, + * should be one of the following: + * - CLKPWR_PCLKSEL_WDT : WDT + - CLKPWR_PCLKSEL_TIMER0 : Timer 0 + - CLKPWR_PCLKSEL_TIMER1 : Timer 1 + - CLKPWR_PCLKSEL_UART0 : UART 0 + - CLKPWR_PCLKSEL_UART1 : UART 1 + - CLKPWR_PCLKSEL_PWM1 : PWM 1 + - CLKPWR_PCLKSEL_I2C0 : I2C 0 + - CLKPWR_PCLKSEL_SPI : SPI + - CLKPWR_PCLKSEL_SSP1 : SSP 1 + - CLKPWR_PCLKSEL_DAC : DAC + - CLKPWR_PCLKSEL_ADC : ADC + - CLKPWR_PCLKSEL_CAN1 : CAN 1 + - CLKPWR_PCLKSEL_CAN2 : CAN 2 + - CLKPWR_PCLKSEL_ACF : ACF + - CLKPWR_PCLKSEL_QEI : QEI + - CLKPWR_PCLKSEL_PCB : PCB + - CLKPWR_PCLKSEL_I2C1 : I2C 1 + - CLKPWR_PCLKSEL_SSP0 : SSP 0 + - CLKPWR_PCLKSEL_TIMER2 : Timer 2 + - CLKPWR_PCLKSEL_TIMER3 : Timer 3 + - CLKPWR_PCLKSEL_UART2 : UART 2 + - CLKPWR_PCLKSEL_UART3 : UART 3 + - CLKPWR_PCLKSEL_I2C2 : I2C 2 + - CLKPWR_PCLKSEL_I2S : I2S + - CLKPWR_PCLKSEL_RIT : RIT + - CLKPWR_PCLKSEL_SYSCON : SYSCON + - CLKPWR_PCLKSEL_MC : MC + + * @return Value of Selected Peripheral Clock + **********************************************************************/ +uint32_t CLKPWR_GetPCLK (uint32_t ClkType) +{ + uint32_t retval, div; + + retval = SystemCoreClock; + div = CLKPWR_GetPCLKSEL(ClkType); + + switch (div) + { + case 0: + div = 4; + break; + + case 1: + div = 1; + break; + + case 2: + div = 2; + break; + + case 3: + div = 8; + break; + } + retval /= div; + + return retval; +} + + + +/*********************************************************************//** + * @brief Configure power supply for each peripheral according to NewState + * @param[in] PPType Type of peripheral used to enable power, + * should be one of the following: + * - CLKPWR_PCONP_PCTIM0 : Timer 0 + - CLKPWR_PCONP_PCTIM1 : Timer 1 + - CLKPWR_PCONP_PCUART0 : UART 0 + - CLKPWR_PCONP_PCUART1 : UART 1 + - CLKPWR_PCONP_PCPWM1 : PWM 1 + - CLKPWR_PCONP_PCI2C0 : I2C 0 + - CLKPWR_PCONP_PCSPI : SPI + - CLKPWR_PCONP_PCRTC : RTC + - CLKPWR_PCONP_PCSSP1 : SSP 1 + - CLKPWR_PCONP_PCAD : ADC + - CLKPWR_PCONP_PCAN1 : CAN 1 + - CLKPWR_PCONP_PCAN2 : CAN 2 + - CLKPWR_PCONP_PCGPIO : GPIO + - CLKPWR_PCONP_PCRIT : RIT + - CLKPWR_PCONP_PCMC : MC + - CLKPWR_PCONP_PCQEI : QEI + - CLKPWR_PCONP_PCI2C1 : I2C 1 + - CLKPWR_PCONP_PCSSP0 : SSP 0 + - CLKPWR_PCONP_PCTIM2 : Timer 2 + - CLKPWR_PCONP_PCTIM3 : Timer 3 + - CLKPWR_PCONP_PCUART2 : UART 2 + - CLKPWR_PCONP_PCUART3 : UART 3 + - CLKPWR_PCONP_PCI2C2 : I2C 2 + - CLKPWR_PCONP_PCI2S : I2S + - CLKPWR_PCONP_PCGPDMA : GPDMA + - CLKPWR_PCONP_PCENET : Ethernet + - CLKPWR_PCONP_PCUSB : USB + * + * @param[in] NewState New state of Peripheral Power, should be: + * - ENABLE : Enable power for this peripheral + * - DISABLE : Disable power for this peripheral + * + * @return none + **********************************************************************/ +void CLKPWR_ConfigPPWR (uint32_t PPType, FunctionalState NewState) +{ + if (NewState == ENABLE) + { + LPC_SC->PCONP |= PPType & CLKPWR_PCONP_BITMASK; + } + else if (NewState == DISABLE) + { + LPC_SC->PCONP &= (~PPType) & CLKPWR_PCONP_BITMASK; + } +} + + +/*********************************************************************//** + * @brief Enter Sleep mode with co-operated instruction by the Cortex-M3. + * @param[in] None + * @return None + **********************************************************************/ +void CLKPWR_Sleep(void) +{ + LPC_SC->PCON = 0x00; + /* Sleep Mode*/ + __WFI(); +} + + +/*********************************************************************//** + * @brief Enter Deep Sleep mode with co-operated instruction by the Cortex-M3. + * @param[in] None + * @return None + **********************************************************************/ +void CLKPWR_DeepSleep(void) +{ + /* Deep-Sleep Mode, set SLEEPDEEP bit */ + SCB->SCR = 0x4; + LPC_SC->PCON = 0x8; + /* Deep Sleep Mode*/ + __WFI(); +} + + +/*********************************************************************//** + * @brief Enter Power Down mode with co-operated instruction by the Cortex-M3. + * @param[in] None + * @return None + **********************************************************************/ +void CLKPWR_PowerDown(void) +{ + /* Deep-Sleep Mode, set SLEEPDEEP bit */ + SCB->SCR = 0x4; + LPC_SC->PCON = 0x09; + /* Power Down Mode*/ + __WFI(); +} + + +/*********************************************************************//** + * @brief Enter Deep Power Down mode with co-operated instruction by the Cortex-M3. + * @param[in] None + * @return None + **********************************************************************/ +void CLKPWR_DeepPowerDown(void) +{ + /* Deep-Sleep Mode, set SLEEPDEEP bit */ + SCB->SCR = 0x4; + LPC_SC->PCON = 0x03; + /* Deep Power Down Mode*/ + __WFI(); +} + +/** + * @} + */ + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */
--- a/lpc17xx_clkpwr.h Sun Jun 12 11:23:03 2011 +0000 +++ b/lpc17xx_clkpwr.h Sun Jun 12 19:17:11 2011 +0000 @@ -100,9 +100,9 @@ #define CLKPWR_PCLKSEL_MC ((uint32_t)(62)) /** Macro for Peripheral Clock Selection register bit values - * Note: When CCLK_DIV_8, Peripheral�s clock is selected to + * Note: When CCLK_DIV_8, Peripheral�s clock is selected to * PCLK_xyz = CCLK/8 except for CAN1, CAN2, and CAN filtering - * when �11�selects PCLK_xyz = CCLK/6 */ + * when �11�selects PCLK_xyz = CCLK/6 */ /* Peripheral clock divider is set to 4 from CCLK */ #define CLKPWR_PCLKSEL_CCLK_DIV_4 ((uint32_t)(0)) /** Peripheral clock divider is the same with CCLK */
--- a/lpc17xx_emac.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,950 +0,0 @@ -/** - * @file lpc17xx_emac.c - * @brief Contains all functions support for Ethernet MAC firmware library on LPC17xx - * @version 2.0 - * @date 21. May. 2010 - * @author NXP MCU SW Application Team - ************************************************************************** - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * products. This software is supplied "AS IS" without any warranties. - * NXP Semiconductors assumes no responsibility or liability for the - * use of the software, conveys no license or title under any patent, - * copyright, or mask work right to the product. NXP Semiconductors - * reserves the right to make changes in the software without - * notification. NXP Semiconductors also make no representation or - * warranty that such application will be suitable for the specified - * use without further testing or modification. - **********************************************************************/ - -/* Peripheral group ----------------------------------------------------------- */ -/** @addtogroup EMAC - * @{ - */ - -/* Includes ------------------------------------------------------------------- */ -#include "lpc17xx_emac.h" -#include "lpc17xx_clkpwr.h" - -/* If this source file built with example, the LPC17xx FW library configuration - * file in each example directory ("lpc17xx_libcfg.h") must be included, - * otherwise the default FW library configuration file must be included instead - */ -#ifdef __BUILD_WITH_EXAMPLE__ -#include "lpc17xx_libcfg.h" -#else -#include "lpc17xx_libcfg_default.h" -#endif /* __BUILD_WITH_EXAMPLE__ */ - - -#ifdef _EMAC - -/* Private Variables ---------------------------------------------------------- */ -/** @defgroup EMAC_Private_Variables EMAC Private Variables - * @{ - */ - -/* MII Mgmt Configuration register - Clock divider setting */ -const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 }; - -/* EMAC local DMA Descriptors */ - -/** Rx Descriptor data array */ -static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG]; - -/** Rx Status data array - Must be 8-Byte aligned */ -#if defined ( __CC_ARM ) -static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; -#elif defined ( __ICCARM__ ) -#pragma data_alignment=8 -static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; -#elif defined ( __GNUC__ ) -static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; -#endif - -/** Tx Descriptor data array */ -static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG]; -/** Tx Status data array */ -static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG]; - -/* EMAC local DMA buffers */ -/** Rx buffer data */ -static uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2]; -/** Tx buffer data */ -static uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2]; - -/** - * @} - */ - -/* Private Functions ---------------------------------------------------------- */ -static void rx_descr_init (void); -static void tx_descr_init (void); -static int32_t write_PHY (uint32_t PhyReg, uint16_t Value); -static int32_t read_PHY (uint32_t PhyReg); - -static void setEmacAddr(uint8_t abStationAddr[]); -static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len); - - -/*--------------------------- rx_descr_init ---------------------------------*/ -/*********************************************************************//** - * @brief Initializes RX Descriptor - * @param[in] None - * @return None - ***********************************************************************/ -static void rx_descr_init (void) -{ - /* Initialize Receive Descriptor and Status array. */ - uint32_t i; - - for (i = 0; i < EMAC_NUM_RX_FRAG; i++) { - Rx_Desc[i].Packet = (uint32_t)&rx_buf[i]; - Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1); - Rx_Stat[i].Info = 0; - Rx_Stat[i].HashCRC = 0; - } - - /* Set EMAC Receive Descriptor Registers. */ - LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0]; - LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0]; - LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1; - - /* Rx Descriptors Point to 0 */ - LPC_EMAC->RxConsumeIndex = 0; -} - - -/*--------------------------- tx_descr_init ---- ----------------------------*/ -/*********************************************************************//** - * @brief Initializes TX Descriptor - * @param[in] None - * @return None - ***********************************************************************/ -static void tx_descr_init (void) { - /* Initialize Transmit Descriptor and Status array. */ - uint32_t i; - - for (i = 0; i < EMAC_NUM_TX_FRAG; i++) { - Tx_Desc[i].Packet = (uint32_t)&tx_buf[i]; - Tx_Desc[i].Ctrl = 0; - Tx_Stat[i].Info = 0; - } - - /* Set EMAC Transmit Descriptor Registers. */ - LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0]; - LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0]; - LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1; - - /* Tx Descriptors Point to 0 */ - LPC_EMAC->TxProduceIndex = 0; -} - - -/*--------------------------- write_PHY -------------------------------------*/ -/*********************************************************************//** - * @brief Write value to PHY device - * @param[in] PhyReg: PHY Register address - * @param[in] Value: Value to write - * @return 0 - if success - * 1 - if fail - ***********************************************************************/ -static int32_t write_PHY (uint32_t PhyReg, uint16_t Value) -{ - /* Write a data 'Value' to PHY register 'PhyReg'. */ - uint32_t tout; - - LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; - LPC_EMAC->MWTD = Value; - - /* Wait until operation completed */ - tout = 0; - for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) { - if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { - return (0); - } - } - // Time out! - return (-1); -} - - -/*--------------------------- read_PHY --------------------------------------*/ -/*********************************************************************//** - * @brief Read value from PHY device - * @param[in] PhyReg: PHY Register address - * @return 0 - if success - * 1 - if fail - ***********************************************************************/ -static int32_t read_PHY (uint32_t PhyReg) -{ - /* Read a PHY register 'PhyReg'. */ - uint32_t tout; - - LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; - LPC_EMAC->MCMD = EMAC_MCMD_READ; - - /* Wait until operation completed */ - tout = 0; - for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) { - if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { - LPC_EMAC->MCMD = 0; - return (LPC_EMAC->MRDD); - } - } - // Time out! - return (-1); -} - -/*********************************************************************//** - * @brief Set Station MAC address for EMAC module - * @param[in] abStationAddr Pointer to Station address that contains 6-bytes - * of MAC address (should be in order from MAC Address 1 to MAC Address 6) - * @return None - **********************************************************************/ -static void setEmacAddr(uint8_t abStationAddr[]) -{ - /* Set the Ethernet MAC Address registers */ - LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4]; - LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2]; - LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0]; -} - - -/*********************************************************************//** - * @brief Calculates CRC code for number of bytes in the frame - * @param[in] frame_no_fcs Pointer to the first byte of the frame - * @param[in] frame_len length of the frame without the FCS - * @return the CRC as a 32 bit integer - **********************************************************************/ -static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len) -{ - int i; // iterator - int j; // another iterator - char byte; // current byte - int crc; // CRC result - int q0, q1, q2, q3; // temporary variables - crc = 0xFFFFFFFF; - for (i = 0; i < frame_len; i++) { - byte = *frame_no_fcs++; - for (j = 0; j < 2; j++) { - if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) { - q3 = 0x04C11DB7; - } else { - q3 = 0x00000000; - } - if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) { - q2 = 0x09823B6E; - } else { - q2 = 0x00000000; - } - if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) { - q1 = 0x130476DC; - } else { - q1 = 0x00000000; - } - if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) { - q0 = 0x2608EDB8; - } else { - q0 = 0x00000000; - } - crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0; - byte >>= 4; - } - } - return crc; -} -/* End of Private Functions --------------------------------------------------- */ - - -/* Public Functions ----------------------------------------------------------- */ -/** @addtogroup EMAC_Public_Functions - * @{ - */ - - -/*********************************************************************//** - * @brief Initializes the EMAC peripheral according to the specified -* parameters in the EMAC_ConfigStruct. - * @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure -* that contains the configuration information for the -* specified EMAC peripheral. - * @return None - * - * Note: This function will initialize EMAC module according to procedure below: - * - Remove the soft reset condition from the MAC - * - Configure the PHY via the MIIM interface of the MAC - * - Select RMII mode - * - Configure the transmit and receive DMA engines, including the descriptor arrays - * - Configure the host registers (MAC1,MAC2 etc.) in the MAC - * - Enable the receive and transmit data paths - * In default state after initializing, only Rx Done and Tx Done interrupt are enabled, - * all remain interrupts are disabled - * (Ref. from LPC17xx UM) - **********************************************************************/ -Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct) -{ - /* Initialize the EMAC Ethernet controller. */ - int32_t regv,tout, tmp; - - /* Set up clock and power for Ethernet module */ - CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE); - - /* Reset all EMAC internal modules */ - LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX | - EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES; - - LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM; - - /* A short delay after reset. */ - for (tout = 100; tout; tout--); - - /* Initialize MAC control registers. */ - LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL; - LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN; - LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN; - /* - * Find the clock that close to desired target clock - */ - tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK; - for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){ - if (EMAC_clkdiv[tout] >= tmp) break; - } - tout++; - // Write to MAC configuration register and reset - LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII; - // release reset - LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII); - LPC_EMAC->CLRT = EMAC_CLRT_DEF; - LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF; - - /* Enable Reduced MII interface. */ - LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM; - - /* Reset Reduced MII Logic. */ - LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII; - - for (tout = 100; tout; tout--); - LPC_EMAC->SUPP = 0; - - /* Put the DP83848C in reset mode */ - write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET); - - /* Wait for hardware reset to end. */ - for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { - regv = read_PHY (EMAC_PHY_REG_BMCR); - if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) { - /* Reset complete, device not Power Down. */ - break; - } - if (tout == 0){ - // Time out, return ERROR - return (ERROR); - } - } - - // Set PHY mode - if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){ - return (ERROR); - } - - // Set EMAC address - setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr); - - /* Initialize Tx and Rx DMA Descriptors */ - rx_descr_init (); - tx_descr_init (); - - // Set Receive Filter register: enable broadcast and multicast - LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN; - - /* Enable Rx Done and Tx Done interrupt for EMAC */ - LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE; - - /* Reset all interrupts */ - LPC_EMAC->IntClear = 0xFFFF; - - /* Enable receive and transmit mode of MAC Ethernet core */ - LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN); - LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; - - return SUCCESS; -} - - -/*********************************************************************//** - * @brief De-initializes the EMAC peripheral registers to their -* default reset values. - * @param[in] None - * @return None - **********************************************************************/ -void EMAC_DeInit(void) -{ - // Disable all interrupt - LPC_EMAC->IntEnable = 0x00; - // Clear all pending interrupt - LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP); - - /* TurnOff clock and power for Ethernet module */ - CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE); -} - - -/*********************************************************************//** - * @brief Check specified PHY status in EMAC peripheral - * @param[in] ulPHYState Specified PHY Status Type, should be: - * - EMAC_PHY_STAT_LINK: Link Status - * - EMAC_PHY_STAT_SPEED: Speed Status - * - EMAC_PHY_STAT_DUP: Duplex Status - * @return Status of specified PHY status (0 or 1). - * (-1) if error. - * - * Note: - * For EMAC_PHY_STAT_LINK, return value: - * - 0: Link Down - * - 1: Link Up - * For EMAC_PHY_STAT_SPEED, return value: - * - 0: 10Mbps - * - 1: 100Mbps - * For EMAC_PHY_STAT_DUP, return value: - * - 0: Half-Duplex - * - 1: Full-Duplex - **********************************************************************/ -int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState) -{ - int32_t regv, tmp; -#ifdef MCB_LPC_1768 - regv = read_PHY (EMAC_PHY_REG_STS); - switch(ulPHYState){ - case EMAC_PHY_STAT_LINK: - tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0; - break; - case EMAC_PHY_STAT_SPEED: - tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1; - break; - case EMAC_PHY_STAT_DUP: - tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; - break; -#elif defined(IAR_LPC_1768) - /* Use IAR_LPC_1768 board: - * FSZ8721BL doesn't have Status Register - * so we read Basic Mode Status Register (0x01h) instead - */ - regv = read_PHY (EMAC_PHY_REG_BMSR); - switch(ulPHYState){ - case EMAC_PHY_STAT_LINK: - tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0; - break; - case EMAC_PHY_STAT_SPEED: - tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0; - break; - case EMAC_PHY_STAT_DUP: - tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; - break; -#endif - default: - tmp = -1; - break; - } - return (tmp); -} - - -/*********************************************************************//** - * @brief Set specified PHY mode in EMAC peripheral - * @param[in] ulPHYMode Specified PHY mode, should be: - * - EMAC_MODE_AUTO - * - EMAC_MODE_10M_FULL - * - EMAC_MODE_10M_HALF - * - EMAC_MODE_100M_FULL - * - EMAC_MODE_100M_HALF - * @return Return (0) if no error, otherwise return (-1) - **********************************************************************/ -int32_t EMAC_SetPHYMode(uint32_t ulPHYMode) -{ - int32_t id1, id2, tout, regv; - - /* Check if this is a DP83848C PHY. */ - id1 = read_PHY (EMAC_PHY_REG_IDR1); - id2 = read_PHY (EMAC_PHY_REG_IDR2); - -#ifdef MCB_LPC_1768 - if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) { - switch(ulPHYMode){ - case EMAC_MODE_AUTO: - write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); -#elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */ - if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) { - /* Configure the PHY device */ - switch(ulPHYMode){ - case EMAC_MODE_AUTO: - /* Use auto-negotiation about the link speed. */ - write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); -// write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN); -#endif - /* Wait to complete Auto_Negotiation */ - for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { - regv = read_PHY (EMAC_PHY_REG_BMSR); - if (regv & EMAC_PHY_BMSR_AUTO_DONE) { - /* Auto-negotiation Complete. */ - break; - } - if (tout == 0){ - // Time out, return error - return (-1); - } - } - break; - case EMAC_MODE_10M_FULL: - /* Connect at 10MBit full-duplex */ - write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M); - break; - case EMAC_MODE_10M_HALF: - /* Connect at 10MBit half-duplex */ - write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M); - break; - case EMAC_MODE_100M_FULL: - /* Connect at 100MBit full-duplex */ - write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M); - break; - case EMAC_MODE_100M_HALF: - /* Connect at 100MBit half-duplex */ - write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M); - break; - default: - // un-supported - return (-1); - } - } - // It's not correct module ID - else { - return (-1); - } - - // Update EMAC configuration with current PHY status - if (EMAC_UpdatePHYStatus() < 0){ - return (-1); - } - - // Complete - return (0); -} - - -/*********************************************************************//** - * @brief Auto-Configures value for the EMAC configuration register to - * match with current PHY mode - * @param[in] None - * @return Return (0) if no error, otherwise return (-1) - * - * Note: The EMAC configuration will be auto-configured: - * - Speed mode. - * - Half/Full duplex mode - **********************************************************************/ -int32_t EMAC_UpdatePHYStatus(void) -{ - int32_t regv, tout; - - /* Check the link status. */ -#ifdef MCB_LPC_1768 - for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { - regv = read_PHY (EMAC_PHY_REG_STS); - if (regv & EMAC_PHY_SR_LINK) { - /* Link is on. */ - break; - } - if (tout == 0){ - // time out - return (-1); - } - } - /* Configure Full/Half Duplex mode. */ - if (regv & EMAC_PHY_SR_DUP) { - /* Full duplex is enabled. */ - LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; - LPC_EMAC->Command |= EMAC_CR_FULL_DUP; - LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; - } else { - /* Half duplex mode. */ - LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; - } - if (regv & EMAC_PHY_SR_SPEED) { - /* 10MBit mode. */ - LPC_EMAC->SUPP = 0; - } else { - /* 100MBit mode. */ - LPC_EMAC->SUPP = EMAC_SUPP_SPEED; - } -#elif defined(IAR_LPC_1768) - for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { - regv = read_PHY (EMAC_PHY_REG_BMSR); - if (regv & EMAC_PHY_BMSR_LINK_STATUS) { - /* Link is on. */ - break; - } - if (tout == 0){ - // time out - return (-1); - } - } - - /* Configure Full/Half Duplex mode. */ - if (regv & EMAC_PHY_SR_FULL_DUP) { - /* Full duplex is enabled. */ - LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; - LPC_EMAC->Command |= EMAC_CR_FULL_DUP; - LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; - } else { - /* Half duplex mode. */ - LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; - } - - /* Configure 100MBit/10MBit mode. */ - if (!(regv & EMAC_PHY_SR_100_SPEED)) { - /* 10MBit mode. */ - LPC_EMAC->SUPP = 0; - } else { - /* 100MBit mode. */ - LPC_EMAC->SUPP = EMAC_SUPP_SPEED; - } -#endif - // Complete - return (0); -} - - -/*********************************************************************//** - * @brief Enable/Disable hash filter functionality for specified destination - * MAC address in EMAC module - * @param[in] dstMAC_addr Pointer to the first MAC destination address, should - * be 6-bytes length, in order LSB to the MSB - * @param[in] NewState New State of this command, should be: - * - ENABLE. - * - DISABLE. - * @return None - * - * Note: - * The standard Ethernet cyclic redundancy check (CRC) function is calculated from - * the 6 byte destination address in the Ethernet frame (this CRC is calculated - * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of - * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access - * the hash table: it is used as an index in the 64 bit HashFilter register that has been - * programmed with accept values. If the selected accept value is 1, the frame is - * accepted. - **********************************************************************/ -void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState) -{ - uint32_t *pReg; - uint32_t tmp; - int32_t crc; - - // Calculate the CRC from the destination MAC address - crc = emac_CRCCalc(dstMAC_addr, 6); - // Extract the value from CRC to get index value for hash filter table - crc = (crc >> 23) & 0x3F; - - pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \ - : ((uint32_t *)&LPC_EMAC->HashFilterL); - tmp = (crc > 31) ? (crc - 32) : crc; - if (NewState == ENABLE) { - (*pReg) |= (1UL << tmp); - } else { - (*pReg) &= ~(1UL << tmp); - } - // Enable Rx Filter - LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT; -} - -/*********************************************************************//** - * @brief Enable/Disable Filter mode for each specified type EMAC peripheral - * @param[in] ulFilterMode Filter mode, should be: - * - EMAC_RFC_UCAST_EN: all frames of unicast types - * will be accepted - * - EMAC_RFC_BCAST_EN: broadcast frame will be - * accepted - * - EMAC_RFC_MCAST_EN: all frames of multicast - * types will be accepted - * - EMAC_RFC_UCAST_HASH_EN: The imperfect hash - * filter will be applied to unicast addresses - * - EMAC_RFC_MCAST_HASH_EN: The imperfect hash - * filter will be applied to multicast addresses - * - EMAC_RFC_PERFECT_EN: the destination address - * will be compared with the 6 byte station address - * programmed in the station address by the filter - * - EMAC_RFC_MAGP_WOL_EN: the result of the magic - * packet filter will generate a WoL interrupt when - * there is a match - * - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address - * matching filter and the imperfect hash filter will - * generate a WoL interrupt when there is a match - * @param[in] NewState New State of this command, should be: - * - ENABLE - * - DISABLE - * @return None - **********************************************************************/ -void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState) -{ - if (NewState == ENABLE){ - LPC_EMAC->RxFilterCtrl |= ulFilterMode; - } else { - LPC_EMAC->RxFilterCtrl &= ~ulFilterMode; - } -} - -/*********************************************************************//** - * @brief Get status of Wake On LAN Filter for each specified - * type in EMAC peripheral, clear this status if it is set - * @param[in] ulWoLMode WoL Filter mode, should be: - * - EMAC_WOL_UCAST: unicast frames caused WoL - * - EMAC_WOL_UCAST: broadcast frame caused WoL - * - EMAC_WOL_MCAST: multicast frame caused WoL - * - EMAC_WOL_UCAST_HASH: unicast frame that passes the - * imperfect hash filter caused WoL - * - EMAC_WOL_MCAST_HASH: multicast frame that passes the - * imperfect hash filter caused WoL - * - EMAC_WOL_PERFECT:perfect address matching filter - * caused WoL - * - EMAC_WOL_RX_FILTER: the receive filter caused WoL - * - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL - * @return SET/RESET - **********************************************************************/ -FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode) -{ - if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) { - LPC_EMAC->RxFilterWoLClear = ulWoLMode; - return SET; - } else { - return RESET; - } -} - - -/*********************************************************************//** - * @brief Write data to Tx packet data buffer at current index due to - * TxProduceIndex - * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure - * data that contain specified information about - * Packet data buffer. - * @return None - **********************************************************************/ -void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) -{ - uint32_t idx,len; - uint32_t *sp,*dp; - - idx = LPC_EMAC->TxProduceIndex; - sp = (uint32_t *)pDataStruct->pbDataBuf; - dp = (uint32_t *)Tx_Desc[idx].Packet; - /* Copy frame data to EMAC packet buffers. */ - for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { - *dp++ = *sp++; - } - Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST); -} - -/*********************************************************************//** - * @brief Read data from Rx packet data buffer at current index due - * to RxConsumeIndex - * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure - * data that contain specified information about - * Packet data buffer. - * @return None - **********************************************************************/ -void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) -{ - uint32_t idx, len; - uint32_t *dp, *sp; - - idx = LPC_EMAC->RxConsumeIndex; - dp = (uint32_t *)pDataStruct->pbDataBuf; - sp = (uint32_t *)Rx_Desc[idx].Packet; - - if (pDataStruct->pbDataBuf != NULL) { - for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { - *dp++ = *sp++; - } - } -} - -/*********************************************************************//** - * @brief Enable/Disable interrupt for each type in EMAC - * @param[in] ulIntType Interrupt Type, should be: - * - EMAC_INT_RX_OVERRUN: Receive Overrun - * - EMAC_INT_RX_ERR: Receive Error - * - EMAC_INT_RX_FIN: Receive Descriptor Finish - * - EMAC_INT_RX_DONE: Receive Done - * - EMAC_INT_TX_UNDERRUN: Transmit Under-run - * - EMAC_INT_TX_ERR: Transmit Error - * - EMAC_INT_TX_FIN: Transmit descriptor finish - * - EMAC_INT_TX_DONE: Transmit Done - * - EMAC_INT_SOFT_INT: Software interrupt - * - EMAC_INT_WAKEUP: Wakeup interrupt - * @param[in] NewState New State of this function, should be: - * - ENABLE. - * - DISABLE. - * @return None - **********************************************************************/ -void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState) -{ - if (NewState == ENABLE) { - LPC_EMAC->IntEnable |= ulIntType; - } else { - LPC_EMAC->IntEnable &= ~(ulIntType); - } -} - -/*********************************************************************//** - * @brief Check whether if specified interrupt flag is set or not - * for each interrupt type in EMAC and clear interrupt pending - * if it is set. - * @param[in] ulIntType Interrupt Type, should be: - * - EMAC_INT_RX_OVERRUN: Receive Overrun - * - EMAC_INT_RX_ERR: Receive Error - * - EMAC_INT_RX_FIN: Receive Descriptor Finish - * - EMAC_INT_RX_DONE: Receive Done - * - EMAC_INT_TX_UNDERRUN: Transmit Under-run - * - EMAC_INT_TX_ERR: Transmit Error - * - EMAC_INT_TX_FIN: Transmit descriptor finish - * - EMAC_INT_TX_DONE: Transmit Done - * - EMAC_INT_SOFT_INT: Software interrupt - * - EMAC_INT_WAKEUP: Wakeup interrupt - * @return New state of specified interrupt (SET or RESET) - **********************************************************************/ -IntStatus EMAC_IntGetStatus(uint32_t ulIntType) -{ - if (LPC_EMAC->IntStatus & ulIntType) { - LPC_EMAC->IntClear = ulIntType; - return SET; - } else { - return RESET; - } -} - - -/*********************************************************************//** - * @brief Check whether if the current RxConsumeIndex is not equal to the - * current RxProduceIndex. - * @param[in] None - * @return TRUE if they're not equal, otherwise return FALSE - * - * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex, - * it means there're available data has been received. They should be read - * out and released the Receive Data Buffer by updating the RxConsumeIndex value. - **********************************************************************/ -Bool EMAC_CheckReceiveIndex(void) -{ - if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) { - return TRUE; - } else { - return FALSE; - } -} - - -/*********************************************************************//** - * @brief Check whether if the current TxProduceIndex is not equal to the - * current RxProduceIndex - 1. - * @param[in] None - * @return TRUE if they're not equal, otherwise return FALSE - * - * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1, - * it means the transmit buffer is available and data can be written to transmit - * buffer to be sent. - **********************************************************************/ -Bool EMAC_CheckTransmitIndex(void) -{ - uint32_t tmp = LPC_EMAC->TxConsumeIndex -1; - if (LPC_EMAC->TxProduceIndex == tmp) { - return FALSE; - } else { - return TRUE; - } -} - - -/*********************************************************************//** - * @brief Get current status value of receive data (due to RxConsumeIndex) - * @param[in] ulRxStatType Received Status type, should be one of following: - * - EMAC_RINFO_CTRL_FRAME: Control Frame - * - EMAC_RINFO_VLAN: VLAN Frame - * - EMAC_RINFO_FAIL_FILT: RX Filter Failed - * - EMAC_RINFO_MCAST: Multicast Frame - * - EMAC_RINFO_BCAST: Broadcast Frame - * - EMAC_RINFO_CRC_ERR: CRC Error in Frame - * - EMAC_RINFO_SYM_ERR: Symbol Error from PHY - * - EMAC_RINFO_LEN_ERR: Length Error - * - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size) - * - EMAC_RINFO_ALIGN_ERR: Alignment error - * - EMAC_RINFO_OVERRUN: Receive overrun - * - EMAC_RINFO_NO_DESCR: No new Descriptor available - * - EMAC_RINFO_LAST_FLAG: last Fragment in Frame - * - EMAC_RINFO_ERR: Error Occurred (OR of all error) - * @return Current value of receive data (due to RxConsumeIndex) - **********************************************************************/ -FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType) -{ - uint32_t idx; - idx = LPC_EMAC->RxConsumeIndex; - return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET); -} - - -/*********************************************************************//** - * @brief Get size of current Received data in received buffer (due to - * RxConsumeIndex) - * @param[in] None - * @return Size of received data - **********************************************************************/ -uint32_t EMAC_GetReceiveDataSize(void) -{ - uint32_t idx; - idx =LPC_EMAC->RxConsumeIndex; - return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE); -} - -/*********************************************************************//** - * @brief Increase the RxConsumeIndex (after reading the Receive buffer - * to release the Receive buffer) and wrap-around the index if - * it reaches the maximum Receive Number - * @param[in] None - * @return None - **********************************************************************/ -void EMAC_UpdateRxConsumeIndex(void) -{ - // Get current Rx consume index - uint32_t idx = LPC_EMAC->RxConsumeIndex; - - /* Release frame from EMAC buffer */ - if (++idx == EMAC_NUM_RX_FRAG) idx = 0; - LPC_EMAC->RxConsumeIndex = idx; -} - -/*********************************************************************//** - * @brief Increase the TxProduceIndex (after writting to the Transmit buffer - * to enable the Transmit buffer) and wrap-around the index if - * it reaches the maximum Transmit Number - * @param[in] None - * @return None - **********************************************************************/ -void EMAC_UpdateTxProduceIndex(void) -{ - // Get current Tx produce index - uint32_t idx = LPC_EMAC->TxProduceIndex; - - /* Start frame transmission */ - if (++idx == EMAC_NUM_TX_FRAG) idx = 0; - LPC_EMAC->TxProduceIndex = idx; -} - - -/** - * @} - */ - -#endif /* _EMAC */ - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lpc17xx_emac.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,950 @@ +/** + * @file lpc17xx_emac.c + * @brief Contains all functions support for Ethernet MAC firmware library on LPC17xx + * @version 2.0 + * @date 21. May. 2010 + * @author NXP MCU SW Application Team + ************************************************************************** + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * products. This software is supplied "AS IS" without any warranties. + * NXP Semiconductors assumes no responsibility or liability for the + * use of the software, conveys no license or title under any patent, + * copyright, or mask work right to the product. NXP Semiconductors + * reserves the right to make changes in the software without + * notification. NXP Semiconductors also make no representation or + * warranty that such application will be suitable for the specified + * use without further testing or modification. + **********************************************************************/ + +/* Peripheral group ----------------------------------------------------------- */ +/** @addtogroup EMAC + * @{ + */ + +/* Includes ------------------------------------------------------------------- */ +#include "lpc17xx_emac.h" +#include "lpc17xx_clkpwr.h" + +/* If this source file built with example, the LPC17xx FW library configuration + * file in each example directory ("lpc17xx_libcfg.h") must be included, + * otherwise the default FW library configuration file must be included instead + */ +#ifdef __BUILD_WITH_EXAMPLE__ +#include "lpc17xx_libcfg.h" +#else +#include "lpc17xx_libcfg_default.h" +#endif /* __BUILD_WITH_EXAMPLE__ */ + + +#ifdef _EMAC + +/* Private Variables ---------------------------------------------------------- */ +/** @defgroup EMAC_Private_Variables EMAC Private Variables + * @{ + */ + +/* MII Mgmt Configuration register - Clock divider setting */ +const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 }; + +/* EMAC local DMA Descriptors */ + +/** Rx Descriptor data array */ +static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG]; + +/** Rx Status data array - Must be 8-Byte aligned */ +#if defined ( __CC_ARM ) +static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; +#elif defined ( __ICCARM__ ) +#pragma data_alignment=8 +static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; +#elif defined ( __GNUC__ ) +static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; +#endif + +/** Tx Descriptor data array */ +static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG]; +/** Tx Status data array */ +static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG]; + +/* EMAC local DMA buffers */ +/** Rx buffer data */ +static __align(8) uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2] __attribute((section("AHBSRAM1"),aligned)) ; +/** Tx buffer data */ +static __align(8) uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2] __attribute((section("AHBSRAM1"),aligned)) ; + +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------- */ +static void rx_descr_init (void); +static void tx_descr_init (void); +static int32_t write_PHY (uint32_t PhyReg, uint16_t Value); +static int32_t read_PHY (uint32_t PhyReg); + +static void setEmacAddr(uint8_t abStationAddr[]); +static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len); + + +/*--------------------------- rx_descr_init ---------------------------------*/ +/*********************************************************************//** + * @brief Initializes RX Descriptor + * @param[in] None + * @return None + ***********************************************************************/ +static void rx_descr_init (void) +{ + /* Initialize Receive Descriptor and Status array. */ + uint32_t i; + + for (i = 0; i < EMAC_NUM_RX_FRAG; i++) { + Rx_Desc[i].Packet = (uint32_t)&rx_buf[i]; + Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1); + Rx_Stat[i].Info = 0; + Rx_Stat[i].HashCRC = 0; + } + + /* Set EMAC Receive Descriptor Registers. */ + LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0]; + LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0]; + LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1; + + /* Rx Descriptors Point to 0 */ + LPC_EMAC->RxConsumeIndex = 0; +} + + +/*--------------------------- tx_descr_init ---- ----------------------------*/ +/*********************************************************************//** + * @brief Initializes TX Descriptor + * @param[in] None + * @return None + ***********************************************************************/ +static void tx_descr_init (void) { + /* Initialize Transmit Descriptor and Status array. */ + uint32_t i; + + for (i = 0; i < EMAC_NUM_TX_FRAG; i++) { + Tx_Desc[i].Packet = (uint32_t)&tx_buf[i]; + Tx_Desc[i].Ctrl = 0; + Tx_Stat[i].Info = 0; + } + + /* Set EMAC Transmit Descriptor Registers. */ + LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0]; + LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0]; + LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1; + + /* Tx Descriptors Point to 0 */ + LPC_EMAC->TxProduceIndex = 0; +} + + +/*--------------------------- write_PHY -------------------------------------*/ +/*********************************************************************//** + * @brief Write value to PHY device + * @param[in] PhyReg: PHY Register address + * @param[in] Value: Value to write + * @return 0 - if success + * 1 - if fail + ***********************************************************************/ +static int32_t write_PHY (uint32_t PhyReg, uint16_t Value) +{ + /* Write a data 'Value' to PHY register 'PhyReg'. */ + uint32_t tout; + + LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; + LPC_EMAC->MWTD = Value; + + /* Wait until operation completed */ + tout = 0; + for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) { + if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { + return (0); + } + } + // Time out! + return (-1); +} + + +/*--------------------------- read_PHY --------------------------------------*/ +/*********************************************************************//** + * @brief Read value from PHY device + * @param[in] PhyReg: PHY Register address + * @return 0 - if success + * 1 - if fail + ***********************************************************************/ +static int32_t read_PHY (uint32_t PhyReg) +{ + /* Read a PHY register 'PhyReg'. */ + uint32_t tout; + + LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; + LPC_EMAC->MCMD = EMAC_MCMD_READ; + + /* Wait until operation completed */ + tout = 0; + for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) { + if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { + LPC_EMAC->MCMD = 0; + return (LPC_EMAC->MRDD); + } + } + // Time out! + return (-1); +} + +/*********************************************************************//** + * @brief Set Station MAC address for EMAC module + * @param[in] abStationAddr Pointer to Station address that contains 6-bytes + * of MAC address (should be in order from MAC Address 1 to MAC Address 6) + * @return None + **********************************************************************/ +static void setEmacAddr(uint8_t abStationAddr[]) +{ + /* Set the Ethernet MAC Address registers */ + LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4]; + LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2]; + LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0]; +} + + +/*********************************************************************//** + * @brief Calculates CRC code for number of bytes in the frame + * @param[in] frame_no_fcs Pointer to the first byte of the frame + * @param[in] frame_len length of the frame without the FCS + * @return the CRC as a 32 bit integer + **********************************************************************/ +static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len) +{ + int i; // iterator + int j; // another iterator + char byte; // current byte + int crc; // CRC result + int q0, q1, q2, q3; // temporary variables + crc = 0xFFFFFFFF; + for (i = 0; i < frame_len; i++) { + byte = *frame_no_fcs++; + for (j = 0; j < 2; j++) { + if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) { + q3 = 0x04C11DB7; + } else { + q3 = 0x00000000; + } + if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) { + q2 = 0x09823B6E; + } else { + q2 = 0x00000000; + } + if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) { + q1 = 0x130476DC; + } else { + q1 = 0x00000000; + } + if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) { + q0 = 0x2608EDB8; + } else { + q0 = 0x00000000; + } + crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0; + byte >>= 4; + } + } + return crc; +} +/* End of Private Functions --------------------------------------------------- */ + + +/* Public Functions ----------------------------------------------------------- */ +/** @addtogroup EMAC_Public_Functions + * @{ + */ + + +/*********************************************************************//** + * @brief Initializes the EMAC peripheral according to the specified +* parameters in the EMAC_ConfigStruct. + * @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure +* that contains the configuration information for the +* specified EMAC peripheral. + * @return None + * + * Note: This function will initialize EMAC module according to procedure below: + * - Remove the soft reset condition from the MAC + * - Configure the PHY via the MIIM interface of the MAC + * - Select RMII mode + * - Configure the transmit and receive DMA engines, including the descriptor arrays + * - Configure the host registers (MAC1,MAC2 etc.) in the MAC + * - Enable the receive and transmit data paths + * In default state after initializing, only Rx Done and Tx Done interrupt are enabled, + * all remain interrupts are disabled + * (Ref. from LPC17xx UM) + **********************************************************************/ +Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct) +{ + /* Initialize the EMAC Ethernet controller. */ + int32_t regv,tout, tmp; + + /* Set up clock and power for Ethernet module */ + CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE); + + /* Reset all EMAC internal modules */ + LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX | + EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES; + + LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM; + + /* A short delay after reset. */ + for (tout = 100; tout; tout--); + + /* Initialize MAC control registers. */ + LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL; + LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN; + LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN; + /* + * Find the clock that close to desired target clock + */ + tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK; + for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){ + if (EMAC_clkdiv[tout] >= tmp) break; + } + tout++; + // Write to MAC configuration register and reset + LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII; + // release reset + LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII); + LPC_EMAC->CLRT = EMAC_CLRT_DEF; + LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF; + + /* Enable Reduced MII interface. */ + LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM; + + /* Reset Reduced MII Logic. */ + LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII; + + for (tout = 100; tout; tout--); + LPC_EMAC->SUPP = 0; + + /* Put the DP83848C in reset mode */ + write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET); + + /* Wait for hardware reset to end. */ + for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { + regv = read_PHY (EMAC_PHY_REG_BMCR); + if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) { + /* Reset complete, device not Power Down. */ + break; + } + if (tout == 0){ + // Time out, return ERROR + return (ERROR); + } + } + + // Set PHY mode + if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){ + return (ERROR); + } + + // Set EMAC address + setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr); + + /* Initialize Tx and Rx DMA Descriptors */ + rx_descr_init (); + tx_descr_init (); + + // Set Receive Filter register: enable broadcast and multicast + LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN; + + /* Enable Rx Done and Tx Done interrupt for EMAC */ + LPC_EMAC->IntEnable = EMAC_INT_RX_DONE/* | EMAC_INT_TX_DONE*/; + + /* Reset all interrupts */ + LPC_EMAC->IntClear = 0xFFFF; + + /* Enable receive and transmit mode of MAC Ethernet core */ + LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN); + LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; + + return SUCCESS; +} + + +/*********************************************************************//** + * @brief De-initializes the EMAC peripheral registers to their +* default reset values. + * @param[in] None + * @return None + **********************************************************************/ +void EMAC_DeInit(void) +{ + // Disable all interrupt + LPC_EMAC->IntEnable = 0x00; + // Clear all pending interrupt + LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP); + + /* TurnOff clock and power for Ethernet module */ + CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE); +} + + +/*********************************************************************//** + * @brief Check specified PHY status in EMAC peripheral + * @param[in] ulPHYState Specified PHY Status Type, should be: + * - EMAC_PHY_STAT_LINK: Link Status + * - EMAC_PHY_STAT_SPEED: Speed Status + * - EMAC_PHY_STAT_DUP: Duplex Status + * @return Status of specified PHY status (0 or 1). + * (-1) if error. + * + * Note: + * For EMAC_PHY_STAT_LINK, return value: + * - 0: Link Down + * - 1: Link Up + * For EMAC_PHY_STAT_SPEED, return value: + * - 0: 10Mbps + * - 1: 100Mbps + * For EMAC_PHY_STAT_DUP, return value: + * - 0: Half-Duplex + * - 1: Full-Duplex + **********************************************************************/ +int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState) +{ + int32_t regv, tmp; +#ifdef MCB_LPC_1768 + regv = read_PHY (EMAC_PHY_REG_STS); + switch(ulPHYState){ + case EMAC_PHY_STAT_LINK: + tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0; + break; + case EMAC_PHY_STAT_SPEED: + tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1; + break; + case EMAC_PHY_STAT_DUP: + tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; + break; +#elif defined(IAR_LPC_1768) + /* Use IAR_LPC_1768 board: + * FSZ8721BL doesn't have Status Register + * so we read Basic Mode Status Register (0x01h) instead + */ + regv = read_PHY (EMAC_PHY_REG_BMSR); + switch(ulPHYState){ + case EMAC_PHY_STAT_LINK: + tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0; + break; + case EMAC_PHY_STAT_SPEED: + tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0; + break; + case EMAC_PHY_STAT_DUP: + tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; + break; +#endif + default: + tmp = -1; + break; + } + return (tmp); +} + + +/*********************************************************************//** + * @brief Set specified PHY mode in EMAC peripheral + * @param[in] ulPHYMode Specified PHY mode, should be: + * - EMAC_MODE_AUTO + * - EMAC_MODE_10M_FULL + * - EMAC_MODE_10M_HALF + * - EMAC_MODE_100M_FULL + * - EMAC_MODE_100M_HALF + * @return Return (0) if no error, otherwise return (-1) + **********************************************************************/ +int32_t EMAC_SetPHYMode(uint32_t ulPHYMode) +{ + int32_t id1, id2, tout, regv; + + /* Check if this is a DP83848C PHY. */ + id1 = read_PHY (EMAC_PHY_REG_IDR1); + id2 = read_PHY (EMAC_PHY_REG_IDR2); + +#ifdef MCB_LPC_1768 + if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) { + switch(ulPHYMode){ + case EMAC_MODE_AUTO: + write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); +#elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */ + if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) { + /* Configure the PHY device */ + switch(ulPHYMode){ + case EMAC_MODE_AUTO: + /* Use auto-negotiation about the link speed. */ + write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); +// write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN); +#endif + /* Wait to complete Auto_Negotiation */ + for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { + regv = read_PHY (EMAC_PHY_REG_BMSR); + if (regv & EMAC_PHY_BMSR_AUTO_DONE) { + /* Auto-negotiation Complete. */ + break; + } + if (tout == 0){ + // Time out, return error + return (-1); + } + } + break; + case EMAC_MODE_10M_FULL: + /* Connect at 10MBit full-duplex */ + write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M); + break; + case EMAC_MODE_10M_HALF: + /* Connect at 10MBit half-duplex */ + write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M); + break; + case EMAC_MODE_100M_FULL: + /* Connect at 100MBit full-duplex */ + write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M); + break; + case EMAC_MODE_100M_HALF: + /* Connect at 100MBit half-duplex */ + write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M); + break; + default: + // un-supported + return (-1); + } + } + // It's not correct module ID + else { + return (-1); + } + + // Update EMAC configuration with current PHY status + if (EMAC_UpdatePHYStatus() < 0){ + return (-1); + } + + // Complete + return (0); +} + + +/*********************************************************************//** + * @brief Auto-Configures value for the EMAC configuration register to + * match with current PHY mode + * @param[in] None + * @return Return (0) if no error, otherwise return (-1) + * + * Note: The EMAC configuration will be auto-configured: + * - Speed mode. + * - Half/Full duplex mode + **********************************************************************/ +int32_t EMAC_UpdatePHYStatus(void) +{ + int32_t regv, tout; + + /* Check the link status. */ +#ifdef MCB_LPC_1768 + for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { + regv = read_PHY (EMAC_PHY_REG_STS); + if (regv & EMAC_PHY_SR_LINK) { + /* Link is on. */ + break; + } + if (tout == 0){ + // time out + return (-1); + } + } + /* Configure Full/Half Duplex mode. */ + if (regv & EMAC_PHY_SR_DUP) { + /* Full duplex is enabled. */ + LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; + LPC_EMAC->Command |= EMAC_CR_FULL_DUP; + LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; + } else { + /* Half duplex mode. */ + LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; + } + if (regv & EMAC_PHY_SR_SPEED) { + /* 10MBit mode. */ + LPC_EMAC->SUPP = 0; + } else { + /* 100MBit mode. */ + LPC_EMAC->SUPP = EMAC_SUPP_SPEED; + } +#elif defined(IAR_LPC_1768) + for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { + regv = read_PHY (EMAC_PHY_REG_BMSR); + if (regv & EMAC_PHY_BMSR_LINK_STATUS) { + /* Link is on. */ + break; + } + if (tout == 0){ + // time out + return (-1); + } + } + + /* Configure Full/Half Duplex mode. */ + if (regv & EMAC_PHY_SR_FULL_DUP) { + /* Full duplex is enabled. */ + LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; + LPC_EMAC->Command |= EMAC_CR_FULL_DUP; + LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; + } else { + /* Half duplex mode. */ + LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; + } + + /* Configure 100MBit/10MBit mode. */ + if (!(regv & EMAC_PHY_SR_100_SPEED)) { + /* 10MBit mode. */ + LPC_EMAC->SUPP = 0; + } else { + /* 100MBit mode. */ + LPC_EMAC->SUPP = EMAC_SUPP_SPEED; + } +#endif + // Complete + return (0); +} + + +/*********************************************************************//** + * @brief Enable/Disable hash filter functionality for specified destination + * MAC address in EMAC module + * @param[in] dstMAC_addr Pointer to the first MAC destination address, should + * be 6-bytes length, in order LSB to the MSB + * @param[in] NewState New State of this command, should be: + * - ENABLE. + * - DISABLE. + * @return None + * + * Note: + * The standard Ethernet cyclic redundancy check (CRC) function is calculated from + * the 6 byte destination address in the Ethernet frame (this CRC is calculated + * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of + * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access + * the hash table: it is used as an index in the 64 bit HashFilter register that has been + * programmed with accept values. If the selected accept value is 1, the frame is + * accepted. + **********************************************************************/ +void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState) +{ + uint32_t *pReg; + uint32_t tmp; + int32_t crc; + + // Calculate the CRC from the destination MAC address + crc = emac_CRCCalc(dstMAC_addr, 6); + // Extract the value from CRC to get index value for hash filter table + crc = (crc >> 23) & 0x3F; + + pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \ + : ((uint32_t *)&LPC_EMAC->HashFilterL); + tmp = (crc > 31) ? (crc - 32) : crc; + if (NewState == ENABLE) { + (*pReg) |= (1UL << tmp); + } else { + (*pReg) &= ~(1UL << tmp); + } + // Enable Rx Filter + LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT; +} + +/*********************************************************************//** + * @brief Enable/Disable Filter mode for each specified type EMAC peripheral + * @param[in] ulFilterMode Filter mode, should be: + * - EMAC_RFC_UCAST_EN: all frames of unicast types + * will be accepted + * - EMAC_RFC_BCAST_EN: broadcast frame will be + * accepted + * - EMAC_RFC_MCAST_EN: all frames of multicast + * types will be accepted + * - EMAC_RFC_UCAST_HASH_EN: The imperfect hash + * filter will be applied to unicast addresses + * - EMAC_RFC_MCAST_HASH_EN: The imperfect hash + * filter will be applied to multicast addresses + * - EMAC_RFC_PERFECT_EN: the destination address + * will be compared with the 6 byte station address + * programmed in the station address by the filter + * - EMAC_RFC_MAGP_WOL_EN: the result of the magic + * packet filter will generate a WoL interrupt when + * there is a match + * - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address + * matching filter and the imperfect hash filter will + * generate a WoL interrupt when there is a match + * @param[in] NewState New State of this command, should be: + * - ENABLE + * - DISABLE + * @return None + **********************************************************************/ +void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState) +{ + if (NewState == ENABLE){ + LPC_EMAC->RxFilterCtrl |= ulFilterMode; + } else { + LPC_EMAC->RxFilterCtrl &= ~ulFilterMode; + } +} + +/*********************************************************************//** + * @brief Get status of Wake On LAN Filter for each specified + * type in EMAC peripheral, clear this status if it is set + * @param[in] ulWoLMode WoL Filter mode, should be: + * - EMAC_WOL_UCAST: unicast frames caused WoL + * - EMAC_WOL_UCAST: broadcast frame caused WoL + * - EMAC_WOL_MCAST: multicast frame caused WoL + * - EMAC_WOL_UCAST_HASH: unicast frame that passes the + * imperfect hash filter caused WoL + * - EMAC_WOL_MCAST_HASH: multicast frame that passes the + * imperfect hash filter caused WoL + * - EMAC_WOL_PERFECT:perfect address matching filter + * caused WoL + * - EMAC_WOL_RX_FILTER: the receive filter caused WoL + * - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL + * @return SET/RESET + **********************************************************************/ +FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode) +{ + if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) { + LPC_EMAC->RxFilterWoLClear = ulWoLMode; + return SET; + } else { + return RESET; + } +} + + +/*********************************************************************//** + * @brief Write data to Tx packet data buffer at current index due to + * TxProduceIndex + * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure + * data that contain specified information about + * Packet data buffer. + * @return None + **********************************************************************/ +void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) +{ + uint32_t idx,len; + uint32_t *sp,*dp; + + idx = LPC_EMAC->TxProduceIndex; + sp = (uint32_t *)pDataStruct->pbDataBuf; + dp = (uint32_t *)Tx_Desc[idx].Packet; + /* Copy frame data to EMAC packet buffers. */ + for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { + *dp++ = *sp++; + } + Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST); +} + +/*********************************************************************//** + * @brief Read data from Rx packet data buffer at current index due + * to RxConsumeIndex + * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure + * data that contain specified information about + * Packet data buffer. + * @return None + **********************************************************************/ +void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) +{ + uint32_t idx, len; + uint32_t *dp, *sp; + + idx = LPC_EMAC->RxConsumeIndex; + dp = (uint32_t *)pDataStruct->pbDataBuf; + sp = (uint32_t *)Rx_Desc[idx].Packet; + + if (pDataStruct->pbDataBuf != NULL) { + for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { + *dp++ = *sp++; + } + } +} + +/*********************************************************************//** + * @brief Enable/Disable interrupt for each type in EMAC + * @param[in] ulIntType Interrupt Type, should be: + * - EMAC_INT_RX_OVERRUN: Receive Overrun + * - EMAC_INT_RX_ERR: Receive Error + * - EMAC_INT_RX_FIN: Receive Descriptor Finish + * - EMAC_INT_RX_DONE: Receive Done + * - EMAC_INT_TX_UNDERRUN: Transmit Under-run + * - EMAC_INT_TX_ERR: Transmit Error + * - EMAC_INT_TX_FIN: Transmit descriptor finish + * - EMAC_INT_TX_DONE: Transmit Done + * - EMAC_INT_SOFT_INT: Software interrupt + * - EMAC_INT_WAKEUP: Wakeup interrupt + * @param[in] NewState New State of this function, should be: + * - ENABLE. + * - DISABLE. + * @return None + **********************************************************************/ +void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState) +{ + if (NewState == ENABLE) { + LPC_EMAC->IntEnable |= ulIntType; + } else { + LPC_EMAC->IntEnable &= ~(ulIntType); + } +} + +/*********************************************************************//** + * @brief Check whether if specified interrupt flag is set or not + * for each interrupt type in EMAC and clear interrupt pending + * if it is set. + * @param[in] ulIntType Interrupt Type, should be: + * - EMAC_INT_RX_OVERRUN: Receive Overrun + * - EMAC_INT_RX_ERR: Receive Error + * - EMAC_INT_RX_FIN: Receive Descriptor Finish + * - EMAC_INT_RX_DONE: Receive Done + * - EMAC_INT_TX_UNDERRUN: Transmit Under-run + * - EMAC_INT_TX_ERR: Transmit Error + * - EMAC_INT_TX_FIN: Transmit descriptor finish + * - EMAC_INT_TX_DONE: Transmit Done + * - EMAC_INT_SOFT_INT: Software interrupt + * - EMAC_INT_WAKEUP: Wakeup interrupt + * @return New state of specified interrupt (SET or RESET) + **********************************************************************/ +IntStatus EMAC_IntGetStatus(uint32_t ulIntType) +{ + if (LPC_EMAC->IntStatus & ulIntType) { + LPC_EMAC->IntClear = ulIntType; + return SET; + } else { + return RESET; + } +} + + +/*********************************************************************//** + * @brief Check whether if the current RxConsumeIndex is not equal to the + * current RxProduceIndex. + * @param[in] None + * @return TRUE if they're not equal, otherwise return FALSE + * + * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex, + * it means there're available data has been received. They should be read + * out and released the Receive Data Buffer by updating the RxConsumeIndex value. + **********************************************************************/ +Bool EMAC_CheckReceiveIndex(void) +{ + if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) { + return TRUE; + } else { + return FALSE; + } +} + + +/*********************************************************************//** + * @brief Check whether if the current TxProduceIndex is not equal to the + * current RxProduceIndex - 1. + * @param[in] None + * @return TRUE if they're not equal, otherwise return FALSE + * + * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1, + * it means the transmit buffer is available and data can be written to transmit + * buffer to be sent. + **********************************************************************/ +Bool EMAC_CheckTransmitIndex(void) +{ + uint32_t tmp = LPC_EMAC->TxConsumeIndex -1; + if (LPC_EMAC->TxProduceIndex == tmp) { + return FALSE; + } else { + return TRUE; + } +} + + +/*********************************************************************//** + * @brief Get current status value of receive data (due to RxConsumeIndex) + * @param[in] ulRxStatType Received Status type, should be one of following: + * - EMAC_RINFO_CTRL_FRAME: Control Frame + * - EMAC_RINFO_VLAN: VLAN Frame + * - EMAC_RINFO_FAIL_FILT: RX Filter Failed + * - EMAC_RINFO_MCAST: Multicast Frame + * - EMAC_RINFO_BCAST: Broadcast Frame + * - EMAC_RINFO_CRC_ERR: CRC Error in Frame + * - EMAC_RINFO_SYM_ERR: Symbol Error from PHY + * - EMAC_RINFO_LEN_ERR: Length Error + * - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size) + * - EMAC_RINFO_ALIGN_ERR: Alignment error + * - EMAC_RINFO_OVERRUN: Receive overrun + * - EMAC_RINFO_NO_DESCR: No new Descriptor available + * - EMAC_RINFO_LAST_FLAG: last Fragment in Frame + * - EMAC_RINFO_ERR: Error Occurred (OR of all error) + * @return Current value of receive data (due to RxConsumeIndex) + **********************************************************************/ +FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType) +{ + uint32_t idx; + idx = LPC_EMAC->RxConsumeIndex; + return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET); +} + + +/*********************************************************************//** + * @brief Get size of current Received data in received buffer (due to + * RxConsumeIndex) + * @param[in] None + * @return Size of received data + **********************************************************************/ +uint32_t EMAC_GetReceiveDataSize(void) +{ + uint32_t idx; + idx =LPC_EMAC->RxConsumeIndex; + return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE); +} + +/*********************************************************************//** + * @brief Increase the RxConsumeIndex (after reading the Receive buffer + * to release the Receive buffer) and wrap-around the index if + * it reaches the maximum Receive Number + * @param[in] None + * @return None + **********************************************************************/ +void EMAC_UpdateRxConsumeIndex(void) +{ + // Get current Rx consume index + uint32_t idx = LPC_EMAC->RxConsumeIndex; + + /* Release frame from EMAC buffer */ + if (++idx == EMAC_NUM_RX_FRAG) idx = 0; + LPC_EMAC->RxConsumeIndex = idx; +} + +/*********************************************************************//** + * @brief Increase the TxProduceIndex (after writting to the Transmit buffer + * to enable the Transmit buffer) and wrap-around the index if + * it reaches the maximum Transmit Number + * @param[in] None + * @return None + **********************************************************************/ +void EMAC_UpdateTxProduceIndex(void) +{ + // Get current Tx produce index + uint32_t idx = LPC_EMAC->TxProduceIndex; + + /* Start frame transmission */ + if (++idx == EMAC_NUM_TX_FRAG) idx = 0; + LPC_EMAC->TxProduceIndex = idx; +} + + +/** + * @} + */ + +#endif /* _EMAC */ + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */
--- a/lpc17xx_emac.h Sun Jun 12 11:23:03 2011 +0000 +++ b/lpc17xx_emac.h Sun Jun 12 19:17:11 2011 +0000 @@ -68,8 +68,8 @@ /* EMAC Memory Buffer configuration for 16K Ethernet RAM */ -#define EMAC_NUM_RX_FRAG 4 /**< Num.of RX Fragments 4*1536= 6.0kB */ -#define EMAC_NUM_TX_FRAG 3 /**< Num.of TX Fragments 3*1536= 4.6kB */ +#define EMAC_NUM_RX_FRAG 6 /**< Num.of RX Fragments 6*1536= 9kB */ +#define EMAC_NUM_TX_FRAG 4 /**< Num.of TX Fragments 4*1536= 6kB */ #define EMAC_ETH_MAX_FLEN 1536 /**< Max. Ethernet Frame Size */ #define EMAC_TX_FRAME_TOUT 0x00100000 /**< Frame Transmit timeout count */ @@ -673,8 +673,8 @@ IntStatus EMAC_IntGetStatus(uint32_t ulIntType); /* EMAC Index functions -----------*/ -bool EMAC_CheckReceiveIndex(void); -bool EMAC_CheckTransmitIndex(void); +Bool EMAC_CheckReceiveIndex(void); +Bool EMAC_CheckTransmitIndex(void); void EMAC_UpdateRxConsumeIndex(void); void EMAC_UpdateTxProduceIndex(void);
--- a/lpc17xx_pinsel.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,306 +0,0 @@ -/***********************************************************************//** - * @file lpc17xx_pinsel.c - * @brief Contains all functions support for Pin connect block firmware - * library on LPC17xx - * @version 2.0 - * @date 21. May. 2010 - * @author NXP MCU SW Application Team - ************************************************************************** - * Software that is described herein is for illustrative purposes only - * which provides customers with programming information regarding the - * products. This software is supplied "AS IS" without any warranties. - * NXP Semiconductors assumes no responsibility or liability for the - * use of the software, conveys no license or title under any patent, - * copyright, or mask work right to the product. NXP Semiconductors - * reserves the right to make changes in the software without - * notification. NXP Semiconductors also make no representation or - * warranty that such application will be suitable for the specified - * use without further testing or modification. - **********************************************************************/ - -/* Peripheral group ----------------------------------------------------------- */ -/** @addtogroup PINSEL - * @{ - */ - -/* Includes ------------------------------------------------------------------- */ -#include "lpc17xx_pinsel.h" - -/* Public Functions ----------------------------------------------------------- */ - -static void set_PinFunc ( uint8_t portnum, uint8_t pinnum, uint8_t funcnum); -static void set_ResistorMode ( uint8_t portnum, uint8_t pinnum, uint8_t modenum); -static void set_OpenDrainMode( uint8_t portnum, uint8_t pinnum, uint8_t modenum); - -/*********************************************************************//** - * @brief Setup the pin selection function - * @param[in] portnum PORT number, - * should be one of the following: - * - PINSEL_PORT_0 : Port 0 - * - PINSEL_PORT_1 : Port 1 - * - PINSEL_PORT_2 : Port 2 - * - PINSEL_PORT_3 : Port 3 - * - * @param[in] pinnum Pin number, - * should be one of the following: - - PINSEL_PIN_0 : Pin 0 - - PINSEL_PIN_1 : Pin 1 - - PINSEL_PIN_2 : Pin 2 - - PINSEL_PIN_3 : Pin 3 - - PINSEL_PIN_4 : Pin 4 - - PINSEL_PIN_5 : Pin 5 - - PINSEL_PIN_6 : Pin 6 - - PINSEL_PIN_7 : Pin 7 - - PINSEL_PIN_8 : Pin 8 - - PINSEL_PIN_9 : Pin 9 - - PINSEL_PIN_10 : Pin 10 - - PINSEL_PIN_11 : Pin 11 - - PINSEL_PIN_12 : Pin 12 - - PINSEL_PIN_13 : Pin 13 - - PINSEL_PIN_14 : Pin 14 - - PINSEL_PIN_15 : Pin 15 - - PINSEL_PIN_16 : Pin 16 - - PINSEL_PIN_17 : Pin 17 - - PINSEL_PIN_18 : Pin 18 - - PINSEL_PIN_19 : Pin 19 - - PINSEL_PIN_20 : Pin 20 - - PINSEL_PIN_21 : Pin 21 - - PINSEL_PIN_22 : Pin 22 - - PINSEL_PIN_23 : Pin 23 - - PINSEL_PIN_24 : Pin 24 - - PINSEL_PIN_25 : Pin 25 - - PINSEL_PIN_26 : Pin 26 - - PINSEL_PIN_27 : Pin 27 - - PINSEL_PIN_28 : Pin 28 - - PINSEL_PIN_29 : Pin 29 - - PINSEL_PIN_30 : Pin 30 - - PINSEL_PIN_31 : Pin 31 - - * @param[in] funcnum Function number, - * should be one of the following: - * - PINSEL_FUNC_0 : default function - * - PINSEL_FUNC_1 : first alternate function - * - PINSEL_FUNC_2 : second alternate function - * - PINSEL_FUNC_3 : third alternate function - * - * @return None - **********************************************************************/ -static void set_PinFunc ( uint8_t portnum, uint8_t pinnum, uint8_t funcnum) -{ - uint32_t pinnum_t = pinnum; - uint32_t pinselreg_idx = 2 * portnum; - uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINSEL0; - - if (pinnum_t >= 16) { - pinnum_t -= 16; - pinselreg_idx++; - } - *(uint32_t *)(pPinCon + pinselreg_idx) &= ~(0x03UL << (pinnum_t * 2)); - *(uint32_t *)(pPinCon + pinselreg_idx) |= ((uint32_t)funcnum) << (pinnum_t * 2); -} - -/*********************************************************************//** - * @brief Setup resistor mode for each pin - * @param[in] portnum PORT number, - * should be one of the following: - * - PINSEL_PORT_0 : Port 0 - * - PINSEL_PORT_1 : Port 1 - * - PINSEL_PORT_2 : Port 2 - * - PINSEL_PORT_3 : Port 3 - * @param[in] pinnum Pin number, - * should be one of the following: - - PINSEL_PIN_0 : Pin 0 - - PINSEL_PIN_1 : Pin 1 - - PINSEL_PIN_2 : Pin 2 - - PINSEL_PIN_3 : Pin 3 - - PINSEL_PIN_4 : Pin 4 - - PINSEL_PIN_5 : Pin 5 - - PINSEL_PIN_6 : Pin 6 - - PINSEL_PIN_7 : Pin 7 - - PINSEL_PIN_8 : Pin 8 - - PINSEL_PIN_9 : Pin 9 - - PINSEL_PIN_10 : Pin 10 - - PINSEL_PIN_11 : Pin 11 - - PINSEL_PIN_12 : Pin 12 - - PINSEL_PIN_13 : Pin 13 - - PINSEL_PIN_14 : Pin 14 - - PINSEL_PIN_15 : Pin 15 - - PINSEL_PIN_16 : Pin 16 - - PINSEL_PIN_17 : Pin 17 - - PINSEL_PIN_18 : Pin 18 - - PINSEL_PIN_19 : Pin 19 - - PINSEL_PIN_20 : Pin 20 - - PINSEL_PIN_21 : Pin 21 - - PINSEL_PIN_22 : Pin 22 - - PINSEL_PIN_23 : Pin 23 - - PINSEL_PIN_24 : Pin 24 - - PINSEL_PIN_25 : Pin 25 - - PINSEL_PIN_26 : Pin 26 - - PINSEL_PIN_27 : Pin 27 - - PINSEL_PIN_28 : Pin 28 - - PINSEL_PIN_29 : Pin 29 - - PINSEL_PIN_30 : Pin 30 - - PINSEL_PIN_31 : Pin 31 - - * @param[in] modenum: Mode number, - * should be one of the following: - - PINSEL_PINMODE_PULLUP : Internal pull-up resistor - - PINSEL_PINMODE_TRISTATE : Tri-state - - PINSEL_PINMODE_PULLDOWN : Internal pull-down resistor - - * @return None - **********************************************************************/ -void set_ResistorMode ( uint8_t portnum, uint8_t pinnum, uint8_t modenum) -{ - uint32_t pinnum_t = pinnum; - uint32_t pinmodereg_idx = 2 * portnum; - uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINMODE0; - - if (pinnum_t >= 16) { - pinnum_t -= 16; - pinmodereg_idx++ ; - } - - *(uint32_t *)(pPinCon + pinmodereg_idx) &= ~(0x03UL << (pinnum_t * 2)); - *(uint32_t *)(pPinCon + pinmodereg_idx) |= ((uint32_t)modenum) << (pinnum_t * 2); -} - -/*********************************************************************//** - * @brief Setup Open drain mode for each pin - * @param[in] portnum PORT number, - * should be one of the following: - * - PINSEL_PORT_0 : Port 0 - * - PINSEL_PORT_1 : Port 1 - * - PINSEL_PORT_2 : Port 2 - * - PINSEL_PORT_3 : Port 3 - * - * @param[in] pinnum Pin number, - * should be one of the following: - - PINSEL_PIN_0 : Pin 0 - - PINSEL_PIN_1 : Pin 1 - - PINSEL_PIN_2 : Pin 2 - - PINSEL_PIN_3 : Pin 3 - - PINSEL_PIN_4 : Pin 4 - - PINSEL_PIN_5 : Pin 5 - - PINSEL_PIN_6 : Pin 6 - - PINSEL_PIN_7 : Pin 7 - - PINSEL_PIN_8 : Pin 8 - - PINSEL_PIN_9 : Pin 9 - - PINSEL_PIN_10 : Pin 10 - - PINSEL_PIN_11 : Pin 11 - - PINSEL_PIN_12 : Pin 12 - - PINSEL_PIN_13 : Pin 13 - - PINSEL_PIN_14 : Pin 14 - - PINSEL_PIN_15 : Pin 15 - - PINSEL_PIN_16 : Pin 16 - - PINSEL_PIN_17 : Pin 17 - - PINSEL_PIN_18 : Pin 18 - - PINSEL_PIN_19 : Pin 19 - - PINSEL_PIN_20 : Pin 20 - - PINSEL_PIN_21 : Pin 21 - - PINSEL_PIN_22 : Pin 22 - - PINSEL_PIN_23 : Pin 23 - - PINSEL_PIN_24 : Pin 24 - - PINSEL_PIN_25 : Pin 25 - - PINSEL_PIN_26 : Pin 26 - - PINSEL_PIN_27 : Pin 27 - - PINSEL_PIN_28 : Pin 28 - - PINSEL_PIN_29 : Pin 29 - - PINSEL_PIN_30 : Pin 30 - - PINSEL_PIN_31 : Pin 31 - - * @param[in] modenum Open drain mode number, - * should be one of the following: - * - PINSEL_PINMODE_NORMAL : Pin is in the normal (not open drain) mode - * - PINSEL_PINMODE_OPENDRAIN : Pin is in the open drain mode - * - * @return None - **********************************************************************/ -void set_OpenDrainMode( uint8_t portnum, uint8_t pinnum, uint8_t modenum) -{ - uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINMODE_OD0; - - if (modenum == PINSEL_PINMODE_OPENDRAIN){ - *(uint32_t *)(pPinCon + portnum) |= (0x01UL << pinnum); - } else { - *(uint32_t *)(pPinCon + portnum) &= ~(0x01UL << pinnum); - } -} - -/* End of Public Functions ---------------------------------------------------- */ - -/* Public Functions ----------------------------------------------------------- */ -/** @addtogroup PINSEL_Public_Functions - * @{ - */ -/*********************************************************************//** - * @brief Configure trace function - * @param[in] NewState State of the Trace function configuration, - * should be one of the following: - * - ENABLE : Enable Trace Function - * - DISABLE : Disable Trace Function - * - * @return None - **********************************************************************/ -void PINSEL_ConfigTraceFunc(FunctionalState NewState) -{ - if (NewState == ENABLE) { - LPC_PINCON->PINSEL10 |= (0x01UL << 3); - } else if (NewState == DISABLE) { - LPC_PINCON->PINSEL10 &= ~(0x01UL << 3); - } -} - -/*********************************************************************//** - * @brief Setup I2C0 pins - * @param[in] i2cPinMode I2C pin mode, - * should be one of the following: - * - PINSEL_I2C_Normal_Mode : The standard drive mode - * - PINSEL_I2C_Fast_Mode : Fast Mode Plus drive mode - * - * @param[in] filterSlewRateEnable should be: - * - ENABLE: Enable filter and slew rate. - * - DISABLE: Disable filter and slew rate. - * - * @return None - **********************************************************************/ -void PINSEL_SetI2C0Pins(uint8_t i2cPinMode, FunctionalState filterSlewRateEnable) -{ - uint32_t regVal = 0; - - if (i2cPinMode == PINSEL_I2C_Fast_Mode){ - regVal = PINSEL_I2CPADCFG_SCLDRV0 | PINSEL_I2CPADCFG_SDADRV0; - } - - if (filterSlewRateEnable == DISABLE){ - regVal = PINSEL_I2CPADCFG_SCLI2C0 | PINSEL_I2CPADCFG_SDAI2C0; - } - LPC_PINCON->I2CPADCFG = regVal; -} - - -/*********************************************************************//** - * @brief Configure Pin corresponding to specified parameters passed - * in the PinCfg - * @param[in] PinCfg Pointer to a PINSEL_CFG_Type structure - * that contains the configuration information for the - * specified pin. - * @return None - **********************************************************************/ -void PINSEL_ConfigPin(PINSEL_CFG_Type *PinCfg) -{ - set_PinFunc(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->Funcnum); - set_ResistorMode(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->Pinmode); - set_OpenDrainMode(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->OpenDrain); -} - - -/** - * @} - */ - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lpc17xx_pinsel.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,306 @@ +/***********************************************************************//** + * @file lpc17xx_pinsel.c + * @brief Contains all functions support for Pin connect block firmware + * library on LPC17xx + * @version 2.0 + * @date 21. May. 2010 + * @author NXP MCU SW Application Team + ************************************************************************** + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * products. This software is supplied "AS IS" without any warranties. + * NXP Semiconductors assumes no responsibility or liability for the + * use of the software, conveys no license or title under any patent, + * copyright, or mask work right to the product. NXP Semiconductors + * reserves the right to make changes in the software without + * notification. NXP Semiconductors also make no representation or + * warranty that such application will be suitable for the specified + * use without further testing or modification. + **********************************************************************/ + +/* Peripheral group ----------------------------------------------------------- */ +/** @addtogroup PINSEL + * @{ + */ + +/* Includes ------------------------------------------------------------------- */ +#include "lpc17xx_pinsel.h" + +/* Public Functions ----------------------------------------------------------- */ + +static void set_PinFunc ( uint8_t portnum, uint8_t pinnum, uint8_t funcnum); +static void set_ResistorMode ( uint8_t portnum, uint8_t pinnum, uint8_t modenum); +static void set_OpenDrainMode( uint8_t portnum, uint8_t pinnum, uint8_t modenum); + +/*********************************************************************//** + * @brief Setup the pin selection function + * @param[in] portnum PORT number, + * should be one of the following: + * - PINSEL_PORT_0 : Port 0 + * - PINSEL_PORT_1 : Port 1 + * - PINSEL_PORT_2 : Port 2 + * - PINSEL_PORT_3 : Port 3 + * + * @param[in] pinnum Pin number, + * should be one of the following: + - PINSEL_PIN_0 : Pin 0 + - PINSEL_PIN_1 : Pin 1 + - PINSEL_PIN_2 : Pin 2 + - PINSEL_PIN_3 : Pin 3 + - PINSEL_PIN_4 : Pin 4 + - PINSEL_PIN_5 : Pin 5 + - PINSEL_PIN_6 : Pin 6 + - PINSEL_PIN_7 : Pin 7 + - PINSEL_PIN_8 : Pin 8 + - PINSEL_PIN_9 : Pin 9 + - PINSEL_PIN_10 : Pin 10 + - PINSEL_PIN_11 : Pin 11 + - PINSEL_PIN_12 : Pin 12 + - PINSEL_PIN_13 : Pin 13 + - PINSEL_PIN_14 : Pin 14 + - PINSEL_PIN_15 : Pin 15 + - PINSEL_PIN_16 : Pin 16 + - PINSEL_PIN_17 : Pin 17 + - PINSEL_PIN_18 : Pin 18 + - PINSEL_PIN_19 : Pin 19 + - PINSEL_PIN_20 : Pin 20 + - PINSEL_PIN_21 : Pin 21 + - PINSEL_PIN_22 : Pin 22 + - PINSEL_PIN_23 : Pin 23 + - PINSEL_PIN_24 : Pin 24 + - PINSEL_PIN_25 : Pin 25 + - PINSEL_PIN_26 : Pin 26 + - PINSEL_PIN_27 : Pin 27 + - PINSEL_PIN_28 : Pin 28 + - PINSEL_PIN_29 : Pin 29 + - PINSEL_PIN_30 : Pin 30 + - PINSEL_PIN_31 : Pin 31 + + * @param[in] funcnum Function number, + * should be one of the following: + * - PINSEL_FUNC_0 : default function + * - PINSEL_FUNC_1 : first alternate function + * - PINSEL_FUNC_2 : second alternate function + * - PINSEL_FUNC_3 : third alternate function + * + * @return None + **********************************************************************/ +static void set_PinFunc ( uint8_t portnum, uint8_t pinnum, uint8_t funcnum) +{ + uint32_t pinnum_t = pinnum; + uint32_t pinselreg_idx = 2 * portnum; + uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINSEL0; + + if (pinnum_t >= 16) { + pinnum_t -= 16; + pinselreg_idx++; + } + *(uint32_t *)(pPinCon + pinselreg_idx) &= ~(0x03UL << (pinnum_t * 2)); + *(uint32_t *)(pPinCon + pinselreg_idx) |= ((uint32_t)funcnum) << (pinnum_t * 2); +} + +/*********************************************************************//** + * @brief Setup resistor mode for each pin + * @param[in] portnum PORT number, + * should be one of the following: + * - PINSEL_PORT_0 : Port 0 + * - PINSEL_PORT_1 : Port 1 + * - PINSEL_PORT_2 : Port 2 + * - PINSEL_PORT_3 : Port 3 + * @param[in] pinnum Pin number, + * should be one of the following: + - PINSEL_PIN_0 : Pin 0 + - PINSEL_PIN_1 : Pin 1 + - PINSEL_PIN_2 : Pin 2 + - PINSEL_PIN_3 : Pin 3 + - PINSEL_PIN_4 : Pin 4 + - PINSEL_PIN_5 : Pin 5 + - PINSEL_PIN_6 : Pin 6 + - PINSEL_PIN_7 : Pin 7 + - PINSEL_PIN_8 : Pin 8 + - PINSEL_PIN_9 : Pin 9 + - PINSEL_PIN_10 : Pin 10 + - PINSEL_PIN_11 : Pin 11 + - PINSEL_PIN_12 : Pin 12 + - PINSEL_PIN_13 : Pin 13 + - PINSEL_PIN_14 : Pin 14 + - PINSEL_PIN_15 : Pin 15 + - PINSEL_PIN_16 : Pin 16 + - PINSEL_PIN_17 : Pin 17 + - PINSEL_PIN_18 : Pin 18 + - PINSEL_PIN_19 : Pin 19 + - PINSEL_PIN_20 : Pin 20 + - PINSEL_PIN_21 : Pin 21 + - PINSEL_PIN_22 : Pin 22 + - PINSEL_PIN_23 : Pin 23 + - PINSEL_PIN_24 : Pin 24 + - PINSEL_PIN_25 : Pin 25 + - PINSEL_PIN_26 : Pin 26 + - PINSEL_PIN_27 : Pin 27 + - PINSEL_PIN_28 : Pin 28 + - PINSEL_PIN_29 : Pin 29 + - PINSEL_PIN_30 : Pin 30 + - PINSEL_PIN_31 : Pin 31 + + * @param[in] modenum: Mode number, + * should be one of the following: + - PINSEL_PINMODE_PULLUP : Internal pull-up resistor + - PINSEL_PINMODE_TRISTATE : Tri-state + - PINSEL_PINMODE_PULLDOWN : Internal pull-down resistor + + * @return None + **********************************************************************/ +void set_ResistorMode ( uint8_t portnum, uint8_t pinnum, uint8_t modenum) +{ + uint32_t pinnum_t = pinnum; + uint32_t pinmodereg_idx = 2 * portnum; + uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINMODE0; + + if (pinnum_t >= 16) { + pinnum_t -= 16; + pinmodereg_idx++ ; + } + + *(uint32_t *)(pPinCon + pinmodereg_idx) &= ~(0x03UL << (pinnum_t * 2)); + *(uint32_t *)(pPinCon + pinmodereg_idx) |= ((uint32_t)modenum) << (pinnum_t * 2); +} + +/*********************************************************************//** + * @brief Setup Open drain mode for each pin + * @param[in] portnum PORT number, + * should be one of the following: + * - PINSEL_PORT_0 : Port 0 + * - PINSEL_PORT_1 : Port 1 + * - PINSEL_PORT_2 : Port 2 + * - PINSEL_PORT_3 : Port 3 + * + * @param[in] pinnum Pin number, + * should be one of the following: + - PINSEL_PIN_0 : Pin 0 + - PINSEL_PIN_1 : Pin 1 + - PINSEL_PIN_2 : Pin 2 + - PINSEL_PIN_3 : Pin 3 + - PINSEL_PIN_4 : Pin 4 + - PINSEL_PIN_5 : Pin 5 + - PINSEL_PIN_6 : Pin 6 + - PINSEL_PIN_7 : Pin 7 + - PINSEL_PIN_8 : Pin 8 + - PINSEL_PIN_9 : Pin 9 + - PINSEL_PIN_10 : Pin 10 + - PINSEL_PIN_11 : Pin 11 + - PINSEL_PIN_12 : Pin 12 + - PINSEL_PIN_13 : Pin 13 + - PINSEL_PIN_14 : Pin 14 + - PINSEL_PIN_15 : Pin 15 + - PINSEL_PIN_16 : Pin 16 + - PINSEL_PIN_17 : Pin 17 + - PINSEL_PIN_18 : Pin 18 + - PINSEL_PIN_19 : Pin 19 + - PINSEL_PIN_20 : Pin 20 + - PINSEL_PIN_21 : Pin 21 + - PINSEL_PIN_22 : Pin 22 + - PINSEL_PIN_23 : Pin 23 + - PINSEL_PIN_24 : Pin 24 + - PINSEL_PIN_25 : Pin 25 + - PINSEL_PIN_26 : Pin 26 + - PINSEL_PIN_27 : Pin 27 + - PINSEL_PIN_28 : Pin 28 + - PINSEL_PIN_29 : Pin 29 + - PINSEL_PIN_30 : Pin 30 + - PINSEL_PIN_31 : Pin 31 + + * @param[in] modenum Open drain mode number, + * should be one of the following: + * - PINSEL_PINMODE_NORMAL : Pin is in the normal (not open drain) mode + * - PINSEL_PINMODE_OPENDRAIN : Pin is in the open drain mode + * + * @return None + **********************************************************************/ +void set_OpenDrainMode( uint8_t portnum, uint8_t pinnum, uint8_t modenum) +{ + uint32_t *pPinCon = (uint32_t *)&LPC_PINCON->PINMODE_OD0; + + if (modenum == PINSEL_PINMODE_OPENDRAIN){ + *(uint32_t *)(pPinCon + portnum) |= (0x01UL << pinnum); + } else { + *(uint32_t *)(pPinCon + portnum) &= ~(0x01UL << pinnum); + } +} + +/* End of Public Functions ---------------------------------------------------- */ + +/* Public Functions ----------------------------------------------------------- */ +/** @addtogroup PINSEL_Public_Functions + * @{ + */ +/*********************************************************************//** + * @brief Configure trace function + * @param[in] NewState State of the Trace function configuration, + * should be one of the following: + * - ENABLE : Enable Trace Function + * - DISABLE : Disable Trace Function + * + * @return None + **********************************************************************/ +void PINSEL_ConfigTraceFunc(FunctionalState NewState) +{ + if (NewState == ENABLE) { + LPC_PINCON->PINSEL10 |= (0x01UL << 3); + } else if (NewState == DISABLE) { + LPC_PINCON->PINSEL10 &= ~(0x01UL << 3); + } +} + +/*********************************************************************//** + * @brief Setup I2C0 pins + * @param[in] i2cPinMode I2C pin mode, + * should be one of the following: + * - PINSEL_I2C_Normal_Mode : The standard drive mode + * - PINSEL_I2C_Fast_Mode : Fast Mode Plus drive mode + * + * @param[in] filterSlewRateEnable should be: + * - ENABLE: Enable filter and slew rate. + * - DISABLE: Disable filter and slew rate. + * + * @return None + **********************************************************************/ +void PINSEL_SetI2C0Pins(uint8_t i2cPinMode, FunctionalState filterSlewRateEnable) +{ + uint32_t regVal = 0; + + if (i2cPinMode == PINSEL_I2C_Fast_Mode){ + regVal = PINSEL_I2CPADCFG_SCLDRV0 | PINSEL_I2CPADCFG_SDADRV0; + } + + if (filterSlewRateEnable == DISABLE){ + regVal = PINSEL_I2CPADCFG_SCLI2C0 | PINSEL_I2CPADCFG_SDAI2C0; + } + LPC_PINCON->I2CPADCFG = regVal; +} + + +/*********************************************************************//** + * @brief Configure Pin corresponding to specified parameters passed + * in the PinCfg + * @param[in] PinCfg Pointer to a PINSEL_CFG_Type structure + * that contains the configuration information for the + * specified pin. + * @return None + **********************************************************************/ +void PINSEL_ConfigPin(PINSEL_CFG_Type *PinCfg) +{ + set_PinFunc(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->Funcnum); + set_ResistorMode(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->Pinmode); + set_OpenDrainMode(PinCfg->Portnum, PinCfg->Pinnum, PinCfg->OpenDrain); +} + + +/** + * @} + */ + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */
--- a/mbedNet.h Sun Jun 12 11:23:03 2011 +0000 +++ b/mbedNet.h Sun Jun 12 19:17:11 2011 +0000 @@ -17,12 +17,6 @@ #include <stdint.h> -#ifdef __cplusplus -#define CAPI -#else -#define CAPI -#endif /* __cplusplus */ - enum Bool { False = 0, @@ -31,7 +25,7 @@ typedef enum Bool Bool_t; -#define DEBUG_ON 1 +#define DEBUG_ON 1 #define NET_DEFAULT_TTL 128 /* Default TTL */ #define NET_ENCAPSULATION_MAX_DEPTH 5 /* Maximum protocol encapsulation depth */ @@ -59,6 +53,8 @@ mbedNetResult_NotEnoughMemory, mbedNetResult_TooManyInterfaces, mbedNetResult_InvalidInterface, + mbedNetResult_InterfaceAlreadyUp, + mbedNetResult_InterfaceAlreadyDown, mbedNetResult_TooManyPeriodicFunctions, mbedNetResult_TooManyDrivers, mbedNetResult_InvalidDriver,
--- a/mbedNetIF.c Sun Jun 12 11:23:03 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -/* - * $Id: mbedNetIF.c 28 2011-06-10 10:16:30Z benoit $ - * $Author: benoit $ - * $Date: 2011-06-10 12:16:30 +0200 (ven., 10 juin 2011) $ - * $Rev: 28 $ - * - * - * - * - * - */ - -#include "mbedNetIF.h" -#include "Ethernet.h" -#include "mbedNet.h" -#include "NetIF.h" -#include "Debug.h" -#include "lpc17xx_pinsel.h" -#include "lpc17xx_emac.h" -#include <string.h> - - -#define DEBUG_CURRENT_MODULE_NAME "mbedNetIF" -#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_MBEDNETIF - - -static int32_t Init(NetIF_t *netif); -static int32_t Read(uint8_t **packet, int32_t *length); -static int32_t Write(uint8_t *packet, int32_t length); -static uint8_t *GetTxBuffer(void); - - -#define MBEDNETIF_DRIVER_NAME "mbedEMAC" - - -static EMAC_CFG_Type Emac_Config; -static PINSEL_CFG_Type PinCfg; -static uint8_t rxPacket[EMAC_ETH_MAX_FLEN], - txPacket[EMAC_ETH_MAX_FLEN]; -static EMAC_PACKETBUF_Type rxBuffer, - txBuffer; - - -static Bool_t EMAC_TxBufferNotFull(void); - - -NetIF_Driver_t mbedNetIF_Driver = -{ - MBEDNETIF_DRIVER_NAME, - Init, - Read, - Write, - GetTxBuffer, - ðernet, - EMAC_ETH_MAX_FLEN -}; - - -static int32_t Init(NetIF_t *netIF) -{ - int32_t result = 0; - uint8_t initMac[6]; - Ethernet_Addr_t *hwAddress = (Ethernet_Addr_t *)netIF->driverParameter; - - initMac[0] = hwAddress->MA0; - initMac[1] = hwAddress->MA1; - initMac[2] = hwAddress->MA2; - initMac[3] = hwAddress->MA3; - initMac[4] = hwAddress->MA4; - initMac[5] = hwAddress->MA5; - - DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing device driver '%s' with hardware address %02x:%02x:%02x:%02x:%02x:%02x", - netIF->driver->name, - initMac[0], - initMac[1], - initMac[2], - initMac[3], - initMac[4], - initMac[5] - )); - - rxBuffer.pbDataBuf = (uint32_t *)&rxPacket; - - PinCfg.Funcnum = 1; - PinCfg.OpenDrain = 0; - PinCfg.Pinmode = 0; - PinCfg.Portnum = 1; - - PinCfg.Pinnum = 0; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 1; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 4; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 8; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 9; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 10; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 14; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 15; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 16; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 17; - PINSEL_ConfigPin(&PinCfg); - - Emac_Config.Mode = EMAC_MODE_AUTO; - Emac_Config.pbEMAC_Addr = initMac; - - memset(txPacket, 0, sizeof(txPacket)); - - if (EMAC_Init(&Emac_Config) == ERROR) - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Error during initializing EMAC, restart after a while")); - } - - Write(txPacket, 14); /* Send dummy frame at init as workaround described in chapter 3.3 of errata sheet document 'ES_LPC176x' rev 9 from June 2011 page 6 */ - - goto Exit; - -Exit: - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result)); - return result; -} - - -static int32_t Read(uint8_t **packet, int32_t *length) -{ - int32_t result = 0; - - - if (EMAC_CheckReceiveIndex() == FALSE) - { - mbedNet_LastError = mbedNetResult_QueueEmpty; - result = -1; - goto Exit; - } - rxBuffer.ulDataLen = EMAC_GetReceiveDataSize(); - *length = rxBuffer.ulDataLen; - EMAC_ReadPacketBuffer(&rxBuffer); - EMAC_UpdateRxConsumeIndex(); - - *packet = (uint8_t *)rxBuffer.pbDataBuf; - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("received %d byte frame", *length)); - -Exit: - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result)); - return result; -} - - -static int32_t Write(uint8_t *packet, int32_t length) -{ - int32_t result = 0; - - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("request to send %d bytes", length)); - - if (EMAC_TxBufferNotFull()) - { - DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) - { - Debug_DumpBufferHex(packet, length); - } - txBuffer.ulDataLen = length; - txBuffer.pbDataBuf = (uint32_t *)packet; - EMAC_WritePacketBuffer(&txBuffer); - EMAC_UpdateTxProduceIndex(); - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("transmitted %d byte frame", length)); - } - else - { - DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("transmission queue is full")); - mbedNet_LastError = mbedNetResult_QueueEmpty; - result = -1; - } - DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result)); - return result; -} - - -static uint8_t *GetTxBuffer(void) -{ - return txPacket; -} - - -static Bool_t EMAC_TxBufferNotFull(void) -{ - uint32_t tmp = LPC_EMAC->TxProduceIndex + 1; - - if (tmp == EMAC_NUM_TX_FRAG) tmp = 0; - return (LPC_EMAC->TxConsumeIndex != tmp) ? True : False; -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedNetIF.cpp Sun Jun 12 19:17:11 2011 +0000 @@ -0,0 +1,244 @@ +/* + * $Id: mbedNetIF.c 28 2011-06-10 10:16:30Z benoit $ + * $Author: benoit $ + * $Date: 2011-06-10 12:16:30 +0200 (ven., 10 juin 2011) $ + * $Rev: 28 $ + * + * + * + * + * + */ + +#include "mbedNetIF.h" +#include "Ethernet.h" +#include "mbedNet.h" +#include "NetIF.h" +#include "Debug.h" +#include "lpc17xx_pinsel.h" +#include "lpc17xx_emac.h" +#include <string.h> + + +#define DEBUG_CURRENT_MODULE_NAME "mbedNetIF" +#define DEBUG_CURRENT_MODULE_ID DEBUG_MODULE_MBEDNETIF + + +static int32_t Init(NetIF_t *netif); +static int32_t Read(uint8_t **packet, int32_t *length); +static int32_t Write(uint8_t *packet, int32_t length); +static void Enable(void); +static void Disable(void); +static uint8_t *GetTxBuffer(void); + + +#define MBEDNETIF_DRIVER_NAME "mbedEMAC" + + +static EMAC_CFG_Type Emac_Config; +static PINSEL_CFG_Type PinCfg; +static uint8_t rxPacket[EMAC_ETH_MAX_FLEN], + txPacket[EMAC_ETH_MAX_FLEN]; +static EMAC_PACKETBUF_Type rxBuffer, + txBuffer; +static NetIF_t *mbedNetIF = NULL; + +static Bool_t EMAC_TxBufferNotFull(void); + + +NetIF_Driver_t mbedNetIF_Driver = +{ + MBEDNETIF_DRIVER_NAME, + Init, + Read, + Write, + Enable, + Disable, + GetTxBuffer, + ðernet, + EMAC_ETH_MAX_FLEN +}; + + +static int32_t Init(NetIF_t *netIF) +{ + int32_t result = 0; + uint8_t initMac[6]; + Ethernet_Addr_t *hwAddress = (Ethernet_Addr_t *)netIF->driverParameter; + + initMac[0] = hwAddress->MA0; + initMac[1] = hwAddress->MA1; + initMac[2] = hwAddress->MA2; + initMac[3] = hwAddress->MA3; + initMac[4] = hwAddress->MA4; + initMac[5] = hwAddress->MA5; + + DEBUG_MODULE(DEBUG_LEVEL_INFO, ("Initializing device driver '%s' with hardware address %02x:%02x:%02x:%02x:%02x:%02x", + netIF->driver->name, + initMac[0], + initMac[1], + initMac[2], + initMac[3], + initMac[4], + initMac[5] + )); + + rxBuffer.pbDataBuf = (uint32_t *)&rxPacket; + + mbedNetIF = netIF; + + PinCfg.Funcnum = 1; + PinCfg.OpenDrain = 0; + PinCfg.Pinmode = 0; + PinCfg.Portnum = 1; + + PinCfg.Pinnum = 0; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 1; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 4; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 8; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 9; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 10; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 14; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 15; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 16; + PINSEL_ConfigPin(&PinCfg); + PinCfg.Pinnum = 17; + PINSEL_ConfigPin(&PinCfg); + + Emac_Config.Mode = EMAC_MODE_AUTO; + Emac_Config.pbEMAC_Addr = initMac; + + memset(txPacket, 0, sizeof(txPacket)); + + if (EMAC_Init(&Emac_Config) == ERROR) + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("Error during initializing EMAC, restart after a while")); + } + + Write(txPacket, 14); /* Send dummy frame at init as workaround described in chapter 3.3 of errata sheet document 'ES_LPC176x' rev 9 from June 2011 page 6 */ + + //NVIC_SetPriority(ENET_IRQn, 10); + + Disable(); + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result)); + return result; +} + + +static int32_t Read(uint8_t **packet, int32_t *length) +{ + int32_t result = 0; + + if (EMAC_CheckReceiveIndex() == FALSE) + { + mbedNet_LastError = mbedNetResult_QueueEmpty; + result = -1; + } + else + { + rxBuffer.ulDataLen = EMAC_GetReceiveDataSize(); + *length = rxBuffer.ulDataLen; + EMAC_ReadPacketBuffer(&rxBuffer); + EMAC_UpdateRxConsumeIndex(); + + *packet = (uint8_t *)rxBuffer.pbDataBuf; + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("received %d byte frame", *length)); + } + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result)); + return result; +} + + +static int32_t Write(uint8_t *packet, int32_t length) +{ + int32_t result = 0; + + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("request to send %d bytes", length)); + + if (EMAC_TxBufferNotFull()) + { + DEBUG_BLOCK(DEBUG_LEVEL_VERBOSE0) + { + Debug_DumpBufferHex(packet, length); + } + txBuffer.ulDataLen = length; + txBuffer.pbDataBuf = (uint32_t *)packet; + EMAC_WritePacketBuffer(&txBuffer); + EMAC_UpdateTxProduceIndex(); + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE1, ("transmitted %d byte frame", length)); + } + else + { + DEBUG_SOURCE(DEBUG_LEVEL_ERROR, ("transmission queue is full")); + mbedNet_LastError = mbedNetResult_QueueEmpty; + result = -1; + } + DEBUG_MODULE(DEBUG_LEVEL_VERBOSE2, ("leaving with code %d", result)); + return result; +} + + +static void Enable(void) +{ + /* Enable receive and transmit mode of MAC Ethernet core */ + LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN); + LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; + NVIC_EnableIRQ(ENET_IRQn); +} + + +static void Disable(void) +{ + /* Disable receive and transmit mode of MAC Ethernet core */ + NVIC_DisableIRQ(ENET_IRQn); + LPC_EMAC->Command &= ~(EMAC_CR_RX_EN | EMAC_CR_TX_EN); + LPC_EMAC->MAC1 &= ~EMAC_MAC1_REC_EN; + while(EMAC_CheckReceiveIndex()) EMAC_UpdateRxConsumeIndex(); +} + + +static uint8_t *GetTxBuffer(void) +{ + return txPacket; +} + + +static Bool_t EMAC_TxBufferNotFull(void) +{ + uint32_t tmp = LPC_EMAC->TxProduceIndex + 1; + + if (tmp == EMAC_NUM_TX_FRAG) tmp = 0; + return (LPC_EMAC->TxConsumeIndex != tmp) ? True : False; +} + + +extern "C" void ENET_IRQHandler(void) +{ + uint32_t status; + Packet_t rxP; + + status = LPC_EMAC->IntStatus; + LPC_EMAC->IntClear = status; + + if(status & EMAC_INT_RX_DONE) + { + while(EMAC_CheckReceiveIndex() == TRUE) + { + if (Read(&rxP.data, &rxP.length) == 0) + { + rxP.depth = -1; + ethernet.HandlePacket(mbedNetIF, &rxP); + } + } + } +}