takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_critical.c Source File

mbed_critical.c

00001 /*
00002  * Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * 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, WITHOUT
00013  * 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 /* Declare __STDC_LIMIT_MACROS so stdint.h defines UINT32_MAX when using C++ */
00019 #define __STDC_LIMIT_MACROS
00020 #include "hal/critical_section_api.h"
00021 
00022 #include "cmsis.h"
00023 #include "platform/mbed_assert.h"
00024 #include "platform/mbed_critical.h"
00025 #include "platform/mbed_toolchain.h"
00026 
00027 // if __EXCLUSIVE_ACCESS rtx macro not defined, we need to get this via own-set architecture macros
00028 #ifndef MBED_EXCLUSIVE_ACCESS
00029 #ifndef __EXCLUSIVE_ACCESS
00030 #if ((__ARM_ARCH_7M__      == 1U) || \
00031     (__ARM_ARCH_7EM__     == 1U) || \
00032     (__ARM_ARCH_8M_BASE__ == 1U) || \
00033     (__ARM_ARCH_8M_MAIN__ == 1U)) || \
00034     (__ARM_ARCH_7A__ == 1U)
00035 #define MBED_EXCLUSIVE_ACCESS      1U
00036 #elif (__ARM_ARCH_6M__ == 1U)
00037 #define MBED_EXCLUSIVE_ACCESS      0U
00038 #else
00039 #error "Unknown architecture for exclusive access"
00040 #endif
00041 #else
00042 #define MBED_EXCLUSIVE_ACCESS __EXCLUSIVE_ACCESS
00043 #endif
00044 #endif
00045 
00046 static volatile uint32_t critical_section_reentrancy_counter = 0;
00047 
00048 bool core_util_are_interrupts_enabled(void)
00049 {
00050 #if defined(__CORTEX_A9)
00051     return ((__get_CPSR() & 0x80) == 0);
00052 #else
00053     return ((__get_PRIMASK() & 0x1) == 0);
00054 #endif
00055 }
00056 
00057 bool core_util_is_isr_active(void)
00058 {
00059 #if defined(__CORTEX_A9)
00060     switch (__get_CPSR() & 0x1FU) {
00061         case CPSR_M_USR:
00062         case CPSR_M_SYS:
00063             return false;
00064         case CPSR_M_SVC:
00065         default:
00066             return true;
00067     }
00068 #else
00069     return (__get_IPSR() != 0U);
00070 #endif
00071 }
00072 
00073 bool core_util_in_critical_section(void)
00074 {
00075     return hal_in_critical_section();
00076 }
00077 
00078 void core_util_critical_section_enter(void)
00079 {
00080     // If the reentrancy counter overflows something has gone badly wrong.
00081     MBED_ASSERT(critical_section_reentrancy_counter < UINT32_MAX);
00082 
00083     hal_critical_section_enter();
00084 
00085     ++critical_section_reentrancy_counter;
00086 }
00087 
00088 void core_util_critical_section_exit(void)
00089 {
00090 
00091     // If critical_section_enter has not previously been called, do nothing
00092     if (critical_section_reentrancy_counter == 0) {
00093         return;
00094     }
00095 
00096     --critical_section_reentrancy_counter;
00097 
00098     if (critical_section_reentrancy_counter == 0) {
00099         hal_critical_section_exit();
00100     }
00101 }
00102 
00103 #if MBED_EXCLUSIVE_ACCESS
00104 
00105 /* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */
00106 #if defined (__CC_ARM)
00107 #pragma diag_suppress 3731
00108 #endif
00109 
00110 bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
00111 {
00112     do {
00113         uint8_t currentValue = __LDREXB(ptr);
00114         if (currentValue != *expectedCurrentValue) {
00115             *expectedCurrentValue = currentValue;
00116             __CLREX();
00117             return false;
00118         }
00119     } while (__STREXB(desiredValue, ptr));
00120     return true;
00121 }
00122 
00123 bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
00124 {
00125     do {
00126         uint16_t currentValue = __LDREXH(ptr);
00127         if (currentValue != *expectedCurrentValue) {
00128             *expectedCurrentValue = currentValue;
00129             __CLREX();
00130             return false;
00131         }
00132     } while (__STREXH(desiredValue, ptr));
00133     return true;
00134 }
00135 
00136 
00137 bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
00138 {
00139     do {
00140         uint32_t currentValue = __LDREXW(ptr);
00141         if (currentValue != *expectedCurrentValue) {
00142             *expectedCurrentValue = currentValue;
00143             __CLREX();
00144             return false;
00145         }
00146     } while (__STREXW(desiredValue, ptr));
00147     return true;
00148 }
00149 
00150 uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
00151 {
00152     uint8_t newValue;
00153     do {
00154         newValue = __LDREXB(valuePtr) + delta;
00155     } while (__STREXB(newValue, valuePtr));
00156     return newValue;
00157 }
00158 
00159 uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta)
00160 {
00161     uint16_t newValue;
00162     do {
00163         newValue = __LDREXH(valuePtr) + delta;
00164     } while (__STREXH(newValue, valuePtr));
00165     return newValue;
00166 }
00167 
00168 uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
00169 {
00170     uint32_t newValue;
00171     do {
00172         newValue = __LDREXW(valuePtr) + delta;
00173     } while (__STREXW(newValue, valuePtr));
00174     return newValue;
00175 }
00176 
00177 
00178 uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)
00179 {
00180     uint8_t newValue;
00181     do {
00182         newValue = __LDREXB(valuePtr) - delta;
00183     } while (__STREXB(newValue, valuePtr));
00184     return newValue;
00185 }
00186 
00187 uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)
00188 {
00189     uint16_t newValue;
00190     do {
00191         newValue = __LDREXH(valuePtr) - delta;
00192     } while (__STREXH(newValue, valuePtr));
00193     return newValue;
00194 }
00195 
00196 uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
00197 {
00198     uint32_t newValue;
00199     do {
00200         newValue = __LDREXW(valuePtr) - delta;
00201     } while (__STREXW(newValue, valuePtr));
00202     return newValue;
00203 }
00204 
00205 #else
00206 
00207 bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
00208 {
00209     bool success;
00210     uint8_t currentValue;
00211     core_util_critical_section_enter();
00212     currentValue = *ptr;
00213     if (currentValue == *expectedCurrentValue) {
00214         *ptr = desiredValue;
00215         success = true;
00216     } else {
00217         *expectedCurrentValue = currentValue;
00218         success = false;
00219     }
00220     core_util_critical_section_exit();
00221     return success;
00222 }
00223 
00224 bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
00225 {
00226     bool success;
00227     uint16_t currentValue;
00228     core_util_critical_section_enter();
00229     currentValue = *ptr;
00230     if (currentValue == *expectedCurrentValue) {
00231         *ptr = desiredValue;
00232         success = true;
00233     } else {
00234         *expectedCurrentValue = currentValue;
00235         success = false;
00236     }
00237     core_util_critical_section_exit();
00238     return success;
00239 }
00240 
00241 
00242 bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
00243 {
00244     bool success;
00245     uint32_t currentValue;
00246     core_util_critical_section_enter();
00247     currentValue = *ptr;
00248     if (currentValue == *expectedCurrentValue) {
00249         *ptr = desiredValue;
00250         success = true;
00251     } else {
00252         *expectedCurrentValue = currentValue;
00253         success = false;
00254     }
00255     core_util_critical_section_exit();
00256     return success;
00257 }
00258 
00259 
00260 uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
00261 {
00262     uint8_t newValue;
00263     core_util_critical_section_enter();
00264     newValue = *valuePtr + delta;
00265     *valuePtr = newValue;
00266     core_util_critical_section_exit();
00267     return newValue;
00268 }
00269 
00270 uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta)
00271 {
00272     uint16_t newValue;
00273     core_util_critical_section_enter();
00274     newValue = *valuePtr + delta;
00275     *valuePtr = newValue;
00276     core_util_critical_section_exit();
00277     return newValue;
00278 }
00279 
00280 uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
00281 {
00282     uint32_t newValue;
00283     core_util_critical_section_enter();
00284     newValue = *valuePtr + delta;
00285     *valuePtr = newValue;
00286     core_util_critical_section_exit();
00287     return newValue;
00288 }
00289 
00290 
00291 uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)
00292 {
00293     uint8_t newValue;
00294     core_util_critical_section_enter();
00295     newValue = *valuePtr - delta;
00296     *valuePtr = newValue;
00297     core_util_critical_section_exit();
00298     return newValue;
00299 }
00300 
00301 uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)
00302 {
00303     uint16_t newValue;
00304     core_util_critical_section_enter();
00305     newValue = *valuePtr - delta;
00306     *valuePtr = newValue;
00307     core_util_critical_section_exit();
00308     return newValue;
00309 }
00310 
00311 uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
00312 {
00313     uint32_t newValue;
00314     core_util_critical_section_enter();
00315     newValue = *valuePtr - delta;
00316     *valuePtr = newValue;
00317     core_util_critical_section_exit();
00318     return newValue;
00319 }
00320 
00321 #endif
00322 
00323 
00324 bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue)
00325 {
00326     return core_util_atomic_cas_u32(
00327                (volatile uint32_t *)ptr,
00328                (uint32_t *)expectedCurrentValue,
00329                (uint32_t)desiredValue);
00330 }
00331 
00332 void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
00333 {
00334     return (void *)core_util_atomic_incr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta);
00335 }
00336 
00337 void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta)
00338 {
00339     return (void *)core_util_atomic_decr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta);
00340 }
00341