78k0 and SWIM stuff that doesn't work
This commit is contained in:
parent
37a41e5f83
commit
989785e06b
|
@ -35,6 +35,7 @@ if(FAMILY STREQUAL "rp2040")
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/tap.c
|
${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/tap.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msp430/msp430dbg.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_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_helpers.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_test_uart2.c
|
${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_test_uart2.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_78k0_spi.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/glitch/glitch.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/cli.c
|
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/cli.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/cli/msp430.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.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/cli/dragonzap.c
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
#define BREADBOARD_SBW_TDIO 9
|
#define BREADBOARD_SBW_TDIO 9
|
||||||
|
|
||||||
#define BREADBOARD_SWIM_PIO pio0
|
#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
|
#define BREADBOARD_TOOL78_PIO pio1
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "breadboard.h"
|
#include "breadboard.h"
|
||||||
#include "zap.h"
|
#include "zap.h"
|
||||||
|
|
||||||
#define PINOUT_USE_DRAGONZAP 1
|
#define PINOUT_USE_DRAGONZAP 0
|
||||||
|
|
||||||
#if PINOUT_USE_DRAGONZAP
|
#if PINOUT_USE_DRAGONZAP
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@
|
||||||
#define PINOUT_SBW_TDIO (ZAP_GPIO_BASE+1)
|
#define PINOUT_SBW_TDIO (ZAP_GPIO_BASE+1)
|
||||||
|
|
||||||
#define PINOUT_SWIM_PIO BREADBOARD_SWIM_PIO
|
#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
|
#define PINOUT_TOOL78_PIO BREADBOARD_TOOL78_PIO
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ inline static void bsp_init_stuff(void) {
|
||||||
#define PINOUT_SBW_TDIO BREADBOARD_SBW_TDIO
|
#define PINOUT_SBW_TDIO BREADBOARD_SBW_TDIO
|
||||||
|
|
||||||
#define PINOUT_SWIM_PIO BREADBOARD_SWIM_PIO
|
#define PINOUT_SWIM_PIO BREADBOARD_SWIM_PIO
|
||||||
|
#define PINOUT_SWIM_nRESET BREADBOARD_SWIM_nRESET
|
||||||
#define PINOUT_SWIM BREADBOARD_SWIM_PIN
|
#define PINOUT_SWIM BREADBOARD_SWIM_PIN
|
||||||
|
|
||||||
#define PINOUT_TOOL78_PIO BREADBOARD_TOOL78_PIO
|
#define PINOUT_TOOL78_PIO BREADBOARD_TOOL78_PIO
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pico/time.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,11 @@ void cli_tool78_glitch_ocd_dump(void);
|
||||||
void cli_tool78_glitch_param_g10(void);
|
void cli_tool78_glitch_param_g10(void);
|
||||||
void cli_tool78_glitch_ocd_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() {
|
static void adc_init_stuff() {
|
||||||
adc_init();
|
adc_init();
|
||||||
adc_gpio_init(27);
|
adc_gpio_init(27);
|
||||||
|
@ -87,6 +92,11 @@ static struct cli_cmd cmds[] = {
|
||||||
|
|
||||||
{ "zap", cli_dragonzap_test },
|
{ "zap", cli_dragonzap_test },
|
||||||
|
|
||||||
|
{ "k0sfp", cli_tool78_proto78k0 },
|
||||||
|
|
||||||
|
{ "swimphy", cli_swim_phytest },
|
||||||
|
{ "swim", cli_swim_prototest },
|
||||||
|
|
||||||
{ NULL, NULL } // final
|
{ NULL, NULL } // final
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -53,17 +52,16 @@ static bool glitch_init_core1_stuff(bool exttrig, uint glitchpin) {
|
||||||
offset.min = 10*1000;
|
offset.min = 10*1000;
|
||||||
offset.max = 35433*1000;
|
offset.max = 35433*1000;
|
||||||
length.min = 100;
|
length.min = 100;
|
||||||
length.max = 10*50/*26*/*1000;
|
length.max = /*10*50*/26*1000;
|
||||||
//length.value = 5*1000; // 5 us
|
//length.value = 5*1000; // 5 us
|
||||||
#if PINOUT_USE_DRAGONZAP
|
#if PINOUT_USE_DRAGONZAP
|
||||||
//length.adc_index = 0;//999;
|
//length.adc_index = 0;//999;
|
||||||
#else
|
#else
|
||||||
#error "a"
|
|
||||||
//length.adc_index = 999;
|
//length.adc_index = 999;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glitch_param_randrange_init(&offset);
|
glitch_param_randrange_init(&offset);
|
||||||
glitch_param_const_init(&length);
|
//glitch_param_const_init(&length);
|
||||||
glitch_param_randrange_init(&length);
|
glitch_param_randrange_init(&length);
|
||||||
//glitch_param_adc_init(&length);
|
//glitch_param_adc_init(&length);
|
||||||
|
|
||||||
|
@ -237,7 +235,9 @@ deinit_bad:
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_tool78_glitch_paramsearch(void) {
|
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");
|
printf("bad glitcher params!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -250,8 +250,12 @@ void cli_tool78_glitch_paramsearch(void) {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
/*glitch_disarm();
|
zap_picoemp_set_armed(false);
|
||||||
busy_wait_ms(40);*/
|
glitch_disarm();
|
||||||
|
/*busy_wait_ms(40);*/
|
||||||
|
|
||||||
|
zap_picoemp_set_armed(true);
|
||||||
|
while (!zap_picoemp_has_hv()) ;
|
||||||
|
|
||||||
ver=0;
|
ver=0;
|
||||||
st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd);
|
st = tool78_init_ocd(&tool78_hw_rl78_uart1, &ver, passwd);
|
||||||
|
@ -332,12 +336,16 @@ restart:
|
||||||
glitch_arm();
|
glitch_arm();
|
||||||
rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 120*1000);
|
rr = tool78_hw_rl78_uart1.recv(2, checkbuf, 120*1000);
|
||||||
glitch_disarm();
|
glitch_disarm();
|
||||||
|
|
||||||
|
bool first_ = true;
|
||||||
|
do {
|
||||||
if (rr == 2 && (checkbuf[0] != 'H' || checkbuf[1] != 'i')) rr = 0;
|
if (rr == 2 && (checkbuf[0] != 'H' || checkbuf[1] != 'i')) rr = 0;
|
||||||
if (rr == 2) {
|
if (rr == 2) {
|
||||||
rr = tool78_hw_rl78_uart1.recv(256, checkbuf, 120*1000);
|
rr = tool78_hw_rl78_uart1.recv(256, checkbuf, 120*1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rr <= 0) {
|
if (rr <= 0) {
|
||||||
|
if (!first_) break;
|
||||||
// timeout or something
|
// timeout or something
|
||||||
printf("X");
|
printf("X");
|
||||||
tool78_hw_rl78_uart1.deinit();
|
tool78_hw_rl78_uart1.deinit();
|
||||||
|
@ -358,29 +366,23 @@ restart:
|
||||||
firstbad, lastbad, *off, *len, rr, checkbuf[firstbad]^0xaa);
|
firstbad, lastbad, *off, *len, rr, checkbuf[firstbad]^0xaa);
|
||||||
} else {
|
} else {
|
||||||
printf(".");
|
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:
|
deinit_bad:
|
||||||
|
zap_picoemp_set_armed(false);
|
||||||
tool78_hw_rl78_uart1.deinit();
|
tool78_hw_rl78_uart1.deinit();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
do_reset_stuff:
|
do_reset_stuff:
|
||||||
|
zap_picoemp_set_armed(false);
|
||||||
tool78_hw_rl78_uart1.deinit();
|
tool78_hw_rl78_uart1.deinit();
|
||||||
|
|
||||||
// glitch for way too long to power cycle
|
// glitch for way too long to power cycle
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pico/time.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
|
@ -3,36 +3,47 @@
|
||||||
|
|
||||||
; Pin assignments:
|
; Pin assignments:
|
||||||
; - SWIM is out/set/side pin 0
|
; - 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:
|
start:
|
||||||
pull side 0
|
nop side 0 [15]
|
||||||
out x, 32 side 0
|
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
|
; pull side 0
|
||||||
; way?
|
; out x, 32 side 0
|
||||||
iter:
|
;
|
||||||
out y, 1 side 0 ; get next bit
|
; ; TODO: can we somehow sleep for a variable amount of cycles in an easier
|
||||||
jmp !y, bit_0 side 0
|
; ; way?
|
||||||
|
;iter:
|
||||||
bit_1:
|
; out y, 1 side 0 ; get next bit
|
||||||
nop side 1 [2]
|
; jmp !y, bit_0 side 0
|
||||||
|
;
|
||||||
|
;bit_1:
|
||||||
|
; nop side 1 [2]
|
||||||
PUBLIC bit_1_delay_long:
|
PUBLIC bit_1_delay_long:
|
||||||
nop side 0 [10] ; or 4
|
; nop side 0 [10] ; or 4
|
||||||
nop side 0 [10] ; or 4
|
; nop side 0 [10] ; or 4
|
||||||
|
;
|
||||||
jmp iter_next side 0
|
; jmp iter_next side 0
|
||||||
|
;
|
||||||
bit_0:
|
;bit_0:
|
||||||
PUBLIC bit_0_delay_long:
|
PUBLIC bit_0_delay_long:
|
||||||
nop side 1 [10] ; or 4
|
; nop side 1 [10] ; or 4
|
||||||
nop side 1 [10] ; or 4
|
; nop side 1 [10] ; or 4
|
||||||
nop side 0 [2]
|
; nop side 0 [2]
|
||||||
|
;
|
||||||
|
;iter_next:
|
||||||
|
; jmp x--, iter side 0
|
||||||
|
|
||||||
iter_next:
|
; 12 instructions
|
||||||
jmp x--, iter side 0
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
@ -42,8 +53,7 @@ iter_next:
|
||||||
; - SWIM is in pin 0
|
; - SWIM is in pin 0
|
||||||
; NOTE: pin needs pullup, either input(+pullup) or output+drivezero
|
; 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:
|
start:
|
||||||
pull
|
pull
|
||||||
|
@ -65,6 +75,8 @@ PUBLIC wait_delay:
|
||||||
|
|
||||||
push
|
push
|
||||||
|
|
||||||
|
; 7 instructions
|
||||||
|
|
||||||
|
|
||||||
;;;; 19 instructions total
|
;;;; 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_out_pins(&c, pin_swim, 1);
|
||||||
sm_config_set_set_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_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_clkdiv(&c, (float)clock_get_hz(clk_sys) / swim_clock_freq);
|
||||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||||
pio_sm_init(pio, sm, prog_offs, &c);
|
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);
|
pio_sm_config c = swim_rx_program_get_default_config(prog_offs);
|
||||||
sm_config_set_in_pins(&c, pin_swim);
|
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_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);
|
pio_sm_init(pio, sm, prog_offs, &c);
|
||||||
|
|
||||||
// SWIM pin is pure input
|
// SWIM pin is pure input
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
#ifndef SWIM_CMD_H_
|
||||||
|
#define SWIM_CMD_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -7,31 +7,182 @@
|
||||||
#include "pinout.h"
|
#include "pinout.h"
|
||||||
|
|
||||||
#include "swim_hw.h"
|
#include "swim_hw.h"
|
||||||
|
#include "swim_cmd.h"
|
||||||
|
|
||||||
#include "swim.pio.h"
|
#include "swim.pio.h"
|
||||||
|
|
||||||
int swim_tx_sm = -1, swim_rx_sm = -1, swim_tx_off = -1, swim_rx_off = -1;
|
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) {
|
void swim_preinit(void) {
|
||||||
// TODO:
|
gpio_disable_pulls(PINOUT_SWIM_nRESET);
|
||||||
// * init GPIO (pulls, dir, out, function)
|
gpio_set_function(PINOUT_SWIM_nRESET, GPIO_FUNC_NULL);
|
||||||
// * do entry sequence (~8 phases?)
|
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) {
|
bool swim_init(void) {
|
||||||
// TODO:
|
if (!pio_can_add_program(PINOUT_SWIM_PIO, &swim_tx_program))
|
||||||
// for each rx, tx:
|
goto error;
|
||||||
// * allocate PIO program space
|
swim_tx_off = pio_add_program(PINOUT_SWIM_PIO, &swim_tx_program);
|
||||||
// * allocate PIO SMs
|
|
||||||
// * init PIO SM program & stuff
|
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;
|
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) {
|
void swim_deinit(void) {
|
||||||
// TODO:
|
if (swim_tx_sm >= 0) {
|
||||||
// * disable PIO SMs
|
pio_sm_set_enabled(PINOUT_SWIM_PIO, swim_tx_sm, false);
|
||||||
// * deallocate PIO SMs
|
pio_sm_unclaim(PINOUT_SWIM_PIO, swim_tx_sm);
|
||||||
// * deallocate PIO program space
|
}
|
||||||
|
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) {
|
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)
|
// 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) {
|
void swim_tx_bits(uint32_t nbits, uint16_t bits) {
|
||||||
// TODO:
|
if (!nbits) return;
|
||||||
// * init PIO SM stuff
|
|
||||||
// * send length
|
while (!pio_sm_is_tx_fifo_empty(PINOUT_SWIM_PIO, swim_tx_sm))
|
||||||
// * send data
|
;
|
||||||
// * wait for tx fifo empty
|
|
||||||
// * wait until finished? (use IRQ?? prolly best sync mechanism)
|
*(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 swim_rx_bits(uint32_t nbits) {
|
||||||
uint16_t r = 0;
|
if (!nbits) return 0xffff;
|
||||||
|
|
||||||
// TODO:
|
while (!pio_sm_is_tx_fifo_empty(PINOUT_SWIM_PIO, swim_rx_sm))
|
||||||
// * init PIO SM stuff
|
;
|
||||||
// * send length
|
|
||||||
// * read data (incl. wait until finished)
|
*(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;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -70,23 +237,8 @@ static uint8_t bitswap(uint8_t in) {
|
||||||
return (lut[in&0xf] << 4) | lut[in>>4];
|
return (lut[in&0xf] << 4) | lut[in>>4];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool swim_tx_command(uint8_t cmd, size_t datasize, const uint8_t* data) {
|
bool swim_tx_data(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;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// start sending data bits
|
// start sending data bits
|
||||||
for (size_t i = 0; i < datasize; ++i) {
|
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;
|
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) {
|
bool swim_rx_data(size_t datasize, uint8_t* data) {
|
||||||
uint16_t v = 0, r = 0;
|
uint16_t v = 0, r = 0;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#ifndef SWIM_HW_H_
|
#ifndef SWIM_HW_H_
|
||||||
#define SWIM_HW_H_
|
#define SWIM_HW_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@ void swim_preinit(void);
|
||||||
bool swim_init(void);
|
bool swim_init(void);
|
||||||
void swim_deinit(void);
|
void swim_deinit(void);
|
||||||
|
|
||||||
|
void swim_comms_reset(void);
|
||||||
|
|
||||||
// 'swim_clock_freq' is the frequency of the underlying SWIM clock,
|
// 'swim_clock_freq' is the frequency of the underlying SWIM clock,
|
||||||
// *NOT* the baudrate! in the STM8 device being debugged, this is usually
|
// *NOT* the baudrate! in the STM8 device being debugged, this is usually
|
||||||
// HSI/2 = 8 MHz
|
// 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);
|
void swim_tx_bits(uint32_t nbits, uint16_t bits);
|
||||||
uint16_t swim_rx_bits(uint32_t nbits);
|
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_tx_command(uint8_t cmd, size_t datasize, const uint8_t* data);
|
||||||
bool swim_rx_data(size_t datasize, uint8_t* data);
|
bool swim_rx_data(size_t datasize, uint8_t* data);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
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);
|
enum tool78_stat st = tool78_cmd_send(hw, tool78_cmd_reset, 0, NULL);
|
||||||
//printf("send st=%02x\n", st);
|
//printf("send st=%02x\n", st);
|
||||||
if (st != tool78_stat_ack) return st;
|
if (st != tool78_stat_ack) return st;
|
||||||
|
|
|
@ -40,7 +40,7 @@ static bool t78k0_uart2_init(void) {
|
||||||
// send 0x00
|
// send 0x00
|
||||||
// wait t2C (>15k/8M s)
|
// 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;
|
uint8_t byte = 0x00;
|
||||||
t78k0_uart2_send(1, &byte, -1);
|
t78k0_uart2_send(1, &byte, -1);
|
||||||
|
@ -57,6 +57,8 @@ static bool t78k0_uart2_init(void) {
|
||||||
return true; // all is well!
|
return true; // all is well!
|
||||||
}
|
}
|
||||||
static void t78k0_uart2_deinit(void) {
|
static void t78k0_uart2_deinit(void) {
|
||||||
|
busy_wait_ms(500);
|
||||||
|
|
||||||
tool78_hw_deinit_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
|
tool78_hw_deinit_help(&tool78_uart_tx_program, &tool78_uart_rx_program,
|
||||||
&vars);
|
&vars);
|
||||||
|
|
||||||
|
|
|
@ -57,10 +57,10 @@ bool tool78_hw_init_help(const pio_program_t* prgm_tx,
|
||||||
return true; // all is well!
|
return true; // all is well!
|
||||||
|
|
||||||
error:
|
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 (smtx >= 0) pio_sm_unclaim(PINOUT_TOOL78_PIO, smtx);
|
||||||
if (smrx >= 0) pio_sm_unclaim(PINOUT_TOOL78_PIO, smrx);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
void tool78_hw_deinit_help(const pio_program_t* prgm_tx,
|
void tool78_hw_deinit_help(const pio_program_t* prgm_tx,
|
||||||
|
|
Loading…
Reference in New Issue