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

Getting issue in nRF9160 Application

Hi,

i am facing two issue in nRF9160 cellular application.

1.Asset tracker Application:

       i loaded Asset tracker example firmware in nRF9160 eval. board. when i run this application, error was displayed on console: "nrf_cloud_connect failed: 60".

2. custom firmware:

     in this firmware when "getaddrinfo" API is called to resolved IP, i am getting error 22:No more processes. i have attached code.please review it.

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

#include <logging/log.h>
#define LOG_DOMAIN sr_uart
#define LOG_LEVEL CONFIG_LOG_AT_HOST_LEVEL
LOG_MODULE_REGISTER(LOG_DOMAIN);

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



//*****************************************************************************
// Define Constant and Variable
//*****************************************************************************

#define INVALID_DESCRIPTOR -1

#define UART_RX_BUF_SIZE 4096 /**< UART RX buffer size. */
/**
 * @brief Size of the buffer used to parse an AT command.
 * Defines the maximum number of characters of an AT command (including null
 * termination) that we can store to decode. Must be a power of two.
 */
#define AT_MAX_CMD_LEN 4096


RINGBUFF_T    SR_UART_rxring;                                                                      // Transmit and receive ring buffers
uint8_t       SR_UART_rxRingbuff[SR_UART_RRB_SIZE];                                                // Transmit and receive buffers
uint8_t       SR_UART_rxbuff[SR_UART_RRB_SIZE], SR_UART_txbuff[SR_UART_SRB_SIZE];                       // Transmit and receive 
uint8_t       SR_UART_rxbuffbase64[SR_UART_RRB_SIZE];

struct device *uart_dev;
static int at_socket_fd = INVALID_DESCRIPTOR;

//*****************************************************************************
// Functions
//*****************************************************************************

void at_host_at_socket_write(const void *data, size_t datalen)
{
  if ((data != NULL) && (datalen > 0)) {
    
    //printf("Cell Tx: %d, Rx Data: %s\r\n", datalen, (char *)data);
    int bytes_written = send(at_socket_fd, data, datalen, 0);

    if (bytes_written <= 0) {
      LOG_ERR("\n Could not send AT-command to modem: [ %d ]", bytes_written);
    }
    gtsSR_ProcessState.CellRespPending = true;
  }
}

void at_host_at_socket_read(void)
{
  uint8_t data_buf[SR_UART_RRB_SIZE];
  int err;
  /* Read AT socket in non-blocking mode. */
  int bytes = recv(at_socket_fd, data_buf, sizeof(data_buf), MSG_DONTWAIT);
  /* Forward the data over UART if any. */
  /* If no data, errno is set to EGAIN and we will try again. */
  
  if (bytes > 0)
  {
   // printf("Cell RxLen: %d, Rx Data: %s\r\n", bytes, data_buf);
    
    switch(gtsSR_ProcessState.Conn_State)
    {
       case SR_Conn_PowerOff:
       {
         if(!gtsSR_ProcessState.CellInitDone)
         {
           if(0 == memcmp(AT_SUCCESS, data_buf, AT_CMD_SIZE(AT_SUCCESS)))
           {
             gtsSR_ProcessState.CellInitDone = true;
             gtsSR_ProcessState.CellRespPending = false;
           }
         }
         else
         {
           if (!memcmp(AT_STATUS_1, data_buf, AT_CMD_SIZE(AT_STATUS_1)) ||
                !memcmp(AT_STATUS_2, data_buf, AT_CMD_SIZE(AT_STATUS_2)) ||
                !memcmp(AT_STATUS_3, data_buf, AT_CMD_SIZE(AT_STATUS_3)) ||
                !memcmp(AT_STATUS_4, data_buf, AT_CMD_SIZE(AT_STATUS_4)))//||
                //!memcmp(AT_STATUS_5, data_buf, AT_CMD_SIZE(AT_STATUS_5))) 
           {
             gtsSR_ProcessState.Conn_State = SR_Conn_CellReg;
             gtsSR_ProcessState.CellRespPending = false;
             gtsSR_ProcessState.CellInitDone = false;
             gtsSR_ProcessState.RegistrationStatus = true;
             at_uart_send(uart_dev, data_buf, bytes);
           }
           else
           {
            at_uart_send(uart_dev, data_buf, bytes);
            gtsSR_ProcessState.RegistrationStatus = false;
           }
         }
       }
       break;
     
       case SR_Conn_CellReg:
       {
        gtsSR_ProcessState.Conn_State = SR_Conn_CellIdle;
       }
       break;
       
       case SR_Conn_Connected:
       {
        linux_NBIoT_write(uart_dev, data_buf, bytes);

        memset(SR_UART_txbuff, 0, sizeof(SR_UART_txbuff));
	sprintf(SR_UART_txbuff, "Host Socket Rx Data Len: %d\r\n Data:", bytes);
        uint8_t len = strlen(SR_UART_txbuff);
        memcpy(&SR_UART_txbuff[strlen(SR_UART_txbuff)], data_buf, bytes);
	at_uart_send(uart_dev, SR_UART_txbuff, len +bytes);
       }
       break;
    }
  }
}
                          
int at_socket_init(void)
{
  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);
  }

  return at_socket_fd;
}

int SR_ResolveServerURL(void)
{
  int err;
  struct addrinfo *res;
  struct addrinfo hints;

  hints.ai_flags = 0;
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = 0;

 // return 0;
  memset(SR_UART_txbuff, 0, sizeof(SR_UART_txbuff));

  err = getaddrinfo(gtsBridgeParam.ServerURL, NULL, &hints, &res);
  if(err)
  {
    sprintf(SR_UART_txbuff, "Get AddrInfo error = %d %s\r\n", err, strerror(errno));
    at_uart_send(uart_dev, SR_UART_txbuff, strlen(SR_UART_txbuff));
    
    return 1;
  }

  ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(gtsBridgeParam.ServerPort);
  
  struct sockaddr_in local_addr;

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

  gtsBridgeParam.ServerSocketFd = socket(AF_INET, SOCK_STREAM, 0);

  //printk("client_fd: %d\n\r", client_fd);
  err = bind(gtsBridgeParam.ServerSocketFd, (struct sockaddr *)&local_addr, sizeof(local_addr));
  
  if(err)
  {
    sprintf(SR_UART_txbuff, "bind error= %d %s\r\n", err, strerror(errno));
    at_uart_send(uart_dev, SR_UART_txbuff, strlen(SR_UART_txbuff));
    return 2;
  }
  //printk("bind err: %d\n\r", err);
  
  err = connect(gtsBridgeParam.ServerSocketFd, (struct sockaddr *)res->ai_addr, sizeof(struct sockaddr_in));

  if(err < 0)
  {
  
    sprintf(SR_UART_txbuff, "Server connect error = %d %s\r\n", err, strerror(errno));
    at_uart_send(uart_dev, SR_UART_txbuff, strlen(SR_UART_txbuff));
    if(errno == EAGAIN)
    {
      return 3;
    }
    else
    {
      return 4;
    }
  }
  
  return 0;
}

int SR_ServerSendData(uint8_t *buf, uint32_t size, uint32_t flags)
{
  return send(gtsBridgeParam.ServerSocketFd, buf, size, flags);
}

void SR_Cellular_Process(void)
{
uint8_t ui8buffer[15];

  if(gtsSR_ProcessState.CellRespPending)
  {
     return;
  }
  
  switch(gtsSR_ProcessState.Conn_State)
  {
     case SR_Conn_PowerOff:
     {
       if(!gtsSR_ProcessState.CellInitDone)
       {
         at_host_at_socket_write(AT_CEREG_2, sizeof(AT_CEREG_2));
       }
       else
       {
         at_host_at_socket_write(AT_CFUN_1, sizeof(AT_CFUN_1));
       }
     }
     break;
     
     case SR_Conn_CellReg:
     {
       if(gtsSR_ProcessState.ConnInitFlg)
       {
         gtsSR_ProcessState.Conn_State = SR_Conn_ResolveDNS;
       }
       else
       {
         gtsSR_ProcessState.Conn_State = SR_Conn_CellIdle;
       }
     }
     break;
     
     case SR_Conn_CellIdle:
     {
       if(gtsSR_ProcessState.ConnInitFlg)
       {
         gtsSR_ProcessState.Conn_State = SR_Conn_ResolveDNS;
       }
     }
     break;
     
     case SR_Conn_ResolveDNS:
     {
       if(gtsSR_ProcessState.ConnInitFlg)
       {
         int err = SR_ResolveServerURL();
         
         if(0 == err)
         {
           gtsSR_ProcessState.ConnInitFlg = false;
           gtsSR_ProcessState.Conn_State = SR_Conn_Connected; 
         }
         else
         {
           gtsSR_ProcessState.ConnInitFlg = false;
           gtsSR_ProcessState.Conn_State = SR_Conn_CellIdle;
         }
         memset(ui8buffer, 0, sizeof(ui8buffer));
         sprintf(ui8buffer,"SR+CONN=%d\r\n",err);
         at_uart_send(uart_dev, ui8buffer,strlen(ui8buffer));

        memset(SR_UART_txbuff, 0, sizeof(SR_UART_txbuff));
        sprintf(SR_UART_txbuff, "Parsed ServerURL: %s, Parsed ServerPort: %d\r\n", gtsBridgeParam.ServerURL, gtsBridgeParam.ServerPort);
        at_uart_send(uart_dev, SR_UART_txbuff, strlen(SR_UART_txbuff));
       }
     }
     break;
  }
  
}

void at_uart_send(struct device *uart_dev, const u8_t *tx_data, int size)
{
  for(uint32_t ui32Idx = 0; ui32Idx < size; ui32Idx++)
  {
    uart_poll_out(uart_dev, tx_data[ui32Idx]);
  }
}

static void isr(struct device *x)
{
  uint32_t lu32_len;
  uint8_t data_buf[SR_UART_RRB_SIZE];
  uart_irq_update(x);

  if (uart_irq_rx_ready(x)) {
  
    lu32_len = uart_fifo_read(x, data_buf, SR_UART_RRB_SIZE);
    RingBuffer_InsertMult(&SR_UART_rxring, data_buf, lu32_len);
    
    gtsSR_ProcessState.UARTRxStartFlg = true;	// Start Inter Character Timer
    gtsSR_ProcessTMR.UARTRxGetTimeMS = 0;
  }
}

int at_uart_init(char *uart_dev_name)
{
  int err;

  // Ringbuffer init
  memset(SR_UART_rxRingbuff, 0, sizeof(SR_UART_rxRingbuff));
  RingBuffer_Init(&SR_UART_rxring, SR_UART_rxRingbuff, 1, SR_UART_RRB_SIZE);
  RingBuffer_Flush(&SR_UART_rxring);

  uart_dev = device_get_binding(uart_dev_name);
  if (uart_dev == NULL) {
    LOG_ERR("Cannot bind %s\n", uart_dev_name);
    return EINVAL;
  }
  err = uart_err_check(uart_dev);
  if (err) {
    LOG_ERR("UART check failed\n");
    return EINVAL;
  }

  uart_irq_rx_enable(uart_dev);
  uart_irq_callback_set(uart_dev, isr);
  return err;
}

void SR_UartParser(void)
{
  volatile unsigned int bytes = 0;
  char *resultptr = NULL;
  int err;

  memset(SR_UART_rxbuff, 0, sizeof(SR_UART_rxbuff));

  bytes = RingBuffer_PopMult(&SR_UART_rxring, &SR_UART_rxbuff[0], SR_UART_RRB_SIZE);

  if(bytes <= 0)
  {
    gtsSR_ProcessState.UARTMsgParseFlg = false;     // Clear UART Parsing flag
    return;
  }
  //  at_host_at_socket_write(SR_UART_rxbuff, bytes);
//  printf("RxLen: %d, Rx Data: %.*s\r\n", bytes, bytes, SR_UART_rxbuff);
//  
  resultptr = strstr(SR_UART_rxbuff, "SR+CON=\"");
  if(NULL != resultptr)
  {
    resultptr += strlen("SR+CON=\"");
    memset(&gtsBridgeParam.ServerURL[0], 0, sizeof(gtsBridgeParam.ServerURL));
    u8_t lu8_UrlIdx = 0;
    while(('"' != *resultptr) && ((sizeof(gtsBridgeParam.ServerURL) - 1) > lu8_UrlIdx))
    {
      gtsBridgeParam.ServerURL[lu8_UrlIdx++] = *resultptr++;
    }
    
    resultptr++;
    resultptr++;
    
    gtsBridgeParam.ServerPort = atoi(resultptr);
  
    if(gtsBridgeParam.ServerSocketFd)
    {
        memset(SR_UART_txbuff, 0, sizeof(SR_UART_txbuff));
        sprintf(SR_UART_txbuff, "Closing opened socket\r\n");
        at_uart_send(uart_dev, SR_UART_txbuff, strlen(SR_UART_txbuff));
        err = close(gtsBridgeParam.ServerSocketFd);
        if(err)
        {
            memset(SR_UART_txbuff, 0, sizeof(SR_UART_txbuff));
            sprintf(SR_UART_txbuff, "socket close error:%d %s\r\n", err, strerror(errno));
            at_uart_send(uart_dev, SR_UART_txbuff, strlen(SR_UART_txbuff));
            return;
        }
    }
    gtsSR_ProcessState.ConnInitFlg = true;
    gtsSR_ProcessState.Conn_State = SR_Conn_CellIdle;
  }
  else
  {
    resultptr = strstr(SR_UART_rxbuff, "SR+MSG=");
    if(NULL != resultptr)
    {
      if(SR_Conn_Connected == gtsSR_ProcessState.Conn_State)
      {
        resultptr = strtok(SR_UART_rxbuff, "=");
        resultptr += strlen("SR+MSG=");
        
        uint32_t  msglen = atoi(resultptr);

        resultptr = strtok(NULL, "\"");
        resultptr = strtok(NULL, "\"");
        
        uint32_t  EncodedMsgLen = strlen(resultptr);  
        
        memset(SR_UART_rxbuffbase64, 0, sizeof(SR_UART_rxbuffbase64));
        if(SUCCESS != Decrypt_Base_64_Data((char *)resultptr, EncodedMsgLen, SR_UART_rxbuffbase64, sizeof(SR_UART_rxbuffbase64)))
        {
          return;
        }

        int err = SR_ServerSendData(SR_UART_rxbuffbase64, msglen, 0);  
        
        memset(SR_UART_txbuff, 0, sizeof(SR_UART_txbuff));
	sprintf(SR_UART_txbuff, "Decoded Rxed Data Len: %d\r\nDecoded Rxed Data:", msglen);
        uint8_t len = strlen(SR_UART_txbuff);
        memcpy(&SR_UART_txbuff[strlen(SR_UART_txbuff)], SR_UART_rxbuffbase64, msglen);
	at_uart_send(uart_dev, SR_UART_txbuff, len + msglen);
      }
    }
    else
    {
      resultptr = strstr(SR_UART_rxbuff, "SR+RSSI?");
      if(NULL != resultptr)
      {
        
      }
      
      else
      {
        resultptr = strstr(SR_UART_rxbuff, "SR+CELL?");
        if(NULL != resultptr)
        {
          memset(SR_UART_rxbuffbase64, 0, sizeof(SR_UART_rxbuffbase64));
          if(gtsSR_ProcessState.RegistrationStatus)
          {
            sprintf(SR_UART_rxbuffbase64, "SR+CELL=1\r\n");
          }
          else
          {
            sprintf(SR_UART_rxbuffbase64, "SR+CELL=0\r\n");
          }
          at_uart_send(uart_dev, SR_UART_rxbuffbase64, strlen(SR_UART_rxbuffbase64));
        }
        else
        {
          at_uart_send(uart_dev, SR_UART_rxbuff, bytes);
        }
      }
    }
  }

}

void linux_NBIoT_write(struct device *uart_dev, unsigned char* buffer, int len)
{
	memset(SR_UART_txbuff, 0, sizeof(SR_UART_txbuff));
	
	sprintf(SR_UART_txbuff, "SR+MSG=%u,\"",len);

	if(SUCCESS != Encrypt_Base_64_Data((char *)buffer, len, &SR_UART_txbuff[strlen(SR_UART_txbuff)], sizeof(SR_UART_txbuff) - strlen(SR_UART_txbuff)))
	{
		return;
	}
	sprintf(&SR_UART_txbuff[strlen(SR_UART_txbuff)],"\"");

	at_uart_send(uart_dev, SR_UART_txbuff, strlen(SR_UART_txbuff));

}

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

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

#define HTTP_HOST "google.com"
#define HTTP_PORT 80
#define RECV_BUF_SIZE 1024


tsBridgeParam gtsBridgeParam = {0};
tsSR_ProcessState gtsSR_ProcessState = {0};
tsSR_ProcessTMR gtsSR_ProcessTMR = {0};

extern struct device *uart_dev;
char recv_buf[RECV_BUF_SIZE + 1];

const char *at_commands[] = {
	"AT+CGMM", "AT+CGDCONT?", "AT%XCBAND=?", "AT+CGSN=1",
	"AT+CESQ", "AT+CEREG=2", "AT+COPS?",
	/* Add more here if needed */
};

uint8_t SR_UART_txbuff1[1000];
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_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 app_socket_start(void)
{
	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);
}

static int SR_Main_PowerUpInit(void)
{
    int err;

    err = at_uart_init(CONFIG_UART_0_NAME);

    if (err != 0) {
      //printf("ERROR: UART not initialized \r\n");
      return -1;
    }
      
    err = at_socket_init();

    if(err < 0)
    {
      //printf("ERROR: AT_Socket not initialized \r\n");
      return -1;
    }
    
    SR_Timer_Init();
    
    return 1;
}

int main(void)
{
  static uint32_t su32_Tick;
  int err;
  err = SR_Main_PowerUpInit();
  if(err < 0)
  {
    printf("ERROR: SR_Main_PowerUpInit.\r\n");
    while(1);
  }
  
  printf("SUCCESS: SR_Main_PowerUpInit.\r\n");

  while (1) {

    if(gtsSR_ProcessState.UARTMsgParseFlg)
    {
      SR_UartParser();
      gtsSR_ProcessState.UARTMsgParseFlg = false;     // Clear UART Parsing flag
    }
    
    at_host_at_socket_read();
    
    SR_Cellular_Process();  
    
    
    if(gtsSR_ProcessState.SecFlg)
    {
      su32_Tick++;
      
      if(0 == (su32_Tick % 60))
      {
        //printf("Tick: %u\r\n", su32_Tick);
      }
      gtsSR_ProcessState.SecFlg = false; 
    }
    
  }
}

//#include <zephyr.h>
//#include <stdio.h>
//#include <uart.h>
//#include <string.h>
//#include <at_host.h>
//
//void main(void)
//{
//	int err;
//
//	printf("The AT host sample started\n");
//
//	err = at_host_init(CONFIG_AT_HOST_UART, CONFIG_AT_HOST_TERMINATION);
//
//	if (err != 0) {
//		printf("ERROR: AT Host not initialized \r\n");
//		return;
//	}
//
//	while (1) {
//		at_host_process();
//	}
//}

  • Hi,

    Please try to run the AT_Client sample and run the LTE Link Monitor to gather the information from the modem side, and post the results.


    • What network are you trying to connect to?

    I have seen that some few providers do not properly setup DNS autoconfiguration on their side, which can cause similar issues as you see.

    To confirm this you could add this to prj.conf file for asset_tracker:

    CONFIG_NRF_CLOUD_STATIC_IPV4_ADDR=<ip_address>
    
    CONFIG_LTE_LEGACY_PCO_MODE=y
    
    CONFIG_NRF_CLOUD_STATIC_IPV4=y

    You can find the ip address to nrf cloud here: 

    https://whatismyipaddress.com/hostname-ip 

    with the nrf cloud host: a2n7tk1kp18wix-ats.iot.us-east-1.amazonaws.com


    Then you can add one of the ip-addresses in the prj.conf file.

    Note that these IPs can change, so you may need to update this if you want to prototype with nrf cloud.

    Build/flash/run

    (note that this needs to be the asset_tracker from master branch)

  • I run AT_Client sample and taken logs written below, please check.

    AT+CEREG?
    
    
    
    
    +CEREG: 2,5,"CB32","031A8B03",7
    
    
    
    
    OK
    
    
    
    
    
    
    AT+COPS=3,2
    
    
    
    
    OK
    
    
    
    
    
    
    AT+COPS?
    
    
    
    
    +COPS: 0,2,"311480",7
    
    
    
    
    OK
    
    
    
    
    
    
    AT%XCBAND
    
    
    
    
    %XCBAND: 13
    
    
    
    
    OK
    
    
    
    
    
    
    AT+CGDCONT?
    
    
    
    
    +CGDCONT: 0,"IP","ibasis.iot","10.160.171.23",0,0
    
    
    
    
    OK
    
    
    
    
    
    
    AT+CGACT?
    
    
    
    
    +CGACT: 0,1
    
    
    
    
    OK
    
    
    
    
    
    
    AT%CESQ=1
    
    
    
    
    OK
    
    
    
    
    
    
    AT+CESQ
    
    
    
    
    +CESQ: 99,99,255,255,255,48
    
    
    
    
    OK
    
    
    
    
    
    
    AT%XSIM=1
    
    
    
    
    OK
    
    
    
    
    
    
    AT%XSIM?
    
    
    
    
    %XSIM: 1
    
    
    
    
    OK
    
    
    
    
    
    
    AT+CPIN?
    
    
    
    
    +CPIN: READY
    
    
    
    
    OK
    
    
    
    
    
    
    AT+CPINR="SIM PIN"
    
    
    
    
    +CPINR: "SIM PIN",3
    
    
    
    
    OK
    
    
    
    
    
    
    AT+CIMI
    
    
    
    
    204080813514770
    
    
  • In my custom firmware, i tried to get Google IP by calling "getaddrinfo" API with "www.google.com", but i am getting same error as error 22:No more processes

  • Hi,

    • What network are you trying to connect to?
    • Which modem firmware are you running?

    From your at_client sample log I can see that you get a connection with the base station.

    I would like you to please try this (custom) asset_tracker sample:

    asset_tracker.hex

    If this one works, we could have a better understanding whats the issue.

    Use the command line with nrfjprog to flash this sample, with this command:

    nrfjprog --program asset_tracker.hex -f nrf91 --sectorerase -r --verify

  • Out of the box, my nrf9160 never blinked LED 3 and LED 4 at the same time. I programmed Martin's `asset_tracker.hex` and was able to successfully register my nrf9160 with nrf cloud. 

    Martin, what was the change to the asset_tracker code? Where can I find this example project?

Related