Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_hal_fhss_timer.cpp Source File

arm_hal_fhss_timer.cpp

00001 /*
00002  * Copyright (c) 2018-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #ifdef MBED_CONF_NANOSTACK_CONFIGURATION
00019 
00020 #include "ns_types.h"
00021 #include "fhss_api.h "
00022 #include "fhss_config.h "
00023 #include "mbed_trace.h"
00024 #include "platform/SingletonPtr.h"
00025 #include "platform/arm_hal_interrupt.h"
00026 #include <Timer.h>
00027 #include "equeue.h"
00028 #include "events/EventQueue.h"
00029 #include "mbed_shared_queues.h"
00030 #include "Timeout.h"
00031 
00032 #define TRACE_GROUP "fhdr"
00033 #ifndef NUMBER_OF_SIMULTANEOUS_TIMEOUTS
00034 #define NUMBER_OF_SIMULTANEOUS_TIMEOUTS  2
00035 #endif //NUMBER_OF_SIMULTANEOUS_TIMEOUTS
00036 
00037 namespace {
00038 using namespace mbed;
00039 using namespace events;
00040 
00041 static SingletonPtr<Timer> timer;
00042 static bool timer_initialized = false;
00043 static const fhss_api_t *fhss_active_handle = NULL;
00044 #if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
00045 static EventQueue *equeue;
00046 #endif
00047 
00048 // All members of fhss_timeout_s must be initialized to make the structure
00049 // constant-initialized, and hence able to be omitted by the linker,
00050 // as SingletonPtr now relies on C++ constant-initialization. (Previously it
00051 // worked through C++ zero-initialization). And all the constants should be zero
00052 // to ensure it stays in the actual zero-init part of the image if used, avoiding
00053 // an initialized-data cost.
00054 struct fhss_timeout_s {
00055     void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t) = nullptr;
00056     uint32_t start_time = 0;
00057     uint32_t stop_time = 0;
00058     bool active = false;
00059     SingletonPtr<Timeout>  timeout;
00060 };
00061 
00062 fhss_timeout_s fhss_timeout[NUMBER_OF_SIMULTANEOUS_TIMEOUTS];
00063 
00064 static uint32_t read_current_time(void)
00065 {
00066     return timer->read_us();
00067 }
00068 
00069 static fhss_timeout_s *find_timeout(void (*callback)(const fhss_api_t *api, uint16_t))
00070 {
00071     for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
00072         if (fhss_timeout[i].fhss_timer_callback == callback) {
00073             return &fhss_timeout[i];
00074         }
00075     }
00076     return NULL;
00077 }
00078 
00079 static fhss_timeout_s *allocate_timeout(void)
00080 {
00081     for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
00082         if (fhss_timeout[i].fhss_timer_callback == NULL) {
00083             return &fhss_timeout[i];
00084         }
00085     }
00086     return NULL;
00087 }
00088 
00089 static void fhss_timeout_handler(void)
00090 {
00091     for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
00092         if (fhss_timeout[i].active && ((fhss_timeout[i].stop_time - fhss_timeout[i].start_time) <= (read_current_time() - fhss_timeout[i].start_time))) {
00093             fhss_timeout[i].active = false;
00094             fhss_timeout[i].fhss_timer_callback(fhss_active_handle, read_current_time() - fhss_timeout[i].stop_time);
00095         }
00096     }
00097 }
00098 
00099 static void timer_callback(void)
00100 {
00101 #if MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
00102     fhss_timeout_handler();
00103 #else
00104     equeue->call(fhss_timeout_handler);
00105 #endif
00106 }
00107 
00108 static int platform_fhss_timer_start(uint32_t slots, void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *callback_param)
00109 {
00110     int ret_val = -1;
00111     platform_enter_critical();
00112     if (timer_initialized == false) {
00113 #if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
00114         equeue = mbed_highprio_event_queue();
00115         MBED_ASSERT(equeue != NULL);
00116 #endif
00117         timer->start();
00118         timer_initialized = true;
00119     }
00120     fhss_timeout_s *fhss_tim = find_timeout(callback);
00121     if (!fhss_tim) {
00122         fhss_tim = allocate_timeout();
00123     }
00124     if (!fhss_tim) {
00125         platform_exit_critical();
00126         tr_error("Failed to allocate timeout");
00127         return ret_val;
00128     }
00129     fhss_tim->fhss_timer_callback = callback;
00130     fhss_tim->start_time = read_current_time();
00131     fhss_tim->stop_time = fhss_tim->start_time + slots;
00132     fhss_tim->active = true;
00133     fhss_tim->timeout->attach_us(timer_callback, slots);
00134     fhss_active_handle = callback_param;
00135     ret_val = 0;
00136     platform_exit_critical();
00137     return ret_val;
00138 }
00139 
00140 static int platform_fhss_timer_stop(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api)
00141 {
00142     (void)api;
00143     platform_enter_critical();
00144     fhss_timeout_s *fhss_tim = find_timeout(callback);
00145     if (!fhss_tim) {
00146         platform_exit_critical();
00147         return -1;
00148     }
00149     fhss_tim->timeout->detach();
00150     fhss_tim->active = false;
00151     platform_exit_critical();
00152     return 0;
00153 }
00154 
00155 static uint32_t platform_fhss_get_remaining_slots(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api)
00156 {
00157     (void)api;
00158     platform_enter_critical();
00159     fhss_timeout_s *fhss_tim = find_timeout(callback);
00160     if (!fhss_tim) {
00161         platform_exit_critical();
00162         return 0;
00163     }
00164     uint32_t remaining_slots = fhss_tim->stop_time - read_current_time();
00165     platform_exit_critical();
00166     return remaining_slots;
00167 }
00168 
00169 static uint32_t platform_fhss_timestamp_read(const fhss_api_t *api)
00170 {
00171     (void)api;
00172     return read_current_time();
00173 }
00174 } // anonymous namespace
00175 
00176 fhss_timer_t fhss_functions = {
00177     .fhss_timer_start = platform_fhss_timer_start,
00178     .fhss_timer_stop = platform_fhss_timer_stop,
00179     .fhss_get_remaining_slots = platform_fhss_get_remaining_slots,
00180     .fhss_get_timestamp = platform_fhss_timestamp_read,
00181     .fhss_resolution_divider = 1
00182 };
00183 
00184 #endif