Erste version der Software für der Prototyp

Committer:
borlanic
Date:
Thu Mar 29 07:02:09 2018 +0000
Revision:
0:380207fcb5c1
Encoder, IMU --> OK; Controller --> in bearbeitung

Who changed what in which revision?

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