leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Committer:
leothedragon
Date:
Tue May 04 08:55:12 2021 +0000
Revision:
0:8f0bb79ddd48
nmn

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leothedragon 0:8f0bb79ddd48 1 /*
leothedragon 0:8f0bb79ddd48 2 * Copyright (c) 2015-2016 ARM Limited. All rights reserved.
leothedragon 0:8f0bb79ddd48 3 * SPDX-License-Identifier: Apache-2.0
leothedragon 0:8f0bb79ddd48 4 * Licensed under the Apache License, Version 2.0 (the License); you may
leothedragon 0:8f0bb79ddd48 5 * not use this file except in compliance with the License.
leothedragon 0:8f0bb79ddd48 6 * You may obtain a copy of the License at
leothedragon 0:8f0bb79ddd48 7 *
leothedragon 0:8f0bb79ddd48 8 * http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:8f0bb79ddd48 9 *
leothedragon 0:8f0bb79ddd48 10 * Unless required by applicable law or agreed to in writing, software
leothedragon 0:8f0bb79ddd48 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
leothedragon 0:8f0bb79ddd48 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:8f0bb79ddd48 13 * See the License for the specific language governing permissions and
leothedragon 0:8f0bb79ddd48 14 * limitations under the License.
leothedragon 0:8f0bb79ddd48 15 */
leothedragon 0:8f0bb79ddd48 16
leothedragon 0:8f0bb79ddd48 17 #include "mbed-client-classic/m2mtimerpimpl.h"
leothedragon 0:8f0bb79ddd48 18 #include "mbed-client/m2mtimerobserver.h"
leothedragon 0:8f0bb79ddd48 19
leothedragon 0:8f0bb79ddd48 20 #include "eventOS_event_timer.h"
leothedragon 0:8f0bb79ddd48 21 #include "eventOS_scheduler.h"
leothedragon 0:8f0bb79ddd48 22
leothedragon 0:8f0bb79ddd48 23 #include <assert.h>
leothedragon 0:8f0bb79ddd48 24 #include <string.h>
leothedragon 0:8f0bb79ddd48 25
leothedragon 0:8f0bb79ddd48 26
leothedragon 0:8f0bb79ddd48 27 #define MBED_CLIENT_TIMER_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet
leothedragon 0:8f0bb79ddd48 28 #define MBED_CLIENT_TIMER_EVENT 10
leothedragon 0:8f0bb79ddd48 29
leothedragon 0:8f0bb79ddd48 30 // This is set to _status on constructor, which forces the lazy second phase initialization
leothedragon 0:8f0bb79ddd48 31 // to happen once in initialize_tasklet(). Whole scheme is there to avoid overhead or
leothedragon 0:8f0bb79ddd48 32 // unwanted serialization on event OS scheduler mutex, as the whole tasklet needs to be initialized
leothedragon 0:8f0bb79ddd48 33 // just once for the whole lifecycle of cloud client.
leothedragon 0:8f0bb79ddd48 34 #define STATUS_INIT_NOT_DONE_YET 3
leothedragon 0:8f0bb79ddd48 35
leothedragon 0:8f0bb79ddd48 36
leothedragon 0:8f0bb79ddd48 37 int8_t M2MTimerPimpl::_tasklet_id = -1;
leothedragon 0:8f0bb79ddd48 38
leothedragon 0:8f0bb79ddd48 39 extern "C" void tasklet_func(arm_event_s *event)
leothedragon 0:8f0bb79ddd48 40 {
leothedragon 0:8f0bb79ddd48 41 // skip the init event as there will be a timer event after
leothedragon 0:8f0bb79ddd48 42 if (event->event_type == MBED_CLIENT_TIMER_EVENT) {
leothedragon 0:8f0bb79ddd48 43
leothedragon 0:8f0bb79ddd48 44 M2MTimerPimpl* timer = (M2MTimerPimpl*)event->data_ptr;
leothedragon 0:8f0bb79ddd48 45 assert(timer);
leothedragon 0:8f0bb79ddd48 46 timer->handle_timer_event(*event);
leothedragon 0:8f0bb79ddd48 47 }
leothedragon 0:8f0bb79ddd48 48 }
leothedragon 0:8f0bb79ddd48 49
leothedragon 0:8f0bb79ddd48 50 void M2MTimerPimpl::handle_timer_event(const arm_event_s &event)
leothedragon 0:8f0bb79ddd48 51 {
leothedragon 0:8f0bb79ddd48 52 // Clear the reference to timer event which is now received and handled.
leothedragon 0:8f0bb79ddd48 53 // This avoids the useless work from canceling a event if the timer is restarted
leothedragon 0:8f0bb79ddd48 54 // and also lets the assertions verify the object state correctly.
leothedragon 0:8f0bb79ddd48 55 _timer_event = NULL;
leothedragon 0:8f0bb79ddd48 56
leothedragon 0:8f0bb79ddd48 57 if (get_still_left_time() > 0) {
leothedragon 0:8f0bb79ddd48 58 start_still_left_timer();
leothedragon 0:8f0bb79ddd48 59 } else {
leothedragon 0:8f0bb79ddd48 60 timer_expired();
leothedragon 0:8f0bb79ddd48 61 }
leothedragon 0:8f0bb79ddd48 62 }
leothedragon 0:8f0bb79ddd48 63
leothedragon 0:8f0bb79ddd48 64 M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer)
leothedragon 0:8f0bb79ddd48 65 : _observer(observer),
leothedragon 0:8f0bb79ddd48 66 _interval(0),
leothedragon 0:8f0bb79ddd48 67 _intermediate_interval(0),
leothedragon 0:8f0bb79ddd48 68 _total_interval(0),
leothedragon 0:8f0bb79ddd48 69 _still_left(0),
leothedragon 0:8f0bb79ddd48 70 _timer_event(NULL),
leothedragon 0:8f0bb79ddd48 71 _type(M2MTimerObserver::Notdefined),
leothedragon 0:8f0bb79ddd48 72 _status(STATUS_INIT_NOT_DONE_YET),
leothedragon 0:8f0bb79ddd48 73 _dtls_type(false),
leothedragon 0:8f0bb79ddd48 74 _single_shot(true)
leothedragon 0:8f0bb79ddd48 75 {
leothedragon 0:8f0bb79ddd48 76 }
leothedragon 0:8f0bb79ddd48 77
leothedragon 0:8f0bb79ddd48 78 M2MTimerPimpl::~M2MTimerPimpl()
leothedragon 0:8f0bb79ddd48 79 {
leothedragon 0:8f0bb79ddd48 80 // cancel the timer request, if any is pending
leothedragon 0:8f0bb79ddd48 81 cancel();
leothedragon 0:8f0bb79ddd48 82
leothedragon 0:8f0bb79ddd48 83 // there is no turning back, event os does not have eventOS_event_handler_delete() or similar,
leothedragon 0:8f0bb79ddd48 84 // so the tasklet is lost forever.
leothedragon 0:8f0bb79ddd48 85 }
leothedragon 0:8f0bb79ddd48 86
leothedragon 0:8f0bb79ddd48 87 void M2MTimerPimpl::initialize_tasklet()
leothedragon 0:8f0bb79ddd48 88 {
leothedragon 0:8f0bb79ddd48 89 // A micro-optimization to avoid operations on mutex on every time the timer is started.
leothedragon 0:8f0bb79ddd48 90 // After all, the tasklet needs to be created just once for the lifecyle of whole client.
leothedragon 0:8f0bb79ddd48 91 if (_status == STATUS_INIT_NOT_DONE_YET) {
leothedragon 0:8f0bb79ddd48 92
leothedragon 0:8f0bb79ddd48 93 eventOS_scheduler_mutex_wait();
leothedragon 0:8f0bb79ddd48 94
leothedragon 0:8f0bb79ddd48 95 if (_tasklet_id < 0) {
leothedragon 0:8f0bb79ddd48 96 _tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_TASKLET_INIT_EVENT);
leothedragon 0:8f0bb79ddd48 97 assert(_tasklet_id >= 0);
leothedragon 0:8f0bb79ddd48 98 }
leothedragon 0:8f0bb79ddd48 99
leothedragon 0:8f0bb79ddd48 100 _status = 0;
leothedragon 0:8f0bb79ddd48 101
leothedragon 0:8f0bb79ddd48 102 eventOS_scheduler_mutex_release();
leothedragon 0:8f0bb79ddd48 103 }
leothedragon 0:8f0bb79ddd48 104 }
leothedragon 0:8f0bb79ddd48 105
leothedragon 0:8f0bb79ddd48 106 void M2MTimerPimpl::start_timer(uint64_t interval,
leothedragon 0:8f0bb79ddd48 107 M2MTimerObserver::Type type,
leothedragon 0:8f0bb79ddd48 108 bool single_shot)
leothedragon 0:8f0bb79ddd48 109 {
leothedragon 0:8f0bb79ddd48 110 initialize_tasklet();
leothedragon 0:8f0bb79ddd48 111
leothedragon 0:8f0bb79ddd48 112 _dtls_type = false;
leothedragon 0:8f0bb79ddd48 113 _intermediate_interval = 0;
leothedragon 0:8f0bb79ddd48 114 _total_interval = 0;
leothedragon 0:8f0bb79ddd48 115 _status = 0;
leothedragon 0:8f0bb79ddd48 116 _single_shot = single_shot;
leothedragon 0:8f0bb79ddd48 117 _interval = interval;
leothedragon 0:8f0bb79ddd48 118 _type = type;
leothedragon 0:8f0bb79ddd48 119 _still_left = 0;
leothedragon 0:8f0bb79ddd48 120 start();
leothedragon 0:8f0bb79ddd48 121 }
leothedragon 0:8f0bb79ddd48 122
leothedragon 0:8f0bb79ddd48 123 void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type)
leothedragon 0:8f0bb79ddd48 124 {
leothedragon 0:8f0bb79ddd48 125 initialize_tasklet();
leothedragon 0:8f0bb79ddd48 126
leothedragon 0:8f0bb79ddd48 127 _dtls_type = true;
leothedragon 0:8f0bb79ddd48 128 _intermediate_interval = intermediate_interval;
leothedragon 0:8f0bb79ddd48 129 _total_interval = total_interval;
leothedragon 0:8f0bb79ddd48 130 _interval = _intermediate_interval;
leothedragon 0:8f0bb79ddd48 131 _status = 0;
leothedragon 0:8f0bb79ddd48 132 _single_shot = false;
leothedragon 0:8f0bb79ddd48 133 _type = type;
leothedragon 0:8f0bb79ddd48 134 start();
leothedragon 0:8f0bb79ddd48 135 }
leothedragon 0:8f0bb79ddd48 136
leothedragon 0:8f0bb79ddd48 137 void M2MTimerPimpl::start()
leothedragon 0:8f0bb79ddd48 138 {
leothedragon 0:8f0bb79ddd48 139 // Cancel ongoing events before creating a new one.
leothedragon 0:8f0bb79ddd48 140 // Otherwise it can happen that there are multiple events running at the same time.
leothedragon 0:8f0bb79ddd48 141 cancel();
leothedragon 0:8f0bb79ddd48 142
leothedragon 0:8f0bb79ddd48 143 int32_t wait_time;
leothedragon 0:8f0bb79ddd48 144
leothedragon 0:8f0bb79ddd48 145 if (_interval > INT32_MAX) {
leothedragon 0:8f0bb79ddd48 146 _still_left = _interval - INT32_MAX;
leothedragon 0:8f0bb79ddd48 147 wait_time = INT32_MAX;
leothedragon 0:8f0bb79ddd48 148 } else {
leothedragon 0:8f0bb79ddd48 149 wait_time = _interval;
leothedragon 0:8f0bb79ddd48 150 }
leothedragon 0:8f0bb79ddd48 151
leothedragon 0:8f0bb79ddd48 152 request_event_in(wait_time);
leothedragon 0:8f0bb79ddd48 153 }
leothedragon 0:8f0bb79ddd48 154
leothedragon 0:8f0bb79ddd48 155 void M2MTimerPimpl::request_event_in(int32_t delay_ms)
leothedragon 0:8f0bb79ddd48 156 {
leothedragon 0:8f0bb79ddd48 157 // init struct to zero to avoid hassle when new fields are added to it
leothedragon 0:8f0bb79ddd48 158 arm_event_t event = { 0 };
leothedragon 0:8f0bb79ddd48 159
leothedragon 0:8f0bb79ddd48 160 event.receiver = _tasklet_id;
leothedragon 0:8f0bb79ddd48 161 event.sender = _tasklet_id;
leothedragon 0:8f0bb79ddd48 162 event.event_type = MBED_CLIENT_TIMER_EVENT;
leothedragon 0:8f0bb79ddd48 163 event.data_ptr = this;
leothedragon 0:8f0bb79ddd48 164 event.priority = ARM_LIB_MED_PRIORITY_EVENT;
leothedragon 0:8f0bb79ddd48 165
leothedragon 0:8f0bb79ddd48 166 // check first, that there is no timer event still pending
leothedragon 0:8f0bb79ddd48 167 assert(_timer_event == NULL);
leothedragon 0:8f0bb79ddd48 168
leothedragon 0:8f0bb79ddd48 169 const uint32_t delay_ticks = eventOS_event_timer_ms_to_ticks(delay_ms);
leothedragon 0:8f0bb79ddd48 170
leothedragon 0:8f0bb79ddd48 171 _timer_event = eventOS_event_timer_request_in(&event, delay_ticks);
leothedragon 0:8f0bb79ddd48 172
leothedragon 0:8f0bb79ddd48 173 // The timer request may fail only if the system is out of pre-allocated
leothedragon 0:8f0bb79ddd48 174 // timers and it can not allocate more.
leothedragon 0:8f0bb79ddd48 175 assert(_timer_event != NULL);
leothedragon 0:8f0bb79ddd48 176 }
leothedragon 0:8f0bb79ddd48 177
leothedragon 0:8f0bb79ddd48 178 void M2MTimerPimpl::cancel()
leothedragon 0:8f0bb79ddd48 179 {
leothedragon 0:8f0bb79ddd48 180 // NULL event is ok to cancel
leothedragon 0:8f0bb79ddd48 181 eventOS_cancel(_timer_event);
leothedragon 0:8f0bb79ddd48 182
leothedragon 0:8f0bb79ddd48 183 _timer_event = NULL;
leothedragon 0:8f0bb79ddd48 184 }
leothedragon 0:8f0bb79ddd48 185
leothedragon 0:8f0bb79ddd48 186 void M2MTimerPimpl::stop_timer()
leothedragon 0:8f0bb79ddd48 187 {
leothedragon 0:8f0bb79ddd48 188 _interval = 0;
leothedragon 0:8f0bb79ddd48 189 _single_shot = true;
leothedragon 0:8f0bb79ddd48 190 _still_left = 0;
leothedragon 0:8f0bb79ddd48 191 cancel();
leothedragon 0:8f0bb79ddd48 192 }
leothedragon 0:8f0bb79ddd48 193
leothedragon 0:8f0bb79ddd48 194 void M2MTimerPimpl::timer_expired()
leothedragon 0:8f0bb79ddd48 195 {
leothedragon 0:8f0bb79ddd48 196 _status++;
leothedragon 0:8f0bb79ddd48 197
leothedragon 0:8f0bb79ddd48 198 // The code is expecting that the expiration has happened 0, 1 or more times,
leothedragon 0:8f0bb79ddd48 199 // and we also need to check for overflow as the _status is stored in 2 bits slot.
leothedragon 0:8f0bb79ddd48 200 if (_status > 2) {
leothedragon 0:8f0bb79ddd48 201 _status = 2;
leothedragon 0:8f0bb79ddd48 202 }
leothedragon 0:8f0bb79ddd48 203
leothedragon 0:8f0bb79ddd48 204 _observer.timer_expired(_type);
leothedragon 0:8f0bb79ddd48 205
leothedragon 0:8f0bb79ddd48 206 if ((!_dtls_type) && (!_single_shot)) {
leothedragon 0:8f0bb79ddd48 207 // start next round of periodic timer
leothedragon 0:8f0bb79ddd48 208 start();
leothedragon 0:8f0bb79ddd48 209 } else if ((_dtls_type) && (!is_total_interval_passed())) {
leothedragon 0:8f0bb79ddd48 210 // if only the intermediate time has passed, we need still wait up to total time
leothedragon 0:8f0bb79ddd48 211 _interval = _total_interval - _intermediate_interval;
leothedragon 0:8f0bb79ddd48 212 start();
leothedragon 0:8f0bb79ddd48 213 }
leothedragon 0:8f0bb79ddd48 214 }
leothedragon 0:8f0bb79ddd48 215
leothedragon 0:8f0bb79ddd48 216 bool M2MTimerPimpl::is_intermediate_interval_passed() const
leothedragon 0:8f0bb79ddd48 217 {
leothedragon 0:8f0bb79ddd48 218 if (_status > 0) {
leothedragon 0:8f0bb79ddd48 219 return true;
leothedragon 0:8f0bb79ddd48 220 }
leothedragon 0:8f0bb79ddd48 221 return false;
leothedragon 0:8f0bb79ddd48 222 }
leothedragon 0:8f0bb79ddd48 223
leothedragon 0:8f0bb79ddd48 224 bool M2MTimerPimpl::is_total_interval_passed() const
leothedragon 0:8f0bb79ddd48 225 {
leothedragon 0:8f0bb79ddd48 226 if (_status > 1) {
leothedragon 0:8f0bb79ddd48 227 return true;
leothedragon 0:8f0bb79ddd48 228 }
leothedragon 0:8f0bb79ddd48 229 return false;
leothedragon 0:8f0bb79ddd48 230 }
leothedragon 0:8f0bb79ddd48 231
leothedragon 0:8f0bb79ddd48 232 uint64_t M2MTimerPimpl::get_still_left_time() const
leothedragon 0:8f0bb79ddd48 233 {
leothedragon 0:8f0bb79ddd48 234 return _still_left;
leothedragon 0:8f0bb79ddd48 235 }
leothedragon 0:8f0bb79ddd48 236
leothedragon 0:8f0bb79ddd48 237 void M2MTimerPimpl::start_still_left_timer()
leothedragon 0:8f0bb79ddd48 238 {
leothedragon 0:8f0bb79ddd48 239 if (_still_left > 0) {
leothedragon 0:8f0bb79ddd48 240
leothedragon 0:8f0bb79ddd48 241 int32_t wait_time;
leothedragon 0:8f0bb79ddd48 242
leothedragon 0:8f0bb79ddd48 243 if (_still_left > INT32_MAX) {
leothedragon 0:8f0bb79ddd48 244 _still_left = _still_left - INT32_MAX;
leothedragon 0:8f0bb79ddd48 245 wait_time = INT32_MAX;
leothedragon 0:8f0bb79ddd48 246 } else {
leothedragon 0:8f0bb79ddd48 247 wait_time = _still_left;
leothedragon 0:8f0bb79ddd48 248 _still_left = 0;
leothedragon 0:8f0bb79ddd48 249 }
leothedragon 0:8f0bb79ddd48 250
leothedragon 0:8f0bb79ddd48 251 request_event_in(wait_time);
leothedragon 0:8f0bb79ddd48 252
leothedragon 0:8f0bb79ddd48 253 } else {
leothedragon 0:8f0bb79ddd48 254 _observer.timer_expired(_type);
leothedragon 0:8f0bb79ddd48 255 if (!_single_shot) {
leothedragon 0:8f0bb79ddd48 256 start_timer(_interval, _type, _single_shot);
leothedragon 0:8f0bb79ddd48 257 }
leothedragon 0:8f0bb79ddd48 258 }
leothedragon 0:8f0bb79ddd48 259 }