PIO-based glitch control now also works in practice

This commit is contained in:
Triss 2022-04-04 03:42:50 +02:00
parent d3654f1762
commit 376a6bce7b
5 changed files with 54 additions and 37 deletions

View File

@ -46,11 +46,11 @@ static uint8_t databuf[DUMP_SIZE];
static void glitch_init_core1_stuff(bool exttrig) { static void glitch_init_core1_stuff(bool exttrig) {
// REGC = 2.11V / 0.47..1 uF // WUFM: REGC = 1.80V // BUT: OCD mode: always 2.1! // 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){ static struct glitch_params gparam = (struct glitch_params){
.offset_min_us = 10, .offset_min_ns = 10*1000,
.offset_max_us = 35433, .offset_max_ns = 35433*1000,
// with REGC & 10uF Vcc: // with REGC & 10uF Vcc:
.length_min_us = -1,//10,//-1,//20, .length_min_ns = -1,//10,//-1,//20,
.length_max_us = 100,//*8, .length_max_ns = 10000,//*8,
// with REGC: // with REGC:
/*.length_min_us = 4000, /*.length_min_us = 4000,
.length_max_us = 6300,*/ .length_max_us = 6300,*/
@ -68,7 +68,7 @@ static void glitch_init_core1_stuff(bool exttrig) {
.glitch_out_pin = GLITCH_OUT_PIN, .glitch_out_pin = GLITCH_OUT_PIN,
.trigger_in_polarity = glitch_positive, .trigger_in_polarity = glitch_positive,
.glitch_out_polarity = glitch_positive, .glitch_out_polarity = glitch_positive,
.impl = glitch_impl_core1, .impl = glitch_impl_pio,//core1,
.offset_cur = 0, .length_cur = 0 .offset_cur = 0, .length_cur = 0
}; };
gparam.trigger_in_pin = exttrig ? TRIGGER_IN_PIN : (-1); gparam.trigger_in_pin = exttrig ? TRIGGER_IN_PIN : (-1);

View File

@ -84,7 +84,7 @@ sec: flg=fe bot=03 fsws=0000 fswe=003f
*/ */
uint8_t* datatoflash = true ? DATA_main_nodbg : DATA_main_dbgpad; uint8_t* datatoflash = false ? DATA_main_nodbg : DATA_main_dbgpad;
// NOTE: RL78 ONLY // NOTE: RL78 ONLY
struct tool78_security sec; struct tool78_security sec;
@ -93,7 +93,7 @@ sec: flg=fe bot=03 fsws=0000 fswe=003f
printf("secget: 0x%02x\n", st); 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); 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); //printf("sec rel: 0x%02x\n", st);
// one block = 0x400 = 1k // one block = 0x400 = 1k
st = tool78_do_block_erase(hw, 0, -1); 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); printf("programming: 0x%02x\n", st);
st = tool78_do_verify(hw, 0, 0x3ff, datatoflash); 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) { /*for (size_t iii = 0; iii < 65536; iii += 0x400) {
st = tool78_do_verify(hw, iii+0, iii+0x3ff, &DATA_wfum_flash[iii]); st = tool78_do_verify(hw, iii+0, iii+0x3ff, &DATA_wfum_flash[iii]);

View File

@ -94,30 +94,30 @@ static void CORE1_FUNC(pcg32_fast_init)(uint64_t seed) {
} }
// ADC value is in low 12 bits of adc_read() // ADC value is in low 12 bits of adc_read()
// FIXME: length_min_us = -1 => adc breaks? | oops was signedness bug // FIXME: length_min_ns = -1 => adc breaks? | oops was signedness bug
#define CORE1_PRE_CALC() /* BIG TODO HERE! */ \ #define CORE1_PRE_CALC() /* BIG TODO HERE! */ \
bool sweep = param_cur.offset_min_us == param_cur.offset_max_us \ bool sweep = param_cur.offset_min_ns == param_cur.offset_max_ns \
&& param_cur.length_min_us >= 0; \ && param_cur.length_min_ns >= 0; \
uint32_t len, off = param_cur.offset_min_us + \ uint32_t len, off = param_cur.offset_min_ns + \
(pcg32_fast() % (param_cur.offset_max_us - param_cur.offset_min_us)), \ (pcg32_fast() % (param_cur.offset_max_ns - param_cur.offset_min_ns)), \
iom = 1u << param_cur.glitch_out_pin; \ iom = 1u << param_cur.glitch_out_pin; \
do { \ do { \
if (sweep) { \ if (sweep) { \
if (len_prev == param_cur.length_max_us) len_prev = (len = param_cur.length_min_us); \ 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 = (len_prev = (len_prev + 1));\
} else { \ } else { \
len = (param_cur.length_min_us < 0) \ len = (param_cur.length_min_ns < 0) \
? (((uint32_t)adc_read() * param_cur.length_max_us) >> 12) \ ? (((uint64_t)adc_read() * param_cur.length_max_ns) >> 12) \
: (param_cur.length_min_us + (pcg32_fast() % \ : (param_cur.length_min_ns + (pcg32_fast() % \
(param_cur.length_max_us - param_cur.length_min_us))); \ (param_cur.length_max_ns - param_cur.length_min_ns))); \
} \ } \
} while (0) \ } while (0) \
#define CORE1_DO_GLITCH() \ #define CORE1_DO_GLITCH() \
do { \ do { \
busy_wait_us_32(off); \ busy_wait_us_32(off/1000); \
sio_hw->gpio_set = iom; \ sio_hw->gpio_set = iom; \
busy_wait_us_32(len); \ busy_wait_us_32(len/1000); \
sio_hw->gpio_clr = iom; \ sio_hw->gpio_clr = iom; \
param_cur.offset_cur = off; \ param_cur.offset_cur = off; \
param_cur.length_cur = len; \ param_cur.length_cur = len; \
@ -125,7 +125,7 @@ static void CORE1_FUNC(pcg32_fast_init)(uint64_t seed) {
__attribute__((__noreturn__)) __attribute__((__noreturn__))
static void CORE1_FUNC(glitch_core1_thread_core1_fifoirq)(void) { static void CORE1_FUNC(glitch_core1_thread_core1_fifoirq)(void) {
int32_t len_prev = param_cur.length_min_us - 1; int32_t len_prev = param_cur.length_min_ns - 1;
SCB->SCR &= ~SCB_SCR_SEVONPEND_Msk; // don't resume WFE on interrupt SCB->SCR &= ~SCB_SCR_SEVONPEND_Msk; // don't resume WFE on interrupt
@ -158,7 +158,7 @@ static void CORE1_FUNC(glitch_core1_thread_core1_fifoirq)(void) {
} }
__attribute__((__noreturn__)) __attribute__((__noreturn__))
static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) { static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) {
int32_t len_prev = param_cur.length_min_us - 1; int32_t len_prev = param_cur.length_min_ns - 1;
// init gpio irq // init gpio irq
const int gpio = param_cur.trigger_in_pin; const int gpio = param_cur.trigger_in_pin;
@ -183,14 +183,16 @@ static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) {
irq_set_enabled(irq, false); irq_set_enabled(irq, false);
//CORE1_DO_GLITCH(); //CORE1_DO_GLITCH();
busy_wait_us_32(off); busy_wait_us_32(off/1000);
if (!(sio_hw->gpio_in & (1u<<gpio))) goto cont; if (!(sio_hw->gpio_in & (1u<<gpio))) goto cont;
param_cur.offset_cur = off; param_cur.offset_cur = off;
param_cur.length_cur = len; param_cur.length_cur = len;
sio_hw->gpio_set = iom; sio_hw->gpio_set = iom;
len = (len >> 4) / 3;
asm volatile( asm volatile(
// loop is 3 cycles
"1: sub %[counter], #1\n" "1: sub %[counter], #1\n"
"cmp %[counter], #0\n" //"cmp %[counter], #0\n"
"bne 1b\n" "bne 1b\n"
:[counter]"+r"(len) :[counter]"+r"(len)
:: ::
@ -204,7 +206,7 @@ static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) {
} }
__attribute__((__noreturn__)) __attribute__((__noreturn__))
static void CORE1_FUNC(glitch_core1_thread_pio)(void) { static void CORE1_FUNC(glitch_core1_thread_pio)(void) {
int32_t len_prev = param_cur.length_min_us - 1; int32_t len_prev = param_cur.length_min_ns - 1;
const int irq = (trigctl_pio == pio0) ? PIO0_IRQ_1 : PIO1_IRQ_1; const int irq = (trigctl_pio == pio0) ? PIO0_IRQ_1 : PIO1_IRQ_1;
irq_set_enabled(irq, false); irq_set_enabled(irq, false);
@ -216,7 +218,9 @@ static void CORE1_FUNC(glitch_core1_thread_pio)(void) {
while (true) { while (true) {
CORE1_PRE_CALC(); CORE1_PRE_CALC();
(void)iom; (void)iom;
trigctl_push_off_len(trigctl_pio, trigctl_sm, off, 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_wait_glitch_irq(trigctl_pio, trigctl_sm, true);
trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm); trigctl_ack_glitch_irq(trigctl_pio, trigctl_sm);
@ -292,8 +296,8 @@ static void CORE0_FUNC(glitch_stop_no_clock_chg)(void) {
bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) { bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) {
// check params values // check params values
if (params->offset_max_us < params->offset_min_us) return false; if (params->offset_max_ns < params->offset_min_ns) return false;
if (params->length_max_us < params->length_min_us) return false; if (params->length_max_ns < params->length_min_ns) return false;
if (params->trigger_in_pin < -1 || params->trigger_in_pin >= 28 if (params->trigger_in_pin < -1 || params->trigger_in_pin >= 28
|| (params->trigger_in_pin >= 23 && params->trigger_in_pin <= 25)) || (params->trigger_in_pin >= 23 && params->trigger_in_pin <= 25))
return false; return false;
@ -323,9 +327,9 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) {
// let's not care about impl and always use core1 for now // let's not care about impl and always use core1 for now
// TODO: if pio: check SM availability etc (& clear param_cur if fails) // TODO: if pio: check SM availability etc (& clear param_cur if fails)
// overclock to 200 MHz // overclock to 250 MHz
vreg_set_voltage(VREG_VOLTAGE_1_15); vreg_set_voltage(VREG_VOLTAGE_1_15);
set_sys_clock_khz(200*1000, true); set_sys_clock_khz(250*1000, true);
uint func = GPIO_FUNC_SIO; uint func = GPIO_FUNC_SIO;
if (params->impl == glitch_impl_pio) { if (params->impl == glitch_impl_pio) {
@ -333,7 +337,7 @@ bool CORE0_FUNC(glitch_ready)(const struct glitch_params* params) {
func = (trigctl_pio == pio0) ? GPIO_FUNC_PIO0 : GPIO_FUNC_PIO1; func = (trigctl_pio == pio0) ? GPIO_FUNC_PIO0 : GPIO_FUNC_PIO1;
} }
if (params->length_min_us < 0) { if (params->length_min_ns < 0) {
// FIXME: use a more generic approach (using dragonzap adc) // FIXME: use a more generic approach (using dragonzap adc)
// ADC1: ADC mode // ADC1: ADC mode

View File

@ -19,12 +19,12 @@ enum glitch_impl {
}; };
struct glitch_params { struct glitch_params {
uint32_t offset_min_us; uint32_t offset_min_ns;
uint32_t offset_max_us; uint32_t offset_max_ns;
// FIXME: use a more generic approach (using dragonzap adc) // FIXME: use a more generic approach (using dragonzap adc)
// for using user-tunable lengths (with physical knobs) // for using user-tunable lengths (with physical knobs)
int32_t length_min_us; int32_t length_min_ns;
int32_t length_max_us; int32_t length_max_ns;
int trigger_in_pin; // use -1 for a signal coming from core 0 int trigger_in_pin; // use -1 for a signal coming from core 0
int glitch_out_pin; int glitch_out_pin;
enum glitch_polarity trigger_in_polarity; enum glitch_polarity trigger_in_polarity;

View File

@ -31,6 +31,9 @@ lenloop:
irq set 0 rel irq set 0 rel
public wait2:
wait 0 pin 0 ; or "nop"
% c-sdk { % c-sdk {
enum trigctl_source { enum trigctl_source {
@ -47,9 +50,13 @@ static inline void trigctl_pio_init(PIO pio, uint sm, uint prog_offs,
if (trigsrc == trig_source_irq) { if (trigsrc == trig_source_irq) {
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] = pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
pio_encode_wait_irq(true, true, 1); pio_encode_wait_irq(true, true, 1);
pio->instr_mem[prog_offs + trigctl_offset_wait2] =
pio_encode_nop();
} else { } else {
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] = pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
pio_encode_wait_pin(true, 0); pio_encode_wait_pin(true, 0);
pio->instr_mem[prog_offs + trigctl_offset_wait2] =
pio_encode_wait_pin(false, 0);
} }
pio_sm_config c = trigctl_program_get_default_config(prog_offs); pio_sm_config c = trigctl_program_get_default_config(prog_offs);
@ -58,6 +65,12 @@ static inline void trigctl_pio_init(PIO pio, uint sm, uint prog_offs,
sm_config_set_out_shift(&c, false, true, 32); sm_config_set_out_shift(&c, false, true, 32);
sm_config_set_in_shift(&c, false, true, 32); sm_config_set_in_shift(&c, false, true, 32);
sm_config_set_clkdiv(&c, 1); sm_config_set_clkdiv(&c, 1);
if (trigsrc == trig_source_irq) {
sm_config_set_wrap(&c, prog_offs + trigctl_wrap_target,
prog_offs + trigctl_wrap - 1);
}
pio_sm_init(pio, sm, prog_offs, &c); pio_sm_init(pio, sm, prog_offs, &c);
pio_sm_set_consecutive_pindirs(pio, sm, glitch_pin, 1, true ); pio_sm_set_consecutive_pindirs(pio, sm, glitch_pin, 1, true );
@ -73,7 +86,7 @@ static inline void trigctl_pio_init(PIO pio, uint sm, uint prog_offs,
static inline void trigctl_wait_glitch_irq(PIO pio, uint sm, bool use_wfi) { static inline void trigctl_wait_glitch_irq(PIO pio, uint sm, bool use_wfi) {
uint mask = 1u << ((sm + 0) & 3); uint mask = 1u << ((sm + 0) & 3);
if (use_wfi) { if (use_wfi) {
while (!(pio->irq & mask)) __WFI(); while (!(pio->irq & mask)) __WFE();
} else { } else {
while (!(pio->irq & mask)) ; while (!(pio->irq & mask)) ;
} }
@ -81,7 +94,7 @@ static inline void trigctl_wait_glitch_irq(PIO pio, uint sm, bool use_wfi) {
static inline void trigctl_ack_glitch_irq(PIO pio, uint sm) { static inline void trigctl_ack_glitch_irq(PIO pio, uint sm) {
hw_set_bits(&pio->irq, 1 << ((sm + 0) & 3)); hw_set_bits(&pio->irq, 1 << ((sm + 0) & 3));
} }
// nvic_irqno: corresponding NVIC IRQ will be PIO${pio}_IRQ${nvic_irqno} // nvic_irqno: corresponding NVIC IRQ will be PIO${pio}_IRQ_${nvic_irqno}
static inline void trigctl_set_glitch_irq_enabled(PIO pio, uint sm, uint nvic_irqno, bool en) { static inline void trigctl_set_glitch_irq_enabled(PIO pio, uint sm, uint nvic_irqno, bool en) {
pio_set_irqn_source_enabled(pio, nvic_irqno, (sm + 0) & 3, en); pio_set_irqn_source_enabled(pio, nvic_irqno, (sm + 0) & 3, en);
} }