Skip to content

Instantly share code, notes, and snippets.

@fanoush

fanoush/swd.js Secret

Created January 10, 2023 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fanoush/4a5dcf777503461297cedf7e21e3c6b3 to your computer and use it in GitHub Desktop.
Save fanoush/4a5dcf777503461297cedf7e21e3c6b3 to your computer and use it in GitHub Desktop.
// SWD protocol implementation for STLINKV2 clone dongle
// uses pins B13,B14 for SWDCLK, SWDIO
// stlinkV2 dongle swd_setup(B13,B14);
// nrf52840 dongle swd_setup(D4,D26);
// benchmark
// var d=Date().ms;readmem(0x20000000,128,4);Date().ms-d;
//
/*
var swd=E.compiledC(`
// int init(JsVar)
// void deinit()
// int read(int)
// void write(int, int)
// int sendReq(int, bool, bool)
// int tran(bool,bool,int,int)
// int parity32(int)
// void setEXPTR(int)
// void swd_mode(JsVar)
// int shiftBitsIn(int)
// int shiftBitsOut(int, int)
//__attribute__((section(".text"))) void **EXPTR;
static void setEXPTR(void **ptr){
EXPTR=ptr;
}
//#define NULL ((void*)0)
// everything gets linked together and loaded to RAM as one binary
// however gcc produces shorter code when variables are put to ".text" segment
#define __code __attribute__((section(".text")))
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Very dodgy reference holding implementation, that allows us to pass most of the locking/unlocking to GCC.
// Mostly this gets collapsed down to virtually nothing, but assignments create a jsvLockAgainSafe.
// copy from EspruinoCompiler
class SV {
JsVar *v;
bool owned;
public:
inline __attribute__((always_inline)) SV( const SV& o ) { owned = true; v = jsvLockAgainSafe(o.v); }
inline __attribute__((always_inline)) SV &operator=(const SV &o) {
if (owned) jsvUnLock(v); owned = true; v = jsvLockAgainSafe(o.v); return *this;
}
inline __attribute__((always_inline)) SV(JsVar *value) { owned = true; v=value; }
inline __attribute__((always_inline)) SV() { owned = false; v=0; }
inline __attribute__((always_inline)) ~SV() { if (owned) jsvUnLock(v); }
inline __attribute__((always_inline)) operator JsVar*() const { return v; }
static inline __attribute__((always_inline)) SV notOwned(JsVar *value) {
SV s = SV(value); s.owned = false; return s;
}
inline __attribute__((always_inline)) JsVar *give() {
if (!owned) v = jsvLockAgainSafe(v); owned = false; return v;
}
};
//#define NULLVAR ((JsVar *)0)
__code struct {
JsVar *pinMode;
JsVar *inputpullup;
JsVar *output;
JsVar *swdclk;
JsVar *swdclk_reset;
JsVar *swdclk_set;
JsVar *swdio;
JsVar *swdio_reset;
JsVar *swdio_set;
JsVar *swdio_read;
JsVar *ACK;
} vars;
JsVar *getVarValue(const char *varName){
return jsvSkipName(SV(jspGetNamedVariable(varName)));
}
JsVar *getObjPropertyValue(JsVar *obj, const char *propName){
return jsvSkipName(SV(jspGetNamedField(obj, propName, 0)));
}
__code int inited=0;
void deinit(){
if (!inited) return;
JsVar **varptr = (JsVar **)&vars;
for (int i=0;i<(sizeof(vars)/sizeof(JsVar*));i++)
jsvUnLock(varptr[i]);
inited=0;
}
int init(JsVar *obj){
if (inited) deinit();
vars.ACK=jspGetNamedField(obj, "ACK", 1); //1=get name not value
//jspReplaceWith(vars.ACK, SV(jsvNewFromInteger(1)));
// pinMode() call setup
vars.pinMode = getVarValue("pinMode");
vars.inputpullup = jsvNewFromString("input_pullup");
vars.output = jsvNewFromString("output");
// CLK pin
vars.swdclk = getObjPropertyValue(obj,"CLK");
vars.swdclk_reset=jspGetNamedField(vars.swdclk, "reset", 0);
vars.swdclk_set=jspGetNamedField(vars.swdclk, "set", 0);
// IO pin
vars.swdio = getObjPropertyValue(obj,"IO");
vars.swdio_reset= jspGetNamedField(vars.swdio, "reset", 0);
vars.swdio_set=jspGetNamedField(vars.swdio, "set", 0);
vars.swdio_read=jspGetNamedField(vars.swdio, "read", 0);
inited=1;
return 0;
}
__code JsVar *noargs[0] = {};
static void toggleClk(){
({SV(jspeFunctionCall(vars.swdclk_reset, 0, vars.swdclk, 0, 0, noargs));});
({SV(jspeFunctionCall(vars.swdclk_set, 0, vars.swdclk, 0, 0, noargs));});
}
static bool ioRead(){
return jsvGetBool(SV(jsvSkipName(SV(jspeFunctionCall(vars.swdio_read, 0, vars.swdio , 0, 0, noargs)))));
}
static void ioWrite(bool val){
SV(jspeFunctionCall(val ? vars.swdio_set : vars.swdio_reset, 0, vars.swdio, 0, 0, noargs));
}
static void ioMode(JsVar *mode){
JsVar *args[2] = {vars.swdio, mode};
SV(jspeFunctionCall(vars.pinMode, 0, 0, 0, 2, args));
}
static void ioModeOutput(){
ioMode(vars.output);
}
static void ioModeInput(){
ioMode(vars.inputpullup);
}
uint32_t shiftBitsIn(int numBits) {
uint32_t val = 0;
int bit = 1;
int i = numBits;
while (i--) {
if (ioRead()) {
val |= bit;
}
toggleClk();
bit<<=1;
}
return val;
}
void shiftBitsOut(uint32_t data, int numBits) {
uint32_t val = 0;
int i = numBits;
while (i--) {
ioWrite(data&1);
toggleClk();
data>>=1;
}
}
__code int swdMode=0; // SWDIO pin mode, 1 = Write 0 = Read
// switching SWDIO mode needs one extra clock
void modeSwitch(int mode){
if (mode == swdMode) return;
if (mode == 0) ioModeInput();
toggleClk();
if (mode) ioModeOutput();
swdMode=mode;
}
uint32_t read(int numBits){
modeSwitch(0);
return shiftBitsIn(numBits);
}
void write(uint32_t data, int numBits){
modeSwitch(1);
shiftBitsOut(data,numBits);
}
// compute parity bit
bool parity32(uint32_t val){
val = (val & 0xFFFF) ^ (val >> 16);
val = (val & 0xFF) ^ (val >> 8);
val = (val & 0xF) ^ (val >> 4);
val = (val & 0x3) ^ (val >> 2);
val = (val & 0x1) ^ (val >> 1);
return val;
}
// send SWD request, return ACK response
int sendReq(int regAddr, bool APorDP, bool RorW){
bool parity = APorDP ^ RorW ^ ((regAddr >> 2) & 1) ^ ((regAddr >> 3) & 1);
uint8_t req = (1 << 0) | (APorDP << 1) | (RorW << 2) | ((regAddr & 0xC) << 1) | (parity << 5) | (1 << 7);
write(req, 8);
int ack=read(3);
jspReplaceWith(vars.ACK, SV(jsvNewFromInteger(ack)));
return ack;
}
uint32_t tran(bool APorDP, bool RorW, int regAddr,uint32_t u32data)
{
int ack=sendReq(regAddr,APorDP, RorW);
if (ack == 1) // OK
{
if (RorW)
{ // Reading 32 bits from SWD
u32data = read(32);
if (read(1) != parity32(u32data))
{
ack = -1; // parity error
jspReplaceWith(vars.ACK, SV(jsvNewFromInteger(ack)));
}
return u32data;
}
else
{ // Writing 32 bits to SWD
write(u32data, 32);
write(parity32(u32data), 1);
return true;
}
}
//write(0, 32);//If Overrun Detection is enabled then a data phase is required on FAULT or WAIT
return 0;
}
`);
//
*/
///*
if (process.memory().stackEndAddress) // this is defined for NRF and STM32 platforms, not for ESP32/8266
var swd = (function(){
var bin=atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABO1Bkx8RCRozekAIwAjCkZkaxlGoEcCsBC9AL8cBAAAg7KD6hBAw7KD6hAjA/APAIDqExMD8AMAgOqTAADwAQOD6lAAcEcAAAFLe0QYYHBH1gMAAAJLe0QbaNtrGEcAv8oDAAACS3tEG2ibaBhHAL+6AwAAAkt7RBtoW2gYRwC/qgMAABO1B0wCInxEo2kAIc3pADBrRiBo//ey///36v8CsBC9Pv///zi1C0wAInxEBPEsBStG1OkDEP/3of//99n/K0bhaGBpACL/95n/veg4QP/3z78Avxr///84tQhMfETlalW5VPgECwE1//fC/wst+NEAIgNLe0TaYji9AL/o/v//0P7//zhLLenwQXtE22oHRgux//fh/zVJASJ5RDhG//eX/zNMM018RH1EoGIraDJIm2t4RJhHgEb/95L/BkZARv/3lv8raC1IJmDbaXhEmEcraGBgKkjbaXhEmEcpSQAieUSgYDhG//dz/wZG//d4/wVGMEYkTv/3e/9+RDFGACIoRuVg//dk/yBNIGF9RClGACLgaP/3XP8dSQAieURgYThG//dV/4BG//da/wdGQEb/917/MUYAIjhGp2H/90j/KUbgYQAioGn/90L/EUkgYgAieUSgaf/3O/8BI2Bi42IAIL3o8IEAv7r+///OAgAAnv7///QCAAC6AgAAqAIAAKkCAACoAgAAkgIAAIICAAB2AgAAQwIAAC3p908bTAZGfEQjazOxYGj/9yr///c6/wAjI2MBJQAkFU/f+FiQf0QH8SwI+UQW8f82G9NDRrlpACJ4av/30v6DRv/3Af/Z+AAggkbSapBHAZBQRv/3AP9YRv/3/f4BmwOxLEP/9xL/bQDg5yBGA7C96PCPpP3//4b9///YAQAALen4QxVOBEZ+RDNrDUYBKwbQ//f7/rBo//fm/gEjM2MPTt/4QIB+RPhEBvEsCRXx/zUR09jpB3AU8AEPS0ZP8AACsWkIvzhG//eM/v/3xP5kCP/32/7q573o+IMk/f//Bv3//wT9///4tcMQg+qgA4HqAgQD8AEDQABjQADwGABA6kMQQOqCAEDqQQBg8H4ACCHAsv/3tP8DIP/3cf8KTQpLfUR7RJ9qK2gGRptpmEcERitoAUYbazhGmEcgRv/3i/4wRvi9AL/iAAAAiPz///i1FUYORgpGAUYoRhxG//fD/wEoBUYu0Q6zICD/90j/BEYoRv/3RP8CRiBG//dC/oJCEtARSxJOe0R+RJ9qM2hP8P8wm2mYRwVGM2gBRhtrOEaYRyhG//dX/iBG+L0gISBG//dl/yBG//ck/ilG//df/yxG8ecAJO/nAL8k/P//egAAAEFDSwBwaW5Nb2RlAGlucHV0X3B1bGx1cABvdXRwdXQAQ0xLAHJlc2V0AElPAHJlYWQAAABYnAEI");
(E.nativeCall(125, "void(int)", bin))(process.env.EXPTR); // call setEXPTR once here
return {
init:E.nativeCall(317, "int(JsVar)", bin),
deinit:E.nativeCall(273, "void()", bin),
read:E.nativeCall(593, "int(int)", bin),
write:E.nativeCall(721, "void(int, int)", bin),
sendReq:E.nativeCall(825, "int(int, bool, bool)", bin),
tran:E.nativeCall(929, "int(bool,bool,int,int)", bin),
parity32:E.nativeCall(85, "int(int)", bin),
// setEXPTR:E.nativeCall(125, "void(int)", bin),
};
})();
else {
// possibly unknown non-ARM platform with no compiler
var swd={};
swd.init = function(obj){
obj.ShiftOut=shiftOut.bind(null,obj.IO,{clk:obj.CLK,repeat:8});
obj.SPI=new SPI();
obj.SPI.setup({sck:obj.CLK,miso:obj.IO,order:"msb",mode:2,bits:8});
};
swd.deinit = function(){
};
swd.read = function(numBits){
};
swd.write = function(data, numBits){
};
swd.sendReq = function(regAddr,APorDP,RorW){
};
swd.tran = function(APorDP,RorW,regAddr,u32data){
};
swd.parity32=function(val){
val = (val & 0xFFFF) ^ (val >>> 16);
val = (val & 0xFF) ^ (val >> 8);
val = (val & 0xF) ^ (val >> 4);
val = (val & 0x3) ^ (val >> 2);
return (val & 0x1) ^ (val >> 1);
};
swd.rbitswap = function(x){
x = (( ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1)>>>0) )>>>0;
x = (( ((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2)>>>0) )>>>0;
return (( ((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)>>>0) )>>>0;
};
}
//*/
function swd_setup(clkPin, ioPin)
{
swd.CLK=clkPin;
swd.IO=ioPin;
swd.ACK=0; // 1 OK, 2 WAIT, 4 FAULT
pinMode(ioPin, "input_pullup");
pinMode(clkPin, "output");
swd.init(swd);
clkPin.set();
}
const AP_CSW = 0x00;
const AP_TAR = 0x04;
const AP_DRW = 0x0c;
const AP_BD0 = 0x10;
const AP_BD1 = 0x14;
const AP_BD2 = 0x18;
const AP_BD3 = 0x1c;
const AP_DBGDRAR = 0xf8;
const AP_IDR = 0xfc;
const DP_IDCODE = 0x00; // R
const DP_ABORT = 0x00; // W
const DP_CTRLSTAT = 0x04; // RW
const DP_RESEND = 0x08; // R
const DP_SELECT = 0x08; // W
const DP_RDBUFF = 0x0c; // R
//var is_connected=false;
var muted=0;
function nrf_begin()
{
var idcode = swd_init();
if (idcode == 0x2ba01477)
{ //if core id is readable the connection is working
dap_poweron();
//is_connected = true;
if (nrf_read_lock_state())
{ //nRF is unlocked so we can talk to the debugging interface
//nrf_read_ficr();
print("nrf52 is unlocked");
}
}
else
{
is_connected = false;
}
return idcode;
}
function stm32_begin(){
var idcode = swd_init(true);
if (idcode == 0x1ba01477){
dap_poweron();
writemem32(0xE0042004,7);// DBGMCU_SLEEP|STOP|STANDBY keep debugger running
var AHBENR=readmem32(0x40021014); // RCC.ahbenr = 0x40021014
writemem32(0x40021014,AHBENR|1); // RCC_AHBPeriph_DMA1
var stm32id=readmem32(0xE0042000).toString(16);
print("STM32 DEVID",stm32id.slice(-4),"REVID",stm32id.slice(0,-4));
}
}
dapBank=0;
dapAP=0;
function dap_select(ap, bank){
dapAP=(ap|0)&255;
dapBank=(bank|0)&15;
DP_Write(DP_SELECT,((dapAP<<24)|(dapBank<<4)>>>0)); //Select AP
}
const AP_NRF_APPROTECTSTATUS = 0x0c;
function nrf_read_lock_state()
{
dap_select(1);
var temp = dap_read(AP_NRF_APPROTECTSTATUS);
dap_select(0);
return temp & 1;
}
function dap_read(regAddr)
{
if (regAddr>>4 != dapBank) dap_select(dapAP,regAddr>>4);
var temp = AP_Read(regAddr&15);
temp = DP_Read(DP_RDBUFF);
if (temp==null) dap_handle_fault("dap_read");
//else print("Read reg: 0x"+regAddr.toString(16)+" : 0x"+temp.toString(16));
return temp;
}
function dap_write(regAddr, value)
{
if (regAddr>>4 != dapBank) dap_select(dapAP,regAddr>>4);
var temp = AP_Write(regAddr&15, value);
temp = DP_Read(DP_RDBUFF);
if (temp==null) return dap_handle_fault("dap_write");
//else print("Write reg: 0x"+regAddr.toString(16)+" : 0x"+value.toString(16));
return true;
}
function dap_handle_fault(msg){
if (swd.ACK==1) return true;
if (swd.ACK==4){ // FAULT
DP_Write(DP_ABORT, 0x1e);
print(msg,"SWD FAULT, CTRLSTAT="+DP_Read(DP_CTRLSTAT).toString(16));
}
else if (swd.ACK==2){ // TIMEOUT
print(msg,"SWD TIMEOUT, CTRLSTAT="+DP_Read(DP_CTRLSTAT).toString(16));
} else {
print(msg,"SWD ACK="+swd.ACK+", no respone?");
}
return false;
}
function dap_poweroff(){
DP_Write(DP_ABORT, 0x1e);
DP_Write(DP_CTRLSTAT,0);
}
function dap_poweron()
{
DP_Write(DP_ABORT, 0x1e);
DP_Write(DP_CTRLSTAT, 0x50000000); // powerup system and debug domain
var retries=3; while(retries--) if (DP_Read(DP_CTRLSTAT)>>>28 == 0xF) break;
if (retries<1) return false;
dap_write(AP_CSW, 0x23000002); // 32 bit read, no increment
return true;
}
function readmem(addr,len,size, buff){
if(!buff||buff.length!=len) buff=Uint32Array(len);
if(!size) size=4;
if(size==4) dap_write(AP_CSW, 0x23000012); //32bit with increment
else if (size==2)dap_write(AP_CSW, 0x23000011); //16bit TAR increment
else if (size==1)dap_write(AP_CSW, 0x23000010); //8bit TAR increment
else return null;
if (len<1) return null;
if (!AP_Write(AP_TAR, addr)) return null;
AP_Read(AP_DRW);//schedule read, AP reads are delayed by one
readloop(buff,len,addr,size);
if(swd.ACK!=1) return dap_handle_fault();
return buff;
}
function readloop(buff,len,addr,size){
// "compiled"; won't work with array [] access
var val;var idx=0;
while(--len>0){
val=AP_Read(AP_DRW);
if(swd.ACK!=1) return idx;
buff[idx++]=val;
}
val=DP_Read(DP_RDBUFF);buff[idx++]=val; // last delayed value
return idx;
}
function readmem32(address)
{
var val = 0;
if (!dap_write(AP_TAR, address)) return null;
AP_Read(AP_DRW); // schedule read
val=DP_Read(DP_RDBUFF);
if (muted) return val;
print("Read memory: 0x"+address.toString(16)+" : 0x"+val.toString(16));
return val;
}
function writemem32(address, value)
{
var temp = 0;
if (!dap_write(AP_TAR, address)) return null;
AP_Write(AP_DRW, value);
temp=DP_Read(DP_RDBUFF);
if (muted) return temp!=null;
if (!muted) print("Write memory: 0x"+address.toString(16)+" : 0x"+value.toString(16));
return temp!=null;
}
function swd_init(jtag2swd)
{ //Returns the ID
if(!(swd.CLK && swd.IO)) {print("setup pins via swd_setup(clkPin,dioPin)!");return null;}
if (jtag2swd){
swd.write(0xffffffff, 32);
swd.write(0xffffffff, 32);
swd.write(0xe79e, 16); // JTAG to SWD 0x79e7
}
swd.write(0xffffffff, 32);
swd.write(0xffffffff, 32);
swd.write(0, 32);
swd.write(0, 32);
return DP_Read(DP_IDCODE);
}
function AP_Write(regAddr, data)
{
var retry = 25;
do {
var res = swd.tran(1, 0, regAddr, data);
if (swd.ACK==1)
return true;
if (swd.ACK!=2) return null; // don't retry if not WAIT
if (!muted) print("AP_Write retrying");
} while (retry--);
DP_Write(DP_ABORT,1);//still waiting, abort
return false;
}
// send AP read request
// AP reads are 'posted' = real data is in next AP read or DP RDBUFF read
function AP_Read(regAddr)
{
var retry = 25;
do {
var data = swd.tran(1,1,regAddr)>>>0;
if (swd.ACK==1)
return data;
if (swd.ACK!=2) return null; // don't retry if not WAIT
if (!muted) print("AP_Read","0x"+regAddr.toString(16),"retry",25-retry);
} while (retry--);
DP_Write(DP_ABORT,1);//still waiting, abort
return null;
}
// write DP register
function DP_Write(regAddr, data)
{
var retry = 25;
do {
var res = swd.tran(0,0,regAddr,data);
if (swd.ACK==1)
return true;
if (swd.ACK!=2) return null; // don't retry if not WAIT
if (!muted) print("DP_Write retrying");
} while (retry--);
DP_Write(DP_ABORT,1);//still waiting, abort
return false;
}
// read DP register
function DP_Read(regAddr)
{
var retry = 25;
do {
var data = swd.tran(0,1,regAddr)>>>0;
if (swd.ACK==1)
return data;
if (swd.ACK!=2) return null; // don't retry if not WAIT
if (!muted) print("DP_Read","0x"+regAddr.toString(16),"retry",25-retry);
} while (retry--);
DP_Write(DP_ABORT,1);//still waiting, abort
return null;
}
/*
//32bit SWD transaction
function swd_tran(APorDP,RorW,regAddr,u32data)
{
swd.sendReq(regAddr,APorDP, RorW);
if (swd.ACK == 1) // OK
{
if (RorW)
{ // Reading 32 bits from SWD
u32data = swd.read(32)>>>0;
if (swd.read(1) == swd.parity32(u32data))
{
return u32data;
}else print("bad parity for 0x"+u32data.toString(16));
}
else
{ // Writing 32 bits to SWD
swd.write(u32data, 32);
swd.write(swd.parity32(u32data), 1);
return true;
}
}
//swd.write(0, 32);//If Overrun Detection is enabled then a data phase is required on FAULT or WAIT
return null;
}
*/
//var SWDCLK;
//var SWDIO;
/*
var c=E.compiledC(`
// int swdreq(int,bool,bool)
// int parity32(int)
// int rbitswap(int)
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
// compute parity bit
bool parity32(uint32_t val){
val = (val & 0xFFFF) ^ (val >> 16);
val = (val & 0xFF) ^ (val >> 8);
val = (val & 0xF) ^ (val >> 4);
val = (val & 0x3) ^ (val >> 2);
val = (val & 0x1) ^ (val >> 1);
return val;
}
//create SWD request byte
uint8_t swdreq(uint8_t regAddr, bool APorDP, bool RorW){
bool parity = APorDP ^ RorW ^ ((regAddr >> 2) & 1) ^ ((regAddr >> 3) & 1);
uint8_t req = (1 << 0) | (APorDP << 1) | (RorW << 2) | ((regAddr & 0xC) << 1) | (parity << 5) | (1 << 7);
return req;
}
// swap bit order MSB to LSB and reverse endianness
uint32_t rbitswap(uint32_t x)
{
//x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
//x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
//return
//x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
return((x >> 16) | (x << 16));
}
`);
*/
/*
function shiftBitsOut(io,clk,data,numBits){
//"compiled";
var val=data|0;
var i=numBits|0;
while (i){
i--;
io.write(val&1);
clk.reset();
clk.set();
val>>=1;
}
}
function shiftBitsIn(io,clk,numBits){
//"compiled";
var val=0;
var bit=1;
var i=numBits|0;
while (i){
i--;
if (io.read()) val|=bit;
clk.reset();
clk.set();
bit<<=1;
}
return val;
}
*/
/*
// write bits in LSB order
function swd_write(data, bits)
{
//if (swdMode != 1)
swd_mode(1);
//return shiftBitsOut(SWDIO,SWDCLK,data,bits);
if (bits==8) return swdShiftOut([data]);
else if (bits==32) return swdShiftOut([data,data>>8,data>>16,data>>>24]);
else while (bits--)
{
digitalWrite(SWDIO, data & 1);
SWDCLK.reset();
//delayus(2);
data >>>= 1;
SWDCLK.set();
//delayus(2);
}
}
var ra=Uint8Array(4);
// read bits in LSB order
function swd_read(bits)
{
//if (swdMode != 0)
swd_mode(0);
return swd.shiftBitsIn(bits)>>>0;
//return shiftBitsIn(SWDIO,SWDCLK,bits);
if (bits==32 && swdSPI){
var a=swdSPI.send(ra);
return rbitswap(Uint32Array(a.buffer)[0])>>>0;
}
var data = 0;
var bit = 1;
var clk=SWDCLK.write.bind(SWDCLK);
while (bits--)
{
if (SWDIO.read())
{
data |= bit;
}
clk(0);
bit <<= 1;
clk(1);
}
return data>>>0; //make unsigned
}
*/
/*
var swdMode; // SWDIO pin mode, 1 = Write 0 = Read
// change SWDIO pin mode
function swd_mode(WorR)
{ //1 = Write 0 = Read
"compiled";
if (WorR == swdMode) return 0; // nothing to do
if (!WorR){
//digitalWrite(SWDIO, HIGH); // help with pull up
pinMode(SWDIO,"input_pullup");
}
SWDCLK.reset();
//delayus(2);
SWDCLK.set();
//delayus(2);
if (WorR)
pinMode(SWDIO,"output");
swdMode = WorR;
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment