PIO-based glitch control now also works in practice
This commit is contained in:
parent
d3654f1762
commit
376a6bce7b
|
@ -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);
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue