FRDM K64F Metronome

Committer:
ram54288
Date:
Sun May 14 18:37:05 2017 +0000
Revision:
0:dbad57390bd1
Initial commit

Who changed what in which revision?

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