Hi
I'm doing a project using the TimeSync library (latest version) on 2 nRF52832 development boards.
I've ported the library to my project, the time synchronization works, but when using a too short interval when calling ts_set_trigger() in the ts_evt_callback() function, the application does one of two things after some time:
- ts_set_trigger() gets executed but suddenly doesn't generate a TS_EVT_TRIGGERED event anymore.
- TS_EVT_DESYNCHRONIZED occurs and triggering stopped
When using a larger trigger period of 20*2.5 ms = 50 ms, for example, the application runs without a problem for days.
The previous version of the TimeSync library didn't have this problem (since it was using compare registers and PPI directly to toggle a GPIO, without event callbacks).
Ideally, we'd like to get a TS_EVT_TRIGGERED event every 1 ms. (By adjusting TIME_SYNC_TIMER_MAX_VAL to 16000.)
I've tried changing the TIME_SYNC_EVT_HANDLER_IRQ_PRIORITY to a higher priority, without success.
A potential hypothesis: From this case, we see that there due to a corner case the timer on the central gets sampled incorrectly. This causes the timer on the receiver to be set incorrectly, and potentially setting the ts_set_trigger() compare value to a value in the past.
In my test setup the following parameters were used:
#ifndef TS_SOC_OBSERVER_PRIO #define TS_SOC_OBSERVER_PRIO 0 #endif #ifndef TIME_SYNC_TIMER_MAX_VAL #define TIME_SYNC_TIMER_MAX_VAL (40000) // #define TIME_SYNC_TIMER_MAX_VAL (16000) #endif #ifndef TIME_SYNC_RTC_MAX_VAL #define TIME_SYNC_RTC_MAX_VAL (0xFFFFFF) #endif #ifndef TIME_SYNC_DESYNC_TIMEOUT #define TIME_SYNC_DESYNC_TIMEOUT 10000000 /* Timeout for desynchronization [us] */ #endif #ifndef TIME_SYNC_TX_OFFSET_REALIGN_TIMEOUT #define TIME_SYNC_TX_OFFSET_REALIGN_TIMEOUT 10000000 /* Set to 0 to disable [us] */ #endif #ifndef TIME_SYNC_EVT_HANDLER_IRQ_PRIORITY #define TIME_SYNC_EVT_HANDLER_IRQ_PRIORITY 7 /* Priority of event handler */ #endif
static void ts_imu_trigger_enable(void)
{
uint64_t time_now_ticks;
uint32_t time_now_msec;
uint32_t time_target;
uint32_t err_code;
if (m_imu_trigger_enabled)
{
return;
}
// Round up to nearest second to next 1000 ms to start toggling.
// If the receiver has received a valid sync packet within this time, the GPIO toggling polarity will be the same.
time_now_ticks = ts_timestamp_get_ticks_u64();
time_now_msec = TIME_SYNC_TIMESTAMP_TO_USEC(time_now_ticks) / 1000;
time_target = TIME_SYNC_MSEC_TO_TICK(time_now_msec) + (1000 * 2);
time_target = (time_target / 1000) * 1000;
err_code = ts_set_trigger(time_target, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_3));
APP_ERROR_CHECK(err_code);
nrf_gpiote_task_set(NRF_GPIOTE_TASKS_CLR_3);
m_imu_trigger_enabled = true;
}
static void ts_imu_trigger_disable(void)
{
m_imu_trigger_enabled = false;
}
static void ts_evt_callback(const ts_evt_t* evt)
{
NRF_LOG_INFO("ts_evt_callback");
APP_ERROR_CHECK_BOOL(evt != NULL);
switch (evt->type)
{
case TS_EVT_SYNCHRONIZED:
NRF_LOG_INFO("TS_EVT_SYNCHRONIZED");
ts_imu_trigger_enable();
break;
case TS_EVT_DESYNCHRONIZED:
NRF_LOG_INFO("TS_EVT_DESYNCHRONIZED");
ts_imu_trigger_disable();
break;
case TS_EVT_TRIGGERED:
// NRF_LOG_INFO("TS_EVT_TRIGGERED");
if (m_imu_trigger_enabled)
{
uint32_t tick_target;
tick_target = evt->params.triggered.tick_target + 2;
uint32_t time;
time = TIME_SYNC_TIMESTAMP_TO_USEC(tick_target) / 1000;
NRF_LOG_INFO("target %d", tick_target);
uint32_t err_code = ts_set_trigger(tick_target, nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_3));
if(err_code != NRF_SUCCESS)
{
NRF_LOG_INFO("err_code: %d", err_code);
}
APP_ERROR_CHECK(err_code);
}
else
{
// Ensure pin is low when triggering is stopped
nrf_gpiote_task_set(NRF_GPIOTE_TASKS_CLR_3);
NRF_LOG_INFO("Triggering stopped");
}
uint64_t time_now_ticks;
uint32_t time_now_msec;
time_now_ticks = ts_timestamp_get_ticks_u64();
time_now_msec = TIME_SYNC_TIMESTAMP_TO_USEC(time_now_ticks) / 1000;
NRF_LOG_INFO("now %d", TIME_SYNC_MSEC_TO_TICK(time_now_msec));
break;
default:
APP_ERROR_CHECK_BOOL(false);
break;
}
}
static void sync_timer_init(void)
{
uint32_t err_code;
// Debug pin:
// nRF52-DK (PCA10040) Toggle P0.24 from sync timer to allow pin measurement
// nRF52840-DK (PCA10056) Toggle P1.14 from sync timer to allow pin measurement
#if defined(BOARD_PCA10040)
nrf_gpiote_task_configure(3, NRF_GPIO_PIN_MAP(0, 24), NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(3);
#elif defined(BOARD_PCA10056)
nrf_gpiote_task_configure(3, NRF_GPIO_PIN_MAP(1, 14), NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(3);
#else
#warning Debug pin not set
#endif
ts_init_t init_ts =
{
.high_freq_timer[0] = NRF_TIMER3,
.high_freq_timer[1] = NRF_TIMER4,
.egu = NRF_EGU3,
.egu_irq_type = SWI3_EGU3_IRQn,
.evt_handler = ts_evt_callback,
};
err_code = ts_init(&init_ts);
APP_ERROR_CHECK(err_code);
ts_rf_config_t rf_config =
{
.rf_chn = 80,
.rf_addr = { 0xDE, 0xAD, 0xBE, 0xEF, 0x19 }
};
err_code = ts_enable(&rf_config);
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("Started listening for beacons.\r\n");
NRF_LOG_INFO("Press Button 1 to start transmitting sync beacons\r\n");
NRF_LOG_INFO("GPIO toggling will begin when transmission has started.\r\n");
}
Any help would be appreciated!