nRF9151 custom board – GNSS sample fails with “Failed to activate GNSS functional mode”

Hi Nordic Team,

I have developed a custom board using the nRF9151 controller.
I am testing the GNSS sample from nRF Connect SDK v3.0.0.
When I flash and run the firmware, I see the following output in RTT Viewer:

Hardware Details:

  • SoC: nRF9151

  • Board: Custom design (based on nRF9151 DK reference)

Software Details:

  • nRF Connect SDK: v3.0.0

  • Toolchain: nRF Connect for VS Code

  • Sample Used: nrf/samples/nrf9160/gnss

  • Build target: nrf9151dk_nrf9151

    How can I solve this issue?


Best regards

Arun

Parents
  • Hi,

    I have tested unmodified sample on nrf9151-dk and I could not replicate reported error.

    Which version of the modem firmware do you use on your custom board?

    Sample Used: nrf/samples/nrf9160/gnss

    The GNSS sample is located in nrf\samples\cellular\gnss in NCS v3.0.0.

    Build target: nrf9151dk_nrf9151

    You can try to build the sample for nrf9151dk/nrf9151/ns as specified in GNSS sample documentation.

    I have developed a custom board using the nRF9151 controller.

     Does the error come when building for nrf9151-dk or for custom board?

    Best regards,
    Dejan

  • Hi Dejan,

    Sorry for the confusion — I’m actually using the nrf/samples/cellular/gnss example from NCS v3.0.0, not nrf/samples/nrf9160/gnss.
    The build target I used is nrf9151dk_nrf9151 ns.

    There were no errors during build or compilation, and I uploaded the firmware to my custom board using the nRF9151 DK as a programmer.

    After uploading, when I open RTT Viewer, I see the following error:

    Could you please advise on what might be causing this issue?

    Best regards,
    Arun

  • Hi Arun,

    Can you try to remove occurrences of printk (from your code and configuration) and leave only logging enabled? What is the result?

    Best regards,
    Dejan

  • Hi Dejan,

    I removed all occurrences of printk from both the project source files and the configuration file, but it’s still showing the same error.

    I’m using the nRF52 DK as a programmer to flash my nRF9151 board.
    I upload the firmware using nRF Connect for Desktop (Programmer tab), and since I can’t see any output in the serial terminal, I’m using J-Link RTT Viewer to monitor the logs.

    I’ve attached my main.c and prj.conf files — could you please check and let me know if anything is missing or needs to be modified?

    /*
     * Copyright (c) 2019 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <zephyr/kernel.h>
    #include <zephyr/logging/log.h>
    #include <nrf_modem_at.h>
    #include <nrf_modem_gnss.h>
    #include <modem/lte_lc.h>
    #include <modem/nrf_modem_lib.h>
    #include <date_time.h>
    
    
    LOG_MODULE_REGISTER(gnss_sample, CONFIG_GNSS_SAMPLE_LOG_LEVEL);
    
    #define PI 3.14159265358979323846
    #define EARTH_RADIUS_METERS (6371.0 * 1000.0)
    
    #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    static struct k_work_q gnss_work_q;
    
    #define GNSS_WORKQ_THREAD_STACK_SIZE 2304
    #define GNSS_WORKQ_THREAD_PRIORITY   5
    
    K_THREAD_STACK_DEFINE(gnss_workq_stack_area, GNSS_WORKQ_THREAD_STACK_SIZE);
    #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE || CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */
    
    #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)
    #include "assistance.h"
    
    static struct nrf_modem_gnss_agnss_data_frame last_agnss;
    static struct k_work agnss_data_get_work;
    static volatile bool requesting_assistance;
    #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */
    
    #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    static struct k_work_delayable ttff_test_got_fix_work;
    static struct k_work_delayable ttff_test_prepare_work;
    static struct k_work ttff_test_start_work;
    static double time_to_fix;
    #endif
    
    static const char update_indicator[] = {'\\', '|', '/', '-'};
    
    static struct nrf_modem_gnss_pvt_data_frame last_pvt;
    static uint64_t fix_timestamp;
    static uint32_t time_blocked;
    
    /* Reference position. */
    static bool ref_used;
    static double ref_latitude;
    static double ref_longitude;
    
    K_MSGQ_DEFINE(nmea_queue, sizeof(struct nrf_modem_gnss_nmea_data_frame *), 10, 4);
    static K_SEM_DEFINE(pvt_data_sem, 0, 1);
    static K_SEM_DEFINE(time_sem, 0, 1);
    
    static struct k_poll_event events[2] = {
    	K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
    					K_POLL_MODE_NOTIFY_ONLY,
    					&pvt_data_sem, 0),
    	K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
    					K_POLL_MODE_NOTIFY_ONLY,
    					&nmea_queue, 0),
    };
    
    BUILD_ASSERT(IS_ENABLED(CONFIG_LTE_NETWORK_MODE_LTE_M_GPS) ||
    	     IS_ENABLED(CONFIG_LTE_NETWORK_MODE_NBIOT_GPS) ||
    	     IS_ENABLED(CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS),
    	     "CONFIG_LTE_NETWORK_MODE_LTE_M_GPS, "
    	     "CONFIG_LTE_NETWORK_MODE_NBIOT_GPS or "
    	     "CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS must be enabled");
    
    BUILD_ASSERT((sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE) == 1 &&
    	      sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE) == 1) ||
    	     (sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE) > 1 &&
    	      sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE) > 1),
    	     "CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE and "
    	     "CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE must be both either set or empty");
    
    /* Returns the distance between two coordinates in meters. The distance is calculated using the
     * haversine formula.
     */
    static double distance_calculate(double lat1, double lon1,
    				 double lat2, double lon2)
    {
    	double d_lat_rad = (lat2 - lat1) * PI / 180.0;
    	double d_lon_rad = (lon2 - lon1) * PI / 180.0;
    
    	double lat1_rad = lat1 * PI / 180.0;
    	double lat2_rad = lat2 * PI / 180.0;
    
    	double a = pow(sin(d_lat_rad / 2), 2) +
    		   pow(sin(d_lon_rad / 2), 2) *
    		   cos(lat1_rad) * cos(lat2_rad);
    
    	double c = 2 * asin(sqrt(a));
    
    	return EARTH_RADIUS_METERS * c;
    }
    
    static void print_distance_from_reference(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	if (!ref_used) {
    		return;
    	}
    
    	double distance = distance_calculate(pvt_data->latitude, pvt_data->longitude,
    					     ref_latitude, ref_longitude);
    
    	if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)) {
    		LOG_INF("Distance from reference: %.01f", distance);
    	} else {
    		printf("\nDistance from reference: %.01f\n", distance);
    	}
    }
    
    static void gnss_event_handler(int event)
    {
    	int retval;
    	struct nrf_modem_gnss_nmea_data_frame *nmea_data;
    
    	switch (event) {
    	case NRF_MODEM_GNSS_EVT_PVT:
    		retval = nrf_modem_gnss_read(&last_pvt, sizeof(last_pvt), NRF_MODEM_GNSS_DATA_PVT);
    		if (retval == 0) {
    			k_sem_give(&pvt_data_sem);
    		}
    		break;
    
    #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    	case NRF_MODEM_GNSS_EVT_FIX:
    		/* Time to fix is calculated here, but it's printed from a delayed work to avoid
    		 * messing up the NMEA output.
    		 */
    		time_to_fix = (k_uptime_get() - fix_timestamp) / 1000.0;
    		k_work_schedule_for_queue(&gnss_work_q, &ttff_test_got_fix_work, K_MSEC(100));
    		k_work_schedule_for_queue(&gnss_work_q, &ttff_test_prepare_work,
    					  K_SECONDS(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_INTERVAL));
    		break;
    #endif /* CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */
    
    	case NRF_MODEM_GNSS_EVT_NMEA:
    		nmea_data = k_malloc(sizeof(struct nrf_modem_gnss_nmea_data_frame));
    		if (nmea_data == NULL) {
    			LOG_ERR("Failed to allocate memory for NMEA");
    			break;
    		}
    
    		retval = nrf_modem_gnss_read(nmea_data,
    					     sizeof(struct nrf_modem_gnss_nmea_data_frame),
    					     NRF_MODEM_GNSS_DATA_NMEA);
    		if (retval == 0) {
    			retval = k_msgq_put(&nmea_queue, &nmea_data, K_NO_WAIT);
    		}
    
    		if (retval != 0) {
    			k_free(nmea_data);
    		}
    		break;
    
    	case NRF_MODEM_GNSS_EVT_AGNSS_REQ:
    #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)
    		retval = nrf_modem_gnss_read(&last_agnss,
    					     sizeof(last_agnss),
    					     NRF_MODEM_GNSS_DATA_AGNSS_REQ);
    		if (retval == 0) {
    			k_work_submit_to_queue(&gnss_work_q, &agnss_data_get_work);
    		}
    #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */
    		break;
    
    	default:
    		break;
    	}
    }
    
    #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)
    #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND)
    K_SEM_DEFINE(lte_ready, 0, 1);
    
    static void lte_lc_event_handler(const struct lte_lc_evt *const evt)
    {
    	switch (evt->type) {
    	case LTE_LC_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)) {
    			LOG_INF("Connected to LTE network");
    			k_sem_give(&lte_ready);
    		}
    		break;
    
    	default:
    		break;
    	}
    }
    
    void lte_connect(void)
    {
    	int err;
    
    	LOG_INF("Connecting to LTE network");
    
    	err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_LTE);
    	if (err) {
    		LOG_ERR("Failed to activate LTE, error: %d", err);
    		return;
    	}
    
    	k_sem_take(&lte_ready, K_FOREVER);
    
    	/* Wait for a while, because with IPv4v6 PDN the IPv6 activation takes a bit more time. */
    	k_sleep(K_SECONDS(1));
    }
    
    void lte_disconnect(void)
    {
    	int err;
    
    	err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_LTE);
    	if (err) {
    		LOG_ERR("Failed to deactivate LTE, error: %d", err);
    		return;
    	}
    
    	LOG_INF("LTE disconnected");
    }
    #endif /* CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */
    
    static const char *get_system_string(uint8_t system_id)
    {
    	switch (system_id) {
    	case NRF_MODEM_GNSS_SYSTEM_INVALID:
    		return "invalid";
    
    	case NRF_MODEM_GNSS_SYSTEM_GPS:
    		return "GPS";
    
    	case NRF_MODEM_GNSS_SYSTEM_QZSS:
    		return "QZSS";
    
    	default:
    		return "unknown";
    	}
    }
    
    static void agnss_data_get_work_fn(struct k_work *item)
    {
    	ARG_UNUSED(item);
    
    	int err;
    
    	/* GPS data need is always expected to be present and first in list. */
    	__ASSERT(last_agnss.system_count > 0,
    		 "GNSS system data need not found");
    	__ASSERT(last_agnss.system[0].system_id == NRF_MODEM_GNSS_SYSTEM_GPS,
    		 "GPS data need not found");
    
    #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_SUPL)
    	/* SUPL doesn't usually provide NeQuick ionospheric corrections and satellite real time
    	 * integrity information. If GNSS asks only for those, the request should be ignored.
    	 */
    	if (last_agnss.system[0].sv_mask_ephe == 0 &&
    	    last_agnss.system[0].sv_mask_alm == 0 &&
    	    (last_agnss.data_flags & ~(NRF_MODEM_GNSS_AGNSS_NEQUICK_REQUEST |
    				       NRF_MODEM_GNSS_AGNSS_INTEGRITY_REQUEST)) == 0) {
    		LOG_INF("Ignoring assistance request for only NeQuick and/or integrity");
    		return;
    	}
    #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_SUPL */
    
    #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_MINIMAL)
    	/* With minimal assistance, the request should be ignored if no GPS time or position
    	 * is requested.
    	 */
    	if (!(last_agnss.data_flags & NRF_MODEM_GNSS_AGNSS_GPS_SYS_TIME_AND_SV_TOW_REQUEST) &&
    	    !(last_agnss.data_flags & NRF_MODEM_GNSS_AGNSS_POSITION_REQUEST)) {
    		LOG_INF("Ignoring assistance request because no GPS time or position is requested");
    		return;
    	}
    #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_MINIMAL */
    
    	if (last_agnss.data_flags == 0 &&
    	    last_agnss.system[0].sv_mask_ephe == 0 &&
    	    last_agnss.system[0].sv_mask_alm == 0) {
    		LOG_INF("Ignoring assistance request because only QZSS data is requested");
    		return;
    	}
    
    	requesting_assistance = true;
    
    	LOG_INF("Assistance data needed: data_flags: 0x%02x", last_agnss.data_flags);
    	for (int i = 0; i < last_agnss.system_count; i++) {
    		LOG_INF("Assistance data needed: %s ephe: 0x%llx, alm: 0x%llx",
    			get_system_string(last_agnss.system[i].system_id),
    			last_agnss.system[i].sv_mask_ephe,
    			last_agnss.system[i].sv_mask_alm);
    	}
    
    #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND)
    	lte_connect();
    #endif /* CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */
    
    	err = assistance_request(&last_agnss);
    	if (err) {
    		LOG_ERR("Failed to request assistance data");
    	}
    
    #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND)
    	lte_disconnect();
    #endif /* CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */
    
    	requesting_assistance = false;
    }
    #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */
    
    #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    static void ttff_test_got_fix_work_fn(struct k_work *item)
    {
    	LOG_INF("Time to fix: %.01f s", time_to_fix);
    	if (time_blocked > 0) {
    		LOG_INF("Time GNSS was blocked by LTE: %u s", time_blocked);
    	}
    	print_distance_from_reference(&last_pvt);
    	LOG_INF("Sleeping for %u s", CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_INTERVAL);
    }
    
    static int ttff_test_force_cold_start(void)
    {
    	int err;
    	uint32_t delete_mask;
    
    	LOG_INF("Deleting GNSS data");
    
    	/* Delete everything else except the TCXO offset. */
    	delete_mask = NRF_MODEM_GNSS_DELETE_EPHEMERIDES |
    		      NRF_MODEM_GNSS_DELETE_ALMANACS |
    		      NRF_MODEM_GNSS_DELETE_IONO_CORRECTION_DATA |
    		      NRF_MODEM_GNSS_DELETE_LAST_GOOD_FIX |
    		      NRF_MODEM_GNSS_DELETE_GPS_TOW |
    		      NRF_MODEM_GNSS_DELETE_GPS_WEEK |
    		      NRF_MODEM_GNSS_DELETE_UTC_DATA |
    		      NRF_MODEM_GNSS_DELETE_GPS_TOW_PRECISION;
    
    	/* With minimal assistance, we want to keep the factory almanac. */
    	if (IS_ENABLED(CONFIG_GNSS_SAMPLE_ASSISTANCE_MINIMAL)) {
    		delete_mask &= ~NRF_MODEM_GNSS_DELETE_ALMANACS;
    	}
    
    	err = nrf_modem_gnss_nv_data_delete(delete_mask);
    	if (err) {
    		LOG_ERR("Failed to delete GNSS data");
    		return -1;
    	}
    
    	return 0;
    }
    
    #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NRF_CLOUD)
    static bool qzss_assistance_is_supported(void)
    {
    	char resp[32];
    
    	if (nrf_modem_at_cmd(resp, sizeof(resp), "AT+CGMM") == 0) {
    		/* nRF9160 does not support QZSS assistance, while nRF91x1 do. */
    		if (strstr(resp, "nRF9160") != NULL) {
    			return false;
    		}
    	}
    
    	return true;
    }
    #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_NRF_CLOUD */
    
    static void ttff_test_prepare_work_fn(struct k_work *item)
    {
    	/* Make sure GNSS is stopped before next start. */
    	nrf_modem_gnss_stop();
    
    	if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_COLD_START)) {
    		if (ttff_test_force_cold_start() != 0) {
    			return;
    		}
    	}
    
    #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)
    	if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST_COLD_START)) {
    		/* All A-GNSS data is always requested before GNSS is started. */
    		last_agnss.data_flags =
    			NRF_MODEM_GNSS_AGNSS_GPS_UTC_REQUEST |
    			NRF_MODEM_GNSS_AGNSS_KLOBUCHAR_REQUEST |
    			NRF_MODEM_GNSS_AGNSS_NEQUICK_REQUEST |
    			NRF_MODEM_GNSS_AGNSS_GPS_SYS_TIME_AND_SV_TOW_REQUEST |
    			NRF_MODEM_GNSS_AGNSS_POSITION_REQUEST |
    			NRF_MODEM_GNSS_AGNSS_INTEGRITY_REQUEST;
    		last_agnss.system_count = 1;
    		last_agnss.system[0].sv_mask_ephe = 0xffffffff;
    		last_agnss.system[0].sv_mask_alm = 0xffffffff;
    #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NRF_CLOUD)
    		if (qzss_assistance_is_supported()) {
    			last_agnss.system_count = 2;
    			last_agnss.system[1].sv_mask_ephe = 0x3ff;
    			last_agnss.system[1].sv_mask_alm = 0x3ff;
    		}
    #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_NRF_CLOUD */
    
    		k_work_submit_to_queue(&gnss_work_q, &agnss_data_get_work);
    	} else {
    		/* Start and stop GNSS to trigger possible A-GNSS data request. If new A-GNSS
    		 * data is needed it is fetched before GNSS is started.
    		 */
    		nrf_modem_gnss_start();
    		nrf_modem_gnss_stop();
    	}
    #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */
    
    	k_work_submit_to_queue(&gnss_work_q, &ttff_test_start_work);
    }
    
    static void ttff_test_start_work_fn(struct k_work *item)
    {
    	LOG_INF("Starting GNSS");
    	if (nrf_modem_gnss_start() != 0) {
    		LOG_ERR("Failed to start GNSS");
    		return;
    	}
    
    	fix_timestamp = k_uptime_get();
    	time_blocked = 0;
    }
    #endif /* CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */
    
    static void date_time_evt_handler(const struct date_time_evt *evt)
    {
    	k_sem_give(&time_sem);
    }
    
    static int modem_init(void)
    {
    	if (IS_ENABLED(CONFIG_DATE_TIME)) {
    		date_time_register_handler(date_time_evt_handler);
    	}
    
    #if defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND)
    	lte_lc_register_handler(lte_lc_event_handler);
    #elif !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)
    	lte_lc_psm_req(true);
    
    	LOG_INF("Connecting to LTE network");
    
    	if (lte_lc_connect() != 0) {
    		LOG_ERR("Failed to connect to LTE network");
    		return -1;
    	}
    
    	LOG_INF("Connected to LTE network");
    
    	if (IS_ENABLED(CONFIG_DATE_TIME)) {
    		LOG_INF("Waiting for current time");
    
    		/* Wait for an event from the Date Time library. */
    		k_sem_take(&time_sem, K_MINUTES(10));
    
    		if (!date_time_is_valid()) {
    			LOG_WRN("Failed to get current time, continuing anyway");
    		}
    	}
    #endif
    
    	return 0;
    }
    
    static int sample_init(void)
    {
    	int err = 0;
    
    #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    	struct k_work_queue_config cfg = {
    		.name = "gnss_work_q",
    		.no_yield = false
    	};
    
    	k_work_queue_start(
    		&gnss_work_q,
    		gnss_workq_stack_area,
    		K_THREAD_STACK_SIZEOF(gnss_workq_stack_area),
    		GNSS_WORKQ_THREAD_PRIORITY,
    		&cfg);
    #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE || CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */
    
    #if !defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)
    	k_work_init(&agnss_data_get_work, agnss_data_get_work_fn);
    
    	err = assistance_init(&gnss_work_q);
    #endif /* !CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE */
    
    #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    	k_work_init_delayable(&ttff_test_got_fix_work, ttff_test_got_fix_work_fn);
    	k_work_init_delayable(&ttff_test_prepare_work, ttff_test_prepare_work_fn);
    	k_work_init(&ttff_test_start_work, ttff_test_start_work_fn);
    #endif /* CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */
    
    	return err;
    }
    
    static int gnss_init_and_start(void)
    {
    #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND)
    	/* Enable GNSS. */
    	if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS) != 0) {
    		LOG_ERR("Failed to activate GNSS functional mode");
    		return -1;
    	}
    #endif /* CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE || CONFIG_GNSS_SAMPLE_LTE_ON_DEMAND */
    
    	/* Configure GNSS. */
    	if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) {
    		LOG_ERR("Failed to set GNSS event handler");
    		return -1;
    	}
    
    	/* Enable all supported NMEA messages. */
    	uint16_t nmea_mask = NRF_MODEM_GNSS_NMEA_RMC_MASK |
    			     NRF_MODEM_GNSS_NMEA_GGA_MASK |
    			     NRF_MODEM_GNSS_NMEA_GLL_MASK |
    			     NRF_MODEM_GNSS_NMEA_GSA_MASK |
    			     NRF_MODEM_GNSS_NMEA_GSV_MASK;
    
    	if (nrf_modem_gnss_nmea_mask_set(nmea_mask) != 0) {
    		LOG_ERR("Failed to set GNSS NMEA mask");
    		return -1;
    	}
    
    	/* Make QZSS satellites visible in the NMEA output. */
    	if (nrf_modem_gnss_qzss_nmea_mode_set(NRF_MODEM_GNSS_QZSS_NMEA_MODE_CUSTOM) != 0) {
    		LOG_WRN("Failed to enable custom QZSS NMEA mode");
    	}
    
    	/* This use case flag should always be set. */
    	uint8_t use_case = NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START;
    
    	if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_PERIODIC) &&
    	    !IS_ENABLED(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE)) {
    		/* Disable GNSS scheduled downloads when assistance is used. */
    		use_case |= NRF_MODEM_GNSS_USE_CASE_SCHED_DOWNLOAD_DISABLE;
    	}
    
    	if (IS_ENABLED(CONFIG_GNSS_SAMPLE_LOW_ACCURACY)) {
    		use_case |= NRF_MODEM_GNSS_USE_CASE_LOW_ACCURACY;
    	}
    
    	if (nrf_modem_gnss_use_case_set(use_case) != 0) {
    		LOG_WRN("Failed to set GNSS use case");
    	}
    
    #if defined(CONFIG_NRF_CLOUD_AGNSS_ELEVATION_MASK)
    	if (nrf_modem_gnss_elevation_threshold_set(CONFIG_NRF_CLOUD_AGNSS_ELEVATION_MASK) != 0) {
    		LOG_ERR("Failed to set elevation threshold");
    		return -1;
    	}
    	LOG_DBG("Set elevation threshold to %u", CONFIG_NRF_CLOUD_AGNSS_ELEVATION_MASK);
    #endif
    
    #if defined(CONFIG_GNSS_SAMPLE_MODE_CONTINUOUS)
    	/* Default to no power saving. */
    	uint8_t power_mode = NRF_MODEM_GNSS_PSM_DISABLED;
    
    #if defined(CONFIG_GNSS_SAMPLE_POWER_SAVING_MODERATE)
    	power_mode = NRF_MODEM_GNSS_PSM_DUTY_CYCLING_PERFORMANCE;
    #elif defined(CONFIG_GNSS_SAMPLE_POWER_SAVING_HIGH)
    	power_mode = NRF_MODEM_GNSS_PSM_DUTY_CYCLING_POWER;
    #endif
    
    	if (nrf_modem_gnss_power_mode_set(power_mode) != 0) {
    		LOG_ERR("Failed to set GNSS power saving mode");
    		return -1;
    	}
    #endif /* CONFIG_GNSS_SAMPLE_MODE_CONTINUOUS */
    
    	/* Default to continuous tracking. */
    	uint16_t fix_retry = 0;
    	uint16_t fix_interval = 1;
    
    #if defined(CONFIG_GNSS_SAMPLE_MODE_PERIODIC)
    	fix_retry = CONFIG_GNSS_SAMPLE_PERIODIC_TIMEOUT;
    	fix_interval = CONFIG_GNSS_SAMPLE_PERIODIC_INTERVAL;
    #elif defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    	/* Single fix for TTFF test mode. */
    	fix_retry = 0;
    	fix_interval = 0;
    #endif
    
    	if (nrf_modem_gnss_fix_retry_set(fix_retry) != 0) {
    		LOG_ERR("Failed to set GNSS fix retry");
    		return -1;
    	}
    
    	if (nrf_modem_gnss_fix_interval_set(fix_interval) != 0) {
    		LOG_ERR("Failed to set GNSS fix interval");
    		return -1;
    	}
    
    #if defined(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)
    	k_work_schedule_for_queue(&gnss_work_q, &ttff_test_prepare_work, K_NO_WAIT);
    #else /* !CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST */
    	if (nrf_modem_gnss_start() != 0) {
    		LOG_ERR("Failed to start GNSS");
    		return -1;
    	}
    #endif
    
    	return 0;
    }
    
    static bool output_paused(void)
    {
    #if defined(CONFIG_GNSS_SAMPLE_ASSISTANCE_NONE) || defined(CONFIG_GNSS_SAMPLE_LOG_LEVEL_OFF)
    	return false;
    #else
    	return (requesting_assistance || assistance_is_active()) ? true : false;
    #endif
    }
    
    static void print_satellite_stats(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	uint8_t tracked   = 0;
    	uint8_t in_fix    = 0;
    	uint8_t unhealthy = 0;
    
    	for (int i = 0; i < NRF_MODEM_GNSS_MAX_SATELLITES; ++i) {
    		if (pvt_data->sv[i].sv > 0) {
    			tracked++;
    
    			if (pvt_data->sv[i].flags & NRF_MODEM_GNSS_SV_FLAG_USED_IN_FIX) {
    				in_fix++;
    			}
    
    			if (pvt_data->sv[i].flags & NRF_MODEM_GNSS_SV_FLAG_UNHEALTHY) {
    				unhealthy++;
    			}
    		}
    	}
    
    	printf("Tracking: %2d Using: %2d Unhealthy: %d\n", tracked, in_fix, unhealthy);
    }
    
    static void print_flags(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	if (pvt_data->flags & NRF_MODEM_GNSS_PVT_FLAG_DEADLINE_MISSED) {
    		printf("GNSS operation blocked by LTE\n");
    	}
    	if (pvt_data->flags & NRF_MODEM_GNSS_PVT_FLAG_NOT_ENOUGH_WINDOW_TIME) {
    		printf("Insufficient GNSS time windows\n");
    	}
    	if (pvt_data->flags & NRF_MODEM_GNSS_PVT_FLAG_SLEEP_BETWEEN_PVT) {
    		printf("Sleep period(s) between PVT notifications\n");
    	}
    	if (pvt_data->flags & NRF_MODEM_GNSS_PVT_FLAG_SCHED_DOWNLOAD) {
    		printf("Scheduled navigation data download\n");
    	}
    }
    
    static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	printf("Latitude:          %.06f\n", pvt_data->latitude);
    	printf("Longitude:         %.06f\n", pvt_data->longitude);
    	printf("Accuracy:          %.01f m\n", (double)pvt_data->accuracy);
    	printf("Altitude:          %.01f m\n", (double)pvt_data->altitude);
    	printf("Altitude accuracy: %.01f m\n", (double)pvt_data->altitude_accuracy);
    	printf("Speed:             %.01f m/s\n", (double)pvt_data->speed);
    	printf("Speed accuracy:    %.01f m/s\n", (double)pvt_data->speed_accuracy);
    	printf("V. speed:          %.01f m/s\n", (double)pvt_data->vertical_speed);
    	printf("V. speed accuracy: %.01f m/s\n", (double)pvt_data->vertical_speed_accuracy);
    	printf("Heading:           %.01f deg\n", (double)pvt_data->heading);
    	printf("Heading accuracy:  %.01f deg\n", (double)pvt_data->heading_accuracy);
    	printf("Date:              %04u-%02u-%02u\n",
    	       pvt_data->datetime.year,
    	       pvt_data->datetime.month,
    	       pvt_data->datetime.day);
    	printf("Time (UTC):        %02u:%02u:%02u.%03u\n",
    	       pvt_data->datetime.hour,
    	       pvt_data->datetime.minute,
    	       pvt_data->datetime.seconds,
    	       pvt_data->datetime.ms);
    // 	printf("PDOP:              %.01f\n", (double)pvt_data->pdop);
    // 	printf("HDOP:              %.01f\n", (double)pvt_data->hdop);
    // 	printf("VDOP:              %.01f\n", (double)pvt_data->vdop);
    // 	printf("TDOP:              %.01f\n", (double)pvt_data->tdop);
     }
    
    int main(void)
    {
    	int err;
    	uint8_t cnt = 0;
    	struct nrf_modem_gnss_nmea_data_frame *nmea_data;
    
    	LOG_INF("Starting GNSS sample");
    
    	err = nrf_modem_lib_init();
    	if (err) {
    		LOG_ERR("Modem library initialization failed, error: %d", err);
    		return err;
    	}
    
    	/* Initialize reference coordinates (if used). */
    	if (sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE) > 1 &&
    	    sizeof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE) > 1) {
    		ref_used = true;
    		ref_latitude = atof(CONFIG_GNSS_SAMPLE_REFERENCE_LATITUDE);
    		ref_longitude = atof(CONFIG_GNSS_SAMPLE_REFERENCE_LONGITUDE);
    	}
    
    	if (modem_init() != 0) {
    		LOG_ERR("Failed to initialize modem");
    		return -1;
    	}
    
    	if (sample_init() != 0) {
    		LOG_ERR("Failed to initialize sample");
    		return -1;
    	}
    
    	if (gnss_init_and_start() != 0) {
    		LOG_ERR("Failed to initialize and start GNSS");
    		return -1;
    	}
    
    	fix_timestamp = k_uptime_get();
    
    	for (;;) {
    		(void)k_poll(events, 2, K_FOREVER);
    
    		if (events[0].state == K_POLL_STATE_SEM_AVAILABLE &&
    		    k_sem_take(events[0].sem, K_NO_WAIT) == 0) {
    			/* New PVT data available */
    
    			if (IS_ENABLED(CONFIG_GNSS_SAMPLE_MODE_TTFF_TEST)) {
    				/* TTFF test mode. */
    
    				/* Calculate the time GNSS has been blocked by LTE. */
    				if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_DEADLINE_MISSED) {
    					time_blocked++;
    				}
    			} else if (IS_ENABLED(CONFIG_GNSS_SAMPLE_NMEA_ONLY)) {
    				/* NMEA-only output mode. */
    
    				if (output_paused()) {
    					goto handle_nmea;
    				}
    
    				if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
    					print_distance_from_reference(&last_pvt);
    				}
    			} else {
    				/* PVT and NMEA output mode. */
    
    				if (output_paused()) {
    					goto handle_nmea;
    				}
    
    				printf("\033[1;1H");
    				printf("\033[2J");
    				print_satellite_stats(&last_pvt);
    				print_flags(&last_pvt);
    				printf("-----------------------------------\n");
    
    				if (last_pvt.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
    					fix_timestamp = k_uptime_get();
    					print_fix_data(&last_pvt);
    					print_distance_from_reference(&last_pvt);
    				} else {
    					printf("Seconds since last fix: %d\n",
    					       (uint32_t)((k_uptime_get() - fix_timestamp) / 1000));
    					cnt++;
    					printf("Searching [%c]\n", update_indicator[cnt%4]);
    				}
    
    				printf("\nNMEA strings:\n\n");
    			}
    		}
    
    handle_nmea:
    		if (events[1].state == K_POLL_STATE_MSGQ_DATA_AVAILABLE &&
    		    k_msgq_get(events[1].msgq, &nmea_data, K_NO_WAIT) == 0) {
    			/* New NMEA data available */
    
    			if (!output_paused()) {
    				printf("%s", nmea_data->nmea_str);
    			}
    			k_free(nmea_data);
    		}
    
    		events[0].state = K_POLL_STATE_NOT_READY;
    		events[1].state = K_POLL_STATE_NOT_READY;
    	}
    
    	return 0;
    }
    

    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    
    # Enable RTT Console and Logging
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_RTT_CONSOLE=y
    CONFIG_LOG_BACKEND_RTT=y
    CONFIG_LOG_BACKEND_UART=n
    
    # General
    CONFIG_FPU=y
    CONFIG_NRF_MODEM_LIB=y
    CONFIG_STDOUT_CONSOLE=y
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_PICOLIBC_IO_FLOAT=y
    CONFIG_LOG=y
    CONFIG_LOG_MODE_IMMEDIATE=y
    
    # GNSS sample
    # Enable to use nRF Cloud A-GNSS
    CONFIG_NRF_CLOUD=y
    CONFIG_GNSS_SAMPLE_ASSISTANCE_NRF_CLOUD=n
    
    # LTE Link Control
    CONFIG_LTE_LINK_CONTROL=y
    # Request eDRX from the network
    CONFIG_LTE_LC_EDRX_MODULE=y
    CONFIG_LTE_EDRX_REQ=y
    # PSM requested periodic TAU 8 hours
    CONFIG_LTE_LC_PSM_MODULE=y
    CONFIG_LTE_PSM_REQ_RPTAU="00101000"
    # PSM requested active time 6 seconds
    CONFIG_LTE_PSM_REQ_RAT="00000011"
    
    # AT Host library - Used to send AT commands directy from an UART terminal and to allow
    #		    integration with nRF Connect for Desktop LTE Link monitor application.
    CONFIG_AT_HOST_LIBRARY=y
    
    # Networking
    CONFIG_NETWORKING=y
    CONFIG_NET_SOCKETS_OFFLOAD=y
    CONFIG_NET_SOCKETS=y
    CONFIG_POSIX_API=y
    # Disable native network stack to save some memory
    CONFIG_NET_NATIVE=n
    
    # Memory and stack configuration
    CONFIG_HEAP_MEM_POOL_SIZE=2048
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1536
    

    Best regards,
    Arun

  • Hi Arun,

    I am testing the GNSS sample from nRF Connect SDK v3.0.0.
    When I flash and run the firmware, I see the following output in RTT Viewer:
    Arun538 said:
    I’ve attached my main.c and prj.conf files — could you please check and let me know if anything is missing or needs to be modified?

    I have tested GNSS application with your main.c file in NCS v3.0.0. I got build error when using your main.c file but building worked fine when using main.c from GNSS sample. You could try to look for any changes between unmodified sample and your application.

    Arun538 said:
    I uploaded the firmware to my custom board using the nRF9151 DK as a programmer.
    Arun538 said:
    I’m using the nRF52 DK as a programmer to flash my nRF9151 board.

    Which device did you use for programming?

    Best regards,
    Dejan

  • Hi Dejan,

    When I run the unmodified GNSS sample, I don’t see any logs in the RTT Viewer.


    However, when I add the following lines to the prj.conf file:

    CONFIG_USE_SEGGER_RTT=y
    CONFIG_RTT_CONSOLE=y
    CONFIG_LOG_BACKEND_RTT=y

    I can see the log output, but then I get error.

    I’m using the nRF52 DK (PCA10040) — the Development Kit for the nRF52810 and nRF52832 SoCs — as a programmer to flash my nRF9151 custom board.

    Best regards,
    Arun

  • Hi Arun,

    Arun538 said:
    When I run the unmodified GNSS sample, I don’t see any logs in the RTT Viewer.

    If you do not modify the sample, you can use your terminal emulator program to connect to available COM port to see the output.

    Best regards,
    Dejan

Reply Children
  • Hi Dejan,

    I tried connecting to all the available COM ports using different terminal programs (like PuTTY, serial terminal and Tera Term), but I’m still not getting any serial output from my custom nRF9151 board. That’s why I switched to RTT Viewer to check if any logs were available.

  • Hi Dejan,

    Can we please connect on a call? I’m running behind schedule and really need to complete this project.
    Please help me when you’re available — I’ll be available until 10 PM (India time).

    Thank you for your support.

    Best regards,
    Arun

  • Hi Arun,

    Maybe you have older version of nRF52-dk. Your nrf52-dk should have nrf5340 on it. You could try to program your board using either newer nrf52-dk or for example nrf9151-dk.

    Best regards,
    Dejan

  • Hi Dejan,

    When I try to connect my custom board to the NRF52 DK, it connects and I am able to upload code.

    15:09:08.717	Using nrfutil device to communicate with target via JLink
    15:09:08.717	JLink OB firmware version J-Link OB-nRF5340-NordicSemi compiled Jul 8 2025 10:15:34
    15:09:08.717	Device family NRF52_FAMILY
    15:09:08.717	Device version NRF9151_xxCA_REV3
    15:09:08.717	Board version PCA10040
    15:09:08.903	Reading readback protection status for Application core
    15:09:08.904	Reading readback protection status for Application core 0%
    15:09:08.905	Reading readback protection status for Application core 100%
    15:09:08.905	Application core protection status 'NRFDL_PROTECTION_STATUS_NONE'
    15:09:08.906	Reading readback protection status for Application core completed
    15:09:09.142	Loading core information for Application core
    15:09:09.143	Loading core information for Application core 0%
    15:09:09.143	Loading core information for Application core 100%
    15:09:09.145	Loading core information for Application core completed
    15:09:09.629	Reading readback protection status for Application core
    15:09:09.629	Reading readback protection status for Application core 0%
    15:09:09.631	Reading readback protection status for Application core 100%
    15:09:09.631	Application core protection status 'NRFDL_PROTECTION_STATUS_NONE'
    15:09:09.631	Reading readback protection status for Application core completed
    15:09:09.682	Device is loaded and ready for further operation


    However, when I try to connect my custom board to the NRF9151 DK, it does not connect and shows this error.

    15:14:04.396	Initialising the bundled nrfutil device
    15:14:04.555	Using the bundled core version for nrfutil device: 8.0.0
    15:14:04.583	Using nrfutil-device version: 2.12.3
    15:14:04.584	Using nrf-device-lib version: 0.17.81
    15:14:04.584	Using nrf-probe version: 0.40.1
    15:14:04.584	Using JLink version: JLink_V8.76
    15:14:04.584	Your version of SEGGER J-Link (8.76) is newer than the one this app was tested with (8.18). The tested version is not required, and your J-Link version will most likely work fine. If you get issues related to J-Link with your devices, use the tested version.
    15:14:04.601	Getting serial port options from the persistent store for 001051231268.pc-nrfconnect-programmer
    15:14:04.602	Device connected with the serial number 001051231268
    15:14:06.422	Selecting device with the serial number 001051231268
    15:14:06.801	Error: Failed with exit code 1. One or more device info tasks failed: * 1051231268: Device error: Setting the debug port SELECT register failed while powering up sys and debug regions (Unknown Error in J-Link DLL (error code =-1)). This might indicate that the debug port is unavailable. Please double-check device power supply and SWD lines, and that SWD isn't disabled (Generic) Message: Operation device-info failed, Device error: Setting the debug port SELECT register failed while powering up sys and debug regions (Unknown Error in J-Link DLL (error code =-1)). This might indicate that the debug port is unavailable. Please double-check device power supply and SWD lines, and that SWD isn't disabled.
    15:14:06.801	Selected device with the serial number 001051231268
    15:14:06.802	Using nrfutil device to communicate with target via JLink
    15:14:07.085	Reading readback protection status for Application core
    15:14:07.086	Reading readback protection status for Application core 0%
    15:14:07.211	Failed "reading readback protection status for application core". Error: code: 1, description: Generic, message: Batch task protection-get failed, Device error: Setting the debug port SELECT register failed while powering up sys and debug regions (Unknown Error in J-Link DLL (error code =-1)). This might indicate that the debug port is unavailable. Please double-check device power supply and SWD lines, and that SWD isn't disabled
    15:14:07.228	Error: Failed with exit code 1. One or more batch tasks failed: * 1051231268: Device error: Setting the debug port SELECT register failed while powering up sys and debug regions (Unknown Error in J-Link DLL (error code =-1)). This might indicate that the debug port is unavailable. Please double-check device power supply and SWD lines, and that SWD isn't disabled (Generic) Message: Batch task protection-get failed, Device error: Setting the debug port SELECT register failed while powering up sys and debug regions (Unknown Error in J-Link DLL (error code =-1)). This might indicate that the debug port is unavailable. Please double-check device power supply and SWD lines, and that SWD isn't disabled.
    15:14:07.228	Error: Failed with exit code 1. One or more batch tasks failed: * 1051231268: Device error: Setting the debug port SELECT register failed while powering up sys and debug regions (Unknown Error in J-Link DLL (error code =-1)). This might indicate that the debug port is unavailable. Please double-check device power supply and SWD lines, and that SWD isn't disabled (Generic) Message: Batch task protection-get failed, Device error: Setting the debug port SELECT register failed while powering up sys and debug regions (Unknown Error in J-Link DLL (error code =-1)). This might indicate that the debug port is unavailable. Please double-check device power supply and SWD lines, and that SWD isn't disabled.

    Best regards,
    Arun

  • Hi Arun,

    You could try to recover your device using nrfutil as indicated in this ticket
    You could also try to double-check power supply and inspect SWD lines. Have a look at this thread.

    Best regards,
    Dejan

Related