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

nRF9160 device functionality after a week

Hi,

I'm using latest master branch of nRF Connect SDK and pre-released modem FW 1.1.2 which is including ANT->AUX switching. I'm developing a firmware for a custom board that has nRF9160 SiP.

I would like to set the device to start GPS once a week. I have read the Date-Time Library and wondered if it's possible to use that library to set the device to start GPS at the specific time. Does anyone any suggestions how to do that?

But for now I have done it with k_delayed_work_submit_to_queue() and set the delay to one week. One week is 168 hours but that value is not working, I tested some different values and noticed that 163h is the maximum that is working in that function. If the value is 164 hours or more it seems to start the work immediately.

Why is that happening? Is there any other way to get 168 hours working than for example adding another delayed work with 8 hours to queue after 160 hours?

Here is some parts of the code:

static int gps_start_delay_hours = 160;		// one week - 8 hours

/* Stack definition for application workqueue */
K_THREAD_STACK_DEFINE(application_stack_area,
			CONFIG_APPLICATION_WORKQUEUE_STACK_SIZE);		// 2048
static struct k_work_q application_work_q;

static struct k_delayed_work start_gps_work;


/**@brief Callback for GPS events */
static void gps_handler(struct device *dev, struct gps_event *evt)
{
    ...
	case GPS_EVT_SEARCH_STOPPED:
		LOG_INF("GPS_EVT_SEARCH_STOPPED");
		gps_control_set_active(false);

		if (gps_failed_fix_attempts >= CONFIG_GPS_CONTROL_MAX_FAILED_FIX_ATTEMPTS) {
            k_delayed_work_submit_to_queue(&application_work_q,
                    &start_gps_work, K_HOURS(gps_start_delay_hours));
		}

		break;
    ...
}

/**@brief Start GPS. */
static void start_gps(struct k_work *work)
{
	gps_control(1);
}

void main(void)
{
    ...
	k_work_q_start(&application_work_q, application_stack_area,
			K_THREAD_STACK_SIZEOF(application_stack_area),
			CONFIG_APPLICATION_WORKQUEUE_PRIORITY);

    k_delayed_work_init(&start_gps_work, start_gps);
    ...
}

Regards,
Tero

Parents Reply Children
  • I played around with the Date-Time Library. I did the following to make it work

    Used an already working nrf9160 project that connects to the network (I used http_application_update)

    • In prj.conf I added these configs:

    CONFIG_DATE_TIME=y
    CONFIG_DATE_TIME_UPDATE_INTERVAL_SECONDS=10

    • At the top of main.c, I included the Date-Time header file:

    #include <date_time.h>

    • In main(), after modem configuration and connection to the network, I added these lines:

    s64_t date_time_stamp;
    .
    .
    .
    k_sleep(25000); //Wait some time to make sure the Date-Time update has happened
    date_time_now(&date_time_stamp); 
    printk("Date time: %016llX\n", date_time_stamp);

    Then I got the following log:

    E: getaddrinfo, error: -11
    E: Not getting time from any NTP server
    LTE Link Connected!
    I: Time successfully obtained (Log added by me in date_time.c)
    Date time: 00000172042bf014

    The timestamp 0x172042bf014 equals 1,589,207,887,892 and gives the dateMon 11 May 2020
    16:38:07, which is correct

    Best regards,

    Simon

  • I did that almost the same way. I'm getting the current time from date_time_now() after date_time_update() and then calculating the time to the target time and using k_delayed_work_submit_to_queue() which is split to 12h periods as minutes, and when the remaining time is shorter than 12h I'm then using the remaining time in k_delayed_work_submit_to_queue(). 

    EDIT: I once verified your answer as a solution but it closed this case so I rejected it. I would like to have an answer for the following and then I could close the case: 
    Any idea will that k_delayed_work_submit_to_queue() be fixed to support longer periods so we shouldn't use the split timer?

    But thanks for the help to this point!

    BR,
    Tero

  • I am sorry for the delay. But when the answer is verified, it is removed from my stack of cases, and that is the reason I haven't answered. I just happen to stumble upon this by accident.

    However, I'll put in a feature request in Devzone that the case is reopened and visible for if the customer rejects it.

    I will look into your issue on the next working day (which is Tuesday due to Norwegian holiday on Monday).

    Best regards,

    Simon

  • Okay, I've figured out what's causing the issue

    • First k_delayed_work_submit_to_queue(&my_work_q, &my_device.work, K_HOURS(160)) is called
      • Where K_HOURS(160) equals 576000000
    • Then k_delayed_work_submit_to_queue()-->k_ms_to_ticks_ceil32(576000000) is called
    • Then k_ms_to_ticks_ceil32()-->z_tmcvt(t, Z_HZ_ms, Z_HZ_ticks...) is called
      • t equals 576000000
      • Z_HZ_ms equals
      • Z_HZ_ticks equals 32768
    • Eventually, this line is returned, which will convert the timeout to ticks. However, the number of ticks calculated will exceed what a u32_t type can store
      • t * to_hz + off) / from_hz = (576 000 000 * 32768 + 999)/1000 = 18874368000 ticks
        • This is bigger than 2,147,483,647, which I mentioned earlier in my reply
      • When converted to u32_t type, it will be equal to 1694498816 ticks (this is what I got when logging it)
      • This will lead to a timeout of (1694498816 ticks)/(32768 ticks/sec) = 51,712‬ seconds = 14.36 hours

    I just figured out that this seems to be fixed in the master branch, where the ticks are stored in k_timeout_t-->k_ticks_t, which can hold up to 64 bits instead of 32 bits.

    Just make sure CONFIG_TIMEOUT_64BIT is enabled.

    Best regards,

    Simon

Related