Toyomasa Watarai
/
Mbed-example-WS-W27
Mbed Cloud example program for workshop in W27 2018.
Embed:
(wiki syntax)
Show/hide line numbers
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 00029 #define MBED_CLIENT_TIMER_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet 00030 #define MBED_CLIENT_TIMER_EVENT 10 00031 00032 #ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE 00033 #define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE 00034 #else 00035 #define MBED_CLIENT_EVENT_LOOP_SIZE 1024 00036 #endif 00037 00038 int8_t M2MTimerPimpl::_tasklet_id = -1; 00039 00040 int8_t M2MTimerPimpl::_next_timer_id = 1; 00041 00042 static m2m::Vector<M2MTimerPimpl*> timer_impl_list; 00043 00044 extern "C" void tasklet_func(arm_event_s *event) 00045 { 00046 // skip the init event as there will be a timer event after 00047 if (event->event_type == MBED_CLIENT_TIMER_EVENT) { 00048 bool timer_found = false; 00049 eventOS_scheduler_mutex_wait(); 00050 int timer_count = timer_impl_list.size(); 00051 for (int index = 0; index < timer_count; index++) { 00052 M2MTimerPimpl* timer = timer_impl_list[index]; 00053 if (timer->get_timer_id() == event->event_id) { 00054 eventOS_scheduler_mutex_release(); 00055 timer_found = true; 00056 if (timer->get_still_left_time() > 0) { 00057 timer->start_still_left_timer(); 00058 }else { 00059 timer->timer_expired(); 00060 } 00061 break; 00062 } 00063 } 00064 if(!timer_found) { 00065 eventOS_scheduler_mutex_release(); 00066 } 00067 } 00068 } 00069 00070 M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer) 00071 : _observer(observer), 00072 _single_shot(true), 00073 _interval(0), 00074 _type(M2MTimerObserver::Notdefined), 00075 _intermediate_interval(0), 00076 _total_interval(0), 00077 _still_left(0), 00078 _status(0), 00079 _dtls_type(false) 00080 { 00081 ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL); 00082 eventOS_scheduler_mutex_wait(); 00083 if (_tasklet_id < 0) { 00084 _tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_TASKLET_INIT_EVENT); 00085 assert(_tasklet_id >= 0); 00086 } 00087 00088 // XXX: this wraps over quite soon 00089 _timer_id = M2MTimerPimpl::_next_timer_id++; 00090 timer_impl_list.push_back(this); 00091 eventOS_scheduler_mutex_release(); 00092 } 00093 00094 M2MTimerPimpl::~M2MTimerPimpl() 00095 { 00096 // cancel the timer request, if any is pending 00097 cancel(); 00098 00099 // there is no turning back, event os does not have eventOS_event_handler_delete() or similar, 00100 // so the tasklet is lost forever. Same goes with timer_impl_list, which leaks now memory. 00101 00102 // remove the timer from object list 00103 eventOS_scheduler_mutex_wait(); 00104 int timer_count = timer_impl_list.size(); 00105 for (int index = 0; index < timer_count; index++) { 00106 const M2MTimerPimpl* timer = timer_impl_list[index]; 00107 if (timer->get_timer_id() == _timer_id) { 00108 timer_impl_list.erase(index); 00109 break; 00110 } 00111 } 00112 eventOS_scheduler_mutex_release(); 00113 } 00114 00115 void M2MTimerPimpl::start_timer( uint64_t interval, 00116 M2MTimerObserver::Type type, 00117 bool single_shot) 00118 { 00119 _dtls_type = false; 00120 _intermediate_interval = 0; 00121 _total_interval = 0; 00122 _status = 0; 00123 _single_shot = single_shot; 00124 _interval = interval; 00125 _type = type; 00126 _still_left = 0; 00127 start(); 00128 } 00129 00130 void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type) 00131 { 00132 _dtls_type = true; 00133 _intermediate_interval = intermediate_interval; 00134 _total_interval = total_interval; 00135 _interval = _intermediate_interval; 00136 _status = 0; 00137 _single_shot = false; 00138 _type = type; 00139 start(); 00140 } 00141 00142 void M2MTimerPimpl::start() 00143 { 00144 int status; 00145 if(_interval > INT32_MAX) { 00146 _still_left = _interval - INT32_MAX; 00147 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00148 M2MTimerPimpl::_tasklet_id, 00149 INT32_MAX); 00150 } 00151 else { 00152 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00153 M2MTimerPimpl::_tasklet_id, 00154 _interval); 00155 } 00156 assert(status == 0); 00157 } 00158 00159 void M2MTimerPimpl::cancel() 00160 { 00161 eventOS_event_timer_cancel(_timer_id, M2MTimerPimpl::_tasklet_id); 00162 } 00163 00164 void M2MTimerPimpl::stop_timer() 00165 { 00166 _interval = 0; 00167 _single_shot = true; 00168 _still_left = 0; 00169 cancel(); 00170 } 00171 00172 void M2MTimerPimpl::timer_expired() 00173 { 00174 _status++; 00175 _observer.timer_expired(_type); 00176 00177 if ((!_dtls_type) && (!_single_shot)) { 00178 // start next round of periodic timer 00179 start(); 00180 } else if ((_dtls_type) && (!is_total_interval_passed())) { 00181 // if only the intermediate time has passed, we need still wait up to total time 00182 _interval = _total_interval - _intermediate_interval; 00183 start(); 00184 } 00185 } 00186 00187 bool M2MTimerPimpl::is_intermediate_interval_passed() 00188 { 00189 if (_status > 0) { 00190 return true; 00191 } 00192 return false; 00193 } 00194 00195 bool M2MTimerPimpl::is_total_interval_passed() 00196 { 00197 if (_status > 1) { 00198 return true; 00199 } 00200 return false; 00201 } 00202 00203 uint64_t M2MTimerPimpl::get_still_left_time() const 00204 { 00205 return _still_left; 00206 } 00207 00208 void M2MTimerPimpl::start_still_left_timer() 00209 { 00210 if (_still_left > 0) { 00211 int status; 00212 if( _still_left > INT32_MAX) { 00213 _still_left = _still_left - INT32_MAX; 00214 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00215 M2MTimerPimpl::_tasklet_id, 00216 INT32_MAX); 00217 } 00218 else { 00219 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00220 M2MTimerPimpl::_tasklet_id, 00221 _still_left); 00222 _still_left = 0; 00223 } 00224 assert(status == 0); 00225 } else { 00226 _observer.timer_expired(_type); 00227 if(!_single_shot) { 00228 start_timer(_interval, _type, _single_shot); 00229 } 00230 } 00231 }
Generated on Tue Jul 12 2022 16:22:07 by 1.7.2