Unexplained power consumption when MPSL Timeslots are scheduled

My application flashes an LED periodically, and I would like to synchronize the LED flashing with radio idle time in order to minimize max current draw. It seems that using MPSL Timeslots  is the preferred method. Using timeslots appears to be working in that I can schedule my LED on time to occur when the radio is idle. Unfortunately, it appears that there is increased power consumption during the time between radio events up until my work is to be scheduled.

In my first test case (non-mpsl.png), I setup for slow advertising (1s), and I flash an LED briefly every 2 seconds. As can be seen, the power consumption rises when the LED is active, but is otherwise low, except for periodic radio events (advertisement).

In my second test case, instead of flashing the LED based upon a timer, I schedule an MPSL timeslot. The LED flashing occurs as expected, but I noticed that during the time between radio events for which my code is scheduled to run, the current is higher than idle until after my timeslot is executed. Since MPSL schedules my timeslot near the end of the time between radio events, my average current draw is much higher than when I don't use MPSL. Why? If MPSL Timeslots are not the proper method to schedule event so that they don't overlap with radio events, please advise an alternate method.

My code is taken straight from the MPSL example.

static mpsl_timeslot_signal_return_param_t *mpsl_timeslot_callback(
	mpsl_timeslot_session_id_t session_id,
	uint32_t signal_type)
{
	(void) session_id; /* unused parameter */

	mpsl_timeslot_signal_return_param_t *p_ret_val = NULL;

	switch (signal_type) {

	case MPSL_TIMESLOT_SIGNAL_START:
        StatusLedOn();
		/* No return action */
		signal_callback_return_param.callback_action =
			MPSL_TIMESLOT_SIGNAL_ACTION_NONE;
		p_ret_val = &signal_callback_return_param;

		/* Setup timer to trigger an interrupt (and thus the TIMER0
		 * signal) before timeslot end.
		 */
		nrf_timer_cc_set(NRF_TIMER0, NRF_TIMER_CC_CHANNEL0,
			TIMER_EXPIRY_US);
		nrf_timer_int_enable(NRF_TIMER0, NRF_TIMER_INT_COMPARE0_MASK);

		break;
	case MPSL_TIMESLOT_SIGNAL_TIMER0:
        StatusLedOff();

		/* Clear event */
		nrf_timer_int_disable(NRF_TIMER0, NRF_TIMER_INT_COMPARE0_MASK);
		nrf_timer_event_clear(NRF_TIMER0, NRF_TIMER_EVENT_COMPARE0);

		if (request_in_cb) {
			/* Request new timeslot when callback returns */
			signal_callback_return_param.params.request.p_next =
				&timeslot_request_normal;
			signal_callback_return_param.callback_action =
				MPSL_TIMESLOT_SIGNAL_ACTION_REQUEST;
		} else {
			/* Timeslot will be ended */
			signal_callback_return_param.callback_action =
				MPSL_TIMESLOT_SIGNAL_ACTION_END;
		}

		p_ret_val = &signal_callback_return_param;

		break;
    case MPSL_TIMESLOT_SIGNAL_BLOCKED:
    case MPSL_TIMESLOT_SIGNAL_CANCELLED:
        break;
	case MPSL_TIMESLOT_SIGNAL_SESSION_IDLE:
		break;
	case MPSL_TIMESLOT_SIGNAL_SESSION_CLOSED:
		break;
	default:
		printk("unexpected signal: %u", signal_type);
		error();
		break;
	}

	return p_ret_val;
}

nRF Connect SDK 1.6.1

Segger Embedded Studio v5.50c

In my complete application, I am periodically (10 Hz) sampling a sensor while streaming BLE data and I would like to ensure that I am not performing radio activities at the same time as sampling my sensor. The LED flashing example is a simpler case, useful for this discussion.

  • Hi, 

    In the non-MPSL version of your tests are you using Timer or RTC to schedule the led on/off? The NRF_TIMER uses HFCLK but if this was same in your non-MPSL version (using Timer) then this is very interesting side affect you are seeing which seems buggy in my opinion. To be able to debug this, i would need to replicate your experiment. If you are using same timers in both non-mpsl and mpsl experimetn then can you please give me a minimalistic project so that i can test this effects quickly?

  • The non-MPSL version is using timers as such:

        // Initialize led period timer and work handlers.
        k_timer_init(&led_period_timer, led_period_timer_handler, NULL);
        k_work_init(&led_period_work, led_period_work_handler);
    
        // Initialize led duty cycle timer and work handlers.
        k_timer_init(&led_duty_cycle_timer, led_duty_cycle_timer_handler, NULL);
        k_work_init(&led_duty_cycle_work, led_duty_cycle_work_handler);
    .
    .
    .
        // start timers
        k_timer_start(&led_period_timer, K_MSEC(LED_IDLE_PERIOD_MS), K_MSEC(LED_IDLE_PERIOD_MS)); // periodic
        k_timer_start(&led_duty_cycle_timer, K_MSEC(LED_IDLE_DUTY_CYCLE_MS), K_NO_WAIT); // one shot, restarted in periodic handler
        // turn on led
        gpio_pin_set(_LedStatus_dev, LED_STATUS_PIN, LED_ON);
    .
    .
    .
        // LED period expires callback
        k_timer_start(&led_duty_cycle_timer, K_MSEC(LED_IDLE_DUTY_CYCLE_MS), K_NO_WAIT); // one shot, restarted in periodic handler
        // turn on led
        gpio_pin_set(_LedStatus_dev, LED_STATUS_PIN, LED_ON);
    .
    .
    .
        // LED duty cycle expires callback
        gpio_pin_set(_LedStatus_dev, LED_STATUS_PIN, LED_OFF);
    

    The timing for the MPSL version is managed as shown in the code snippet of the original post:

        StatusLedOn();
        nrf_timer_cc_set(NRF_TIMER0, NRF_TIMER_CC_CHANNEL0,
        			TIMER_EXPIRY_US);
    .
    .
    .
    	case MPSL_TIMESLOT_SIGNAL_TIMER0:
            StatusLedOff();
    

  • That explains it.

    using nrf_timer_xxx related stuff is expensive. And seems like the MPSL starts the timeslot with the TIMER0 enabled at 1 MHz. You can brutally disable the TIMER0 when the timeslot starts and use k_timer (which is rtos timer using RTC) API to close the timeslot in time. 

  • My concern (right now) is not the power consumption during my event processing, but rather the power consumption of the MPSL library prior to my event processing. If you look at the graph, the power consumption between radio events when my event is not scheduled to run is quite low. But between radio event when my event is scheduled to run has higher power consumption prior to my event even being started. So turning off TIMER0 in my handler it too late. I believe that the problem is in the MPSL library and what it is doing in the background between radio events for which a scheduled timeslot has been requested.

  • Hi, 

    You are right, the power spike seems short lived and seems like it is not extending into the user timeslot. I need to ask the team of MPSL to understand what it is doing just before the user timeslot starts to have this spike.

Related