Analyse d'une fuite mémoire sur ESP32

1 min - Publié le

Client


Client : Swatch Group

Service : Support applicatif

Site web : [Swatch Group]

Problématique


La connexion en OPC UA (OPC Unified Architecture) sur le système de production était impossible après que plusieurs clients OPC UA se sont connectés sur ce dernier. De ce fait, il fallait redémarrer le système de production manuellement pour regagner l'accès par OPC UA et ainsi accéder aux données de production.

Analyse


Suite à quatre connexions consécutives sur le serveur OPC UA de l'ESP32, ce dernier se coupe, rendant le service indisponible. Les connexions peuvent provenir de différents clients et/ou de différentes machines, et la coupure du service intervient de la même manière. Un redémarrage du système est nécessaire pour permettre une nouvelle connexion.

Solution proposée


La coupure du service OPC UA est la conséquence de la fermeture par FreeRTOS de la tâche « opcua_task » suite à un manque de mémoire de données (DRAM). Premièrement, à chaque fois qu’une session est créée la base de temps utilisée n’est pas la bonne et cette dernière n’expire donc jamais.

Deuxièmement, dans le cas d’une coupure brutale du réseau (arrachage du câble réseau ou fermeture du client OPC UA sans les signaux de terminaison de connexion TCP), la session TCP est fermée partiellement et continue à utiliser des ressources mémoire. Une cause aggravante est le manque de mémoire de données disponible car le paramétrage du système ESP32 n’est pas optimisé.

Mise en œuvre


  • Corriger les bases de temps lors de la création des sessions OPC UA.
  • Activer l’option TCP SO_LINGER dans le fichier sdkconfig pour terminer et libérer la mémoire. dès qu’une demande de fermeture de session côté serveur est demandée. CONFIG_LWIP_SO_LINGER=y
  • Optimiser l’empreinte mémoire en configurant les options système de l’ESP32. Article Espressif sur l'optimisation de la mémoire de données

- Optimisations dans le fichier sdkconfig :

CONFIG_FREERTOS_UNICORE=y
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
CONFIG_ESP32_ALLOW_RTC_FAST_MEM_AS_HEAP=y

À noter qu’une configuration des clients OPC UA avec des timeouts faibles permet de libérer plus rapidement les sessions dans le cas d’une coupure brutale du réseau (arrachage du câble réseau ou fermeture du client OPC UA sans les signaux de terminaison de connexion TCP). La configuration suivante peut être adoptée à titre indicatif :

Configuration clients OPC UA :
  • Timeout Secure channel: 10 minutes
  • Timeout Session: 1 minute

Résultats


Après test sur une maquette simulant des dizaines de cycles de connexion et déconnexion et plusieurs connexions en simultané, aucun problème d'accès n'a été rencontré. De même, après traçage de la mémoire de données disponible, cette dernière libère bien l'intégralité des ressources réservées à chaque clôture de connexion.

Conclusion


Il est important de maîtriser le système cible lorsqu'on effectue une intégration d'applications. Dans notre cas, la fuite de mémoire n'était ni due à l'application ni au système cible. En fait, c'est la connexion/déconnexion fréquente de l'utilisateur qui n'était pas prévue. Les piles IP comme LWIP ne libèrent pas instantanément les ressources à la fermeture d'une session TCP, il est donc nécessaire de s'adapter en libérant plus rapidement les ressources pour accepter de nouvelles connexions.