Переглянути джерело

WIP - Starts of flashing, mostly lined up minus async bits

craigsdennis 9 роки тому
батько
коміт
a37e2186ab
1 змінених файлів з 91 додано та 2 видалено
  1. 91 2
      back-end/rom_comm.js

+ 91 - 2
back-end/rom_comm.js

@@ -1,8 +1,10 @@
 "use strict";
 
+const fs = require("fs");
 const SerialPort = require("serialport").SerialPort;
 const slip = require("./streams/slip");
 
+
 // ../esptool.py --port /dev/cu.SLAB_USBtoUART --baud 115200 \
 //   write_flash --flash_freq 80m --flash_mode qio --flash_size 32m \
 //   0x0000 "boot_v1.4(b1).bin" 0x1000 espruino_esp8266_user1.bin \
@@ -35,6 +37,9 @@ const SYNC_FRAME = new Buffer([0x07, 0x07, 0x12, 0x20,
                         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
                         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55]);
 
+const FLASH_BLOCK_SIZE = 0x400;
+const SUCCESS = [0x01, 0x01];
+
 var debug = function() {};
 
 function delay(time) {
@@ -214,6 +219,91 @@ class RomComm {
         return header;
     }
 
+    determineNumBlocks(blockSize, length) {
+        return Math.round((length + blockSize - 1) / blockSize);
+    }
+
+    prepareFlashAddress(address, size) {
+        let numBlocks = this.determineNumBlocks(FLASH_BLOCK_SIZE, size);
+        let sectorsPerBlock = 16;
+        let sectorSize = 4096;
+        let numSectors = (size + sectorSize -1) / sectorSize;
+        let startSector = address / sectorSize;
+        // Leave some room for header space
+        let headSectors = sectorsPerBlock - (startSector % sectorsPerBlock);
+        if (numSectors < headSectors) {
+            headSectors = numSectors;
+        }
+        let eraseSize = (numSectors - headSectors) * sectorSize;
+        // TODO:csd - Research this...
+        /* SPIEraseArea function in the esp8266 ROM has a bug which causes extra area to be erased.
+            If the address range to be erased crosses the block boundary,
+            then extra head_sector_count sectors are erased.
+            If the address range doesn't cross the block boundary,
+            then extra total_sector_count sectors are erased.
+        */
+        if (numSectors < (2 * headSectors)) {
+            eraseSize = (numSectors + 1) / (2 * sectorSize);
+        }
+        var buffer = new ArrayBuffer(16);
+        var dv = new DataView(buffer);
+        dv.setUint32(0, eraseSize, true);
+        dv.setUint32(4, numBlocks, true);
+        dv.setUint32(8, FLASH_BLOCK_SIZE, true);
+        dv.setUint32(12, address, true);
+        return this.sendCommand(commands.FLASH_DOWNLOAD_BEGIN, new Buffer(buffer))
+            .then((result) => {
+                if (result.slice(0, 1) == SUCCESS) {
+                    return true;
+                } else {
+                    throw Error("Received unknown response: " + result);
+                }
+            });
+    }
+
+    flashAddressFromFile(address, fileName) {
+        return new Promise((resolve, reject) => {
+            fs.readFile(fileName, (err, data) => {
+               if (err) {
+                   reject(err);
+               }
+               return this.flashAddress(address, data)
+                    .then((result) => resolve(result));
+            });
+        });
+    }
+
+    flashAddress(address, data) {
+        return new Promise((resolve, reject) => {
+            this.prepareFlashAddress(address, data.length)
+                .then(() => {
+                    let numBlocks = this.determineNumBlocks(FLASH_BLOCK_SIZE, data.length);
+                    for (let seq = 0; seq < numBlocks; seq++) {
+                        let startIndex = seq * FLASH_BLOCK_SIZE;
+                        let endIndex = Math.min((seq + 1) * FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE);
+                        let block = data.slice(startIndex, endIndex);
+                        let padAmount = FLASH_BLOCK_SIZE - data.length;
+                        // Pad the remaining bits, should only happen on the last block
+                        if (padAmount > 0) {
+                            let padding = new Buffer(padAmount);
+                            padding.fill(0xFF);
+                            block = Buffer.concat(block, padding);
+                        }
+
+                        // TODO:csd - How are we going to flash in a tight loop like this asynchronously?
+                        var buffer = new ArrayBuffer(16);
+                        var dv = new DataView(buffer);
+                        dv.setUint32(0, block.length, true);
+                        dv.setUint32(4, seq, true);
+                        dv.setUint32(8, 0, true);  // Uhhh
+                        dv.setUint32(12, 0, true);  // Uhhh
+                        this.sendCommand(commands.FLASH_DOWNLOAD_DATA, Buffer.concat([buffer, block]));
+                    }
+                }).then((result) => resolve(result));
+        });
+    }
+
+
     // https://github.com/themadinventor/esptool/blob/master/esptool.py#L108
     // https://github.com/igrr/esptool-ck/blob/master/espcomm/espcomm.c#L103
     sendCommand(command, data, ignoreResponse) {
@@ -249,5 +339,4 @@ class RomComm {
 
 
 
-module.exports = RomComm;
-
+module.exports = RomComm;