Toyomasa Watarai / simple-mbed-cloud-client

Dependents:  

Revision:
0:276e7a263c35
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical-nordic.c	Mon Jul 02 06:30:39 2018 +0000
@@ -0,0 +1,90 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------
+
+#ifdef TARGET_MCU_NRF51
+
+#include <stdint.h>                  // uint32_t, UINT32_MAX
+#include <stddef.h>                  // NULL
+#include <cmsis-core/core_generic.h> //__disable_irq, __enable_irq
+#include <assert.h>
+#include <stdbool.h>
+#include <nrf_soc.h>
+#include <nrf_sdm.h>
+
+// Module include
+#include "aq_critical.h"
+
+static volatile union {
+    uint32_t _PRIMASK_state;
+    uint8_t  _sd_state;
+} _state = { 0 } ;
+static volatile uint32_t _entry_count = 0;
+static volatile bool _use_softdevice_routine = false;
+
+void aq_critical_section_enter()
+{
+    // if a critical section has already been entered, just update the counter
+    if (_entry_count) {
+        ++_entry_count;
+        return;
+    }
+
+    // in this path, a critical section has never been entered
+    uint32_t primask = __get_PRIMASK();
+
+    // if interrupts are enabled, try to use the soft device
+    uint8_t sd_enabled;
+    if ((primask == 0) && (sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && sd_enabled == 1) {
+        // if the soft device can be use, use it
+        sd_nvic_critical_region_enter(&_state._sd_state);
+        _use_softdevice_routine = true;
+    } else {
+        // if interrupts where enabled, disable them
+        if(primask == 0) {
+            __disable_irq();
+        }
+
+        // store the PRIMASK state, it will be restored at the end of the critical section
+        _state._PRIMASK_state = primask;
+        _use_softdevice_routine = false;
+    }
+
+    assert(_entry_count == 0); // entry count should always be equal to 0 at this point
+    ++_entry_count;
+}
+
+void aq_critical_section_exit()
+{
+    assert(_entry_count > 0);
+    --_entry_count;
+
+    // If their is other segments which have entered the critical section, just leave
+    if (_entry_count) {
+        return;
+    }
+
+    // This is the last segment of the critical section, state should be restored as before entering
+    // the critical section
+    if (_use_softdevice_routine) {
+        sd_nvic_critical_region_exit(_state._sd_state);
+    } else {
+        __set_PRIMASK(_state._PRIMASK_state);
+    }
+}
+
+#endif //TARGET_MCU_NRF51