PES4 / Mbed OS Queue_02
Committer:
demayer
Date:
Sat Mar 28 15:28:19 2020 +0000
Revision:
0:6bf0743ece18
IMU Thread with an event-queue running parallel to handle tasks like a 5 times blinking LED. Button with interrupt detected.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
demayer 0:6bf0743ece18 1 /* mbed Microcontroller Library
demayer 0:6bf0743ece18 2 * Copyright (c) 2017-2017 ARM Limited
demayer 0:6bf0743ece18 3 *
demayer 0:6bf0743ece18 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
demayer 0:6bf0743ece18 5 * of this software and associated documentation files (the "Software"), to deal
demayer 0:6bf0743ece18 6 * in the Software without restriction, including without limitation the rights
demayer 0:6bf0743ece18 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
demayer 0:6bf0743ece18 8 * copies of the Software, and to permit persons to whom the Software is
demayer 0:6bf0743ece18 9 * furnished to do so, subject to the following conditions:
demayer 0:6bf0743ece18 10 *
demayer 0:6bf0743ece18 11 * The above copyright notice and this permission notice shall be included in
demayer 0:6bf0743ece18 12 * all copies or substantial portions of the Software.
demayer 0:6bf0743ece18 13 *
demayer 0:6bf0743ece18 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
demayer 0:6bf0743ece18 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
demayer 0:6bf0743ece18 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
demayer 0:6bf0743ece18 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
demayer 0:6bf0743ece18 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
demayer 0:6bf0743ece18 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
demayer 0:6bf0743ece18 20 * SOFTWARE.
demayer 0:6bf0743ece18 21 */
demayer 0:6bf0743ece18 22 #ifndef CONDITIONVARIABLE_H
demayer 0:6bf0743ece18 23 #define CONDITIONVARIABLE_H
demayer 0:6bf0743ece18 24
demayer 0:6bf0743ece18 25 #include <stdint.h>
demayer 0:6bf0743ece18 26 #include "cmsis_os.h"
demayer 0:6bf0743ece18 27 #include "rtos/Mutex.h"
demayer 0:6bf0743ece18 28 #include "rtos/Semaphore.h"
demayer 0:6bf0743ece18 29
demayer 0:6bf0743ece18 30 #include "platform/NonCopyable.h"
demayer 0:6bf0743ece18 31
demayer 0:6bf0743ece18 32 namespace rtos {
demayer 0:6bf0743ece18 33 /** \addtogroup rtos */
demayer 0:6bf0743ece18 34 /** @{*/
demayer 0:6bf0743ece18 35
demayer 0:6bf0743ece18 36 struct Waiter;
demayer 0:6bf0743ece18 37
demayer 0:6bf0743ece18 38 /** This class provides a safe way to wait for or send notifications of condition changes
demayer 0:6bf0743ece18 39 *
demayer 0:6bf0743ece18 40 * This class is used in conjunction with a mutex to safely wait for or
demayer 0:6bf0743ece18 41 * notify waiters of condition changes to a resource accessible by multiple
demayer 0:6bf0743ece18 42 * threads.
demayer 0:6bf0743ece18 43 *
demayer 0:6bf0743ece18 44 * # Defined behavior
demayer 0:6bf0743ece18 45 * - All threads waiting on the condition variable wake when
demayer 0:6bf0743ece18 46 * ConditionVariable::notify_all is called.
demayer 0:6bf0743ece18 47 * - If one or more threads are waiting on the condition variable at least
demayer 0:6bf0743ece18 48 * one of them wakes when ConditionVariable::notify is called.
demayer 0:6bf0743ece18 49 *
demayer 0:6bf0743ece18 50 * # Undefined behavior
demayer 0:6bf0743ece18 51 * - The thread which is unblocked on ConditionVariable::notify_one is
demayer 0:6bf0743ece18 52 * undefined if there are multiple waiters.
demayer 0:6bf0743ece18 53 * - The order which in which waiting threads acquire the condition variable's
demayer 0:6bf0743ece18 54 * mutex after ConditionVariable::notify_all is called is undefined.
demayer 0:6bf0743ece18 55 * - When ConditionVariable::notify_one or ConditionVariable::notify_all is
demayer 0:6bf0743ece18 56 * called and there are one or more waiters and one or more threads attempting
demayer 0:6bf0743ece18 57 * to acquire the condition variable's mutex the order in which the mutex is
demayer 0:6bf0743ece18 58 * acquired is undefined.
demayer 0:6bf0743ece18 59 * - The behavior of ConditionVariable::wait and ConditionVariable::wait_for
demayer 0:6bf0743ece18 60 * is undefined if the condition variable's mutex is locked more than once by
demayer 0:6bf0743ece18 61 * the calling thread.
demayer 0:6bf0743ece18 62 * - Spurious notifications (not triggered by the application) can occur
demayer 0:6bf0743ece18 63 * and it is not defined when these occur.
demayer 0:6bf0743ece18 64 *
demayer 0:6bf0743ece18 65 * @note Synchronization level: Thread safe
demayer 0:6bf0743ece18 66 *
demayer 0:6bf0743ece18 67 * Example:
demayer 0:6bf0743ece18 68 * @code
demayer 0:6bf0743ece18 69 * #include "mbed.h"
demayer 0:6bf0743ece18 70 *
demayer 0:6bf0743ece18 71 * Mutex mutex;
demayer 0:6bf0743ece18 72 * ConditionVariable cond(mutex);
demayer 0:6bf0743ece18 73 *
demayer 0:6bf0743ece18 74 * // These variables are protected by locking mutex
demayer 0:6bf0743ece18 75 * uint32_t count = 0;
demayer 0:6bf0743ece18 76 * bool done = false;
demayer 0:6bf0743ece18 77 *
demayer 0:6bf0743ece18 78 * void worker_thread()
demayer 0:6bf0743ece18 79 * {
demayer 0:6bf0743ece18 80 * mutex.lock();
demayer 0:6bf0743ece18 81 * do {
demayer 0:6bf0743ece18 82 * printf("Worker: Count %lu\r\n", count);
demayer 0:6bf0743ece18 83 *
demayer 0:6bf0743ece18 84 * // Wait for a condition to change
demayer 0:6bf0743ece18 85 * cond.wait();
demayer 0:6bf0743ece18 86 *
demayer 0:6bf0743ece18 87 * } while (!done);
demayer 0:6bf0743ece18 88 * printf("Worker: Exiting\r\n");
demayer 0:6bf0743ece18 89 * mutex.unlock();
demayer 0:6bf0743ece18 90 * }
demayer 0:6bf0743ece18 91 *
demayer 0:6bf0743ece18 92 * int main() {
demayer 0:6bf0743ece18 93 * Thread thread;
demayer 0:6bf0743ece18 94 * thread.start(worker_thread);
demayer 0:6bf0743ece18 95 *
demayer 0:6bf0743ece18 96 * for (int i = 0; i < 5; i++) {
demayer 0:6bf0743ece18 97 *
demayer 0:6bf0743ece18 98 * mutex.lock();
demayer 0:6bf0743ece18 99 * // Change count and notify waiters of this
demayer 0:6bf0743ece18 100 * count++;
demayer 0:6bf0743ece18 101 * printf("Main: Set count to %lu\r\n", count);
demayer 0:6bf0743ece18 102 * cond.notify_all();
demayer 0:6bf0743ece18 103 * mutex.unlock();
demayer 0:6bf0743ece18 104 *
demayer 0:6bf0743ece18 105 * wait(1.0);
demayer 0:6bf0743ece18 106 * }
demayer 0:6bf0743ece18 107 *
demayer 0:6bf0743ece18 108 * mutex.lock();
demayer 0:6bf0743ece18 109 * // Change done and notify waiters of this
demayer 0:6bf0743ece18 110 * done = true;
demayer 0:6bf0743ece18 111 * printf("Main: Set done\r\n");
demayer 0:6bf0743ece18 112 * cond.notify_all();
demayer 0:6bf0743ece18 113 * mutex.unlock();
demayer 0:6bf0743ece18 114 *
demayer 0:6bf0743ece18 115 * thread.join();
demayer 0:6bf0743ece18 116 * }
demayer 0:6bf0743ece18 117 * @endcode
demayer 0:6bf0743ece18 118 */
demayer 0:6bf0743ece18 119 class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
demayer 0:6bf0743ece18 120 public:
demayer 0:6bf0743ece18 121 /** Create and Initialize a ConditionVariable object */
demayer 0:6bf0743ece18 122 ConditionVariable(Mutex &mutex);
demayer 0:6bf0743ece18 123
demayer 0:6bf0743ece18 124 /** Wait for a notification
demayer 0:6bf0743ece18 125 *
demayer 0:6bf0743ece18 126 * Wait until a notification occurs.
demayer 0:6bf0743ece18 127 *
demayer 0:6bf0743ece18 128 * @note - The thread calling this function must be the owner of the
demayer 0:6bf0743ece18 129 * ConditionVariable's mutex and it must be locked exactly once
demayer 0:6bf0743ece18 130 * @note - Spurious notifications can occur so the caller of this API
demayer 0:6bf0743ece18 131 * should check to make sure the condition they are waiting on has
demayer 0:6bf0743ece18 132 * been met
demayer 0:6bf0743ece18 133 *
demayer 0:6bf0743ece18 134 * Example:
demayer 0:6bf0743ece18 135 * @code
demayer 0:6bf0743ece18 136 * mutex.lock();
demayer 0:6bf0743ece18 137 * while (!condition_met) {
demayer 0:6bf0743ece18 138 * cond.wait();
demayer 0:6bf0743ece18 139 * }
demayer 0:6bf0743ece18 140 *
demayer 0:6bf0743ece18 141 * function_to_handle_condition();
demayer 0:6bf0743ece18 142 *
demayer 0:6bf0743ece18 143 * mutex.unlock();
demayer 0:6bf0743ece18 144 * @endcode
demayer 0:6bf0743ece18 145 */
demayer 0:6bf0743ece18 146 void wait();
demayer 0:6bf0743ece18 147
demayer 0:6bf0743ece18 148 /** Wait for a notification or timeout
demayer 0:6bf0743ece18 149 *
demayer 0:6bf0743ece18 150 * @param millisec timeout value or osWaitForever in case of no time-out.
demayer 0:6bf0743ece18 151 * @return true if a timeout occurred, false otherwise.
demayer 0:6bf0743ece18 152 *
demayer 0:6bf0743ece18 153 * @note - The thread calling this function must be the owner of the
demayer 0:6bf0743ece18 154 * ConditionVariable's mutex and it must be locked exactly once
demayer 0:6bf0743ece18 155 * @note - Spurious notifications can occur so the caller of this API
demayer 0:6bf0743ece18 156 * should check to make sure the condition they are waiting on has
demayer 0:6bf0743ece18 157 * been met
demayer 0:6bf0743ece18 158 *
demayer 0:6bf0743ece18 159 * Example:
demayer 0:6bf0743ece18 160 * @code
demayer 0:6bf0743ece18 161 * mutex.lock();
demayer 0:6bf0743ece18 162 * Timer timer;
demayer 0:6bf0743ece18 163 * timer.start();
demayer 0:6bf0743ece18 164 *
demayer 0:6bf0743ece18 165 * bool timed_out = false;
demayer 0:6bf0743ece18 166 * uint32_t time_left = TIMEOUT;
demayer 0:6bf0743ece18 167 * while (!condition_met && !timed_out) {
demayer 0:6bf0743ece18 168 * timed_out = cond.wait_for(time_left);
demayer 0:6bf0743ece18 169 * uint32_t elapsed = timer.read_ms();
demayer 0:6bf0743ece18 170 * time_left = elapsed > TIMEOUT ? 0 : TIMEOUT - elapsed;
demayer 0:6bf0743ece18 171 * }
demayer 0:6bf0743ece18 172 *
demayer 0:6bf0743ece18 173 * if (condition_met) {
demayer 0:6bf0743ece18 174 * function_to_handle_condition();
demayer 0:6bf0743ece18 175 * }
demayer 0:6bf0743ece18 176 *
demayer 0:6bf0743ece18 177 * mutex.unlock();
demayer 0:6bf0743ece18 178 * @endcode
demayer 0:6bf0743ece18 179 */
demayer 0:6bf0743ece18 180 bool wait_for(uint32_t millisec);
demayer 0:6bf0743ece18 181
demayer 0:6bf0743ece18 182 /** Notify one waiter on this condition variable that a condition changed.
demayer 0:6bf0743ece18 183 *
demayer 0:6bf0743ece18 184 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
demayer 0:6bf0743ece18 185 */
demayer 0:6bf0743ece18 186 void notify_one();
demayer 0:6bf0743ece18 187
demayer 0:6bf0743ece18 188 /** Notify all waiters on this condition variable that a condition changed.
demayer 0:6bf0743ece18 189 *
demayer 0:6bf0743ece18 190 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
demayer 0:6bf0743ece18 191 */
demayer 0:6bf0743ece18 192 void notify_all();
demayer 0:6bf0743ece18 193
demayer 0:6bf0743ece18 194 ~ConditionVariable();
demayer 0:6bf0743ece18 195
demayer 0:6bf0743ece18 196 protected:
demayer 0:6bf0743ece18 197 struct Waiter {
demayer 0:6bf0743ece18 198 Waiter();
demayer 0:6bf0743ece18 199 Semaphore sem;
demayer 0:6bf0743ece18 200 Waiter *prev;
demayer 0:6bf0743ece18 201 Waiter *next;
demayer 0:6bf0743ece18 202 bool in_list;
demayer 0:6bf0743ece18 203 };
demayer 0:6bf0743ece18 204
demayer 0:6bf0743ece18 205 static void _add_wait_list(Waiter **wait_list, Waiter *waiter);
demayer 0:6bf0743ece18 206 static void _remove_wait_list(Waiter **wait_list, Waiter *waiter);
demayer 0:6bf0743ece18 207 Mutex &_mutex;
demayer 0:6bf0743ece18 208 Waiter *_wait_list;
demayer 0:6bf0743ece18 209 };
demayer 0:6bf0743ece18 210
demayer 0:6bf0743ece18 211 }
demayer 0:6bf0743ece18 212 #endif
demayer 0:6bf0743ece18 213
demayer 0:6bf0743ece18 214 /** @}*/