This page describes timing concepts and suggests timing libraries for this project.
(Image from Wikipedia.)
Motivation
This project needs to read data from the accelerometer and microphone "simultaneously". It is important to have a precise understanding of when each data point was collected to get an accurate picture of acceleration and acoustic waves from our machinery. Therefore every data point will be timestamped, either in ticks or in actual seconds (ms or us), of how much time has passed since the last collection point.
There is also a need for delays in this code, however I have noticed that some delay-creating methods are incompatible with this sensor code, for example when used with interrupts.
Reference
Our highest-speed component will be the KX134-1211 accelerometer, which could have an ODR of up to 25600Hz. This would mean a period of ~39us. Therefore it would be really nice to have at least 2x this resolution (maybe even 3x or 4x) as our timing method to get accurate timestamps between measurements.
- 2x —> 51200Hz
- 3x —> 76800Hz
- 4x —> 102400Hz
These mean that we need a high-frequency clock - LFXO won't cut it (see Clock Sources below).
We will also need to collect data for 1s, so it will be important to make sure that the rollover is higher than a second (if we choose not to reset the counter between readings in order to save precious nanoseconds).
Creating Delays
There are several kinds of delays you could use in Simplicity Studio 5 [1]:
- USTIMER_DelayIntSafe: Seems to be safe for threads and interrupts. Mags: I recommend this one, it seems to work great in my code.
- USTIMER_Delay: Not thread safe, does not play nice with other interrupts (Mags: I have seen this in my code, so I switched over to #1.)
- halCommonDelayMicroseconds: Internally uses USTIMER_DelayIntSafe() (not verified)
- usecDelay: Have only seen implemented in EFR32.
- UDELAY_Delay, coded in assembly language. Comments state that could only be delaying for 75% of intended value, and also not for values more than 1ms (1000 us).
- UTIL_TIMER_delay: in RAIL app utils. This seems to use a combination of TIMER0 and TIMER1.
Timestamps
Besides the methods listed below, I have seen suggestions for other methods of timestamping mentioned in the forums:
- There is a mysterious halCommonGet-Int16uMillisecondTick() and halCommonGetInt32uMillisecondTick() duo of functions, however I don't think they're available for this board (can't find anything about them anywhere else) [2].
Real Time Clock (RTC)
This driver is deprecated in Series 2 devices. The manufacturer recommends using 'Sleeptimer' instead. [3]
Real Time Clock/Calendar (RTCC)
- Hard to tell, but it looks like it will only work on LF sources [6, pg. 415] - this would mean maximum resolution of 30.5us.
- Works up to EM3, the second-lowest energy mode.
- In older models (EFR32xG1 and EFR32xG12) the BLE module needed exclusive use of the RTCC, however there were some ways you could get around this to use the RTCC functions. [4]
- To get accurate timing in fluctuating temperatures, you may need to apply a transform to the clock frequency that takes the following form (not currently implemented): [5]
- where $\beta =$ -0.04 [ppm/°C²], $T_0 =$ the central temperature (looks to be 25°C), $f_0 =$ the typical clock frequency at this central temperature (should be found in the datasheet), and $T =$ the ambient temperature. More info can be found in the Silicon Labs whitepaper AN0004.1: EFM32 Series 1 and EFR32 Wireless MCU Clock Management Unit (CMU), although AN0004.2: EFR32 Series 2 Wireless MCU Clock Management Unit (CMU) may have better information for our needs.
- Silicon Labs Documentation for RTCC
Back-up Real Time Clock (BURTC)
- Can use LFXO, LFRCO, or ULFRC as the clock source. [6, pg 434]. Maximum resolution of 30.5us.
- Works up to EM4, which is the lowest-possible energy mode (uses ULFRCO).
- Silicon Labs Documentation for BURTC
Sleeptimer
- Interestingly enough, so far it's the only peripheral I've seen that has an explicit "Tick" function in the library that can do milliseconds. I'm worried that ms is not going to be precise enough, although I have yet to try.
- One of the following clock sources must be enabled before initializing the sleeptimer [8]:
- LFXO: external crystal oscillator. Typically running at 32.768 kHz.
- LFRCO: internal oscillator running at 32.768 kHz
- ULFRCO: Ultra low-frequency oscillator running at 1.000 kHz
- This means this also has a maximum resolution of 30.5us.
Timer (TIMER)
After all that: probably going to be the most useful going forward.
- The default clock source is the 'Prescaled EM01GRPA clock', which is initialized to the HFXO. This clock is optimized for 38.4 MHz crystals [6 pg. 171], which would suggest that the period of ticks is 26ns.
- There is some nice math provided by [14] if we ever want to change it from the fastest timer, but for now we'll leave it since we only want one second of data.
Low-Energy Timer (LETIMER)
Clock Sources
From [7]:
There are a maximum of seven oscillators that can be used as clock sources for different purposes. The SYSCLK is usually clocked by the HFXO, FSRCO or HFRCO, whereas low energy peripherals are usually clocked by the LFXO, LFRCO, or ULFRCO. The HFRCOEM231 is typically used for the low energy peripherals such as LETIMER.
Oscillator | Frequency Range |
---|---|
HFXO | 38-40 MHz |
HFRCODPLL | 1-80 MHz |
HFRCOEM23 | 1-38 MHz |
FSRCO | 20 MHz |
LFXO | 32768 Hz |
LFRCO | 32768 Hz |
ULFRCO | 1000 Hz |
Clocks that have this effect are not available on the EFR32xG22.
Important Note about Bricking
When picking the oscillator for something like SYSCLK, the chosen oscillator HAS to be enabled first before it is selected or else all modules running that clock source will stop. Then the CPU will stop, and then the device has potentially entered an unrecoverable state.