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.
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
Generated on Tue Aug 9 2022 00:37:14 by
