游戏王对战板,目前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) 2018 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 "hal/lp_ticker_api.h"
WFKnight 0:9b3d4731edbb 17
WFKnight 0:9b3d4731edbb 18 #if DEVICE_LPTICKER && (LPTICKER_DELAY_TICKS > 0)
WFKnight 0:9b3d4731edbb 19
WFKnight 0:9b3d4731edbb 20 #include "Timeout.h"
WFKnight 0:9b3d4731edbb 21 #include "mbed_critical.h"
WFKnight 0:9b3d4731edbb 22
WFKnight 0:9b3d4731edbb 23 static const timestamp_t min_delta = LPTICKER_DELAY_TICKS;
WFKnight 0:9b3d4731edbb 24
WFKnight 0:9b3d4731edbb 25 static bool init = false;
WFKnight 0:9b3d4731edbb 26 static bool pending = false;
WFKnight 0:9b3d4731edbb 27 static bool timeout_pending = false;
WFKnight 0:9b3d4731edbb 28 static timestamp_t last_set_interrupt = 0;
WFKnight 0:9b3d4731edbb 29 static timestamp_t last_request = 0;
WFKnight 0:9b3d4731edbb 30 static timestamp_t next = 0;
WFKnight 0:9b3d4731edbb 31
WFKnight 0:9b3d4731edbb 32 static timestamp_t mask;
WFKnight 0:9b3d4731edbb 33 static timestamp_t reschedule_us;
WFKnight 0:9b3d4731edbb 34
WFKnight 0:9b3d4731edbb 35 // Do not use SingletonPtr since this must be initialized in a critical section
WFKnight 0:9b3d4731edbb 36 static mbed::Timeout *timeout;
WFKnight 0:9b3d4731edbb 37 static uint64_t timeout_data[sizeof(mbed::Timeout) / 8];
WFKnight 0:9b3d4731edbb 38
WFKnight 0:9b3d4731edbb 39 /**
WFKnight 0:9b3d4731edbb 40 * Initialize variables
WFKnight 0:9b3d4731edbb 41 */
WFKnight 0:9b3d4731edbb 42 static void init_local()
WFKnight 0:9b3d4731edbb 43 {
WFKnight 0:9b3d4731edbb 44 MBED_ASSERT(core_util_in_critical_section());
WFKnight 0:9b3d4731edbb 45
WFKnight 0:9b3d4731edbb 46 const ticker_info_t* info = lp_ticker_get_info();
WFKnight 0:9b3d4731edbb 47 if (info->bits >= 32) {
WFKnight 0:9b3d4731edbb 48 mask = 0xffffffff;
WFKnight 0:9b3d4731edbb 49 } else {
WFKnight 0:9b3d4731edbb 50 mask = ((uint64_t)1 << info->bits) - 1;
WFKnight 0:9b3d4731edbb 51 }
WFKnight 0:9b3d4731edbb 52
WFKnight 0:9b3d4731edbb 53 // Round us_per_tick up
WFKnight 0:9b3d4731edbb 54 timestamp_t us_per_tick = (1000000 + info->frequency - 1) / info->frequency;
WFKnight 0:9b3d4731edbb 55
WFKnight 0:9b3d4731edbb 56 // Add 1 tick to the min delta for the case where the clock transitions after you read it
WFKnight 0:9b3d4731edbb 57 // Add 4 microseconds to round up the micro second ticker time (which has a frequency of at least 250KHz - 4us period)
WFKnight 0:9b3d4731edbb 58 reschedule_us = (min_delta + 1) * us_per_tick + 4;
WFKnight 0:9b3d4731edbb 59
WFKnight 0:9b3d4731edbb 60 timeout = new (timeout_data) mbed::Timeout();
WFKnight 0:9b3d4731edbb 61 }
WFKnight 0:9b3d4731edbb 62
WFKnight 0:9b3d4731edbb 63 /**
WFKnight 0:9b3d4731edbb 64 * Call lp_ticker_set_interrupt with a value that is guaranteed to fire
WFKnight 0:9b3d4731edbb 65 *
WFKnight 0:9b3d4731edbb 66 * Assumptions
WFKnight 0:9b3d4731edbb 67 * -Only one low power clock tick can pass from the last read (last_read)
WFKnight 0:9b3d4731edbb 68 * -The closest an interrupt can fire is max_delta + 1
WFKnight 0:9b3d4731edbb 69 *
WFKnight 0:9b3d4731edbb 70 * @param last_read The last value read from lp_ticker_read
WFKnight 0:9b3d4731edbb 71 * @param timestamp The timestamp to trigger the interrupt at
WFKnight 0:9b3d4731edbb 72 */
WFKnight 0:9b3d4731edbb 73 static void set_interrupt_safe(timestamp_t last_read, timestamp_t timestamp)
WFKnight 0:9b3d4731edbb 74 {
WFKnight 0:9b3d4731edbb 75 MBED_ASSERT(core_util_in_critical_section());
WFKnight 0:9b3d4731edbb 76 uint32_t delta = (timestamp - last_read) & mask;
WFKnight 0:9b3d4731edbb 77 if (delta < min_delta + 2) {
WFKnight 0:9b3d4731edbb 78 timestamp = (last_read + min_delta + 2) & mask;
WFKnight 0:9b3d4731edbb 79 }
WFKnight 0:9b3d4731edbb 80 lp_ticker_set_interrupt(timestamp);
WFKnight 0:9b3d4731edbb 81 }
WFKnight 0:9b3d4731edbb 82
WFKnight 0:9b3d4731edbb 83 /**
WFKnight 0:9b3d4731edbb 84 * Set the low power ticker match time when hardware is ready
WFKnight 0:9b3d4731edbb 85 *
WFKnight 0:9b3d4731edbb 86 * This event is scheduled to set the lp timer after the previous write
WFKnight 0:9b3d4731edbb 87 * has taken effect and it is safe to write a new value without blocking.
WFKnight 0:9b3d4731edbb 88 * If the time has already passed then this function fires and interrupt
WFKnight 0:9b3d4731edbb 89 * immediately.
WFKnight 0:9b3d4731edbb 90 */
WFKnight 0:9b3d4731edbb 91 static void set_interrupt_later()
WFKnight 0:9b3d4731edbb 92 {
WFKnight 0:9b3d4731edbb 93 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 94
WFKnight 0:9b3d4731edbb 95 timestamp_t current = lp_ticker_read();
WFKnight 0:9b3d4731edbb 96 if (_ticker_match_interval_passed(last_request, current, next)) {
WFKnight 0:9b3d4731edbb 97 lp_ticker_fire_interrupt();
WFKnight 0:9b3d4731edbb 98 } else {
WFKnight 0:9b3d4731edbb 99 set_interrupt_safe(current, next);
WFKnight 0:9b3d4731edbb 100 last_set_interrupt = lp_ticker_read();
WFKnight 0:9b3d4731edbb 101 }
WFKnight 0:9b3d4731edbb 102 timeout_pending = false;
WFKnight 0:9b3d4731edbb 103
WFKnight 0:9b3d4731edbb 104 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 105 }
WFKnight 0:9b3d4731edbb 106
WFKnight 0:9b3d4731edbb 107 /**
WFKnight 0:9b3d4731edbb 108 * Wrapper around lp_ticker_set_interrupt to prevent blocking
WFKnight 0:9b3d4731edbb 109 *
WFKnight 0:9b3d4731edbb 110 * Problems this function is solving:
WFKnight 0:9b3d4731edbb 111 * 1. Interrupt may not fire if set earlier than LPTICKER_DELAY_TICKS low power clock cycles
WFKnight 0:9b3d4731edbb 112 * 2. Setting the interrupt back-to-back will block
WFKnight 0:9b3d4731edbb 113 *
WFKnight 0:9b3d4731edbb 114 * This wrapper function prevents lp_ticker_set_interrupt from being called
WFKnight 0:9b3d4731edbb 115 * back-to-back and blocking while the first write is in progress. This function
WFKnight 0:9b3d4731edbb 116 * avoids that problem by scheduling a timeout event if the lp ticker is in the
WFKnight 0:9b3d4731edbb 117 * middle of a write operation.
WFKnight 0:9b3d4731edbb 118 *
WFKnight 0:9b3d4731edbb 119 * @param timestamp Time to call ticker irq
WFKnight 0:9b3d4731edbb 120 * @note this is a utility function and it's not required part of HAL implementation
WFKnight 0:9b3d4731edbb 121 */
WFKnight 0:9b3d4731edbb 122 extern "C" void lp_ticker_set_interrupt_wrapper(timestamp_t timestamp)
WFKnight 0:9b3d4731edbb 123 {
WFKnight 0:9b3d4731edbb 124 core_util_critical_section_enter();
WFKnight 0:9b3d4731edbb 125
WFKnight 0:9b3d4731edbb 126 if (!init) {
WFKnight 0:9b3d4731edbb 127 init_local();
WFKnight 0:9b3d4731edbb 128 init = true;
WFKnight 0:9b3d4731edbb 129 }
WFKnight 0:9b3d4731edbb 130
WFKnight 0:9b3d4731edbb 131 timestamp_t current = lp_ticker_read();
WFKnight 0:9b3d4731edbb 132 if (pending) {
WFKnight 0:9b3d4731edbb 133 // Check if pending should be cleared
WFKnight 0:9b3d4731edbb 134 if (((current - last_set_interrupt) & mask) >= min_delta) {
WFKnight 0:9b3d4731edbb 135 pending = false;
WFKnight 0:9b3d4731edbb 136 }
WFKnight 0:9b3d4731edbb 137 }
WFKnight 0:9b3d4731edbb 138
WFKnight 0:9b3d4731edbb 139 if (pending || timeout_pending) {
WFKnight 0:9b3d4731edbb 140 next = timestamp;
WFKnight 0:9b3d4731edbb 141 last_request = current;
WFKnight 0:9b3d4731edbb 142 if (!timeout_pending) {
WFKnight 0:9b3d4731edbb 143 timeout->attach_us(set_interrupt_later, reschedule_us);
WFKnight 0:9b3d4731edbb 144 timeout_pending = true;
WFKnight 0:9b3d4731edbb 145 }
WFKnight 0:9b3d4731edbb 146 } else {
WFKnight 0:9b3d4731edbb 147 // Schedule immediately if nothing is pending
WFKnight 0:9b3d4731edbb 148 set_interrupt_safe(current, timestamp);
WFKnight 0:9b3d4731edbb 149 last_set_interrupt = lp_ticker_read();
WFKnight 0:9b3d4731edbb 150 pending = true;
WFKnight 0:9b3d4731edbb 151 }
WFKnight 0:9b3d4731edbb 152
WFKnight 0:9b3d4731edbb 153 core_util_critical_section_exit();
WFKnight 0:9b3d4731edbb 154 }
WFKnight 0:9b3d4731edbb 155
WFKnight 0:9b3d4731edbb 156 #endif