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

Calling app_sched_event_put inside interrupt

Hi, I'm debugging a small app that is using the LPCOMP to trigger an interrupt when the BLE device is turned off. We have a capacitor to maintain alive the nRF for a while after the power is turned off (the idea is to let the nRF store some data in flash before die).

This is the code I use to configure and use the LPCOMP:

void LPCOMP_init(void) {
/* Enable interrupt on LPCOMP CROSS event */		
NRF_LPCOMP->INTENSET = LPCOMP_INTENSET_DOWN_Msk;
NVIC_EnableIRQ(LPCOMP_IRQn);

//  5 : 5V,  ref. 1/8 VDD
// 12 : 12V, ref. 3/8 VDD
// 24 : 24V, ref. 6/8 VDD

/* Configure LPCOMP */
if (power == 5) 
	NRF_LPCOMP->REFSEL = (LPCOMP_REFSEL_REFSEL_SupplyOneEighthPrescaling << LPCOMP_REFSEL_REFSEL_Pos);
else if (power == 12)
	NRF_LPCOMP->REFSEL = (LPCOMP_REFSEL_REFSEL_SupplyThreeEighthsPrescaling << LPCOMP_REFSEL_REFSEL_Pos);
else
	NRF_LPCOMP->REFSEL = (LPCOMP_REFSEL_REFSEL_SupplySixEighthsPrescaling << LPCOMP_REFSEL_REFSEL_Pos);

/* Configure LPCOMP - set reference input source to AIN2 */
NRF_LPCOMP->PSEL |= (LPCOMP_PSEL_PSEL_AnalogInput2 << LPCOMP_PSEL_PSEL_Pos);

/* Enable and start the low power comparator */
NRF_LPCOMP->ENABLE = LPCOMP_ENABLE_ENABLE_Enabled;	
NRF_LPCOMP->TASKS_START = 1;
}

/* Interrupt handler for LPCOMP */
void LPCOMP_COMP_IRQHandler(void)
{
uint32_t err_code;

// Clear event
NRF_LPCOMP->EVENTS_DOWN = 0;
// Stop LPCOMP
NRF_LPCOMP->TASKS_STOP = 1;
NRF_LPCOMP->ENABLE = LPCOMP_ENABLE_ENABLE_Disabled;

// Debug
nrf_gpio_pin_set(GPIO_PIN);

// Append store task in scheduler
err_code = app_sched_event_put(NULL, 0, config_store);
APP_ERROR_CHECK(err_code);

// Debug
nrf_gpio_pin_clear(GPIO_PIN);
}

void config_store(void *p_data, uint16_t p_size)
{
// Stop Advertising
sd_ble_gap_adv_stop();

// Store current configuration to flash
ps_config_store(&m_config);
}


int main(void)
{

...

// Enter main loop.
for (;;) {
    app_sched_execute();
	sd_app_evt_wait();
}
}

The problem I'm facing with this configuration is that when I call the app_sched_event_put() the code hangs and stops working. Looking inside at the app_sched_event_put() I see that there are two calls to CRITICAL_REGION_ENTER() and CRITICAL_REGION_EXIT(), I tried to comment out those calls and now the code works as expected. So my question is, why the CRITICAL_REGION_ENTER/EXIT macros are causing this problem?

The software is compiled with -DSOFTDEVICE_PRESENT and SoftDevice is enabled and inited.

Parents
  • I doubt the code hangs and stops working - I expect it goes to the hardfault handler, which a debugger would tell you.

    If that's so, most likely because your interrupt handler is running at HIGH priority and the critical region macros call a softdevice function and you can't call softdevice functions from APP_HIGH priority interrupt handlers, only from LOW or main thread context.

  • But the app priority shouldn't be APP_PRIORITY_HIGHEST because only the softdevice uses that, unless you never set the priority of your LPCOMP interrupt and you started it after you started the softdevice (which checks interrupt priorities on startup and fails if they are wrong).

Reply Children
No Data
Related