Donald Meyers / Mbed OS evan
Committer:
djmeyers
Date:
Sat Mar 18 22:37:16 2017 +0000
Revision:
0:06ee5f8a484a
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
djmeyers 0:06ee5f8a484a 1 /*
djmeyers 0:06ee5f8a484a 2 * Copyright (c) 2015-2016 ARM Limited. All rights reserved.
djmeyers 0:06ee5f8a484a 3 * SPDX-License-Identifier: Apache-2.0
djmeyers 0:06ee5f8a484a 4 * Licensed under the Apache License, Version 2.0 (the License); you may
djmeyers 0:06ee5f8a484a 5 * not use this file except in compliance with the License.
djmeyers 0:06ee5f8a484a 6 * You may obtain a copy of the License at
djmeyers 0:06ee5f8a484a 7 *
djmeyers 0:06ee5f8a484a 8 * http://www.apache.org/licenses/LICENSE-2.0
djmeyers 0:06ee5f8a484a 9 *
djmeyers 0:06ee5f8a484a 10 * Unless required by applicable law or agreed to in writing, software
djmeyers 0:06ee5f8a484a 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
djmeyers 0:06ee5f8a484a 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
djmeyers 0:06ee5f8a484a 13 * See the License for the specific language governing permissions and
djmeyers 0:06ee5f8a484a 14 * limitations under the License.
djmeyers 0:06ee5f8a484a 15 */
djmeyers 0:06ee5f8a484a 16
djmeyers 0:06ee5f8a484a 17 #include <assert.h>
djmeyers 0:06ee5f8a484a 18 #include <time.h>
djmeyers 0:06ee5f8a484a 19
djmeyers 0:06ee5f8a484a 20 #include "mbed-client-classic/m2mtimerpimpl.h"
djmeyers 0:06ee5f8a484a 21 #include "mbed-client/m2mtimerobserver.h"
djmeyers 0:06ee5f8a484a 22 #include "mbed-client/m2mvector.h"
djmeyers 0:06ee5f8a484a 23
djmeyers 0:06ee5f8a484a 24 #include "eventOS_event.h"
djmeyers 0:06ee5f8a484a 25 #include "eventOS_event_timer.h"
djmeyers 0:06ee5f8a484a 26 #include "eventOS_scheduler.h"
djmeyers 0:06ee5f8a484a 27 #include "ns_hal_init.h"
djmeyers 0:06ee5f8a484a 28
djmeyers 0:06ee5f8a484a 29 #define MBED_CLIENT_TIMER_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet
djmeyers 0:06ee5f8a484a 30 #define MBED_CLIENT_TIMER_EVENT 10
djmeyers 0:06ee5f8a484a 31
djmeyers 0:06ee5f8a484a 32 #ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
djmeyers 0:06ee5f8a484a 33 #define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
djmeyers 0:06ee5f8a484a 34 #else
djmeyers 0:06ee5f8a484a 35 #define MBED_CLIENT_EVENT_LOOP_SIZE 1024
djmeyers 0:06ee5f8a484a 36 #endif
djmeyers 0:06ee5f8a484a 37
djmeyers 0:06ee5f8a484a 38 int8_t M2MTimerPimpl::_tasklet_id = -1;
djmeyers 0:06ee5f8a484a 39
djmeyers 0:06ee5f8a484a 40 int8_t M2MTimerPimpl::_next_timer_id = 1;
djmeyers 0:06ee5f8a484a 41
djmeyers 0:06ee5f8a484a 42 static m2m::Vector<M2MTimerPimpl*> timer_impl_list;
djmeyers 0:06ee5f8a484a 43
djmeyers 0:06ee5f8a484a 44 extern "C" void tasklet_func(arm_event_s *event)
djmeyers 0:06ee5f8a484a 45 {
djmeyers 0:06ee5f8a484a 46 // skip the init event as there will be a timer event after
djmeyers 0:06ee5f8a484a 47 if (event->event_type == MBED_CLIENT_TIMER_EVENT) {
djmeyers 0:06ee5f8a484a 48 bool timer_found = false;
djmeyers 0:06ee5f8a484a 49 eventOS_scheduler_mutex_wait();
djmeyers 0:06ee5f8a484a 50 int timer_count = timer_impl_list.size();
djmeyers 0:06ee5f8a484a 51 for (int index = 0; index < timer_count; index++) {
djmeyers 0:06ee5f8a484a 52 M2MTimerPimpl* timer = timer_impl_list[index];
djmeyers 0:06ee5f8a484a 53 if (timer->get_timer_id() == event->event_id) {
djmeyers 0:06ee5f8a484a 54 eventOS_scheduler_mutex_release();
djmeyers 0:06ee5f8a484a 55 timer_found = true;
djmeyers 0:06ee5f8a484a 56 if (timer->get_still_left_time() > 0) {
djmeyers 0:06ee5f8a484a 57 timer->start_still_left_timer();
djmeyers 0:06ee5f8a484a 58 }else {
djmeyers 0:06ee5f8a484a 59 timer->timer_expired();
djmeyers 0:06ee5f8a484a 60 }
djmeyers 0:06ee5f8a484a 61 break;
djmeyers 0:06ee5f8a484a 62 }
djmeyers 0:06ee5f8a484a 63 }
djmeyers 0:06ee5f8a484a 64 if(!timer_found) {
djmeyers 0:06ee5f8a484a 65 eventOS_scheduler_mutex_release();
djmeyers 0:06ee5f8a484a 66 }
djmeyers 0:06ee5f8a484a 67 }
djmeyers 0:06ee5f8a484a 68 }
djmeyers 0:06ee5f8a484a 69
djmeyers 0:06ee5f8a484a 70 M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer)
djmeyers 0:06ee5f8a484a 71 : _observer(observer),
djmeyers 0:06ee5f8a484a 72 _single_shot(true),
djmeyers 0:06ee5f8a484a 73 _interval(0),
djmeyers 0:06ee5f8a484a 74 _type(M2MTimerObserver::Notdefined),
djmeyers 0:06ee5f8a484a 75 _intermediate_interval(0),
djmeyers 0:06ee5f8a484a 76 _total_interval(0),
djmeyers 0:06ee5f8a484a 77 _still_left(0),
djmeyers 0:06ee5f8a484a 78 _status(0),
djmeyers 0:06ee5f8a484a 79 _dtls_type(false)
djmeyers 0:06ee5f8a484a 80 {
djmeyers 0:06ee5f8a484a 81 ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL);
djmeyers 0:06ee5f8a484a 82 eventOS_scheduler_mutex_wait();
djmeyers 0:06ee5f8a484a 83 if (_tasklet_id < 0) {
djmeyers 0:06ee5f8a484a 84 _tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_TASKLET_INIT_EVENT);
djmeyers 0:06ee5f8a484a 85 assert(_tasklet_id >= 0);
djmeyers 0:06ee5f8a484a 86 }
djmeyers 0:06ee5f8a484a 87
djmeyers 0:06ee5f8a484a 88 // XXX: this wraps over quite soon
djmeyers 0:06ee5f8a484a 89 _timer_id = M2MTimerPimpl::_next_timer_id++;
djmeyers 0:06ee5f8a484a 90 timer_impl_list.push_back(this);
djmeyers 0:06ee5f8a484a 91 eventOS_scheduler_mutex_release();
djmeyers 0:06ee5f8a484a 92 }
djmeyers 0:06ee5f8a484a 93
djmeyers 0:06ee5f8a484a 94 M2MTimerPimpl::~M2MTimerPimpl()
djmeyers 0:06ee5f8a484a 95 {
djmeyers 0:06ee5f8a484a 96 // cancel the timer request, if any is pending
djmeyers 0:06ee5f8a484a 97 cancel();
djmeyers 0:06ee5f8a484a 98
djmeyers 0:06ee5f8a484a 99 // there is no turning back, event os does not have eventOS_event_handler_delete() or similar,
djmeyers 0:06ee5f8a484a 100 // so the tasklet is lost forever. Same goes with timer_impl_list, which leaks now memory.
djmeyers 0:06ee5f8a484a 101
djmeyers 0:06ee5f8a484a 102 // remove the timer from object list
djmeyers 0:06ee5f8a484a 103 eventOS_scheduler_mutex_wait();
djmeyers 0:06ee5f8a484a 104 int timer_count = timer_impl_list.size();
djmeyers 0:06ee5f8a484a 105 for (int index = 0; index < timer_count; index++) {
djmeyers 0:06ee5f8a484a 106 const M2MTimerPimpl* timer = timer_impl_list[index];
djmeyers 0:06ee5f8a484a 107 if (timer->get_timer_id() == _timer_id) {
djmeyers 0:06ee5f8a484a 108 timer_impl_list.erase(index);
djmeyers 0:06ee5f8a484a 109 break;
djmeyers 0:06ee5f8a484a 110 }
djmeyers 0:06ee5f8a484a 111 }
djmeyers 0:06ee5f8a484a 112 eventOS_scheduler_mutex_release();
djmeyers 0:06ee5f8a484a 113 }
djmeyers 0:06ee5f8a484a 114
djmeyers 0:06ee5f8a484a 115 void M2MTimerPimpl::start_timer( uint64_t interval,
djmeyers 0:06ee5f8a484a 116 M2MTimerObserver::Type type,
djmeyers 0:06ee5f8a484a 117 bool single_shot)
djmeyers 0:06ee5f8a484a 118 {
djmeyers 0:06ee5f8a484a 119 _dtls_type = false;
djmeyers 0:06ee5f8a484a 120 _intermediate_interval = 0;
djmeyers 0:06ee5f8a484a 121 _total_interval = 0;
djmeyers 0:06ee5f8a484a 122 _status = 0;
djmeyers 0:06ee5f8a484a 123 _single_shot = single_shot;
djmeyers 0:06ee5f8a484a 124 _interval = interval;
djmeyers 0:06ee5f8a484a 125 _type = type;
djmeyers 0:06ee5f8a484a 126 _still_left = 0;
djmeyers 0:06ee5f8a484a 127 start();
djmeyers 0:06ee5f8a484a 128 }
djmeyers 0:06ee5f8a484a 129
djmeyers 0:06ee5f8a484a 130 void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type)
djmeyers 0:06ee5f8a484a 131 {
djmeyers 0:06ee5f8a484a 132 _dtls_type = true;
djmeyers 0:06ee5f8a484a 133 _intermediate_interval = intermediate_interval;
djmeyers 0:06ee5f8a484a 134 _total_interval = total_interval;
djmeyers 0:06ee5f8a484a 135 _interval = _intermediate_interval;
djmeyers 0:06ee5f8a484a 136 _status = 0;
djmeyers 0:06ee5f8a484a 137 _single_shot = false;
djmeyers 0:06ee5f8a484a 138 _type = type;
djmeyers 0:06ee5f8a484a 139 start();
djmeyers 0:06ee5f8a484a 140 }
djmeyers 0:06ee5f8a484a 141
djmeyers 0:06ee5f8a484a 142 void M2MTimerPimpl::start()
djmeyers 0:06ee5f8a484a 143 {
djmeyers 0:06ee5f8a484a 144 int status;
djmeyers 0:06ee5f8a484a 145 if(_interval > INT32_MAX) {
djmeyers 0:06ee5f8a484a 146 _still_left = _interval - INT32_MAX;
djmeyers 0:06ee5f8a484a 147 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT,
djmeyers 0:06ee5f8a484a 148 M2MTimerPimpl::_tasklet_id,
djmeyers 0:06ee5f8a484a 149 INT32_MAX);
djmeyers 0:06ee5f8a484a 150 }
djmeyers 0:06ee5f8a484a 151 else {
djmeyers 0:06ee5f8a484a 152 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT,
djmeyers 0:06ee5f8a484a 153 M2MTimerPimpl::_tasklet_id,
djmeyers 0:06ee5f8a484a 154 _interval);
djmeyers 0:06ee5f8a484a 155 }
djmeyers 0:06ee5f8a484a 156 assert(status == 0);
djmeyers 0:06ee5f8a484a 157 }
djmeyers 0:06ee5f8a484a 158
djmeyers 0:06ee5f8a484a 159 void M2MTimerPimpl::cancel()
djmeyers 0:06ee5f8a484a 160 {
djmeyers 0:06ee5f8a484a 161 eventOS_event_timer_cancel(_timer_id, M2MTimerPimpl::_tasklet_id);
djmeyers 0:06ee5f8a484a 162 }
djmeyers 0:06ee5f8a484a 163
djmeyers 0:06ee5f8a484a 164 void M2MTimerPimpl::stop_timer()
djmeyers 0:06ee5f8a484a 165 {
djmeyers 0:06ee5f8a484a 166 _interval = 0;
djmeyers 0:06ee5f8a484a 167 _single_shot = true;
djmeyers 0:06ee5f8a484a 168 _still_left = 0;
djmeyers 0:06ee5f8a484a 169 cancel();
djmeyers 0:06ee5f8a484a 170 }
djmeyers 0:06ee5f8a484a 171
djmeyers 0:06ee5f8a484a 172 void M2MTimerPimpl::timer_expired()
djmeyers 0:06ee5f8a484a 173 {
djmeyers 0:06ee5f8a484a 174 _status++;
djmeyers 0:06ee5f8a484a 175 _observer.timer_expired(_type);
djmeyers 0:06ee5f8a484a 176
djmeyers 0:06ee5f8a484a 177 if ((!_dtls_type) && (!_single_shot)) {
djmeyers 0:06ee5f8a484a 178 // start next round of periodic timer
djmeyers 0:06ee5f8a484a 179 start();
djmeyers 0:06ee5f8a484a 180 } else if ((_dtls_type) && (!is_total_interval_passed())) {
djmeyers 0:06ee5f8a484a 181 // if only the intermediate time has passed, we need still wait up to total time
djmeyers 0:06ee5f8a484a 182 _interval = _total_interval - _intermediate_interval;
djmeyers 0:06ee5f8a484a 183 start();
djmeyers 0:06ee5f8a484a 184 }
djmeyers 0:06ee5f8a484a 185 }
djmeyers 0:06ee5f8a484a 186
djmeyers 0:06ee5f8a484a 187 bool M2MTimerPimpl::is_intermediate_interval_passed()
djmeyers 0:06ee5f8a484a 188 {
djmeyers 0:06ee5f8a484a 189 if (_status > 0) {
djmeyers 0:06ee5f8a484a 190 return true;
djmeyers 0:06ee5f8a484a 191 }
djmeyers 0:06ee5f8a484a 192 return false;
djmeyers 0:06ee5f8a484a 193 }
djmeyers 0:06ee5f8a484a 194
djmeyers 0:06ee5f8a484a 195 bool M2MTimerPimpl::is_total_interval_passed()
djmeyers 0:06ee5f8a484a 196 {
djmeyers 0:06ee5f8a484a 197 if (_status > 1) {
djmeyers 0:06ee5f8a484a 198 return true;
djmeyers 0:06ee5f8a484a 199 }
djmeyers 0:06ee5f8a484a 200 return false;
djmeyers 0:06ee5f8a484a 201 }
djmeyers 0:06ee5f8a484a 202
djmeyers 0:06ee5f8a484a 203 uint64_t M2MTimerPimpl::get_still_left_time() const
djmeyers 0:06ee5f8a484a 204 {
djmeyers 0:06ee5f8a484a 205 return _still_left;
djmeyers 0:06ee5f8a484a 206 }
djmeyers 0:06ee5f8a484a 207
djmeyers 0:06ee5f8a484a 208 void M2MTimerPimpl::start_still_left_timer()
djmeyers 0:06ee5f8a484a 209 {
djmeyers 0:06ee5f8a484a 210 if (_still_left > 0) {
djmeyers 0:06ee5f8a484a 211 int status;
djmeyers 0:06ee5f8a484a 212 if( _still_left > INT32_MAX) {
djmeyers 0:06ee5f8a484a 213 _still_left = _still_left - INT32_MAX;
djmeyers 0:06ee5f8a484a 214 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT,
djmeyers 0:06ee5f8a484a 215 M2MTimerPimpl::_tasklet_id,
djmeyers 0:06ee5f8a484a 216 INT32_MAX);
djmeyers 0:06ee5f8a484a 217 }
djmeyers 0:06ee5f8a484a 218 else {
djmeyers 0:06ee5f8a484a 219 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT,
djmeyers 0:06ee5f8a484a 220 M2MTimerPimpl::_tasklet_id,
djmeyers 0:06ee5f8a484a 221 _still_left);
djmeyers 0:06ee5f8a484a 222 _still_left = 0;
djmeyers 0:06ee5f8a484a 223 }
djmeyers 0:06ee5f8a484a 224 assert(status == 0);
djmeyers 0:06ee5f8a484a 225 } else {
djmeyers 0:06ee5f8a484a 226 _observer.timer_expired(_type);
djmeyers 0:06ee5f8a484a 227 if(!_single_shot) {
djmeyers 0:06ee5f8a484a 228 start_timer(_interval, _type, _single_shot);
djmeyers 0:06ee5f8a484a 229 }
djmeyers 0:06ee5f8a484a 230 }
djmeyers 0:06ee5f8a484a 231 }