From e0fedc3e60a211cbe3c57a6d8dd22e59adc90694 Mon Sep 17 00:00:00 2001 From: sys64738 Date: Thu, 7 Apr 2022 02:19:58 +0200 Subject: [PATCH] better glitch parameter api --- CMakeLists.txt | 1 + src/cli/dragonzap.c | 4 +- src/cli/rl78-glitch.c | 53 ++++++++++++++---- src/cli/rl78.c | 4 +- src/glitch/glitch.c | 109 ++++++++++++-------------------------- src/glitch/glitch.h | 11 ++-- src/glitch/glitch_param.c | 87 ++++++++++++++++++++++++++++++ src/glitch/glitch_param.h | 53 ++++++++++++++++++ src/zap/zap_max4619.c | 4 +- 9 files changed, 228 insertions(+), 98 deletions(-) create mode 100644 src/glitch/glitch_param.c create mode 100644 src/glitch/glitch_param.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cd111ca..d8cda2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ if(FAMILY STREQUAL "rp2040") ${CMAKE_CURRENT_SOURCE_DIR}/src/test/piotest.c ${CMAKE_CURRENT_SOURCE_DIR}/src/test/delaytest.c ${CMAKE_CURRENT_SOURCE_DIR}/src/test/piodump.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/glitch/glitch_param.c ${CMAKE_CURRENT_SOURCE_DIR}/src/glitch/glitch.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/cli.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/msp430.c diff --git a/src/cli/dragonzap.c b/src/cli/dragonzap.c index 92853a4..ed804d6 100644 --- a/src/cli/dragonzap.c +++ b/src/cli/dragonzap.c @@ -34,14 +34,14 @@ void cli_dragonzap_test(void) { zap_crowbar_a_act(); zap_crowbar_b_act(); zap_max_put(true); - sio_hw->gpio_togl = 0x80; + sio_hw->gpio_set = 0x80; busy_wait_ms(1000); zap_crowbar_a_hiz(); zap_crowbar_b_hiz(); zap_max_put(false); - sio_hw->gpio_togl = 0x80; + sio_hw->gpio_set = 0x80; busy_wait_ms(1000); } diff --git a/src/cli/rl78-glitch.c b/src/cli/rl78-glitch.c index 67ea1f4..58a9e82 100644 --- a/src/cli/rl78-glitch.c +++ b/src/cli/rl78-glitch.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -42,15 +43,26 @@ sec: flg=fe bot=03 fsws=0000 fswe=003f //void trl78_uart1_set_exclusive(bool ex); static uint8_t databuf[DUMP_SIZE]; +static struct glitch_param_randrange offset; +static struct glitch_param_adc length; static void glitch_init_core1_stuff(bool exttrig) { + offset.min = 10*1000; + offset.max = 35433*1000; + length.min = 10; + length.max = 10*1000; + length.adc_index = 999; + + glitch_param_randrange_init(&offset); + glitch_param_adc_init(&length); + // REGC = 2.11V / 0.47..1 uF // WUFM: REGC = 1.80V // BUT: OCD mode: always 2.1! static struct glitch_params gparam = (struct glitch_params){ - .offset_min_ns = 10*1000, - .offset_max_ns = 35433*1000, + //.offset_min_ns = 10*1000, + //.offset_max_ns = 35433*1000, // with REGC & 10uF Vcc: - .length_min_ns = -1,//10,//-1,//20, - .length_max_ns = 10000,//*8, + //.length_min_ns = -1,//10,//-1,//20, + //.length_max_ns = 10000,//*8, // with REGC: /*.length_min_us = 4000, .length_max_us = 6300,*/ @@ -69,7 +81,14 @@ static void glitch_init_core1_stuff(bool exttrig) { .trigger_in_polarity = glitch_positive, .glitch_out_polarity = glitch_positive, .impl = glitch_impl_pio,//core1, - .offset_cur = 0, .length_cur = 0 + }; + gparam.offset_ns = (struct glitch_param){ + .ud = &offset, + .getter = glitch_param_randrange_fn + }; + gparam.length_ns = (struct glitch_param){ + .ud = &length, + .getter = glitch_param_adc_fn }; gparam.trigger_in_pin = exttrig ? TRIGGER_IN_PIN : (-1); glitch_ready(&gparam); @@ -295,11 +314,27 @@ restart: } if (firstbad >= 0) { volatile uint32_t - *off = (volatile uint32_t*)&glitch_param_cur.offset_cur, - *len = (volatile uint32_t*)&glitch_param_cur.length_cur; + *off = (volatile uint32_t*)&glitch_param_cur.offset_ns.cur, + *len = (volatile uint32_t*)&glitch_param_cur.length_ns.cur; printf("glitch first=%d last=%d off=%lu len=%lu rr=%d v=%02x\n", firstbad, lastbad, *off, *len, rr, checkbuf[firstbad]^0xaa); - } else printf("."); + } else { + printf("."); + /*volatile uint32_t + *off = (volatile uint32_t*)&glitch_param_cur.offset_ns.cur, + *len = (volatile uint32_t*)&glitch_param_cur.length_ns.cur; + printf("off was %lu, len was %lu, adc=%04x\n", + *off, *len, adc_read()); + printf("offset: fn=%p ud=%p\n", + glitch_param_cur.offset_ns.getter, + glitch_param_cur.offset_ns.ud); + printf("len: fn=%p ud=%p\n", + glitch_param_cur.length_ns.getter, + glitch_param_cur.length_ns.ud); + uint32_t ofv = glitch_param_cur.offset_ns.getter(glitch_param_cur.offset_ns.ud); + uint32_t lnv = glitch_param_cur.length_ns.getter(glitch_param_cur.length_ns.ud); + printf("sample: len=%lu off=%lu\n", ofv, lnv);*/ + } } } @@ -433,7 +468,7 @@ success:; } printf("got ver! %04x\n", ver); - printf("glitch len: %lu us\n", *(volatile uint32_t*)&glitch_param_cur.length_cur); + printf("glitch len: %lu us\n", *(volatile uint32_t*)&glitch_param_cur.length_ns.cur); /*goto do_reset_stuff;*/ st = tool78_ocd_connect(&tool78_hw_rl78_uart1, passwd); diff --git a/src/cli/rl78.c b/src/cli/rl78.c index ed4505e..5468bbc 100644 --- a/src/cli/rl78.c +++ b/src/cli/rl78.c @@ -93,7 +93,7 @@ sec: flg=fe bot=03 fsws=0000 fswe=003f printf("secget: 0x%02x\n", st); printf("sec: flg=%02x bot=%02x fsws=%04x fswe=%04x\n", sec.flg, sec.bot, sec.fsws, sec.fswe); - //st = tool78_do_security_release(&tool78_hw_rl78_uart1); + /*//st = tool78_do_security_release(&tool78_hw_rl78_uart1); //printf("sec rel: 0x%02x\n", st); // one block = 0x400 = 1k st = tool78_do_block_erase(hw, 0, -1); @@ -104,7 +104,7 @@ sec: flg=fe bot=03 fsws=0000 fswe=003f printf("programming: 0x%02x\n", st); st = tool78_do_verify(hw, 0, 0x3ff, datatoflash); - printf("verify: 0x%02x\n", st); + printf("verify: 0x%02x\n", st);*/ /*for (size_t iii = 0; iii < 65536; iii += 0x400) { st = tool78_do_verify(hw, iii+0, iii+0x3ff, &DATA_wfum_flash[iii]); diff --git a/src/glitch/glitch.c b/src/glitch/glitch.c index 8ba2da6..9007666 100644 --- a/src/glitch/glitch.c +++ b/src/glitch/glitch.c @@ -2,8 +2,8 @@ #include #include #include -#include #include +#include #include #include @@ -23,19 +23,10 @@ #include "trigctl.pio.h" -#define __STRINGIFY(f) #f -#define STRINGIFY(f) __STRINGIFY(f) -#define CORE0_FUNC(f) __scratch_x(STRINGIFY(f)) f -#define CORE1_FUNC(f) __scratch_y(STRINGIFY(f)) f - volatile struct glitch_params glitch_param_cur = {0}; #define param_cur glitch_param_cur -// PCG impl lifted from Wikipedia -#define PCG_MULTIPLIER 6364136223846793005uLL -static uint64_t mcg_state = 0xcafef00dd15ea5e5uLL; // Must be odd - static PIO trigctl_pio = NULL; static uint trigctl_sm, trigctl_off; @@ -80,53 +71,37 @@ static void trigctl_pio_deinit(void) { trigctl_off = trigctl_sm = ~(uint32_t)0; } -static uint32_t CORE1_FUNC(pcg32_fast)(void) { - uint64_t x = mcg_state; - unsigned count = (unsigned)(x >> 61); // 61 = 64 - 3 +#define CORE1_PRE_CALC() \ + uint32_t len = param_cur.length_ns.getter(param_cur.length_ns.ud), \ + off = param_cur.offset_ns.getter(param_cur.offset_ns.ud), \ + iom = 1u << param_cur.glitch_out_pin; \ - mcg_state = x * PCG_MULTIPLIER; - x ^= x >> 22; - return (uint32_t)(x >> (22 + count)); // 22 = 32 - 3 - 7 -} -static void CORE1_FUNC(pcg32_fast_init)(uint64_t seed) { - mcg_state = 2*seed + 1; - (void)pcg32_fast(); -} -// ADC value is in low 12 bits of adc_read() -// FIXME: length_min_ns = -1 => adc breaks? | oops was signedness bug -#define CORE1_PRE_CALC() /* BIG TODO HERE! */ \ - bool sweep = param_cur.offset_min_ns == param_cur.offset_max_ns \ - && param_cur.length_min_ns >= 0; \ - uint32_t len, off = param_cur.offset_min_ns + \ - (pcg32_fast() % (param_cur.offset_max_ns - param_cur.offset_min_ns)), \ - iom = 1u << param_cur.glitch_out_pin; \ - do { \ - if (sweep) { \ - if (len_prev == param_cur.length_max_ns) len_prev = (len = param_cur.length_min_ns); \ - else len = (len_prev = (len_prev + 1));\ - } else { \ - len = (param_cur.length_min_ns < 0) \ - ? (((uint64_t)adc_read() * param_cur.length_max_ns) >> 12) \ - : (param_cur.length_min_ns + (pcg32_fast() % \ - (param_cur.length_max_ns - param_cur.length_min_ns))); \ - } \ - } while (0) \ +//#define CORE1_BUSYLOOP(v) do { \ +// uint32_t counter = (v)/*((v) >> 2) / 3*/; \ +// asm volatile( \ +// "1: sub %[counter], #12\n" \ +// "bgt 1b\n" \ +// :[counter]"+r"(counter) \ +// :: \ +// ); \ +//} while (0) \ +// +//#undef CORE1_BUSYLOOP +#define CORE1_BUSYLOOP(v) busy_wait_us_32((v)/1000) #define CORE1_DO_GLITCH() \ do { \ - busy_wait_us_32(off/1000); \ + CORE1_BUSYLOOP(off); \ + param_cur.offset_ns.cur = off; \ + param_cur.length_ns.cur = len; \ sio_hw->gpio_set = iom; \ - busy_wait_us_32(len/1000); \ + CORE1_BUSYLOOP(len); \ sio_hw->gpio_clr = iom; \ - param_cur.offset_cur = off; \ - param_cur.length_cur = len; \ } while (0) \ __attribute__((__noreturn__)) static void CORE1_FUNC(glitch_core1_thread_core1_fifoirq)(void) { - int32_t len_prev = param_cur.length_min_ns - 1; - SCB->SCR &= ~SCB_SCR_SEVONPEND_Msk; // don't resume WFE on interrupt const int irq = SIO_IRQ_PROC1; @@ -158,8 +133,6 @@ static void CORE1_FUNC(glitch_core1_thread_core1_fifoirq)(void) { } __attribute__((__noreturn__)) static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) { - int32_t len_prev = param_cur.length_min_ns - 1; - // init gpio irq const int gpio = param_cur.trigger_in_pin; const int irq = IO_IRQ_BANK0; @@ -183,31 +156,19 @@ static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) { irq_set_enabled(irq, false); //CORE1_DO_GLITCH(); - busy_wait_us_32(off/1000); + CORE1_BUSYLOOP(off); if (!(sio_hw->gpio_in & (1u<gpio_set = iom; - len = (len >> 4) / 3; - asm volatile( - // loop is 3 cycles - "1: sub %[counter], #1\n" - //"cmp %[counter], #0\n" - "bne 1b\n" - :[counter]"+r"(len) - :: - ); - //busy_wait_us_32(len); + CORE1_BUSYLOOP(len); sio_hw->gpio_clr = iom; - cont: irq_set_enabled(irq, true); } } __attribute__((__noreturn__)) static void CORE1_FUNC(glitch_core1_thread_pio)(void) { - int32_t len_prev = param_cur.length_min_ns - 1; - const int irq = (trigctl_pio == pio0) ? PIO0_IRQ_1 : PIO1_IRQ_1; irq_set_enabled(irq, false); trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm); @@ -218,9 +179,9 @@ static void CORE1_FUNC(glitch_core1_thread_pio)(void) { while (true) { CORE1_PRE_CALC(); (void)iom; + param_cur.offset_ns.cur = off; + param_cur.length_ns.cur = len; trigctl_push_off_len(trigctl_pio, trigctl_sm, off>>2, len>>2); - param_cur.offset_cur = off; - param_cur.length_cur = len; trigctl_wait_glitch_irq(trigctl_pio, trigctl_sm, true); trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm); @@ -229,10 +190,6 @@ static void CORE1_FUNC(glitch_core1_thread_pio)(void) { __attribute__((__noreturn__)) static void CORE1_FUNC(glitch_core1_thread)(void) { - // use stdlib randomness only for the seed, but use a custom rng sitting in - // SRAM 5 to avoid bus contention - pcg32_fast_init(random()); - __disable_irq(); if (param_cur.impl == glitch_impl_pio) { @@ -296,8 +253,8 @@ static void CORE0_FUNC(glitch_stop_no_clock_chg)(void) { bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) { // check params values - if (params->offset_max_ns < params->offset_min_ns) return false; - if (params->length_max_ns < params->length_min_ns) return false; + if (!params->offset_ns.getter || !params->offset_ns.ud) return false; + if (!params->length_ns.getter || !params->length_ns.ud) return false; if (params->trigger_in_pin < -1 || params->trigger_in_pin >= 28 || (params->trigger_in_pin >= 23 && params->trigger_in_pin <= 25)) return false; @@ -320,8 +277,8 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) { glitch_stop(); memcpy(¶m_cur, params, sizeof param_cur); // apply new params - param_cur.offset_cur = 0; - param_cur.length_cur = 0; + param_cur.offset_ns.cur = 0; + param_cur.length_ns.cur = 0; param_cur.armed = false; // let's not care about impl and always use core1 for now @@ -337,7 +294,7 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) { func = (trigctl_pio == pio0) ? GPIO_FUNC_PIO0 : GPIO_FUNC_PIO1; } - if (params->length_min_ns < 0) { + /*if (params->length_min_ns < 0) { // FIXME: use a more generic approach (using dragonzap adc) // ADC1: ADC mode @@ -350,7 +307,7 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) { gpio_set_function(26, GPIO_FUNC_SIO); } else { gpio_set_function(26, GPIO_FUNC_NULL); - } + }*/ if (params->trigger_in_pin >= 0) { //gpio_set_input_hysteresis_enabled(params->trigger_in_pin, false); diff --git a/src/glitch/glitch.h b/src/glitch/glitch.h index 6d98dc7..d385194 100644 --- a/src/glitch/glitch.h +++ b/src/glitch/glitch.h @@ -8,6 +8,8 @@ #include +#include "glitch_param.h" + enum glitch_polarity { glitch_positive, glitch_negative, @@ -19,18 +21,13 @@ enum glitch_impl { }; struct glitch_params { - uint32_t offset_min_ns; - uint32_t offset_max_ns; - // FIXME: use a more generic approach (using dragonzap adc) - // for using user-tunable lengths (with physical knobs) - int32_t length_min_ns; - int32_t length_max_ns; + struct glitch_param offset_ns; + struct glitch_param length_ns; int trigger_in_pin; // use -1 for a signal coming from core 0 int glitch_out_pin; enum glitch_polarity trigger_in_polarity; enum glitch_polarity glitch_out_polarity; enum glitch_impl impl; - uint32_t offset_cur, length_cur; PIO trigctl_pio; uint32_t trigctl_sm; bool armed; diff --git a/src/glitch/glitch_param.c b/src/glitch/glitch_param.c new file mode 100644 index 0000000..c84c764 --- /dev/null +++ b/src/glitch/glitch_param.c @@ -0,0 +1,87 @@ + +#include + +#include +#include +#include +#include +#include + +#include "zap_adc.h" + +#include "glitch_param.h" + +// PCG impl lifted from Wikipedia +#define PCG_MULTIPLIER 6364136223846793005uLL + +__attribute__((__force_inline__)) +inline static uint32_t pcg32_next(uint64_t* st) { + uint64_t x = *st; + unsigned count = (unsigned)(x >> 61); + *st = x * PCG_MULTIPLIER; + x ^= x >> 22; + return (uint32_t)(x >> (22 + count)); +} + +uint32_t CORE1_FUNC(glitch_param_const_fn)(void* p) { + return ((struct glitch_param_const*)p)->value; +} +uint32_t CORE1_FUNC(glitch_param_randrange_fn)(void* p_) { + struct glitch_param_randrange* p = (struct glitch_param_randrange*)p_; + + return p->min + pcg32_next(&p->rand_state) % p->max/*actually delta now*/; +} +uint32_t CORE1_FUNC(glitch_param_sweep_fn)(void* p_) { + struct glitch_param_sweep* p = (struct glitch_param_sweep*)p_; + + uint32_t rv = p->min + p->step * p->cur_index; + if (rv > p->max) { + p->cur_index = 0; + rv = p->min; + } else { + ++p->cur_index; + } + + return rv; +} +uint32_t CORE1_FUNC(glitch_param_adc_fn)(void* p_) { + struct glitch_param_adc* p = (struct glitch_param_adc*)p_; + + uint16_t av; + if (p->adc_index == 0 || p->adc_index == 1) { + av = zap_adc_read(p->adc_index); + } else { + adc_select_input(1); + av = adc_read(); + } + + uint64_t vvv = ((uint64_t)av * (uint64_t)p->max/*actually delta now*/) >> 12; + + return p->min + (uint32_t)vvv; +} + +void glitch_param_randrange_init(struct glitch_param_randrange* p) { + //p->rand_state = 0xcafef00dd15ea5e5uLL; // must be odd + + // use stdlib randomness only for the seed, but use a custom rng sitting in + // SRAM 5 to avoid bus contention + p->rand_state = 2*random()+1; + pcg32_next(&p->rand_state); + p->max = p->max - p->min; +} +void glitch_param_adc_init(struct glitch_param_adc* p) { + if (p->adc_index == 0 || p->adc_index == 1) { + zap_adc_init(); + } else { + // ADC1: ADC mode + adc_init(); + adc_gpio_init(27); + adc_select_input(1); + // ADC0 = GPIO26 = fixed high (as vref) + sio_hw->gpio_set = 1u << 26; + sio_hw->gpio_oe_set = 1u << 26; + gpio_set_function(26, GPIO_FUNC_SIO); + } + p->max = p->max - p->min; +} + diff --git a/src/glitch/glitch_param.h b/src/glitch/glitch_param.h new file mode 100644 index 0000000..6e646c7 --- /dev/null +++ b/src/glitch/glitch_param.h @@ -0,0 +1,53 @@ + +#ifndef GLITCH_PARAM_H_ +#define GLITCH_PARAM_H_ + +#include + +#define __STRINGIFY(f) #f +#define STRINGIFY(f) __STRINGIFY(f) +#define CORE0_FUNC(f) __scratch_x(STRINGIFY(f)) f +#define CORE1_FUNC(f) __scratch_y(STRINGIFY(f)) f + +typedef uint32_t (*glitch_param_fn)(void*); + +struct glitch_param { + glitch_param_fn getter; + void* ud; + uint32_t cur; +}; + +struct glitch_param_const { + uint32_t value; +}; +struct glitch_param_randrange { + uint32_t min; + uint32_t max; + uint64_t rand_state; +}; +struct glitch_param_sweep { + uint32_t min; + uint32_t max; + uint32_t step; + uint32_t cur_index; +}; +struct glitch_param_adc { + uint32_t min; + uint32_t max; + int adc_index; +}; + +uint32_t CORE1_FUNC(glitch_param_const_fn)(void* p); +uint32_t CORE1_FUNC(glitch_param_randrange_fn)(void* p); +uint32_t CORE1_FUNC(glitch_param_sweep_fn)(void* p); +uint32_t CORE1_FUNC(glitch_param_adc_fn)(void* p); + +inline static void glitch_param_const_init(struct glitch_param_const* p) { (void)p; } +inline static void glitch_param_sweep_init(struct glitch_param_sweep* p) { (void)p; } +// NOTE: call this AFTER initializing min and max! +void glitch_param_randrange_init(struct glitch_param_randrange* p); +// NOTE: call this AFTER initializing min, max and adc_index! +void glitch_param_adc_init(struct glitch_param_adc* p); + +#endif + diff --git a/src/zap/zap_max4619.c b/src/zap/zap_max4619.c index 41a327f..c80f294 100644 --- a/src/zap/zap_max4619.c +++ b/src/zap/zap_max4619.c @@ -9,9 +9,9 @@ #include "zap_max4619.h" void zap_max_init(bool inhibit, bool use_jp300) { - const io_rw_32 pinmask = 1u << ZAP_GLITCH_OUT; + const io_rw_32 pinmask = (1u << ZAP_GLITCH_OUT) | (1u << ZAP_MAX_INHIBIT) | (1u << ZAP_MAX_VHI_SW); - sio_hw->gpio_clr = pinmask; // default to low -> JP300 + sio_hw->gpio_clr = pinmask; // default to low -> Vdac1 sio_hw->gpio_oe_set = pinmask; gpio_set_slew_rate(ZAP_GLITCH_OUT, GPIO_SLEW_RATE_FAST);