MCU driver/HAL for the Picocell Gateway concentrator board. The firmware implements either a USB CDC protocol or a UART protocol to bridge commands coming from host to the SX1308 SPI interface.

Committer:
dgabino
Date:
Wed Apr 11 14:42:47 2018 +0000
Revision:
0:c76361bd82e8
Initial commit

Who changed what in which revision?

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