Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nRF51822 by
Diff: source/nRF5xGap.h
- Revision:
- 471:945e53179855
- Parent:
- 470:2c1d3b1fe249
- Child:
- 475:fe3d08b3a8e9
--- a/source/nRF5xGap.h Thu Nov 26 14:33:45 2015 +0000 +++ b/source/nRF5xGap.h Thu Nov 26 14:33:45 2015 +0000 @@ -110,36 +110,50 @@ private: #ifdef YOTTA_CFG_MBED_OS - /* Store the current radio notification value that will be used in the next callback */ - bool radioNotificationCallbackParam; - /* - * In mbed OS, the idea is to post all callbacks through minar scheduler. However, the radio notifications - * are handled in IRQs with very high priority. Trying to post a minar callback directly in - * processRadioNotification() will result in a hard-fault. This is because minar asumes that all callbacks - * are posted from low priority context, so when minar schedules the callback it attempts to enter a - * critical section and disable all interrupts. The problem is that minar tries to do this by invoking the - * SoftDevice with a call to sd_nvic_critical_region_enter() while already running in high priority. This - * results in the SoftDevice generating a hard-fault. - * A solution is to reduce the priority from which the callback is posted to minar. Unfortunately, there - * are not clean ways to do this. The solution implemented uses a Timeout to call - * postRadioNotificationCallback() after a very short delay (1 us) and post the minar callback there. + * In mbed OS, all user-facing BLE events (interrupts) are posted to the + * MINAR scheduler to be executed as callbacks in thread mode. MINAR guards + * its critical sections from interrupts by acquiring CriticalSectionLock, + * which results in a call to sd_nvic_critical_region_enter(). Thus, it is + * safe to invoke MINAR APIs from interrupt context as long as those + * interrupts are blocked by sd_nvic_critical_region_enter(). + * + * Radio notifications are a special case for the above. The Radio + * Notification IRQ is handled at a very high priority--higher than the + * level blocked by sd_nvic_critical_region_enter(). Thus Radio Notification + * events can preempt MINAR's critical sections. Using MINAR APIs (such as + * posting an event) directly in processRadioNotification() may result in a + * race condition ending in a hard-fault. * - * !!!WARNING!!! Radio notifications are very time critical events. The current solution is expected to - * work under the assumption that postRadioNotificationCalback() will be executed BEFORE the next radio + * The solution is to *not* call MINAR APIs directly from the Radio + * Notification handling; i.e. to do the bulk of RadioNotification + * processing at a reduced priority which respects MINAR's critical + * sections. Unfortunately, on a cortex-M0, there is no clean way to demote + * priority for the currently executing interrupt--we wouldn't want to + * demote the radio notification handling anyway because it is sensitive to + * timing, and the system expects to finish this handling very quickly. The + * workaround is to employ a Timeout to trigger + * postRadioNotificationCallback() after a very short delay (~0 us) and post + * the MINAR callback that context. + * + * !!!WARNING!!! Radio notifications are very time critical events. The + * current solution is expected to work under the assumption that + * postRadioNotificationCalback() will be executed BEFORE the next radio * notification event is generated. */ + + bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */ Timeout radioNotificationTimeout; /* - * A helper function to post radio notification callbacks through minar when using mbed OS. + * A helper function to post radio notification callbacks through MINAR when using mbed OS. */ void postRadioNotificationCallback(void) { minar::Scheduler::postCallback( mbed::util::FunctionPointer1<void, bool>(&radioNotificationCallback, &FunctionPointerWithContext<bool>::call).bind(radioNotificationCallbackParam) ); } -#endif +#endif /* #ifdef YOTTA_CFG_MBED_OS */ /** * A helper function to process radio-notification events; to be called internally.