From 989785e06b05b4fd44c3d736961a8a3be30b2833 Mon Sep 17 00:00:00 2001 From: sys64738 Date: Thu, 30 Jun 2022 02:52:17 +0200 Subject: [PATCH] 78k0 and SWIM stuff that doesn't work --- CMakeLists.txt | 3 + src/bsp/breadboard.h | 3 +- src/bsp/pinout.h | 10 +- src/cli/78k0.c | 26 +++ src/cli/cli.c | 10 ++ src/cli/rl78-glitch.c | 94 +++++------ src/cli/swim.c | 45 ++++++ src/swim/swim.pio | 66 ++++---- src/swim/swim_cmd.c | 39 +++++ src/swim/swim_cmd.h | 19 +++ src/swim/swim_hw.c | 252 +++++++++++++++++++++++++----- src/swim/swim_hw.h | 4 + src/tool78/tool78_cmds.c | 2 + src/tool78/tool78_hw_78k0_uart2.c | 4 +- src/tool78/tool78_hw_helpers.c | 4 +- 15 files changed, 460 insertions(+), 121 deletions(-) create mode 100644 src/cli/78k0.c create mode 100644 src/cli/swim.c create mode 100644 src/swim/swim_cmd.c create mode 100644 src/swim/swim_cmd.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ef1fb9..8ad0034 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ if(FAMILY STREQUAL "rp2040") ${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/tap.c ${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/msp430dbg.c ${CMAKE_CURRENT_SOURCE_DIR}/src/swim/swim_hw.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/swim/swim_cmd.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_helpers.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_test_uart2.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_78k0_spi.c @@ -51,6 +52,8 @@ if(FAMILY STREQUAL "rp2040") ${CMAKE_CURRENT_SOURCE_DIR}/src/glitch/glitch.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/cli.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/msp430.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/swim.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/78k0.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/rl78.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/rl78-glitch.c ${CMAKE_CURRENT_SOURCE_DIR}/src/cli/dragonzap.c diff --git a/src/bsp/breadboard.h b/src/bsp/breadboard.h index aae5e9c..b81675c 100644 --- a/src/bsp/breadboard.h +++ b/src/bsp/breadboard.h @@ -10,7 +10,8 @@ #define BREADBOARD_SBW_TDIO 9 #define BREADBOARD_SWIM_PIO pio0 -#define BREADBOARD_SWIM_PIN 22 +#define BREADBOARD_SWIM_PIN /*22*/16 +#define BREADBOARD_SWIM_nRESET 21 #define BREADBOARD_TOOL78_PIO pio1 diff --git a/src/bsp/pinout.h b/src/bsp/pinout.h index 9837c77..0a61ab3 100644 --- a/src/bsp/pinout.h +++ b/src/bsp/pinout.h @@ -5,7 +5,7 @@ #include "breadboard.h" #include "zap.h" -#define PINOUT_USE_DRAGONZAP 1 +#define PINOUT_USE_DRAGONZAP 0 #if PINOUT_USE_DRAGONZAP @@ -18,7 +18,8 @@ #define PINOUT_SBW_TDIO (ZAP_GPIO_BASE+1) #define PINOUT_SWIM_PIO BREADBOARD_SWIM_PIO -#define PINOUT_SWIM ZAP_GPIO_BASE +#define PINOUT_SWIM (ZAP_GPIO_BASE+1) +#define PINOUT_SWIM_nRESET (ZAP_GPIO_BASE+0) #define PINOUT_TOOL78_PIO BREADBOARD_TOOL78_PIO @@ -49,8 +50,9 @@ inline static void bsp_init_stuff(void) { #define PINOUT_SBW_TCK BREADBOARD_SBW_TCK #define PINOUT_SBW_TDIO BREADBOARD_SBW_TDIO -#define PINOUT_SWIM_PIO BREADBOARD_SWIM_PIO -#define PINOUT_SWIM BREADBOARD_SWIM_PIN +#define PINOUT_SWIM_PIO BREADBOARD_SWIM_PIO +#define PINOUT_SWIM_nRESET BREADBOARD_SWIM_nRESET +#define PINOUT_SWIM BREADBOARD_SWIM_PIN #define PINOUT_TOOL78_PIO BREADBOARD_TOOL78_PIO diff --git a/src/cli/78k0.c b/src/cli/78k0.c new file mode 100644 index 0000000..95935b6 --- /dev/null +++ b/src/cli/78k0.c @@ -0,0 +1,26 @@ + +#include +#include +#include + +#include "tool78_hw.h" +#include "tool78_cmds.h" + +/*#include "wfum-flash.h"*/ + +void cli_tool78_proto78k0(void); + +void cli_tool78_proto78k0(void) { + struct tool78_hw* hw = &tool78_hw_78k0_uart2; + + tool78_silicon_sig_t sig; + memset(&sig, 0, sizeof sig); + enum tool78_stat st = tool78_init_sfp(hw, &sig); + printf("result: 0x%02x. sig:\n", st); + for (size_t i = 0; i < sizeof(struct tool78_silicon_sig_78k0); ++i) + printf("0x%02x ", ((const uint8_t*)&sig)[i]); + printf("%c", '\n'); + + hw->deinit(); +} + diff --git a/src/cli/cli.c b/src/cli/cli.c index feabbd2..f67a3df 100644 --- a/src/cli/cli.c +++ b/src/cli/cli.c @@ -38,6 +38,11 @@ void cli_tool78_glitch_ocd_dump(void); void cli_tool78_glitch_param_g10(void); void cli_tool78_glitch_ocd_g10(void); +void cli_tool78_proto78k0(void); + +void cli_swim_phytest(void); +void cli_swim_prototest(void); + static void adc_init_stuff() { adc_init(); adc_gpio_init(27); @@ -87,6 +92,11 @@ static struct cli_cmd cmds[] = { { "zap", cli_dragonzap_test }, + { "k0sfp", cli_tool78_proto78k0 }, + + { "swimphy", cli_swim_phytest }, + { "swim", cli_swim_prototest }, + { NULL, NULL } // final }; diff --git a/src/cli/rl78-glitch.c b/src/cli/rl78-glitch.c index 142dc12..290f66f 100644 --- a/src/cli/rl78-glitch.c +++ b/src/cli/rl78-glitch.c @@ -1,4 +1,3 @@ - #include #include #include @@ -53,17 +52,16 @@ static bool glitch_init_core1_stuff(bool exttrig, uint glitchpin) { offset.min = 10*1000; offset.max = 35433*1000; length.min = 100; - length.max = 10*50/*26*/*1000; + length.max = /*10*50*/26*1000; //length.value = 5*1000; // 5 us #if PINOUT_USE_DRAGONZAP //length.adc_index = 0;//999; #else -#error "a" //length.adc_index = 999; #endif glitch_param_randrange_init(&offset); - glitch_param_const_init(&length); + //glitch_param_const_init(&length); glitch_param_randrange_init(&length); //glitch_param_adc_init(&length); @@ -237,7 +235,9 @@ deinit_bad: } void cli_tool78_glitch_paramsearch(void) { - if (!glitch_init_core1_stuff(true, GLITCH_OUT_PIN)) { + zap_picoemp_init(); + + if (!glitch_init_core1_stuff(true, ZAP_GLITCH_OUT/*GLITCH_OUT_PIN*/)) { printf("bad glitcher params!\n"); return; } @@ -250,8 +250,12 @@ void cli_tool78_glitch_paramsearch(void) { bool first = true; restart: - /*glitch_disarm(); - busy_wait_ms(40);*/ + zap_picoemp_set_armed(false); + glitch_disarm(); + /*busy_wait_ms(40);*/ + + zap_picoemp_set_armed(true); + while (!zap_picoemp_has_hv()) ; ver=0; st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd); @@ -332,55 +336,53 @@ restart: glitch_arm(); rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 120*1000); glitch_disarm(); - if (rr == 2 && (checkbuf[0] != 'H' || checkbuf[1] != 'i')) rr = 0; - if (rr == 2) { - rr = tool78_hw_rl78_uart1.recv(256, checkbuf, 120*1000); - } - if (rr <= 0) { - // timeout or something - printf("X"); - tool78_hw_rl78_uart1.deinit(); - goto do_reset_stuff; - } else { - int firstbad = -1, lastbad = -1; - for (int i = 0; i < rr; ++i) { - if (checkbuf[i] != (0xaa^0xff)) { - if (firstbad == -1) firstbad = i; - lastbad = i; + bool first_ = true; + do { + if (rr == 2 && (checkbuf[0] != 'H' || checkbuf[1] != 'i')) rr = 0; + if (rr == 2) { + rr = tool78_hw_rl78_uart1.recv(256, checkbuf, 120*1000); + } + + if (rr <= 0) { + if (!first_) break; + // timeout or something + printf("X"); + tool78_hw_rl78_uart1.deinit(); + goto do_reset_stuff; + } else { + int firstbad = -1, lastbad = -1; + for (int i = 0; i < rr; ++i) { + if (checkbuf[i] != (0xaa^0xff)) { + if (firstbad == -1) firstbad = i; + lastbad = i; + } + } + if (firstbad >= 0) { + volatile uint32_t + *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("."); } } - if (firstbad >= 0) { - volatile uint32_t - *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("."); - /*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);*/ - } - } + + first_=false; + if (!zap_picoemp_has_hv()) { + rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 150*1000); + } else break; + } while (true); } deinit_bad: + zap_picoemp_set_armed(false); tool78_hw_rl78_uart1.deinit(); return; do_reset_stuff: + zap_picoemp_set_armed(false); tool78_hw_rl78_uart1.deinit(); // glitch for way too long to power cycle diff --git a/src/cli/swim.c b/src/cli/swim.c new file mode 100644 index 0000000..91f1740 --- /dev/null +++ b/src/cli/swim.c @@ -0,0 +1,45 @@ + +#include +#include +#include + +#include "swim_hw.h" +#include "swim_cmd.h" + +void cli_swim_phytest(void); +void cli_swim_prototest(void); + +void cli_swim_phytest(void) { + swim_preinit(); + swim_init(); + swim_deinit(); +} +void cli_swim_prototest(void) { + swim_preinit(); + swim_init(); + + if (!swim_cmd_srst()) { + printf("srst error!\n"); + goto end; + } + + uint8_t option[0x10], id[0x10]; + + if (!swim_cmd_rotf(0x4800, 0x0a, option)) { + printf("rotf option error!\n"); + goto end; + } + printf("option: %02hhx %02hhx %02hhx ...\n", + option[0], option[1], option[2]); + + if (!swim_cmd_rotf(0x4876, 0x10-5, id)) { + printf("rotf id error!\n"); + goto end; + } + printf("id: %02hhx %02hhx %02hhx ...\n", + id[0], id[1], id[2]); + +end: + swim_deinit(); +} + diff --git a/src/swim/swim.pio b/src/swim/swim.pio index 512168b..4ced38d 100644 --- a/src/swim/swim.pio +++ b/src/swim/swim.pio @@ -3,36 +3,47 @@ ; Pin assignments: ; - SWIM is out/set/side pin 0 -; NOTE: pin needs pullup, either input(+pullup) or output+drivezero => use set pindirs AND sideset is direction! +; NOTE: pin needs pullup, either input(+pullup) or output+drivezero +; => use set pindirs AND sideset is direction! ; -; Autopush and autopull must be enabled, set to 8 +; Autopull should be enabled, and set to 0 start: - pull side 0 - out x, 32 side 0 + nop side 0 [15] + nop side 1 [15] + nop side 0 [15] + nop side 1 [15] +.wrap_target + nop side 0 [10] +.wrap - ; TODO: can we somehow sleep for a variable amount of cycles in an easier - ; way? -iter: - out y, 1 side 0 ; get next bit - jmp !y, bit_0 side 0 - -bit_1: - nop side 1 [2] +; pull side 0 +; out x, 32 side 0 +; +; ; TODO: can we somehow sleep for a variable amount of cycles in an easier +; ; way? +;iter: +; out y, 1 side 0 ; get next bit +; jmp !y, bit_0 side 0 +; +;bit_1: +; nop side 1 [2] PUBLIC bit_1_delay_long: - nop side 0 [10] ; or 4 - nop side 0 [10] ; or 4 - - jmp iter_next side 0 - -bit_0: +; nop side 0 [10] ; or 4 +; nop side 0 [10] ; or 4 +; +; jmp iter_next side 0 +; +;bit_0: PUBLIC bit_0_delay_long: - nop side 1 [10] ; or 4 - nop side 1 [10] ; or 4 - nop side 0 [2] +; nop side 1 [10] ; or 4 +; nop side 1 [10] ; or 4 +; nop side 0 [2] +; +;iter_next: +; jmp x--, iter side 0 -iter_next: - jmp x--, iter side 0 +; 12 instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -42,8 +53,7 @@ iter_next: ; - SWIM is in pin 0 ; NOTE: pin needs pullup, either input(+pullup) or output+drivezero ; -; Autopush and autopull must be enabled, set to 8 - +; Autopush should be enabled, and set to 32 start: pull @@ -65,6 +75,8 @@ PUBLIC wait_delay: push +; 7 instructions + ;;;; 19 instructions total @@ -80,7 +92,7 @@ static inline void swim_tx_pio_init(PIO pio, uint sm, uint prog_offs, sm_config_set_out_pins(&c, pin_swim, 1); sm_config_set_set_pins(&c, pin_swim, 1); sm_config_set_sideset_pins(&c, pin_swim); - sm_config_set_out_shift(&c, false, true, 8); + sm_config_set_out_shift(&c, false, true, 0); sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / swim_clock_freq); sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); pio_sm_init(pio, sm, prog_offs, &c); @@ -130,7 +142,7 @@ static inline void swim_rx_pio_init(PIO pio, uint sm, uint prog_offs, pio_sm_config c = swim_rx_program_get_default_config(prog_offs); sm_config_set_in_pins(&c, pin_swim); sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / swim_clock_freq); - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + sm_config_set_in_shift(&c, false, true, 32); pio_sm_init(pio, sm, prog_offs, &c); // SWIM pin is pure input diff --git a/src/swim/swim_cmd.c b/src/swim/swim_cmd.c new file mode 100644 index 0000000..06d3f8e --- /dev/null +++ b/src/swim/swim_cmd.c @@ -0,0 +1,39 @@ + +#include "swim_hw.h" + +#include "swim_cmd.h" + +bool swim_cmd_srst(void) { + return swim_tx_command(SWIM_CMD_SRST, 0, NULL); +} + +bool swim_cmd_rotf(uint32_t addr, uint8_t len, uint8_t* data) { + if (!len) return false; + + uint8_t hdr[4]; + hdr[0] = len; + hdr[1] = (addr >> 16) & 0xff; + hdr[2] = (addr >> 8) & 0xff; + hdr[3] = (addr >> 0) & 0xff; + + bool r = swim_tx_command(SWIM_CMD_ROTF, 4, hdr); + if (!r) return false; + + return swim_rx_data(len, data); +} + +bool swim_cmd_wotf(uint32_t addr, uint8_t len, const uint8_t* data) { + if (!len) return false; + + uint8_t hdr[4]; + hdr[0] = len; + hdr[1] = (addr >> 16) & 0xff; + hdr[2] = (addr >> 8) & 0xff; + hdr[3] = (addr >> 0) & 0xff; + + bool r = swim_tx_command(SWIM_CMD_WOTF, 4, hdr); + if (!r) return false; + + return swim_tx_data(len, data); +} + diff --git a/src/swim/swim_cmd.h b/src/swim/swim_cmd.h new file mode 100644 index 0000000..45bb6d0 --- /dev/null +++ b/src/swim/swim_cmd.h @@ -0,0 +1,19 @@ + +#ifndef SWIM_CMD_H_ +#define SWIM_CMD_H_ + +#include + +enum swim_cmd { + SWIM_CMD_SRST = 0, + SWIM_CMD_ROTF = 1, + SWIM_CMD_WOTF = 2 +}; + +bool swim_cmd_srst(void); + +bool swim_cmd_rotf(uint32_t addr, uint8_t len, uint8_t* data); +bool swim_cmd_wotf(uint32_t addr, uint8_t len, const uint8_t* data); + +#endif + diff --git a/src/swim/swim_hw.c b/src/swim/swim_hw.c index 0722ec5..b662b9f 100644 --- a/src/swim/swim_hw.c +++ b/src/swim/swim_hw.c @@ -7,31 +7,182 @@ #include "pinout.h" #include "swim_hw.h" +#include "swim_cmd.h" #include "swim.pio.h" int swim_tx_sm = -1, swim_rx_sm = -1, swim_tx_off = -1, swim_rx_off = -1; +#define SWIM_DEFAULT_FREQ (8*1000*1000) + +static void initseq_1(void) { + // phase 1: set SWIM low for 16 us + gpio_set_dir(PINOUT_SWIM, GPIO_OUT); + busy_wait_us_32(16); + + gpio_set_drive_strength(PINOUT_SWIM, GPIO_DRIVE_STRENGTH_12MA); + gpio_set_slew_rate(PINOUT_SWIM, GPIO_SLEW_RATE_FAST); + + gpio_init(20); + gpio_set_dir(20, GPIO_OUT); + gpio_put(20, true); + gpio_set_function(20, GPIO_FUNC_SIO); + + // phase 2: entry sequence + for (size_t i = 0; i < 4; ++i) { + gpio_set_dir(PINOUT_SWIM, GPIO_IN); + busy_wait_us_32(500); + gpio_set_dir(PINOUT_SWIM, GPIO_OUT); + busy_wait_us_32(500); + } + for (size_t i = 0; i < 4; ++i) { + gpio_set_dir(PINOUT_SWIM, GPIO_IN); + busy_wait_us_32(250); + gpio_set_dir(PINOUT_SWIM, GPIO_OUT); + busy_wait_us_32(250); + } + + sio_hw->gpio_togl = 1u<<20; + + /*for (size_t i = 0; i < 8; ++i) { + const int delay = 2; + gpio_set_dir(PINOUT_SWIM, GPIO_IN); + busy_wait_us_32(delay); + gpio_set_dir(PINOUT_SWIM, GPIO_OUT); + busy_wait_us_32(delay); + }*/ + + // phase 3: line rises again: SWIM activation, hi-speed osc on MCU starts + gpio_set_dir(PINOUT_SWIM, GPIO_IN); + + // phase 4: SWIM sync: MCU sends 'synchronization frame' (pulls line low + // for some time) + // TODO: timeouts! + /*while (gpio_get(PINOUT_SWIM)) ; + while (!gpio_get(PINOUT_SWIM)) ;*/ + busy_wait_us_32(1000); + + // phase 5: wait a bit + busy_wait_us_32(1); +} +static void initseq_2(void) { + sio_hw->gpio_togl = 1u<<20; + // phase 6: "write 0x0A0 to SWIM CSR" + /*uint8_t data = 0xA0; + swim_cmd_wotf(0x007F80, 1, &data);*/ + swim_tx_bits(4, 0xffff); + + busy_wait_us_32(100); + // phase 7: reset release for 1ms. option bytes are read (!) + gpio_put(PINOUT_SWIM_nRESET, true); + busy_wait_ms(3); + + // phase 8: things are initialized: + // * STM8 CPU halted, HSI = 16 MHz + // * SWIM clock = HSI/2 = 8 MHz + // * SWIM uses low-speed format + + // phase 9: ??? +} + void swim_preinit(void) { - // TODO: - // * init GPIO (pulls, dir, out, function) - // * do entry sequence (~8 phases?) + gpio_disable_pulls(PINOUT_SWIM_nRESET); + gpio_set_function(PINOUT_SWIM_nRESET, GPIO_FUNC_NULL); + gpio_set_function(PINOUT_SWIM, GPIO_FUNC_NULL); + gpio_pull_up(PINOUT_SWIM); + + // SWIM pin is high before reset release USING PULLUP FROM PADS + // to set SWIM pin to 0, set direction to output + gpio_put_masked((1u << PINOUT_SWIM_nRESET) | (1u << PINOUT_SWIM), 0); + gpio_set_dir(PINOUT_SWIM_nRESET, GPIO_OUT); + gpio_set_dir(PINOUT_SWIM, GPIO_IN); + gpio_set_function(PINOUT_SWIM_nRESET, GPIO_FUNC_SIO); + gpio_set_function(PINOUT_SWIM, GPIO_FUNC_SIO); + + // SWIM is now high, reset line is asserted + + busy_wait_ms(3); + + initseq_1(); + + // phase 6 and on: do this in swim_init() } bool swim_init(void) { - // TODO: - // for each rx, tx: - // * allocate PIO program space - // * allocate PIO SMs - // * init PIO SM program & stuff + if (!pio_can_add_program(PINOUT_SWIM_PIO, &swim_tx_program)) + goto error; + swim_tx_off = pio_add_program(PINOUT_SWIM_PIO, &swim_tx_program); + + if (!pio_can_add_program(PINOUT_SWIM_PIO, &swim_rx_program)) + goto error; + swim_rx_off = pio_add_program(PINOUT_SWIM_PIO, &swim_rx_program); + + swim_tx_sm = pio_claim_unused_sm(PINOUT_SWIM_PIO, false); + if (swim_tx_sm == -1) goto error; + swim_rx_sm = pio_claim_unused_sm(PINOUT_SWIM_PIO, false); + if (swim_rx_sm == -1) goto error; + + swim_tx_pio_init(PINOUT_SWIM_PIO, swim_tx_sm, swim_tx_off, SWIM_DEFAULT_FREQ, PINOUT_SWIM); + //swim_rx_pio_init(PINOUT_SWIM_PIO, swim_rx_sm, swim_rx_off, SWIM_DEFAULT_FREQ, PINOUT_SWIM); + + // continue SWIM init sequence: + initseq_2(); + + return true; + +error: return false; + + // NOTE: you should call swim_deinit(); in this case tho +} + +void swim_comms_reset(void) { + gpio_set_dir(PINOUT_SWIM, GPIO_IN); + gpio_put(PINOUT_SWIM, false); + gpio_set_function(PINOUT_SWIM, GPIO_FUNC_SIO); + + // comms reset + gpio_set_dir(PINOUT_SWIM, GPIO_OUT); + busy_wait_ms(10); + gpio_set_dir(PINOUT_SWIM, GPIO_IN); + + // maybe there's a reply here? UM0470 is confusing about it + busy_wait_ms(10); + + // --- + + initseq_1(); + + // --- + + gpio_set_function(PINOUT_SWIM, + (PINOUT_SWIM_PIO == pio1) ? GPIO_FUNC_PIO1 : GPIO_FUNC_PIO0); + + initseq_2(); } void swim_deinit(void) { - // TODO: - // * disable PIO SMs - // * deallocate PIO SMs - // * deallocate PIO program space + if (swim_tx_sm >= 0) { + pio_sm_set_enabled(PINOUT_SWIM_PIO, swim_tx_sm, false); + pio_sm_unclaim(PINOUT_SWIM_PIO, swim_tx_sm); + } + if (swim_rx_sm >= 0) { + pio_sm_set_enabled(PINOUT_SWIM_PIO, swim_rx_sm, false); + pio_sm_unclaim(PINOUT_SWIM_PIO, swim_rx_sm); + } + if (!~swim_tx_off) pio_remove_program(PINOUT_SWIM_PIO, &swim_tx_program, swim_tx_off); + if (!~swim_rx_off) pio_remove_program(PINOUT_SWIM_PIO, &swim_rx_program, swim_rx_off); + + gpio_put(PINOUT_SWIM_nRESET, false); + + gpio_disable_pulls(PINOUT_SWIM); + gpio_disable_pulls(PINOUT_SWIM_nRESET); + gpio_set_function(PINOUT_SWIM, GPIO_FUNC_NULL); + + busy_wait_ms(1); + + gpio_pull_down(PINOUT_SWIM_nRESET); + gpio_set_function(PINOUT_SWIM_nRESET, GPIO_FUNC_NULL); } void swim_set_speed(float swim_clock_freq, bool fast) { @@ -43,20 +194,36 @@ void swim_set_speed(float swim_clock_freq, bool fast) { // SWIM only sends up to 10 bits at once before changing direction (for an ack) void swim_tx_bits(uint32_t nbits, uint16_t bits) { - // TODO: - // * init PIO SM stuff - // * send length - // * send data - // * wait for tx fifo empty - // * wait until finished? (use IRQ?? prolly best sync mechanism) + if (!nbits) return; + + while (!pio_sm_is_tx_fifo_empty(PINOUT_SWIM_PIO, swim_tx_sm)) + ; + + *(volatile uint32_t*)&PINOUT_SWIM_PIO->txf[swim_tx_sm] = nbits - 1; + *(volatile uint16_t*)&PINOUT_SWIM_PIO->txf[swim_tx_sm] = bits; + + while (!pio_sm_is_tx_fifo_empty(PINOUT_SWIM_PIO, swim_tx_sm)) + ; + while (!(PINOUT_SWIM_PIO->fdebug & ((1u << swim_tx_sm) << PIO_FDEBUG_TXSTALL_LSB))) + ; } uint16_t swim_rx_bits(uint32_t nbits) { - uint16_t r = 0; + if (!nbits) return 0xffff; - // TODO: - // * init PIO SM stuff - // * send length - // * read data (incl. wait until finished) + while (!pio_sm_is_tx_fifo_empty(PINOUT_SWIM_PIO, swim_rx_sm)) + ; + + *(volatile uint32_t*)&PINOUT_SWIM_PIO->txf[swim_rx_sm] = nbits - 1; + + while (!pio_sm_is_tx_fifo_empty(PINOUT_SWIM_PIO, swim_rx_sm)) + ; + while (pio_sm_is_rx_fifo_empty(PINOUT_SWIM_PIO, swim_rx_sm)) + ; + + uint16_t r = *(volatile uint16_t*)&PINOUT_SWIM_PIO->rxf[swim_rx_sm]; + + while (!(PINOUT_SWIM_PIO->fdebug & ((1u << swim_rx_sm) << PIO_FDEBUG_TXSTALL_LSB))) + ; return r; } @@ -70,23 +237,8 @@ static uint8_t bitswap(uint8_t in) { return (lut[in&0xf] << 4) | lut[in>>4]; } -bool swim_tx_command(uint8_t cmd, size_t datasize, const uint8_t* data) { - // cmd is 0 bit, 3 data bits, parity bit, responded by an ack bit - uint16_t r = 0, v = (0<<15) | ((cmd&1)<<14) | ((cmd&2)<<12) | ((cmd&4)<<10); - // add parity bit - v |= (((cmd>>0)^(cmd>>1)^(cmd>>2)) & 1) << 11; - - for (size_t i = 0; i < 10; ++i) { - swim_tx_bits(5, v); - - r = swim_rx_bits(1); // ack bit - if (r) break; - } - - if (!r) { - // oops, no ack! - return false; - } +bool swim_tx_data(size_t datasize, const uint8_t* data) { + uint16_t r = 0, v = 0; // start sending data bits for (size_t i = 0; i < datasize; ++i) { @@ -111,6 +263,26 @@ bool swim_tx_command(uint8_t cmd, size_t datasize, const uint8_t* data) { return true; } +bool swim_tx_command(uint8_t cmd, size_t datasize, const uint8_t* data) { + // cmd is 0 bit, 3 data bits, parity bit, responded by an ack bit + uint16_t r = 0, v = (0<<15) | ((cmd&1)<<14) | ((cmd&2)<<12) | ((cmd&4)<<10); + // add parity bit + v |= (((cmd>>0)^(cmd>>1)^(cmd>>2)) & 1) << 11; + + for (size_t i = 0; i < 10; ++i) { + swim_tx_bits(5, v); + + r = swim_rx_bits(1); // ack bit + if (r) break; + } + + if (!r) { + // oops, no ack! + return false; + } + + return swim_tx_data(datasize, data); +} bool swim_rx_data(size_t datasize, uint8_t* data) { uint16_t v = 0, r = 0; diff --git a/src/swim/swim_hw.h b/src/swim/swim_hw.h index 98e20d6..1641f27 100644 --- a/src/swim/swim_hw.h +++ b/src/swim/swim_hw.h @@ -2,6 +2,7 @@ #ifndef SWIM_HW_H_ #define SWIM_HW_H_ +#include #include #include @@ -11,6 +12,8 @@ void swim_preinit(void); bool swim_init(void); void swim_deinit(void); +void swim_comms_reset(void); + // 'swim_clock_freq' is the frequency of the underlying SWIM clock, // *NOT* the baudrate! in the STM8 device being debugged, this is usually // HSI/2 = 8 MHz @@ -21,6 +24,7 @@ void swim_set_speed(float swim_clock_freq, bool fast); void swim_tx_bits(uint32_t nbits, uint16_t bits); uint16_t swim_rx_bits(uint32_t nbits); +bool swim_tx_data(size_t datasize, const uint8_t* data); bool swim_tx_command(uint8_t cmd, size_t datasize, const uint8_t* data); bool swim_rx_data(size_t datasize, uint8_t* data); diff --git a/src/tool78/tool78_cmds.c b/src/tool78/tool78_cmds.c index 2c3852e..ac1cd4f 100644 --- a/src/tool78/tool78_cmds.c +++ b/src/tool78/tool78_cmds.c @@ -287,6 +287,8 @@ static enum tool78_stat tool78_wait_status/*__impl*/(struct tool78_hw* hw, int l // ---- enum tool78_stat tool78_do_reset(struct tool78_hw* hw) { + //busy_wait_ms(100); + enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_reset, 0, NULL); //printf("send st=%02x\n", st); if (st != tool78_stat_ack) return st; diff --git a/src/tool78/tool78_hw_78k0_uart2.c b/src/tool78/tool78_hw_78k0_uart2.c index 0c1b203..422b5a9 100644 --- a/src/tool78/tool78_hw_78k0_uart2.c +++ b/src/tool78/tool78_hw_78k0_uart2.c @@ -40,7 +40,7 @@ static bool t78k0_uart2_init(void) { // send 0x00 // wait t2C (>15k/8M s) - busy_wait_us_32(477768); // tCOM or tR1 + busy_wait_us_32(477768/*>>3*/); // tCOM or tR1 uint8_t byte = 0x00; t78k0_uart2_send(1, &byte, -1); @@ -57,6 +57,8 @@ static bool t78k0_uart2_init(void) { return true; // all is well! } static void t78k0_uart2_deinit(void) { + busy_wait_ms(500); + tool78_hw_deinit_help(&tool78_uart_tx_program, &tool78_uart_rx_program, &vars); diff --git a/src/tool78/tool78_hw_helpers.c b/src/tool78/tool78_hw_helpers.c index b5987cb..d9dbef8 100644 --- a/src/tool78/tool78_hw_helpers.c +++ b/src/tool78/tool78_hw_helpers.c @@ -57,10 +57,10 @@ bool tool78_hw_init_help(const pio_program_t* prgm_tx, return true; // all is well! error: - if (!~txoff) pio_remove_program(PINOUT_TOOL78_PIO, prgm_tx, txoff); - if (!~rxoff) pio_remove_program(PINOUT_TOOL78_PIO, prgm_rx, rxoff); if (smtx >= 0) pio_sm_unclaim(PINOUT_TOOL78_PIO, smtx); if (smrx >= 0) pio_sm_unclaim(PINOUT_TOOL78_PIO, smrx); + if (!~txoff) pio_remove_program(PINOUT_TOOL78_PIO, prgm_tx, txoff); + if (!~rxoff) pio_remove_program(PINOUT_TOOL78_PIO, prgm_rx, rxoff); return false; } void tool78_hw_deinit_help(const pio_program_t* prgm_tx,