FRDM K64F Metronome

Committer:
ram54288
Date:
Sun May 14 18:35:07 2017 +0000
Revision:
0:a2cb7295a1f7
Initial commit

Who changed what in which revision?

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