I’ve been learning (still feel very newbie-like) by taking the blinky example and putting in some LTE connectivity from the tracker sample as well as the http_get samples. It seems to work - The first 7 requests get made and the board sleeps for the defined time. However, completely consistently, on the 8th request, I can no longer get information from the modem, and getaddr fails. I try to catch this and deinit and init the modem, but it just stalls.

Sample log:

Loop 7... Reset count = 0
APN: nbiot.tdc.dk
IP Addr: 10.255.64.247
Signal Strength: 55
Preparing HTTP GET request for http://postman-echo.com:80/get?foo1=bar1&foo2=bar2
getaddrinfo status: 0
addrinfo @0x2000f5d0: ai_family=1, ai_socktype=1, ai_protocol=6, sa_family=1, sin_port=5000
sock = 0
Response:

HTTP/1.1 200 OK
Date: Thu, 24 Nov 2022 21:27:20 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 244
Connection: close
ETag: W/"f4-H5xxJO6rN9uh4r3dp5C0I+E6s1k"
Vary: Accept-Encoding
set-cookie: sails.sid=s%3AhXnBAGixP9uTLQrzNk43YXlhmfZ5yhJx.845%2BVWlJYvsJcT7DmQy1xEgZVieJ9DMJ5gcMZxLv7I8; Path=/; HttpOnly

{"args":{"foo1":"bar1","foo2":"bar2"},"headers":{"x-forwarded-proto":"http","x-forwarded-port":"80","host":"postman-echo.com","x-amzn-trace-id":"Root=1-637fe1b8-03ef660e2daf2e171a89f538"},"url":"http://postman-echo.com/get?foo1=bar1&foo2=bar2"}
Sleeping
Loop 8... Reset count = 0
APN: Error -22
IP Addr: Error -22
Signal Strength: 55
Preparing HTTP GET request for http://postman-echo.com:80/get?foo1=bar1&foo2=bar2
getaddrinfo status: -10
Unable to resolve address
Restarting modem
Deinit
Init
Done restarting modem
Loop 9... Reset count = 1
Starting network...

main.c:

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/gpio.h>

#include <modem/lte_lc.h>
#include <modem/modem_info.h>
#include <date_time.h>

#include <posix/time.h>
#include <posix/sys/time.h>

#include <net/socket.h>
#include <kernel.h>

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS   5000

/* Imei */
static char imei[20];

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)

#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
#define LED0	DT_GPIO_LABEL(LED0_NODE, gpios)
#define PIN	DT_GPIO_PIN(LED0_NODE, gpios)
#if DT_PHA_HAS_CELL(LED0_NODE, gpios, flags)
#define FLAGS	DT_GPIO_FLAGS(LED0_NODE, gpios)
#endif
#else
/* A build error here means your board isn't set up to blink an LED. */
#error "Unsupported board: led0 devicetree alias is not defined"
#define LED0	""
#define PIN	0
#endif

#ifndef FLAGS
#define FLAGS	0
#endif

/* HTTP server to connect to */
#define HTTP_HOST "postman-echo.com"
/* Port to connect to, as string */
#define HTTP_PORT "80"
/* HTTP path to request */
#define HTTP_PATH "/get?foo1=bar1&foo2=bar2"


#define SSTRLEN(s) (sizeof(s) - 1)
#define CHECK(r) { if (r == -1) { printf("Error: " #r "\n"); exit(1); } }

#define REQUEST "GET " HTTP_PATH " HTTP/1.0\r\nHost: " HTTP_HOST "\r\n\r\n"

static char response[1024];

int resetcount = 0;
bool connected = false;

void dump_addrinfo(const struct addrinfo *ai)
{
	printf("addrinfo @%p: ai_family=%d, ai_socktype=%d, ai_protocol=%d, "
	       "sa_family=%d, sin_port=%x\n",
	       ai, ai->ai_family, ai->ai_socktype, ai->ai_protocol,
	       ai->ai_addr->sa_family,
	       ((struct sockaddr_in *)ai->ai_addr)->sin_port);
}

void print_modem_info(enum modem_info info)
{
	int len;
	char buf[80];
	len = modem_info_string_get(info, buf, 80);

	switch (info) {
		case MODEM_INFO_RSRP:
			printk("Signal Strength: ");
			break;
		case MODEM_INFO_IP_ADDRESS:
			printk("IP Addr: ");
			break;
		case MODEM_INFO_FW_VERSION:
			printk("Modem FW Ver: ");
			break;
		case MODEM_INFO_ICCID:
			printk("SIM ICCID: ");
			break;
		case MODEM_INFO_IMSI:
			printk("IMSI: ");
			break;
		case MODEM_INFO_IMEI:
			printk("IMEI: ");
			break;
		case MODEM_INFO_DATE_TIME:
			printk("Network Date/Time: ");
			break;
		case MODEM_INFO_APN:
			printk("APN: ");
			break;
		default:
			printk("Unsupported: ");
			break;
	}

	if (len > 0) {
		printk("%s\n",buf);
	} else {
		printk("Error %d\n", len);
	}
}

void restart_modem() {
	int err;
	printk("Restarting modem\n");

	printk("Deinit\n");
	err = lte_lc_deinit();
	if (err) {
		printk("Failed to deactivate LTE, error: %d\n", err);
	}
	k_msleep(2000);

	printk("Init\n");
	err = lte_lc_init();
	if (err) {
		printk("Failed to activate LTE, error: %d\n", err);
	}
	printk("Done restarting modem\n");
	connected = false;
	resetcount++;
}

static void lte_handler(const struct lte_lc_evt *const evt)
{
    switch (evt->type)
    {
    case LTE_LC_EVT_NW_REG_STATUS:
        printk("LTE Status: %i", evt->nw_reg_status);

        if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
            (evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING))
        {
            
			printk("Moden disconnected!");
			connected = false;
            break;
        }

        /* Otherwise send connected event */
        printk("Moden connected!");
		connected = true;

        printk("Network registration status: %s",
                evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ? "Connected - home network" : "Connected - roaming");

        break;
    default:
        break;
    }
}

void main(void)
{
	printk("Booting up...\n");
	const struct device *dev;
	int ret;
	int loop = 0;

	dev = device_get_binding(LED0);
	if (dev == NULL) {
		return;
	}

	ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
	if (ret < 0) {
		return;
	}
	gpio_pin_set(dev, PIN, 0);

	static struct addrinfo hints;
	struct addrinfo *res;
	int st, sock;
	int err;

	/* Register LTE handler */
    lte_lc_register_handler(lte_handler);

	/* Enable PSM mode */
	err = lte_lc_psm_req(true);
	if (err)
		printk("Requesting PSM failed, error: %d", err);


	err = lte_lc_init();
	if (err) {
		printk("Failed to init. Err: %i\n", err);
		return err;
	}

	/* Configure modem info module*/
	err = modem_info_init();
	if (err) {
		printk("Failed initializing modem info module, error: %d\n",
				err);
		return err;
	}

	while (1) {
		loop++;
		gpio_pin_set(dev, PIN, 0);
		printk("Loop %d... Reset count = %d\n", loop, resetcount);

		if(!connected) {
			// TODO: move all of this inside the main while loop, so we can "re start" properly
			printk("Starting network...\n");

			/* Init lte_lc*/
			err = lte_lc_connect();
			if (err) {
				printk("Failed to connect. Err: %i\n", err);
				restart_modem();
				continue;
			}

			/* RSRP value */
			//err = modem_info_rsrp_register(rsrp_cb);

			print_modem_info(MODEM_INFO_FW_VERSION);
			print_modem_info(MODEM_INFO_IMEI);
			print_modem_info(MODEM_INFO_ICCID);
			connected = true;
		}

		print_modem_info(MODEM_INFO_APN);
		print_modem_info(MODEM_INFO_IP_ADDRESS);
		print_modem_info(MODEM_INFO_RSRP);

		printf("Preparing HTTP GET request for http://" HTTP_HOST
	       ":" HTTP_PORT HTTP_PATH "\n");
		   

		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		st = getaddrinfo(HTTP_HOST, HTTP_PORT, &hints, &res);
		printf("getaddrinfo status: %d\n", st);

		if (st != 0) {
			printf("Unable to resolve address\n");
			restart_modem();
			continue;
		} else {
			dump_addrinfo(res);
			sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
			CHECK(sock);
			printf("sock = %d\n", sock);

			CHECK(connect(sock, res->ai_addr, res->ai_addrlen));
			CHECK(send(sock, REQUEST, SSTRLEN(REQUEST), 0));

			printf("Response:\n\n");

			while (1) {
				// TODO: recv this can hang, this a timeout?
				int len = recv(sock, response, sizeof(response) - 1, 0);

				if (len < 0) {
					printf("Error reading response\n");
					len = 0;
				}

				if (len == 0) {
					break;
				}

				response[len] = 0;
				printf("%s", response);
			}

			printf("\n");

			(void)close(sock);
		}

		gpio_pin_set(dev, PIN, 1);
		printk("Sleeping\n");
		k_msleep(SLEEP_TIME_MS);
	}
}

and prj.conf:

# Network
CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_NATIVE=n

CONFIG_HEAP_MEM_POOL_SIZE=1024
CONFIG_MAIN_STACK_SIZE=2048

# Modem Library
CONFIG_NRF_MODEM_LIB=y

# Modem Information 
CONFIG_MODEM_INFO=y

CONFIG_MODEM_KEY_MGMT=y

# LTE Link Control
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n

# NEWLIB C Library
CONFIG_NEWLIB_LIBC=y

# Date-Time Library
CONFIG_DATE_TIME=y
# Enables use of modem time
CONFIG_DATE_TIME_MODEM=y
# Trigger date-time update automatically when LTE is connected
CONFIG_DATE_TIME_AUTO_UPDATE=y
# Date time update interval, in seconds (Default 14400/4 hours). 
# Set to 0 to disable date-time updates.
#CONFIG_DATE_TIME_UPDATE_INTERVAL_SECONDS=3600

CONFIG_GPIO=y

# Enable Zephyr application to be booted by MCUboot
CONFIG_BOOTLOADER_MCUBOOT=y 

Any clues on what I’m doing wrong? I have a feeling it might be more to do with the code than the modem, since it doesnt seem to matter what I set the sleep time to (it still fails at loop 8). However, I have no clue how to debug this on the device?

It just seemed to hit a very long timeout - Maybe 30 mins?

Loop 9... Reset count = 1
Starting network...
Failed to connect. Err: -116
Restarting modem
Deinit
Init
Done restarting modem
Loop 10... Reset count = 2
Starting network...

Looking at this again this morning, i believe that it’s due to me not freeing the addrinfo memory. I added freeaddrinfo(res); now, and it’s been running for almost 700 loops without problems.

Is there a way to reach such a conclusion faster? E.g. getting an error somewhere when the board runs out of memory or whatever happened?

@JeppeMariagerLam your situation is very common. I usually make sure that HW stack protection is turned on. That way if there’s an overflow it will fault.

# Enable HW stack protection
CONFIG_HW_STACK_PROTECTION=y

You can also use the thread monitor to check if your threads are having issues:

CONFIG_THREAD_NAME=y
CONFIG_THREAD_ANALYZER=y
CONFIG_THREAD_ANALYZER_AUTO=y
CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y

You can check out zephyr/subsys/debug/Kconfig for more info on that.

I know there are some debugging provisions for checking things real time but I don’t know of the top of my head.

Terms and Conditions | Privacy Policy