From 3fce47d023f7c54bb05b64772d27442808a07a4b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 15 Oct 2019 14:21:26 +0200 Subject: [PATCH] Add `hw tia` to trigger a new Timing Interval Acquisition --- armsrc/Makefile | 1 + armsrc/appmain.c | 19 ++++++++++++++ bootrom/Makefile | 1 + bootrom/bootrom.c | 41 ++---------------------------- client/cmdhw.c | 13 ++++++++++ common_arm/clocks.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ common_arm/clocks.h | 10 ++++++++ include/pm3_cmd.h | 1 + 8 files changed, 109 insertions(+), 39 deletions(-) create mode 100644 common_arm/clocks.c create mode 100644 common_arm/clocks.h diff --git a/armsrc/Makefile b/armsrc/Makefile index f94868b6e..beb19c243 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -109,6 +109,7 @@ THUMBSRC = start.c \ string.c \ BigBuf.c \ ticks.c \ + clocks.c \ hfsnoop.c diff --git a/armsrc/appmain.c b/armsrc/appmain.c index a0c9a78f2..f2e4424ee 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -11,6 +11,7 @@ //----------------------------------------------------------------------------- #include "appmain.h" +#include "clocks.h" #include "usb_cdc.h" #include "proxmark3_arm.h" #include "dbprint.h" @@ -303,6 +304,14 @@ void SendVersion(void) { reply_ng(CMD_VERSION, PM3_SUCCESS, (uint8_t *)&payload, 12 + payload.versionstr_len); } +void TimingIntervalAcquisition(void) { + // trigger new acquisition by turning main oscillator off and on + mck_from_pll_to_slck(); + mck_from_slck_to_pll(false); + // wait for MCFR and recompute RTMR scaler + StartTickCount(); +} + // measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time. // Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the PacketCommandNG structure included. void printConnSpeed(void) { @@ -1889,6 +1898,16 @@ static void PacketReceived(PacketCommandNG *packet) { SendStatus(); break; } + case CMD_TIA: { + uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; + Dbprintf(" Slow clock old measured value:.........%d Hz", (16 * MAINCK) / mainf); + TimingIntervalAcquisition(); + mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; + Dbprintf(""); // first message gets lost + Dbprintf(" Slow clock new measured value:.........%d Hz", (16 * MAINCK) / mainf); + reply_ng(CMD_TIA, PM3_SUCCESS, NULL, 0); + break; + } case CMD_STANDALONE: { RunMod(); break; diff --git a/bootrom/Makefile b/bootrom/Makefile index d666f3acd..5c7823896 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -9,6 +9,7 @@ # DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code ARMSRC = THUMBSRC = usb_cdc.c \ + clocks.c \ bootrom.c ASMSRC = ram-reset.s flash-reset.s diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 4b255536f..081a49c24 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -6,6 +6,7 @@ // Main code for the bootloader //----------------------------------------------------------------------------- +#include "clocks.h" #include "usb_cdc.h" #include "proxmark3_arm.h" @@ -68,45 +69,7 @@ static void ConfigClocks(void) { (1 << AT91C_ID_PWMC) | (1 << AT91C_ID_UDP); - // worst case scenario, with MAINCK = 16MHz xtal, startup delay is 1.4ms - // if SLCK slow clock runs at its worst case (max) frequency of 42kHz - // max startup delay = (1.4ms*42k)/8 = 7.356 so round up to 8 - - // enable main oscillator and set startup delay - AT91C_BASE_PMC->PMC_MOR = - AT91C_CKGR_MOSCEN | - PMC_MAIN_OSC_STARTUP_DELAY(8); - - // wait for main oscillator to stabilize - while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)) {}; - - // PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00 - // PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10 - // PLL output is MAINCK * multiplier / divisor = 16MHz * 12 / 2 = 96MHz - AT91C_BASE_PMC->PMC_PLLR = - PMC_PLL_DIVISOR(2) | - //PMC_PLL_COUNT_BEFORE_LOCK(0x10) | - PMC_PLL_COUNT_BEFORE_LOCK(0x3F) | - PMC_PLL_FREQUENCY_RANGE(0) | - PMC_PLL_MULTIPLIER(12) | - PMC_PLL_USB_DIVISOR(1); - - // wait for PLL to lock - while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)) {}; - - // we want a master clock (MCK) to be PLL clock / 2 = 96MHz / 2 = 48MHz - // datasheet recommends that this register is programmed in two operations - // when changing to PLL, program the prescaler first then the source - AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; - - // wait for main clock ready signal - while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {}; - - // set the source to PLL - AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK; - - // wait for main clock ready signal - while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {}; + mck_from_slck_to_pll(true); } static void Fatal(void) { diff --git a/client/cmdhw.c b/client/cmdhw.c index 5dddac5fc..ec53ad2cf 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -511,6 +511,18 @@ static int CmdStatus(const char *Cmd) { return PM3_SUCCESS; } +static int CmdTia(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + clearCommandBuffer(); + PrintAndLogEx(INFO, "Triggering new Timing Interval Acquisition..."); + PacketResponseNG resp; + SendCommandNG(CMD_TIA, NULL, 0); + if (WaitForResponseTimeout(CMD_TIA, &resp, 2000) == false) + PrintAndLogEx(WARNING, "Tia command failed. You probably need to unplug the Proxmark3."); + PrintAndLogEx(INFO, "TIA done."); + return PM3_SUCCESS; +} + static int CmdPing(const char *Cmd) { uint32_t len = strtol(Cmd, NULL, 0); if (len > PM3_CMD_DATA_SIZE) @@ -604,6 +616,7 @@ static command_t CommandTable[] = { {"setmux", CmdSetMux, IfPm3Present, "Set the ADC mux to a specific value"}, {"standalone", CmdStandalone, IfPm3Present, "Jump to the standalone mode"}, {"status", CmdStatus, IfPm3Present, "Show runtime status information about the connected Proxmark3"}, + {"tia", CmdTia, IfPm3Present, "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider"}, {"tune", CmdTune, IfPm3Present, "Measure antenna tuning"}, {"version", CmdVersion, IfPm3Present, "Show version information about the connected Proxmark3"}, {NULL, NULL, NULL, NULL} diff --git a/common_arm/clocks.c b/common_arm/clocks.c new file mode 100644 index 000000000..a4c2d6ced --- /dev/null +++ b/common_arm/clocks.c @@ -0,0 +1,62 @@ +#include "clocks.h" +#include "proxmark3_arm.h" + +void mck_from_pll_to_slck(void) { + // switch main clk to slow clk, first CSS then PRES + AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_SLOW_CLK; + while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {}; + AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK | AT91C_PMC_CSS_SLOW_CLK; + while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {}; + + // disable the PLL + AT91C_BASE_PMC->PMC_PLLR = 0x0; + + // disable main oscillator + AT91C_BASE_PMC->PMC_MOR = 0; +} + +void mck_from_slck_to_pll(bool cold) { + // worst case scenario, with MAINCK = 16MHz xtal, startup delay is 1.4ms + // if SLCK slow clock runs at its worst case (max) frequency of 42kHz + // max startup delay = (1.4ms*42k)/8 = 7.356 so round up to 8 + + // enable main oscillator and set startup delay if cold boot + if (cold) { + AT91C_BASE_PMC->PMC_MOR = + AT91C_CKGR_MOSCEN | + PMC_MAIN_OSC_STARTUP_DELAY(8); + } else { + AT91C_BASE_PMC->PMC_MOR = AT91C_CKGR_MOSCEN; + } + + // wait for main oscillator to stabilize + while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)) {}; + + // PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00 + // PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10 + // PLL output is MAINCK * multiplier / divisor = 16MHz * 12 / 2 = 96MHz + AT91C_BASE_PMC->PMC_PLLR = + PMC_PLL_DIVISOR(2) | + //PMC_PLL_COUNT_BEFORE_LOCK(0x10) | + PMC_PLL_COUNT_BEFORE_LOCK(0x3F) | + PMC_PLL_FREQUENCY_RANGE(0) | + PMC_PLL_MULTIPLIER(12) | + PMC_PLL_USB_DIVISOR(1); + + // wait for PLL to lock + while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)) {}; + + // we want a master clock (MCK) to be PLL clock / 2 = 96MHz / 2 = 48MHz + // datasheet recommends that this register is programmed in two operations + // when changing to PLL, program the prescaler first then the source + AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_SLOW_CLK; + + // wait for main clock ready signal + while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {}; + + // set the source to PLL + AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK; + + // wait for main clock ready signal + while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {}; +} diff --git a/common_arm/clocks.h b/common_arm/clocks.h new file mode 100644 index 000000000..8359dad27 --- /dev/null +++ b/common_arm/clocks.h @@ -0,0 +1,10 @@ +#ifndef _CLOCKS_H_ +#define _CLOCKS_H_ + +#include "common.h" +#include "at91sam7s512.h" + +void mck_from_pll_to_slck(void); +void mck_from_slck_to_pll(bool cold); + +#endif // _CLOCKS_H_ diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index c92a1faee..19ef27afb 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -287,6 +287,7 @@ typedef struct { #define CMD_SET_DBGMODE 0x0114 #define CMD_STANDALONE 0x0115 #define CMD_WTX 0x0116 +#define CMD_TIA 0x0117 // RDV40, Flash memory operations #define CMD_FLASHMEM_WRITE 0x0121