This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to use PSM with UDP on DK 0.8.5?

I've been attempting to use PSM but got an error.

I've already checked the post below. I download the project file and fixed a bit.

https://devzone.nordicsemi.com/nordic/cellular-iot-guides/b/hardware-design/posts/measuring-psm-idle-current-on-the-nrf91-dk

It causes an error, which is "Error setting PSM: -5 Errno: 0" at the line of "int err = lte_lc_psm_req(true);"

<condition>
- DK 0.8.5
- modem: v1.0.0
- firmware ver: v1.0.0
- iBasis SIM

<main.c>

/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
 */

#include <zephyr.h>
#include <net/socket.h>
#include <stdio.h>
#include <uart.h>
#include <string.h>
#include <lte_lc.h>

#define HOST "129.240.2.6"
#define PORT 123
#define RECV_BUF_SIZE 1024
#define SEND_BUF_SIZE 1024

u8_t recv_buf[RECV_BUF_SIZE];

struct ntp_format {
	u8_t flags;
	u8_t stratum; /* stratum */
	u8_t poll; /* poll interval */
	s8_t precision; /* precision */
	u32_t rootdelay; /* root delay */
	u32_t rootdisp; /* root dispersion */
	u32_t refid; /* reference ID */
	u32_t reftime_sec; /* reference time */
	u32_t reftime_frac; /* reference time */
	u32_t org_sec; /* origin timestamp */
	u32_t org_frac; /* origin timestamp */
	u32_t rec_sec; /* receive timestamp */
	u32_t rec_frac; /* receive timestamp */
	u32_t xmt_sec; /* transmit timestamp */
	u32_t xmt_frac; /* transmit timestamp */
};

int blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = recv(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_recvfrom(int fd, void *buf, u32_t size, u32_t flags,
		      struct sockaddr *src_addr, socklen_t *addrlen)
{
	int err;

	do {
		err = recvfrom(fd, buf, size, flags, src_addr, addrlen);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_send(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = send(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_connect(int fd, struct sockaddr *local_addr, socklen_t len)
{
	int err;

	do {
		err = connect(fd, local_addr, len);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

void setup_psm(void)
{
	/*
	* GPRS Timer 3 value (octet 3)
	*
	* Bits 5 to 1 represent the binary coded timer value.
	*
	* Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
	* Bits 
	* 8 7 6
	* 0 0 0 value is incremented in multiples of 10 minutes 
	* 0 0 1 value is incremented in multiples of 1 hour 
	* 0 1 0 value is incremented in multiples of 10 hours
	* 0 1 1 value is incremented in multiples of 2 seconds
	* 1 0 0 value is incremented in multiples of 30 seconds
	* 1 0 1 value is incremented in multiples of 1 minute
	* 1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
	* 1 1 1 value indicates that the timer is deactivated (NOTE 2).
	*/
	char psm_settings[] = CONFIG_LTE_PSM_REQ_RPTAU;
	printk("PSM bits: %c%c%c\n", psm_settings[0], psm_settings[1], psm_settings[2]);
	printk("PSM Interval: %c%c%c%c%c\n", psm_settings[3], psm_settings[4], psm_settings[5], psm_settings[6], psm_settings[7]);
	int err = lte_lc_psm_req(true);
	if (err < 0) {
		printk("Error setting PSM: %d Errno: %d\n", err, errno);
	}
}

void app_udp_start(void)
{
	struct addrinfo *res;
	socklen_t addrlen = sizeof(struct sockaddr_storage);

	int err = getaddrinfo(HOST, NULL, NULL, &res);
	if (err < 0) {
		printk("getaddrinfo err: %d\n\r", err);
		return;
	}
	((struct sockaddr_in *)res->ai_addr)->sin_port = htons(PORT);
	struct sockaddr_in local_addr;

	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons(0);
	local_addr.sin_addr.s_addr = 0;

	int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (client_fd < 0) {
		printk("client_fd: %d\n\r", client_fd);
		goto error;
	}

	err = bind(client_fd, (struct sockaddr *)&local_addr, sizeof(local_addr));
	if (err < 0) {
		printk("bind err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	err = connect(client_fd, (struct sockaddr *)res->ai_addr, sizeof(struct sockaddr_in));
	if (err < 0) {
		printk("connect err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	/* Just hard code the packet format */
	u8_t send_buf[sizeof(struct ntp_format)] = { 0xe3 };

	err = send(client_fd, send_buf, sizeof(send_buf), 0);
	printk("sendto ret: %d\n\r", err);
	if (err < 0) {
		printk("sendto err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	err = blocking_recvfrom(client_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)res->ai_addr, &addrlen);
	if (err < 0) {
		printk("recvfrom err: %d errno: %d\n\r", err, errno);
		goto error;
	} else {
		printk("Got data back: ");
		for (int i = 0; i < err; i++) {
			printk("%x ", recv_buf[i]);
		}
		printk("\n");
	}

error:
	printk("Finished\n");
	(void)close(client_fd);
}

static volatile bool run_udp;

void app_timer_handler(struct k_timer *dummy)
{
	static u32_t minutes;

	minutes++;
	/* This shall match the PSM interval */
	if (minutes % 10 == 0) {
		run_udp = true;
	}
	printk("Elapsed time: %d\n", minutes);
}

K_TIMER_DEFINE(app_timer, app_timer_handler, NULL);

void timer_init(void)
{
	k_timer_start(&app_timer, K_MINUTES(1), K_MINUTES(1));
}

void send_at_commands(void)
{
        char recv_buf[1024 + 1];

        const char *at_commands[] = { "AT+CPSMS?", "AT+CEREG=5", "AT+CEREG?" };
	int at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);

	printk("Starting simple AT socket application\n\r");

	if (at_socket_fd < 0) {
		printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
	}
	for (int i = 0; i < ARRAY_SIZE(at_commands); i++) {
		int bytes_written = send(at_socket_fd, at_commands[i],
					 strlen(at_commands[i]), 0);
		if (bytes_written > 0) {
			int r_bytes =
				blocking_recv(at_socket_fd, recv_buf,
					      sizeof(recv_buf), MSG_DONTWAIT);
			if (r_bytes > 0) {
				printk("%s", recv_buf);
			}
		}
	}
	printk("Closing socket\n\r");
	(void)close(at_socket_fd);
}

int main(void)
{
	printk("UDP test with PSM\n");
	app_udp_start();
        printk("here1\n");
	setup_psm();
        printk("here2\n");
	timer_init();
        printk("here3\n");
        send_at_commands();
	while (1) {
                printk("here4\n");
		k_sleep(5000);
		if (run_udp == true) {
			printk("Run UDP\n");
			run_udp = false;
			app_udp_start();
		}
	}
	return 1;
}

<main.c>
CONFIG_NEWLIB_LIBC=n
CONFIG_BSD_LIBRARY=y
CONFIG_GPIO=n
CONFIG_SERIAL=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NETWORKING=y
CONFIG_NET_BUF_USER_DATA_SIZE=1
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_RAW_MODE=y
CONFIG_TRUSTED_EXECUTION_NONSECURE=y
CONFIG_LOG=n
CONFIG_LOG_DEFAULT_LEVEL=4
CONFIG_HEAP_MEM_POOL_SIZE=1024

# LTE link control
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_LEGACY_PCO_MODE=y
# CONFIG_LTE_NETWORK_MODE_NBIOT=y
CONFIG_LTE_NETWORK_MODE_LTE_M=y

# Main thread
CONFIG_MAIN_THREAD_PRIORITY=7
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_LTE_PSM_REQ_RPTAU="10101010"
CONFIG_LTE_PSM_REQ_RAT="00100001"
CONFIG_AT_HOST_LIBRARY=y

CONFIG_BSD_LIBRARY_TRACE_ENABLED=n

***** Booting Zephyr OS v1.14.99-ncs2 *****
UDP test with PSM
sendto ret: 48
Got data back: 24 2 3 e8 0 0 3 78 0 0 5 af c0 26 7 f0 e0 de f8 ec a3 2e c5 af 0 0 0 0 0 0 0 0 e0 de fa 9c a3 e2 d7 bf e0 de fa 9c a3 e4 d2 77 
Finished
here1
PSM bits: 101
PSM Interval: 01010
Error setting PSM: -5 Errno: 0 // HERE
here2
here3
Starting simple AT socket application
+CPSMS: 1,,,"10101010","00100001"
OK
+CEREG: 0,5,"1247","02DCD201",7
OK
Closing socket
here4
here4

Any advice?

Related