joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mtimerpimpl.cpp Source File

m2mtimerpimpl.cpp

00001 /*
00002  * Copyright (c) 2015-2016 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include <assert.h>
00018 #include <time.h>
00019 
00020 #include "mbed-client-classic/m2mtimerpimpl.h"
00021 #include "mbed-client/m2mtimerobserver.h"
00022 #include "mbed-client/m2mvector.h"
00023 
00024 #include "eventOS_event.h"
00025 #include "eventOS_event_timer.h"
00026 #include "eventOS_scheduler.h"
00027 #include "ns_hal_init.h"
00028 #include "mbed-trace/mbed_trace.h"
00029 
00030 #define TRACE_GROUP "mClt"
00031 
00032 #define MBED_CLIENT_TIMER_EVENT 10
00033 
00034 #ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
00035 #define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
00036 #else
00037 #define MBED_CLIENT_EVENT_LOOP_SIZE 1024
00038 #endif
00039 
00040 int8_t M2MTimerPimpl::_tasklet_id = -1;
00041 
00042 int8_t M2MTimerPimpl::_next_timer_id = 1;
00043 
00044 static m2m::Vector<M2MTimerPimpl*> timer_impl_list;
00045 
00046 extern "C" void tasklet_func(arm_event_s *event)
00047 {
00048     // skip the init event as there will be a timer event after
00049     if (event->event_type == MBED_CLIENT_TIMER_EVENT) {
00050 
00051         bool timer_found = false;
00052         eventOS_scheduler_mutex_wait();
00053         int timer_count = timer_impl_list.size();
00054         for (int index = 0; index < timer_count; index++) {
00055             M2MTimerPimpl* timer = timer_impl_list[index];
00056             if (timer->get_timer_id() == event->event_id) {
00057                 eventOS_scheduler_mutex_release();
00058                 timer_found = true;
00059                 timer->timer_expired();
00060                 break;
00061             }
00062         }
00063         if(!timer_found) {
00064             eventOS_scheduler_mutex_release();
00065         }
00066     }
00067 }
00068 
00069 M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer)
00070 : _observer(observer),
00071   _single_shot(true),
00072   _interval(0),
00073   _type(M2MTimerObserver::Notdefined),
00074   _intermediate_interval(0),
00075   _total_interval(0),
00076   _status(0),
00077   _dtls_type(false)
00078 {
00079     ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL);
00080     eventOS_scheduler_mutex_wait();
00081     if (_tasklet_id < 0) {
00082         _tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_EVENT);
00083         assert(_tasklet_id >= 0);
00084     }
00085 
00086     // XXX: this wraps over quite soon
00087     _timer_id = M2MTimerPimpl::_next_timer_id++;
00088 
00089     timer_impl_list.push_back(this);
00090     eventOS_scheduler_mutex_release();
00091 }
00092 
00093 M2MTimerPimpl::~M2MTimerPimpl()
00094 {
00095     // cancel the timer request, if any is pending
00096     cancel();
00097 
00098     // there is no turning back, event os does not have eventOS_event_handler_delete() or similar,
00099     // so the tasklet is lost forever. Same goes with timer_impl_list, which leaks now memory.
00100 
00101     // remove the timer from object list
00102     eventOS_scheduler_mutex_wait();
00103     int timer_count = timer_impl_list.size();
00104     for (int index = 0; index < timer_count; index++) {
00105 
00106         const M2MTimerPimpl* timer = timer_impl_list[index];
00107         if (timer->get_timer_id() == _timer_id) {
00108 
00109             timer_impl_list.erase(index);
00110             break;
00111         }
00112     }
00113     eventOS_scheduler_mutex_release();
00114 }
00115 
00116 void M2MTimerPimpl::start_timer( uint64_t interval,
00117                                  M2MTimerObserver::Type type,
00118                                  bool single_shot)
00119 {
00120     assert(interval <= INT32_MAX);
00121 
00122     _dtls_type = false;
00123     _intermediate_interval = 0;
00124     _total_interval = 0;
00125     _status = 0;
00126     _single_shot = single_shot;
00127     _interval = interval;
00128     _type = type;
00129     start();
00130 }
00131 
00132 void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type)
00133 {
00134     assert(intermediate_interval <= INT32_MAX);
00135     assert(intermediate_interval <= total_interval);
00136 
00137     _dtls_type = true;
00138     _intermediate_interval = intermediate_interval;
00139     _total_interval = total_interval;
00140     _interval = _intermediate_interval;
00141     _status = 0;
00142     _single_shot = false;
00143     _type = type;
00144     start();
00145 }
00146 
00147 void M2MTimerPimpl::start()
00148 {
00149     int status;
00150 
00151     status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT,
00152                                             M2MTimerPimpl::_tasklet_id,
00153                                             _interval);
00154     assert(status == 0);
00155 }
00156 
00157 void M2MTimerPimpl::cancel()
00158 {
00159     eventOS_event_timer_cancel(_timer_id, M2MTimerPimpl::_tasklet_id);
00160 }
00161 
00162 void M2MTimerPimpl::stop_timer()
00163 {
00164     _interval = 0;
00165     _single_shot = true;
00166     cancel();
00167 }
00168 
00169 void M2MTimerPimpl::timer_expired()
00170 {
00171     _status++;
00172     _observer.timer_expired(_type);
00173 
00174     if ((!_dtls_type) && (!_single_shot)) {
00175         // start next round of periodic timer
00176         start();
00177     } else if ((_dtls_type) && (!is_total_interval_passed())) {
00178         // if only the intermediate time has passed, we need still wait up to total time
00179         _interval = _total_interval - _intermediate_interval;
00180         start();
00181     }
00182 }
00183 
00184 bool M2MTimerPimpl::is_intermediate_interval_passed()
00185 {
00186     if (_status > 0) {
00187         return true;
00188     }
00189     return false;
00190 }
00191 
00192 bool M2MTimerPimpl::is_total_interval_passed()
00193 {
00194     if (_status > 1) {
00195         return true;
00196     }
00197     return false;
00198 }