Christopher Haster / Mbed 2 deprecated ESPQuickFlash

Dependencies:   BufferedSerial mbed

Revision:
0:d84cdaf22096
diff -r 000000000000 -r d84cdaf22096 esp_command.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/esp_command.h	Mon Apr 18 20:36:49 2016 +0000
@@ -0,0 +1,198 @@
+#ifndef ESP_COMMAND_H
+#define ESP_COMMAND_H
+
+#include "slip.h"
+
+
+#define FLASH_BLOCK_SIZE 0x400
+#define RESET_WAIT_MS 250
+
+enum esp_commands {
+    ESP_FLASH_START     = 0x02,
+    ESP_FLASH_DATA      = 0x03,
+    ESP_FLASH_FINISH    = 0x04,
+    ESP_RAM_START       = 0x05,
+    ESP_RAM_DATA        = 0x07,
+    ESP_RAM_FINISH      = 0x06,
+    ESP_SYNC_FRAME      = 0x08,
+    ESP_WRITE_REG       = 0x09,
+    ESP_READ_REG        = 0x0a,
+    ESP_SPI_CONFIG      = 0x0b,
+};
+
+
+
+
+// Commands follow the following format
+// request:
+// [- 0x00 -|- command -|- size -|- value -|-- body --]
+//     1          1         2         4        size
+//
+// response:
+// [- 0x01 -|- command -|- size -|- value -|-- body --|- status -|- error -]
+//     1          1         2         4     size-error     1          1
+//
+template <typename SERIAL>
+class ESPCommand {
+private:
+    SLIPPacket<SERIAL> _slip;
+    DigitalOut _reset;
+    DigitalOut _prog;
+    
+public:
+    ESPCommand(PinName tx, PinName rx, PinName reset, PinName prog) : 
+            _slip(tx, rx), _reset(reset, 1), _prog(prog, 1) {}
+    
+private:
+    bool command_start(char cmd, uint16_t len) {
+        len -= 4; // First word not included in length
+        
+        return _slip.req_start() &&
+               _slip.putc(0x00) &&
+               _slip.putc(cmd) &&
+               _slip.send(&len, 2);
+    }
+    
+    bool command_flush() {
+        uint16_t len;
+
+        return _slip.resp_start() &&
+               _slip.getc() == 0x01 &&
+               _slip.getc() >= 0 &&
+               _slip.recv(&len, 2) &&
+               _slip.recv(0, 4+len-2) &&
+               _slip.getc() == 0x00 &&
+               _slip.getc() >= 0 &&
+               _slip.resp_finish();
+    }
+    
+    bool command_finish() {
+        return _slip.req_finish() && 
+               command_flush();
+    }
+    
+public:
+    bool sync() {
+#ifdef LED_STATUS
+        led_green = 0; // Show progress
+#endif
+        while (true) {
+            if (sync_frame()) {
+#ifdef LED_STATUS
+                led_green = 1; // Show progress
+#endif
+                return true;
+            }
+        }
+    }
+
+    bool sync_frame() {
+        // Reset board
+        _reset = 0;
+        _prog = 1;
+        wait_ms(250);
+        _reset = 1;
+        wait_ms(250);
+        _reset = 0;
+        _prog = 0;
+        wait_ms(250);
+        _reset = 1;
+        wait_ms(250);
+        
+        // Flush serial line
+        _slip.flush();
+        
+        // Send sync frame
+        uint32_t x = 0;
+        
+        if (!(command_start(ESP_SYNC_FRAME, 2*4 + 32) &&
+              _slip.send(&x, 4) &&
+              _slip.putc(0x07) &&
+              _slip.putc(0x07) &&
+              _slip.putc(0x12) &&
+              _slip.putc(0x20)))
+            return false;
+            
+        for (int i = 0; i < 32; i++) {
+            if (!_slip.putc(0x55))
+                return false;
+        }
+        
+        if (!command_finish())
+            return false;
+        
+        for (int i = 0; i < 7; i++) {
+            if (!command_flush())
+                return false;
+        }
+        
+        return true;
+    }
+ 
+    bool flash_start(uint32_t blocks, uint32_t block_size, uint32_t address) {
+        uint32_t x = 0;
+        uint32_t size = blocks * block_size;
+        
+        return command_start(ESP_FLASH_START, 5*4) &&
+               _slip.send(&x, 4) &&
+               _slip.send(&size, 4) &&
+               _slip.send(&blocks, 4) &&
+               _slip.send(&block_size, 4) &&
+               _slip.send(&address, 4) && 
+               command_finish();
+    }
+    
+    bool flash_data(const char *data, uint32_t len, uint32_t n) {
+        uint32_t zero = 0;
+        
+        uint32_t x = 0xef;
+        for (int i = 0; i < len; i++) {
+            x ^= data[i];
+        }
+        
+        return command_start(ESP_FLASH_DATA, 5*4 + len) &&
+               _slip.send(&x, 4) &&
+               _slip.send(&len, 4) &&
+               _slip.send(&n, 4) &&
+               _slip.send(&zero, 4) &&
+               _slip.send(&zero, 4) &&
+               _slip.send(data, len) &&
+               command_finish();
+    }
+
+    bool flash_finish() {
+        uint32_t x = 0;
+        
+        return command_start(ESP_FLASH_FINISH, 2*4) &&
+               _slip.send(&x, 4) &&
+               _slip.send(&x, 4) &&
+               command_finish();
+    }
+    
+    bool flash_write(uint32_t address, const char *data, uint32_t size) {
+        uint32_t blocks = (size-1)/FLASH_BLOCK_SIZE + 1;
+        
+        printf("Synching...\r\n");
+        if (!sync())
+            error("Sync error!");
+        
+        printf("Starting transfer 0x%05x - 0x%05x\r\n", address, address + blocks*FLASH_BLOCK_SIZE);
+        if (!flash_start(blocks, FLASH_BLOCK_SIZE, address))
+            return false;
+            
+        for (int i = 0; i < blocks; i++) {
+            printf("Flashing address 0x%05x\r\n", address + i*FLASH_BLOCK_SIZE);
+            if (!flash_data(&data[i*FLASH_BLOCK_SIZE], FLASH_BLOCK_SIZE, i))
+                return false;
+        }
+        
+        printf("Finishing transfer\r\n");
+        if (!flash_finish())
+            return false;
+            
+        wait_ms(250);
+        return true;
+    }
+};
+
+#endif
\ No newline at end of file