Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers equeue_mbed.cpp Source File

equeue_mbed.cpp

00001 /*
00002  * Implementation for the mbed library
00003  * https://github.com/mbedmicro/mbed
00004  *
00005  * Copyright (c) 2016-2019 ARM Limited
00006  *
00007  * Licensed under the Apache License, Version 2.0 (the "License");
00008  * you may not use this file except in compliance with the License.
00009  * You may obtain a copy of the License at
00010  *
00011  *     http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  * Unless required by applicable law or agreed to in writing, software
00014  * distributed under the License is distributed on an "AS IS" BASIS,
00015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  * See the License for the specific language governing permissions and
00017  * limitations under the License.
00018  */
00019 #include "events/internal/equeue_platform.h"
00020 
00021 #if defined(EQUEUE_PLATFORM_MBED)
00022 
00023 #include <stdbool.h>
00024 #include <string.h>
00025 #include "cmsis.h"
00026 #include "platform/mbed_critical.h"
00027 #include "platform/mbed_power_mgmt.h"
00028 #include "drivers/Timer.h"
00029 #include "drivers/Ticker.h"
00030 #include "drivers/Timeout.h"
00031 #include "drivers/LowPowerTimeout.h"
00032 #include "drivers/LowPowerTicker.h"
00033 #include "drivers/LowPowerTimer.h"
00034 
00035 using namespace mbed;
00036 
00037 // Ticker operations
00038 #if MBED_CONF_RTOS_API_PRESENT
00039 
00040 #include "rtos/Kernel.h"
00041 #include "platform/source/mbed_os_timer.h"
00042 
00043 void equeue_tick_init()
00044 {
00045 #if defined MBED_TICKLESS || !MBED_CONF_RTOS_PRESENT
00046     mbed::internal::init_os_timer();
00047 #endif
00048 }
00049 
00050 unsigned equeue_tick()
00051 {
00052 #if defined MBED_TICKLESS || !MBED_CONF_RTOS_PRESENT
00053     // It is not safe to call get_ms_count from ISRs, both
00054     // because documentation says so, and because it will give
00055     // a stale value from the RTOS if the interrupt has woken
00056     // us out of sleep - the RTOS will not have updated its
00057     // ticks yet.
00058     if (core_util_is_isr_active()) {
00059         // And the documentation further says that this
00060         // should not be called from critical sections, for
00061         // performance reasons, but I don't have a good
00062         // current alternative!
00063         return mbed::internal::os_timer->get_time() / 1000;
00064     } else {
00065         return rtos::Kernel::get_ms_count();
00066     }
00067 #else
00068     // And this is the legacy behaviour - if running in
00069     // non-tickless mode, this works fine, despite Mbed OS
00070     // documentation saying no. (Most recent CMSIS-RTOS
00071     // permits `ososKernelGetTickCount` from IRQ, and our
00072     // `rtos::Kernel` wrapper copes too).
00073     return rtos::Kernel::get_ms_count();
00074 #endif
00075 }
00076 
00077 #else
00078 
00079 #if MBED_CONF_EVENTS_USE_LOWPOWER_TIMER_TICKER
00080 
00081 #define ALIAS_TIMER      LowPowerTimer
00082 #define ALIAS_TICKER     LowPowerTicker
00083 #define ALIAS_TIMEOUT    LowPowerTimeout
00084 #else
00085 #define ALIAS_TIMER      Timer
00086 #define ALIAS_TICKER     Ticker
00087 #define ALIAS_TIMEOUT    Timeout
00088 #endif
00089 
00090 static volatile unsigned equeue_minutes = 0;
00091 static unsigned equeue_timer[
00092      (sizeof(ALIAS_TIMER) + sizeof(unsigned) - 1) / sizeof(unsigned)];
00093 static unsigned equeue_ticker[
00094      (sizeof(ALIAS_TICKER) + sizeof(unsigned) - 1) / sizeof(unsigned)];
00095 
00096 static void equeue_tick_update()
00097 {
00098     equeue_minutes += reinterpret_cast<ALIAS_TIMER *>(equeue_timer)->read_ms();
00099     reinterpret_cast<ALIAS_TIMER *>(equeue_timer)->reset();
00100 }
00101 
00102 void equeue_tick_init()
00103 {
00104     MBED_STATIC_ASSERT(sizeof(equeue_timer) >= sizeof(ALIAS_TIMER),
00105                        "The equeue_timer buffer must fit the class Timer");
00106     MBED_STATIC_ASSERT(sizeof(equeue_ticker) >= sizeof(ALIAS_TICKER),
00107                        "The equeue_ticker buffer must fit the class Ticker");
00108     ALIAS_TIMER *timer = new (equeue_timer) ALIAS_TIMER;
00109     ALIAS_TICKER *ticker = new (equeue_ticker) ALIAS_TICKER;
00110 
00111     equeue_minutes = 0;
00112     timer->start();
00113     ticker->attach_us(equeue_tick_update, 1000 << 16);
00114 }
00115 
00116 unsigned equeue_tick()
00117 {
00118     unsigned minutes;
00119     unsigned ms;
00120 
00121     do {
00122         minutes = equeue_minutes;
00123         ms = reinterpret_cast<ALIAS_TIMER *>(equeue_timer)->read_ms();
00124     } while (minutes != equeue_minutes);
00125 
00126     return minutes + ms;
00127 }
00128 
00129 #endif
00130 
00131 // Mutex operations
00132 int equeue_mutex_create(equeue_mutex_t *m)
00133 {
00134     return 0;
00135 }
00136 void equeue_mutex_destroy(equeue_mutex_t *m) { }
00137 
00138 void equeue_mutex_lock(equeue_mutex_t *m)
00139 {
00140     core_util_critical_section_enter();
00141 }
00142 
00143 void equeue_mutex_unlock(equeue_mutex_t *m)
00144 {
00145     core_util_critical_section_exit();
00146 }
00147 
00148 
00149 // Semaphore operations
00150 #ifdef MBED_CONF_RTOS_API_PRESENT
00151 
00152 #include "rtos/EventFlags.h"
00153 
00154 MBED_STATIC_ASSERT(sizeof(equeue_sema_t) == sizeof(rtos::EventFlags), "equeue_sema_t / rtos::EventFlags mismatch");
00155 
00156 int equeue_sema_create(equeue_sema_t *s)
00157 {
00158     new (s) rtos::EventFlags("equeue");
00159     return 0;
00160 }
00161 
00162 void equeue_sema_destroy(equeue_sema_t *s)
00163 {
00164     rtos::EventFlags *ef = reinterpret_cast<rtos::EventFlags *>(s);
00165     ef->~EventFlags();
00166 }
00167 
00168 void equeue_sema_signal(equeue_sema_t *s)
00169 {
00170     rtos::EventFlags *ef = reinterpret_cast<rtos::EventFlags *>(s);
00171     ef->set(1);
00172 }
00173 
00174 bool equeue_sema_wait(equeue_sema_t *s, int ms)
00175 {
00176     if (ms < 0) {
00177         ms = osWaitForever;
00178     }
00179 
00180     rtos::EventFlags *ef = reinterpret_cast<rtos::EventFlags *>(s);
00181     return ef->wait_any(1, ms) == 1;
00182 }
00183 
00184 #else
00185 
00186 // Semaphore operations
00187 int equeue_sema_create(equeue_sema_t *s)
00188 {
00189     *s = 0;
00190     return 0;
00191 }
00192 
00193 void equeue_sema_destroy(equeue_sema_t *s)
00194 {
00195 }
00196 
00197 void equeue_sema_signal(equeue_sema_t *s)
00198 {
00199     *s = 1;
00200 }
00201 
00202 static void equeue_sema_timeout(equeue_sema_t *s)
00203 {
00204     *s = -1;
00205 }
00206 
00207 bool equeue_sema_wait(equeue_sema_t *s, int ms)
00208 {
00209     ALIAS_TIMEOUT timeout;
00210     if (ms > 0) {
00211         timeout.attach_us(callback(equeue_sema_timeout, s), (us_timestamp_t)ms * 1000);
00212     }
00213 
00214     core_util_critical_section_enter();
00215     while (!*s && ms != 0) {
00216         sleep();
00217         core_util_critical_section_exit();
00218         __ISB();
00219         core_util_critical_section_enter();
00220     }
00221 
00222     int signal = *s;
00223     *s = 0;
00224     core_util_critical_section_exit();
00225 
00226     return (signal > 0);
00227 }
00228 
00229 #endif
00230 
00231 #endif