#include #include #include "bitbang_rvswdio.h" #include "hardware/timer.h" #include "lwipopts.h" #include "pico.h" #define PIN_SWDIO 10 #define PIN_SWCLK 11 // wait time between line transitions #define SWD_DELAY() busy_wait_us(2); // microseconds between each register read/write #define STOP_WAIT 8 // Single wire debug (SWDIO and SWCLK) static inline void ConfigureIOForRVSWD(void) { // SWCLK forced, starts at 1 gpio_init(PIN_SWCLK); gpio_set_pulls(PIN_SWCLK, false, false); gpio_put(PIN_SWCLK, 1); gpio_set_dir(PIN_SWCLK, GPIO_OUT); // SWDIO, open drain (emulated) with pull-up gpio_init(PIN_SWDIO); gpio_set_pulls(PIN_SWDIO, true, false); gpio_put(PIN_SWDIO, 1); gpio_set_dir(PIN_SWDIO, GPIO_IN); } // Single wire input-output SDI (just SWDIO) static inline void ConfigureIOForRVSWIO(void) { //BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" ); } void rvswd_write_bit(bool value) { gpio_put(PIN_SWCLK, 0); gpio_put(PIN_SWDIO, value); gpio_set_dir(PIN_SWDIO, GPIO_OUT); gpio_set_dir(PIN_SWDIO, GPIO_IN); SWD_DELAY(); gpio_put(PIN_SWCLK, 1); // Data is sampled on rising edge of clock SWD_DELAY(); } bool rvswd_read_bit(void) { gpio_put(PIN_SWDIO, 1); gpio_set_dir(PIN_SWDIO, GPIO_IN); gpio_put(PIN_SWCLK, 0); SWD_DELAY(); bool bit = gpio_get(PIN_SWDIO); gpio_put(PIN_SWCLK, 1); // Data is output on rising edge of clock SWD_DELAY(); return bit; } static inline void rvswd_stop(void) { gpio_put(PIN_SWCLK, 0); SWD_DELAY(); gpio_put(PIN_SWDIO, 0); gpio_set_dir(PIN_SWDIO, GPIO_OUT); SWD_DELAY(); gpio_put(PIN_SWCLK, 1); SWD_DELAY(); gpio_put(PIN_SWDIO, 1); gpio_set_dir(PIN_SWDIO, GPIO_IN); } static void MCFWriteReg32( struct SWIOState * state, uint8_t command, uint32_t value ) { // only supported mode is SWD if (state->opmode != 2) { //BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" ); return; } noInterrupts(); // start transaction gpio_put(PIN_SWDIO, 0); gpio_set_dir(PIN_SWDIO, GPIO_OUT); SWD_DELAY(); // ADDR HOST bool parity = true; for (uint32_t mask = 1<<6; mask; mask >>= 1) { bool bit = !!(command & mask); parity ^= bit; rvswd_write_bit(bit); } rvswd_write_bit(1); // Operation: write rvswd_write_bit(parity); rvswd_read_bit(); // ??? rvswd_read_bit(); // Seems only need to be set for first transaction (We are ignoring that though) rvswd_read_bit(); // ??? rvswd_write_bit(0); // 0 for register, 1 for value. rvswd_write_bit(0); // ??? Seems to have something to do with halting. // DATA parity = false; // This time it's even parity? for (uint32_t mask = 1<<31; mask; mask >>= 1) { bool bit = !!(value & mask); parity ^= bit; rvswd_write_bit(bit); } // Parity bit rvswd_write_bit(parity); rvswd_read_bit(); // ??? rvswd_read_bit(); // ??? rvswd_read_bit(); // ??? rvswd_write_bit(1); // 0 for register, 1 for value rvswd_write_bit(0); // ??? Seems to have something to do with halting? rvswd_stop(); interrupts(); sleep_us(STOP_WAIT); } static int MCFReadReg32( struct SWIOState * state, uint8_t command, uint32_t * value ) { // only supported mode is SWD if (state->opmode != 2) { //BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" ); return -1; } noInterrupts(); // start transaction gpio_put(PIN_SWDIO, 0); gpio_set_dir(PIN_SWDIO, GPIO_OUT); SWD_DELAY(); // ADDR HOST bool parity = false; for (uint8_t mask = 1<<6; mask; mask >>= 1) { bool bit = !!(command & mask); parity ^= bit; rvswd_write_bit(bit); } rvswd_write_bit(0); // Operation: read rvswd_write_bit(parity); rvswd_read_bit(); // ?? rvswd_read_bit(); // ?? rvswd_read_bit(); // ?? rvswd_write_bit(0); // 0 for register, 1 for value rvswd_write_bit(0); // ??? Seems to have something to do with halting? // DATA *value = 0; parity = false; uint32_t rval = 0; for (uint8_t position = 0; position < 32; position++) { bool bit = rvswd_read_bit(); rval <<= 1; rval |= bit; parity ^= bit; } *value = rval; // Parity bit bool parity_read = rvswd_read_bit(); if (parity_read != parity) goto read_end; rvswd_read_bit(); // ?? rvswd_read_bit(); // ?? rvswd_read_bit(); // ?? rvswd_write_bit(1); // 0 for register, 1 for value rvswd_write_bit(0); // ??? Seems to have something to do with halting? rvswd_stop(); read_end: interrupts(); sleep_us(STOP_WAIT); BB_PRINTF_DEBUG("wrong parity: %d\n", parity_read); return (parity == parity_read) ? 0 : -1; }