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

Using RTC2, PPI and GPIOTE to drive LED

SDK Version: 15.1
IDE: Keil
Softdevice: S132 v6
Example:  Blinky peripheral example slightly modified

Q1.  Does the Softdevice use RTC0?
Q2.  Does the App Timer use RTC1?  If yes, I am assuming for BLE connection events and other BLE stuff.  Is this correct?

My goal is to use RTC2, PPI and GPIOTE create a pseudo-PWM drive for a single LED.  Why not use the PWM driver, because it consumes ~ 500uA due to the fact that it uses HFCLK....Why not use an App Timer?...because from my investigation, it consumes more current than talking to the RTC directly without interrupts.  So, here's my code:

void GPIOTE6_init(void)
{
	// Configure GPIOTE to toggle pin
	NRF_GPIOTE->CONFIG[6] =	(GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | 					//task mode using GPIOTE CH7
													(PIN_BLUE_LED << GPIOTE_CONFIG_PSEL_Pos) |											//BLUE LED
													(GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |	//set mode
													(GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos);				//initial state = high/LED off
}

void PPI17_init(void)
{
	NRF_PPI->CH[17].EEP = (uint32_t) &NRF_RTC2->EVENTS_COMPARE[0];	//trigger from this event
	NRF_PPI->CH[17].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[6];			//end point for task
	
	NRF_PPI->CH[16].EEP = (uint32_t) &NRF_RTC2->EVENTS_COMPARE[1];	//trigger from this event
	NRF_PPI->CH[16].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[6];			//end point for task
	NRF_PPI->FORK[16].TEP = (uint32_t) &NRF_RTC2->TASKS_CLEAR;			//clear RTC2 counter value
	
	NRF_PPI->CHENSET = ((PPI_CHENSET_CH17_Enabled << PPI_CHENSET_CH17_Pos) |	//enable PPI CH17
											(PPI_CHENSET_CH16_Enabled << PPI_CHENSET_CH16_Pos));	//enable PPI CH16
}



NRF_RTC2->PRESCALER = 0;
NRF_RTC2->TASKS_CLEAR = 0;
NRF_RTC2->CC[0] = 5;
NRF_RTC2->CC[1] = 20; 	//20 caused 150uA, 10 caused 172uA
NRF_RTC2->EVTEN = ((RTC_EVTEN_COMPARE0_Enabled << RTC_EVTEN_COMPARE0_Pos) |
				(RTC_EVTEN_COMPARE1_Enabled << RTC_EVTEN_COMPARE1_Pos));
GPIOTE6_init();
PPI17_init();
NRF_RTC2->TASKS_START = 1;

My goal here is to use RTC2 to generate 2 toggles of the LED.  One at CC[0] = 5, and the other one at CC[1] = 20 so that the LED is on (active low) for 5 RTC counts and off for 20 RTC counts.  So I've hooked up PPI CH 17 to trigger when RTC2 reaches CC[0], and toggle "PIN_NRF_BLUE_LED" without clearing/resetting the count value.  Then as the RTC2 keeps counting, when it reaches CC[1],  I setup PP1 CH 16 to toggle that same pin once more.  I have also configured a fork on PPI CH 16 so that the timer clears and starts all over.

The problem I'm having is that I'm getting a 50% duty cyle waveform at the rate of CC[1].  I am not sure what is happening here, please help.

Regards,

E

Parents
  • Hi,

    Q1: Yes, the softdevice use RTC0, see SoC hardware peripheral requirements in the softdevice specifications.

    Q2: Yes, the app_timer library uses RTC1 by default. The use of app_timer is not required by the softdevice, but it is used by some SDK libraries (for instance the BLE Connection Parameters Negotiation library, and in the app_button/BSP library to detect long button pushes) and for software timers in the example applications.

    PPI channel 17 is reserved by the softdevice (you can see which channels are reserved in nrf_soc.h header file - for s132 v6.1.0, 17-31 is reserved). Maybe that could be the reason for the issue you are seeing?

    The app_timer library should not have a very much higher current than using RTC directly, but this depends on your power requirements. If you are interested, there is a low-power PWM library in the SDK that uses app_timer.

    Best regards,
    Jørgen

Reply
  • Hi,

    Q1: Yes, the softdevice use RTC0, see SoC hardware peripheral requirements in the softdevice specifications.

    Q2: Yes, the app_timer library uses RTC1 by default. The use of app_timer is not required by the softdevice, but it is used by some SDK libraries (for instance the BLE Connection Parameters Negotiation library, and in the app_button/BSP library to detect long button pushes) and for software timers in the example applications.

    PPI channel 17 is reserved by the softdevice (you can see which channels are reserved in nrf_soc.h header file - for s132 v6.1.0, 17-31 is reserved). Maybe that could be the reason for the issue you are seeing?

    The app_timer library should not have a very much higher current than using RTC directly, but this depends on your power requirements. If you are interested, there is a low-power PWM library in the SDK that uses app_timer.

    Best regards,
    Jørgen

Children
  • Hello Jorgen,

    Thanks for your continuing support.

    Q1.  Thanks for clarifying and providing a link to the documentation.

    Q2.  Although RTC1 is not used by the softdevice directly, negotiating connection parameters for BLE seems like an essential task that either through code of my own or the SDK libraries, seems necessary.  I'm assuming there is some timer functionality here needed here to support BLE and the best choice is the App Timer.  If I am not understanding this correctly, please clarify.  What additional functionality other than app_button/BSP and Connection Parameters negotiation would I need to disable in order to use RTC1 for my own needs?

    Regarding the RTC2 usage for PWM, you were absolutely correct, PPI channel 17 was used so that is why that part of my code was not working. After changing it to use PPI channels 16 and 15, everything worked like a charm.

    The App Timer seems to consume more current than using the RTC2 directly.  Not sure why, since the App Timer is an RTC instance but that is what my current measurements are showing.  Can you elaborate on this?  Do you expect this?

    Also, regarding low-power PWM library suggestion, it also uses the App Timer, and since I still measure higher current consumption when compared to using RTC2 directly, I am going with the RTC2 route until I understand why this is the case

    Best Regards,

    E

  • Q2. Yes, if you want to use the libraries from the SDK, the best option is to use app_timer. Connection parameter negotiation could also be handled in your application and then you could have used another timing mechanism to do this. You should check through your project for calls to app_timer APIs, it is used in some other libraries for various tasks (CPU usage monitor in power management library, timeouts in serial libraries and CLI modules, LED-blinking libraries, low-power PWM library, etc.) Most likely most of these are not used in your project, which is why you should check for API calls to know which libraries are included.

    I would expect the app_timer to have a marginally higher average run current due to the CPU having to wake up to handle events and timeouts. I'm not sure what kind of difference in consumption you saw with your testing, I have not done any power profiling on this myself. As longs as you have the RTC2 approach working, and you plan on eliminating the app_timer usage from your application, I do not see any problems with that.

Related