stm32-community / stm32-enc28j60

An ENC28J60 (cheap ethernet module) library for STM32 projects
62 stars 26 forks source link

Enhancements and Fixes for NTP Management with STM32 and ENC28J60 #11

Closed DtNeo closed 6 months ago

DtNeo commented 6 months ago

Context

In the development of applications using STM32 with the ENC28J60 module for network communication, I've integrated functions to manage time synchronization via NTP. This includes sending NTP requests and processing responses to obtain a coherent timestamp.

Resolved Issues and Improvements

  1. Integration of client_ntp_process_answer : I placed the client_ntp_process_answer functions directly in packetloop_icmp_tcp. This integration allows for better management of NTP packets directly upon their reception.

    
    #ifdef NTP_client
    // TODO - does this work?
    // If NTP response, drop out to have it processed elsewhere
    if (buf[IP_PROTO_P] == IP_PROTO_UDP_V && buf[UDP_SRC_PORT_H_P] == 0 && buf[UDP_SRC_PORT_L_P] == 0x7b) {
      if (buf[UDP_LEN_H_P]!=0 || buf[UDP_LEN_L_P]!=56 || buf[UDP_SRC_PORT_L_P]!=0x7b){
        // not ntp
        return(0);
      }
      NTPanswer();
      return (UDP_DATA_P);
    }
    #endif // NTP_client
  2. NTP Timestamp Correction :

    • The initial NTP timestamp calculation provides the time in seconds since 1900. To obtain a coherent UNIX timestamp (seconds since 1970), it is necessary to subtract the seconds elapsed between 1900 and 1970.
    • Formula used: time = ((uint32_t)packet[82] << 24) | ((uint32_t)packet[83] << 16) | ((uint32_t)packet[84] << 8) | (uint32_t)packet[85]; This extraction is performed correctly and delivers the expected results, in accordance with NTP protocol standards.
void NTPanswer() {
    uint32_t time;
    // Extraction du timestamp NTP (les secondes depuis 1900)
    time = ((uint32_t)packet[82] << 24) | ((uint32_t)packet[83] << 16) | ((uint32_t)packet[84] << 8) | (uint32_t)packet[85];
    // Convertir le timestamp NTP en timestamp UNIX (les secondes depuis 1970) en soustrayant les secondes entre 1900 et 1970.
    // Note: Ceci ne prend en compte que la partie secondes du timestamp NTP et ignore les fractions de seconde.
    if (time > 2208988800UL) {
        time -= 2208988800UL;
    } else {
        // Gérer le cas où le timestamp NTP est avant l'époque UNIX (très improbable, mais pour la robustesse du code)
        time = 0;
    }
    char timeStr[20]; // Augmenté la taille pour éviter tout dépassement potentiel
    sprintf(timeStr, "%lu", time);
    udpLog2("NTP", timeStr);
}
  1. Function client_ntp_request :
    • No modification was necessary for the client_ntp_request function. It works as intended to send NTP requests to the specified server.

Acknowledgments

I would like to thank everyone who has contributed to the stm32-libs/stm32-enc28j60 project. The work provided is extremely useful and serves as a solid foundation for expanding network functionalities on STM32 devices.

Next Steps

Thanks again for all

xaionaro commented 6 months ago

This is amazing! It it always pleasant to see that a code lives somewhere :)

Please, feel free to make a PR if you feel that something could be improved right here in this repository. And thanks for sharing the issues and the improvements!

... Also I think it is time to create a LICENSE file (it is GPLv2, BTW) and mention all the contributors there...