Maxim mbed development library

Dependents:   sensomed

Committer:
switches
Date:
Tue Nov 08 18:27:11 2016 +0000
Revision:
0:0e018d759a2a
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
switches 0:0e018d759a2a 1 /*
switches 0:0e018d759a2a 2 * Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
switches 0:0e018d759a2a 3 * SPDX-License-Identifier: Apache-2.0
switches 0:0e018d759a2a 4 *
switches 0:0e018d759a2a 5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
switches 0:0e018d759a2a 6 * not use this file except in compliance with the License.
switches 0:0e018d759a2a 7 * You may obtain a copy of the License at
switches 0:0e018d759a2a 8 *
switches 0:0e018d759a2a 9 * http://www.apache.org/licenses/LICENSE-2.0
switches 0:0e018d759a2a 10 *
switches 0:0e018d759a2a 11 * Unless required by applicable law or agreed to in writing, software
switches 0:0e018d759a2a 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
switches 0:0e018d759a2a 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
switches 0:0e018d759a2a 14 * See the License for the specific language governing permissions and
switches 0:0e018d759a2a 15 * limitations under the License.
switches 0:0e018d759a2a 16 */
switches 0:0e018d759a2a 17
switches 0:0e018d759a2a 18 #include "platform/critical.h"
switches 0:0e018d759a2a 19
switches 0:0e018d759a2a 20 #include "cmsis.h"
switches 0:0e018d759a2a 21 #include "platform/mbed_assert.h"
switches 0:0e018d759a2a 22 #include "platform/toolchain.h"
switches 0:0e018d759a2a 23
switches 0:0e018d759a2a 24 #define EXCLUSIVE_ACCESS (!defined (__CORTEX_M0) && !defined (__CORTEX_M0PLUS))
switches 0:0e018d759a2a 25
switches 0:0e018d759a2a 26 static volatile uint32_t interrupt_enable_counter = 0;
switches 0:0e018d759a2a 27 static volatile bool critical_interrupts_disabled = false;
switches 0:0e018d759a2a 28
switches 0:0e018d759a2a 29 bool core_util_are_interrupts_enabled(void)
switches 0:0e018d759a2a 30 {
switches 0:0e018d759a2a 31 #if defined(__CORTEX_A9)
switches 0:0e018d759a2a 32 return ((__get_CPSR() & 0x80) == 0);
switches 0:0e018d759a2a 33 #else
switches 0:0e018d759a2a 34 return ((__get_PRIMASK() & 0x1) == 0);
switches 0:0e018d759a2a 35 #endif
switches 0:0e018d759a2a 36 }
switches 0:0e018d759a2a 37
switches 0:0e018d759a2a 38 MBED_WEAK void core_util_critical_section_enter(void)
switches 0:0e018d759a2a 39 {
switches 0:0e018d759a2a 40 bool interrupts_disabled = !core_util_are_interrupts_enabled();
switches 0:0e018d759a2a 41 __disable_irq();
switches 0:0e018d759a2a 42
switches 0:0e018d759a2a 43 /* Save the interrupt disabled state as it was prior to any nested critical section lock use */
switches 0:0e018d759a2a 44 if (!interrupt_enable_counter) {
switches 0:0e018d759a2a 45 critical_interrupts_disabled = interrupts_disabled;
switches 0:0e018d759a2a 46 }
switches 0:0e018d759a2a 47
switches 0:0e018d759a2a 48 /* If the interrupt_enable_counter overflows or we are in a nested critical section and interrupts
switches 0:0e018d759a2a 49 are enabled, then something has gone badly wrong thus assert an error.
switches 0:0e018d759a2a 50 */
switches 0:0e018d759a2a 51 MBED_ASSERT(interrupt_enable_counter < UINT32_MAX);
switches 0:0e018d759a2a 52 // FIXME
switches 0:0e018d759a2a 53 #ifndef FEATURE_UVISOR
switches 0:0e018d759a2a 54 if (interrupt_enable_counter > 0) {
switches 0:0e018d759a2a 55 MBED_ASSERT(interrupts_disabled);
switches 0:0e018d759a2a 56 }
switches 0:0e018d759a2a 57 #else
switches 0:0e018d759a2a 58 #warning "core_util_critical_section_enter needs fixing to work from unprivileged code"
switches 0:0e018d759a2a 59 #endif /* FEATURE_UVISOR */
switches 0:0e018d759a2a 60 interrupt_enable_counter++;
switches 0:0e018d759a2a 61 }
switches 0:0e018d759a2a 62
switches 0:0e018d759a2a 63 MBED_WEAK void core_util_critical_section_exit(void)
switches 0:0e018d759a2a 64 {
switches 0:0e018d759a2a 65 /* If critical_section_enter has not previously been called, do nothing */
switches 0:0e018d759a2a 66 if (interrupt_enable_counter) {
switches 0:0e018d759a2a 67
switches 0:0e018d759a2a 68 // FIXME
switches 0:0e018d759a2a 69 #ifndef FEATURE_UVISOR
switches 0:0e018d759a2a 70 bool interrupts_disabled = !core_util_are_interrupts_enabled(); /* get the current interrupt disabled state */
switches 0:0e018d759a2a 71
switches 0:0e018d759a2a 72 MBED_ASSERT(interrupts_disabled); /* Interrupts must be disabled on invoking an exit from a critical section */
switches 0:0e018d759a2a 73 #else
switches 0:0e018d759a2a 74 #warning "core_util_critical_section_exit needs fixing to work from unprivileged code"
switches 0:0e018d759a2a 75 #endif /* FEATURE_UVISOR */
switches 0:0e018d759a2a 76
switches 0:0e018d759a2a 77 interrupt_enable_counter--;
switches 0:0e018d759a2a 78
switches 0:0e018d759a2a 79 /* Only re-enable interrupts if we are exiting the last of the nested critical sections and
switches 0:0e018d759a2a 80 interrupts were enabled on entry to the first critical section.
switches 0:0e018d759a2a 81 */
switches 0:0e018d759a2a 82 if (!interrupt_enable_counter && !critical_interrupts_disabled) {
switches 0:0e018d759a2a 83 __enable_irq();
switches 0:0e018d759a2a 84 }
switches 0:0e018d759a2a 85 }
switches 0:0e018d759a2a 86 }
switches 0:0e018d759a2a 87
switches 0:0e018d759a2a 88 #if EXCLUSIVE_ACCESS
switches 0:0e018d759a2a 89
switches 0:0e018d759a2a 90 /* Supress __ldrex and __strex deprecated warnings - "#3731-D: intrinsic is deprecated" */
switches 0:0e018d759a2a 91 #if defined (__CC_ARM)
switches 0:0e018d759a2a 92 #pragma diag_suppress 3731
switches 0:0e018d759a2a 93 #endif
switches 0:0e018d759a2a 94
switches 0:0e018d759a2a 95 bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
switches 0:0e018d759a2a 96 {
switches 0:0e018d759a2a 97 uint8_t currentValue = __LDREXB((volatile uint8_t*)ptr);
switches 0:0e018d759a2a 98 if (currentValue != *expectedCurrentValue) {
switches 0:0e018d759a2a 99 *expectedCurrentValue = currentValue;
switches 0:0e018d759a2a 100 __CLREX();
switches 0:0e018d759a2a 101 return false;
switches 0:0e018d759a2a 102 }
switches 0:0e018d759a2a 103
switches 0:0e018d759a2a 104 return !__STREXB(desiredValue, (volatile uint8_t*)ptr);
switches 0:0e018d759a2a 105 }
switches 0:0e018d759a2a 106
switches 0:0e018d759a2a 107 bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
switches 0:0e018d759a2a 108 {
switches 0:0e018d759a2a 109 uint16_t currentValue = __LDREXH((volatile uint16_t*)ptr);
switches 0:0e018d759a2a 110 if (currentValue != *expectedCurrentValue) {
switches 0:0e018d759a2a 111 *expectedCurrentValue = currentValue;
switches 0:0e018d759a2a 112 __CLREX();
switches 0:0e018d759a2a 113 return false;
switches 0:0e018d759a2a 114 }
switches 0:0e018d759a2a 115
switches 0:0e018d759a2a 116 return !__STREXH(desiredValue, (volatile uint16_t*)ptr);
switches 0:0e018d759a2a 117 }
switches 0:0e018d759a2a 118
switches 0:0e018d759a2a 119
switches 0:0e018d759a2a 120 bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
switches 0:0e018d759a2a 121 {
switches 0:0e018d759a2a 122 uint32_t currentValue = __LDREXW((volatile uint32_t*)ptr);
switches 0:0e018d759a2a 123 if (currentValue != *expectedCurrentValue) {
switches 0:0e018d759a2a 124 *expectedCurrentValue = currentValue;
switches 0:0e018d759a2a 125 __CLREX();
switches 0:0e018d759a2a 126 return false;
switches 0:0e018d759a2a 127 }
switches 0:0e018d759a2a 128
switches 0:0e018d759a2a 129 return !__STREXW(desiredValue, (volatile uint32_t*)ptr);
switches 0:0e018d759a2a 130 }
switches 0:0e018d759a2a 131
switches 0:0e018d759a2a 132 uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta)
switches 0:0e018d759a2a 133 {
switches 0:0e018d759a2a 134 uint8_t newValue;
switches 0:0e018d759a2a 135 do {
switches 0:0e018d759a2a 136 newValue = __LDREXB((volatile uint8_t*)valuePtr) + delta;
switches 0:0e018d759a2a 137 } while (__STREXB(newValue, (volatile uint8_t*)valuePtr));
switches 0:0e018d759a2a 138 return newValue;
switches 0:0e018d759a2a 139 }
switches 0:0e018d759a2a 140
switches 0:0e018d759a2a 141 uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta)
switches 0:0e018d759a2a 142 {
switches 0:0e018d759a2a 143 uint16_t newValue;
switches 0:0e018d759a2a 144 do {
switches 0:0e018d759a2a 145 newValue = __LDREXH((volatile uint16_t*)valuePtr) + delta;
switches 0:0e018d759a2a 146 } while (__STREXH(newValue, (volatile uint16_t*)valuePtr));
switches 0:0e018d759a2a 147 return newValue;
switches 0:0e018d759a2a 148 }
switches 0:0e018d759a2a 149
switches 0:0e018d759a2a 150 uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta)
switches 0:0e018d759a2a 151 {
switches 0:0e018d759a2a 152 uint32_t newValue;
switches 0:0e018d759a2a 153 do {
switches 0:0e018d759a2a 154 newValue = __LDREXW((volatile uint32_t*)valuePtr) + delta;
switches 0:0e018d759a2a 155 } while (__STREXW(newValue, (volatile uint32_t*)valuePtr));
switches 0:0e018d759a2a 156 return newValue;
switches 0:0e018d759a2a 157 }
switches 0:0e018d759a2a 158
switches 0:0e018d759a2a 159
switches 0:0e018d759a2a 160 uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta)
switches 0:0e018d759a2a 161 {
switches 0:0e018d759a2a 162 uint8_t newValue;
switches 0:0e018d759a2a 163 do {
switches 0:0e018d759a2a 164 newValue = __LDREXB((volatile uint8_t*)valuePtr) - delta;
switches 0:0e018d759a2a 165 } while (__STREXB(newValue, (volatile uint8_t*)valuePtr));
switches 0:0e018d759a2a 166 return newValue;
switches 0:0e018d759a2a 167 }
switches 0:0e018d759a2a 168
switches 0:0e018d759a2a 169 uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta)
switches 0:0e018d759a2a 170 {
switches 0:0e018d759a2a 171 uint16_t newValue;
switches 0:0e018d759a2a 172 do {
switches 0:0e018d759a2a 173 newValue = __LDREXH((volatile uint16_t*)valuePtr) - delta;
switches 0:0e018d759a2a 174 } while (__STREXH(newValue, (volatile uint16_t*)valuePtr));
switches 0:0e018d759a2a 175 return newValue;
switches 0:0e018d759a2a 176 }
switches 0:0e018d759a2a 177
switches 0:0e018d759a2a 178 uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta)
switches 0:0e018d759a2a 179 {
switches 0:0e018d759a2a 180 uint32_t newValue;
switches 0:0e018d759a2a 181 do {
switches 0:0e018d759a2a 182 newValue = __LDREXW((volatile uint32_t*)valuePtr) - delta;
switches 0:0e018d759a2a 183 } while (__STREXW(newValue, (volatile uint32_t*)valuePtr));
switches 0:0e018d759a2a 184 return newValue;
switches 0:0e018d759a2a 185 }
switches 0:0e018d759a2a 186
switches 0:0e018d759a2a 187 #else
switches 0:0e018d759a2a 188
switches 0:0e018d759a2a 189 bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
switches 0:0e018d759a2a 190 {
switches 0:0e018d759a2a 191 bool success;
switches 0:0e018d759a2a 192 uint8_t currentValue;
switches 0:0e018d759a2a 193 core_util_critical_section_enter();
switches 0:0e018d759a2a 194 currentValue = *ptr;
switches 0:0e018d759a2a 195 if (currentValue == *expectedCurrentValue) {
switches 0:0e018d759a2a 196 *ptr = desiredValue;
switches 0:0e018d759a2a 197 success = true;
switches 0:0e018d759a2a 198 } else {
switches 0:0e018d759a2a 199 *expectedCurrentValue = currentValue;
switches 0:0e018d759a2a 200 success = false;
switches 0:0e018d759a2a 201 }
switches 0:0e018d759a2a 202 core_util_critical_section_exit();
switches 0:0e018d759a2a 203 return success;
switches 0:0e018d759a2a 204 }
switches 0:0e018d759a2a 205
switches 0:0e018d759a2a 206 bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
switches 0:0e018d759a2a 207 {
switches 0:0e018d759a2a 208 bool success;
switches 0:0e018d759a2a 209 uint16_t currentValue;
switches 0:0e018d759a2a 210 core_util_critical_section_enter();
switches 0:0e018d759a2a 211 currentValue = *ptr;
switches 0:0e018d759a2a 212 if (currentValue == *expectedCurrentValue) {
switches 0:0e018d759a2a 213 *ptr = desiredValue;
switches 0:0e018d759a2a 214 success = true;
switches 0:0e018d759a2a 215 } else {
switches 0:0e018d759a2a 216 *expectedCurrentValue = currentValue;
switches 0:0e018d759a2a 217 success = false;
switches 0:0e018d759a2a 218 }
switches 0:0e018d759a2a 219 core_util_critical_section_exit();
switches 0:0e018d759a2a 220 return success;
switches 0:0e018d759a2a 221 }
switches 0:0e018d759a2a 222
switches 0:0e018d759a2a 223
switches 0:0e018d759a2a 224 bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
switches 0:0e018d759a2a 225 {
switches 0:0e018d759a2a 226 bool success;
switches 0:0e018d759a2a 227 uint32_t currentValue;
switches 0:0e018d759a2a 228 core_util_critical_section_enter();
switches 0:0e018d759a2a 229 currentValue = *ptr;
switches 0:0e018d759a2a 230 if (currentValue == *expectedCurrentValue) {
switches 0:0e018d759a2a 231 *ptr = desiredValue;
switches 0:0e018d759a2a 232 success = true;
switches 0:0e018d759a2a 233 } else {
switches 0:0e018d759a2a 234 *expectedCurrentValue = currentValue;
switches 0:0e018d759a2a 235 success = false;
switches 0:0e018d759a2a 236 }
switches 0:0e018d759a2a 237 core_util_critical_section_exit();
switches 0:0e018d759a2a 238 return success;
switches 0:0e018d759a2a 239 }
switches 0:0e018d759a2a 240
switches 0:0e018d759a2a 241
switches 0:0e018d759a2a 242 uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta)
switches 0:0e018d759a2a 243 {
switches 0:0e018d759a2a 244 uint8_t newValue;
switches 0:0e018d759a2a 245 core_util_critical_section_enter();
switches 0:0e018d759a2a 246 newValue = *valuePtr + delta;
switches 0:0e018d759a2a 247 *valuePtr = newValue;
switches 0:0e018d759a2a 248 core_util_critical_section_exit();
switches 0:0e018d759a2a 249 return newValue;
switches 0:0e018d759a2a 250 }
switches 0:0e018d759a2a 251
switches 0:0e018d759a2a 252 uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta)
switches 0:0e018d759a2a 253 {
switches 0:0e018d759a2a 254 uint16_t newValue;
switches 0:0e018d759a2a 255 core_util_critical_section_enter();
switches 0:0e018d759a2a 256 newValue = *valuePtr + delta;
switches 0:0e018d759a2a 257 *valuePtr = newValue;
switches 0:0e018d759a2a 258 core_util_critical_section_exit();
switches 0:0e018d759a2a 259 return newValue;
switches 0:0e018d759a2a 260 }
switches 0:0e018d759a2a 261
switches 0:0e018d759a2a 262 uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta)
switches 0:0e018d759a2a 263 {
switches 0:0e018d759a2a 264 uint32_t newValue;
switches 0:0e018d759a2a 265 core_util_critical_section_enter();
switches 0:0e018d759a2a 266 newValue = *valuePtr + delta;
switches 0:0e018d759a2a 267 *valuePtr = newValue;
switches 0:0e018d759a2a 268 core_util_critical_section_exit();
switches 0:0e018d759a2a 269 return newValue;
switches 0:0e018d759a2a 270 }
switches 0:0e018d759a2a 271
switches 0:0e018d759a2a 272
switches 0:0e018d759a2a 273 uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta)
switches 0:0e018d759a2a 274 {
switches 0:0e018d759a2a 275 uint8_t newValue;
switches 0:0e018d759a2a 276 core_util_critical_section_enter();
switches 0:0e018d759a2a 277 newValue = *valuePtr - delta;
switches 0:0e018d759a2a 278 *valuePtr = newValue;
switches 0:0e018d759a2a 279 core_util_critical_section_exit();
switches 0:0e018d759a2a 280 return newValue;
switches 0:0e018d759a2a 281 }
switches 0:0e018d759a2a 282
switches 0:0e018d759a2a 283 uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta)
switches 0:0e018d759a2a 284 {
switches 0:0e018d759a2a 285 uint16_t newValue;
switches 0:0e018d759a2a 286 core_util_critical_section_enter();
switches 0:0e018d759a2a 287 newValue = *valuePtr - delta;
switches 0:0e018d759a2a 288 *valuePtr = newValue;
switches 0:0e018d759a2a 289 core_util_critical_section_exit();
switches 0:0e018d759a2a 290 return newValue;
switches 0:0e018d759a2a 291 }
switches 0:0e018d759a2a 292
switches 0:0e018d759a2a 293 uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta)
switches 0:0e018d759a2a 294 {
switches 0:0e018d759a2a 295 uint32_t newValue;
switches 0:0e018d759a2a 296 core_util_critical_section_enter();
switches 0:0e018d759a2a 297 newValue = *valuePtr - delta;
switches 0:0e018d759a2a 298 *valuePtr = newValue;
switches 0:0e018d759a2a 299 core_util_critical_section_exit();
switches 0:0e018d759a2a 300 return newValue;
switches 0:0e018d759a2a 301 }
switches 0:0e018d759a2a 302
switches 0:0e018d759a2a 303 #endif
switches 0:0e018d759a2a 304
switches 0:0e018d759a2a 305
switches 0:0e018d759a2a 306 bool core_util_atomic_cas_ptr(void **ptr, void **expectedCurrentValue, void *desiredValue) {
switches 0:0e018d759a2a 307 return core_util_atomic_cas_u32(
switches 0:0e018d759a2a 308 (uint32_t *)ptr,
switches 0:0e018d759a2a 309 (uint32_t *)expectedCurrentValue,
switches 0:0e018d759a2a 310 (uint32_t)desiredValue);
switches 0:0e018d759a2a 311 }
switches 0:0e018d759a2a 312
switches 0:0e018d759a2a 313 void *core_util_atomic_incr_ptr(void **valuePtr, ptrdiff_t delta) {
switches 0:0e018d759a2a 314 return (void *)core_util_atomic_incr_u32((uint32_t *)valuePtr, (uint32_t)delta);
switches 0:0e018d759a2a 315 }
switches 0:0e018d759a2a 316
switches 0:0e018d759a2a 317 void *core_util_atomic_decr_ptr(void **valuePtr, ptrdiff_t delta) {
switches 0:0e018d759a2a 318 return (void *)core_util_atomic_decr_u32((uint32_t *)valuePtr, (uint32_t)delta);
switches 0:0e018d759a2a 319 }
switches 0:0e018d759a2a 320