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!

cancel
Showing results for 
Search instead for 
Did you mean: 
Observer nunu
Observer
1,073 Views
Registered: ‎06-08-2017

Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

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

 

0 Kudos
7 Replies
Observer nunu
Observer
1,008 Views
Registered: ‎06-08-2017

Re: Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

Had to the MQTT protocol be activated in the Lwip settings?

0 Kudos
Highlighted
Visitor okanbozkurt
Visitor
684 Views
Registered: ‎12-25-2018

Re: Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

Hi nunu,

Did you solve the problem? I have same problem now.

Thanks

0 Kudos
Moderator
Moderator
636 Views
Registered: ‎09-12-2007

Re: Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

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

0 Kudos
Visitor okanbozkurt
Visitor
624 Views
Registered: ‎12-25-2018

Re: Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

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.

0 Kudos
Visitor serkane
Visitor
407 Views
Registered: ‎03-24-2019

Re: Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

Hello,

Could you give more detail about how to solve this problem?

Thanks,

Serkane

0 Kudos
Moderator
Moderator
399 Views
Registered: ‎09-12-2007

Re: Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

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.

 

0 Kudos
Visitor serkane
Visitor
388 Views
Registered: ‎03-24-2019

Re: Zynq Eval. Board zc706: Lwip: Mqtt-Client : Error

Yes, I got the same error.  Which modifications I should do on a local copy of LwIP? 

0 Kudos