A metronome using the FRDM K64F board

Committer:
ram54288
Date:
Sun May 14 18:40:18 2017 +0000
Revision:
0:a7a43371b306
Initial commit

Who changed what in which revision?

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