LWIP + FreeRTOS a UDP příjem a odeslání dat

C,C++,C#

Moderátori: psichac, Moderátori

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa jirka.jirka. » 22 Nov 2023, 16:13

Ahoj přátelé,

už delší dobu zápasím s UDP na mcu. Uniká mi něco a ne a ne na to přijít.

Kód: Vybrať všetko

// Define a FreeRTOS queue handle
QueueHandle_t SendData_queue;

static struct netconn *conn;
static struct netbuf *buf;
static struct pbuf *txBuf;

static ip_addr_t *addr;
static unsigned short port;

char receiveBuffer[MAX_BUFFER_SIZE];

static void vUDPnetconnTask(void *pvParameters) {
    err_t err, recv_err;


    /* Create a new connection identifier */
    conn = netconn_new(NETCONN_UDP);

    Send_FEKU_Data sendData;

    if (conn != NULL) {
        /* Bind connection to the port 7 */
        err = netconn_bind(conn, IP_ADDR_ANY, 50055);

        if (err == ERR_OK) {
            /* The while loop will run everytime this Task is executed */
            while (1) {
                /* Receive the data from the connection */
                recv_err = netconn_recv(conn, &buf);
                if (recv_err == ERR_OK) { // if the data is received

                    addr = netbuf_fromaddr(buf);  // get the address of the client
                    port = netbuf_fromport(buf);  // get the Port of the client
                    uint16_t len = buf->p->len > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : buf->p->len;
                    void *data;

                    netbuf_data(buf, &data, &len);
                    memcpy(receiveBuffer, data, len);

                    printf("Received data: ");
                    for (uint8_t i = 0; i < len; i++) {
                        print("%02x ", receiveBuffer[i]);
                    }

                    // Here work with receive data
                    
                    netbuf_delete(buf);  // delete the netbuf
                }
                // Wait for a message on the queue
                BaseType_t queueStatus;

                queueStatus = xQueueReceive(SendData_queue, &sendData, portMAX_DELAY);
                if (queueStatus == pdPASS) {
                    // Process the received data and send the response

                    txBuf = pbuf_alloc(PBUF_TRANSPORT, sendData.Len + 2, PBUF_RAM);

                    if (txBuf != NULL) {

                        uint8_t sendArray[100];
                        sendArray[0] = sendData.ID;
                        sendArray[1] = sendData.Len;
                        sendArray[2] = sendData.Data[0];
                        sendArray[3] = sendData.Data[1];
                        sendArray[4] = sendData.Data[2];
                        sendArray[5] = sendData.Data[3];

                        pbuf_take(txBuf, sendArray, sendData.Len + 2); 
                        // In a real application, you might need to get the destination address and port
                        // from the message or another source
                        buf->p = txBuf;
                        netconn_connect(conn, addr, port);  // connect to the destination address and port
                        netconn_send(conn, buf);
                        netbuf_delete(buf);  // delete the netbuf
                        pbuf_free(txBuf);   // clear the pbuf
                    }
                }
            }
        } else {
            netconn_delete(conn);
        }
    }
}
No a co to má dělat.

Odešlu data z PC do mcu, kde je zpracuji. Následně se v jiném tasku vygenerují odchozí data. Na to mám frontu SendData_queue. Jakmile se v ní objeví data, tak se mají odeslat po UDP zpět do PC.

Data se odešlou, ale dostávám chybu:
FAIL-A: "pbuf_free: p->ref > 0" on 752 in ERA-FW/MP-ETH-STM32-LwIP/MP/src/core/pbuf.c

Kde to vidím na něco prohnilého zde:

Kód: Vybrať všetko

pbuf_take(txBuf, sendArray, sendData.Len + 2); 
// In a real application, you might need to get the destination address and port
// from the message or another source
buf->p = txBuf;
netconn_connect(conn, addr, port);  // connect to the destination address and port
netconn_send(conn, buf);
netbuf_delete(buf);  // delete the netbuf
pbuf_free(txBuf);   // clear the pbuf
Zkoušel jsem debug, ale moc moudrý z toho nejsem. Nevidíte tam někdo hned na první pohled chybu?
0

stefanSK
Pokročilý člen
Pokročilý člen
Príspevky: 752
Dátum registrácie: 24 Jún 2010, 00:00
Bydlisko: Trnava
Vek: 68

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa stefanSK » 22 Nov 2023, 16:41

Nepoznám túto komunikáciu, ale ma napadá otázka:
táto definícia premennej addr je správna?
static ip_addr_t *addr;

naozaj to má to byť pointer?
0
S.K.

Používateľov profilový obrázok
YellowJacket
Pokročilý člen
Pokročilý člen
Príspevky: 503
Dátum registrácie: 05 Feb 2012, 11:58
Bydlisko: Hrinova
Vek: 33

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa YellowJacket » 22 Nov 2023, 18:01

@stefanSK: podla dokumentacie to vyzera na spravnu definiciu.

@jirka.jirka: taktiez len skusim tip, mozno odveci, ale skus prehodit riadky:

Kód: Vybrať všetko

netbuf_delete(buf);
pbuf_free(txBuf);
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa jirka.jirka. » 22 Nov 2023, 18:03

YellowJacket: Myslím jsem to zkoušel, ale nepomohlo, ale radši zítra ještě ověřím.
netbuf_delete(buf);
pbuf_free(txBuf);
0

stefanSK
Pokročilý člen
Pokročilý člen
Príspevky: 752
Dátum registrácie: 24 Jún 2010, 00:00
Bydlisko: Trnava
Vek: 68

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa stefanSK » 22 Nov 2023, 20:56

nedá mi pokoj toto:
addr = netbuf_fromaddr(buf); // get the address of the client
port = netbuf_fromport(buf); // get the Port of the client

raz to vráti z buf hodnotu portu - číslo, v druhom prípade to vráti smerník na "address of the client".
Veď v ďalšom sa s buf manipuluje a takže sa prvok v poli buf prepíše v tých miestach, kde
ukazuje pointer adr. Neskôr sa hodnoty adr a port použijú:
netconn_connect(conn, addr, port); // connect to the destination address and port
0
S.K.

pocitujlasku
Ultimate člen
Ultimate člen
Príspevky: 6205
Dátum registrácie: 20 Júl 2007, 00:00
Vek: 41

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa pocitujlasku » 22 Nov 2023, 21:57

Mozno blbost, ale skus dat nejaky delay medzi:

Kód: Vybrať všetko

netconn_send(conn, buf);
TU DAJ DELAY
netbuf_delete(buf);  // delete the netbuf
pbuf_free(txBuf);   // clear the pbuf
Sice nerobim velmi s C, skor z lenivosti arduino, ale napr. v C# sa mi to casto stavalo, ze som chcel vymazat buffer hned po odoslani dat, bez toho, aby som si overil, ze uz odisli. A vtedy to slo do chyby. A pri debugovani nebol problem, lebo sa stihli odoslat kym som skocil na dalsi krok.
0
Jedním z největších projevů nedůvěry v Boha je hromosvod na kostele.

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa jirka.jirka. » 23 Nov 2023, 08:06

Provedl jsem update, ale stejně tam ta chyba je... :vom:

Kód: Vybrať všetko

                        buf->p = txBuf;
                        netconn_connect(conn, addr, port);  // pripojit se k adrese a portu
                        err_t send_err = netconn_send(conn, buf);

                        if (send_err == ERR_OK) {
                            // netconn_send successful, takze free pbuf
                            if (txBuf->ref == 1) {
                                // Pokud je reference 1, je to posledni reference
                                pbuf_free(txBuf);
                            } else {
                                // Pokud je reference >1 snizit bez uvolneni
                                pbuf_ref(txBuf);
                            }
                        } else {
                            // Chyba
                            // Neuvolňujte zde pbuf, abyste se vyhnuli chybě "pbuf_free: p->ref > 0".
                            ErrPrint("Failed to send data over UDP\n");
                            pbuf_free(txBuf);
                        }

                        netbuf_delete(buf);  // delete the netbuf
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa jirka.jirka. » 23 Nov 2023, 10:11

Byl to boj, ale už to šlape. Wireshark vidí data, všechno bez chybky. Jenom jsem to trošku přeoral. Možná se někomu bude hodit....

Rozděleno na dva tasky:
1. Task

Kód: Vybrať všetko

static void receiveTask(void *pvParameters) {
       // Create a new UDP PCB structure
       pcb = udp_new();

       // Bind the PCB to a specific IP address and port
       udp_bind(pcb, IP_ADDR_ANY, UDP_PORT);

       // Set up the receive callback function
       udp_recv(pcb, udpReceiveCallback, NULL);

       while (1) {
           vTaskDelay(10);
       }
}
2. Task

Kód: Vybrať všetko

static void sendTask(void *pvParameters) {
    Send_FEKU_Data sendData;

    while (1) {
        // Wait for data to be sent
        BaseType_t queueStatus = xQueueReceive(SendData_queue, &sendData, portMAX_DELAY);

        if (queueStatus == pdPASS) {

            char ipString[16]; // Sufficient for IPv4 addresses
            ipaddr_ntoa_r(&addr_cli, ipString, sizeof(ipString));
            InfoPrint("IP: %s", ipString);

            // Create a new UDP PCB structure
            pcb = udp_new();

            // Connect to the remote client
            udp_connect(pcb, &addr_cli, UDP_PORT);

            // Create a buffer for sending data
            uint8_t sendArray[MAX_BUFFER_SIZE];

            // Copy relevant data to sendArray
           // Do with data what zou want and fill Data_Len

            // Create a pbuf structure from the sendArray
            struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, Data_Len, PBUF_RAM);
            if (p != NULL) {
                // Copy sendArray to pbuf payload
                memcpy(p->payload, sendArray, Data_Len);

                // Send data
                udp_sendto(pcb, p, &addr_cli, UDP_PORT);

                // Free the pbuf structure
                pbuf_free(p);
            }

            // Close the UDP PCB when done
            udp_remove(pcb);
        }

        vTaskDelay(10);
    }
}
a nakonec callback

Kód: Vybrať všetko

// Callback function for receiving UDP data
static void udpReceiveCallback(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) {

    uint32_t ipAddr = ip_addr_get_ip4_u32(addr);
    IP_ADDR4(&addr_cli, (u8_t)ipAddr, (u8_t)(ipAddr >> 8), (u8_t)(ipAddr >> 16), (u8_t)(ipAddr >> 24));

    // Process the received data here
    if (p != NULL) {
        // Extract data from pbuf payload
        uint8_t receivedArray[MAX_BUFFER_SIZE];
        if (p->tot_len <= MAX_BUFFER_SIZE) {
            pbuf_copy_partial(p, receivedArray, p->tot_len, 0);

            // Do what you want with receivedArray

            // Free the pbuf structure
            pbuf_free(p);
        }
    }
}
0

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: LWIP + FreeRTOS a UDP příjem a odeslání dat

Príspevok od používateľa jirka.jirka. » 23 Nov 2023, 17:41

Člověk si otevře pívo a ono ejhle. Jedna věc mi docvakla.

Kód: Vybrať všetko

recv_err = netconn_recv(conn, &buf);


funkce, zablokuje task. :biggrin: Takže dobře, že jsem dostával tu chybu. Mohl jsem to přepracovat. Nyní už je všechno funkční. :agree:
0

Napísať odpoveď
  • Podobné témy
    Odpovedí
    Zobrazení
    Posledný príspevok