游戏王对战板,目前code还是空的

Committer:
WFKnight
Date:
Thu Jun 21 13:51:43 2018 +0000
Revision:
0:9b3d4731edbb
UART, RTOS, LED

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WFKnight 0:9b3d4731edbb 1 /* mbed Microcontroller Library
WFKnight 0:9b3d4731edbb 2 * Copyright (c) 2015 ARM Limited
WFKnight 0:9b3d4731edbb 3 *
WFKnight 0:9b3d4731edbb 4 * Licensed under the Apache License, Version 2.0 (the "License");
WFKnight 0:9b3d4731edbb 5 * you may not use this file except in compliance with the License.
WFKnight 0:9b3d4731edbb 6 * You may obtain a copy of the License at
WFKnight 0:9b3d4731edbb 7 *
WFKnight 0:9b3d4731edbb 8 * http://www.apache.org/licenses/LICENSE-2.0
WFKnight 0:9b3d4731edbb 9 *
WFKnight 0:9b3d4731edbb 10 * Unless required by applicable law or agreed to in writing, software
WFKnight 0:9b3d4731edbb 11 * distributed under the License is distributed on an "AS IS" BASIS,
WFKnight 0:9b3d4731edbb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
WFKnight 0:9b3d4731edbb 13 * See the License for the specific language governing permissions and
WFKnight 0:9b3d4731edbb 14 * limitations under the License.
WFKnight 0:9b3d4731edbb 15 */
WFKnight 0:9b3d4731edbb 16 #include <stdio.h>
WFKnight 0:9b3d4731edbb 17 #include <stddef.h>
WFKnight 0:9b3d4731edbb 18 #include "hal/ticker_api.h"
WFKnight 0:9b3d4731edbb 19 #include "platform/mbed_critical.h"
WFKnight 0:9b3d4731edbb 20 #include "mbed_assert.h"
WFKnight 0:9b3d4731edbb 21
WFKnight 0:9b3d4731edbb 22 static void schedule_interrupt(const ticker_data_t *const ticker);
WFKnight 0:9b3d4731edbb 23 static void update_present_time(const ticker_data_t *const ticker);
WFKnight 0:9b3d4731edbb 24
WFKnight 0:9b3d4731edbb 25 /*
WFKnight 0:9b3d4731edbb 26 * Initialize a ticker instance.
WFKnight 0:9b3d4731edbb 27 */
WFKnight 0:9b3d4731edbb 28 static void initialize(const ticker_data_t *ticker)
WFKnight 0:9b3d4731edbb 29 {
WFKnight 0:9b3d4731edbb 30 // return if the queue has already been initialized, in that case the
WFKnight 0:9b3d4731edbb 31 // interface used by the queue is already initialized.
WFKnight 0:9b3d4731edbb 32 if (ticker->queue->initialized) {
WFKnight 0:9b3d4731edbb 33 return;
WFKnight 0:9b3d4731edbb 34 }
WFKnight 0:9b3d4731edbb 35
WFKnight 0:9b3d4731edbb 36 ticker->interface->init();
WFKnight 0:9b3d4731edbb 37
WFKnight 0:9b3d4731edbb 38 const ticker_info_t *info = ticker->interface->get_info();
WFKnight 0:9b3d4731edbb 39 uint32_t frequency = info->frequency;
WFKnight 0:9b3d4731edbb 40 if (info->frequency == 0) {
WFKnight 0:9b3d4731edbb 41 MBED_ASSERT(0);
WFKnight 0:9b3d4731edbb 42 frequency = 1000000;
WFKnight 0:9b3d4731edbb 43 }
WFKnight 0:9b3d4731edbb 44
WFKnight 0:9b3d4731edbb 45 uint8_t frequency_shifts = 0;
WFKnight 0:9b3d4731edbb 46 for (uint8_t i = 31; i > 0; --i) {
WFKnight 0:9b3d4731edbb 47 if ((1 << i) == frequency) {
WFKnight 0:9b3d4731edbb 48 frequency_shifts = i;
WFKnight 0:9b3d4731edbb 49 break;
WFKnight 0:9b3d4731edbb 50 }
WFKnight 0:9b3d4731edbb 51 }
WFKnight 0:9b3d4731edbb 52
WFKnight 0:9b3d4731edbb 53 uint32_t bits = info->bits;
WFKnight 0:9b3d4731edbb 54 if ((info->bits > 32) || (info->bits < 4)) {
WFKnight 0:9b3d4731edbb 55 MBED_ASSERT(0);
WFKnight 0:9b3d4731edbb 56 bits = 32;
WFKnight 0:9b3d4731edbb 57 }
WFKnight 0:9b3d4731edbb 58 uint32_t max_delta = 0x7 << (bits - 4); // 7/16th
WFKnight 0:9b3d4731edbb 59 uint64_t max_delta_us =
WFKnight 0:9b3d4731edbb 60 ((uint64_t)max_delta * 1000000 + frequency - 1) / frequency;
WFKnight 0:9b3d4731edbb 61
WFKnight 0:9b3d4731edbb 62 ticker->queue->event_handler = NULL;
WFKnight 0:9b3d4731edbb 63 ticker->queue->head = NULL;
WFKnight 0:9b3d4731edbb 64 ticker->queue->tick_last_read = ticker->interface->read();
WFKnight 0:9b3d4731edbb 65 ticker->queue->tick_remainder = 0;
WFKnight 0:9b3d4731edbb 66 ticker->queue->frequency = frequency;
WFKnight 0:9b3d4731edbb 67 ticker->queue->frequency_shifts = frequency_shifts;
WFKnight 0:9b3d4731edbb 68 ticker->queue->bitmask = ((uint64_t)1 << bits) - 1;
WFKnight 0:9b3d4731edbb 69 ticker->queue->max_delta = max_delta;
WFKnight 0:9b3d4731edbb 70 ticker->queue->max_delta_us = max_delta_us;
WFKnight 0:9b3d4731edbb 71 ticker->queue->present_time = 0;
WFKnight 0:9b3d4731edbb 72 ticker->queue->initialized = true;
WFKnight 0:9b3d4731edbb 73
WFKnight 0:9b3d4731edbb 74 update_present_time(ticker);
WFKnight 0:9b3d4731edbb 75 schedule_interrupt(ticker);
WFKnight 0:9b3d4731edbb 76 }
WFKnight 0:9b3d4731edbb 77
WFKnight 0:9b3d4731edbb 78 /**
WFKnight 0:9b3d4731edbb 79 * Set the event handler function of a ticker instance.
WFKnight 0:9b3d4731edbb 80 */
WFKnight 0:9b3d4731edbb 81 static void set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
WFKnight 0:9b3d4731edbb 82 {
WFKnight 0:9b3d4731edbb 83 ticker->queue->event_handler = handler;
WFKnight 0:9b3d4731edbb 84 }
WFKnight 0:9b3d4731edbb 85
WFKnight 0:9b3d4731edbb 86 /*
WFKnight 0:9b3d4731edbb 87 * Convert a 32 bit timestamp into a 64 bit timestamp.
WFKnight 0:9b3d4731edbb 88 *
WFKnight 0:9b3d4731edbb 89 * A 64 bit timestamp is used as the point of time of reference while the
WFKnight 0:9b3d4731edbb 90 * timestamp to convert is relative to this point of time.
WFKnight 0:9b3d4731edbb 91 *
WFKnight 0:9b3d4731edbb 92 * The lower 32 bits of the timestamp returned will be equal to the timestamp to
WFKnight 0:9b3d4731edbb 93 * convert.
WFKnight 0:9b3d4731edbb 94 *
WFKnight 0:9b3d4731edbb 95 * If the timestamp to convert is less than the lower 32 bits of the time
WFKnight 0:9b3d4731edbb 96 * reference then the timestamp to convert is seen as an overflowed value and
WFKnight 0:9b3d4731edbb 97 * the upper 32 bit of the timestamp returned will be equal to the upper 32 bit
WFKnight 0:9b3d4731edbb 98 * of the reference point + 1.
WFKnight 0:9b3d4731edbb 99 * Otherwise, the upper 32 bit returned will be equal to the upper 32 bit of the
WFKnight 0:9b3d4731edbb 100 * reference point.
WFKnight 0:9b3d4731edbb 101 *
WFKnight 0:9b3d4731edbb 102 * @param ref: The 64 bit timestamp of reference.
WFKnight 0:9b3d4731edbb 103 * @param timestamp: The timestamp to convert.
WFKnight 0:9b3d4731edbb 104 */
WFKnight 0:9b3d4731edbb 105 static us_timestamp_t convert_timestamp(us_timestamp_t ref, timestamp_t timestamp)
WFKnight 0:9b3d4731edbb 106 {
WFKnight 0:9b3d4731edbb 107 bool overflow = timestamp < ((timestamp_t) ref) ? true : false;
WFKnight 0:9b3d4731edbb 108
WFKnight 0:9b3d4731edbb 109 us_timestamp_t result = (ref & ~((us_timestamp_t)UINT32_MAX)) | timestamp;
WFKnight 0:9b3d4731edbb 110 if (overflow) {
WFKnight 0:9b3d4731edbb 111 result += (1ULL<<32);
WFKnight 0:9b3d4731edbb 112 }
WFKnight 0:9b3d4731edbb 113
WFKnight 0:9b3d4731edbb 114 return result;
WFKnight 0:9b3d4731edbb 115 }
WFKnight 0:9b3d4731edbb 116
WFKnight 0:9b3d4731edbb 117 /**
WFKnight 0:9b3d4731edbb 118 * Update the present timestamp value of a ticker.
WFKnight 0:9b3d4731edbb 119 */
WFKnight 0:9b3d4731edbb 120 static void update_present_time(const ticker_data_t *const ticker)
WFKnight 0:9b3d4731edbb 121 {
WFKnight 0:9b3d4731edbb 122 ticker_event_queue_t *queue = ticker->queue;
WFKnight 0:9b3d4731edbb 123 uint32_t ticker_time = ticker->interface->read();
WFKnight 0:9b3d4731edbb 124 if (ticker_time == ticker->queue->tick_last_read) {
WFKnight 0:9b3d4731edbb 125 // No work to do
WFKnight 0:9b3d4731edbb 126 return;
WFKnight 0:9b3d4731edbb 127 }
WFKnight 0:9b3d4731edbb 128
WFKnight 0:9b3d4731edbb 129 uint64_t elapsed_ticks = (ticker_time - queue->tick_last_read) & queue->bitmask;
WFKnight 0:9b3d4731edbb 130 queue->tick_last_read = ticker_time;
WFKnight 0:9b3d4731edbb 131
WFKnight 0:9b3d4731edbb 132 uint64_t elapsed_us;
WFKnight 0:9b3d4731edbb 133 if (1000000 == queue->frequency) {
WFKnight 0:9b3d4731edbb 134 // Optimized for 1MHz
WFKnight 0:9b3d4731edbb 135
WFKnight 0:9b3d4731edbb 136 elapsed_us = elapsed_ticks;
WFKnight 0:9b3d4731edbb 137 } else if (0 != queue->frequency_shifts) {
WFKnight 0:9b3d4731edbb 138 // Optimized for frequencies divisible by 2
WFKnight 0:9b3d4731edbb 139 uint64_t us_x_ticks = elapsed_ticks * 1000000;
WFKnight 0:9b3d4731edbb 140 elapsed_us = us_x_ticks >> queue->frequency_shifts;
WFKnight 0:9b3d4731edbb 141
WFKnight 0:9b3d4731edbb 142 // Update remainder
WFKnight 0:9b3d4731edbb 143 queue->tick_remainder += us_x_ticks - (elapsed_us << queue->frequency_shifts);
WFKnight 0:9b3d4731edbb 144 if (queue->tick_remainder >= queue->frequency) {
WFKnight 0:9b3d4731edbb 145 elapsed_us += 1;
WFKnight 0:9b3d4731edbb 146 queue->tick_remainder -= queue->frequency;
WFKnight 0:9b3d4731edbb 147 }
WFKnight 0:9b3d4731edbb 148 } else {
WFKnight 0:9b3d4731edbb 149 // General case
WFKnight 0:9b3d4731edbb 150
WFKnight 0:9b3d4731edbb 151 uint64_t us_x_ticks = elapsed_ticks * 1000000;
WFKnight 0:9b3d4731edbb 152 elapsed_us = us_x_ticks / queue->frequency;
WFKnight 0:9b3d4731edbb 153
WFKnight 0:9b3d4731edbb 154 // Update remainder
WFKnight 0:9b3d4731edbb 155 queue->tick_remainder += us_x_ticks - elapsed_us * queue->frequency;
WFKnight 0:9b3d4731edbb 156 if (queue->tick_remainder >= queue->frequency) {
WFKnight 0:9b3d4731edbb 157 elapsed_us += 1;
WFKnight 0:9b3d4731edbb 158 queue->tick_remainder -= queue->frequency;
WFKnight 0:9b3d4731edbb 159 }
WFKnight 0:9b3d4731edbb 160 }
WFKnight 0:9b3d4731edbb 161
WFKnight 0:9b3d4731edbb 162 // Update current time
WFKnight 0:9b3d4731edbb 163 queue->present_time += elapsed_us;
WFKnight 0:9b3d4731edbb 164 }
WFKnight 0:9b3d4731edbb 165
WFKnight 0:9b3d4731edbb 166 /**
WFKnight 0:9b3d4731edbb 167 * Given the absolute timestamp compute the hal tick timestamp.
WFKnight 0:9b3d4731edbb 168 */
WFKnight 0:9b3d4731edbb 169 static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_t timestamp)
WFKnight 0:9b3d4731edbb 170 {
WFKnight 0:9b3d4731edbb 171 ticker_event_queue_t *queue = ticker->queue;
WFKnight 0:9b3d4731edbb 172 us_timestamp_t delta_us = timestamp - queue->present_time;
WFKnight 0:9b3d4731edbb 173
WFKnight 0:9b3d4731edbb 174 timestamp_t delta = ticker->queue->max_delta;
WFKnight 0:9b3d4731edbb 175 if (delta_us <= ticker->queue->max_delta_us) {
WFKnight 0:9b3d4731edbb 176 // Checking max_delta_us ensures the operation will not overflow
WFKnight 0:9b3d4731edbb 177
WFKnight 0:9b3d4731edbb 178 if (1000000 == queue->frequency) {
WFKnight 0:9b3d4731edbb 179 // Optimized for 1MHz
WFKnight 0:9b3d4731edbb 180
WFKnight 0:9b3d4731edbb 181 delta = delta_us;
WFKnight 0:9b3d4731edbb 182 if (delta > ticker->queue->max_delta) {
WFKnight 0:9b3d4731edbb 183 delta = ticker->queue->max_delta;
WFKnight 0:9b3d4731edbb 184 }
WFKnight 0:9b3d4731edbb 185 } else if (0 != queue->frequency_shifts) {
WFKnight 0:9b3d4731edbb 186 // Optimized frequencies divisible by 2
WFKnight 0:9b3d4731edbb 187
WFKnight 0:9b3d4731edbb 188 delta = (delta_us << ticker->queue->frequency_shifts) / 1000000;
WFKnight 0:9b3d4731edbb 189 if (delta > ticker->queue->max_delta) {
WFKnight 0:9b3d4731edbb 190 delta = ticker->queue->max_delta;
WFKnight 0:9b3d4731edbb 191 }
WFKnight 0:9b3d4731edbb 192 } else {
WFKnight 0:9b3d4731edbb 193 // General case
WFKnight 0:9b3d4731edbb 194
WFKnight 0:9b3d4731edbb 195 delta = delta_us * queue->frequency / 1000000;
WFKnight 0:9b3d4731edbb 196 if (delta > ticker->queue->max_delta) {
WFKnight 0:9b3d4731edbb 197 delta = ticker->queue->max_delta;
WFKnight 0:9b3d4731edbb 198 }
WFKnight 0:9b3d4731edbb 199 }
WFKnight 0:9b3d4731edbb 200 }
WFKnight 0:9b3d4731edbb 201 return (queue->tick_last_read + delta) & queue->bitmask;
WFKnight 0:9b3d4731edbb 202 }
WFKnight 0:9b3d4731edbb 203
WFKnight 0:9b3d4731edbb 204 /**
WFKnight 0:9b3d4731edbb 205 * Return 1 if the tick has incremented to or past match_tick, otherwise 0.
WFKnight 0:9b3d4731edbb 206 */
WFKnight 0:9b3d4731edbb 207 int _ticker_match_interval_passed(timestamp_t prev_tick, timestamp_t cur_tick, timestamp_t match_tick)
WFKnight 0:9b3d4731edbb 208 {
WFKnight 0:9b3d4731edbb 209 if (match_tick > prev_tick) {
WFKnight 0:9b3d4731edbb 210 return (cur_tick >= match_tick) || (cur_tick < prev_tick);
WFKnight 0:9b3d4731edbb 211 } else {
WFKnight 0:9b3d4731edbb 212 return (cur_tick < prev_tick) && (cur_tick >= match_tick);
WFKnight 0:9b3d4731edbb 213 }
WFKnight 0:9b3d4731edbb 214 }
WFKnight 0:9b3d4731edbb 215
WFKnight 0:9b3d4731edbb 216 /**
WFKnight 0:9b3d4731edbb 217 * Compute the time when the interrupt has to be triggered and schedule it.
WFKnight 0:9b3d4731edbb 218 *
WFKnight 0:9b3d4731edbb 219 * If there is no event in the queue or the next event to execute is in more
WFKnight 0:9b3d4731edbb 220 * than ticker.queue.max_delta ticks from now then the ticker irq will be
WFKnight 0:9b3d4731edbb 221 * scheduled in ticker.queue.max_delta ticks. Otherwise the irq will be
WFKnight 0:9b3d4731edbb 222 * scheduled to happen when the running counter reach the timestamp of the
WFKnight 0:9b3d4731edbb 223 * first event in the queue.
WFKnight 0:9b3d4731edbb 224 *
WFKnight 0:9b3d4731edbb 225 * @note If there is no event in the queue then the interrupt is scheduled to
WFKnight 0:9b3d4731edbb 226 * in ticker.queue.max_delta. This is necessary to keep track
WFKnight 0:9b3d4731edbb 227 * of the timer overflow.
WFKnight 0:9b3d4731edbb 228 */
WFKnight 0:9b3d4731edbb 229 static void schedule_interrupt(const ticker_data_t *const ticker)
WFKnight 0:9b3d4731edbb 230 {
WFKnight 0:9b3d4731edbb 231 ticker_event_queue_t *queue = ticker->queue;
WFKnight 0:9b3d4731edbb 232 update_present_time(ticker);
WFKnight 0:9b3d4731edbb 233
WFKnight 0:9b3d4731edbb 234 if (ticker->queue->head) {
WFKnight 0:9b3d4731edbb 235 us_timestamp_t present = ticker->queue->present_time;
WFKnight 0:9b3d4731edbb 236 us_timestamp_t match_time = ticker->queue->head->timestamp;
WFKnight 0:9b3d4731edbb 237
WFKnight 0:9b3d4731edbb 238 // if the event at the head of the queue is in the past then schedule
WFKnight 0:9b3d4731edbb 239 // it immediately.
WFKnight 0:9b3d4731edbb 240 if (match_time <= present) {
WFKnight 0:9b3d4731edbb 241 ticker->interface->fire_interrupt();
WFKnight 0:9b3d4731edbb 242 return;
WFKnight 0:9b3d4731edbb 243 }
WFKnight 0:9b3d4731edbb 244
WFKnight 0:9b3d4731edbb 245 timestamp_t match_tick = compute_tick(ticker, match_time);
WFKnight 0:9b3d4731edbb 246 // The time has been checked to be future, but it could still round
WFKnight 0:9b3d4731edbb 247 // to the last tick as a result of us to ticks conversion
WFKnight 0:9b3d4731edbb 248 if (match_tick == queue->tick_last_read) {
WFKnight 0:9b3d4731edbb 249 // Match time has already expired so fire immediately
WFKnight 0:9b3d4731edbb 250 ticker->interface->fire_interrupt();
WFKnight 0:9b3d4731edbb 251 return;
WFKnight 0:9b3d4731edbb 252 }
WFKnight 0:9b3d4731edbb 253
WFKnight 0:9b3d4731edbb 254 ticker->interface->set_interrupt(match_tick);
WFKnight 0:9b3d4731edbb 255 timestamp_t cur_tick = ticker->interface->read();
WFKnight 0:9b3d4731edbb 256
WFKnight 0:9b3d4731edbb 257 if (_ticker_match_interval_passed(queue->tick_last_read, cur_tick, match_tick)) {
WFKnight 0:9b3d4731edbb 258 ticker->interface->fire_interrupt();
WFKnight 0:9b3d4731edbb 259 }
WFKnight 0:9b3d4731edbb 260 } else {
WFKnight 0:9b3d4731edbb 261 uint32_t match_tick =
WFKnight 0:9b3d4731edbb 262 (queue->tick_last_read + queue->max_delta) & queue->bitmask;
WFKnight 0:9b3d4731edbb 263 ticker->interface->set_interrupt(match_tick);
WFKnight 0:9b3d4731edbb 264 }
WFKnight 0:9b3d4731edbb 265 }
WFKnight 0:9b3d4731edbb 266
WFKnight 0:9b3d4731edbb 267 void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
WFKnight 0:9b3d4731edbb 268 {
WFKnight 0:9b3d4731edbb 269 initialize(ticker);
WFKnight 0:9b3d4731edbb 270
WFKnight 0:9b3d4731edbb 271 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 272 set_handler(ticker, handler);
WFKnight 0:9b3d4731edbb 273 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 274 }
WFKnight 0:9b3d4731edbb 275
WFKnight 0:9b3d4731edbb 276 void ticker_irq_handler(const ticker_data_t *const ticker)
WFKnight 0:9b3d4731edbb 277 {
WFKnight 0:9b3d4731edbb 278 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 279
WFKnight 0:9b3d4731edbb 280 ticker->interface->clear_interrupt();
WFKnight 0:9b3d4731edbb 281
WFKnight 0:9b3d4731edbb 282 /* Go through all the pending TimerEvents */
WFKnight 0:9b3d4731edbb 283 while (1) {
WFKnight 0:9b3d4731edbb 284 if (ticker->queue->head == NULL) {
WFKnight 0:9b3d4731edbb 285 break;
WFKnight 0:9b3d4731edbb 286 }
WFKnight 0:9b3d4731edbb 287
WFKnight 0:9b3d4731edbb 288 // update the current timestamp used by the queue
WFKnight 0:9b3d4731edbb 289 update_present_time(ticker);
WFKnight 0:9b3d4731edbb 290
WFKnight 0:9b3d4731edbb 291 if (ticker->queue->head->timestamp <= ticker->queue->present_time) {
WFKnight 0:9b3d4731edbb 292 // This event was in the past:
WFKnight 0:9b3d4731edbb 293 // point to the following one and execute its handler
WFKnight 0:9b3d4731edbb 294 ticker_event_t *p = ticker->queue->head;
WFKnight 0:9b3d4731edbb 295 ticker->queue->head = ticker->queue->head->next;
WFKnight 0:9b3d4731edbb 296 if (ticker->queue->event_handler != NULL) {
WFKnight 0:9b3d4731edbb 297 (*ticker->queue->event_handler)(p->id); // NOTE: the handler can set new events
WFKnight 0:9b3d4731edbb 298 }
WFKnight 0:9b3d4731edbb 299 /* Note: We continue back to examining the head because calling the
WFKnight 0:9b3d4731edbb 300 * event handler may have altered the chain of pending events. */
WFKnight 0:9b3d4731edbb 301 } else {
WFKnight 0:9b3d4731edbb 302 break;
WFKnight 0:9b3d4731edbb 303 }
WFKnight 0:9b3d4731edbb 304 }
WFKnight 0:9b3d4731edbb 305
WFKnight 0:9b3d4731edbb 306 schedule_interrupt(ticker);
WFKnight 0:9b3d4731edbb 307
WFKnight 0:9b3d4731edbb 308 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 309 }
WFKnight 0:9b3d4731edbb 310
WFKnight 0:9b3d4731edbb 311 void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, timestamp_t timestamp, uint32_t id)
WFKnight 0:9b3d4731edbb 312 {
WFKnight 0:9b3d4731edbb 313 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 314
WFKnight 0:9b3d4731edbb 315 // update the current timestamp
WFKnight 0:9b3d4731edbb 316 update_present_time(ticker);
WFKnight 0:9b3d4731edbb 317 us_timestamp_t absolute_timestamp = convert_timestamp(
WFKnight 0:9b3d4731edbb 318 ticker->queue->present_time,
WFKnight 0:9b3d4731edbb 319 timestamp
WFKnight 0:9b3d4731edbb 320 );
WFKnight 0:9b3d4731edbb 321
WFKnight 0:9b3d4731edbb 322 // defer to ticker_insert_event_us
WFKnight 0:9b3d4731edbb 323 ticker_insert_event_us(
WFKnight 0:9b3d4731edbb 324 ticker,
WFKnight 0:9b3d4731edbb 325 obj, absolute_timestamp, id
WFKnight 0:9b3d4731edbb 326 );
WFKnight 0:9b3d4731edbb 327
WFKnight 0:9b3d4731edbb 328 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 329 }
WFKnight 0:9b3d4731edbb 330
WFKnight 0:9b3d4731edbb 331 void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *obj, us_timestamp_t timestamp, uint32_t id)
WFKnight 0:9b3d4731edbb 332 {
WFKnight 0:9b3d4731edbb 333 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 334
WFKnight 0:9b3d4731edbb 335 // update the current timestamp
WFKnight 0:9b3d4731edbb 336 update_present_time(ticker);
WFKnight 0:9b3d4731edbb 337
WFKnight 0:9b3d4731edbb 338 // initialise our data
WFKnight 0:9b3d4731edbb 339 obj->timestamp = timestamp;
WFKnight 0:9b3d4731edbb 340 obj->id = id;
WFKnight 0:9b3d4731edbb 341
WFKnight 0:9b3d4731edbb 342 /* Go through the list until we either reach the end, or find
WFKnight 0:9b3d4731edbb 343 an element this should come before (which is possibly the
WFKnight 0:9b3d4731edbb 344 head). */
WFKnight 0:9b3d4731edbb 345 ticker_event_t *prev = NULL, *p = ticker->queue->head;
WFKnight 0:9b3d4731edbb 346 while (p != NULL) {
WFKnight 0:9b3d4731edbb 347 /* check if we come before p */
WFKnight 0:9b3d4731edbb 348 if (timestamp < p->timestamp) {
WFKnight 0:9b3d4731edbb 349 break;
WFKnight 0:9b3d4731edbb 350 }
WFKnight 0:9b3d4731edbb 351 /* go to the next element */
WFKnight 0:9b3d4731edbb 352 prev = p;
WFKnight 0:9b3d4731edbb 353 p = p->next;
WFKnight 0:9b3d4731edbb 354 }
WFKnight 0:9b3d4731edbb 355
WFKnight 0:9b3d4731edbb 356 /* if we're at the end p will be NULL, which is correct */
WFKnight 0:9b3d4731edbb 357 obj->next = p;
WFKnight 0:9b3d4731edbb 358
WFKnight 0:9b3d4731edbb 359 /* if prev is NULL we're at the head */
WFKnight 0:9b3d4731edbb 360 if (prev == NULL) {
WFKnight 0:9b3d4731edbb 361 ticker->queue->head = obj;
WFKnight 0:9b3d4731edbb 362 schedule_interrupt(ticker);
WFKnight 0:9b3d4731edbb 363 } else {
WFKnight 0:9b3d4731edbb 364 prev->next = obj;
WFKnight 0:9b3d4731edbb 365 }
WFKnight 0:9b3d4731edbb 366
WFKnight 0:9b3d4731edbb 367 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 368 }
WFKnight 0:9b3d4731edbb 369
WFKnight 0:9b3d4731edbb 370 void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj)
WFKnight 0:9b3d4731edbb 371 {
WFKnight 0:9b3d4731edbb 372 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 373
WFKnight 0:9b3d4731edbb 374 // remove this object from the list
WFKnight 0:9b3d4731edbb 375 if (ticker->queue->head == obj) {
WFKnight 0:9b3d4731edbb 376 // first in the list, so just drop me
WFKnight 0:9b3d4731edbb 377 ticker->queue->head = obj->next;
WFKnight 0:9b3d4731edbb 378 schedule_interrupt(ticker);
WFKnight 0:9b3d4731edbb 379 } else {
WFKnight 0:9b3d4731edbb 380 // find the object before me, then drop me
WFKnight 0:9b3d4731edbb 381 ticker_event_t* p = ticker->queue->head;
WFKnight 0:9b3d4731edbb 382 while (p != NULL) {
WFKnight 0:9b3d4731edbb 383 if (p->next == obj) {
WFKnight 0:9b3d4731edbb 384 p->next = obj->next;
WFKnight 0:9b3d4731edbb 385 break;
WFKnight 0:9b3d4731edbb 386 }
WFKnight 0:9b3d4731edbb 387 p = p->next;
WFKnight 0:9b3d4731edbb 388 }
WFKnight 0:9b3d4731edbb 389 }
WFKnight 0:9b3d4731edbb 390
WFKnight 0:9b3d4731edbb 391 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 392 }
WFKnight 0:9b3d4731edbb 393
WFKnight 0:9b3d4731edbb 394 timestamp_t ticker_read(const ticker_data_t *const ticker)
WFKnight 0:9b3d4731edbb 395 {
WFKnight 0:9b3d4731edbb 396 return ticker_read_us(ticker);
WFKnight 0:9b3d4731edbb 397 }
WFKnight 0:9b3d4731edbb 398
WFKnight 0:9b3d4731edbb 399 us_timestamp_t ticker_read_us(const ticker_data_t *const ticker)
WFKnight 0:9b3d4731edbb 400 {
WFKnight 0:9b3d4731edbb 401 initialize(ticker);
WFKnight 0:9b3d4731edbb 402
WFKnight 0:9b3d4731edbb 403 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 404 update_present_time(ticker);
WFKnight 0:9b3d4731edbb 405 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 406
WFKnight 0:9b3d4731edbb 407 return ticker->queue->present_time;
WFKnight 0:9b3d4731edbb 408 }
WFKnight 0:9b3d4731edbb 409
WFKnight 0:9b3d4731edbb 410 int ticker_get_next_timestamp(const ticker_data_t *const data, timestamp_t *timestamp)
WFKnight 0:9b3d4731edbb 411 {
WFKnight 0:9b3d4731edbb 412 int ret = 0;
WFKnight 0:9b3d4731edbb 413
WFKnight 0:9b3d4731edbb 414 /* if head is NULL, there are no pending events */
WFKnight 0:9b3d4731edbb 415 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 416 if (data->queue->head != NULL) {
WFKnight 0:9b3d4731edbb 417 *timestamp = data->queue->head->timestamp;
WFKnight 0:9b3d4731edbb 418 ret = 1;
WFKnight 0:9b3d4731edbb 419 }
WFKnight 0:9b3d4731edbb 420 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 421
WFKnight 0:9b3d4731edbb 422 return ret;
WFKnight 0:9b3d4731edbb 423 }