forked
Embed:
(wiki syntax)
Show/hide line numbers
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 "platform/mbed_critical.h" 00021 00022 #include "cmsis.h" 00023 #include "platform/mbed_assert.h" 00024 #include "platform/mbed_toolchain.h" 00025 00026 #if !defined (__CORTEX_M0) && !defined (__CORTEX_M0PLUS) 00027 #define EXCLUSIVE_ACCESS 1 00028 #else 00029 #define EXCLUSIVE_ACCESS 0 00030 #endif 00031 00032 static volatile uint32_t interrupt_enable_counter = 0; 00033 static volatile bool critical_interrupts_disabled = false; 00034 00035 bool core_util_are_interrupts_enabled(void) 00036 { 00037 #if defined(__CORTEX_A9) 00038 return ((__get_CPSR() & 0x80) == 0); 00039 #else 00040 return ((__get_PRIMASK() & 0x1) == 0); 00041 #endif 00042 } 00043 00044 bool core_util_is_isr_active(void) 00045 { 00046 #if defined(__CORTEX_A9) 00047 switch(__get_CPSR() & 0x1FU) { 00048 case MODE_USR: 00049 case MODE_SYS: 00050 return false; 00051 case MODE_SVC: 00052 default: 00053 return true; 00054 } 00055 #else 00056 return (__get_IPSR() != 0U); 00057 #endif 00058 } 00059 00060 MBED_WEAK void core_util_critical_section_enter(void) 00061 { 00062 bool interrupts_disabled = !core_util_are_interrupts_enabled(); 00063 __disable_irq(); 00064 00065 /* Save the interrupt disabled state as it was prior to any nested critical section lock use */ 00066 if (!interrupt_enable_counter) { 00067 critical_interrupts_disabled = interrupts_disabled; 00068 } 00069 00070 /* If the interrupt_enable_counter overflows or we are in a nested critical section and interrupts 00071 are enabled, then something has gone badly wrong thus assert an error. 00072 */ 00073 MBED_ASSERT(interrupt_enable_counter < UINT32_MAX); 00074 // FIXME 00075 #ifndef FEATURE_UVISOR 00076 if (interrupt_enable_counter > 0) { 00077 MBED_ASSERT(interrupts_disabled); 00078 } 00079 #else 00080 #warning "core_util_critical_section_enter needs fixing to work from unprivileged code" 00081 #endif /* FEATURE_UVISOR */ 00082 interrupt_enable_counter++; 00083 } 00084 00085 MBED_WEAK void core_util_critical_section_exit(void) 00086 { 00087 /* If critical_section_enter has not previously been called, do nothing */ 00088 if (interrupt_enable_counter) { 00089 00090 // FIXME 00091 #ifndef FEATURE_UVISOR 00092 bool interrupts_disabled = !core_util_are_interrupts_enabled(); /* get the current interrupt disabled state */ 00093 00094 MBED_ASSERT(interrupts_disabled); /* Interrupts must be disabled on invoking an exit from a critical section */ 00095 #else 00096 #warning "core_util_critical_section_exit needs fixing to work from unprivileged code" 00097 #endif /* FEATURE_UVISOR */ 00098 00099 interrupt_enable_counter--; 00100 00101 /* Only re-enable interrupts if we are exiting the last of the nested critical sections and 00102 interrupts were enabled on entry to the first critical section. 00103 */ 00104 if (!interrupt_enable_counter && !critical_interrupts_disabled) { 00105 __enable_irq(); 00106 } 00107 } 00108 } 00109 00110 #if EXCLUSIVE_ACCESS 00111 00112 /* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */ 00113 #if defined (__CC_ARM) 00114 #pragma diag_suppress 3731 00115 #endif 00116 00117 bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue) 00118 { 00119 uint8_t currentValue = __LDREXB((volatile uint8_t*)ptr); 00120 if (currentValue != *expectedCurrentValue) { 00121 *expectedCurrentValue = currentValue; 00122 __CLREX(); 00123 return false; 00124 } 00125 00126 return !__STREXB(desiredValue, (volatile uint8_t*)ptr); 00127 } 00128 00129 bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue) 00130 { 00131 uint16_t currentValue = __LDREXH((volatile uint16_t*)ptr); 00132 if (currentValue != *expectedCurrentValue) { 00133 *expectedCurrentValue = currentValue; 00134 __CLREX(); 00135 return false; 00136 } 00137 00138 return !__STREXH(desiredValue, (volatile uint16_t*)ptr); 00139 } 00140 00141 00142 bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue) 00143 { 00144 uint32_t currentValue = __LDREXW((volatile uint32_t*)ptr); 00145 if (currentValue != *expectedCurrentValue) { 00146 *expectedCurrentValue = currentValue; 00147 __CLREX(); 00148 return false; 00149 } 00150 00151 return !__STREXW(desiredValue, (volatile uint32_t*)ptr); 00152 } 00153 00154 uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta) 00155 { 00156 uint8_t newValue; 00157 do { 00158 newValue = __LDREXB((volatile uint8_t*)valuePtr) + delta; 00159 } while (__STREXB(newValue, (volatile uint8_t*)valuePtr)); 00160 return newValue; 00161 } 00162 00163 uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta) 00164 { 00165 uint16_t newValue; 00166 do { 00167 newValue = __LDREXH((volatile uint16_t*)valuePtr) + delta; 00168 } while (__STREXH(newValue, (volatile uint16_t*)valuePtr)); 00169 return newValue; 00170 } 00171 00172 uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta) 00173 { 00174 uint32_t newValue; 00175 do { 00176 newValue = __LDREXW((volatile uint32_t*)valuePtr) + delta; 00177 } while (__STREXW(newValue, (volatile uint32_t*)valuePtr)); 00178 return newValue; 00179 } 00180 00181 00182 uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta) 00183 { 00184 uint8_t newValue; 00185 do { 00186 newValue = __LDREXB((volatile uint8_t*)valuePtr) - delta; 00187 } while (__STREXB(newValue, (volatile uint8_t*)valuePtr)); 00188 return newValue; 00189 } 00190 00191 uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta) 00192 { 00193 uint16_t newValue; 00194 do { 00195 newValue = __LDREXH((volatile uint16_t*)valuePtr) - delta; 00196 } while (__STREXH(newValue, (volatile uint16_t*)valuePtr)); 00197 return newValue; 00198 } 00199 00200 uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta) 00201 { 00202 uint32_t newValue; 00203 do { 00204 newValue = __LDREXW((volatile uint32_t*)valuePtr) - delta; 00205 } while (__STREXW(newValue, (volatile uint32_t*)valuePtr)); 00206 return newValue; 00207 } 00208 00209 #else 00210 00211 bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue) 00212 { 00213 bool success; 00214 uint8_t currentValue; 00215 core_util_critical_section_enter(); 00216 currentValue = *ptr; 00217 if (currentValue == *expectedCurrentValue) { 00218 *ptr = desiredValue; 00219 success = true; 00220 } else { 00221 *expectedCurrentValue = currentValue; 00222 success = false; 00223 } 00224 core_util_critical_section_exit(); 00225 return success; 00226 } 00227 00228 bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue) 00229 { 00230 bool success; 00231 uint16_t currentValue; 00232 core_util_critical_section_enter(); 00233 currentValue = *ptr; 00234 if (currentValue == *expectedCurrentValue) { 00235 *ptr = desiredValue; 00236 success = true; 00237 } else { 00238 *expectedCurrentValue = currentValue; 00239 success = false; 00240 } 00241 core_util_critical_section_exit(); 00242 return success; 00243 } 00244 00245 00246 bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue) 00247 { 00248 bool success; 00249 uint32_t currentValue; 00250 core_util_critical_section_enter(); 00251 currentValue = *ptr; 00252 if (currentValue == *expectedCurrentValue) { 00253 *ptr = desiredValue; 00254 success = true; 00255 } else { 00256 *expectedCurrentValue = currentValue; 00257 success = false; 00258 } 00259 core_util_critical_section_exit(); 00260 return success; 00261 } 00262 00263 00264 uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta) 00265 { 00266 uint8_t newValue; 00267 core_util_critical_section_enter(); 00268 newValue = *valuePtr + delta; 00269 *valuePtr = newValue; 00270 core_util_critical_section_exit(); 00271 return newValue; 00272 } 00273 00274 uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta) 00275 { 00276 uint16_t newValue; 00277 core_util_critical_section_enter(); 00278 newValue = *valuePtr + delta; 00279 *valuePtr = newValue; 00280 core_util_critical_section_exit(); 00281 return newValue; 00282 } 00283 00284 uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta) 00285 { 00286 uint32_t newValue; 00287 core_util_critical_section_enter(); 00288 newValue = *valuePtr + delta; 00289 *valuePtr = newValue; 00290 core_util_critical_section_exit(); 00291 return newValue; 00292 } 00293 00294 00295 uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta) 00296 { 00297 uint8_t newValue; 00298 core_util_critical_section_enter(); 00299 newValue = *valuePtr - delta; 00300 *valuePtr = newValue; 00301 core_util_critical_section_exit(); 00302 return newValue; 00303 } 00304 00305 uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta) 00306 { 00307 uint16_t newValue; 00308 core_util_critical_section_enter(); 00309 newValue = *valuePtr - delta; 00310 *valuePtr = newValue; 00311 core_util_critical_section_exit(); 00312 return newValue; 00313 } 00314 00315 uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta) 00316 { 00317 uint32_t newValue; 00318 core_util_critical_section_enter(); 00319 newValue = *valuePtr - delta; 00320 *valuePtr = newValue; 00321 core_util_critical_section_exit(); 00322 return newValue; 00323 } 00324 00325 #endif 00326 00327 00328 bool core_util_atomic_cas_ptr(void **ptr, void **expectedCurrentValue, void *desiredValue) { 00329 return core_util_atomic_cas_u32( 00330 (uint32_t *)ptr, 00331 (uint32_t *)expectedCurrentValue, 00332 (uint32_t)desiredValue); 00333 } 00334 00335 void *core_util_atomic_incr_ptr(void **valuePtr, ptrdiff_t delta) { 00336 return (void *)core_util_atomic_incr_u32((uint32_t *)valuePtr, (uint32_t)delta); 00337 } 00338 00339 void *core_util_atomic_decr_ptr(void **valuePtr, ptrdiff_t delta) { 00340 return (void *)core_util_atomic_decr_u32((uint32_t *)valuePtr, (uint32_t)delta); 00341 } 00342
Generated on Tue Jul 12 2022 16:02:32 by 1.7.2