Add serial support over webusb (#975)
* Add serial support over webusb * Disable DAPLink serial on older firmware * Disable sendMany - doesn't work with hidbridge at the moment
This commit is contained in:
		@@ -32,24 +32,30 @@ namespace pxt.editor {
 | 
				
			|||||||
    class DAPWrapper {
 | 
					    class DAPWrapper {
 | 
				
			||||||
        cortexM: DapJS.CortexM
 | 
					        cortexM: DapJS.CortexM
 | 
				
			||||||
        packetIo: HF2.PacketIO;
 | 
					        packetIo: HF2.PacketIO;
 | 
				
			||||||
 | 
					        cmsisdap: any;
 | 
				
			||||||
 | 
					        flashing = true;
 | 
				
			||||||
 | 
					        private useSerial = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        constructor(h: HF2.PacketIO) {
 | 
					        constructor(h: HF2.PacketIO) {
 | 
				
			||||||
            this.packetIo = h;
 | 
					            this.packetIo = h;
 | 
				
			||||||
            let pbuf = new U.PromiseBuffer<Uint8Array>();
 | 
					            let pbuf = new U.PromiseBuffer<Uint8Array>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
            let sendMany = (cmds: Uint8Array[]) => {
 | 
					            let sendMany = (cmds: Uint8Array[]) => {
 | 
				
			||||||
                return h.talksAsync(cmds.map(c => ({ cmd: 0, data: c })));
 | 
					                return h.talksAsync(cmds.map(c => ({ cmd: 0, data: c })));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!h.talksAsync)
 | 
					            if (!h.talksAsync)
 | 
				
			||||||
                sendMany = null;
 | 
					                sendMany = null;
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let dev = new DapJS.DAP({
 | 
					            let dev = new DapJS.DAP({
 | 
				
			||||||
                write: writeAsync,
 | 
					                write: writeAsync,
 | 
				
			||||||
                close: this.disconnectAsync,
 | 
					                close: this.disconnectAsync,
 | 
				
			||||||
                read: readAsync,
 | 
					                read: readAsync,
 | 
				
			||||||
                sendMany: sendMany
 | 
					                //sendMany: sendMany
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					            this.cmsisdap = (dev as any).dap;
 | 
				
			||||||
            this.cortexM = new DapJS.CortexM(dev);
 | 
					            this.cortexM = new DapJS.CortexM(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            h.onData = buf => {
 | 
					            h.onData = buf => {
 | 
				
			||||||
@@ -63,11 +69,48 @@ namespace pxt.editor {
 | 
				
			|||||||
            function readAsync() {
 | 
					            function readAsync() {
 | 
				
			||||||
                return pbuf.shiftAsync();
 | 
					                return pbuf.shiftAsync();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const readSerial = () => {
 | 
				
			||||||
 | 
					                if (!this.useSerial) {
 | 
				
			||||||
 | 
					                    return
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (this.flashing) {
 | 
				
			||||||
 | 
					                    setTimeout(readSerial, 300)
 | 
				
			||||||
 | 
					                    return
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                this.cmsisdap.cmdNums(0x83, [])
 | 
				
			||||||
 | 
					                    .then((r: number[]) => {
 | 
				
			||||||
 | 
					                        const len = r[1]
 | 
				
			||||||
 | 
					                        let str = ""
 | 
				
			||||||
 | 
					                        for (let i = 2; i < len + 2; ++i) {
 | 
				
			||||||
 | 
					                            str += String.fromCharCode(r[i])
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        if (str.length > 0) {
 | 
				
			||||||
 | 
					                            U.nextTick(readSerial)
 | 
				
			||||||
 | 
					                            window.postMessage({
 | 
				
			||||||
 | 
					                                type: 'serial',
 | 
				
			||||||
 | 
					                                id: 'n/a', // TODO
 | 
				
			||||||
 | 
					                                data: str
 | 
				
			||||||
 | 
					                            }, "*")
 | 
				
			||||||
 | 
					                            // console.log("SERIAL: " + str)
 | 
				
			||||||
 | 
					                        } else
 | 
				
			||||||
 | 
					                            setTimeout(readSerial, 50)
 | 
				
			||||||
 | 
					                    }, (err: any) => {
 | 
				
			||||||
 | 
					                        setTimeout(readSerial, 1000)
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            readSerial()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        reconnectAsync(first: boolean) {
 | 
					        reconnectAsync(first: boolean) {
 | 
				
			||||||
            if (!first)
 | 
					            if (!first)
 | 
				
			||||||
                return this.packetIo.reconnectAsync()
 | 
					                return this.packetIo.reconnectAsync()
 | 
				
			||||||
 | 
					                    // configure serial at 115200
 | 
				
			||||||
 | 
					                    .then(() => this.cmsisdap.cmdNums(0x82, [0x00, 0xC2, 0x01, 0x00]))
 | 
				
			||||||
 | 
					                    .then(() => {}, err => { this.useSerial = false })
 | 
				
			||||||
                    .then(() => this.cortexM.init())
 | 
					                    .then(() => this.cortexM.init())
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                return this.cortexM.init();
 | 
					                return this.cortexM.init();
 | 
				
			||||||
@@ -117,7 +160,9 @@ namespace pxt.editor {
 | 
				
			|||||||
                let w = new DAPWrapper(h)
 | 
					                let w = new DAPWrapper(h)
 | 
				
			||||||
                previousDapWrapper = w;
 | 
					                previousDapWrapper = w;
 | 
				
			||||||
                return w.reconnectAsync(true)
 | 
					                return w.reconnectAsync(true)
 | 
				
			||||||
                    .then(() => w)
 | 
					                    .then(() => {
 | 
				
			||||||
 | 
					                        return w
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -290,7 +335,15 @@ namespace pxt.editor {
 | 
				
			|||||||
        let checksums: Uint8Array
 | 
					        let checksums: Uint8Array
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pxt.tickEvent("hid.flash.start");
 | 
					        pxt.tickEvent("hid.flash.start");
 | 
				
			||||||
        return initAsync()
 | 
					        return Promise.resolve()
 | 
				
			||||||
 | 
					            .then(() => {
 | 
				
			||||||
 | 
					                if (previousDapWrapper) {
 | 
				
			||||||
 | 
					                    previousDapWrapper.flashing = true
 | 
				
			||||||
 | 
					                    return Promise.delay(100)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return Promise.resolve()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .then(initAsync)
 | 
				
			||||||
            .then(w => {
 | 
					            .then(w => {
 | 
				
			||||||
                wrap = w
 | 
					                wrap = w
 | 
				
			||||||
                log("reset")
 | 
					                log("reset")
 | 
				
			||||||
@@ -370,6 +423,9 @@ namespace pxt.editor {
 | 
				
			|||||||
                        pxt.tickEvent("hid.flash.done");
 | 
					                        pxt.tickEvent("hid.flash.done");
 | 
				
			||||||
                        return wrap.cortexM.reset(false)
 | 
					                        return wrap.cortexM.reset(false)
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
 | 
					                    .then(() => {
 | 
				
			||||||
 | 
					                        wrap.flashing = false;
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .catch(e => {
 | 
					            .catch(e => {
 | 
				
			||||||
                // TODO: (microbit master)
 | 
					                // TODO: (microbit master)
 | 
				
			||||||
@@ -543,7 +599,7 @@ namespace pxt.editor {
 | 
				
			|||||||
        pxt.debug('loading microbit target extensions...')
 | 
					        pxt.debug('loading microbit target extensions...')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!Math.imul)
 | 
					        if (!Math.imul)
 | 
				
			||||||
            Math.imul = function(a, b) {
 | 
					            Math.imul = function (a, b) {
 | 
				
			||||||
                const ah = (a >>> 16) & 0xffff;
 | 
					                const ah = (a >>> 16) & 0xffff;
 | 
				
			||||||
                const al = a & 0xffff;
 | 
					                const al = a & 0xffff;
 | 
				
			||||||
                const bh = (b >>> 16) & 0xffff;
 | 
					                const bh = (b >>> 16) & 0xffff;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								external/dapjs.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								external/dapjs.js
									
									
									
									
										vendored
									
									
								
							@@ -2397,7 +2397,7 @@ var CMSISDAP = (function () {
 | 
				
			|||||||
                            case 6 /* DAP_TRANSFER_BLOCK */:
 | 
					                            case 6 /* DAP_TRANSFER_BLOCK */:
 | 
				
			||||||
                                break;
 | 
					                                break;
 | 
				
			||||||
                            default:
 | 
					                            default:
 | 
				
			||||||
                                if (buf[1] !== 0) {
 | 
					                                if (op < 0x80 && buf[1] !== 0) {
 | 
				
			||||||
                                    throw new Error("Bad status for " + op + " -> " + buf[1]);
 | 
					                                    throw new Error("Bad status for " + op + " -> " + buf[1]);
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user