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) {
|
||||
// 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_us = 10,
|
||||
.offset_max_us = 35433,
|
||||
.offset_min_ns = 10*1000,
|
||||
.offset_max_ns = 35433*1000,
|
||||
// with REGC & 10uF Vcc:
|
||||
.length_min_us = -1,//10,//-1,//20,
|
||||
.length_max_us = 100,//*8,
|
||||
.length_min_ns = -1,//10,//-1,//20,
|
||||
.length_max_ns = 10000,//*8,
|
||||
// with REGC:
|
||||
/*.length_min_us = 4000,
|
||||
.length_max_us = 6300,*/
|
||||
|
@ -68,7 +68,7 @@ static void glitch_init_core1_stuff(bool exttrig) {
|
|||
.glitch_out_pin = GLITCH_OUT_PIN,
|
||||
.trigger_in_polarity = glitch_positive,
|
||||
.glitch_out_polarity = glitch_positive,
|
||||
.impl = glitch_impl_core1,
|
||||
.impl = glitch_impl_pio,//core1,
|
||||
.offset_cur = 0, .length_cur = 0
|
||||
};
|
||||
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
|
||||
struct tool78_security sec;
|
||||
|
@ -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]);
|
||||
|
|
|
@ -94,30 +94,30 @@ static void CORE1_FUNC(pcg32_fast_init)(uint64_t seed) {
|
|||
}
|
||||
|
||||
// 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! */ \
|
||||
bool sweep = param_cur.offset_min_us == param_cur.offset_max_us \
|
||||
&& param_cur.length_min_us >= 0; \
|
||||
uint32_t len, off = param_cur.offset_min_us + \
|
||||
(pcg32_fast() % (param_cur.offset_max_us - param_cur.offset_min_us)), \
|
||||
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_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 = (param_cur.length_min_us < 0) \
|
||||
? (((uint32_t)adc_read() * param_cur.length_max_us) >> 12) \
|
||||
: (param_cur.length_min_us + (pcg32_fast() % \
|
||||
(param_cur.length_max_us - param_cur.length_min_us))); \
|
||||
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_DO_GLITCH() \
|
||||
do { \
|
||||
busy_wait_us_32(off); \
|
||||
busy_wait_us_32(off/1000); \
|
||||
sio_hw->gpio_set = iom; \
|
||||
busy_wait_us_32(len); \
|
||||
busy_wait_us_32(len/1000); \
|
||||
sio_hw->gpio_clr = iom; \
|
||||
param_cur.offset_cur = off; \
|
||||
param_cur.length_cur = len; \
|
||||
|
@ -125,7 +125,7 @@ static void CORE1_FUNC(pcg32_fast_init)(uint64_t seed) {
|
|||
|
||||
__attribute__((__noreturn__))
|
||||
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
|
||||
|
||||
|
@ -158,7 +158,7 @@ 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_us - 1;
|
||||
int32_t len_prev = param_cur.length_min_ns - 1;
|
||||
|
||||
// init gpio irq
|
||||
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);
|
||||
//CORE1_DO_GLITCH();
|
||||
busy_wait_us_32(off);
|
||||
busy_wait_us_32(off/1000);
|
||||
if (!(sio_hw->gpio_in & (1u<<gpio))) goto cont;
|
||||
param_cur.offset_cur = off;
|
||||
param_cur.length_cur = len;
|
||||
sio_hw->gpio_set = iom;
|
||||
len = (len >> 4) / 3;
|
||||
asm volatile(
|
||||
// loop is 3 cycles
|
||||
"1: sub %[counter], #1\n"
|
||||
"cmp %[counter], #0\n"
|
||||
//"cmp %[counter], #0\n"
|
||||
"bne 1b\n"
|
||||
:[counter]"+r"(len)
|
||||
::
|
||||
|
@ -204,7 +206,7 @@ static void CORE1_FUNC(glitch_core1_thread_core1_gpio)(void) {
|
|||
}
|
||||
__attribute__((__noreturn__))
|
||||
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;
|
||||
irq_set_enabled(irq, false);
|
||||
|
@ -216,7 +218,9 @@ static void CORE1_FUNC(glitch_core1_thread_pio)(void) {
|
|||
while (true) {
|
||||
CORE1_PRE_CALC();
|
||||
(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_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) {
|
||||
// check params values
|
||||
if (params->offset_max_us < params->offset_min_us) return false;
|
||||
if (params->length_max_us < params->length_min_us) return false;
|
||||
if (params->offset_max_ns < params->offset_min_ns) return false;
|
||||
if (params->length_max_ns < params->length_min_ns) 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;
|
||||
|
@ -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
|
||||
// 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);
|
||||
set_sys_clock_khz(200*1000, true);
|
||||
set_sys_clock_khz(250*1000, true);
|
||||
|
||||
uint func = GPIO_FUNC_SIO;
|
||||
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;
|
||||
}
|
||||
|
||||
if (params->length_min_us < 0) {
|
||||
if (params->length_min_ns < 0) {
|
||||
// FIXME: use a more generic approach (using dragonzap adc)
|
||||
|
||||
// ADC1: ADC mode
|
||||
|
|
|
@ -19,12 +19,12 @@ enum glitch_impl {
|
|||
};
|
||||
|
||||
struct glitch_params {
|
||||
uint32_t offset_min_us;
|
||||
uint32_t offset_max_us;
|
||||
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_us;
|
||||
int32_t length_max_us;
|
||||
int32_t length_min_ns;
|
||||
int32_t length_max_ns;
|
||||
int trigger_in_pin; // use -1 for a signal coming from core 0
|
||||
int glitch_out_pin;
|
||||
enum glitch_polarity trigger_in_polarity;
|
||||
|
|
|
@ -31,6 +31,9 @@ lenloop:
|
|||
|
||||
irq set 0 rel
|
||||
|
||||
public wait2:
|
||||
wait 0 pin 0 ; or "nop"
|
||||
|
||||
% c-sdk {
|
||||
|
||||
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) {
|
||||
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
|
||||
pio_encode_wait_irq(true, true, 1);
|
||||
pio->instr_mem[prog_offs + trigctl_offset_wait2] =
|
||||
pio_encode_nop();
|
||||
} else {
|
||||
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
|
||||
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);
|
||||
|
@ -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_in_shift(&c, false, true, 32);
|
||||
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_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) {
|
||||
uint mask = 1u << ((sm + 0) & 3);
|
||||
if (use_wfi) {
|
||||
while (!(pio->irq & mask)) __WFI();
|
||||
while (!(pio->irq & mask)) __WFE();
|
||||
} else {
|
||||
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) {
|
||||
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) {
|
||||
pio_set_irqn_source_enabled(pio, nvic_irqno, (sm + 0) & 3, en);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue