Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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
Generated on Tue Jul 12 2022 13:54:18 by
