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.

  • Hi DK and Samuele,

    I caught the same problem while tring to put event into scheduler. but the version I used is 15.2 .

    The definition of the macro is the following content:

    #ifdef SOFTDEVICE_PRESENT
    #define CRITICAL_REGION_ENTER() \
    { \
    uint8_t __CR_NESTED = 0; \
    app_util_critical_region_enter(&__CR_NESTED);
    #else
    #define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL)
    #endif

    void app_util_critical_region_enter(uint8_t *p_nested)
    {
    #if __CORTEX_M == (0x04U)
    ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
    #endif

    #if defined(SOFTDEVICE_PRESENT)
    /* return value can be safely ignored */
    (void) sd_nvic_critical_region_enter(p_nested);
    #else
    app_util_disable_irq();
    #endif
    }

    There is not any if statement and it will disable irq which will cause error when I put in interrupt handler in lpcomp. I am not using softdevice.

Reply
  • Hi DK and Samuele,

    I caught the same problem while tring to put event into scheduler. but the version I used is 15.2 .

    The definition of the macro is the following content:

    #ifdef SOFTDEVICE_PRESENT
    #define CRITICAL_REGION_ENTER() \
    { \
    uint8_t __CR_NESTED = 0; \
    app_util_critical_region_enter(&__CR_NESTED);
    #else
    #define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL)
    #endif

    void app_util_critical_region_enter(uint8_t *p_nested)
    {
    #if __CORTEX_M == (0x04U)
    ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
    #endif

    #if defined(SOFTDEVICE_PRESENT)
    /* return value can be safely ignored */
    (void) sd_nvic_critical_region_enter(p_nested);
    #else
    app_util_disable_irq();
    #endif
    }

    There is not any if statement and it will disable irq which will cause error when I put in interrupt handler in lpcomp. I am not using softdevice.

Children
No Data
Related