I wished you'd have your proper code ready yet...
I ran into a strange problem and wonder if anybody has experienced similar problems:
I have a SNTP server running which queries the time from my laptop every 5 seconds or so. Everything seems to work fine but sometimes the MAC does not send the outgoing UDP packages anymore. The lwip trace is
Code: Select all
sntp_send_request: Sending request to server
udp_send
pbuf_header: old p new p (536910916)
udp_send: added header in given pbuf p
udp_send: sending datagram of length 56
udp_send: UDP packet length 56
udp_send: UDP checksum 0x 0
udp_send: ip_output_if (,,,,IP_PROTO_UDP,)
pbuf_header: old p new p (536910908)
ip_output_if: ms0
IP header:
+-------------------------------+
| 4 | 5 | 0x 0 | 76 | (v, hl, tos, len)
+-------------------------------+
| 68 |000| 0 | (id, flags, offset)
+-------------------------------+
| 255 | 17 | 0x 0 | (ttl, proto, chksum)
+-------------------------------+
| 172 | 16 | 0 | 21 | (src)
+-------------------------------+
| 172 | 16 | 0 | 168 | (dest)
+-------------------------------+
netif->output()pbuf_header: old p new p (536910888)
etharp_send_ip: sending packet p
pbuf_free(p)
pbuf_free: deallocating p
And looks the same as when the packages are still sent, also low_level_output in lwipthread.c is still called and executed successfully. Now, it continues to not work until I ping the board - at which point things magically start to work again!
I guess I'll have to dig through the MAC registers and all the ugly ST source code
EDIT:When the execution is stalled the ETH_DMASR has the TS, TBUS, ETS set. So it might be some kind of DMA problem.
EDIT2:Basically what happens is that the current Tx buffer doesnt get cleared and therefore always does a
if ((mdp->Status & ETH_DMATxDesc_OWN) != (uint32_t)RESET) return RDY_TIMEOUT; in max_lld_get_transmit_descriptor.
I am a real newbie to this ethernet mac stuff, so I don't understand the whole code. First, where does DMATxDescToSet get updated to the next current descriptor? I tried the following code in mac_lld_release_transmit_descriptor
Code: Select all
/* Selects the next DMA Tx descriptor list for next buffer read */
DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMAPTPTxDescToSet->Buffer2NextDescAddr);
if(DMAPTPTxDescToSet->Status != 0){
DMAPTPTxDescToSet = (ETH_DMADESCTypeDef*) (DMAPTPTxDescToSet->Status);
}
else{
DMAPTPTxDescToSet++;
}
but this makes to driver fail completely.
Also there is the following code in mac_lld_release_transmit_descriptor
Code: Select all
/* Clear unavailable flag & resume transmission */
//TODO: the following check for DMASR_TBUS doesn't work
//if ((ETH->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) {
ETH->DMASR = ETH_DMASR_TBUS;
ETH->DMATPDR = 0;
//}
The todo says it all - but from reading the parts of the documentation it should work with the if. I cannot figure out why the driver stops working with the enabled if branch. I do not understand why I need to do a ETH->DMASR = ETH_DMASR_TBUS; though.
Hmm probably time to go to bed...