|
NetBurner 3.5.7
PDF Version |
Topics | |
| High Resolution Delay Timer | |
| High-precision microsecond delay functionality. | |
| Interval Timer | |
| Stopwatch Timer | |
NetBurner provides three hardware timer APIs:
| API | Header | Purpose |
|---|---|---|
HiResDelay (DelayObject) | HiResDelay.h | Blocking microsecond-precision delays |
| IntervalTimer | IntervalTimer.h | Periodic callbacks, semaphore posts, or flag sets |
| StopWatch | stopwatch.h | High-resolution elapsed time measurement |
Each API allocates timers from the underlying CPU's hardware timer peripherals. The number of available timers and the specific hardware used varies by CPU family. This document maps each platform to its timer hardware and documents resource limits.
| Platform | CPU | Architecture | Timer Hardware |
|---|---|---|---|
| MOD5441X | MCF5441X | ColdFire | DMA Timers + PIT Timers |
| NANO54415 | MCF5441X | ColdFire | DMA Timers + PIT Timers |
| SB800EX | MCF5441X | ColdFire | DMA Timers + PIT Timers |
| MODM7AE70 | SAME70 | Cortex-M7 | TC (Timer Counter) Channels |
| SBE70LC | SAME70 | Cortex-M7 | TC Channels |
| SOMRT1061 | MIMXRT10xx | Cortex-M7 | Quad Timers (QTimer) |
| MODRT1171 | MIMXRT11xx | Cortex-M7 | Quad Timers (QTimer) |
| CPU Family | HiResDelay Pool | IntervalTimer Pool | StopWatch Source | Total HW Timers |
|---|---|---|---|---|
| MCF5441X | 4 DMA timers (shared with StopWatch) | 2 PIT timers (PIT 1-2) | 1 DMA timer (shared from same 4) | 4 DMA + 4 PIT |
| SAME70 | 12 TC channels (shared pool) | 12 TC channels (shared pool) | SysTick (no timer consumed) | 12 TC |
| MIMXRT10xx | 12 QTimer channels (shared pool) | 12 QTimer channels (shared pool) | System QTimer pair (no user timer consumed) | 12 QTimer |
| MIMXRT11xx | 12 QTimer channels (shared pool) | 12 QTimer channels | System QTimer pair (no user timer consumed) | 12 QTimer |
Each CPU reserves certain timer hardware for the RTOS system tick. These timers are not available to user code and are already excluded from the timer API allocation pools.
| CPU | Reserved Hardware | Purpose | Configured In |
|---|---|---|---|
| MCF5441X | PIT 0 | RTOS system tick (OSTickISR) | platform/*/source/hal.cpp via sim2.pit[0] |
| 1 | PIT 3 | Debugger | Reserved by convention |
| SAME70 | ARM SysTick | RTOS system tick (SysTick_Handler) | platform/*/source/hal.cpp via SysTick_Config() |
| MIMXRT10xx/11xx | TMR4 channels 2-3 | RTOS system tick (SysTick_Handler) | platform/*/source/hal.cpp via SysTmrLo/SysTmrHi on TMR4 |
Key points**:
Platforms**: MOD5441X, NANO54415, SB800EX
The 1 has 4 DMA timers (DMA Timer 0-3), accessed through sim2.timer[0..3]. These are 32-bit free-running timers clocked at CPU_CLOCK / 2 (~75 MHz at 150 MHz CPU clock).
DelayObject allocates one DMA timer. Up to 4 DelayObject instances can exist simultaneously. The timer is held for the lifetime of the object.StopWatch instance allocates one DMA timer. All subsequent StopWatch instances share that same timer (singleton initialization via bTimerInit flag).Shared pool: HiResDelay and StopWatch compete for the same 4 DMA timers. If StopWatch takes timer 0 and two DelayObject instances take timers 1 and 2, only timer 3 remains.
Timer allocation**: FIRST_UNUSED_TIMER scans sim2.timer[0..3], selecting the first timer whose TMR register bit 0 is clear (timer disabled).
Clock and resolution**:
CPU_CLOCK / 2 (prescale = 1), typically 75 MHz2 / CPU_CLOCK seconds per tick (~13.3 ns at 150 MHz)CountResolution() returns 2.0 / CPU_CLOCKConvert(ticks) returns ticks * 2 / CPU_CLOCK
Short-delay busy-wait**: Delays <= 20 us use a hand-tuned busy-wait loop instead of the hardware timer to avoid semaphore overhead. The loop uses nop instructions calibrated for the ColdFire pipeline.
Max single delay**: The 32-bit reference register allows delays up to 0xFFFFFFFF / (CPU_CLOCK/2) seconds (~57 seconds at 75 MHz).
Source files**:
arch/coldfire/cpu/1/source/HiResDelay.cpparch/coldfire/cpu/1/source/stopwatch.cppThe 1 has 4 PIT (Programmable Interrupt Timer) modules. PIT 0 is reserved for the RTOS system tick, and PIT 3 is reserved for the debugger. PIT 1 and PIT 2 are available for application IntervalTimer use.
FindUnusedPit() scans PIT 1, 2, and 3 checking the pcsr enable bit. However, ISR handlers and configuration functions only exist for PIT 1 and PIT 2 (NbPit1_ISR, NbPit2_ISR), so effectively only 2 IntervalTimers can be active simultaneously.Each PIT is a 16-bit down-counter with a 4-bit prescaler (divides by 2 to 32768), yielding flexible frequency ranges.
Prescaler**: The prescaler is auto-selected to fit the desired frequency within the 16-bit counter range. Divider values range from 2 to 32768 (4-bit field, powers of 2).
Minimum frequency**: The code checks num_per_sec < 1 (returns -2), so the practical minimum is 1 Hz. The header documentation recommends >= 20 Hz.
Source files**:
arch/coldfire/cpu/1/source/IntervalTimer.cpparch/coldfire/cpu/1/source/pitr_sem.cppPlatforms**: 1, SBE70LC
The SAME70 has 4 TC blocks (TC0-TC3), each with 3 channels, totaling 12 TC channels (timers 0-11). These are managed by a unified dispatch system (timer_dispatch.cpp) with a 16-bit timerInUse bitmask.
DelayObject calls AllocateTimer() to reserve a TC channel from the shared 12-channel pool. The channel is freed on destruction via FreeTimer().IntervalOSSem(), IntervalOSFlag(), or IntervalInterruptCallback() call allocates a TC channel from the same shared 12-channel pool.Shared pool: HiResDelay and IntervalTimer draw from the same pool of 12 timers. A DelayObject and an IntervalOSSem() each consume one timer.
Timer dispatch architecture** (timer_dispatch.cpp):
AllocateTimer(handler, extra, timer): Allocates a timer, registers ISR handler. Returns timer number or -1/-2 on failure.FreeTimer(timer): Releases a timer back to the pool.GetTc(timer): Maps timer number (0-11) to TcChannel* via tc[timer/3]->TC_CHANNEL[timer%3].GetTimerPeriphID(timer): Maps timer number to NVIC IRQ number (TC0_IRQn through TC11_IRQn).Individual TC0_Handler() through TC11_Handler() forward to registered handlers.
Clock selection** (IntervalTimer): The driver auto-selects the clock source that minimizes frequency error:
OSC_CLOCK)PERIPH_CLOCK / 8PERIPH_CLOCK / 32PERIPH_CLOCK / 128Each option is evaluated with ClockCheck() and the best-fit is chosen. The 16-bit compare register limits the maximum divider per clock source to 65535.
Clock (HiResDelay)**: Uses TC_CMR_TCCLKS_TIMER_CLOCK2 (PERIPH_CLOCK / 8). At 300 MHz CPU, PERIPH_CLOCK is typically 150 MHz, giving 18.75 MHz timer clock (75/4 ticks per microsecond).
Short-delay busy-wait**: Delays <= 20 us use a calibrated busy-wait loop (magic number 55).
Max single HiResDelay**: ~3400 us per hardware delay cycle (16-bit compare register at 18.75 MHz). Longer delays are handled by chaining multiple 3001 us delays.
StopWatch on SAME70 uses the ARM SysTick timer, which is already running for the RTOS tick. No additional hardware timer is consumed.
GetNow() combines SysTick->VAL (down-counter) with the TimeTick software counter to produce a 64-bit timestamp at CPU clock resolution.Includes rollover correction logic: detects when TimeTick increments between two reads of SysTick->VAL and compensates. Also checks for pending SysTick ISR when called from interrupt context.
Resolution**: 1 / CPU_CLOCK seconds per tick (~3.3 ns at 300 MHz).
Source files**:
arch/cortex-m7/cpu/SAME70/source/HiResDelay.cpparch/cortex-m7/cpu/SAME70/source/IntervalTimer.cpparch/cortex-m7/cpu/SAME70/source/stopwatch.cpparch/cortex-m7/cpu/SAME70/source/timer_dispatch.cppPlatforms**: 1
The MIMXRT10xx has 3 QTimer modules (TMR1[0..2]), each with 4 channels, totaling 12 QTimer channels (timers 0-11). HiResDelay and IntervalTimer share this pool.
FindUnusedTimer().DelayObject is implemented within IntervalTimer.cpp and allocates from the same 12-channel pool via FindUnusedTimer(). It registers the shared IntervalTmrCB callback and uses the semaphore-based interval context for wake-up.Shared pool: Both APIs draw from the identical pool. The intervalCtx[12] array tracks allocations; FindUnusedTimer() checks both the context type and hardware COMP1/COMP2 registers to find free channels.
Timer allocation** (FindUnusedTimer()): Iterates modules 0-2, channels 0-3 (12 total). A channel is free if intervalCtx[].type == None AND COMP1 == 0 AND COMP2 == 0.
Prescaling** (IntervalTimer): 8 hardware prescale levels (QTMR_PRI_CLK_DIV_1 through QTMR_PRI_CLK_DIV_128, shifting PERIPH_CLOCK by 0-7 bits). If prescale 7 is still insufficient for the desired frequency, a software divider (swDiv = 0xF, dividing by 16) extends the range further. The 16-bit compare register limits the count per prescale level to 65535.
Clock (HiResDelay)**: Uses QTMR_PRI_CLK_DIV_1 (no prescale), counting at PERIPH_CLOCK (typically 132 MHz on 1). This gives ~132 counts per microsecond.
Short-delay busy-wait**: Delays <= 21 us use a calibrated busy-wait loop (magic number 63 for inner loop, 58 for startup).
Max single HiResDelay**: ~498 us per hardware delay cycle (0xFFFF / (PERIPH_CLOCK / 1000000)). Longer delays are handled by chaining multiple 497 us delays.
StopWatch on MIMXRT10xx uses a pre-allocated linked QTimer pair (SysTmrLo / SysTmrHi) that is already set up by the HAL for system timekeeping. No user QTimer channel is consumed.
GetNow() reads SysTmrLo.CNTR + SysTmrHi.HOLD * (SysTmrLo.COMP1 + 1) and combines with TimeTick for a 64-bit timestamp.Includes the same rollover correction as SAME70 (TimeTick increment detection + pending ISR check).
Resolution**: 1 / (PERIPH_CLOCK / 16) seconds per tick. At 132 MHz PERIPH_CLOCK, this is 1 / 8,250,000 = ~121 ns.
Source files**:
arch/cortex-m7/cpu/MIMXRT10xx/source/IntervalTimer.cpp (includes HiResDelay implementation)arch/cortex-m7/cpu/MIMXRT10xx/source/stopwatch.cppPlatforms**: MODRT1171
The MIMXRT11xx has the same 3 QTimer modules x 4 channels = 12 QTimer channels as MIMXRT10xx. The IntervalTimer implementation is structurally identical to MIMXRT10xx.
Key difference from MIMXRT10xx**: The MIMXRT11xx IntervalTimer.cpp does not include the DelayObject (HiResDelay) implementation. There is no separate HiResDelay.cpp for this CPU. HiResDelay is not available on MIMXRT11xx platforms.
Identical to MIMXRT10xx. Uses the pre-allocated SysTmrLo / SysTmrHi QTimer pair. No user timer consumed.
Resolution**: 1 / (PERIPH_CLOCK / 16) seconds per tick, same as MIMXRT10xx.
Source files**:
arch/cortex-m7/cpu/MIMXRT11xx/source/IntervalTimer.cpparch/cortex-m7/cpu/MIMXRT11xx/source/stopwatch.cppAll three APIs accept FIRST_UNUSED_TIMER (defined as -1 in constants.h) as the default timer parameter. This triggers automatic allocation of the next available hardware timer.
| Return Value | Meaning |
|---|---|
| >= 0 | Success: allocated timer number |
| -1 | No hardware timer available (all in use) |
| -2 | Invalid frequency (IntervalTimer: < 1 Hz in code, recommended >= 20 Hz) |
valid() to check allocation success.IntervalOSSem() / IntervalOSFlag() / IntervalInterruptCallback() call. Must call IntervalStop(timer_number) to release.| CPU | Max Concurrent DelayObjects | Max Concurrent IntervalTimers | StopWatch Cost |
|---|---|---|---|
| 1 | 3 (if StopWatch uses 1 DMA timer) | 2 (PIT 1-2) | 1 DMA timer (shared) |
| SAME70 | 12 minus active IntervalTimers | 12 minus active DelayObjects | Free (SysTick) |
| MIMXRT10xx | 12 minus active IntervalTimers | 12 minus active DelayObjects | Free (system QTimer) |
| MIMXRT11xx | N/A (not available) | 12 | Free (system QTimer) |
| CPU | HiResDelay | IntervalTimer | StopWatch | Timer Dispatch |
|---|---|---|---|---|
| 1 | arch/coldfire/cpu/1/source/HiResDelay.cpp | arch/coldfire/cpu/1/source/IntervalTimer.cpp + pitr_sem.cpp | arch/coldfire/cpu/1/source/stopwatch.cpp | N/A (direct register access) |
| SAME70 | arch/cortex-m7/cpu/SAME70/source/HiResDelay.cpp | arch/cortex-m7/cpu/SAME70/source/IntervalTimer.cpp | arch/cortex-m7/cpu/SAME70/source/stopwatch.cpp | arch/cortex-m7/cpu/SAME70/source/timer_dispatch.cpp |
| MIMXRT10xx | Combined in IntervalTimer.cpp | arch/cortex-m7/cpu/MIMXRT10xx/source/IntervalTimer.cpp | arch/cortex-m7/cpu/MIMXRT10xx/source/stopwatch.cpp | N/A (inline in IntervalTimer.cpp) |
| MIMXRT11xx | Not available | arch/cortex-m7/cpu/MIMXRT11xx/source/IntervalTimer.cpp | arch/cortex-m7/cpu/MIMXRT11xx/source/stopwatch.cpp | N/A (inline in IntervalTimer.cpp) |
nbrtos/include/HiResDelay.h - DelayObject classnbrtos/include/IntervalTimer.h - IntervalOSSem, IntervalOSFlag, IntervalInterruptCallback, IntervalStopnbrtos/include/stopwatch.h - StopWatch class| CPU | StopWatch Resolution | StopWatch Convert |
|---|---|---|
| 1 | 2.0 / CPU_CLOCK sec/tick | ticks * 2.0 / CPU_CLOCK seconds |
| SAME70 | 1.0 / CPU_CLOCK sec/tick | ticks / CPU_CLOCK seconds |
| MIMXRT10xx/11xx | 1.0 / (PERIPH_CLOCK / 16) sec/tick | ticks / (PERIPH_CLOCK / 16) seconds |
| CPU | Clock Variable | Typical Value | StopWatch Tick |
|---|---|---|---|
| 1 | CPU_CLOCK | 150 MHz | ~13.3 ns |
| SAME70 | CPU_CLOCK | 300 MHz | ~3.3 ns |
| MIMXRT10xx | PERIPH_CLOCK | 132 MHz | ~121 ns |
| MIMXRT11xx | PERIPH_CLOCK | 240 MHz | ~66.7 ns |