doc/clocks.md
<a id="Top"></a>
The device side firmware uses a range of different clocks. Here is an attempt to document the clocks in use and for what they are used.
^Top
Good calculator https://www.unitjuggler.com/convert-frequency-from-MHz-to-ns(p).html?val=3.39
Basic units of time measurment or how long in time is a Hertz?
1 hertz = 1 second = 1000 milli seconds
10 Hertz = 1 / 10 = 0,1 = 100 milli seconds
100 Hertz = 1 / 100 = 0,01 = 10 milli seconds
1 kHz = 1 / 1000 = 0,001 = 1 milli seconds
10 kHz = 1 / 10 000 = 0,000 1 = 100 micro seconds
100 kHz = 1 / 100 000 = 0,000 01 = 10 micro seconds
1 MHZ = 1 / 1 000 000 = 0,000 001 = 1 micro seconds
Basic units of time you will run into in the RFID world.
13.56 MHz = 1 / 13 560 000 = 73,74 nano seconds = 0,07374 micro seconds
125 kHz = 1/ 125 000 = 8 micro seconds
Given these units the following clocks used by Proxmark3 will make more sense.
Like the SSP Clock running at 3.39 MHz. 3.39 MHz = 1 / 3 390 000 = 294,98 nano seconds = 0,2949 micro seconds
1 tick at 3.39 MHz is 294.98 nano seconds.
^Top
~32kHz internal RC clock
Can be between 22 and 42 kHz
^Top
cf PMC_MOR register
16 MHz, based on external Xtal
^Top
cf PMC_PLLR register
96 MHz (MAINCK * 12 / 2)
^Top
cf common_arm/clocks.c
cf PMC_MCKR and PMC_SCER registers
cf bootrom.c:
PCK can be disabled to enter idle mode, but on Proxmark3 it's always on, so PCK is also 48 MHz.
USB need to be clocked at 48 MHz from the PLL, so PLL / 2 (cf CKGR_PLLR).
^Top
cf bootrom.c:
Distribute MCK/PCK? clock to Parallel I/O controller, ADC, SPI, Synchronous Serial controller, PWM controller, USB.
cf appmain.c
Activate PCK0 pin as clock output, based on PLL / 4 = 24 MHz, for the FPGA.
^Top
cf armsrc/ticks.c
cf PMC_MCFR and RTTC_RTMR registers for configuration, RTTC_RTVR register for reading value.
Characteristics:
StartTickCount()GetTickCount()/GetTickCountDeltaDelta(), see exampleUsage:
uint32_t ti = GetTickCount();
...do stuff...
uint32_t delta = GetTickCountDelta(ti);
Current usages:
prng_successor(GetTickCount(), 32)^Top
void SpinDelayUs(int us)void SpinDelay(int ms) based on SpinDelayUsvoid SpinDelayUsPrecision(int us)Busy wait based on 46.875 kHz PWM Channel 0
^Top
cf armsrc/ticks.c
About 1 us precision
void StartCountUS(void)uint32_t RAMFUNC GetCountUS(void)Use two chained timers TC0 and TC1. TC0 runs at 1.5 MHz and TC1 is clocked when TC0 reaches 0xC000.
Maximal value: 0x7fffffff = 2147 s
Can't be used at the same time as CountSspClk or Ticks functions.
^Top
cf armsrc/ticks.c
About 1 cycle of 13.56 MHz? precision
void StartCountSspClk(void)void ResetSspClk(void)uint32_t RAMFUNC GetCountSspClk(void)uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start) <= TODO could be used more oftenUse two chained timers TC0 and TC1. TC0 runs at SSP_CLK from FPGA (13.56 MHz?) and TC1 is clocked when TC0 loops.
Usage:
armsrc/legicrfsim.c SSP Clock is clocked by the FPGA at 212 kHz (sub-carrier frequency)Can't be used at the same time as CountUS or Ticks functions.
^Top
cf armsrc/ticks.c
1.5 MHz
void StartTicks(void)uint32_t GetTicks(void) <= TODO why no GetTicksDelta ?void WaitTicks(uint32_t ticks)void WaitUS(uint32_t us)void WaitMS(uint32_t ms)void StopTicks(void) <= TODO why a stop for this timer and not for CountUS / CountSspClk ?Use two chained timers TC0 and TC1. TC0 runs at 1.5 MHz and TC1 is clocked when TC0 loops.
Maximal value: 0xffffffff = 2863 s (but don't use high value with WaitTicks else you'll trigger WDT)
Usage:
Can't be used at the same time as CountUS or CountSspClk functions.