This is a fork of the `events` subdirectory of https://github.com/ARMmbed/mbed-os

Dependents:   HelloWorld_CCA01M1 HelloWorld_CCA02M1 CI-data-logger-server HelloWorld_CCA02M1 ... more

This is a fork of the events subdirectory of https://github.com/ARMmbed/mbed-os.

Note, you must import this library with import name: events!!!

Committer:
Christopher Haster
Date:
Wed Feb 15 10:04:11 2017 -0600
Revision:
16:e974c9c27619
Parent:
13:93ea03db7d46
Child:
18:dba7bd0f39f3
Child:
9820:245503c70134
events: Added better handling of desynchronized timers in platform layer

An odd bug (c0951c9) in the NCS36510 ticker code caused the timer/ticker
classes to become desynchronized. Updated the handling to not assume the
timers are perfectly in synch. This will increase the event's tolerance of
less robust platforms.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bogdan Marinescu 0:a792d4bf36c2 1 /*
Bogdan Marinescu 0:a792d4bf36c2 2 * Implementation for the mbed library
Bogdan Marinescu 0:a792d4bf36c2 3 * https://github.com/mbedmicro/mbed
Bogdan Marinescu 0:a792d4bf36c2 4 *
Bogdan Marinescu 0:a792d4bf36c2 5 * Copyright (c) 2016 Christopher Haster
Bogdan Marinescu 0:a792d4bf36c2 6 *
Bogdan Marinescu 0:a792d4bf36c2 7 * Licensed under the Apache License, Version 2.0 (the "License");
Bogdan Marinescu 0:a792d4bf36c2 8 * you may not use this file except in compliance with the License.
Bogdan Marinescu 0:a792d4bf36c2 9 * You may obtain a copy of the License at
Bogdan Marinescu 0:a792d4bf36c2 10 *
Bogdan Marinescu 0:a792d4bf36c2 11 * http://www.apache.org/licenses/LICENSE-2.0
Bogdan Marinescu 0:a792d4bf36c2 12 *
Bogdan Marinescu 0:a792d4bf36c2 13 * Unless required by applicable law or agreed to in writing, software
Bogdan Marinescu 0:a792d4bf36c2 14 * distributed under the License is distributed on an "AS IS" BASIS,
Bogdan Marinescu 0:a792d4bf36c2 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Bogdan Marinescu 0:a792d4bf36c2 16 * See the License for the specific language governing permissions and
Bogdan Marinescu 0:a792d4bf36c2 17 * limitations under the License.
Bogdan Marinescu 0:a792d4bf36c2 18 */
Sam Grove 2:a60d8117d0e0 19 #include "equeue/equeue_platform.h"
Bogdan Marinescu 0:a792d4bf36c2 20
Bogdan Marinescu 0:a792d4bf36c2 21 #if defined(EQUEUE_PLATFORM_MBED)
Bogdan Marinescu 0:a792d4bf36c2 22
Bogdan Marinescu 0:a792d4bf36c2 23 #include <stdbool.h>
Bogdan Marinescu 0:a792d4bf36c2 24 #include "mbed.h"
Bogdan Marinescu 0:a792d4bf36c2 25
Bogdan Marinescu 0:a792d4bf36c2 26
Bogdan Marinescu 0:a792d4bf36c2 27 // Ticker operations
Bogdan Marinescu 0:a792d4bf36c2 28 static bool equeue_tick_inited = false;
Christopher Haster 16:e974c9c27619 29 static volatile unsigned equeue_minutes = 0;
Bogdan Marinescu 0:a792d4bf36c2 30 static unsigned equeue_timer[
Bogdan Marinescu 0:a792d4bf36c2 31 (sizeof(Timer)+sizeof(unsigned)-1)/sizeof(unsigned)];
Bogdan Marinescu 0:a792d4bf36c2 32 static unsigned equeue_ticker[
Bogdan Marinescu 0:a792d4bf36c2 33 (sizeof(Ticker)+sizeof(unsigned)-1)/sizeof(unsigned)];
Bogdan Marinescu 0:a792d4bf36c2 34
Bogdan Marinescu 0:a792d4bf36c2 35 static void equeue_tick_update() {
Christopher Haster 16:e974c9c27619 36 equeue_minutes += reinterpret_cast<Timer*>(equeue_timer)->read_ms();
Bogdan Marinescu 0:a792d4bf36c2 37 reinterpret_cast<Timer*>(equeue_timer)->reset();
Bogdan Marinescu 0:a792d4bf36c2 38 }
Bogdan Marinescu 0:a792d4bf36c2 39
Bogdan Marinescu 0:a792d4bf36c2 40 static void equeue_tick_init() {
Christopher Haster 9:a372bff82709 41 MBED_STATIC_ASSERT(sizeof(equeue_timer) >= sizeof(Timer),
Christopher Haster 9:a372bff82709 42 "The equeue_timer buffer must fit the class Timer");
Christopher Haster 9:a372bff82709 43 MBED_STATIC_ASSERT(sizeof(equeue_ticker) >= sizeof(Ticker),
Christopher Haster 9:a372bff82709 44 "The equeue_ticker buffer must fit the class Ticker");
Bogdan Marinescu 0:a792d4bf36c2 45 new (equeue_timer) Timer;
Bogdan Marinescu 0:a792d4bf36c2 46 new (equeue_ticker) Ticker;
Bogdan Marinescu 0:a792d4bf36c2 47
Bogdan Marinescu 0:a792d4bf36c2 48 equeue_minutes = 0;
Bogdan Marinescu 0:a792d4bf36c2 49 reinterpret_cast<Timer*>(equeue_timer)->start();
Bogdan Marinescu 0:a792d4bf36c2 50 reinterpret_cast<Ticker*>(equeue_ticker)
Christopher Haster 16:e974c9c27619 51 ->attach_us(equeue_tick_update, 1000 << 16);
Bogdan Marinescu 0:a792d4bf36c2 52
Bogdan Marinescu 0:a792d4bf36c2 53 equeue_tick_inited = true;
Bogdan Marinescu 0:a792d4bf36c2 54 }
Bogdan Marinescu 0:a792d4bf36c2 55
Bogdan Marinescu 0:a792d4bf36c2 56 unsigned equeue_tick() {
Bogdan Marinescu 0:a792d4bf36c2 57 if (!equeue_tick_inited) {
Bogdan Marinescu 0:a792d4bf36c2 58 equeue_tick_init();
Bogdan Marinescu 0:a792d4bf36c2 59 }
Bogdan Marinescu 0:a792d4bf36c2 60
Christopher Haster 16:e974c9c27619 61 unsigned minutes;
Christopher Haster 16:e974c9c27619 62 unsigned ms;
Christopher Haster 16:e974c9c27619 63
Christopher Haster 16:e974c9c27619 64 do {
Christopher Haster 16:e974c9c27619 65 minutes = equeue_minutes;
Christopher Haster 16:e974c9c27619 66 ms = reinterpret_cast<Timer*>(equeue_timer)->read_ms();
Christopher Haster 16:e974c9c27619 67 } while (minutes != equeue_minutes);
Christopher Haster 16:e974c9c27619 68
Christopher Haster 16:e974c9c27619 69 return minutes + ms;
Bogdan Marinescu 0:a792d4bf36c2 70 }
Bogdan Marinescu 0:a792d4bf36c2 71
Bogdan Marinescu 0:a792d4bf36c2 72
Bogdan Marinescu 0:a792d4bf36c2 73 // Mutex operations
Bogdan Marinescu 0:a792d4bf36c2 74 int equeue_mutex_create(equeue_mutex_t *m) { return 0; }
Bogdan Marinescu 0:a792d4bf36c2 75 void equeue_mutex_destroy(equeue_mutex_t *m) { }
Bogdan Marinescu 0:a792d4bf36c2 76
Bogdan Marinescu 0:a792d4bf36c2 77 void equeue_mutex_lock(equeue_mutex_t *m) {
Bogdan Marinescu 0:a792d4bf36c2 78 core_util_critical_section_enter();
Bogdan Marinescu 0:a792d4bf36c2 79 }
Bogdan Marinescu 0:a792d4bf36c2 80
Bogdan Marinescu 0:a792d4bf36c2 81 void equeue_mutex_unlock(equeue_mutex_t *m) {
Bogdan Marinescu 0:a792d4bf36c2 82 core_util_critical_section_exit();
Bogdan Marinescu 0:a792d4bf36c2 83 }
Bogdan Marinescu 0:a792d4bf36c2 84
Bogdan Marinescu 0:a792d4bf36c2 85
Bogdan Marinescu 0:a792d4bf36c2 86 // Semaphore operations
Bogdan Marinescu 0:a792d4bf36c2 87 #ifdef MBED_CONF_RTOS_PRESENT
Bogdan Marinescu 0:a792d4bf36c2 88
Bogdan Marinescu 0:a792d4bf36c2 89 int equeue_sema_create(equeue_sema_t *s) {
Christopher Haster 9:a372bff82709 90 MBED_STATIC_ASSERT(sizeof(equeue_sema_t) >= sizeof(Semaphore),
Christopher Haster 9:a372bff82709 91 "The equeue_sema_t must fit the class Semaphore");
Bogdan Marinescu 0:a792d4bf36c2 92 new (s) Semaphore(0);
Bogdan Marinescu 0:a792d4bf36c2 93 return 0;
Bogdan Marinescu 0:a792d4bf36c2 94 }
Bogdan Marinescu 0:a792d4bf36c2 95
Bogdan Marinescu 0:a792d4bf36c2 96 void equeue_sema_destroy(equeue_sema_t *s) {
Bogdan Marinescu 0:a792d4bf36c2 97 reinterpret_cast<Semaphore*>(s)->~Semaphore();
Bogdan Marinescu 0:a792d4bf36c2 98 }
Bogdan Marinescu 0:a792d4bf36c2 99
Bogdan Marinescu 0:a792d4bf36c2 100 void equeue_sema_signal(equeue_sema_t *s) {
Bogdan Marinescu 0:a792d4bf36c2 101 reinterpret_cast<Semaphore*>(s)->release();
Bogdan Marinescu 0:a792d4bf36c2 102 }
Bogdan Marinescu 0:a792d4bf36c2 103
Bogdan Marinescu 0:a792d4bf36c2 104 bool equeue_sema_wait(equeue_sema_t *s, int ms) {
Bogdan Marinescu 0:a792d4bf36c2 105 if (ms < 0) {
Bogdan Marinescu 0:a792d4bf36c2 106 ms = osWaitForever;
Bogdan Marinescu 0:a792d4bf36c2 107 }
Bogdan Marinescu 0:a792d4bf36c2 108
Bogdan Marinescu 0:a792d4bf36c2 109 return (reinterpret_cast<Semaphore*>(s)->wait(ms) > 0);
Bogdan Marinescu 0:a792d4bf36c2 110 }
Bogdan Marinescu 0:a792d4bf36c2 111
Bogdan Marinescu 0:a792d4bf36c2 112 #else
Bogdan Marinescu 0:a792d4bf36c2 113
Bogdan Marinescu 0:a792d4bf36c2 114 // Semaphore operations
Bogdan Marinescu 0:a792d4bf36c2 115 int equeue_sema_create(equeue_sema_t *s) {
Bogdan Marinescu 0:a792d4bf36c2 116 *s = false;
Bogdan Marinescu 0:a792d4bf36c2 117 return 0;
Bogdan Marinescu 0:a792d4bf36c2 118 }
Bogdan Marinescu 0:a792d4bf36c2 119
Bogdan Marinescu 0:a792d4bf36c2 120 void equeue_sema_destroy(equeue_sema_t *s) {
Bogdan Marinescu 0:a792d4bf36c2 121 }
Bogdan Marinescu 0:a792d4bf36c2 122
Bogdan Marinescu 0:a792d4bf36c2 123 void equeue_sema_signal(equeue_sema_t *s) {
Bogdan Marinescu 0:a792d4bf36c2 124 *s = 1;
Bogdan Marinescu 0:a792d4bf36c2 125 }
Bogdan Marinescu 0:a792d4bf36c2 126
Bogdan Marinescu 0:a792d4bf36c2 127 static void equeue_sema_timeout(equeue_sema_t *s) {
Bogdan Marinescu 0:a792d4bf36c2 128 *s = -1;
Bogdan Marinescu 0:a792d4bf36c2 129 }
Bogdan Marinescu 0:a792d4bf36c2 130
Bogdan Marinescu 0:a792d4bf36c2 131 bool equeue_sema_wait(equeue_sema_t *s, int ms) {
Bogdan Marinescu 0:a792d4bf36c2 132 int signal = 0;
Bogdan Marinescu 0:a792d4bf36c2 133 Timeout timeout;
Christopher Haster 13:93ea03db7d46 134 if (ms > 0) {
Christopher Haster 13:93ea03db7d46 135 timeout.attach_us(callback(equeue_sema_timeout, s), ms*1000);
Christopher Haster 13:93ea03db7d46 136 }
Bogdan Marinescu 0:a792d4bf36c2 137
Bogdan Marinescu 0:a792d4bf36c2 138 core_util_critical_section_enter();
Bogdan Marinescu 0:a792d4bf36c2 139 while (!*s) {
Bogdan Marinescu 0:a792d4bf36c2 140 sleep();
Bogdan Marinescu 0:a792d4bf36c2 141 core_util_critical_section_exit();
Bogdan Marinescu 0:a792d4bf36c2 142 core_util_critical_section_enter();
Bogdan Marinescu 0:a792d4bf36c2 143 }
Bogdan Marinescu 0:a792d4bf36c2 144
Bogdan Marinescu 0:a792d4bf36c2 145 signal = *s;
Bogdan Marinescu 0:a792d4bf36c2 146 *s = false;
Bogdan Marinescu 0:a792d4bf36c2 147 core_util_critical_section_exit();
Bogdan Marinescu 0:a792d4bf36c2 148
Bogdan Marinescu 0:a792d4bf36c2 149 return (signal > 0);
Bogdan Marinescu 0:a792d4bf36c2 150 }
Bogdan Marinescu 0:a792d4bf36c2 151
Bogdan Marinescu 0:a792d4bf36c2 152 #endif
Bogdan Marinescu 0:a792d4bf36c2 153
Bogdan Marinescu 0:a792d4bf36c2 154 #endif