mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: platform/CThunkBase.cpp
- Revision:
- 189:f392fc9709a3
diff -r bcfe06ba3d64 -r f392fc9709a3 platform/CThunkBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/platform/CThunkBase.cpp Wed Feb 20 22:31:08 2019 +0000 @@ -0,0 +1,145 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "platform/platform.h" +#include "platform/mbed_critical.h" +#include "platform/mbed_assert.h" +#include "platform/mbed_error.h" + + +#include "CThunkBase.h" + +MBED_STATIC_ASSERT(MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX < 256, "MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX must be less than 256"); +MBED_STATIC_ASSERT(MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX > 0, "MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX must be greater than 0"); + +#define ENABLE_N(N) ((MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX & N) ? 1 : 0) + +#define START_128 0 +#define START_64 (START_128 + ENABLE_N(128) * 128) +#define START_32 (START_64 + ENABLE_N(64) * 64) +#define START_16 (START_32 + ENABLE_N(32) * 32) +#define START_8 (START_16 + ENABLE_N(16) * 16) +#define START_4 (START_8 + ENABLE_N(8) * 8) +#define START_2 (START_4 + ENABLE_N(4) * 4) +#define START_1 (START_2 + ENABLE_N(2) * 2) + +#define DECLARE_THUNK128(start) \ + DECLARE_THUNK64(start), \ + DECLARE_THUNK64(start + 64) +#define DECLARE_THUNK64(start) \ + DECLARE_THUNK32(start), \ + DECLARE_THUNK32(start + 32) +#define DECLARE_THUNK32(start) \ + DECLARE_THUNK16(start), \ + DECLARE_THUNK16(start + 16) +#define DECLARE_THUNK16(start) \ + DECLARE_THUNK8(start), \ + DECLARE_THUNK8(start + 8) +#define DECLARE_THUNK8(start) \ + DECLARE_THUNK4(start), \ + DECLARE_THUNK4(start + 4) +#define DECLARE_THUNK4(start) \ + DECLARE_THUNK2(start), \ + DECLARE_THUNK2(start + 2) +#define DECLARE_THUNK2(start) \ + DECLARE_THUNK1(start), \ + DECLARE_THUNK1(start + 1) +#define DECLARE_THUNK1(index) &CThunkBase::thunk_entry<index> + +const CThunkEntry CThunkBase::_thunk_table[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX] = { +#if ENABLE_N(128) + DECLARE_THUNK128(START_128), +#endif +#if ENABLE_N(64) + DECLARE_THUNK64(START_64), +#endif +#if ENABLE_N(32) + DECLARE_THUNK32(START_32), +#endif +#if ENABLE_N(16) + DECLARE_THUNK16(START_16), +#endif +#if ENABLE_N(8) + DECLARE_THUNK8(START_8), +#endif +#if ENABLE_N(4) + DECLARE_THUNK4(START_4), +#endif +#if ENABLE_N(2) + DECLARE_THUNK2(START_2), +#endif +#if ENABLE_N(1) + DECLARE_THUNK1(START_1) +#endif +}; + +CThunkBase *CThunkBase::_thunk_storage[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX]; + +CThunkBase::CthunkFree CThunkBase::_cthunk_free_real = NULL; + +CThunkEntry CThunkBase::cthunk_alloc(CThunkBase *cthunk) +{ + // Atomically allocate one entry + core_util_critical_section_enter(); + CThunkEntry entry = NULL; + for (int i = 0; i < MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX; i++) { + if (_thunk_storage[i] == NULL) { + _thunk_storage[i] = cthunk; + entry = _thunk_table[i]; + break; + } + } + core_util_critical_section_exit(); + + if (entry == NULL) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_RESOURCES), "Ran out of CThunk entries. Increase MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX to fix this error"); + } + + // Set function pointer on first use. This allows _thunk_table + // and _thunk_storage to get removed by the linker if + // cthunk_alloc is never used. + _cthunk_free_real = &cthunk_free_real; + + return entry; +} + +void CThunkBase::cthunk_free(CThunkEntry item) +{ + if (_cthunk_free_real) { + _cthunk_free_real(item); + } +} + +void CThunkBase::cthunk_free_real(CThunkEntry item) +{ + bool found = false; + + core_util_critical_section_enter(); + for (int i = 0; i < MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX; i++) { + if (_thunk_table[i] == item) { + _thunk_storage[i] = NULL; + found = true; + break; + } + } + core_util_critical_section_exit(); + + if (!found) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT), "Tried to free invalid CThunkEntry"); + } + +}