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

How to redefine PPI tasks inside a TIMER interrupt ???

Dear Nordic Developer Zone,

I am working on a BLE application using nrf51822 with softDevice.

My aim is to be able to redefine which GPIOTE channel my PPI is using inside the TIMER1 interrupt under logical conditions.

Unfortunately, all softdevice calls to modify the PPI (sd_ppi_X) in the TIMER1 interrupt doesn't work and crash the app ?!

It should be trivial, but I can't figure it out by myself... I am able to redefine the PPI tasks in my app functions, but not inside interrupt.

Is there someone to help me? Here is my code.


static uint32_t                               m_counter = 0; 

void TIMER1_IRQHandler(void)
{
	uint32_t err_code;
	
  if ((NRF_TIMER1->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER1->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0))
  {
	//Reinit comparator	
        NRF_TIMER1->EVENTS_COMPARE[0] = 0;
	
        m_counter = m_counter +1;

        if(m_counter == 5)
        {
	     //-->PPI call here crash the app
             //! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    	    sd_ppi_channel_assign(0, &(NRF_TIMER1->EVENTS_COMPARE[0]), &(NRF_GPIOTE->TASKS_OUT[1]));
        }

	//Toggle led to have a visual feedback that the application didn't crash
	nrf_gpio_pin_toggle(17);//Devkit
  }
}

/**
 * main function
 * \return 0. int return type required by ANSI/ISO standard.
 */
void rtc_test(void)
{
	uint32_t err_code;
	
	nrf_gpio_cfg_output(M1_A0_PIN);
	nrf_gpio_cfg_output(M1_B0_PIN);
	nrf_gpio_cfg_output(M1_C0_PIN);
	
	// Configure timer
	NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
	NRF_TIMER1->PRESCALER = 9;   // 31.25kHz ? 32us tick 
	NRF_TIMER1->TASKS_CLEAR = 1;  // Clear the timer
	NRF_TIMER1->CC[0] = 0x1E84;  // CC[0] occurs at 250ms from START
	
	// Configure the shortcut to clear and restart on Compare[0]
	NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); 
	
	NRF_TIMER1->INTENSET = (1UL << TIMER_INTENSET_COMPARE0_Pos);
	NVIC_EnableIRQ(TIMER1_IRQn);
	
	// Configure the GPIOTE Task to toggle the LED state. 
	nrf_gpiote_task_config(0,  // GPIOTE Channel
					M1_A0_PIN, // GPIO pin
					NRF_GPIOTE_POLARITY_TOGGLE,
					NRF_GPIOTE_INITIAL_VALUE_HIGH);

	// Configure the GPIOTE Task to toggle the LED state. 
	nrf_gpiote_task_config(1,  // GPIOTE Channel
					M1_B0_PIN, // GPIO pin
					NRF_GPIOTE_POLARITY_TOGGLE,
					NRF_GPIOTE_INITIAL_VALUE_HIGH);
											
	//Configure PPI
	err_code = sd_ppi_channel_assign(0, &(NRF_TIMER1->EVENTS_COMPARE[0]), &(NRF_GPIOTE->TASKS_OUT[0]));
	// Enable PPI channel 0
	err_code = sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk);

	NRF_TIMER1->TASKS_START = 1;
}
Parents
  • If you see this consistently failing (with a HardFault error), the timer interrupt most likely runs with too high priority to call softdevice functions. The problem with this is described in the "Application Programming Interface" section in the nRF51 Series Reference Manual appendix:

    SVC calls are conceptually software triggered interrupts with a procedure call standard for parameter passing and return values. Each API call generates an interrupt allowing single-thread API context and SoftDevice function locations to be independent from the application perspective at compile-time. SoftDevice API functions can only be called from lower interrupt priority when compared to the SVC priority. See the Exception (interrupt) management with a SoftDevice section on page 182.

    The SVC interrupt have priority 2, so to call softdevice API functions (for example the PPI function), your IRQ handler must run at priority 3.

  • Thank you so much. I was stucked on this problem for 2 days.

Reply Children
No Data
Related