source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/platform/mbed_critical.c@ 352

Last change on this file since 352 was 352, checked in by coas-nagasima, 6 years ago

arm向けASP3版ECNLを追加

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