mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/api/us_ticker.c@189:f392fc9709a3, 2019-02-20 (annotated)
- Committer:
- AnnaBridge
- Date:
- Wed Feb 20 22:31:08 2019 +0000
- Revision:
- 189:f392fc9709a3
- Parent:
- 188:bcfe06ba3d64
mbed library release version 165
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 178:79309dc6340a | 1 | /******************************************************************************* |
AnnaBridge | 184:08ed48f1de7f | 2 | * Copyright (c) 2010-2018 Analog Devices, Inc. |
AnnaBridge | 178:79309dc6340a | 3 | * |
AnnaBridge | 178:79309dc6340a | 4 | * All rights reserved. |
AnnaBridge | 178:79309dc6340a | 5 | * |
AnnaBridge | 178:79309dc6340a | 6 | * Redistribution and use in source and binary forms, with or without modification, |
AnnaBridge | 178:79309dc6340a | 7 | * are permitted provided that the following conditions are met: |
AnnaBridge | 178:79309dc6340a | 8 | * - Redistributions of source code must retain the above copyright notice, |
AnnaBridge | 178:79309dc6340a | 9 | * this list of conditions and the following disclaimer. |
AnnaBridge | 178:79309dc6340a | 10 | * - Redistributions in binary form must reproduce the above copyright notice, |
AnnaBridge | 178:79309dc6340a | 11 | * this list of conditions and the following disclaimer in the documentation |
AnnaBridge | 178:79309dc6340a | 12 | * and/or other materials provided with the distribution. |
AnnaBridge | 178:79309dc6340a | 13 | * - Modified versions of the software must be conspicuously marked as such. |
AnnaBridge | 178:79309dc6340a | 14 | * - This software is licensed solely and exclusively for use with processors |
AnnaBridge | 178:79309dc6340a | 15 | * manufactured by or for Analog Devices, Inc. |
AnnaBridge | 178:79309dc6340a | 16 | * - This software may not be combined or merged with other code in any manner |
AnnaBridge | 178:79309dc6340a | 17 | * that would cause the software to become subject to terms and conditions |
AnnaBridge | 178:79309dc6340a | 18 | * which differ from those listed here. |
AnnaBridge | 178:79309dc6340a | 19 | * - Neither the name of Analog Devices, Inc. nor the names of its |
AnnaBridge | 178:79309dc6340a | 20 | * contributors may be used to endorse or promote products derived |
AnnaBridge | 178:79309dc6340a | 21 | * from this software without specific prior written permission. |
AnnaBridge | 178:79309dc6340a | 22 | * - The use of this software may or may not infringe the patent rights of one |
AnnaBridge | 178:79309dc6340a | 23 | * or more patent holders. This license does not release you from the |
AnnaBridge | 178:79309dc6340a | 24 | * requirement that you obtain separate licenses from these patent holders |
AnnaBridge | 178:79309dc6340a | 25 | * to use this software. |
AnnaBridge | 178:79309dc6340a | 26 | * |
AnnaBridge | 178:79309dc6340a | 27 | * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" |
AnnaBridge | 178:79309dc6340a | 28 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON- |
AnnaBridge | 178:79309dc6340a | 29 | * INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
AnnaBridge | 178:79309dc6340a | 30 | * DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE |
AnnaBridge | 178:79309dc6340a | 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR |
AnnaBridge | 178:79309dc6340a | 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF |
AnnaBridge | 178:79309dc6340a | 33 | * CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF |
AnnaBridge | 178:79309dc6340a | 34 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
AnnaBridge | 178:79309dc6340a | 35 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
AnnaBridge | 178:79309dc6340a | 36 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
AnnaBridge | 178:79309dc6340a | 37 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
AnnaBridge | 178:79309dc6340a | 38 | * POSSIBILITY OF SUCH DAMAGE. |
AnnaBridge | 178:79309dc6340a | 39 | ******************************************************************************/ |
AnnaBridge | 178:79309dc6340a | 40 | |
AnnaBridge | 178:79309dc6340a | 41 | #include <stdint.h> |
AnnaBridge | 178:79309dc6340a | 42 | #include <stdio.h> |
AnnaBridge | 178:79309dc6340a | 43 | #include <drivers/tmr/adi_tmr.h> |
AnnaBridge | 178:79309dc6340a | 44 | #include <drivers/pwr/adi_pwr.h> |
AnnaBridge | 178:79309dc6340a | 45 | #include <drivers/gpio/adi_gpio.h> |
AnnaBridge | 178:79309dc6340a | 46 | |
AnnaBridge | 178:79309dc6340a | 47 | #ifndef BITM_TMR_RGB_CTL_EN |
AnnaBridge | 178:79309dc6340a | 48 | #define BITM_TMR_RGB_CTL_EN BITM_TMR_CTL_EN |
AnnaBridge | 178:79309dc6340a | 49 | #endif |
AnnaBridge | 178:79309dc6340a | 50 | |
AnnaBridge | 178:79309dc6340a | 51 | typedef uint32_t timestamp_t; |
AnnaBridge | 178:79309dc6340a | 52 | |
AnnaBridge | 178:79309dc6340a | 53 | // defined in mbed_us_ticker_api.c which calls the ticker_irq_handler() routine |
AnnaBridge | 178:79309dc6340a | 54 | // defined in mbed_ticker_api.c |
AnnaBridge | 178:79309dc6340a | 55 | void us_ticker_irq_handler(void); |
AnnaBridge | 178:79309dc6340a | 56 | |
AnnaBridge | 178:79309dc6340a | 57 | static int us_ticker_inited = 0; |
AnnaBridge | 178:79309dc6340a | 58 | |
Anna Bridge |
186:707f6e361f3e | 59 | static ADI_TMR_CONFIG tmrConfig; |
AnnaBridge | 178:79309dc6340a | 60 | |
AnnaBridge | 178:79309dc6340a | 61 | static volatile uint32_t Upper_count = 0, largecnt = 0; |
AnnaBridge | 178:79309dc6340a | 62 | |
AnnaBridge | 178:79309dc6340a | 63 | static ADI_TMR_TypeDef * adi_tmr_registers[ADI_TMR_DEVICE_NUM] = {pADI_TMR0, pADI_TMR1, pADI_TMR2}; |
AnnaBridge | 178:79309dc6340a | 64 | |
AnnaBridge | 178:79309dc6340a | 65 | #if defined(__ADUCM302x__) |
AnnaBridge | 178:79309dc6340a | 66 | static const IRQn_Type adi_tmr_interrupt[ADI_TMR_DEVICE_NUM] = {TMR0_EVT_IRQn, TMR1_EVT_IRQn, TMR2_EVT_IRQn}; |
AnnaBridge | 178:79309dc6340a | 67 | #elif defined(__ADUCM4x50__) |
AnnaBridge | 178:79309dc6340a | 68 | static const IRQn_Type adi_tmr_interrupt[ADI_TMR_DEVICE_NUM] = {TMR0_EVT_IRQn, TMR1_EVT_IRQn, TMR2_EVT_IRQn, TMR_RGB_EVT_IRQn}; |
AnnaBridge | 178:79309dc6340a | 69 | #else |
AnnaBridge | 178:79309dc6340a | 70 | #error TMR is not ported for this processor |
AnnaBridge | 178:79309dc6340a | 71 | #endif |
AnnaBridge | 178:79309dc6340a | 72 | |
AnnaBridge | 178:79309dc6340a | 73 | |
AnnaBridge | 178:79309dc6340a | 74 | /*---------------------------------------------------------------------------* |
AnnaBridge | 178:79309dc6340a | 75 | Local functions |
AnnaBridge | 178:79309dc6340a | 76 | *---------------------------------------------------------------------------*/ |
AnnaBridge | 178:79309dc6340a | 77 | static void GP1CallbackFunction(void *pCBParam, uint32_t Event, void * pArg) |
AnnaBridge | 178:79309dc6340a | 78 | { |
AnnaBridge | 178:79309dc6340a | 79 | Upper_count++; |
AnnaBridge | 178:79309dc6340a | 80 | } |
AnnaBridge | 178:79309dc6340a | 81 | |
AnnaBridge | 178:79309dc6340a | 82 | |
AnnaBridge | 178:79309dc6340a | 83 | static uint32_t get_current_time(void) |
AnnaBridge | 178:79309dc6340a | 84 | { |
AnnaBridge | 178:79309dc6340a | 85 | uint16_t tmrcnt0, tmrcnt1; |
AnnaBridge | 178:79309dc6340a | 86 | uint32_t totaltmr0, totaltmr1; |
AnnaBridge | 178:79309dc6340a | 87 | uint32_t uc1, tmrpend0, tmrpend1; |
AnnaBridge | 178:79309dc6340a | 88 | |
AnnaBridge | 178:79309dc6340a | 89 | do { |
AnnaBridge | 178:79309dc6340a | 90 | volatile uint32_t *ucptr = &Upper_count; |
AnnaBridge | 178:79309dc6340a | 91 | |
AnnaBridge | 178:79309dc6340a | 92 | /* |
AnnaBridge | 178:79309dc6340a | 93 | * Carefully coded to prevent race conditions. Do not make changes unless you understand all the |
AnnaBridge | 178:79309dc6340a | 94 | * implications. |
AnnaBridge | 178:79309dc6340a | 95 | * |
AnnaBridge | 178:79309dc6340a | 96 | * Note this function can be called with interrupts globally disabled or enabled. It has been coded to work in both cases. |
AnnaBridge | 178:79309dc6340a | 97 | * |
AnnaBridge | 178:79309dc6340a | 98 | * TMR0 and TMR1 both run from the same synchronous clock. TMR0 runs at 26MHz and TMR1 runs at 26/256MHz. |
AnnaBridge | 178:79309dc6340a | 99 | * TMR1 generates an interrupt every time it overflows its 16 bit counter. TMR0 runs faster and provides |
AnnaBridge | 178:79309dc6340a | 100 | * the lowest 8 bits of the current time count. When TMR0 and TMR1 are combined, they provide 24 bits of |
AnnaBridge | 178:79309dc6340a | 101 | * timer precision. i.e. (TMR0.CURCNT & 0xff) + (TMR1.CURCNT << 8) |
AnnaBridge | 178:79309dc6340a | 102 | * |
AnnaBridge | 178:79309dc6340a | 103 | * There are several race conditions protected against: |
AnnaBridge | 178:79309dc6340a | 104 | * 1. TMR0 and TMR1 are both read at the same time, however, on rare occasions, one will have incremented before the other. |
AnnaBridge | 178:79309dc6340a | 105 | * Therefore we read both timer counters, and check if the middle 8 bits match, if they don't then read the counts again |
AnnaBridge | 178:79309dc6340a | 106 | * until they do. This ensures that one or the other counters are stable with respect to each other. |
AnnaBridge | 178:79309dc6340a | 107 | * |
AnnaBridge | 178:79309dc6340a | 108 | * 2. TMR1.CURCNT and Upper_count racing. Prevent this by disabling the TMR1 interrupt, which stops Upper_count increment interrupt (GP1CallbackFunction). |
AnnaBridge | 178:79309dc6340a | 109 | * Then check pending bit of TMR1 to see if we missed Upper_count interrupt, and add it manually later. |
AnnaBridge | 178:79309dc6340a | 110 | * |
AnnaBridge | 178:79309dc6340a | 111 | * 3. Race between the TMR1 pend, and the TMR1.CURCNT read. Even with TMR1 interrupt disabled, the pend bit |
AnnaBridge | 178:79309dc6340a | 112 | * may be set while TMR1.CURCNT is being read. We don't know if the pend bit matches the TMR1 state. |
AnnaBridge | 178:79309dc6340a | 113 | * To prevent this, the pending bit is read twice, and we see if it matches; if it doesn't, loop around again. |
AnnaBridge | 178:79309dc6340a | 114 | * |
AnnaBridge | 178:79309dc6340a | 115 | * Note the TMR1 interrupt is enabled on each iteration of the loop to flush out any pending TMR1 interrupt, |
AnnaBridge | 178:79309dc6340a | 116 | * thereby clearing any TMR1 pend's. This have no effect if this routine is called with interrupts globally disabled. |
AnnaBridge | 178:79309dc6340a | 117 | */ |
AnnaBridge | 178:79309dc6340a | 118 | |
AnnaBridge | 178:79309dc6340a | 119 | NVIC_DisableIRQ(adi_tmr_interrupt[ADI_TMR_DEVICE_GP1]); // Prevent Upper_count increment |
AnnaBridge | 178:79309dc6340a | 120 | tmrpend0 = NVIC_GetPendingIRQ(adi_tmr_interrupt[ADI_TMR_DEVICE_GP1]); |
AnnaBridge | 178:79309dc6340a | 121 | // Check if there is a pending interrupt for timer 1 |
AnnaBridge | 178:79309dc6340a | 122 | |
AnnaBridge | 178:79309dc6340a | 123 | __DMB(); // memory barrier: read GP0 before GP1 |
AnnaBridge | 178:79309dc6340a | 124 | |
AnnaBridge | 178:79309dc6340a | 125 | tmrcnt0 = adi_tmr_registers[ADI_TMR_DEVICE_GP0]->CURCNT; // to minimize skew, read both timers manually |
AnnaBridge | 178:79309dc6340a | 126 | |
AnnaBridge | 178:79309dc6340a | 127 | __DMB(); // memory barrier: read GP0 before GP1 |
AnnaBridge | 178:79309dc6340a | 128 | |
AnnaBridge | 178:79309dc6340a | 129 | tmrcnt1 = adi_tmr_registers[ADI_TMR_DEVICE_GP1]->CURCNT; // read both timers manually |
AnnaBridge | 178:79309dc6340a | 130 | |
AnnaBridge | 178:79309dc6340a | 131 | totaltmr0 = tmrcnt0; // expand to u32 bits |
AnnaBridge | 178:79309dc6340a | 132 | totaltmr1 = tmrcnt1; // expand to u32 bits |
AnnaBridge | 178:79309dc6340a | 133 | |
AnnaBridge | 178:79309dc6340a | 134 | tmrcnt0 &= 0xff00u; |
AnnaBridge | 178:79309dc6340a | 135 | tmrcnt1 <<= 8; |
AnnaBridge | 178:79309dc6340a | 136 | |
AnnaBridge | 178:79309dc6340a | 137 | __DMB(); |
AnnaBridge | 178:79309dc6340a | 138 | |
AnnaBridge | 178:79309dc6340a | 139 | uc1 = *ucptr; // Read Upper_count |
AnnaBridge | 178:79309dc6340a | 140 | |
AnnaBridge | 178:79309dc6340a | 141 | tmrpend1 = NVIC_GetPendingIRQ(adi_tmr_interrupt[ADI_TMR_DEVICE_GP1]); |
AnnaBridge | 178:79309dc6340a | 142 | // Check for a pending interrupt again. Only leave loop if they match |
AnnaBridge | 178:79309dc6340a | 143 | |
AnnaBridge | 178:79309dc6340a | 144 | NVIC_EnableIRQ(adi_tmr_interrupt[ADI_TMR_DEVICE_GP1]); // enable interrupt on every loop to allow TMR1 interrupt to run |
AnnaBridge | 178:79309dc6340a | 145 | } while ((tmrcnt0 != tmrcnt1) || (tmrpend0 != tmrpend1)); |
AnnaBridge | 178:79309dc6340a | 146 | |
AnnaBridge | 178:79309dc6340a | 147 | totaltmr1 <<= 8; // Timer1 runs 256x slower |
AnnaBridge | 178:79309dc6340a | 148 | totaltmr1 += totaltmr0 & 0xffu; // Use last 8 bits of Timer0 as it runs faster |
AnnaBridge | 178:79309dc6340a | 149 | // totaltmr1 now contain 24 bits of significance |
AnnaBridge | 178:79309dc6340a | 150 | |
AnnaBridge | 178:79309dc6340a | 151 | if (tmrpend0) { // If an interrupt is pending, then increment local copy of upper count |
AnnaBridge | 178:79309dc6340a | 152 | uc1++; |
AnnaBridge | 178:79309dc6340a | 153 | } |
AnnaBridge | 178:79309dc6340a | 154 | |
AnnaBridge | 178:79309dc6340a | 155 | uint64_t Uc = totaltmr1; // expand out to 64 bits unsigned |
AnnaBridge | 178:79309dc6340a | 156 | Uc += ((uint64_t) uc1) << 24; // Add on the upper count to get the full precision count |
AnnaBridge | 178:79309dc6340a | 157 | |
AnnaBridge | 178:79309dc6340a | 158 | // Divide Uc by 26 (26MHz converted to 1MHz) todo scale for other clock freqs |
AnnaBridge | 178:79309dc6340a | 159 | |
AnnaBridge | 178:79309dc6340a | 160 | Uc *= 1290555u; // Divide total(1/26) << 25 |
AnnaBridge | 178:79309dc6340a | 161 | Uc >>= 25; // shift back. Fixed point avoid use of floating point divide. |
AnnaBridge | 178:79309dc6340a | 162 | // Compiler does this inline using shifts and adds. |
AnnaBridge | 178:79309dc6340a | 163 | |
AnnaBridge | 178:79309dc6340a | 164 | return Uc; |
AnnaBridge | 178:79309dc6340a | 165 | } |
AnnaBridge | 178:79309dc6340a | 166 | |
AnnaBridge | 178:79309dc6340a | 167 | |
AnnaBridge | 178:79309dc6340a | 168 | static void calc_event_counts(uint32_t timestamp) |
AnnaBridge | 178:79309dc6340a | 169 | { |
AnnaBridge | 178:79309dc6340a | 170 | uint32_t calc_time, blocks, offset; |
AnnaBridge | 178:79309dc6340a | 171 | uint64_t aa; |
AnnaBridge | 178:79309dc6340a | 172 | |
AnnaBridge | 178:79309dc6340a | 173 | calc_time = get_current_time(); |
AnnaBridge | 178:79309dc6340a | 174 | offset = timestamp - calc_time; // offset in useconds |
AnnaBridge | 178:79309dc6340a | 175 | |
AnnaBridge | 178:79309dc6340a | 176 | if (offset > 0xf0000000u) // if offset is a really big number, assume that timer has already expired (i.e. negative) |
AnnaBridge | 178:79309dc6340a | 177 | offset = 0u; |
AnnaBridge | 178:79309dc6340a | 178 | |
AnnaBridge | 178:79309dc6340a | 179 | if (offset > 10u) { // it takes 10us to user timer routine after interrupt. Offset timer to account for that. |
AnnaBridge | 178:79309dc6340a | 180 | offset -= 10u; |
AnnaBridge | 178:79309dc6340a | 181 | } else |
AnnaBridge | 178:79309dc6340a | 182 | offset = 0u; |
AnnaBridge | 178:79309dc6340a | 183 | |
AnnaBridge | 178:79309dc6340a | 184 | aa = (uint64_t) offset; |
AnnaBridge | 178:79309dc6340a | 185 | aa *= 26u; // convert from 1MHz to 26MHz clock. todo scale for other clock freqs |
AnnaBridge | 178:79309dc6340a | 186 | |
AnnaBridge | 178:79309dc6340a | 187 | blocks = aa >> 7; |
AnnaBridge | 178:79309dc6340a | 188 | blocks++; // round |
AnnaBridge | 178:79309dc6340a | 189 | |
AnnaBridge | 178:79309dc6340a | 190 | largecnt = blocks>>1; // communicate to event_timer() routine |
AnnaBridge | 178:79309dc6340a | 191 | } |
AnnaBridge | 178:79309dc6340a | 192 | |
AnnaBridge | 178:79309dc6340a | 193 | static void event_timer() |
AnnaBridge | 178:79309dc6340a | 194 | { |
AnnaBridge | 178:79309dc6340a | 195 | if (largecnt) { |
AnnaBridge | 178:79309dc6340a | 196 | uint32_t cnt = largecnt; |
AnnaBridge | 178:79309dc6340a | 197 | |
AnnaBridge | 178:79309dc6340a | 198 | if (cnt > 65535u) { |
AnnaBridge | 178:79309dc6340a | 199 | cnt = 0u; |
AnnaBridge | 178:79309dc6340a | 200 | } else { |
AnnaBridge | 178:79309dc6340a | 201 | cnt = 65536u - cnt; |
AnnaBridge | 178:79309dc6340a | 202 | } |
AnnaBridge | 178:79309dc6340a | 203 | |
Anna Bridge |
186:707f6e361f3e | 204 | tmrConfig.nLoad = cnt; |
Anna Bridge |
186:707f6e361f3e | 205 | tmrConfig.nAsyncLoad = cnt; |
Anna Bridge |
186:707f6e361f3e | 206 | adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmrConfig); |
AnnaBridge | 178:79309dc6340a | 207 | adi_tmr_Enable(ADI_TMR_DEVICE_GP2, true); |
AnnaBridge | 178:79309dc6340a | 208 | } else { |
Anna Bridge |
186:707f6e361f3e | 209 | tmrConfig.nLoad = 65535u; |
Anna Bridge |
186:707f6e361f3e | 210 | tmrConfig.nAsyncLoad = 65535u; |
Anna Bridge |
186:707f6e361f3e | 211 | adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmrConfig); |
AnnaBridge | 184:08ed48f1de7f | 212 | adi_tmr_Enable(ADI_TMR_DEVICE_GP2, true); |
AnnaBridge | 178:79309dc6340a | 213 | } |
AnnaBridge | 178:79309dc6340a | 214 | } |
AnnaBridge | 178:79309dc6340a | 215 | |
AnnaBridge | 178:79309dc6340a | 216 | |
AnnaBridge | 178:79309dc6340a | 217 | /* |
AnnaBridge | 178:79309dc6340a | 218 | * Interrupt routine for timer 2 |
AnnaBridge | 178:79309dc6340a | 219 | * |
AnnaBridge | 178:79309dc6340a | 220 | * largecnt counts how many timer ticks should be counted to reach timer event. |
AnnaBridge | 178:79309dc6340a | 221 | * Each interrupt happens every 65536 timer ticks, unless there are less than 65536 ticks to count. |
AnnaBridge | 178:79309dc6340a | 222 | * In that case do the remaining timers ticks. |
AnnaBridge | 178:79309dc6340a | 223 | * |
AnnaBridge | 178:79309dc6340a | 224 | * largecnt is a global that is used to communicate between event_timer and the interrupt routine |
AnnaBridge | 178:79309dc6340a | 225 | * On entry, largecnt will be any value larger than 0. |
AnnaBridge | 178:79309dc6340a | 226 | */ |
AnnaBridge | 178:79309dc6340a | 227 | static void GP2CallbackFunction(void *pCBParam, uint32_t Event, void * pArg) |
AnnaBridge | 178:79309dc6340a | 228 | { |
AnnaBridge | 178:79309dc6340a | 229 | if (largecnt >= 65536u) { |
AnnaBridge | 178:79309dc6340a | 230 | largecnt -= 65536u; |
AnnaBridge | 178:79309dc6340a | 231 | } else { |
AnnaBridge | 178:79309dc6340a | 232 | largecnt = 0; |
AnnaBridge | 178:79309dc6340a | 233 | } |
AnnaBridge | 178:79309dc6340a | 234 | |
AnnaBridge | 178:79309dc6340a | 235 | if (largecnt < 65536u) { |
AnnaBridge | 178:79309dc6340a | 236 | adi_tmr_Enable(ADI_TMR_DEVICE_GP2, false); |
AnnaBridge | 184:08ed48f1de7f | 237 | if (largecnt) { |
AnnaBridge | 184:08ed48f1de7f | 238 | event_timer(); |
AnnaBridge | 184:08ed48f1de7f | 239 | } else { |
AnnaBridge | 184:08ed48f1de7f | 240 | us_ticker_irq_handler(); |
AnnaBridge | 184:08ed48f1de7f | 241 | } |
AnnaBridge | 178:79309dc6340a | 242 | } |
AnnaBridge | 178:79309dc6340a | 243 | } |
AnnaBridge | 178:79309dc6340a | 244 | |
AnnaBridge | 178:79309dc6340a | 245 | |
AnnaBridge | 178:79309dc6340a | 246 | /*---------------------------------------------------------------------------* |
AnnaBridge | 178:79309dc6340a | 247 | us_ticker HAL APIs |
AnnaBridge | 178:79309dc6340a | 248 | *---------------------------------------------------------------------------*/ |
AnnaBridge | 178:79309dc6340a | 249 | void us_ticker_init(void) |
AnnaBridge | 178:79309dc6340a | 250 | { |
AnnaBridge | 178:79309dc6340a | 251 | if (us_ticker_inited) { |
Anna Bridge |
186:707f6e361f3e | 252 | // Disable ticker interrupt on reinitialization |
Anna Bridge |
186:707f6e361f3e | 253 | adi_tmr_Enable(ADI_TMR_DEVICE_GP2, false); |
AnnaBridge | 178:79309dc6340a | 254 | return; |
AnnaBridge | 178:79309dc6340a | 255 | } |
AnnaBridge | 178:79309dc6340a | 256 | |
AnnaBridge | 178:79309dc6340a | 257 | us_ticker_inited = 1; |
AnnaBridge | 178:79309dc6340a | 258 | |
AnnaBridge | 178:79309dc6340a | 259 | /*--------------------- GP TIMER INITIALIZATION --------------------------*/ |
AnnaBridge | 178:79309dc6340a | 260 | |
AnnaBridge | 178:79309dc6340a | 261 | /* Set up GP0 callback function */ |
AnnaBridge | 178:79309dc6340a | 262 | adi_tmr_Init(ADI_TMR_DEVICE_GP0, NULL, NULL, false); |
AnnaBridge | 178:79309dc6340a | 263 | |
AnnaBridge | 178:79309dc6340a | 264 | /* Set up GP1 callback function */ |
AnnaBridge | 178:79309dc6340a | 265 | adi_tmr_Init(ADI_TMR_DEVICE_GP1, GP1CallbackFunction, NULL, true); |
AnnaBridge | 178:79309dc6340a | 266 | |
AnnaBridge | 178:79309dc6340a | 267 | /* Set up GP1 callback function */ |
AnnaBridge | 178:79309dc6340a | 268 | adi_tmr_Init(ADI_TMR_DEVICE_GP2, GP2CallbackFunction, NULL, true); |
AnnaBridge | 178:79309dc6340a | 269 | |
AnnaBridge | 178:79309dc6340a | 270 | /* Configure GP0 to run at 26MHz */ |
AnnaBridge | 178:79309dc6340a | 271 | tmrConfig.bCountingUp = true; |
AnnaBridge | 178:79309dc6340a | 272 | tmrConfig.bPeriodic = true; |
AnnaBridge | 178:79309dc6340a | 273 | tmrConfig.ePrescaler = ADI_TMR_PRESCALER_1; // TMR0 at 26MHz |
AnnaBridge | 178:79309dc6340a | 274 | tmrConfig.eClockSource = ADI_TMR_CLOCK_PCLK; // TMR source is PCLK (most examples use HFOSC) |
AnnaBridge | 178:79309dc6340a | 275 | tmrConfig.nLoad = 0; |
AnnaBridge | 178:79309dc6340a | 276 | tmrConfig.nAsyncLoad = 0; |
AnnaBridge | 178:79309dc6340a | 277 | tmrConfig.bReloading = false; |
AnnaBridge | 178:79309dc6340a | 278 | tmrConfig.bSyncBypass = true; // Allow x1 prescale: requires PCLK as a clk |
AnnaBridge | 178:79309dc6340a | 279 | adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP0, &tmrConfig); |
AnnaBridge | 178:79309dc6340a | 280 | |
AnnaBridge | 178:79309dc6340a | 281 | /* Configure GP1 to have a period 256 times longer than GP0 */ |
AnnaBridge | 178:79309dc6340a | 282 | tmrConfig.nLoad = 0; |
AnnaBridge | 178:79309dc6340a | 283 | tmrConfig.nAsyncLoad = 0; |
AnnaBridge | 178:79309dc6340a | 284 | tmrConfig.ePrescaler = ADI_TMR_PRESCALER_256; // TMR1 = 26MHz/256 |
AnnaBridge | 178:79309dc6340a | 285 | adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP1, &tmrConfig); |
AnnaBridge | 178:79309dc6340a | 286 | |
AnnaBridge | 178:79309dc6340a | 287 | /* Configure GP2 for doing event counts */ |
Anna Bridge |
186:707f6e361f3e | 288 | tmrConfig.bCountingUp = true; |
Anna Bridge |
186:707f6e361f3e | 289 | tmrConfig.bPeriodic = true; |
Anna Bridge |
186:707f6e361f3e | 290 | tmrConfig.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 |
Anna Bridge |
186:707f6e361f3e | 291 | tmrConfig.eClockSource = ADI_TMR_CLOCK_PCLK; // TMR source is PCLK (most examples use HFOSC) |
Anna Bridge |
186:707f6e361f3e | 292 | tmrConfig.nLoad = 0; |
Anna Bridge |
186:707f6e361f3e | 293 | tmrConfig.nAsyncLoad = 0; |
Anna Bridge |
186:707f6e361f3e | 294 | tmrConfig.bReloading = false; |
Anna Bridge |
186:707f6e361f3e | 295 | tmrConfig.bSyncBypass = true; // Allow x1 prescale |
Anna Bridge |
186:707f6e361f3e | 296 | adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmrConfig); |
AnnaBridge | 178:79309dc6340a | 297 | |
AnnaBridge | 178:79309dc6340a | 298 | |
AnnaBridge | 178:79309dc6340a | 299 | /*------------------------- GP TIMER ENABLE ------------------------------*/ |
AnnaBridge | 178:79309dc6340a | 300 | |
AnnaBridge | 178:79309dc6340a | 301 | /* Manually enable both timers to get them started at the same time |
AnnaBridge | 178:79309dc6340a | 302 | * |
AnnaBridge | 178:79309dc6340a | 303 | */ |
AnnaBridge | 178:79309dc6340a | 304 | adi_tmr_registers[ADI_TMR_DEVICE_GP0]->CTL |= (uint16_t) BITM_TMR_RGB_CTL_EN; |
AnnaBridge | 178:79309dc6340a | 305 | adi_tmr_registers[ADI_TMR_DEVICE_GP1]->CTL |= (uint16_t) BITM_TMR_RGB_CTL_EN; |
AnnaBridge | 178:79309dc6340a | 306 | } |
AnnaBridge | 178:79309dc6340a | 307 | |
AnnaBridge | 178:79309dc6340a | 308 | uint32_t us_ticker_read() |
AnnaBridge | 178:79309dc6340a | 309 | { |
AnnaBridge | 178:79309dc6340a | 310 | uint32_t curr_time; |
AnnaBridge | 178:79309dc6340a | 311 | |
AnnaBridge | 178:79309dc6340a | 312 | if (!us_ticker_inited) { |
AnnaBridge | 178:79309dc6340a | 313 | us_ticker_init(); |
AnnaBridge | 178:79309dc6340a | 314 | } |
AnnaBridge | 178:79309dc6340a | 315 | |
AnnaBridge | 178:79309dc6340a | 316 | curr_time = get_current_time(); |
AnnaBridge | 178:79309dc6340a | 317 | |
AnnaBridge | 178:79309dc6340a | 318 | return curr_time; |
AnnaBridge | 178:79309dc6340a | 319 | } |
AnnaBridge | 178:79309dc6340a | 320 | |
AnnaBridge | 178:79309dc6340a | 321 | void us_ticker_disable_interrupt(void) |
AnnaBridge | 178:79309dc6340a | 322 | { |
AnnaBridge | 178:79309dc6340a | 323 | adi_tmr_Enable(ADI_TMR_DEVICE_GP2, false); |
AnnaBridge | 178:79309dc6340a | 324 | } |
AnnaBridge | 178:79309dc6340a | 325 | |
AnnaBridge | 178:79309dc6340a | 326 | void us_ticker_clear_interrupt(void) |
AnnaBridge | 178:79309dc6340a | 327 | { |
AnnaBridge | 178:79309dc6340a | 328 | NVIC_ClearPendingIRQ(TMR2_EVT_IRQn); |
AnnaBridge | 178:79309dc6340a | 329 | } |
AnnaBridge | 178:79309dc6340a | 330 | |
AnnaBridge | 178:79309dc6340a | 331 | void us_ticker_set_interrupt(timestamp_t timestamp) |
AnnaBridge | 178:79309dc6340a | 332 | { |
Anna Bridge |
186:707f6e361f3e | 333 | // if timestamp is already past, do not set interrupt |
Anna Bridge |
186:707f6e361f3e | 334 | if ((timestamp + 10) <= us_ticker_read()) return; |
AnnaBridge | 178:79309dc6340a | 335 | /* timestamp is when interrupt should fire. |
AnnaBridge | 178:79309dc6340a | 336 | * |
AnnaBridge | 178:79309dc6340a | 337 | * This MUST not be called if another timer event is currently enabled. |
AnnaBridge | 178:79309dc6340a | 338 | * |
AnnaBridge | 178:79309dc6340a | 339 | */ |
AnnaBridge | 178:79309dc6340a | 340 | calc_event_counts(timestamp); // use timestamp to calculate largecnt to control number of timer interrupts |
Anna Bridge |
186:707f6e361f3e | 341 | tmrConfig.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 |
AnnaBridge | 178:79309dc6340a | 342 | event_timer(); // uses largecnt to initiate timer interrupts |
AnnaBridge | 178:79309dc6340a | 343 | } |
AnnaBridge | 178:79309dc6340a | 344 | |
AnnaBridge | 178:79309dc6340a | 345 | /** Set pending interrupt that should be fired right away. |
AnnaBridge | 178:79309dc6340a | 346 | * |
AnnaBridge | 178:79309dc6340a | 347 | * The ticker should be initialized prior calling this function. |
AnnaBridge | 178:79309dc6340a | 348 | * |
AnnaBridge | 178:79309dc6340a | 349 | * This MUST not be called if another timer event is currently enabled. |
AnnaBridge | 178:79309dc6340a | 350 | */ |
AnnaBridge | 178:79309dc6340a | 351 | void us_ticker_fire_interrupt(void) |
AnnaBridge | 178:79309dc6340a | 352 | { |
AnnaBridge | 184:08ed48f1de7f | 353 | largecnt = 1; // set a minimal interval so interrupt fire immediately |
Anna Bridge |
186:707f6e361f3e | 354 | tmrConfig.ePrescaler = ADI_TMR_PRESCALER_1; // TMR2 at 26MHz/1 |
AnnaBridge | 184:08ed48f1de7f | 355 | event_timer(); // enable the timer and interrupt |
AnnaBridge | 178:79309dc6340a | 356 | } |
AnnaBridge | 178:79309dc6340a | 357 | |
AnnaBridge | 188:bcfe06ba3d64 | 358 | void us_ticker_free(void) |
AnnaBridge | 188:bcfe06ba3d64 | 359 | { |
AnnaBridge | 188:bcfe06ba3d64 | 360 | adi_tmr_Enable(ADI_TMR_DEVICE_GP2, false); |
AnnaBridge | 188:bcfe06ba3d64 | 361 | } |
AnnaBridge | 178:79309dc6340a | 362 | |
AnnaBridge | 178:79309dc6340a | 363 | /* |
AnnaBridge | 178:79309dc6340a | 364 | ** EOF |
AnnaBridge | 178:79309dc6340a | 365 | */ |