Hello everyone!
I am trying to migrate a simple application using ENET driver from a MK60DN256 (Rev 2.x) to a MK60DN256Z (Rev 1.x).
I came across what I suspect is a known issue about this driver and the Buffer Descriptor: the driver of the DEMO I have got from a generated SDK 2.2 (LWIP ping baremetal) uses the DBSWP functionality from the ENET_ECR register, which is a new functionality added in the 2.x release of the microprocessor I am using.
What I am trying to do now (at the present with little success) is manually disable the DBSWP bit from the ENET_ECR register and swap structure and the endian-ness of _enet_rx_bd_struct.
The migration guide AN4445 says that I have to change the structure from (2.x):
typedef struct
{
uint16_t length; /* transfer length */
uint16_t status; /* control and status */
uint8_t *data; /* buffer address */
} NBUF;
to (1.x):
typedef struct
{
uint16_t status; /* control and status */
uint16_t length; /* transfer length */
uint8_t *data; /* buffer address */
} NBUF;
I also tried to follow some other forum discussions in order to manually swap the endian-ness of the structure content (like bit masks defines).
I am working on it from fiew days now and I think I am missing something (or I am doing something wrong, or something highly discouraged), but I need to find out a solution.
Do you have any suggestions or a driver version already compatible with my micro revision?
In attachment the original version of the driver modules I am working on.
Hi Mattia
You can reference the uTasker project (with integrated TCP/IP stack and real-time Kinetis Ethernet emulation in VisualStudio) on Git Hub. It automatically selects the natural little-endian ENET mode if the chip used support its and operates on all Kinetis parts wit Ethernet or RNDIS over USB.
Below are the defines that need to be controlled so that you quickly solve your present difficulty.
Regards
Mark
#if defined ETHER_DBSWP // natural little-endian
typedef struct stKINETIS_FEC_BD
{
volatile unsigned short usBDLength;
volatile unsigned short usBDControl;
unsigned char *ptrBD_Data;
#if defined 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 promiscuous 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;
#if defined 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 promiscuous 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
Hello Mark,
These are very interesting information, thank you.
I quickly tried to apply them to my project, but it not seems working anyway.
The changes I applied are:
typedef struct _enet_rx_bd_struct { #if 0 uint16_t length; /*!< Buffer descriptor data length. */ uint16_t control; /*!< Buffer descriptor control and status. */ uint8_t *buffer; /*!< Data buffer pointer. */ #else uint16_t control; /*!< Buffer descriptor control and status. */ uint16_t length; /*!< Buffer descriptor data length. */ uint8_t *buffer; /*!< Data buffer pointer. */ #endif #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE uint16_t controlExtend0; /*!< Extend buffer descriptor control0. */ uint16_t controlExtend1; /*!< Extend buffer descriptor control1. */ uint16_t payloadCheckSum; /*!< Internal payload checksum. */ uint8_t headerLength; /*!< Header length. */ uint8_t protocolTyte; /*!< Protocol type. */ uint16_t reserved0; uint16_t controlExtend2; /*!< Extend buffer descriptor control2. */ uint32_t timestamp; /*!< Timestamp. */ uint16_t reserved1; uint16_t reserved2; uint16_t reserved3; uint16_t reserved4; #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_rx_bd_struct_t; typedef struct _enet_tx_bd_struct { #if 0 uint16_t length; /*!< Buffer descriptor data length. */ uint16_t control; /*!< Buffer descriptor control and status. */ uint8_t *buffer; /*!< Data buffer pointer. */ #else uint16_t control; /*!< Buffer descriptor control and status. */ uint16_t length; /*!< Buffer descriptor data length. */ uint8_t *buffer; /*!< Data buffer pointer. */ #endif #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE uint16_t controlExtend0; /*!< Extend buffer descriptor control0. */ uint16_t controlExtend1; /*!< Extend buffer descriptor control1. */ uint16_t reserved0; uint16_t reserved1; uint16_t reserved2; uint16_t controlExtend2; /*!< Extend buffer descriptor control2. */ uint32_t timestamp; /*!< Timestamp. */ uint16_t reserved3; uint16_t reserved4; uint16_t reserved5; uint16_t reserved6; #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ } enet_tx_bd_struct_t;
#if 0 #define ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK 0x8000U /*!< Empty bit mask. */ #define ENET_BUFFDESCRIPTOR_RX_SOFTOWNER1_MASK 0x4000U /*!< Software owner one mask. */ #define ENET_BUFFDESCRIPTOR_RX_WRAP_MASK 0x2000U /*!< Next buffer descriptor is the start address. */ #define ENET_BUFFDESCRIPTOR_RX_SOFTOWNER2_Mask 0x1000U /*!< Software owner two mask. */ #define ENET_BUFFDESCRIPTOR_RX_LAST_MASK 0x0800U /*!< Last BD of the frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_MISS_MASK 0x0100U /*!< Received because of the promiscuous mode. */ #define ENET_BUFFDESCRIPTOR_RX_BROADCAST_MASK 0x0080U /*!< Broadcast packet mask. */ #define ENET_BUFFDESCRIPTOR_RX_MULTICAST_MASK 0x0040U /*!< Multicast packet mask. */ #define ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK 0x0020U /*!< Length violation mask. */ #define ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK 0x0010U /*!< Non-octet aligned frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_CRC_MASK 0x0004U /*!< CRC error mask. */ #define ENET_BUFFDESCRIPTOR_RX_OVERRUN_MASK 0x0002U /*!< FIFO overrun mask. */ #define ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK 0x0001U /*!< Frame is truncated mask. */ #define ENET_BUFFDESCRIPTOR_TX_READY_MASK 0x8000U /*!< Ready bit mask. */ #define ENET_BUFFDESCRIPTOR_TX_SOFTOWENER1_MASK 0x4000U /*!< Software owner one mask. */ #define ENET_BUFFDESCRIPTOR_TX_WRAP_MASK 0x2000U /*!< Wrap buffer descriptor mask. */ #define ENET_BUFFDESCRIPTOR_TX_SOFTOWENER2_MASK 0x1000U /*!< Software owner two mask. */ #define ENET_BUFFDESCRIPTOR_TX_LAST_MASK 0x0800U /*!< Last BD of the frame mask. */ #define ENET_BUFFDESCRIPTOR_TX_TRANMITCRC_MASK 0x0400U /*!< Transmit CRC mask. */ #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE #define ENET_BUFFDESCRIPTOR_RX_IPV4_MASK 0x0001U /*!< Ipv4 frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_IPV6_MASK 0x0002U /*!< Ipv6 frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_VLAN_MASK 0x0004U /*!< VLAN frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_PROTOCOLCHECKSUM_MASK 0x0010U /*!< Protocol checksum error mask. */ #define ENET_BUFFDESCRIPTOR_RX_IPHEADCHECKSUM_MASK 0x0020U /*!< IP header checksum error mask. */ #define ENET_BUFFDESCRIPTOR_RX_INTERRUPT_MASK 0x0080U /*!< BD interrupt mask. */ #define ENET_BUFFDESCRIPTOR_RX_UNICAST_MASK 0x0100U /*!< Unicast frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_COLLISION_MASK 0x0200U /*!< BD collision mask. */ #define ENET_BUFFDESCRIPTOR_RX_PHYERR_MASK 0x0400U /*!< PHY error mask. */ #define ENET_BUFFDESCRIPTOR_RX_MACERR_MASK 0x8000U /*!< Mac error mask. */ #define ENET_BUFFDESCRIPTOR_TX_ERR_MASK 0x8000U /*!< Transmit error mask. */ #define ENET_BUFFDESCRIPTOR_TX_UNDERFLOWERR_MASK 0x2000U /*!< Underflow error mask. */ #define ENET_BUFFDESCRIPTOR_TX_EXCCOLLISIONERR_MASK 0x1000U /*!< Excess collision error mask. */ #define ENET_BUFFDESCRIPTOR_TX_FRAMEERR_MASK 0x0800U /*!< Frame error mask. */ #define ENET_BUFFDESCRIPTOR_TX_LATECOLLISIONERR_MASK 0x0400U /*!< Late collision error mask. */ #define ENET_BUFFDESCRIPTOR_TX_OVERFLOWERR_MASK 0x0200U /*!< Overflow error mask. */ #define ENET_BUFFDESCRIPTOR_TX_TIMESTAMPERR_MASK 0x0100U /*!< Timestamp error mask. */ #define ENET_BUFFDESCRIPTOR_TX_INTERRUPT_MASK 0x4000U /*!< Interrupt mask. */ #define ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK 0x2000U /*!< Timestamp flag mask. */ #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ #else #define ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK 0x0080U /*!< Empty bit mask. */ #define ENET_BUFFDESCRIPTOR_RX_SOFTOWNER1_MASK 0x0040U /*!< Software owner one mask. */ #define ENET_BUFFDESCRIPTOR_RX_WRAP_MASK 0x0020U /*!< Next buffer descriptor is the start address. */ #define ENET_BUFFDESCRIPTOR_RX_SOFTOWNER2_Mask 0x0010U /*!< Software owner two mask. */ #define ENET_BUFFDESCRIPTOR_RX_LAST_MASK 0x0008U /*!< Last BD of the frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_MISS_MASK 0x0001U /*!< Received because of the promiscuous mode. */ #define ENET_BUFFDESCRIPTOR_RX_BROADCAST_MASK 0x8000U /*!< Broadcast packet mask. */ #define ENET_BUFFDESCRIPTOR_RX_MULTICAST_MASK 0x4000U /*!< Multicast packet mask. */ #define ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK 0x2000U /*!< Length violation mask. */ #define ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK 0x1000U /*!< Non-octet aligned frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_CRC_MASK 0x0400U /*!< CRC error mask. */ #define ENET_BUFFDESCRIPTOR_RX_OVERRUN_MASK 0x0200U /*!< FIFO overrun mask. */ #define ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK 0x0100U /*!< Frame is truncated mask. */ #define ENET_BUFFDESCRIPTOR_TX_READY_MASK 0x0080U /*!< Ready bit mask. */ #define ENET_BUFFDESCRIPTOR_TX_SOFTOWENER1_MASK 0x0040U /*!< Software owner one mask. */ #define ENET_BUFFDESCRIPTOR_TX_WRAP_MASK 0x0020U /*!< Wrap buffer descriptor mask. */ #define ENET_BUFFDESCRIPTOR_TX_SOFTOWENER2_MASK 0x0010U /*!< Software owner two mask. */ #define ENET_BUFFDESCRIPTOR_TX_LAST_MASK 0x0008U /*!< Last BD of the frame mask. */ #define ENET_BUFFDESCRIPTOR_TX_TRANMITCRC_MASK 0x0004U /*!< Transmit CRC mask. */ #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE #define ENET_BUFFDESCRIPTOR_RX_IPV4_MASK 0x0100U /*!< Ipv4 frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_IPV6_MASK 0x0200U /*!< Ipv6 frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_VLAN_MASK 0x0400U /*!< VLAN frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_PROTOCOLCHECKSUM_MASK 0x1000U /*!< Protocol checksum error mask. */ #define ENET_BUFFDESCRIPTOR_RX_IPHEADCHECKSUM_MASK 0x2000U /*!< IP header checksum error mask. */ #define ENET_BUFFDESCRIPTOR_RX_INTERRUPT_MASK 0x8000U /*!< BD interrupt mask. */ #define ENET_BUFFDESCRIPTOR_RX_UNICAST_MASK 0x0001U /*!< Unicast frame mask. */ #define ENET_BUFFDESCRIPTOR_RX_COLLISION_MASK 0x0002U /*!< BD collision mask. */ #define ENET_BUFFDESCRIPTOR_RX_PHYERR_MASK 0x0004U /*!< PHY error mask. */ #define ENET_BUFFDESCRIPTOR_RX_MACERR_MASK 0x0080U /*!< Mac error mask. */ #define ENET_BUFFDESCRIPTOR_TX_ERR_MASK 0x0080U /*!< Transmit error mask. */ #define ENET_BUFFDESCRIPTOR_TX_UNDERFLOWERR_MASK 0x0020U /*!< Underflow error mask. */ #define ENET_BUFFDESCRIPTOR_TX_EXCCOLLISIONERR_MASK 0x0010U /*!< Excess collision error mask. */ #define ENET_BUFFDESCRIPTOR_TX_FRAMEERR_MASK 0x0008U /*!< Frame error mask. */ #define ENET_BUFFDESCRIPTOR_TX_LATECOLLISIONERR_MASK 0x0004U /*!< Late collision error mask. */ #define ENET_BUFFDESCRIPTOR_TX_OVERFLOWERR_MASK 0x0002U /*!< Overflow error mask. */ #define ENET_BUFFDESCRIPTOR_TX_TIMESTAMPERR_MASK 0x0001U /*!< Timestamp error mask. */ #define ENET_BUFFDESCRIPTOR_TX_INTERRUPT_MASK 0x0040U /*!< Interrupt mask. */ #define ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK 0x0020U /*!< Timestamp flag mask. */ #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ #endif
And of course I disabled the DBSWP bit. I cannot figure out what I am missing.
Mattia
Without looking in more detail I don't know what the problem is but maybe some pointers used by other parts of the code (eg. when constructing the buffer descriptor pointers) need to also be swapped between little and big endian at run time.
If you download the open source uTasker project from GIT hub you can run it in Visual Studio (in both modes) and emulate the complete operation. If you step through the initialisation and compare with your code you may find some additional things required.
Good luck.
Regards
Mark
P.S. If you are a professional and you need a quick solution you can also get help at http://www.utasker.com/support.html
Hello Mark,
Thank you for the support, I finally got through the problem.
I confirm that the problem is on the endian-ness of the buffer descriptor pointers. As I suspected, the whole structure has to work with the reversed endian-ness.
Regards,
Mattia