2021-09-22 00:31:09 +00:00
|
|
|
// vim: set et:
|
|
|
|
|
|
|
|
#include "DAP_config.h"
|
|
|
|
#include <DAP.h>
|
|
|
|
|
|
|
|
/*#define SWD_PIO*/
|
|
|
|
|
|
|
|
#ifndef SWD_PIO
|
|
|
|
void PORT_SWD_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_SWCLK_MASK | PINOUT_SWDIO_MASK;
|
|
|
|
sio_hw->gpio_set = PINOUT_SWCLK_MASK | PINOUT_SWDIO_MASK;
|
|
|
|
|
|
|
|
hw_write_masked(&padsbank0_hw->io[PINOUT_SWCLK], PADS_BANK0_GPIO0_IE_BITS,
|
|
|
|
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
|
|
|
hw_write_masked(&padsbank0_hw->io[PINOUT_SWDIO], PADS_BANK0_GPIO0_IE_BITS,
|
|
|
|
PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS);
|
|
|
|
iobank0_hw->io[PINOUT_SWCLK].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
|
|
|
iobank0_hw->io[PINOUT_SWDIO].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void PORT_SWD_SETUP(void) {
|
|
|
|
// TODO...
|
|
|
|
}
|
|
|
|
|
2021-09-24 01:41:25 +00:00
|
|
|
// 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)
|
|
|
|
|
2021-09-22 00:31:09 +00:00
|
|
|
void SWJ_Sequence(uint32_t count, const uint8_t* data) {
|
2021-09-24 01:41:25 +00:00
|
|
|
for (uint32_t i = 0, k = 0; i < count; ++i) {
|
|
|
|
if ((i & 7) == 0) {
|
|
|
|
val = data[k];
|
|
|
|
++k;
|
|
|
|
}
|
2021-09-22 00:31:09 +00:00
|
|
|
|
2021-09-24 01:41:25 +00:00
|
|
|
swdio = (val >> (i & 7)) & 1;
|
|
|
|
// SET SWDIO
|
|
|
|
// SWCLK LO; DELAY; SWCLK HI; DELAY
|
|
|
|
}
|
2021-09-22 00:31:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SWD_Sequence(uint32_t info, const uint8_t* swdo, uint8_t* swdi) {
|
2021-09-24 01:41:25 +00:00
|
|
|
uint32_t n = info & SWD_SEQUENCE_CLK;
|
|
|
|
if (n == 0) n = 64;
|
2021-09-22 00:31:09 +00:00
|
|
|
|
2021-09-24 01:41:25 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-22 00:31:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SWD_Transfer(uint32_t request, uint32_t* data) {
|
2021-09-24 01:41:25 +00:00
|
|
|
// 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
|
|
|
|
}
|
2021-09-22 00:31:09 +00:00
|
|
|
|
2021-09-24 01:41:25 +00:00
|
|
|
// TODO: SWDIO to output!
|
|
|
|
swdio = 1;
|
|
|
|
// SET SWDIO (no clk!)
|
|
|
|
return (uint8_t)ack;
|
|
|
|
}
|
2021-09-22 00:31:09 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|