I have to write new firmware for an old device. The device is based on the MK60DN512ZVMC10 (note the Z) and uses an Ethernet connection to communication with a control system. The existing firmware is based on MQX and some unknown version of the Kinetis SDK and is in quite a messy state. Hence it was decided to rewrite the firmware based on FreeRTOS and the LWIP stack (and to use the open62541 stack to replace our broken custom network protocol).
I downloaded the MCUXpresso SDK with FreeRTOS and LWIP and used the Config Tools to setup pins, clocks and peripherials. After realising the differences between MK60DN512ZVMC10 and MK60DN512VMC10 (NXP should really point this out clearly on the product page!), I found out that I have to comment a few lines which use MCG->C7 so that the clock configuration works (it tries to configure a switch which is not there and hence runs into a hard fault - the commented lines merely put the switch into the position which is the hardcoded signal flow in my MCU). Now the code compiles and runs, and I see output on the serial console.
Next part is to get Ethernet working. I managed to communicate with the PHY by using fsl_phy.c/h from one of the examples and modifying it slightly (our PHY somehow seems to report the auto-negotiation result differently). I see it reports a link with the proper parameters (100M full-duplex), and this matches what the other side sees.
From this point I do not get any further. I do not manage to convince the Ethernet controller to send or receive any packages. I have tried many things. To boil down the problem, I have switched to the enet_txrx_transfer example and modified it for my board. I again see serial output and the PHY is working, but nothing gets transmitted or received through Ethernet. The example seems to fill up the buffers and prints "The 1 frame transmitted success!" etc. until the buffers are all full, then it prints "Transmit frame failed!" for the remaining attempts. Of course I have checked with wireshark that no package arrives at the other side.
I went through all registers of the Ethernet controller and checked them with the reference manual. I found no obvious problem. I have also checked the content of the first transmit buffer descriptor (after the first package has been seemingly successfully sent). Everything looks ok to me. I have put the dump below.
I can exclude hardware issues, because the old firmware works. It is very hard to understand what the old firmware does differently, since its structure is entirely different from the MCUXpresso SDK.
I don't understand what I am doing wrong. I know that this particular version of the MCU is not well supported any more, but I fail to see why this should not work. Can someone point me into the right direction what else to try or how to debug this further?
Cheers and many thanks in advance,
Martin
Here is the register/buffer dump:
==== ETHERNET MAC MEMORY MAP
EIR: 0
EIMR: 0
RDAR: 0
TDAR: 1000000
ECR: f0000002
MMFR: 6006786d
MSCR: 26
MIBC: c0000000
RCR: 5ee4104
TCR: 4
PALR: d4bed945
PAUR: 22608808
OPD: 10000
IAUR: 0
IALR: 0
GAUR: 0
GALR: 0
TFWR: 100
RDSR: 1fff0170
TDSR: 1fff01a0
MRBR: 5f0
RSFL: 0
RSEM: 0
RAEM: 4
RAFL: 4
TSEM: 0
TAEM: 4
TAFL: 8
TIPG: c
FTRL: 7ff
TACC: 0
RACC: 0
==== BUFFER DESCRIPTOR:
control: 8c00
length: 1000
==== BUFFER CONTENT:
0000: ffff ffff ffff d4be
0008: d945 2260 03da 0001
0016: 0203 0405 0607 0809
0024: 0a0b 0c0d 0e0f 1011
0032: 1213 1415 1617 1819
(continues like this for all 1000 bytes in the buffer)
This output has been produced using the following code (placed right below the call to ENET_SendFrame()):
ENET_Type *b = EXAMPLE_ENET;
PRINTF("==== ETHERNET MAC MEMORY MAP\n\r");
PRINTF("EIR: %x\n\r", b->EIR);
PRINTF("EIMR: %x\n\r", b->EIMR);
PRINTF("RDAR: %x\n\r", b->RDAR);
PRINTF("TDAR: %x\n\r", b->TDAR);
PRINTF("ECR: %x\n\r", b->ECR);
PRINTF("MMFR: %x\n\r", b->MMFR);
PRINTF("MSCR: %x\n\r", b->MSCR);
PRINTF("MIBC: %x\n\r", b->MIBC);
PRINTF("RCR: %x\n\r", b->RCR);
PRINTF("TCR: %x\n\r", b->TCR);
PRINTF("PALR: %x\n\r", b->PALR);
PRINTF("PAUR: %x\n\r", b->PAUR);
PRINTF("OPD: %x\n\r", b->OPD);
PRINTF("IAUR: %x\n\r", b->IAUR);
PRINTF("IALR: %x\n\r", b->IALR);
PRINTF("GAUR: %x\n\r", b->GAUR);
PRINTF("GALR: %x\n\r", b->GALR);
PRINTF("TFWR: %x\n\r", b->TFWR);
PRINTF("RDSR: %x\n\r", b->RDSR);
PRINTF("TDSR: %x\n\r", b->TDSR);
PRINTF("MRBR: %x\n\r", b->MRBR);
PRINTF("RSFL: %x\n\r", b->RSFL);
PRINTF("RSEM: %x\n\r", b->RSEM);
PRINTF("RAEM: %x\n\r", b->RAEM);
PRINTF("RAFL: %x\n\r", b->RAFL);
PRINTF("TSEM: %x\n\r", b->TSEM);
PRINTF("TAEM: %x\n\r", b->TAEM);
PRINTF("TAFL: %x\n\r", b->TAFL);
PRINTF("TIPG: %x\n\r", b->TIPG);
PRINTF("FTRL: %x\n\r", b->FTRL);
PRINTF("TACC: %x\n\r", b->TACC);
PRINTF("RACC: %x\n\r", b->RACC);
// -> TX buffer descriptor
void *transmitBufferDescriptorRingStart = (void *) b->TDSR;
typedef struct
{
uint16_t length; /*!< Buffer descriptor data length. */
uint16_t control; /*!< Buffer descriptor control and status. */
uint8_t *buffer; /*!< Data buffer pointer. */
} bd_struct;
bd_struct *desc = (bd_struct *) transmitBufferDescriptorRingStart;
PRINTF("==== BUFFER DESCRIPTOR:\n\r");
PRINTF("control: %04x\n\r", desc->control);
PRINTF("length: %d\n\r", desc->length);
PRINTF("==== BUFFER CONTENT:\n\r");
void *buffer = desc->buffer;
for (uint16_t i = 0; i < desc->length; ++i) {
uint8_t p = ((uint8_t *) buffer)[i];
if (i == 0) {
PRINTF("%04d: ", i);
} else if (i % 8 == 0) {
PRINTF("\n\r%04d: ", i);
} else if (i % 2 == 0) {
PRINTF(" ");
}
PRINTF("%02x", p);
}
PRINTF("\n\r");
PRINTF("======================================\n\r");