{"id":365,"date":"2023-07-04T14:35:43","date_gmt":"2023-07-04T13:35:43","guid":{"rendered":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/?p=365"},"modified":"2023-11-21T08:43:03","modified_gmt":"2023-11-21T07:43:03","slug":"365","status":"publish","type":"post","link":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/?p=365","title":{"rendered":"Ethernet sur nucleo-F429ZI"},"content":{"rendered":"<h1>Mise en oeuvre sur un microcontr\u00f4leur STM32F429ZI (Nucleo-F429ZI) en UDP<\/h1>\n<p>Test\u00e9 avec STM32CubeIDE 1.12.1<\/p>\n<h2>Objectif de ce tutoriel :<\/h2>\n<p>Etablir une communication ethernet entre un PC et une carte Nucleo-F429ZI en utilisant le protocole UDP.<br \/>\nUne fois la configuration hardware r\u00e9alis\u00e9e, nous aborderons deux cas d'utilisations :<\/p>\n<ul>\n<li>1 La carte Nucleo-F429ZI dans le r\u00f4le de serveur UDP sur lequel vient se connecter le PC avec l'outil Netcat<\/li>\n<li>2 La carte Nucleo-F429ZI dans le r\u00f4le de client UDP qui vient se connecter au serveur Netcat d\u00e9marr\u00e9 sur le PC pr\u00e9alablement.<\/li>\n<\/ul>\n<h2>Step 0 : configuration de l'Ethernet histoire de communiquer avec le PC et Netcat<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/wp-content\/uploads\/2023\/07\/ethernet.png\" alt=\"\" \/><\/p>\n<h2>Step 1  : configuration des horloges du STM32<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/wp-content\/uploads\/2023\/07\/clock_config.png\" alt=\"\" \/><\/p>\n<h2>Step 1  : configuration du driver LWIP<\/h2>\n<p>Le sch\u00e9ma \u00e9lectronique de la nucleo-F429ZI nous renseigne sur le driver hardware (LAN8742), qu'on choisit donc pour notre projet.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/wp-content\/uploads\/2023\/07\/LWIP_config_platform_settings.png\" alt=\"\" \/><\/p>\n<p>Le checksum est calcul\u00e9 par le hardware :<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/wp-content\/uploads\/2023\/07\/Lwip_checksum_hardware.png\" alt=\"\" \/><\/p>\n<p>On d\u00e9sactive le DHCP pour fixer une adresse IPV4 de notre choix. Ici 192.168.0.51<br \/>\nGateway 192.168.0.50 (ce sera l'adresse IP du PC de test).<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/wp-content\/uploads\/2023\/07\/Lwip_config_general_settings.png\" alt=\"\" \/><\/p>\n<p>On alloue 10 KBytes pour la m\u00e9moire.<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/wp-content\/uploads\/2023\/07\/Lwip_Key_options.png\" alt=\"\" \/><\/p>\n<p>et on n'oublie pas d'activer les &quot;interruptions&quot; ethernet dans la section NVIC de System core dans le Pinout and configuration (IOC).<\/p>\n<h1>Serveur UDP<\/h1>\n<p>Dans cette partie nous allons traiter de la mise en oeuvre du code en C pour r\u00e9aliser un serveur UDP sur la carte Nucleo-F429ZI. Il aura l'adresse IP 192.168.0.51 et le PC : 192.168.0.50<\/p>\n<h2>Serveur-Step 0  : que faire dans le main ?<\/h2>\n<p>On rajoute la biblioth\u00e8que udp.h ains<\/p>\n<pre><code class=\"language-c\">#include &quot;lwip\/udp.h&quot;\n\nvoid udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);\n\nvoid udpServer_init(void);\nextern struct netif gnetif; \/\/ d\u00e9j\u00e0 d\u00e9fini ailleurs mais on en a besoin donc on le met en extern\nstruct udp_pcb *upcb;\n\nint main(void)\n{\n    HAL_Init();\n    SystemClock_Config();\n    MX_GPIO_Init();\n    MX_USART3_UART_Init();\n    MX_LWIP_Init();\n    udpServer_init();\n    while (1)\n    {\n        ethernetif_input(&amp;gnetif);\n        sys_check_timeouts();\n    }\n    } \/\/fin main\n<\/code><\/pre>\n<h2>Serveur-Step 1  : que faire ensuite ?<\/h2>\n<p>On rajoute les fonctions udbServer_init et udp_receive_callback<\/p>\n<pre><code class=\"language-c\">\nvoid udpServer_init(void)\n{\n    \/\/ UDP Control Block structure\n   struct udp_pcb *upcb;\n   err_t err;\n\n   \/* 1. Create a new UDP control block  *\/\n   upcb = udp_new();\n\n   \/* 2. Bind the upcb to the local port *\/\n   ip_addr_t myIPADDR;\n   IP_ADDR4(&amp;myIPADDR, 192, 168, 0, 51);\n\n   err = udp_bind(upcb, &amp;myIPADDR, 7000);  \/\/ 7 is the server UDP port\n\n   \/* 3. Set a receive callback for the upcb *\/\n   if(err == ERR_OK)\n   {\n       udp_recv(upcb, udp_receive_callback, NULL);\n   }\n   else\n   {\n       udp_remove(upcb);\n   }\n}\n\n\/\/cette fonction sera ex\u00e9cut\u00e9e lorsqu&#039;un paquet de donn\u00e9es UDP arrivera sur la nucleo-F429ZI\n\/\/Elle renvoie le contenu du paquet et un petit Hello xxx From UDP SERVER\nvoid udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)\n{\n    struct pbuf *txBuf;\n    \/* Get the IP of the Client *\/\n    char *remoteIP = ipaddr_ntoa(addr);\n    char buf[100];\n\n    int len = sprintf (buf,&quot;Hello %s From UDP SERVER\\n&quot;, (char*)p-&gt;payload);\n    \/* allocate pbuf from RAM*\/\n    txBuf = pbuf_alloc(PBUF_TRANSPORT,len, PBUF_RAM);\n    \/* copy the data into the buffer  *\/\n    pbuf_take(txBuf, buf, len);\n    \/* Connect to the remote client *\/\n    udp_connect(upcb, addr, port);\n    \/* Send a Reply to the Client *\/\n    udp_send(upcb, txBuf);\n    \/* free the UDP connection, so we can accept new clients *\/\n    udp_disconnect(upcb);\n    \/* Free the p_tx buffer *\/\n    pbuf_free(txBuf);\n    \/* Free the p buffer *\/\n    pbuf_free(p);\n}\n<\/code><\/pre>\n<h2>Serveur-Step 2  : c'est bien tout \u00e7a mais comment je teste ?<\/h2>\n<p>Pour les tests, la bonne mani\u00e8re est :<br \/>\n1 - de regarder si la carte r\u00e9pond \u00e0 un ping<br \/>\n2 - de tester si le serveur r\u00e9pond<\/p>\n<pre><code class=\"language-zsh\">ping 192.168.0.51<\/code><\/pre>\n<p>Si la r\u00e9ponse est du genre :<\/p>\n<pre><code class=\"language-zsh\">\u279c \u00a0ozone ping 192.168.0.51  \nPING 192.168.0.51 (192.168.0.51) 56(84) bytes of data.  \n64 bytes from 192.168.0.51: icmp_seq=1 ttl=255 time=0.580 ms  \n64 bytes from 192.168.0.51: icmp_seq=2 ttl=255 time=0.686 ms  \n^C  \n--- 192.168.0.51 ping statistics ---  \n2 packets transmitted, 2 received, 0% packet loss, time 1006ms  \nrtt min\/avg\/max\/mdev = 0.580\/0.633\/0.686\/0.053 ms<\/code><\/pre>\n<p>C'est que \u00e7a fonctionne, on peut passer au test du serveur UDP.<\/p>\n<p>Pour ce faire, on utilise l'outils Netcat (nc), cela donne :<\/p>\n<pre><code class=\"language-zsh\">\u279c \u00a0ozone nc -u 192.168.0.51 7000<\/code><\/pre>\n<p>-u : UDP<br \/>\n192.168.0.51 adresse du PC<br \/>\n7000 port utilis\u00e9 dans notre cas.<\/p>\n<p>Rien ne se passe, c'est normal, il n'y a pas de donn\u00e9es \u00e9chang\u00e9es pour le moment entre le PC et la nucleo.<\/p>\n<p>On tape Alice dans le terminal et si on voit cela : <\/p>\n<pre><code class=\"language-zsh\">\u279c \u00a0ozone nc -u 192.168.0.51 7000  \nAlice  \nHello Alice  \nFrom UDP SERVER<\/code><\/pre>\n<p>C'est gagn\u00e9 !<\/p>\n<h1>Client UDP<\/h1>\n<p>Dans cette partie nous allons traiter de la mise en oeuvre du code en C pour r\u00e9aliser un client UDP sur la carte Nucleo-F429ZI. Il aura l'adresse IP 192.168.0.51 et le PC qui sera un serveur aura l'adresse : 192.168.0.50<\/p>\n<h2>Client-Step 0  : que faire dans le main ?<\/h2>\n<p>On rajoute la biblioth\u00e8que udp.h ains<\/p>\n<pre><code class=\"language-c\">#include &quot;lwip\/udp.h&quot;\n\nvoid udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);\n\nvoid udpClient_connect(void);\nstatic void udpClient_send(void);\n\nextern struct netif gnetif; \/\/ d\u00e9j\u00e0 d\u00e9fini ailleurs mais on en a besoin donc on le met en extern\nstruct udp_pcb *upcb;\n\nint main(void)\n{\n    HAL_Init();\n    SystemClock_Config();\n    MX_GPIO_Init();\n    MX_USART3_UART_Init();\n    MX_LWIP_Init();\n    udpClient_connect();\n    while (1)\n    {\n        ethernetif_input(&amp;gnetif);\n        sys_check_timeouts();\n    }\n    } \/\/fin main\n<\/code><\/pre>\n<h2>Client-Step 1  : que faire ensuite ?<\/h2>\n<p>On rajoute les fonctions udpClient_connect et udp_receive_callback<\/p>\n<pre><code class=\"language-c\">\nvoid udpClient_connect(void)\n{\n    err_t err;\n    \/* 1. Create a new UDP control block  *\/\n    upcb = udp_new();\n\n    \/* Bind the block to module&#039;s IP and port *\/\n    ip_addr_t myIPaddr;\n    IP_ADDR4(&amp;myIPaddr, 192, 168, 0, 51);\n    udp_bind(upcb, &amp;myIPaddr, 7000);\n\n    \/* configure destination IP address and port *\/\n    ip_addr_t DestIPaddr;\n    IP_ADDR4(&amp;DestIPaddr, 192, 168, 0, 50);\n    err= udp_connect(upcb, &amp;DestIPaddr, 7000);\n\n    if (err == ERR_OK)\n    {\n        \/* 2. Send message to server *\/\n        udpClient_send ();\n        \/* 3. Set a receive callback for the upcb *\/\n        udp_recv(upcb, udp_receive_callback, NULL);\n    }\n}\n\nstatic void udpClient_send(void)\n{\n  struct pbuf *txBuf;\n  char data[100];\n\n  int len = sprintf(data, &quot;sending UDP client message\\r\\n&quot;);\n\n  \/* allocate pbuf from pool*\/\n  txBuf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);\n\n  if (txBuf != NULL)\n  {\n    \/* copy data to pbuf *\/\n    pbuf_take(txBuf, data, len);\n    \/* send udp data *\/\n    udp_send(upcb, txBuf);\n    \/* free pbuf *\/\n    pbuf_free(txBuf);\n  }\n}\n\n\/\/cette fonction sera ex\u00e9cut\u00e9e lorsqu&#039;un paquet de donn\u00e9es UDP arrivera sur la nucleo-F429ZI\n\/\/Elle renvoie le contenu du paquet et un petit Hello xxx From UDP SERVER\nvoid udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)\n{\n    struct pbuf *txBuf;\n    \/* Get the IP of the Client *\/\n    char *remoteIP = ipaddr_ntoa(addr);\n    char buf[100];\n\n    int len = sprintf (buf,&quot;Hello %s From Nucleo-F429ZI UDP client\\n&quot;, (char*)p-&gt;payload);\n    \/* allocate pbuf from RAM*\/\n    txBuf = pbuf_alloc(PBUF_TRANSPORT,len, PBUF_RAM);\n    \/* copy the data into the buffer  *\/\n    pbuf_take(txBuf, buf, len);\n    \/* Connect to the remote client *\/\n    udp_connect(upcb, addr, port);\n    \/* Send a Reply to the Client *\/\n    udp_send(upcb, txBuf);\n    \/* free the UDP connection, so we can accept new clients *\/\n    udp_disconnect(upcb);\n    \/* Free the p_tx buffer *\/\n    pbuf_free(txBuf);\n    \/* Free the p buffer *\/\n    pbuf_free(p);\n}\n<\/code><\/pre>\n<h2>Client-Step 2  : c'est bien tout \u00e7a mais comment je teste ?<\/h2>\n<p>Pour les tests, la bonne mani\u00e8re est :<br \/>\n1 - de regarder si la carte r\u00e9pond \u00e0 un ping<br \/>\n2 - de tester si le serveur r\u00e9pond<\/p>\n<pre><code class=\"language-zsh\">ping 192.168.0.51<\/code><\/pre>\n<p>Si la r\u00e9ponse est du genre :<\/p>\n<pre><code class=\"language-zsh\">\u279c \u00a0ozone ping 192.168.0.51  \nPING 192.168.0.51 (192.168.0.51) 56(84) bytes of data.  \n64 bytes from 192.168.0.51: icmp_seq=1 ttl=255 time=0.580 ms  \n64 bytes from 192.168.0.51: icmp_seq=2 ttl=255 time=0.686 ms  \n^C  \n--- 192.168.0.51 ping statistics ---  \n2 packets transmitted, 2 received, 0% packet loss, time 1006ms  \nrtt min\/avg\/max\/mdev = 0.580\/0.633\/0.686\/0.053 ms<\/code><\/pre>\n<p>C'est que \u00e7a fonctionne, on peut passer au test de notre nucleo-F429ZI.<\/p>\n<p>Ensuite on va lance le serveur UDP sur le PC<br \/>\nPour ce faire, on utilise l'outils Netcat (nc), cela donne :<\/p>\n<pre><code class=\"language-zsh\">\u279c \u00a0ozone nc -ul 7000<\/code><\/pre>\n<p>-u : UDP<br \/>\n-l : listen (le PC est un serveur en \u00e9coute sur le port 7000)<br \/>\n7000 port utilis\u00e9 dans notre cas.<\/p>\n<p>On reset la nucleo<br \/>\nOn tape Alice dans le terminal et si on voit cela : <\/p>\n<pre><code class=\"language-zsh\">\u279c \u00a0ozone nc -ul 7000  \nsending UDP client message<\/code><\/pre>\n<p>C'est gagn\u00e9 !<\/p>\n<p>Et maintenant si c'est le PC qui envoie des donn\u00e9es, cela donne :<\/p>\n<pre><code class=\"language-zsh\">\u279c \u00a0ozone nc -ul 7000  \nsending UDP client message  \nBob  \nHello Bob  \nFrom Nucleo-F429ZI UDP client<\/code><\/pre>\n<p>That's all folks!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mise en oeuvre sur un microcontr\u00f4leur STM32F429ZI (Nucleo-F429ZI) en UDP Test\u00e9 avec STM32CubeIDE 1.12.1 Objectif de ce tutoriel : Etablir une communication ethernet entre un PC et une carte Nucleo-F429ZI en utilisant le protocole UDP. Une fois la configuration hardware r\u00e9alis\u00e9e, nous aborderons deux cas d&rsquo;utilisations : 1 La carte Nucleo-F429ZI dans le r\u00f4le de &hellip; <a href=\"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/?p=365\" class=\"more-link\">Continuer la lecture de <span class=\"screen-reader-text\">Ethernet sur nucleo-F429ZI<\/span>  <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-365","post","type-post","status-publish","format-standard","hentry","category-stm32"],"_links":{"self":[{"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=\/wp\/v2\/posts\/365","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=365"}],"version-history":[{"count":8,"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=\/wp\/v2\/posts\/365\/revisions"}],"predecessor-version":[{"id":388,"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=\/wp\/v2\/posts\/365\/revisions\/388"}],"wp:attachment":[{"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.spacelabcachan.universite-paris-saclay.fr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}