Mbed-os: NRF51_DK: core_util_are_interrupts_enabled wrong behavior when inside critical section

Created on 26 Sep 2017  路  11Comments  路  Source: ARMmbed/mbed-os

Description

  • Type: Bug
  • Priority: Major

Bug

Target
NRF51_DK

Toolchain:
GCC_ARM|ARM|IAR

mbed-os sha:
c6f655c02

Expected behavior
core_util_are_interrupts_enabled return false when interupt disabled

Actual behavior
core_util_are_interrupts_enabled return true when interupt disabled

Steps to reproduce

...
printf("interrupts_enabled (1): %s\r\n", core_util_are_interrupts_enabled() ? "yes" : "no");
core_util_critical_section_enter();
printf("interrupts_enabled (2): %s\r\n", core_util_are_interrupts_enabled() ? "yes" : "no");
core_util_critical_section_exit();
printf("interrupts_enabled (3): %s\r\n", core_util_are_interrupts_enabled() ? "yes" : "no");
printf("\r\n");
...

Result

interrupts_enabled (1): yes
interrupts_enabled (2): yes
interrupts_enabled (3): yes

Expected result

interrupts_enabled (1): yes
interrupts_enabled (2): no
interrupts_enabled (3): yes
nordic bug

All 11 comments

@bulislaw @0xc0170

cc @nvlsianpu @anangl

On the NRF51, core_util_critical_section_enter doesn't disable interrupts instead it mask all interrupts which are not reserved for BLE processing. core_util_are_interrupts_enabled look after PRIMASK to assess if the interrupts are enabled or not. In that case it will always return true.

@maciejbocianski ping

So assuming that BLE interrupts are out of scope of our interest maybe we should also modify a behaviour of core_util_are_interrupts_enabled to align it to core_util_critical_section_enter and core_util_critical_section_exit for this platform?
I think that some expert on NRF51(BLE) should look on it

Other solution could be introduction of another function core_util_in_critical_section which will be complementation of core_util_critical_section_enter and core_util_critical_section_exit and to check if we are in critical secition we will use core_util_in_critical_section not core_util_are_interrupts_enabled.

So assuming that BLE interrupts are out of scope of our interest maybe we should also modify a behaviour of core_util_are_interrupts_enabled to align it to core_util_critical_section_enter and core_util_critical_section_exit for this platform?

If on this platform core_util_critical_section_enter and core_util_critical_section_exit disable interrupts then BLE connection may drop unexpectedly and won't be reliable anymore. The main reason for this chip to exist being to execute BLE applications, it is critical that the OS doesn't interfere in BLE handling. Otherwise there is little point of running mbed OS on this chip and even less for Nordic to partner with us.

Other solution could be introduction of another function core_util_in_critical_section which will be complementation of core_util_critical_section_enter and core_util_critical_section_exit and to check if we are in critical secition we will use core_util_in_critical_section not core_util_are_interrupts_enabled.

@bulislaw What do you think of this proposition ?

I think it makes sense, we can't remove core_util_are_interrupts_enabled, but we can add extra function. Bu i don't like idea of quick fixing it and relying on platform code to set some flags.
Maybe we could make it a non-mandatory HAL API? Something like:

/* in hal_critical_section.c */
MBED_WEAK hal_critical_section_enter(void)
{
    __disable_irq();
}

/* in mbed_critical.c */
void core_util_critical_section_enter(void)
{
    bool interrupts_disabled = !core_util_in_critical_section();
    hal_critical_section_enter();

    /* Save the interrupt disabled state as it was prior to any nested critical section lock use */
    if (!interrupt_enable_counter) {
        critical_interrupts_disabled = interrupts_disabled;
    }

    /* If the interrupt_enable_counter overflows or we are in a nested critical section and interrupts
       are enabled, then something has gone badly wrong thus assert an error.
    */
    MBED_ASSERT(interrupt_enable_counter < UINT32_MAX); 
// FIXME
#ifndef   FEATURE_UVISOR
    if (interrupt_enable_counter > 0) {
        MBED_ASSERT(interrupts_disabled);
    }
#else
#warning "core_util_critical_section_enter needs fixing to work from unprivileged code"
#endif /* FEATURE_UVISOR */
    interrupt_enable_counter++;
}

@0xc0170 @pan- @c1728p9 what do you think?

Other solution could be introduction of another function core_util_in_critical_section which will be complementation of core_util_critical_section_enter and core_util_critical_section_exit and to check if we are in critical secition we will use core_util_in_critical_section not core_util_are_interrupts_enabled.
@bulislaw What do you think of this proposition ?

wouldn't be better to have target specific implementation ? As I understand if softdevice is active, its own interrupt are enabled and do not interfere with an application, thus if an app asks if interrupts are disabled for this platform, what should be returned? app interrupts state? or include also softdevice interrupts state? I would say just app interrupts. Is something like softdevice common (having app interrupts + specific chip interrupts that are separated from app space thus no conflicts there) ?
I believe this is what was proposed above (https://github.com/ARMmbed/mbed-os/issues/5198#issuecomment-332529282). Or might be better just leave it as it , interrupt status (all of them), and having a new api. Anyway, this nordic specific behaviour should be documented in critical section (generic description that in some cases critical section might just disable only app interrupts, having this new indirection via hal, it would be obvious that there are special cases).

MBED_WEAK hal_critical_section_enter(void) - I do not follow how this solves the issue we are having? That nordic would provide own implementation as it does now, but in hal for enter/exit, that would be good.

I like the idea of hal_critical_section_enter and hal_critical_section_exit overridden if required by the platform and called indirectly by core_util_in_critical_section_enter and core_util_in_critical_section_exit.

Thanks to the introduction of that level of indirection core_util_in_critical_section might be defined outside platform code and wouldn't need any action from partner.

core_util_are_interrupts_enabled and core_util_in_critical_section can coexist together.

@scartmell-arm will propose solution, based on comments here.

fixed by adding new API
HAL: hal_in_critical_section()
platform: core_util_in_critical_section()

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ashok-rao picture ashok-rao  路  4Comments

bcostm picture bcostm  路  4Comments

chrissnow picture chrissnow  路  4Comments

cesarvandevelde picture cesarvandevelde  路  4Comments

sarahmarshy picture sarahmarshy  路  4Comments