Hi All
The Kinetis has an Ethernet EMAC peripheral (when available) based on the one used in the Coldfire but with some extensions. The EMAC is based on buffer descriptors which are created and controlled in SRAM and these buffer descriptors work basically in big-endian mode. This suited the Coldfire but required some big / little-endian swapping in code when used with the Cortex M4 based Kinetis.
It happens that the K70 and K61 derivatives now allow the endian mode to be configured so that the buffer descriptors can operate in the more natural (for the ARM) mode which saves having to do this swapping in code and there results in a small improvement in the code efficiency. Although maybe not a huge saving every bit helps and so the following change has been made to make use of this capability.
1) When the chip supports this it will have an extra bit called ETHER_DBSWP in the EMAC ECR register. Therefore this bit is made conditional on the processor used:
#define ECR *(volatile unsigned long *)(EMAC_BASE_ADD + 0x24) // Ethernet Control Register
#define RESET_FEC 0x00000001 // issue MAC reset (self-clearing)
#define ETHER_EN 0x00000002 // enable ethernet operation
#define ETHER_MAGICEN 0x00000004 // enable magic package detection
#define ETHER_SLEEP 0x00000008 // enable sleep mode
#define ETHER_EN1588 0x00000010 // enable enhanced functionality
#define ETHER_DBGEN 0x00000040 // enter freeze mode when debuggig
#define ETHER_STOPEN 0x00000080 // enabled in doze mode
#if defined KINETIS_K61 || defined KINETIS_K70
#define ETHER_DBSWP 0x00000100 // enabled descriptor byte swapping to support little-endian devices
#endif
2) Then the definitions of the buffer descriptors and their content are conditional on the presence of the bit:
#if defined ETHER_DBSWP // natural little-endian
typedef struct stKINETIS_FEC_BD
{
volatile unsigned short usBDLength;
volatile unsigned short usBDControl;
unsigned char *ptrBD_Data;
#ifdef EMAC_ENHANCED // additional fields available in enhanced mode
volatile unsigned long ulBDControlEnhanced;
volatile unsigned short usPayloadCS; // only receiver
volatile unsigned short usRxInfoHeaderProt; // only receiver
volatile unsigned long ulBDU;
volatile unsigned long ul1588_timestamp;
unsigned long ulRes[2];
#endif
} KINETIS_FEC_BD;
#define EMPTY_BUFFER 0x8000 // RX BD Control bits
#define RECEIVE_OWNERSHIP_1 0x4000 // can be optionally used by software
#define WRAP_BIT_RX 0x2000
#define RECEIVE_OWNERSHIP_2 0x1000 // can be optionally used by software
#define LAST_IN_FRAME_RX 0x0800
#define RECEIVE_MISS 0x0100 // received due to promiscuouse mode only
#define RECEIVE_BROADCAST 0x0080 // received due to broadcast address
#define RECEIVE_MULTICAST 0x0040 // received due to multicast address
#define RECEIVE_LENGTH_VIOL 0x0020 // receive frame length violation
#define RECEIVE_NON_OCTET_AL 0x0010 // non-octet aligned frame
#define RECEIVE_CRC_ERROR 0x0004 // receive CRC or frame error
#define OVERRUN_FRAME 0x0002
#define TRUNCATED_FRAME 0x0001
// Enhanced
//
#define RX_MAC_ERROR 0x80000000
#define RX_PHY_ERROR 0x04000000
#define RX_COLLISION 0x02000000
#define RX_UNICAST 0x01000000
#define RX_GEN_INTERRUPT 0x00800000
#define RX_IP_CS_ERROR 0x00000020
#define RX_PROT_CS_ERROR 0x00000010
#define RX_VLAN 0x00000004
#define RX_IPV6 0x00000002
#define RX_IPV4_FRAG 0x00000001
#define RX_HEADER_LEN_MASK 0xf800
#define RX_PROT_TYPE_MASK 0x00ff
#define READY_TX 0x8000 // TX BD Control bits
#define TRANSMIT_OWNERSHIP_1 0x4000 // can be optionally used by software
#define WRAP_BIT_TX 0x2000
#define TRANSMIT_OWNERSHIP_2 0x1000 // can be optionally used by software
#define LAST_IN_FRAME_TX 0x0800
#define TX_CRC 0x0400
#define TX_ABC 0x0200 // append bad CRC - not supported in enhanced mode
// Enhanced
//
#define TX_GENERATE_INT 0x40000000
#define TX_ADD_TIMESTAMP 0x20000000
#define TX_INSERT_PROT_CS 0x10000000
#define TX_INSERT_IP_CS 0x08000000
#define TX_ERROR_OCCURRED 0x00008000
#define TX_UNDERFLOW_ERROR 0x00002000
#define TX_EXCESS_COLLISIONS 0x00001000
#define TX_FRAME_ERROR 0x00000800
#define TX_LATE_COLLISION 0x00000400
#define TX_OVERFLOW_ERROR 0x00000200
#define TX_TIMESTAMP_ERROR 0x00000100
#define BD_UPDATE_DONE 0x80000000 // rx and tx
#else // big-endian representation
typedef struct stKINETIS_FEC_BD
{
volatile unsigned short usBDControl;
volatile unsigned short usBDLength;
unsigned char *ptrBD_Data;
#ifdef EMAC_ENHANCED // additional fields available in enhanced mode
volatile unsigned long ulBDControlEnhanced;
volatile unsigned short usRxInfoHeaderProt; // only receiver
volatile unsigned short usPayloadCS; // only receiver
volatile unsigned long ulBDU;
volatile unsigned long ul1588_timestamp;
unsigned long ulRes[2];
#endif
} KINETIS_FEC_BD;
#define EMPTY_BUFFER 0x0080 // RX BD Control bits
#define RECEIVE_OWNERSHIP_1 0x0040 // can be optionally used by software
#define WRAP_BIT_RX 0x0020
#define RECEIVE_OWNERSHIP_2 0x0010 // can be optionally used by software
#define LAST_IN_FRAME_RX 0x0008
#define RECEIVE_MISS 0x0001 // received due to promiscuouse mode only
#define RECEIVE_BROADCAST 0x8000 // received due to broadcast address
#define RECEIVE_MULTICAST 0x4000 // received due to multicast address
#define RECEIVE_LENGTH_VIOL 0x2000 // receive frame length violation
#define RECEIVE_NON_OCTET_AL 0x1000 // non-octet aligned frame
#define RECEIVE_CRC_ERROR 0x0400 // receive CRC or frame error
#define OVERRUN_FRAME 0x0200
#define TRUNCATED_FRAME 0x0100
// Enhanced
//
#define RX_MAC_ERROR 0x00000080
#define RX_PHY_ERROR 0x00000004
#define RX_COLLISION 0x00000002
#define RX_UNICAST 0x00000001
#define RX_GEN_INTERRUPT 0x00008000
#define RX_IP_CS_ERROR 0x20000000
#define RX_PROT_CS_ERROR 0x10000000
#define RX_VLAN 0x04000000
#define RX_IPV6 0x02000000
#define RX_IPV4_FRAG 0x01000000
#define RX_HEADER_LEN_MASK 0x00f8
#define RX_PROT_TYPE_MASK 0xff00
#define READY_TX 0x0080 // TX BD Control bits
#define TRANSMIT_OWNERSHIP_1 0x0040 // can be optionally used by software
#define WRAP_BIT_TX 0x0020
#define TRANSMIT_OWNERSHIP_2 0x0010 // can be optionally used by software
#define LAST_IN_FRAME_TX 0x0008
#define TX_CRC 0x0004
#define TX_ABC 0x0002 // append bad CRC - not supported in enhanced mode
// Enhanced
//
#define TX_GENERATE_INT 0x00000040
#define TX_ADD_TIMESTAMP 0x00000020
#define TX_INSERT_PROT_CS 0x00000010
#define TX_INSERT_IP_CS 0x00000008
#define TX_ERROR_OCCURRED 0x00800000
#define TX_UNDERFLOW_ERROR 0x00200000
#define TX_EXCESS_COLLISIONS 0x00100000
#define TX_FRAME_ERROR 0x00080000
#define TX_LATE_COLLISION 0x00040000
#define TX_OVERFLOW_ERROR 0x00020000
#define TX_TIMESTAMP_ERROR 0x00010000
#define BD_UPDATE_DONE 0x00000080 // rx and tx
#endif
Note that the buffer descriptor content is swapped between little-and big-endian and also some of the elements in the KINETIS_FEC_BD struct have a different ordering to suit.
3) When accesses to some buffer descriptor values (like data length and address pointers) are made macros are used which are defined as below. When the buffer decriptors can work in little-endian mode the macros are simply made to directly use the value without any extra work:
#if defined _WINDOWS || defined ETHER_DBSWP // device with ETHER_DBSWP control in the ECR register can configure the EMAC buffer decriptors to use little-endian mode
#define fnLE_ENET_add(x) x
#define fnLE_ENET_word(x) x
#else
// Convert between little and big-endian address
//
#define fnLE_ENET_add(x) (unsigned char *)(((unsigned long)(x) >> 24) | (((unsigned long)(x) >> 8) & 0x0000ff00) | (((unsigned long)(x) << 8) & 0x00ff0000) | (((unsigned long)(x) << 24) & 0xff000000))
// Convert between little and big-endian short word
//
#define fnLE_ENET_word(x) (((unsigned short)(x) >> 8) | ((unsigned short)(x) << 8))
#endif
4) Finally, when the Ethernet operation is enabled - or re-enabled, the little-endian mode is selected by
ECR = ENABLE_ETHERNET_OPERATION;
where the value of ENABLE_ETHERNET_OPERATION is made conditional on whether enhanced mode is used or whether the chip supports the little-endian mode by using the following:
#ifdef EMAC_ENHANCED
#if defined ETHER_DBSWP // if the EMAC supports buffer descriptors in little-endian format enable this mode
#define ENABLE_ETHERNET_OPERATION (ETHER_EN | ETHER_EN1588 | ETHER_DBSWP)
#else
#define ENABLE_ETHERNET_OPERATION (ETHER_EN | ETHER_EN1588)
#endif
#else
#if defined ETHER_DBSWP // if the EMAC supports buffer descriptors in little-endian format enable this mode
#define ENABLE_ETHERNET_OPERATION (ETHER_EN | ETHER_DBSWP)
#else
#define ENABLE_ETHERNET_OPERATION (ETHER_EN)
#endif
#endif
Therefore by changing a few defines K70 and K61 processors automatically take advantage of this capability...
Good luck!
Regards
Mark
P.S. The above has been tested and will be automatically included in the next Kinetis project release.