-
-
Save fanoush/4a5dcf777503461297cedf7e21e3c6b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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