f

Committer:
TMRL123
Date:
Thu Apr 18 14:02:42 2019 +0000
Revision:
119:eac0140d1d3b
Parent:
86:49d19df5bbce
Child:
87:5f31c157ed15
t

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Helmut Tschemernjak 77:7f227a4dffe6 1 /*
Helmut Tschemernjak 77:7f227a4dffe6 2 * The file is Licensed under the Apache License, Version 2.0
Helmut Tschemernjak 77:7f227a4dffe6 3 * (c) 2017 Helmut Tschemernjak
Helmut Tschemernjak 77:7f227a4dffe6 4 * 30826 Garbsen (Hannover) Germany
Helmut Tschemernjak 77:7f227a4dffe6 5 */
Helmut Tschemernjak 77:7f227a4dffe6 6
Helmut Tschemernjak 77:7f227a4dffe6 7 #ifdef ARDUINO
Helmut Tschemernjak 77:7f227a4dffe6 8
Helmut Tschemernjak 77:7f227a4dffe6 9 using namespace std;
Helmut Tschemernjak 77:7f227a4dffe6 10
Helmut Tschemernjak 77:7f227a4dffe6 11 #include "arduino-mbed.h"
Helmut Tschemernjak 77:7f227a4dffe6 12 #include "arduino-util.h"
Helmut Tschemernjak 77:7f227a4dffe6 13
Helmut Tschemernjak 77:7f227a4dffe6 14
Helmut Tschemernjak 77:7f227a4dffe6 15
Helmut Tschemernjak 77:7f227a4dffe6 16 #if defined(__SAMD21G18A__) || defined(__SAMD21J18A__)
Helmut Tschemernjak 77:7f227a4dffe6 17 /*
Helmut Tschemernjak 77:7f227a4dffe6 18 * __SAMD21J18A__ is the SamD21 Explained Board
Helmut Tschemernjak 77:7f227a4dffe6 19 * __SAMD21G18A__ is Genuino Zero-Board (compatible with the LoRa board)
Helmut Tschemernjak 77:7f227a4dffe6 20 */
Helmut Tschemernjak 77:7f227a4dffe6 21
Helmut Tschemernjak 78:9d2cc07d9525 22 int
Helmut Tschemernjak 78:9d2cc07d9525 23 CPUID(uint8_t *buf, int maxSize, uint32_t xorval)
Helmut Tschemernjak 78:9d2cc07d9525 24 {
Helmut Tschemernjak 78:9d2cc07d9525 25 int f1 = 0x55d5f559; // D21 128-bit UUID, first 32 bit.
Helmut Tschemernjak 78:9d2cc07d9525 26 int f2 = 0x55d5f515; // D21 128-bit UUID, next 96 bit.
Helmut Tschemernjak 78:9d2cc07d9525 27
Helmut Tschemernjak 78:9d2cc07d9525 28 if (maxSize >= 16 ) {
Helmut Tschemernjak 78:9d2cc07d9525 29 int cnt = 0;
Helmut Tschemernjak 78:9d2cc07d9525 30 int fa = f1 ^ xorval;
Helmut Tschemernjak 78:9d2cc07d9525 31 uint32_t *first = (uint32_t *)fa;
Helmut Tschemernjak 78:9d2cc07d9525 32 uint8_t *dst = (uint8_t *)first;
Helmut Tschemernjak 84:3428e25c7157 33 for (int i = 0; i < (int)sizeof(uint32_t); i++)
Helmut Tschemernjak 78:9d2cc07d9525 34 *buf++ = *dst++;
Helmut Tschemernjak 78:9d2cc07d9525 35 cnt += 4;
Helmut Tschemernjak 78:9d2cc07d9525 36 int fb = f2 ^ xorval;
Helmut Tschemernjak 78:9d2cc07d9525 37 uint32_t *next = (uint32_t *)fb;
Helmut Tschemernjak 78:9d2cc07d9525 38 dst = (uint8_t *)next;
Helmut Tschemernjak 84:3428e25c7157 39 for (int i = 0; i < (int)sizeof(uint32_t)*3; i++)
Helmut Tschemernjak 78:9d2cc07d9525 40 *buf++ = *dst++;
Helmut Tschemernjak 78:9d2cc07d9525 41 cnt += 12;
Helmut Tschemernjak 78:9d2cc07d9525 42 return cnt;
Helmut Tschemernjak 78:9d2cc07d9525 43 }
Helmut Tschemernjak 78:9d2cc07d9525 44
Helmut Tschemernjak 78:9d2cc07d9525 45 return 0;
Helmut Tschemernjak 78:9d2cc07d9525 46 }
Helmut Tschemernjak 78:9d2cc07d9525 47
Helmut Tschemernjak 77:7f227a4dffe6 48 /*
Helmut Tschemernjak 77:7f227a4dffe6 49 * see tcc.h is automatically included from:
Helmut Tschemernjak 77:7f227a4dffe6 50 * Arduino15/packages/arduino/tools/CMSIS-Atmel/1.1.0/CMSIS/
Helmut Tschemernjak 77:7f227a4dffe6 51 * Device/ATMEL/samd21/include/component/tcc.h
Helmut Tschemernjak 77:7f227a4dffe6 52 * See also tcc.c (ASF/mbed, e.g. Tcc_get_count_value)
Helmut Tschemernjak 77:7f227a4dffe6 53 */
Helmut Tschemernjak 77:7f227a4dffe6 54 static void initTimer(Tcc *t);
Helmut Tschemernjak 77:7f227a4dffe6 55 static uint32_t getTimerCount(Tcc *t);
Helmut Tschemernjak 77:7f227a4dffe6 56
Helmut Tschemernjak 77:7f227a4dffe6 57 /*
Helmut Tschemernjak 77:7f227a4dffe6 58 * The Atmel D21 has three TCC timer, other models have more.
Helmut Tschemernjak 77:7f227a4dffe6 59 */
Helmut Tschemernjak 77:7f227a4dffe6 60 const struct TCC_config {
Helmut Tschemernjak 77:7f227a4dffe6 61 Tcc *tcc_ptr;
Helmut Tschemernjak 77:7f227a4dffe6 62 IRQn_Type tcc_irq;
Helmut Tschemernjak 77:7f227a4dffe6 63 uint8_t nbits;
Helmut Tschemernjak 77:7f227a4dffe6 64 } TCC_data[] {
Helmut Tschemernjak 77:7f227a4dffe6 65 { TCC0, TCC0_IRQn, 24 },
Helmut Tschemernjak 77:7f227a4dffe6 66 { TCC1, TCC1_IRQn, 24 },
Helmut Tschemernjak 77:7f227a4dffe6 67 { TCC2, TCC2_IRQn, 16 },
Helmut Tschemernjak 77:7f227a4dffe6 68 { NULL, (IRQn_Type)NULL, 0 }
Helmut Tschemernjak 77:7f227a4dffe6 69 };
Helmut Tschemernjak 77:7f227a4dffe6 70
Helmut Tschemernjak 77:7f227a4dffe6 71 /*
Helmut Tschemernjak 77:7f227a4dffe6 72 * We preferably use the TCC timers because it supports 24-bit counters
Helmut Tschemernjak 77:7f227a4dffe6 73 * versus TC Timer which supports only 8 or 16 bit counters only.
Helmut Tschemernjak 77:7f227a4dffe6 74 * TCC0/1/2 timer work on the D21 using Arduino Zero.
Helmut Tschemernjak 77:7f227a4dffe6 75 */
Helmut Tschemernjak 77:7f227a4dffe6 76 #define USE_TCC_TIMEOUT 0 // 0=TCC0, 1=TTC1, 2=TTC2 (see TCC_data)
Helmut Tschemernjak 77:7f227a4dffe6 77 #define USE_TCC_TICKER 1
Helmut Tschemernjak 77:7f227a4dffe6 78
Helmut Tschemernjak 77:7f227a4dffe6 79
Helmut Tschemernjak 77:7f227a4dffe6 80 /*
Helmut Tschemernjak 77:7f227a4dffe6 81 * every 21333 ns equals one tick (1/(48000000/1024)) // prescaler 1024, 48 MHz
Helmut Tschemernjak 77:7f227a4dffe6 82 * every 61035 ns equals one tick (1/(32768/2)) // prescaler 2, 32 kHz
Helmut Tschemernjak 77:7f227a4dffe6 83 * COUNT*DIVIDER*SECS until interrupt
Helmut Tschemernjak 77:7f227a4dffe6 84 * CPU 48 MHz = (65536*1024)/1.398636s
Helmut Tschemernjak 77:7f227a4dffe6 85 * RTC 32 kHz = (65536*2)/4.0s
Helmut Tschemernjak 77:7f227a4dffe6 86 */
Helmut Tschemernjak 77:7f227a4dffe6 87 #define NS_PER_CLOCK_CPU 21333 // ns secs per clock
Helmut Tschemernjak 77:7f227a4dffe6 88 #define NS_PER_CLOCK_RTC 61035 // ns secs per clock
Helmut Tschemernjak 77:7f227a4dffe6 89
Helmut Tschemernjak 77:7f227a4dffe6 90 #define NS_PER_CLOCK NS_PER_CLOCK_RTC
Helmut Tschemernjak 77:7f227a4dffe6 91
Helmut Tschemernjak 77:7f227a4dffe6 92 /* ----------------- TICKER TIMER CODE ----------------------*/
Helmut Tschemernjak 77:7f227a4dffe6 93
Helmut Tschemernjak 77:7f227a4dffe6 94 /*
Helmut Tschemernjak 77:7f227a4dffe6 95 * The global ns_counter contains the time in ns from the last time
Helmut Tschemernjak 77:7f227a4dffe6 96 * the counter has been wrapped. It cannot be used directly because the
Helmut Tschemernjak 77:7f227a4dffe6 97 * current counter has to be added fore using it. Use instead
Helmut Tschemernjak 77:7f227a4dffe6 98 * ns_getTicker(), us_ ns_getTicker(), ms_getTicker()
Helmut Tschemernjak 77:7f227a4dffe6 99 */
Helmut Tschemernjak 77:7f227a4dffe6 100
Helmut Tschemernjak 77:7f227a4dffe6 101 uint64_t ticker_ns;
Helmut Tschemernjak 77:7f227a4dffe6 102 static bool initTickerDone = false;
Helmut Tschemernjak 77:7f227a4dffe6 103
Helmut Tschemernjak 77:7f227a4dffe6 104 uint64_t ns_getTicker(void)
Helmut Tschemernjak 77:7f227a4dffe6 105 {
Helmut Tschemernjak 77:7f227a4dffe6 106 Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr;
Helmut Tschemernjak 77:7f227a4dffe6 107 if (!initTickerDone) {
Helmut Tschemernjak 77:7f227a4dffe6 108 initTimer(t);
Helmut Tschemernjak 77:7f227a4dffe6 109 initTickerDone = true;
Helmut Tschemernjak 77:7f227a4dffe6 110
Helmut Tschemernjak 77:7f227a4dffe6 111 // set counter top to max 16 bit for testing
Helmut Tschemernjak 77:7f227a4dffe6 112 // t->PER.bit.PER = 0xffff;
Helmut Tschemernjak 77:7f227a4dffe6 113 // while (t->SYNCBUSY.bit.PER == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 114
Helmut Tschemernjak 77:7f227a4dffe6 115 t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC
Helmut Tschemernjak 77:7f227a4dffe6 116 while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 117 }
Helmut Tschemernjak 77:7f227a4dffe6 118
Helmut Tschemernjak 77:7f227a4dffe6 119 /*
Helmut Tschemernjak 77:7f227a4dffe6 120 * if we are called from the interrupt level, the counter contains
Helmut Tschemernjak 77:7f227a4dffe6 121 * somehow wrong data, therfore we needs to read it twice.
Helmut Tschemernjak 77:7f227a4dffe6 122 * Another option was to add a little wait (loop 500x)
Helmut Tschemernjak 77:7f227a4dffe6 123 * in the TCC_TIMEOUT interrupt handler.
Helmut Tschemernjak 77:7f227a4dffe6 124 */
Helmut Tschemernjak 77:7f227a4dffe6 125 if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) // check if we are in the interrupt
Helmut Tschemernjak 77:7f227a4dffe6 126 getTimerCount(t);
Helmut Tschemernjak 77:7f227a4dffe6 127
Helmut Tschemernjak 77:7f227a4dffe6 128 uint64_t counter_us = (uint64_t)NS_PER_CLOCK * (uint64_t)getTimerCount(t);
Helmut Tschemernjak 77:7f227a4dffe6 129 uint64_t ns = ticker_ns + counter_us;
Helmut Tschemernjak 77:7f227a4dffe6 130
Helmut Tschemernjak 77:7f227a4dffe6 131 return ns;
Helmut Tschemernjak 77:7f227a4dffe6 132 }
Helmut Tschemernjak 77:7f227a4dffe6 133
Helmut Tschemernjak 77:7f227a4dffe6 134 #if USE_TCC_TICKER == 0
Helmut Tschemernjak 77:7f227a4dffe6 135 void TCC0_Handler()
Helmut Tschemernjak 77:7f227a4dffe6 136 #elif USE_TCC_TICKER == 1
Helmut Tschemernjak 77:7f227a4dffe6 137 void TCC1_Handler()
Helmut Tschemernjak 77:7f227a4dffe6 138 #elif USE_TCC_TICKER == 2
Helmut Tschemernjak 77:7f227a4dffe6 139 void TCC2_Handler()
Helmut Tschemernjak 77:7f227a4dffe6 140 #endif
Helmut Tschemernjak 77:7f227a4dffe6 141 {
Helmut Tschemernjak 77:7f227a4dffe6 142 Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr;
Helmut Tschemernjak 77:7f227a4dffe6 143 /*
Helmut Tschemernjak 77:7f227a4dffe6 144 * Overflow means the timer top exeeded
Helmut Tschemernjak 77:7f227a4dffe6 145 */
Helmut Tschemernjak 77:7f227a4dffe6 146 if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt
Helmut Tschemernjak 77:7f227a4dffe6 147 t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag
Helmut Tschemernjak 77:7f227a4dffe6 148 // ser->println("T_OVF");
Helmut Tschemernjak 77:7f227a4dffe6 149
Helmut Tschemernjak 77:7f227a4dffe6 150 /*
Helmut Tschemernjak 77:7f227a4dffe6 151 * reading the count once is needed, otherwise
Helmut Tschemernjak 77:7f227a4dffe6 152 * it will not wrap correct.
Helmut Tschemernjak 77:7f227a4dffe6 153 */
Helmut Tschemernjak 77:7f227a4dffe6 154 getTimerCount(t);
Helmut Tschemernjak 77:7f227a4dffe6 155
Helmut Tschemernjak 77:7f227a4dffe6 156 int bits = TCC_data[USE_TCC_TICKER].nbits;
Helmut Tschemernjak 77:7f227a4dffe6 157 int maxCounts = (uint32_t)(1<<bits);
Helmut Tschemernjak 77:7f227a4dffe6 158
Helmut Tschemernjak 77:7f227a4dffe6 159 ticker_ns += (uint64_t)NS_PER_CLOCK * (uint64_t)maxCounts;
Helmut Tschemernjak 77:7f227a4dffe6 160 }
Helmut Tschemernjak 77:7f227a4dffe6 161 if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt
Helmut Tschemernjak 77:7f227a4dffe6 162 t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag
Helmut Tschemernjak 77:7f227a4dffe6 163 // ser->println("T_MC0");
Helmut Tschemernjak 77:7f227a4dffe6 164 }
Helmut Tschemernjak 77:7f227a4dffe6 165 }
Helmut Tschemernjak 77:7f227a4dffe6 166
Helmut Tschemernjak 77:7f227a4dffe6 167 /* ----------------- SUPPORT CODE FOR TCC TIMERS----------------------*/
Helmut Tschemernjak 77:7f227a4dffe6 168
Helmut Tschemernjak 77:7f227a4dffe6 169 static bool initTimerDone = false;
Helmut Tschemernjak 77:7f227a4dffe6 170
Helmut Tschemernjak 77:7f227a4dffe6 171 static void initTimer(Tcc *t)
Helmut Tschemernjak 77:7f227a4dffe6 172 {
Helmut Tschemernjak 77:7f227a4dffe6 173
Helmut Tschemernjak 77:7f227a4dffe6 174 /*
Helmut Tschemernjak 77:7f227a4dffe6 175 * enable clock for TCC, see gclk.h
Helmut Tschemernjak 77:7f227a4dffe6 176 * GCLK_CLKCTRL_GEN_GCLK0 for 48 Mhz CPU
Helmut Tschemernjak 77:7f227a4dffe6 177 * GCLK_CLKCTRL_GEN_GCLK1 for 32k extern crystal XOSC32K (ifdef CRYSTALLESS)
Helmut Tschemernjak 77:7f227a4dffe6 178 * GCLK_CLKCTRL_GEN_GCLK1 for 32k internal OSC32K
Helmut Tschemernjak 77:7f227a4dffe6 179 * see Arduino: arduino/hardware/samd/1.6.15/cores/arduino/startup.c
Helmut Tschemernjak 77:7f227a4dffe6 180 * Use TCC_CTRLA_PRESCALER_DIV1024 for for 48 Mhz clock
Helmut Tschemernjak 77:7f227a4dffe6 181 * Use TCC_CTRLA_PRESCALER_DIV2 for 32k clock
Helmut Tschemernjak 77:7f227a4dffe6 182 */
Helmut Tschemernjak 77:7f227a4dffe6 183 if (t == TCC0 || t == TCC1) {
Helmut Tschemernjak 77:7f227a4dffe6 184 REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC0_TCC1);
Helmut Tschemernjak 77:7f227a4dffe6 185 } else if (t == TCC2) {
Helmut Tschemernjak 77:7f227a4dffe6 186 REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC2_TC3_Val);
Helmut Tschemernjak 77:7f227a4dffe6 187 }
Helmut Tschemernjak 77:7f227a4dffe6 188 while (GCLK->STATUS.bit.SYNCBUSY == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 189
Helmut Tschemernjak 77:7f227a4dffe6 190 t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TCC
Helmut Tschemernjak 77:7f227a4dffe6 191 while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 192
Helmut Tschemernjak 77:7f227a4dffe6 193 t->CTRLA.reg |= (TCC_CTRLA_PRESCALER_DIV2 | TCC_CTRLA_RUNSTDBY); // Set perscaler
Helmut Tschemernjak 77:7f227a4dffe6 194
Helmut Tschemernjak 77:7f227a4dffe6 195 t->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ; // Set wave form configuration
Helmut Tschemernjak 77:7f227a4dffe6 196 while (t->SYNCBUSY.bit.WAVE == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 197
Helmut Tschemernjak 77:7f227a4dffe6 198 t->PER.bit.PER = 0xffffff; // set counter top to max 24 bit
Helmut Tschemernjak 77:7f227a4dffe6 199 while (t->SYNCBUSY.bit.PER == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 200
Helmut Tschemernjak 77:7f227a4dffe6 201 // the compare counter TC->CC[0].reg will be set in the startTimer
Helmut Tschemernjak 77:7f227a4dffe6 202 // after the timeout calculation is known.
Helmut Tschemernjak 77:7f227a4dffe6 203
Helmut Tschemernjak 77:7f227a4dffe6 204 // Interrupts
Helmut Tschemernjak 77:7f227a4dffe6 205 t->INTENSET.reg = 0; // disable all interrupts
Helmut Tschemernjak 77:7f227a4dffe6 206 t->INTENSET.bit.OVF = 1; // enable overfollow
Helmut Tschemernjak 77:7f227a4dffe6 207 t->INTENSET.bit.MC0 = 1; // enable compare match to CC0
Helmut Tschemernjak 77:7f227a4dffe6 208
Helmut Tschemernjak 77:7f227a4dffe6 209 const struct TCC_config *cp = &TCC_data[0];
Helmut Tschemernjak 77:7f227a4dffe6 210 while (cp->tcc_ptr) {
Helmut Tschemernjak 77:7f227a4dffe6 211 if (cp->tcc_ptr == t) {
Helmut Tschemernjak 77:7f227a4dffe6 212 NVIC_EnableIRQ(cp->tcc_irq); // Enable InterruptVector
Helmut Tschemernjak 77:7f227a4dffe6 213 break;
Helmut Tschemernjak 77:7f227a4dffe6 214 }
Helmut Tschemernjak 77:7f227a4dffe6 215 cp++;
Helmut Tschemernjak 77:7f227a4dffe6 216 }
Helmut Tschemernjak 77:7f227a4dffe6 217 }
Helmut Tschemernjak 77:7f227a4dffe6 218
Helmut Tschemernjak 77:7f227a4dffe6 219
Helmut Tschemernjak 77:7f227a4dffe6 220 #if 0
Helmut Tschemernjak 77:7f227a4dffe6 221 // Atmel ASF Code
Helmut Tschemernjak 77:7f227a4dffe6 222 static uint32_t getTimerCount(Tcc *t)
Helmut Tschemernjak 77:7f227a4dffe6 223 {
Helmut Tschemernjak 77:7f227a4dffe6 224 uint32_t last_cmd;
Helmut Tschemernjak 77:7f227a4dffe6 225 /* Wait last command done */
Helmut Tschemernjak 77:7f227a4dffe6 226 do {
Helmut Tschemernjak 77:7f227a4dffe6 227 while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */
Helmut Tschemernjak 77:7f227a4dffe6 228
Helmut Tschemernjak 77:7f227a4dffe6 229 last_cmd = t->CTRLBSET.reg & TCC_CTRLBSET_CMD_Msk;
Helmut Tschemernjak 77:7f227a4dffe6 230 if (TCC_CTRLBSET_CMD_NONE == last_cmd) {
Helmut Tschemernjak 77:7f227a4dffe6 231 /* Issue read command and break */
Helmut Tschemernjak 77:7f227a4dffe6 232 t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val;
Helmut Tschemernjak 77:7f227a4dffe6 233 break;
Helmut Tschemernjak 77:7f227a4dffe6 234 } else if (TCC_CTRLBSET_CMD_READSYNC == last_cmd) {
Helmut Tschemernjak 77:7f227a4dffe6 235 /* Command have been issued */
Helmut Tschemernjak 77:7f227a4dffe6 236 break;
Helmut Tschemernjak 77:7f227a4dffe6 237 }
Helmut Tschemernjak 77:7f227a4dffe6 238 } while (1);
Helmut Tschemernjak 77:7f227a4dffe6 239
Helmut Tschemernjak 77:7f227a4dffe6 240 while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */
Helmut Tschemernjak 77:7f227a4dffe6 241
Helmut Tschemernjak 77:7f227a4dffe6 242 return t->COUNT.reg;
Helmut Tschemernjak 77:7f227a4dffe6 243 }
Helmut Tschemernjak 77:7f227a4dffe6 244 #endif
Helmut Tschemernjak 77:7f227a4dffe6 245
Helmut Tschemernjak 77:7f227a4dffe6 246
Helmut Tschemernjak 77:7f227a4dffe6 247 static uint32_t getTimerCount(Tcc *t)
Helmut Tschemernjak 77:7f227a4dffe6 248 {
Helmut Tschemernjak 77:7f227a4dffe6 249
Helmut Tschemernjak 77:7f227a4dffe6 250 noInterrupts();
Helmut Tschemernjak 77:7f227a4dffe6 251
Helmut Tschemernjak 77:7f227a4dffe6 252 while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */
Helmut Tschemernjak 77:7f227a4dffe6 253
Helmut Tschemernjak 77:7f227a4dffe6 254 t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val; /* Issue read command and break */
Helmut Tschemernjak 77:7f227a4dffe6 255
Helmut Tschemernjak 77:7f227a4dffe6 256 while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */
Helmut Tschemernjak 77:7f227a4dffe6 257
Helmut Tschemernjak 77:7f227a4dffe6 258 uint32_t count = t->COUNT.reg;
Helmut Tschemernjak 77:7f227a4dffe6 259
Helmut Tschemernjak 77:7f227a4dffe6 260 interrupts();
Helmut Tschemernjak 77:7f227a4dffe6 261
Helmut Tschemernjak 77:7f227a4dffe6 262 return count;
Helmut Tschemernjak 77:7f227a4dffe6 263 }
Helmut Tschemernjak 77:7f227a4dffe6 264
Helmut Tschemernjak 77:7f227a4dffe6 265
Helmut Tschemernjak 77:7f227a4dffe6 266 Tcc *getTimeout_tcc(void)
Helmut Tschemernjak 77:7f227a4dffe6 267 {
Helmut Tschemernjak 77:7f227a4dffe6 268 return TCC_data[USE_TCC_TIMEOUT].tcc_ptr;
Helmut Tschemernjak 77:7f227a4dffe6 269 }
Helmut Tschemernjak 77:7f227a4dffe6 270
Helmut Tschemernjak 77:7f227a4dffe6 271
Helmut Tschemernjak 77:7f227a4dffe6 272 void stopTimer(Tcc *t)
Helmut Tschemernjak 77:7f227a4dffe6 273 {
Helmut Tschemernjak 77:7f227a4dffe6 274 t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
Helmut Tschemernjak 77:7f227a4dffe6 275 while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 276 }
Helmut Tschemernjak 77:7f227a4dffe6 277
Helmut Tschemernjak 77:7f227a4dffe6 278
Helmut Tschemernjak 77:7f227a4dffe6 279 /* ----------------- TIMEOUT TIMER CODE ----------------------*/
Helmut Tschemernjak 77:7f227a4dffe6 280
Helmut Tschemernjak 77:7f227a4dffe6 281 void startTimer(Tcc *t, uint64_t delay_ns)
Helmut Tschemernjak 77:7f227a4dffe6 282 {
Helmut Tschemernjak 77:7f227a4dffe6 283 if (!initTimerDone) {
Helmut Tschemernjak 77:7f227a4dffe6 284 initTimer(t); // initial setup with stopped timer
Helmut Tschemernjak 77:7f227a4dffe6 285 initTimerDone = true;
Helmut Tschemernjak 77:7f227a4dffe6 286 }
Helmut Tschemernjak 77:7f227a4dffe6 287
Helmut Tschemernjak 77:7f227a4dffe6 288 stopTimer(t); // avoid timer interrupts while calculating
Helmut Tschemernjak 77:7f227a4dffe6 289
Helmut Tschemernjak 77:7f227a4dffe6 290 /*
Helmut Tschemernjak 77:7f227a4dffe6 291 * every 21333 ns equals one tick (1/(48000000/1024))
Helmut Tschemernjak 77:7f227a4dffe6 292 * COUNT*DIVIDER*SECS until interrupt
Helmut Tschemernjak 77:7f227a4dffe6 293 * 48 Mhz = (65536*1024)/1.398636s
Helmut Tschemernjak 77:7f227a4dffe6 294 */
Helmut Tschemernjak 77:7f227a4dffe6 295 uint64_t nclocks = (uint64_t)delay_ns;
Helmut Tschemernjak 77:7f227a4dffe6 296 nclocks /= (uint64_t)NS_PER_CLOCK;
Helmut Tschemernjak 77:7f227a4dffe6 297 int nCounts = nclocks;
Helmut Tschemernjak 77:7f227a4dffe6 298
Helmut Tschemernjak 77:7f227a4dffe6 299 int bits = TCC_data[USE_TCC_TIMEOUT].nbits;
Helmut Tschemernjak 77:7f227a4dffe6 300 int maxCounts = (uint32_t)(1<<bits)-1;
Helmut Tschemernjak 77:7f227a4dffe6 301
Helmut Tschemernjak 77:7f227a4dffe6 302 if (nCounts > maxCounts) // if count exceeds timer capacity
Helmut Tschemernjak 77:7f227a4dffe6 303 nCounts = maxCounts; // set the largest posible count.
Helmut Tschemernjak 77:7f227a4dffe6 304 if (nCounts <= 0)
Helmut Tschemernjak 77:7f227a4dffe6 305 nCounts = 1;
Helmut Tschemernjak 77:7f227a4dffe6 306 t->CC[0].bit.CC = nCounts;
Helmut Tschemernjak 77:7f227a4dffe6 307 while (t->SYNCBUSY.bit.CC0 == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 308
Helmut Tschemernjak 77:7f227a4dffe6 309 t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC
Helmut Tschemernjak 77:7f227a4dffe6 310 while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 311 #if 0
Helmut Tschemernjak 77:7f227a4dffe6 312 ser->print(ms_getTicker(), DEC);
Helmut Tschemernjak 77:7f227a4dffe6 313 ser->print(" startTimer: nCounts=");
Helmut Tschemernjak 77:7f227a4dffe6 314 ser->println(nCounts, DEC);
Helmut Tschemernjak 77:7f227a4dffe6 315 #endif
Helmut Tschemernjak 77:7f227a4dffe6 316 }
Helmut Tschemernjak 77:7f227a4dffe6 317
Helmut Tschemernjak 77:7f227a4dffe6 318
Helmut Tschemernjak 77:7f227a4dffe6 319 #if USE_TCC_TIMEOUT == 0
Helmut Tschemernjak 77:7f227a4dffe6 320 void TCC0_Handler()
Helmut Tschemernjak 77:7f227a4dffe6 321 #elif USE_TCC_TIMEOUT == 1
Helmut Tschemernjak 77:7f227a4dffe6 322 void TCC1_Handler()
Helmut Tschemernjak 77:7f227a4dffe6 323 #elif USE_TCC_TIMEOUT == 2
Helmut Tschemernjak 77:7f227a4dffe6 324 void TCC2_Handler()
Helmut Tschemernjak 77:7f227a4dffe6 325 #endif
Helmut Tschemernjak 77:7f227a4dffe6 326 {
Helmut Tschemernjak 77:7f227a4dffe6 327 Tcc *t = TCC_data[USE_TCC_TIMEOUT].tcc_ptr;
Helmut Tschemernjak 77:7f227a4dffe6 328 uint64_t nsecs = ns_getTicker();
Helmut Tschemernjak 77:7f227a4dffe6 329
Helmut Tschemernjak 77:7f227a4dffe6 330 /*
Helmut Tschemernjak 77:7f227a4dffe6 331 * Overflow means the max timer exeeded, we need restart the timer
Helmut Tschemernjak 77:7f227a4dffe6 332 * Interrupts and
Helmut Tschemernjak 77:7f227a4dffe6 333 */
Helmut Tschemernjak 77:7f227a4dffe6 334 if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt
Helmut Tschemernjak 77:7f227a4dffe6 335 t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag
Helmut Tschemernjak 77:7f227a4dffe6 336 }
Helmut Tschemernjak 77:7f227a4dffe6 337
Helmut Tschemernjak 77:7f227a4dffe6 338 if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt
Helmut Tschemernjak 77:7f227a4dffe6 339 //ser->print("MC0\r\n");
Helmut Tschemernjak 77:7f227a4dffe6 340 t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag
Helmut Tschemernjak 77:7f227a4dffe6 341 }
Helmut Tschemernjak 77:7f227a4dffe6 342
Helmut Tschemernjak 77:7f227a4dffe6 343 t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
Helmut Tschemernjak 77:7f227a4dffe6 344 while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
Helmut Tschemernjak 77:7f227a4dffe6 345
Helmut Tschemernjak 77:7f227a4dffe6 346 for (int i = 0; i < MAX_TIMEOUTS-1; i++) {
Helmut Tschemernjak 77:7f227a4dffe6 347 struct TimeoutVector *tvp = &TimeOuts[i];
Helmut Tschemernjak 77:7f227a4dffe6 348 if (tvp->timer && nsecs >= tvp->timer->_timeout) {
Helmut Tschemernjak 77:7f227a4dffe6 349 Timeout *saveTimer = tvp->timer;
Helmut Tschemernjak 77:7f227a4dffe6 350 tvp->timer = NULL;
Helmut Tschemernjak 77:7f227a4dffe6 351 Timeout::_irq_handler(saveTimer);
Helmut Tschemernjak 77:7f227a4dffe6 352 }
Helmut Tschemernjak 77:7f227a4dffe6 353 }
Helmut Tschemernjak 77:7f227a4dffe6 354 /*
Helmut Tschemernjak 77:7f227a4dffe6 355 * we need to restart the timer for remaining interrupts
Helmut Tschemernjak 77:7f227a4dffe6 356 * Another reason is that we stopped this counter, in case there are
Helmut Tschemernjak 77:7f227a4dffe6 357 * remaining counts, we need to re-schedule the counter.
Helmut Tschemernjak 77:7f227a4dffe6 358 */
Helmut Tschemernjak 77:7f227a4dffe6 359 Timeout::restart();
Helmut Tschemernjak 77:7f227a4dffe6 360 }
Helmut Tschemernjak 77:7f227a4dffe6 361
Helmut Tschemernjak 77:7f227a4dffe6 362
Helmut Tschemernjak 77:7f227a4dffe6 363 /* ----------------- D21 sleep() and deepsleep() code ----------------------*/
Helmut Tschemernjak 77:7f227a4dffe6 364
Helmut Tschemernjak 77:7f227a4dffe6 365 void sleep(void)
Helmut Tschemernjak 77:7f227a4dffe6 366 {
Helmut Tschemernjak 77:7f227a4dffe6 367 /*
Helmut Tschemernjak 77:7f227a4dffe6 368 * If we use the native USB port our Serial is SerialUSB
Helmut Tschemernjak 77:7f227a4dffe6 369 * and if the SerialUSB and connected we should
Helmut Tschemernjak 77:7f227a4dffe6 370 * not enter into sleep mode because this kills the Arduino USB emulation
Helmut Tschemernjak 77:7f227a4dffe6 371 */
Helmut Tschemernjak 84:3428e25c7157 372 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disbale SysTick
Helmut Tschemernjak 84:3428e25c7157 373 uint32_t saved_ms = ms_getTicker();
Helmut Tschemernjak 84:3428e25c7157 374
Helmut Tschemernjak 84:3428e25c7157 375 if (SerialUSB_active) {
Helmut Tschemernjak 84:3428e25c7157 376 __DSB(); // ensures the completion of memory accesses
Helmut Tschemernjak 84:3428e25c7157 377 __WFI(); // wait for interrupt
Helmut Tschemernjak 84:3428e25c7157 378 } else {
Helmut Tschemernjak 84:3428e25c7157 379 #if 0 // (SAMD20 || SAMD21)
Helmut Tschemernjak 84:3428e25c7157 380 /* Errata: Make sure that the Flash does not power all the way down
Helmut Tschemernjak 84:3428e25c7157 381 * when in sleep mode. */
Helmut Tschemernjak 84:3428e25c7157 382 NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;
Helmut Tschemernjak 77:7f227a4dffe6 383 #endif
Helmut Tschemernjak 84:3428e25c7157 384
Helmut Tschemernjak 84:3428e25c7157 385 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // clear deep sleep
Helmut Tschemernjak 84:3428e25c7157 386 PM->SLEEP.reg = 2; // SYSTEM_SLEEPMODE_IDLE_2 IDLE 2 sleep mode.
Helmut Tschemernjak 84:3428e25c7157 387
Helmut Tschemernjak 84:3428e25c7157 388 __DSB(); // ensures the completion of memory accesses
Helmut Tschemernjak 84:3428e25c7157 389 __WFI(); // wait for interrupt
Helmut Tschemernjak 84:3428e25c7157 390 }
Helmut Tschemernjak 77:7f227a4dffe6 391
Helmut Tschemernjak 77:7f227a4dffe6 392 int count = ms_getTicker() - saved_ms;
Helmut Tschemernjak 77:7f227a4dffe6 393 if (count > 0) { // update the Arduino Systicks
Helmut Tschemernjak 77:7f227a4dffe6 394 for (int i = 0; i < count; i++) {
Helmut Tschemernjak 77:7f227a4dffe6 395 SysTick_Handler();
Helmut Tschemernjak 77:7f227a4dffe6 396 }
Helmut Tschemernjak 77:7f227a4dffe6 397 }
Helmut Tschemernjak 77:7f227a4dffe6 398 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // enable SysTick
Helmut Tschemernjak 77:7f227a4dffe6 399 }
Helmut Tschemernjak 77:7f227a4dffe6 400
Helmut Tschemernjak 85:93832cc77534 401 /*
Helmut Tschemernjak 85:93832cc77534 402 * TODO
Helmut Tschemernjak 85:93832cc77534 403 * Check if we need to disable the USB GCLK->CLKCTRL.reg (see USBCore.cpp)
Helmut Tschemernjak 85:93832cc77534 404 * Check what else we need to disable?
Helmut Tschemernjak 85:93832cc77534 405 */
Helmut Tschemernjak 85:93832cc77534 406
Helmut Tschemernjak 77:7f227a4dffe6 407 void deepsleep(void)
Helmut Tschemernjak 77:7f227a4dffe6 408 {
Helmut Tschemernjak 85:93832cc77534 409 #if 0 // (SAMD20 || SAMD21)
Helmut Tschemernjak 77:7f227a4dffe6 410 /* Errata: Make sure that the Flash does not power all the way down
Helmut Tschemernjak 77:7f227a4dffe6 411 * when in sleep mode. */
Helmut Tschemernjak 77:7f227a4dffe6 412 NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;
Helmut Tschemernjak 77:7f227a4dffe6 413 #endif
Helmut Tschemernjak 77:7f227a4dffe6 414
Helmut Tschemernjak 77:7f227a4dffe6 415 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // standby mode
Helmut Tschemernjak 86:49d19df5bbce 416 //EIC->WAKEUP.bit.WAKEUPEN3 = 1; // enable wakeup on Pin 12/PA19/EXTINT[3] see variants.h
Helmut Tschemernjak 77:7f227a4dffe6 417
Helmut Tschemernjak 77:7f227a4dffe6 418 __DSB(); // ensures the completion of memory accesses
Helmut Tschemernjak 77:7f227a4dffe6 419 __WFI(); // wait for interrupt
Helmut Tschemernjak 77:7f227a4dffe6 420 }
Helmut Tschemernjak 77:7f227a4dffe6 421
Helmut Tschemernjak 77:7f227a4dffe6 422 #endif // D21 TCC Timer, sleep, etc-
Helmut Tschemernjak 77:7f227a4dffe6 423
Helmut Tschemernjak 77:7f227a4dffe6 424 #endif // ARDUINO