jtag pio workingish but actually not at all
This commit is contained in:
parent
aa1d4ddf56
commit
f4d25dbed9
|
@ -45,11 +45,12 @@ if(FAMILY STREQUAL "rp2040")
|
|||
# need uart stdio, usb is busy doing other stuff
|
||||
if(USE_USBCDC_FOR_STDIO)
|
||||
# we're going to manually implement this case
|
||||
pico_enable_stdio_uart(${PROJECT} 0)
|
||||
#pico_enable_stdio_uart(${PROJECT} 0)
|
||||
target_compile_definitions(${PROJECT} PUBLIC USE_USBCDC_FOR_STDIO=1 PICO_STDIO_USB=1)
|
||||
else()
|
||||
pico_enable_stdio_uart(${PROJECT} 1)
|
||||
#pico_enable_stdio_uart(${PROJECT} 1)
|
||||
endif()
|
||||
pico_enable_stdio_uart(${PROJECT} 1)
|
||||
pico_enable_stdio_usb(${PROJECT} 0)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid FAMILY '${FAMILY}' specified")
|
||||
|
@ -81,6 +82,8 @@ target_sources(${PROJECT} PUBLIC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/m_sump/_sump.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/m_sump/cdc_sump.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/cdc_uart.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/dap_jtag.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/dap_swd.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/dap_uart.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/dap_swo.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/i2c_tinyusb.c
|
||||
|
@ -133,6 +136,7 @@ if(FAMILY STREQUAL "rp2040")
|
|||
target_link_libraries(${PROJECT} pico_stdio)
|
||||
endif()
|
||||
|
||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/dap_jtag.pio)
|
||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/swo_uart_rx.pio)
|
||||
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/swo_manchester_encoding.pio)
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ projects. These respective licenses can be found in
|
|||
- [ ] PIC programming
|
||||
- https://github.com/travisgoodspeed/goodfet/tree/master/firmware/apps/pic
|
||||
- iCE40 programming??
|
||||
- https://github.com/adamgreig/ffp
|
||||
- Renesas E7-{0,1,2} programming thing????
|
||||
- Renesas tell us how this works pls
|
||||
- https://github.com/szymonh/rl78check is something at least
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
// vim: set et:
|
||||
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/pio.h>
|
||||
|
||||
#include "DAP_config.h"
|
||||
#include <DAP.h>
|
||||
|
||||
/*#define JTAG_PIO*/
|
||||
#include "tusb_config.h"
|
||||
#include <tusb.h>
|
||||
|
||||
#include "dap_jtag.pio.h"
|
||||
|
||||
#define JTAG_PIO
|
||||
|
||||
#ifndef JTAG_PIO
|
||||
void PORT_JTAG_SETUP(void) {
|
||||
|
@ -52,19 +61,204 @@ void PORT_OFF(void) {
|
|||
PINOUT_TDI_MASK //| PINOUT_TDO_MASK
|
||||
| PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
|
||||
}
|
||||
#else
|
||||
void PORT_JTAG_SETUP(void) {
|
||||
// TODO...
|
||||
}
|
||||
|
||||
void PORT_OFF(void) {
|
||||
|
||||
}
|
||||
|
||||
void JTAG_Sequence(uint32_t info, const uint8_t* tdi, uint8_t* tdo) {
|
||||
uint32_t n = info & JTAG_SEQUENCE_TCK;
|
||||
if (n == 0) n = 64;
|
||||
|
||||
printf("seq hi 0x%lx\n", info);
|
||||
|
||||
printf("%s", "tdi: ");
|
||||
for (size_t j = 0; j < ((n + 7) >> 3); ++j) {
|
||||
printf("0x%x ", ((const uint8_t*)tdi)[j]);
|
||||
}
|
||||
|
||||
if (info & JTAG_SEQUENCE_TMS) PIN_SWDIO_TMS_SET();
|
||||
else PIN_SWDIO_TMS_CLR();
|
||||
|
||||
for (size_t i = 0; n != 0; ++i) {
|
||||
uint8_t iv = tdi[i], ov = 0;
|
||||
|
||||
for (size_t k = 0; k < 8 && n != 0; ++k, --n) {
|
||||
PIN_TDI_OUT((iv >> k) & 1);
|
||||
PIN_SWCLK_TCK_CLR();
|
||||
PIN_DELAY_SLOW(DAP_Data.clock_delay);
|
||||
ov |= PIN_TDO_IN() << k;
|
||||
PIN_SWCLK_TCK_SET();
|
||||
PIN_DELAY_SLOW(DAP_Data.clock_delay);
|
||||
}
|
||||
|
||||
if (info & JTAG_SEQUENCE_TDO) tdo[i] = ov;
|
||||
}
|
||||
|
||||
n = info & JTAG_SEQUENCE_TCK;
|
||||
if (n == 0) n = 64;
|
||||
|
||||
if (info & JTAG_SEQUENCE_TDO) {
|
||||
printf("%s", "\ntdo: ");
|
||||
for (size_t j = 0; j < ((n + 7) >> 3); ++j) {
|
||||
printf("0x%x ", ((const uint8_t*)tdo)[j]);
|
||||
}
|
||||
printf("%c", '\n');
|
||||
} else printf("%s", "\nno tdo\n");
|
||||
}
|
||||
#else
|
||||
static int jtagsm = -1, offset = -1;
|
||||
|
||||
void PORT_JTAG_SETUP(void) {
|
||||
resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS);
|
||||
|
||||
/* set to default high level */
|
||||
sio_hw->gpio_oe_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK |
|
||||
PINOUT_nRESET_MASK;
|
||||
sio_hw->gpio_set = PINOUT_TCK_MASK | PINOUT_TMS_MASK | PINOUT_TDI_MASK | PINOUT_nTRST_MASK |
|
||||
PINOUT_nRESET_MASK;
|
||||
/* TDO needs to be an input */
|
||||
sio_hw->gpio_oe_clr = PINOUT_TDO_MASK;
|
||||
|
||||
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TCK],
|
||||
PADS_BANK0_GPIO0_IE_BITS, // bits to set: input enable
|
||||
PADS_BANK0_GPIO0_IE_BITS |
|
||||
PADS_BANK0_GPIO0_OD_BITS); // bits to mask out: input enable, output disable
|
||||
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TMS], PADS_BANK0_GPIO0_IE_BITS,
|
||||
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
||||
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDI], PADS_BANK0_GPIO0_IE_BITS,
|
||||
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
||||
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_TDO],
|
||||
PADS_BANK0_GPIO0_IE_BITS |
|
||||
PADS_BANK0_GPIO0_OD_BITS, // TDO needs to have its output disabled
|
||||
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
||||
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nTRST], PADS_BANK0_GPIO0_IE_BITS,
|
||||
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
||||
hw_write_masked(&padsbank0_hw->io[PINOUT_JTAG_nRESET], PADS_BANK0_GPIO0_IE_BITS,
|
||||
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
||||
|
||||
// NOTE: hiZ: ctrl = (ctrl & ~(CTRL_OEOVER_BITS)) | (GPIO_OVERRIDE_LOW << CTRL_OEOVER_LSB);
|
||||
// normal == 0, low == 2
|
||||
|
||||
// set pin modes to general IO (SIO)
|
||||
iobank0_hw->io[PINOUT_JTAG_TCK].ctrl = GPIO_FUNC_PIO0 << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
||||
iobank0_hw->io[PINOUT_JTAG_TMS].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
||||
iobank0_hw->io[PINOUT_JTAG_TDI].ctrl = GPIO_FUNC_PIO0 << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
||||
iobank0_hw->io[PINOUT_JTAG_TDO].ctrl = (GPIO_FUNC_PIO0 << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB)
|
||||
/*| (GPIO_OVERRIDE_LOW << IO_BANK0_GPIO0_CTRL_OEOVER_LSB)*/;
|
||||
iobank0_hw->io[PINOUT_JTAG_nTRST].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
||||
iobank0_hw->io[PINOUT_JTAG_nRESET].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
||||
|
||||
jtagsm = pio_claim_unused_sm(PINOUT_JTAG_PIO_DEV, true);
|
||||
offset = pio_add_program(PINOUT_JTAG_PIO_DEV, &dap_jtag_program);
|
||||
dap_jtag_program_init(PINOUT_JTAG_PIO_DEV, jtagsm, offset,
|
||||
50*1000, PINOUT_JTAG_TCK, PINOUT_JTAG_TDI, PINOUT_JTAG_TDO);
|
||||
}
|
||||
|
||||
void PORT_OFF(void) {
|
||||
pio_sm_set_enabled(PINOUT_JTAG_PIO_DEV, jtagsm, false);
|
||||
pio_sm_unclaim(PINOUT_JTAG_PIO_DEV, jtagsm);
|
||||
pio_remove_program(PINOUT_JTAG_PIO_DEV, &dap_jtag_program, offset);
|
||||
offset = jtagsm = -1;
|
||||
|
||||
sio_hw->gpio_oe_clr = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK |
|
||||
PINOUT_TDI_MASK //| PINOUT_TDO_MASK
|
||||
| PINOUT_nTRST_MASK | PINOUT_nRESET_MASK;
|
||||
}
|
||||
|
||||
static uint8_t bitswap(uint8_t in) {
|
||||
static const uint8_t lut[16] = {
|
||||
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
|
||||
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
|
||||
};
|
||||
|
||||
return (lut[in&0xf] << 4) | lut[in>>4];
|
||||
}
|
||||
|
||||
void JTAG_Sequence(uint32_t info, const uint8_t* tdi, uint8_t* tdo) {
|
||||
dap_jtag_program_init(PINOUT_JTAG_PIO_DEV, jtagsm, offset,
|
||||
50*1000, PINOUT_JTAG_TCK, PINOUT_JTAG_TDI, PINOUT_JTAG_TDO);
|
||||
|
||||
uint32_t n = info & JTAG_SEQUENCE_TCK;
|
||||
if (n == 0) n = 64;
|
||||
|
||||
if (info & JTAG_SEQUENCE_TMS) PIN_SWDIO_TMS_SET();
|
||||
else PIN_SWDIO_TMS_CLR();
|
||||
|
||||
io_wo_8* tx = (io_wo_8*)&PINOUT_JTAG_PIO_DEV->txf[jtagsm];
|
||||
io_ro_8* rx = (io_ro_8*)&PINOUT_JTAG_PIO_DEV->rxf[jtagsm];
|
||||
|
||||
uint32_t bytelen = (n + 7) >> 3;
|
||||
uint32_t last_shift = (8 - n) & 7;//(bytelen << 3) - n;
|
||||
printf("n=%lu bytelen=%lu last_shift=%lu\n", n, bytelen, last_shift);
|
||||
uint32_t txremain = bytelen,
|
||||
rxremain = last_shift ? bytelen : (bytelen /*+ 1*/);
|
||||
printf("txremain=%lu rxremain=%lu\n", txremain, rxremain);
|
||||
|
||||
printf("%s", "tdi: ");
|
||||
for (size_t j = 0; j < ((n + 7) >> 3); ++j) {
|
||||
printf("0x%x ", ((const uint8_t*)tdi)[j]);
|
||||
}
|
||||
|
||||
//printf("init : pc=%x insn=%04lx\n", pio_sm_get_pc(PINOUT_JTAG_PIO_DEV, jtagsm), pio0_hw->sm[jtagsm].instr);
|
||||
*tx = (uint8_t)(n - 1);
|
||||
//printf("txlen: pc=%x insn=%04lx\n", pio_sm_get_pc(PINOUT_JTAG_PIO_DEV, jtagsm), pio0_hw->sm[jtagsm].instr);
|
||||
//return;
|
||||
|
||||
bool done_extrabit = false;
|
||||
size_t oi = 0, ii = 0;
|
||||
while (txremain || rxremain) {
|
||||
if (txremain && !pio_sm_is_tx_fifo_full(PINOUT_JTAG_PIO_DEV, jtagsm)) {
|
||||
//printf("tdi%2u: pc=%x insn=%04lx\n", ii, pio_sm_get_pc(PINOUT_JTAG_PIO_DEV, jtagsm), pio0_hw->sm[jtagsm].instr);
|
||||
*tx = bitswap(tdi[ii]);
|
||||
--txremain;
|
||||
printf("tx %02x rem %lu smpc=%x\n", tdi[ii], txremain, pio_sm_get_pc(PINOUT_JTAG_PIO_DEV, jtagsm));
|
||||
++ii;
|
||||
}
|
||||
|
||||
if (rxremain && !pio_sm_is_rx_fifo_empty(PINOUT_JTAG_PIO_DEV, jtagsm)) {
|
||||
//printf("tdo%2u: pc=%x insn=%04lx\n", oi, pio_sm_get_pc(PINOUT_JTAG_PIO_DEV, jtagsm), pio0_hw->sm[jtagsm].instr);
|
||||
uint8_t ov = *rx;
|
||||
--rxremain;
|
||||
printf("rx %02x rem %lu smpc=%x\n", ov, rxremain, pio_sm_get_pc(PINOUT_JTAG_PIO_DEV, jtagsm));
|
||||
if ((info & JTAG_SEQUENCE_TDO) /*&& !(!last_shift && rxremain == 1)*/) {
|
||||
if (last_shift && oi == bytelen - 1) {
|
||||
tdo[oi] = bitswap(ov << last_shift);
|
||||
} else {
|
||||
tdo[oi] = bitswap(ov);
|
||||
}
|
||||
++oi;
|
||||
}
|
||||
}
|
||||
|
||||
/*if (rxremain == 1 && txremain == 0 && last_shift == 0) {
|
||||
printf("smpc=%x smin=%04lx\n",
|
||||
pio_sm_get_pc(PINOUT_JTAG_PIO_DEV, jtagsm), pio0_hw->sm[jtagsm].instr);
|
||||
|
||||
if (!pio_sm_is_tx_fifo_full(PINOUT_JTAG_PIO_DEV, jtagsm) && !done_extrabit) {
|
||||
done_extrabit = true;
|
||||
uint8_t last_byte = tdi[ii-1];
|
||||
uint8_t last_bit = last_byte & 0x80;
|
||||
printf("extrabit %x!\n", last_bit);
|
||||
*tx = last_bit ? 0xff : 0x00;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/*if (last_shift) {
|
||||
uint8_t* last = &tdo[bytelen-1];
|
||||
*last = bitswap(*last);
|
||||
*last <<= last_shift;
|
||||
*last = bitswap(*last);
|
||||
}*/
|
||||
|
||||
if (info & JTAG_SEQUENCE_TDO) {
|
||||
printf("%s", "\ntdo: ");
|
||||
for (size_t j = 0; j < ((n + 7) >> 3); ++j) {
|
||||
printf("0x%x ", ((const uint8_t*)tdo)[j]);
|
||||
}
|
||||
printf("%c", '\n');
|
||||
} else printf("%s", "\nno tdo\n");
|
||||
|
||||
/*uint32_t n = info & JTAG_SEQUENCE_TCK;
|
||||
if (n == 0) n = 64;
|
||||
|
||||
bool tms = info & JTAG_SEQUENCE_TMS;
|
||||
// SET TMS TO ^
|
||||
|
||||
|
@ -80,24 +274,48 @@ void JTAG_Sequence(uint32_t info, const uint8_t* tdi, uint8_t* tdo) {
|
|||
ov |= tdo << k;
|
||||
}
|
||||
|
||||
tdo[i] = ov;
|
||||
}
|
||||
if (info & JTAG_SEQUENCE_TDO) tdo[i] = ov;
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: the following ones can all be implemented in terms of JTAG_Sequence
|
||||
|
||||
static void jtag_seq(uint32_t num, int tms, const void* tdi, void* tdo) {
|
||||
static uint64_t last_bit = ~(uint64_t)0;
|
||||
uint64_t devnull = 0;
|
||||
|
||||
bool notdi, notdo;
|
||||
|
||||
if ((notdi = (tdi == NULL))) tdi = &last_bit;
|
||||
if ((notdo = (tdo == NULL))) tdo = &devnull;
|
||||
else tms |= JTAG_SEQUENCE_TDO;
|
||||
|
||||
uint32_t nreal;
|
||||
for (uint32_t i = 0; i < num; i += nreal) {
|
||||
uint32_t nmod = (num - i) & 63;
|
||||
nreal = nmod ? nmod : 64;
|
||||
|
||||
JTAG_Sequence(nmod | tms, (const uint8_t*)tdi + (i >> 3), (uint8_t*)tdo + (i >> 3));
|
||||
}
|
||||
|
||||
uint8_t lastbyte = *((const uint8_t*)tdi + (num >> 3));
|
||||
last_bit = (lastbyte & (1 << (num & 7))) ? ~(uint64_t)0 : (uint64_t)0;
|
||||
}
|
||||
|
||||
uint32_t JTAG_ReadIDCode(void) {
|
||||
// tdi=NULL: ~~0xff!~~ repeat last-seen bit, ignore otherwise
|
||||
// tdo=NULL: ignore
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
JTAG_Sequence((2+DAP_Data.jtag_dev.index)|0, NULL, NULL);
|
||||
jtag_seq(1, JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq(2+DAP_Data.jtag_dev.index, 0, NULL, NULL);
|
||||
uint32_t v=0, v2=0;
|
||||
JTAG_Sequence(31|0, NULL, &v);
|
||||
JTAG_Sequence(2|JTAG_SEQUENCE_TMS, NULL, &v2);
|
||||
v |= (v2 << 31 & 1);
|
||||
JTAG_Sequence(1|0, NULL, NULL);
|
||||
jtag_seq(31, 0, NULL, &v);
|
||||
jtag_seq(2, JTAG_SEQUENCE_TMS, NULL, &v2);
|
||||
v |= (v2 << 31);
|
||||
jtag_seq(1, 0, NULL, NULL);
|
||||
return v;
|
||||
|
||||
// TMS HI
|
||||
/*// TMS HI
|
||||
// TCK LOW; DELAY; TCK HI; DELAY (DRscan)
|
||||
// TMS LOW
|
||||
// TCK LOW; DELAY; TCK HI; DELAY (capture)
|
||||
|
@ -122,26 +340,30 @@ uint32_t JTAG_ReadIDCode(void) {
|
|||
// TMS LO
|
||||
// TCK LOW; DELAY; TCK HI; DELAY
|
||||
|
||||
return v;
|
||||
return v;*/
|
||||
}
|
||||
|
||||
void JTAG_IR(uint32_t ir) {
|
||||
JTAG_Sequence(2|JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
JTAG_Sequence(2|0, NULL, NULL);
|
||||
jtag_seq(2,JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq(2,0, NULL, NULL);
|
||||
uint64_t v = ~(uint64_t)0;
|
||||
JTAG_Sequence(DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]|0, &v, NULL);
|
||||
JTAG_Sequence((DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index]-1)|0, &ir, NULL);
|
||||
jtag_seq(DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index],0, &v, NULL);
|
||||
jtag_seq((DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index]-1),0, &ir, NULL);
|
||||
uint32_t ir2 = ir >> (DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index]-1);
|
||||
uint32_t n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index];
|
||||
if (n) {
|
||||
JTAG_Sequence(1|0, &(ir>>TODO_N), NULL);
|
||||
ir = -1;
|
||||
JTAG_Sequence((n-1)|0, &ir, NULL);
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, &ir, NULL);
|
||||
jtag_seq(1,0, &ir2, NULL);
|
||||
ir = ~(uint32_t)0;
|
||||
jtag_seq((n-1),0, &ir, NULL);
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, &ir, NULL);
|
||||
} else {
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, &(ir>>TODO_N), NULL);
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, &ir2, NULL);
|
||||
}
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq(1,0, NULL, NULL);
|
||||
PIN_TDI_OUT(1); // TODO: TDI HI
|
||||
|
||||
// TMS HI
|
||||
/*// TMS HI
|
||||
// TCK LOW; DELAY; TCK HI; DELAY (DRscan)
|
||||
// TCK LOW; DELAY; TCK HI; DELAY (IRscan)
|
||||
// TMS LO
|
||||
|
@ -180,50 +402,56 @@ void JTAG_IR(uint32_t ir) {
|
|||
// TCK LOW; DELAY; TCK HI; DELAY
|
||||
// TMS LO
|
||||
// TCK LOW; DELAY; TCK HI; DELAY
|
||||
// TDI HI
|
||||
// TDI HI*/
|
||||
}
|
||||
|
||||
static uint8_t xfer_base(uint32_t request, uint32_t* data; bool check_ack) {
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
JTAG_Sequence((2+DAP_Data.jtag_dev.index)|0, NULL, NULL);
|
||||
static uint8_t xfer_base(uint32_t request, uint32_t* data, bool check_ack) {
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq((2+DAP_Data.jtag_dev.index),0, NULL, NULL);
|
||||
uint32_t ack=0;
|
||||
JTAG_Sequence(3|0, &(request>>1), &ack);
|
||||
uint32_t reqsh1 = request>>1;
|
||||
jtag_seq(3,0, &reqsh1, &ack);
|
||||
// ack bits are 1,0,2, not 0,1,2 => swap bottom 2 bits
|
||||
ack = ((ack & 2) >> 1) | ((ack & 1) << 2) | (ack & ~(uint32_t)3);
|
||||
if (ack!=DAP_TRANSFER_OK && check_ack) {
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
goto exit;
|
||||
}
|
||||
} else ack=DAP_TRANSFER_OK;
|
||||
if (request & DAP_TRANSFER_RnW) { // read
|
||||
uint32_t val = 0;
|
||||
JTAG_Sequence(31|0, NULL, &val);
|
||||
jtag_seq(31,0, NULL, &val);
|
||||
uint32_t n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1;
|
||||
uint32_t valb = 0;
|
||||
if (n) {
|
||||
JTAG_Sequence(1|0, NULL, &(val>>31));
|
||||
JTAG_Sequence((n-1)|0, NULL, NULL);
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq(1,0, NULL, &valb);
|
||||
jtag_seq((n-1),0, NULL, NULL);
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
} else {
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, NULL, &(val>>31));
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, NULL, &valb);
|
||||
}
|
||||
*data = val | (valb << 31);
|
||||
} else {
|
||||
uint32_t val = *data;
|
||||
JTAG_Sequence(31|0, &val, NULL);
|
||||
uint32_t val = *data, valb=val>>31;
|
||||
jtag_seq(31,0, &val, NULL);
|
||||
uint32_t n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1;
|
||||
if (n) {
|
||||
JTAG_Sequence(1|0, &(val>>31), NULL);
|
||||
JTAG_Sequence((n-1)|0, NULL, NULL);
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq(1,0, &valb, NULL);
|
||||
jtag_seq((n-1),0, NULL, NULL);
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
} else {
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, &(val>>31), NULL);
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, &valb, NULL);
|
||||
}
|
||||
}
|
||||
exit:
|
||||
JTAG_Sequence(1|JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
JTAG_Sequence(1|0, NULL, NULL);
|
||||
// TODO: TDI HI (no clk)
|
||||
if (request & DAP_REQUEST_TIMESTAMP) DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
if (check_ack) JTAG_Sequence(DAP_Data.idle_cycles, NULL, NULL);
|
||||
jtag_seq(1,JTAG_SEQUENCE_TMS, NULL, NULL);
|
||||
jtag_seq(1,0, NULL, NULL);
|
||||
PIN_TDI_OUT(1); // TODO: TDI HI (no clk)
|
||||
if (request & DAP_TRANSFER_TIMESTAMP) DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
if (check_ack) jtag_seq(DAP_Data.transfer.idle_cycles, 0, NULL, NULL);
|
||||
return (uint8_t)ack;
|
||||
|
||||
|
||||
// TMS HI
|
||||
/*// TMS HI
|
||||
// TCK LOW; DELAY; TCK HI; DELAY
|
||||
// TMS LO
|
||||
// TCK LOW; DELAY; TCK HI; DELAY
|
||||
|
@ -327,7 +555,7 @@ exit:
|
|||
// TCK LOW; DELAY; TCK HI; DELAY
|
||||
}
|
||||
|
||||
return (uint8_t)ack;
|
||||
return (uint8_t)ack;*/
|
||||
}
|
||||
|
||||
void JTAG_WriteAbort(uint32_t data) {
|
||||
|
@ -337,5 +565,5 @@ void JTAG_WriteAbort(uint32_t data) {
|
|||
uint8_t JTAG_Transfer(uint32_t request, uint32_t* data) {
|
||||
return xfer_base(request, data, true);
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
|
|
|
@ -1,28 +1,55 @@
|
|||
; vim: set et:
|
||||
|
||||
.program dap_jtag
|
||||
.side_set 1 opt
|
||||
|
||||
; Pin assignments:
|
||||
; - TCK is side-set pin 0
|
||||
; - TDI is OUT pin 0
|
||||
; - TDO is IN pin 0
|
||||
;
|
||||
; Autopush and autopull must be enabled, and the serial frame size is set by
|
||||
; configuring the push/pull threshold (32 bits). Shift should be left
|
||||
;
|
||||
; data is captured on the leading edge of each TCK pulse, and
|
||||
; transitions on the trailing edge, or some time before the first leading edge.
|
||||
|
||||
start:
|
||||
jmp start
|
||||
pull ; get length-1 and disregard previous OSR state
|
||||
out x, 32 side 0 ; this moves the first 32 bits into X
|
||||
loop:
|
||||
out pins, 1 side 0 ; Stall here on empty (sideset proceeds even if instruction stalls, so we stall with SCK low
|
||||
in pins, 1 side 1 [1]
|
||||
jmp x-- loop side 0
|
||||
end:
|
||||
push side 0 ; Force the last ISR bits to be pushed to the tx fifo
|
||||
|
||||
|
||||
% c-sdk {
|
||||
static inline void dap_jtag_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud) {
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
|
||||
pio_gpio_init(pio, pin);
|
||||
gpio_pull_up(pin);
|
||||
|
||||
static inline void dap_jtag_program_init(PIO pio, uint sm, uint offset,
|
||||
uint16_t freq, uint pin_tck, uint pin_tdi, uint pin_tdo) {
|
||||
pio_sm_config c = dap_jtag_program_get_default_config(offset);
|
||||
sm_config_set_in_pins(&c, pin); // for WAIT, IN
|
||||
sm_config_set_jmp_pin(&c, pin); // for JMP
|
||||
// Shift to right, autopull disabled
|
||||
sm_config_set_in_shift(&c, true, false, 32);
|
||||
// SM transmits 1 bit per 8 execution cycles.
|
||||
float div = (float)clock_get_hz(clk_sys) / (8 * baud);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
sm_config_set_out_pins(&c, pin_tdi, 1);
|
||||
sm_config_set_in_pins(&c, pin_tdo);
|
||||
sm_config_set_sideset_pins(&c, pin_tck);
|
||||
// (shift to left, autopush/pull, threshold=nbits)
|
||||
sm_config_set_out_shift(&c, false, true, 8); // shift left feature is broken???
|
||||
sm_config_set_in_shift(&c, false, true, 8);
|
||||
sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / (4 * freq));
|
||||
|
||||
// TDI, TCK output are low, TDO is input
|
||||
pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_tck) | (1u << pin_tdi));
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, (1u << pin_tck) | (1u << pin_tdi),
|
||||
(1u << pin_tck) | (1u << pin_tdi) | (1u << pin_tdo));
|
||||
pio_gpio_init(pio, pin_tdi);
|
||||
//pio_gpio_init(pio, pin_tdo);
|
||||
pio_gpio_init(pio, pin_tck);
|
||||
|
||||
// jtag is synchronous, so bypass input synchroniser to reduce input delay.
|
||||
hw_set_bits(&pio->input_sync_bypass, 1u << pin_tdo);
|
||||
gpio_set_pulls(pin_tdo, false, true); // TDO is pulled down
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
//pio_sm_set_enabled(pio, sm, true);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
%}
|
||||
|
|
|
@ -25,16 +25,200 @@ void PORT_SWD_SETUP(void) {
|
|||
// TODO...
|
||||
}
|
||||
|
||||
void SWJ_Sequence(uint32_t count, const uint8_t* data) {
|
||||
// TODO: also hijack PIN_SWDIO_OUT_{DIS,EN}ABLE ! (used in DAP_SWD_Sequence)
|
||||
// TODO: also hijack DAP_SWJ_PINS(?: should data pins be controlled like that? only rst stuff tbh)
|
||||
|
||||
void SWJ_Sequence(uint32_t count, const uint8_t* data) {
|
||||
for (uint32_t i = 0, k = 0; i < count; ++i) {
|
||||
if ((i & 7) == 0) {
|
||||
val = data[k];
|
||||
++k;
|
||||
}
|
||||
|
||||
swdio = (val >> (i & 7)) & 1;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
}
|
||||
|
||||
void SWD_Sequence(uint32_t info, const uint8_t* swdo, uint8_t* swdi) {
|
||||
uint32_t n = info & SWD_SEQUENCE_CLK;
|
||||
if (n == 0) n = 64;
|
||||
|
||||
if (info & SWD_SEQUENCE_DIN) {
|
||||
for (uint32_t i = 0; i < n; ) {
|
||||
uint32_t v = 0;
|
||||
for (uint32_t k = 0; k < 8; ++k, ++i) {
|
||||
// SWCLK LO; DELAY
|
||||
// GET SWDIO; SWCLK HI; DELAY
|
||||
val |= swdio << k;
|
||||
}
|
||||
swdi[i >> 3] = v;
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < n; ) {
|
||||
uint32_t val = swdo[i >> 3];
|
||||
for (uint32_t k = 0; k < 8; ++i, ++k) {
|
||||
swdio = (val >> k) & 1;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SWD_Transfer(uint32_t request, uint32_t* data) {
|
||||
// TODO: to SWD_Sequence stuff(?)
|
||||
|
||||
uint32_t parity = 0;
|
||||
|
||||
swdio = 1;
|
||||
parity += swdio;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
swdio = (request >> 0) & 1;
|
||||
parity += swdio;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
swdio = (request >> 1) & 1;
|
||||
parity += swdio;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
swdio = (request >> 2) & 1;
|
||||
parity += swdio;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
swdio = (request >> 3) & 1;
|
||||
parity += swdio;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
|
||||
swdio = parity & 1;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
|
||||
swdio = 0;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
|
||||
swdio = 1;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
|
||||
// TODO: SWDIO is now input
|
||||
|
||||
for (size_t i = 0; i < DAP_Data.swd_conf.turnaround; ++i) {
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
|
||||
uint32_t ack = 0;
|
||||
|
||||
// SWCLK LO; DELAY
|
||||
// GET SWDIO; SWCLK HI; DELAY
|
||||
ack |= swdio << 0;
|
||||
// SWCLK LO; DELAY
|
||||
// GET SWDIO; SWCLK HI; DELAY
|
||||
ack |= swdio << 1;
|
||||
// SWCLK LO; DELAY
|
||||
// GET SWDIO; SWCLK HI; DELAY
|
||||
ack |= swdio << 2;
|
||||
|
||||
switch (ack) {
|
||||
case DAP_TRANSFER_OK:
|
||||
if (request & DAP_TRANSFER_RnW) { // read
|
||||
uint32_t val = 0;
|
||||
parity = 0;
|
||||
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
// SWCLK LO; DELAY
|
||||
// GET SWDIO; SWCLK HI; DELAY
|
||||
parity += swdio;
|
||||
val |= swdio << i;
|
||||
}
|
||||
|
||||
// SWCLK LO; DELAY
|
||||
// GET SWDIO; SWCLK HI; DELAY
|
||||
if ((parity & 1) != (swdio & 1)) {
|
||||
ack = DAP_TRANSFER_ERROR;
|
||||
}
|
||||
if (data) *data = val;
|
||||
|
||||
for (size_t i = 0; i < DAP_Data.swd_conf.turnaround; ++i) {
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
|
||||
// TODO: swdio is now output!
|
||||
} else { // write
|
||||
for (size_t i = 0; i < DAP_Data.swd_conf.turnaround; ++i) {
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
|
||||
// TODO: SWDIO is now output!
|
||||
|
||||
uint32_t val = *data;
|
||||
parity = 0;
|
||||
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
swdio = (val >> i) & 1;
|
||||
parity += swdio;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
swdio = parity;
|
||||
// SET SWDIO
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
|
||||
if (request & DAP_TRANSFER_TIMESTAMP) DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
|
||||
uint32_t n = DAP_Data.transfer.idle_cycles;
|
||||
if (n) {
|
||||
swdio = 0;
|
||||
// SET SWDIO
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
}
|
||||
|
||||
swdio = 1;
|
||||
// SET SWDIO (no clk!)
|
||||
|
||||
return (uint8_t)ack;
|
||||
|
||||
case DAP_TRANSFER_WAIT: case DAP_TRANSFER_FAULT:
|
||||
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0)) {
|
||||
for (size_t i = 0; i < 33; ++i) { // 32data + parity
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < DAP_Data.swd_conf.turnaround; ++i) {
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
|
||||
// TODO: SWDIO to output!
|
||||
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0)) {
|
||||
swdio = 0;
|
||||
// SET SWDIO
|
||||
for (size_t i = 0; i < 33; ++i) { // 32data + parity
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
}
|
||||
|
||||
swdio = 1;
|
||||
// SET SWDIO (no clk!)
|
||||
return (uint8_t)ack;
|
||||
|
||||
default: // protocol error
|
||||
for (uint32_t i = 0; i < DAP_Data.swd_conf.turnaround + 33; ++i) {
|
||||
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
||||
}
|
||||
|
||||
// TODO: SWDIO to output!
|
||||
swdio = 1;
|
||||
// SET SWDIO (no clk!)
|
||||
return (uint8_t)ack;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ static uint32_t
|
|||
static int swo_sm = -1, swo_dmach = -1;
|
||||
static bool mode_enabled = false;
|
||||
|
||||
#define SWO_PIO pio1
|
||||
#define SWO_PIO PINOUT_JTAG_SWO_DEV
|
||||
|
||||
// Enable or disable SWO Mode (UART)
|
||||
// enable: enable flag
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#define PINOUT_JTAG_TDO 5
|
||||
#define PINOUT_JTAG_nTRST 6
|
||||
#define PINOUT_JTAG_nRESET 7
|
||||
#define PINOUT_JTAG_PIO_DEV pio0
|
||||
#define PINOUT_JTAG_SWO_DEV pio1
|
||||
|
||||
// SPI config
|
||||
#define PINOUT_SPI_DEV spi1
|
||||
|
@ -60,6 +62,10 @@
|
|||
* SWO-MC 1
|
||||
*
|
||||
* PIO:
|
||||
* PIO0: (max. 4)
|
||||
* JTAG 1
|
||||
* PIO1: (max. 4)
|
||||
* SWO 2
|
||||
*
|
||||
* UART0: stdio
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue