Raw Ethernet issues with XMC4800 on Relax EtherCAT card

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
EDIT: The issue has been resolved. It was not related to the Ethernet stack. Please remove this thread.


Hi,

We are communicating between a PC and the XMC4800 Relax EtherCAT board via Ethernet. The communication works well until we have sent ~1MB. At that point memory becomes corrupted.
We are using raw ethernet non-jumbo frames, sending and receving packages with payload of 1496 bytes.
We are using the file xmc_eth_phy_ksz8081ml.c (2015-06-20) for the phy device.

Everything works well until we have sent ~1MB. At that point, the buffer send_frame[] starts getting corrupted from its lower bytes and up. It's as if there is a buffer overflow in the memory before that location. In the memory map, the buffer recv_frame[] is located before send_frame. This made me suspicious that the recv_frame overwrites its boundaries, but after investigating that is not the case. Moving send_frame[] to another address in ram (by adding another dummy-array between recv_frame and send_frame) will make the memory corruption happen later (around 2MBs).

Running the application in DEBUG mode works well. This issue is not happening in DEBUG.

Below is the code for handling the Ethernet communication. We are sending and receving approximately 100kB/s in bursts.

Any ideas of what could cause this?

Thanks
Rickard


/*
* Ethernet.c
*/

#include "Ethernet.h"
#include "EventLoop.h"
#include
#include
#include

#define RX_BUFSIZE 53300
#define TX_BUFSIZE 5000
uint8_t rxBufEth[2][RX_BUFSIZE] = {{0},{0}};
uint8_t txBufEth[TX_BUFSIZE] = {0};
uint32_t receivedBytes[2] = {0};
uint32_t bytesToSend = 0;

static uint32_t readIndex = 0;
static uint32_t writeIndex = 0;

#define ETH_PHY_ADDR 0

#define ETH_RXD1 P2_3
#define ETH_RXD0 P2_2
#define ETH_RXER P2_4
#define ETH_CLK_RMII P15_8
#define ETH_TX_EN P2_5
#define ETH_TXD1 P2_9
#define ETH_TXD0 P2_8
#define ETH_CRS_DV P15_9
#define ETH_MDIO P2_0
#define ETH_MDC P2_7

/* MAC ADDRESS*/
#define MAC_ADDR0 0x00
#define MAC_ADDR1 0x00
#define MAC_ADDR2 0x45
#define MAC_ADDR3 0x19
#define MAC_ADDR4 0x03
#define MAC_ADDR5 0x00
#define MAC_ADDR ((uint64_t)MAC_ADDR0 | \
((uint64_t)MAC_ADDR1 << 😎 | \
((uint64_t)MAC_ADDR2 << 16) | \
((uint64_t)MAC_ADDR3 << 24) | \
((uint64_t)MAC_ADDR4 << 32) | \
((uint64_t)MAC_ADDR5 << 40))

#define XMC_ETH_MAC_NUM_RX_BUF (4)
#define XMC_ETH_MAC_NUM_TX_BUF (4)

#define USERDATA 14

static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t rx_desc[XMC_ETH_MAC_NUM_RX_BUF] __attribute__((section ("ETH_RAM")));
static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t tx_desc[XMC_ETH_MAC_NUM_TX_BUF] __attribute__((section ("ETH_RAM")));
static __attribute__((aligned(4))) uint8_t rx_buf[XMC_ETH_MAC_NUM_RX_BUF][XMC_ETH_MAC_BUF_SIZE] __attribute__((section ("ETH_RAM")));
static __attribute__((aligned(4))) uint8_t tx_buf[XMC_ETH_MAC_NUM_TX_BUF][XMC_ETH_MAC_BUF_SIZE] __attribute__((section ("ETH_RAM")));

static XMC_ETH_PHY_CONFIG_t eth_phy_config =
{
.interface = XMC_ETH_LINK_INTERFACE_RMII,
.enable_auto_negotiate = true
};

static XMC_ETH_MAC_t eth_mac =
{
.regs = ETH0,
.address = MAC_ADDR,
.rx_desc = rx_desc,
.tx_desc = tx_desc,
.rx_buf = &rx_buf[0][0],
.tx_buf = &tx_buf[0][0],
.num_rx_buf = XMC_ETH_MAC_NUM_RX_BUF,
.num_tx_buf = XMC_ETH_MAC_NUM_TX_BUF
};

static __attribute__((aligned(4))) uint8_t recv_frame[XMC_ETH_MAC_BUF_SIZE];
static __attribute__((aligned(4))) uint8_t send_frame[XMC_ETH_MAC_BUF_SIZE];

unsigned char xmc_mac[6] = {0x00, 0x00, 0x45, 0x19, 0x03, 0x00};
unsigned char pc_mac[6] = {0x54, 0xEE, 0x75, 0x56, 0xA8, 0x09};
unsigned char ethType[2] = { 0xb5, 0x88 };

void ETH_MAC_Init(void);

void Ethernet_Initialize()
{
ETH_MAC_Init();

memset(send_frame, 0, XMC_ETH_MAC_BUF_SIZE);
memcpy(&send_frame[0], &pc_mac[0], 6); // destination
memcpy(&send_frame[6], &xmc_mac[0], 6); // source
memcpy(&send_frame[12], &ethType[0], 2); // ethType
}

int32_t CheckCorruption()
{
int32_t res = memcmp(&send_frame[0], &pc_mac[0], 6);
res |= memcmp(&send_frame[6], &xmc_mac[0], 6);
res |= memcmp(&send_frame[12], &ethType[0], 2);
return res;
}

void Ethernet_StartTransmit(uint8_t* data, uint32_t count)
{
memcpy(&send_frame[16], &data[0], count);

if (CheckCorruption())
{
XMC_GPIO_ToggleOutput(XMC_GPIO_PORT3, 0U);
}

XMC_ETH_MAC_SendFrame(&eth_mac, &send_frame[0], count + 16, 0);
}

uint32_t Ethernet_GetBuffer(uint8_t** buf)
{
uint32_t ret = receivedBytes[readIndex];
receivedBytes[readIndex] = 0;
*buf = &rxBufEth[readIndex][0];
readIndex = readIndex == 0 ? 1 : 0;
return ret;
}

// ethernet initialisation
// from a tip by Jesus @ Infineon forum
void ETH_MAC_Init(void)
{
XMC_ETH_MAC_PORT_CTRL_t port_control;
XMC_GPIO_CONFIG_t gpio_config;

gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
XMC_GPIO_Init(ETH_RXD0, &gpio_config);
XMC_GPIO_Init(ETH_RXD1, &gpio_config);
XMC_GPIO_Init(ETH_CLK_RMII, &gpio_config);
XMC_GPIO_Init(ETH_CRS_DV, &gpio_config);
XMC_GPIO_Init(ETH_RXER, &gpio_config);
XMC_GPIO_Init(ETH_MDIO, &gpio_config);

port_control.mode = XMC_ETH_MAC_PORT_CTRL_MODE_RMII;
port_control.rxd0 = XMC_ETH_MAC_PORT_CTRL_RXD0_P2_2;
port_control.rxd1 = XMC_ETH_MAC_PORT_CTRL_RXD1_P2_3;
port_control.clk_rmii = XMC_ETH_MAC_PORT_CTRL_CLK_RMII_P15_8;
port_control.crs_dv = XMC_ETH_MAC_PORT_CTRL_CRS_DV_P15_9;
port_control.rxer = XMC_ETH_MAC_PORT_CTRL_RXER_P2_4;
port_control.mdio = XMC_ETH_MAC_PORT_CTRL_MDIO_P2_0;
XMC_ETH_MAC_SetPortControl(&eth_mac, port_control);

XMC_ETH_MAC_Init(&eth_mac);

XMC_ETH_MAC_DisableJumboFrame(&eth_mac);

gpio_config.output_level = XMC_GPIO_OUTPUT_LEVEL_LOW;
gpio_config.output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SHARP_EDGE;
gpio_config.mode = (XMC_GPIO_MODE_t)((uint32_t)XMC_GPIO_MODE_OUTPUT_PUSH_PULL | P2_8_AF_ETH0_TXD0);
XMC_GPIO_Init(ETH_TXD0, &gpio_config);

gpio_config.mode = (XMC_GPIO_MODE_t)((uint32_t)XMC_GPIO_MODE_OUTPUT_PUSH_PULL | P2_9_AF_ETH0_TXD1);
XMC_GPIO_Init(ETH_TXD1, &gpio_config);

gpio_config.mode = (XMC_GPIO_MODE_t)((uint32_t)XMC_GPIO_MODE_OUTPUT_PUSH_PULL | P2_5_AF_ETH0_TX_EN);
XMC_GPIO_Init(ETH_TX_EN, &gpio_config);

gpio_config.mode = (XMC_GPIO_MODE_t)((uint32_t)XMC_GPIO_MODE_OUTPUT_PUSH_PULL | P2_7_AF_ETH0_MDC);
XMC_GPIO_Init(ETH_MDC, &gpio_config);

XMC_GPIO_SetHardwareControl(ETH_MDIO, P2_0_HWCTRL_ETH0_MDO);

XMC_ETH_PHY_Init(&eth_mac, ETH_PHY_ADDR, &eth_phy_config);

while(XMC_ETH_PHY_GetLinkStatus(&eth_mac, ETH_PHY_ADDR) != XMC_ETH_LINK_STATUS_UP);

XMC_ETH_LINK_SPEED_t speed = XMC_ETH_PHY_GetLinkSpeed(&eth_mac, ETH_PHY_ADDR);
XMC_ETH_LINK_DUPLEX_t duplex = XMC_ETH_PHY_GetLinkDuplex(&eth_mac, ETH_PHY_ADDR);

XMC_ETH_MAC_SetLink(&eth_mac, speed, duplex);

// Enable ethernet interrupts
XMC_ETH_MAC_EnableEvent(&eth_mac, XMC_ETH_MAC_EVENT_RECEIVE);

NVIC_SetPriority(ETH0_0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 63, 0));
NVIC_ClearPendingIRQ(ETH0_0_IRQn);
NVIC_EnableIRQ(ETH0_0_IRQn);

XMC_ETH_MAC_EnableTx(&eth_mac);
XMC_ETH_MAC_EnableRx(&eth_mac);
}

// Ethernet receive interrupt routine
void ETH0_0_IRQHandler(void)
{
uint32_t status;
uint32_t len;

status = XMC_ETH_MAC_GetEventStatus(&eth_mac);

if (status & XMC_ETH_MAC_EVENT_RECEIVE)
{
XMC_ETH_MAC_ClearEventStatus(&eth_mac, XMC_ETH_MAC_EVENT_RECEIVE);

len = XMC_ETH_MAC_GetRxFrameSize(&eth_mac);
XMC_ETH_MAC_ReadFrame(&eth_mac, &recv_frame[0], len);

if (memcmp(&recv_frame[0], &xmc_mac, 6))
{ // packet for us?
return; // nope
}

uint16_t fragmentationOffset = recv_frame[14] | ((recv_frame[15] & 0x7F) << 8);
uint16_t offset = 8 * fragmentationOffset;
uint32_t dataLength = len - 14 - 2;

if (receivedBytes[writeIndex] + dataLength > RX_BUFSIZE)
{
return;
}

memcpy(&rxBufEth[writeIndex][offset], &recv_frame[16], dataLength);
receivedBytes[writeIndex] += dataLength;

if (ethData->moreFragments)
{
// Wait for more data
return;
}

writeIndex = writeIndex == 0 ? 1 : 0;

EventLoop_events |= ReceivedEthernetPackageEventFlag;
}
}
0 Likes
0 Replies