dragonzap: firmware code

This commit is contained in:
Triss 2022-04-02 03:45:47 +02:00
parent 76fb6a0ba6
commit 18a0277284
18 changed files with 563 additions and 2 deletions

View File

@ -52,6 +52,13 @@ if(FAMILY STREQUAL "rp2040")
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/msp430.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/msp430.c
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/rl78.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/rl78.c
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/rl78-glitch.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/rl78-glitch.c
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/dragonzap.c
${CMAKE_CURRENT_SOURCE_DIR}/src/zap/zap_adc.c
${CMAKE_CURRENT_SOURCE_DIR}/src/zap/zap_crowbar.c
${CMAKE_CURRENT_SOURCE_DIR}/src/zap/zap_dac.c
${CMAKE_CURRENT_SOURCE_DIR}/src/zap/zap_gpio.c
${CMAKE_CURRENT_SOURCE_DIR}/src/zap/zap_max4619.c
${CMAKE_CURRENT_SOURCE_DIR}/src/zap/zap_picoemp.c
) )
# Example include # Example include
@ -63,6 +70,7 @@ if(FAMILY STREQUAL "rp2040")
${CMAKE_CURRENT_SOURCE_DIR}/src/test/ ${CMAKE_CURRENT_SOURCE_DIR}/src/test/
${CMAKE_CURRENT_SOURCE_DIR}/src/glitch/ ${CMAKE_CURRENT_SOURCE_DIR}/src/glitch/
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/ ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/
${CMAKE_CURRENT_SOURCE_DIR}/src/zap/
) )
# Example defines # Example defines
@ -70,7 +78,8 @@ if(FAMILY STREQUAL "rp2040")
) )
target_link_libraries(${PROJECT} pico_stdlib pico_unique_id hardware_adc target_link_libraries(${PROJECT} pico_stdlib pico_unique_id hardware_adc
hardware_pio hardware_dma hardware_pwm cmsis_core pico_multicore) hardware_pio hardware_dma hardware_pwm cmsis_core pico_multicore
hardware_spi)
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/sbw.pio) pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/sbw.pio)
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/swim/swim.pio) pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/swim/swim.pio)

View File

@ -18,6 +18,7 @@
void piotest(void); void piotest(void);
void delaytest(void); void delaytest(void);
void piodump_main(void); void piodump_main(void);
void cli_dragonzap_test(void);
void cli_msp430_phy(void); void cli_msp430_phy(void);
void cli_msp430_conn(void); void cli_msp430_conn(void);
@ -75,6 +76,8 @@ static struct cli_cmd cmds[] = {
{ "g78param", cli_tool78_glitch_paramsearch }, { "g78param", cli_tool78_glitch_paramsearch },
{ "g78ocd", cli_tool78_glitch_ocd_dump }, { "g78ocd", cli_tool78_glitch_ocd_dump },
{ "zap", cli_dragonzap_test },
{ NULL, NULL } // final { NULL, NULL } // final
}; };

59
src/cli/dragonzap.c Normal file
View File

@ -0,0 +1,59 @@
#include <stdio.h>
#include <string.h>
#include <pico/time.h>
#include "zap.h"
void cli_dragonzap_test(void);
void cli_dragonzap_test(void) {
// TODO: test:
// * ADC0,1,2 input
// -> ADC0,1: OK
// -> ADC2: ≃0xB80 is 5.04V; not ≃0xC38?
// 2.48V measured at ADC2 pin...
// * DAC control
// * MAX4619 control (enable, switch)
// * crowbar 1,2 control
// * NXS0108 functionality
zap_init_default();
zap_dac_set_enable(zap_dac_a | zap_dac_b);
zap_dac_set_mulx2(zap_dac_a | zap_dac_b);
sio_hw->gpio_oe_set = ZAP_GPIO_MASK;
sio_hw->gpio_clr = ZAP_GPIO_MASK;
for (int i = ZAP_GPIO_BASE; i <= ZAP_GPIO_END; ++i) {
gpio_set_function(i, GPIO_FUNC_SIO);
}
while (true) {
uint16_t adcv[3];
for (int i = 0; i < 3; ++i) {
adcv[i] = zap_adc_read(i);
}
uint32_t vbus = zap_adc_get_vbus();
float vbusf = vbus / (float)0x10000;
printf("ADC: 0x%04x, 0x%04x, 0x%04x = %.2f\n", adcv[0], adcv[1], adcv[2], vbusf);
zap_dac_set_a(adcv[0]);
zap_dac_set_b(adcv[1]);
zap_dac_latch();
zap_crowbar_a_act();
zap_crowbar_b_act();
zap_max_put(true);
sio_hw->gpio_togl = 0x80;
busy_wait_ms(1000);
zap_crowbar_a_hiz();
zap_crowbar_b_hiz();
zap_max_put(false);
sio_hw->gpio_togl = 0x80;
busy_wait_ms(1000);
}
}

View File

@ -149,7 +149,7 @@ void cli_msp430_flash(void) {
printf("flashing text...\n"); printf("flashing text...\n");
for (size_t i = 0; i < 0x24; ++i) { for (size_t i = 0; i < 0x24; ++i) {
printf("%zu : %04x\n", DATA_text[i]); printf("%zu : %04x\n", i, DATA_text[i]);
msp430_flash_write(0xf800 + (i*2), 1, &DATA_text[i]); msp430_flash_write(0xf800 + (i*2), 1, &DATA_text[i]);
} }
printf("flashing vectors...\n"); printf("flashing vectors...\n");

37
src/zap/zap.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef ZAP_H_
#define ZAP_H_
#include "zap_pinout.h"
#include "zap_adc.h"
#include "zap_crowbar.h"
#include "zap_dac.h"
#include "zap_gpio.h"
#include "zap_max4619.h"
#include "zap_picoemp.h"
enum zap_component {
zap_adc = 1,
zap_crowbar = 2,
zap_dac = 4,
zap_gpio = 8,
zap_max4619 = 16,
zap_picoemp = 32
};
static inline void zap_init(enum zap_component zc) {
if (zc & zap_adc) zap_adc_init();
if (zc & zap_crowbar) zap_crowbar_init();
if (zc & zap_dac) zap_dac_init();
if (zc & zap_gpio) zap_gpio_init(false, true);
if (zc & zap_max4619) zap_max_init(false);
if (zc & zap_picoemp) zap_picoemp_init();
}
static inline void zap_init_default(void) {
zap_init(zap_adc | zap_crowbar | zap_dac | zap_gpio | zap_max4619);
}
#endif

24
src/zap/zap_adc.c Normal file
View File

@ -0,0 +1,24 @@
#include <stdint.h>
#include <hardware/adc.h>
#include "zap_pinout.h"
#include "zap_adc.h"
void zap_adc_init(void) {
adc_init();
adc_gpio_init(ZAP_ADC_A);
adc_gpio_init(ZAP_ADC_B);
adc_gpio_init(ZAP_ADC_REF);
}
uint16_t zap_adc_read(int idx) {
if (idx < 0 || idx >= 3) return 0xf000;
adc_select_input(idx);
return adc_read();
}

31
src/zap/zap_adc.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef ZAP_ADC_H_
#define ZAP_ADC_H_
#include <stdint.h>
void zap_adc_init(void);
uint16_t zap_adc_read(int idx);
static inline uint16_t zap_adc_read_a(void) { return zap_adc_read(0); }
static inline uint16_t zap_adc_read_b(void) { return zap_adc_read(1); }
// returns Vbus value in 16.16 fixed-point format
//
// sadly uuuh in practice it's 'a bit' noisy, assuming Vbus = 5V is
// often more reliable than hand-tuning with this value, due to ADC
// inaccuracies, mismatch between R500 and R501, and so on...
static inline uint32_t zap_adc_get_vbus(void) {
// Vbus value, 0x0fff = 3V3
// (ADC2 value is Vbus divided down by 2)
uint32_t vbus = (zap_adc_read(2) + 0x57/*hacky offset correction*/) * 2;
// shouldn't overflow
uint32_t vbusf = (vbus * (uint32_t)(3.3f * 0x10000)) / 0xfff;
return vbusf;
}
#endif

18
src/zap/zap_crowbar.c Normal file
View File

@ -0,0 +1,18 @@
#include "zap_crowbar.h"
void zap_crowbar_init(void) {
const io_rw_32 pinmask = (1u << ZAP_CROWBAR_1) | (1u << ZAP_CROWBAR_2);
sio_hw->gpio_clr = pinmask; // default to low -> hiZ by default
sio_hw->gpio_oe_set = pinmask;
gpio_set_slew_rate(ZAP_CROWBAR_1, GPIO_SLEW_RATE_FAST);
gpio_set_slew_rate(ZAP_CROWBAR_2, GPIO_SLEW_RATE_FAST);
gpio_set_drive_strength(ZAP_CROWBAR_1, GPIO_DRIVE_STRENGTH_12MA);
gpio_set_drive_strength(ZAP_CROWBAR_2, GPIO_DRIVE_STRENGTH_12MA);
gpio_set_function(ZAP_CROWBAR_1, GPIO_FUNC_SIO);
gpio_set_function(ZAP_CROWBAR_2, GPIO_FUNC_SIO);
}

19
src/zap/zap_crowbar.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef ZAP_CROWBAR_H_
#define ZAP_CROWBAR_H_
#include <hardware/structs/iobank0.h>
#include <hardware/gpio.h>
#include "zap_pinout.h"
void zap_crowbar_init(void);
static inline void zap_crowbar_a_act(void) { sio_hw->gpio_set = 1u << ZAP_CROWBAR_1; }
static inline void zap_crowbar_a_hiz(void) { sio_hw->gpio_clr = 1u << ZAP_CROWBAR_1; }
static inline void zap_crowbar_b_act(void) { sio_hw->gpio_set = 1u << ZAP_CROWBAR_2; }
static inline void zap_crowbar_b_hiz(void) { sio_hw->gpio_clr = 1u << ZAP_CROWBAR_2; }
#endif

93
src/zap/zap_dac.c Normal file
View File

@ -0,0 +1,93 @@
#include <stdint.h>
#include <stdbool.h>
#include <hardware/structs/iobank0.h>
#include <hardware/gpio.h>
#include <hardware/spi.h>
#include "zap_pinout.h"
#include "zap_dac.h"
static enum zap_dac_ch gain, enable;
static uint16_t va, vb;
void zap_dac_init(void) {
spi_init(ZAP_DAC_SPI, 1*1000*1000); // TODO: can we go higher?
spi_set_format(ZAP_DAC_SPI, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_put(ZAP_DAC_NLATCH, true);
gpio_put(ZAP_DAC_CS , true);
gpio_set_dir(ZAP_DAC_NLATCH, GPIO_OUT);
gpio_set_dir(ZAP_DAC_CS , GPIO_OUT);
gpio_set_function(ZAP_DAC_SCLK , GPIO_FUNC_SPI);
gpio_set_function(ZAP_DAC_TX , GPIO_FUNC_SPI);
gpio_set_function(ZAP_DAC_NLATCH, GPIO_FUNC_SIO);
gpio_set_function(ZAP_DAC_CS , GPIO_FUNC_SIO);
enable = 0;
gain = 3; // 1x for both
va = 0x0fff;
vb = 0x0800;
}
static void zap_flush(enum zap_dac_ch ch) {
if (ch & zap_dac_a) {
uint16_t v = va;
v |= 0x8000*0; // channel A
if (gain & zap_dac_a) v |= 0x2000;
if (enable & zap_dac_a) v |= 0x1000;
sio_hw->gpio_clr = 1u << ZAP_DAC_CS;
busy_wait_us_32(10); // TODO: better timing
spi_write16_blocking(ZAP_DAC_SPI, &v, 1);
busy_wait_us_32(10);
sio_hw->gpio_set = (1u << ZAP_DAC_CS);
}
if (ch & zap_dac_b) {
uint16_t v = vb;
v |= 0x8000*1; // channel B
if (gain & zap_dac_b) v |= 0x2000;
if (enable & zap_dac_b) v |= 0x1000;
sio_hw->gpio_clr = 1u << ZAP_DAC_CS;
busy_wait_us_32(10); // TODO: better timing
spi_write16_blocking(ZAP_DAC_SPI, &v, 1);
busy_wait_us_32(10);
sio_hw->gpio_set = (1u << ZAP_DAC_CS);
}
}
enum zap_dac_ch zap_dac_get_enable(void) { return enable; }
enum zap_dac_ch zap_dac_get_mulx2(void) { return ~gain & 3; }
void zap_dac_set_enable(enum zap_dac_ch chen) {
enum zap_dac_ch change = chen ^ enable;
enable = chen;
zap_flush(change);
}
void zap_dac_set_mulx2(enum zap_dac_ch ch_x2) { gain = ~ch_x2 & 3; }
uint16_t zap_dac_get_a(void) { return va; }
uint16_t zap_dac_get_b(void) { return vb; }
void zap_dac_set_a(uint16_t a) {
va = a & 0x0fff;
zap_flush(zap_dac_a);
}
void zap_dac_set_b(uint16_t b) {
vb = b & 0x0fff;
zap_flush(zap_dac_b);
}
void zap_dac_latch(void) {
busy_wait_us_32(10); // TODO: better timing
sio_hw->gpio_clr = 1u << ZAP_DAC_NLATCH;
busy_wait_us_32(10);
sio_hw->gpio_set = 1u << ZAP_DAC_NLATCH;
}

32
src/zap/zap_dac.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef ZAP_DAC_H_
#define ZAP_DAC_H_
#include <stdint.h>
#include <stdbool.h>
enum zap_dac_ch {
zap_dac_a = 1,
zap_dac_b = 2
};
void zap_dac_init(void);
enum zap_dac_ch zap_dac_get_enable(void);
void zap_dac_set_enable(enum zap_dac_ch ch);
enum zap_dac_ch zap_dac_get_mulx2(void);
void zap_dac_set_mulx2(enum zap_dac_ch ch_x2);
uint16_t zap_dac_get_a(void);
uint16_t zap_dac_get_b(void);
void zap_dac_set_a(uint16_t a);
void zap_dac_set_b(uint16_t b);
static inline void zap_dac_set(uint16_t a, uint16_t b) {
zap_dac_set_a(a);
zap_dac_set_b(b);
}
void zap_dac_latch(void);
#endif

25
src/zap/zap_gpio.c Normal file
View File

@ -0,0 +1,25 @@
#include <stdbool.h>
#include <hardware/structs/iobank0.h>
#include <hardware/gpio.h>
#include "zap_pinout.h"
#include "zap_gpio.h"
void zap_gpio_init(bool init_pins_as_gpio, bool enable) {
gpio_put(ZAP_GPIO_ENABLE, enable);
gpio_set_dir(ZAP_GPIO_ENABLE, GPIO_OUT);
gpio_set_function(ZAP_GPIO_ENABLE, GPIO_FUNC_SIO);
if (init_pins_as_gpio) {
// don't use them as output yet
sio_hw->gpio_oe_clr = ZAP_GPIO_MASK;
for (int i = ZAP_GPIO_BASE; i <= ZAP_GPIO_END; ++i) {
gpio_set_pulls(i, false, false);
gpio_set_function(i, GPIO_FUNC_SIO);
}
}
}

19
src/zap/zap_gpio.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef ZAP_GPIO_H_
#define ZAP_GPIO_H_
#include <stdbool.h>
#include <hardware/structs/iobank0.h>
#include "zap_pinout.h"
void zap_gpio_init(bool init_pins_as_gpio, bool enable);
static inline void zap_gpio_set_en(bool enable) {
if (enable) sio_hw->gpio_set = 1u << ZAP_GPIO_ENABLE;
else sio_hw->gpio_clr = 1u << ZAP_GPIO_ENABLE;
}
#endif

26
src/zap/zap_max4619.c Normal file
View File

@ -0,0 +1,26 @@
#include <stdbool.h>
#include <hardware/structs/iobank0.h>
#include <hardware/gpio.h>
#include "zap_pinout.h"
#include "zap_max4619.h"
void zap_max_init(bool inhibit) {
const io_rw_32 pinmask = 1u << ZAP_GLITCH_OUT;
sio_hw->gpio_clr = pinmask; // default to low -> JP300
sio_hw->gpio_oe_set = pinmask;
gpio_set_slew_rate(ZAP_GLITCH_OUT, GPIO_SLEW_RATE_FAST);
gpio_set_drive_strength(ZAP_GLITCH_OUT, GPIO_DRIVE_STRENGTH_12MA);
gpio_set_function(ZAP_GLITCH_OUT, GPIO_FUNC_SIO);
gpio_put(ZAP_MAX_INHIBIT, inhibit);
gpio_set_dir(ZAP_MAX_INHIBIT, GPIO_OUT);
gpio_set_function(ZAP_MAX_INHIBIT, GPIO_FUNC_SIO);
}

24
src/zap/zap_max4619.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef ZAP_MAX4619_H_
#define ZAP_MAX4619_H_
#include <stdbool.h>
#include <hardware/structs/iobank0.h>
#include "zap_pinout.h"
void zap_max_init(bool inhibit);
static inline void zap_max_set_inhibit(bool inhibit) {
if (inhibit) sio_hw->gpio_set = 1u << ZAP_MAX_INHIBIT;
else sio_hw->gpio_clr = 1u << ZAP_MAX_INHIBIT;
}
static inline void zap_max_put(bool low) {
if (low) sio_hw->gpio_set = 1u << ZAP_GLITCH_OUT;
else sio_hw->gpio_clr = 1u << ZAP_GLITCH_OUT;
}
#endif

93
src/zap/zap_picoemp.c Normal file
View File

@ -0,0 +1,93 @@
// code partly from https://github.com/newaetech/chipshouter-picoemp/tree/main/firmware/c
#include <stdint.h>
#include <stdbool.h>
#include <hardware/structs/iobank0.h>
#include <hardware/clocks.h>
#include <hardware/gpio.h>
#include <hardware/pwm.h>
#include <pico/time.h>
#include "zap_pinout.h"
#include "zap_picoemp.h"
static bool armed;
void zap_picoemp_init(void) {
gpio_put(ZAP_PICOEMP_HVP, false);
gpio_set_dir(ZAP_PICOEMP_HVP, GPIO_OUT);
gpio_set_pulls(ZAP_PICOEMP_HVP, false, false);
gpio_set_drive_strength(ZAP_PICOEMP_HVP, GPIO_DRIVE_STRENGTH_12MA);
gpio_set_slew_rate(ZAP_PICOEMP_HVP, GPIO_SLEW_RATE_FAST);
gpio_set_function(ZAP_PICOEMP_HVP, GPIO_FUNC_SIO);
gpio_set_dir(ZAP_PICOEMP_CHG, GPIO_IN);
gpio_set_pulls(ZAP_PICOEMP_CHG, false, false);
gpio_set_inover(ZAP_PICOEMP_CHG, GPIO_OVERRIDE_INVERT);
gpio_set_function(ZAP_PICOEMP_CHG, GPIO_FUNC_SIO);
zap_picoemp_set_armed(false);
}
bool zap_picoemp_get_armed(void) { return armed; }
static uint32_t pwm_set_freq_duty(uint slice_num, uint chan, uint32_t f, float d) {
uint32_t clock = clock_get_hz(clk_sys);
uint32_t div16 = clock / f / 4096 + (clock % (f * 4096) != 0);
if (div16 / 16 == 0) div16 = 16;
uint32_t wrap = clock * 16 / div16 / f - 1;
pwm_set_clkdiv_int_frac(slice_num, div16/16, div16 & 0xf);
pwm_set_wrap(slice_num, wrap);
pwm_set_chan_level(slice_num, chan, (int)((float)wrap * d));
return wrap;
}
void zap_picoemp_set_armed(bool arm) {
if (arm) {
if (armed) return;
uint32_t slice = pwm_gpio_to_slice_num(ZAP_PICOEMP_PWM);
uint32_t chan = pwm_gpio_to_channel(ZAP_PICOEMP_PWM);
float tar_freq = 25;
float div = clock_get_hz(clk_sys) / tar_freq;
pwm_config cfg = pwm_get_default_config();
pwm_config_set_clkdiv(&cfg, div);
pwm_config_set_wrap(&cfg, UINT16_MAX);
pwm_init(slice, &cfg, false);
pwm_set_chan_level(slice, chan, 800);
pwm_set_freq_duty(slice, chan, 2500, 0.0122);
pwm_set_enabled(slice, true);
gpio_set_function(ZAP_PICOEMP_PWM, GPIO_FUNC_PWM);
armed = arm;
} else {
armed = false;
gpio_set_dir(ZAP_PICOEMP_PWM, GPIO_OUT);
gpio_put(ZAP_PICOEMP_PWM, false);
gpio_set_function(ZAP_PICOEMP_PWM, GPIO_FUNC_SIO);
}
}
void zap_picoemp_pulse(void) {
gpio_put(ZAP_PICOEMP_HVP, true);
busy_wait_us_32(5);
gpio_put(ZAP_PICOEMP_HVP, false);
busy_wait_us_32(5);
gpio_put(ZAP_PICOEMP_HVP, true);
busy_wait_us_32(5);
gpio_put(ZAP_PICOEMP_HVP, false);
busy_wait_ms(250);
}

17
src/zap/zap_picoemp.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef ZAP_PICOEMP_H_
#define ZAP_PICOEMP_H_
#include <stdint.h>
#include <stdbool.h>
void zap_picoemp_init(void);
bool zap_picoemp_get_armed(void);
void zap_picoemp_set_armed(bool arm);
uint16_t zap_picoemp_chg_get(void);
void zap_picoemp_pulse(void);
#endif

32
src/zap/zap_pinout.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef ZAP_PINOUT_H_
#define ZAP_PINOUT_H_
#define ZAP_GPIO_BASE 0
#define ZAP_GPIO_END 7
#define ZAP_GPIO_MASK 0xff
#define ZAP_TRIG_IN 10
#define ZAP_GLITCH_OUT 11
#define ZAP_CROWBAR_1 12
#define ZAP_CROWBAR_2 13
#define ZAP_MAX_INHIBIT 16
#define ZAP_GPIO_ENABLE 22
#define ZAP_DAC_SPI spi0
#define ZAP_DAC_NLATCH 17
#define ZAP_DAC_SCLK 18
#define ZAP_DAC_TX 19
#define ZAP_DAC_CS 20
#define ZAP_ADC_A 26
#define ZAP_ADC_B 27
#define ZAP_ADC_REF 28
#define ZAP_PICOEMP_PWM 14
#define ZAP_PICOEMP_CHG 15
#define ZAP_PICOEMP_HVP ZAP_GLITCH_OUT
#endif