UPGRADE YOUR BROWSER
We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!
05-20-2018 09:35 AM - edited 05-20-2018 02:05 PM
Hello,
I'm trying to implement a mqtt client with Lwip 2.0.2.
The Vivado version is 2018_1.
The Lwip is part of the BSP.
I used the code of this side as a template: http://www.nongnu.org/lwip/2_0_x/group__mqtt.html
#include <stdio.h> #include "xparameters.h" #include "netif/xadapter.h" #include "platform_config.h" #include "xil_printf.h" #include "lwip/apps/mqtt.h" #include "lwip/apps/mqtt_opts.h" #include "lwip/err.h" #include "lwip/ip_addr.h" static void mqtt_pub_request_cb(void *arg, err_t result); void example_publish(mqtt_client_t *client, void *arg); static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len); static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags); static void mqtt_sub_request_cb(void *arg, err_t result); static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); void example_do_connect(mqtt_client_t *client); /* * ----------------------------------------------------------------- 4. Using outgoing publish * */ /* Called when publish is complete either with sucess or failure */ static void mqtt_pub_request_cb(void *arg, err_t result) { if(result != ERR_OK) { printf("Publish result: %d\n", result); } } void example_publish(mqtt_client_t *client, void *arg) { const char *pub_payload= "PubSubHubLubJub"; err_t err; u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ u8_t retain = 0; /* No don't retain such crappy payload... */ err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg); if(err != ERR_OK) { printf("Publish err: %d\n", err); } } /*----------------------------------------------------------------- 3. Implementing callbacks for incoming publish and data*/ /* The idea is to demultiplex topic and create some reference to be used in data callbacks Example here uses a global variable, better would be to use a member in arg If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of the topic string and use it in mqtt_incoming_data_cb */ static int inpub_id; static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) { printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len); /* Decode topic string into a user defined reference */ if(strcmp(topic, "print_payload") == 0) { inpub_id = 0; } else if(topic[0] == 'A') { /* All topics starting with 'A' might be handled at the same way */ inpub_id = 1; } else { /* For all other topics */ inpub_id = 2; } } static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) { printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags); if(flags & MQTT_DATA_FLAG_LAST) { /* Last fragment of payload received (or whole part if payload fits receive buffer See MQTT_VAR_HEADER_BUFFER_LEN) */ /* Call function or do action depending on reference, in this case inpub_id */ if(inpub_id == 0) { /* Don't trust the publisher, check zero termination */ if(data[len-1] == 0) { printf("mqtt_incoming_data_cb: %s\n", (const char *)data); } } else if(inpub_id == 1) { /* Call an 'A' function... */ } else { printf("mqtt_incoming_data_cb: Ignoring payload...\n"); } } else { /* Handle fragmented payload, store in buffer, write to file or whatever */ } } /*----------------------------------------------------------------- 2. Implementing the connection status callback*/ static void mqtt_sub_request_cb(void *arg, err_t result) { /* Just print the result code here for simplicity, normal behaviour would be to take some action if subscribe fails like notifying user, retry subscribe or disconnect from server */ printf("Subscribe result: %d\n", result); } static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) { err_t err; if(status == MQTT_CONNECT_ACCEPTED) { printf("mqtt_connection_cb: Successfully connected\n"); /* Setup callback for incoming publish requests */ mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg); /* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */ err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg); if(err != ERR_OK) { printf("mqtt_subscribe return: %d\n", err); } } else { printf("mqtt_connection_cb: Disconnected, reason: %d\n", status); /* Its more nice to be connected, so try to reconnect */ example_do_connect(client); } } void example_do_connect(mqtt_client_t *client) { struct mqtt_connect_client_info_t ci; ip_addr_t serverIpAddr; /* initliaze IP addresses to be used */ IP4_ADDR(&serverIpAddr, 192, 168, 1, 10); //IP4_ADDR(&netmask, 255, 255, 255, 0); //IP4_ADDR(&gw, 192, 168, 1, 1); err_t err; /* Setup an empty client info structure */ memset(&ci, 0, sizeof(ci)); /* Minimal amount of information required is client identifier, so set it here */ ci.client_id = "lwip_test"; /* Initiate client and connect to server, if this fails immediately an error code is returned otherwise mqtt_connection_cb will be called with connection result after attempting to establish a connection with the server. For now MQTT version 3.1.1 is always used */ //err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci); err = mqtt_client_connect(client, &serverIpAddr, MQTT_PORT, mqtt_connection_cb, 0, &ci); /* For now just print the result code if something goes wrong */ if(err != ERR_OK) { printf("mqtt_connect return %d\n", err); } } int main(){ mqtt_client_t static_client; example_do_connect(&static_client); return 0; }
The Sdk generates the following error:
Building target: TestMQTT02.elf Invoking: ARM v7 gcc linker arm-none-eabi-gcc -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none -specs=Xilinx.spec -Wl,-T -Wl,../src/lscript.ld -L../../TestMQTT_bsp/ps7_cortexa9_0/lib -o "TestMQTT02.elf" ./src/main.o -Wl,--start-group,-lxil,-lfreertos,-lgcc,-lc,--end-group -Wl,--start-group,-lxil,-llwip4,-lgcc,-lc,--end-group ./src/main.o: In function `example_publish': workspaceSDK2018_1\TestMQTT02\Debug/../src/main.c:77: undefined reference to `mqtt_publish' ./src/main.o: In function `mqtt_connection_cb': workspaceSDK2018_1\TestMQTT02\Debug/../src/main.c:153: undefined reference to `mqtt_set_inpub_callback' workspaceSDK2018_1\TestMQTT02\Debug/../src/main.c:157: undefined reference to `mqtt_sub_unsub' ./src/main.o: In function `example_do_connect': workspaceSDK2018_1\TestMQTT02\Debug/../src/main.c:193: undefined reference to `mqtt_client_connect' collect2.exe: error: ld returned 1 exit status make: *** [TestMQTT02.elf] Fehler 1
It seems like the Linker does not find the functions:
mqtt_publish
mqtt_set_inpub_callback
mqtt_sub_unsub
mqtt_client_connect
Does somebody has any idea, how to solve this issue?
Thx in advance
05-22-2018 01:49 AM
Had to the MQTT protocol be activated in the Lwip settings?
01-02-2019 02:09 AM
Hi nunu,
Did you solve the problem? I have same problem now.
Thanks
01-03-2019 03:16 AM
The Xilinx Port of the LwIP doesnt enable all the features of the LwIP. This one may be just one of them. So, you may need to use the lwip library from the community and add this library to your BSP manually.
Or hack the xilinx port to enable this feature with #defines
01-03-2019 09:41 PM
Thank you for your answer. I solved problem with another way.
Actually there is "mqtt.c" file in Xilinx LwIP port. But it is not compiled. I realized that there is nothing about "mqtt.c" file in makefile of LwIP. I added it but I had some failure. So, I moved "mqtt.c" file from BSP to application. Then it works well.
04-09-2019 03:30 AM
Hello,
Could you give more detail about how to solve this problem?
Thanks,
Serkane
04-09-2019 03:45 AM
Are you seeing the same issue? As mentioned above, xilinx takes the lwip libary and will port it to work on the xilinx devices, so all the features are not enabled. You would need to make a local copy of the library (for example c:\test/repo/lib/sw_services/lwip202_v1_2), then in SDK, Xilinx -> Repositories, and point to the repo folder (note the two levels of hierarchy). You would then modify the local copy of the lwip to add your feature you want.
04-09-2019 05:17 AM
Yes, I got the same error. Which modifications I should do on a local copy of LwIP?