Roy Want / Mbed OS beaconCompileReadyFork
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NordicCriticalSectionLock.h Source File

NordicCriticalSectionLock.h

00001 /*
00002  * PackageLicenseDeclared: Apache-2.0
00003  * Copyright (c) 2015 ARM Limited
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /**
00019  * NOTE: THIS FILE IS A WORKAROUND FOR mbed::util::CriticalSectionLock implementation
00020  * it should be removed as soon as https://github.com/ARMmbed/core-util/pull/50 is
00021  * accepted and published.
00022  */
00023 
00024 #ifndef BLE_CLIAPP_UTIL_NORDIC_CRITICAL_SECTION_LOCK_H__
00025 #define BLE_CLIAPP_UTIL_NORDIC_CRITICAL_SECTION_LOCK_H__
00026 
00027 #include <stdint.h>
00028 #include "cmsis.h"
00029 #include "nrf_soc.h"
00030 #include "nrf_sdm.h"
00031 #include "nrf_nvic.h"
00032 extern "C" {
00033 #include "softdevice_handler.h"
00034 }
00035 namespace util {
00036 
00037 /** RAII object for disabling, then restoring, interrupt state
00038   * Usage:
00039   * @code
00040   *
00041   * void f() {
00042   *     // some code here
00043   *     {
00044   *         NordicCriticalSectionLock lock;
00045   *         // Code in this block will run with interrupts disabled
00046   *     }
00047   *     // interrupts will be restored to their previous state
00048   * }
00049   * @endcode
00050   */
00051 class NordicCriticalSectionLock {
00052 public:
00053 
00054     /**
00055      * Start a critical section, the critical section will end when the
00056      * destructor is invoked.
00057      */
00058     NordicCriticalSectionLock() {
00059         // get the state of exceptions for the CPU
00060         _PRIMASK_state = __get_PRIMASK();
00061 
00062         // if exceptions are not enabled, there is nothing more to do
00063         if(_PRIMASK_state == 1) {
00064           _use_softdevice_routine = false;
00065         } else {
00066           // otherwise, use soft device routine if softdevice is running or disable
00067           // the irq if softdevice is not running
00068           if(softdevice_handler_isEnabled()) {
00069             _use_softdevice_routine = true;
00070             sd_nvic_critical_region_enter(&_sd_state);
00071           } else {
00072             _use_softdevice_routine = false;
00073             __disable_irq();
00074           }
00075         }
00076     }
00077 
00078     /**
00079      * eqnd a critical section
00080      */
00081     ~NordicCriticalSectionLock() {
00082         if(_use_softdevice_routine) {
00083           sd_nvic_critical_region_exit(_sd_state);
00084         } else {
00085           __set_PRIMASK(_PRIMASK_state);
00086         }
00087     }
00088 
00089 private:
00090     union {
00091       uint32_t _PRIMASK_state;
00092       uint8_t  _sd_state;
00093     };
00094     bool _use_softdevice_routine;
00095 };
00096 
00097 } // namespace util
00098 
00099 #endif // #ifndef BLE_CLIAPP_UTIL_NORDIC_CRITICAL_SECTION_LOCK_H__