Nicolas Borla / Mbed OS ROME2_Robot_Firmware
Committer:
boro
Date:
Tue Mar 09 13:10:40 2021 +0000
Revision:
3:6fe17b8a6d62
Parent:
0:4beb2ea291ec
SDBlockDevice added

Who changed what in which revision?

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