WORKS

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Committer:
cyberjoey
Date:
Sat Oct 22 01:31:58 2016 +0000
Revision:
9:6bb35cef007d
Parent:
1:55a6170b404f
WORKING

Who changed what in which revision?

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