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