,,

Fork of Application by Daniel Sygut

Committer:
Zaitsev
Date:
Tue Jan 10 20:42:26 2017 +0000
Revision:
10:41552d038a69
USB Serial bi-directional bridge

Who changed what in which revision?

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