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

How to disable radio notification after enabling it

Hi,

In my application I need radio notification only during connection. When connection is dropped the peripheral goes to advertising mode and here i disable the radio notification. But it looks like the notification is not disabled since I see the current consumption is high. Is there something that I shud keep in mind regarding enabling and disabling radio notifications. The reason I know high current consumption is caused by radio notification is that this happens only when transitioning from connection->advertisement mode. whereas if the device starts in advertisement mode straight away then current consumption is in right ball park. Please see the code below on how I enable and disable notification. I am using s110 softdevice. Any help is appreciated. Thanks in advance.

 void radio_enable_notif(uint32_t type, uint32_t distance){
  uint32_t err_code;

  err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
  APP_ERROR_CHECK(err_code);

  err_code = sd_nvic_SetPriority(SWI1_IRQn, APP_IRQ_PRIORITY_LOW);
  APP_ERROR_CHECK(err_code);

  err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
  APP_ERROR_CHECK(err_code);

  err_code = sd_radio_notification_cfg_set(type, distance);
  APP_ERROR_CHECK(err_code);
}

void radio_disable_notif(void){
  uint32_t err_code = sd_radio_notification_cfg_set(
      NRF_RADIO_NOTIFICATION_TYPE_NONE, NRF_RADIO_NOTIFICATION_DISTANCE_NONE);
  APP_ERROR_CHECK(err_code);

  err_code = sd_nvic_DisableIRQ(SWI1_IRQn);
  APP_ERROR_CHECK(err_code);
}

Update 1: I used timeslot APIs from here to disable/enable radio notifications only when Softdevice is idle. This worked for S110 softdevice. But would not work for S130 which is used in our master devices.

Update 2: I have attached an example Radio_notification_Example.zip to reproduce the bug I have been talking about. The example builds for PCA10028 boards. The example compiles with all necessary files including softdevice. On development kit I could reproduce the bug for the s110 softdevice(used by slave) and not on s130(used by master). After running slave_example we can notice advertisement consuming low current on bootup, but after it connects and goes back to advertisement the current consumption is high. Please feel free to ask if any questions. The example I have provided is a bare minimum version of what we are trying to do on our custom boards. PS: In my set up i use GCC 5.3.1. I'm using Linux machine. Example usage -

make GCC_INSTALL_ROOT=/usr/local/gcc-arm-none-eabi-5_3-2016q1 GCC_VERSION=5.3.1 JLINK_DIR=/opt/SEGGER/JLink SLNO=682844601 clean all upload

Update 3: radio_notif.c attached as mentioned in the comment to the answer.

Parents
  • Hi,

    Starting with a general answer for further reference:

    If you have set up radio notifications and do not want to use it, clear the interrupt right after receiving it, this will cause CPU to wakeup once and add some extra current, but is a easy and low complexity solution. If you need to do something periodically there are better, simpler and more energy efficient solutions than using radio notifications. For instance you can use the application timer as described in this tutorial.

    To disable radio notifications you have a few options, some fit certain solutions better than others. To ensure proper operation we need to heed the following sentence from the SoftDevice specification.

    To ensure that the Radio Notification signals behave in a consistent way, the Radio Notification 
    shall always be configured when the SoftDevice is in an idle state with no protocol stack or 
    other SoftDevice activity in progress. Therefore, it is recommended to configure the Radio 
    Notification signals directly after the SoftDevice has been enabled.
    

    Start off by making sure that the first time it is initialized is in a section where the SoftDevice is not active, for example right after initialization.

    In the right context, radio notification can be disabled by calling:

    // Deinitialize Radio Notification software interrupt
    uint32_t ble_radio_notification_uninit(void)
    {
        err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        err_code = sd_nvic_DisableIRQ(SWI1_IRQn);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_NONE, NRF_RADIO_NOTIFICATION_DISTANCE_NONE);
    }
    

    This context limitations is the same as for the first initialization of the radio notifications, as described above. We need to find some context where there will not be any SoftDevice activity. Since we already have radio notifications set up it is simplest to call ble_radio_notification_uninit() inside itself. However if we want to restart it we will be faced with the problem of when/how to restart it.

    One of the tools available is a radio timeslot where radio activity is guaranteed to not occur. When using timeslots be aware that you cannot call SoftDevice functions in the signal handler as it executes at priority 0. A simple timeslot signal handler that fulfills our purpose is:

    nrf_radio_signal_callback_return_param_t * timeslot_callback(uint8_t signal_type)
    {
      static nrf_radio_signal_callback_return_param_t signal_callback_return_param;
    
      switch(signal_type)
      {
          case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
    	  
             signal_callback_return_param.params.request.p_next = NULL;
             signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
    
             NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;                  // Timeslot timeout bookkeeper
             NRF_TIMER0->CC[0] = m_slot_length - 1000;
             NVIC_EnableIRQ(TIMER0_IRQn);
    
             NVIC_EnableIRQ(SWI0_IRQn);                                           // Set artififical interrupt
             NVIC_SetPendingIRQ(SWI0_IRQn);
    
             break;
        
         case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
         
             signal_callback_return_param.params.request.p_next = NULL;           // End timeslot
             signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_END;
    
    	default:
    	      break;
      }    
      return (&signal_callback_return_param);
    }
    

    And the corresponding IRQ handler:

    void SWI0_IRQHandler(void){
    	//Context where we can call SoftDevice functions
    	uint32_t err_code = sd_nvic_ClearPendingIRQ(SWI0_IRQn);																						//Clear artifical IRQ
    	APP_ERROR_CHECK(err_code);
    	err_code = sd_nvic_DisableIRQ(SWI0_IRQn);																									//Disable artificial IRQ channel
    	APP_ERROR_CHECK(err_code);
    
    	if(enable_radio_notification)																												//Boolean flag to enable/disable radio notification
    	{
    		err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
    		APP_ERROR_CHECK(err_code);
    		err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
    		APP_ERROR_CHECK(err_code);
    		err_code = sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_YOURTYPEHERE, NRF_RADIO_NOTIFICATION_DISTANCE_YOURDISTANCEHERE);	//Set desired type and distance
    		APP_ERROR_CHECK(err_code);
    	} 
    	else 
    	{
    		err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
    		APP_ERROR_CHECK(err_code);
    		err_code = sd_nvic_DisableIRQ(SWI1_IRQn);
    		APP_ERROR_CHECK(err_code);
    		err_code = sd_radio_notification_cfg_set(
    		NRF_RADIO_NOTIFICATION_TYPE_NONE, NRF_RADIO_NOTIFICATION_DISTANCE_NONE);
    		APP_ERROR_CHECK(err_code);
    	}
    	sd_nvic_SetPendingIRQ(TIMER0_IRQn);               					//Trigger the timer interrupt to end the timeslot
    }
    

    To reiterate, this is a very complicated way of solving a relatively simple problem, make sure that you are absolutely sure that this is the way you want to solve the problem if you go down this road.

    Best regards,

    Øyvind

    EDIT:

    Current draw measurements

  • There are several methods in that tutorial, which one are you using and what equipment?

Reply Children
No Data
Related