ISP example program.

Dependencies:   SLCD mbed USBLocalFileSystem

/media/uploads/va009039/lpc81isp-360x240.jpg

FRDM-KL46ZLPC810
UART RXDPTE23p2(P0_4)
UART TXDPTE22p8(P0_0)
nRESETD6p1(P0_5)
nISPD8p5(P0_1)
GNDGNDp7
3.3VP3V3p6

Copy binary image to the disk called LPC81ISP.
Push sw1 or sw3, start write to LPC810 flash.

Revision:
2:eafc1c6787c7
Parent:
0:ad2b1fc04955
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseLpcIsp.cpp	Sun May 04 00:36:04 2014 +0000
@@ -0,0 +1,258 @@
+#include "BaseLpcIsp.h"
+#include <algorithm>
+
+#if (DEBUG2 > 3)
+#define ISP_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
+#else
+#define ISP_DBG(...) while(0);
+#endif
+
+#define ISP_ERR() isp_error(__LINE__)
+
+#define RAM 0x10000300
+#define ROM_SIZE 0x10000
+
+void BaseLpcIsp::Reset(bool isp)
+{
+    _nisp = isp ? 0 : 1;
+    _nreset = 0;
+    wait_ms(50);
+    _nreset = 1;
+    wait_ms(100);
+}
+
+bool BaseLpcIsp::Sync()
+{
+    putc('?');
+    if (waitln("Synchronized")) { // Synchronized
+        sendln("Synchronized");
+        if (waitln("OK")) {
+            sendln("14748");
+            if (waitln("OK")) {
+                if (_cmd("A 0")) { // echo off
+                    return true;
+                }
+            }
+        }
+    }
+    ISP_ERR();
+    return false;
+}
+
+bool BaseLpcIsp::_cmd(const char* format, ...)
+{
+    char buf[128];
+    va_list args;
+    va_start(args, format);
+    vsprintf(buf, format, args);
+    va_end(args);
+    sendln(buf);
+
+    if (waitln("0")) { // CMD_SUCCESS ?
+        return true;
+    }
+    ISP_ERR();
+    return false;
+}
+
+void BaseLpcIsp::sendln(const char* s)
+{
+    infoLED(LED_TX, tx_sw++ & 1);
+    ISP_DBG("send:[%s]", s);
+    puts(s);
+    puts(CRLF);
+}
+
+bool BaseLpcIsp::waitln(const char* s)
+{
+    char buf[64];
+    while(recvln(buf, sizeof(buf))) {
+        if (strcmp(buf, s) == 0) {
+            ISP_DBG("recv:[%s]", buf);
+            return true;
+        }
+        ISP_DBG("skip:[%s]", buf);
+    }
+    ISP_ERR();
+    return false;
+}
+
+bool BaseLpcIsp::recvln(mystring& s)
+{
+    Timer t;
+    t.reset();
+    t.start();
+    while(t.read_ms() < 900) {
+        if (readable()) {
+            int c = getc();
+            if (c == LF) {
+                return true;
+            } else if (c >= ' ') {
+                s.append(c);
+            }
+        }
+    }
+    ISP_ERR();
+    return false;
+}
+
+bool BaseLpcIsp::recvln(char* buf, int size)
+{
+    Timer t;
+    t.reset();
+    t.start();
+    int pos = 0;
+    while(t.read_ms() < 900) {
+        if (readable()) {
+            int c = getc();
+            if (c == LF) {
+                buf[pos] = '\0';
+                return true;
+            } else if (c >= ' ') {
+                if (pos < size-1) {
+                    buf[pos++] = c;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool BaseLpcIsp::FlashWrite(const char* filename)
+{
+    infoLED(LED_TX, 0);
+    if (!_cmd("J")) {
+        return false;
+    }
+    char lineBuf[16];
+    if (!recvln(lineBuf, sizeof(lineBuf))) {
+        ISP_ERR();
+        return false;
+    }
+    ISP_DBG("recv:[%s]", lineBuf);
+
+    part_code = strtoul(lineBuf, NULL, 10);
+    if (part_code >= 0x8100 && part_code <= 0x81ff) { // LPC8XX
+        chunk_size = 64;
+        sector_size = 1024;
+        plan_binary = true;
+        infoSLCD("810 ");
+    } else {
+        chunk_size = 256;
+        sector_size = 4096;
+        plan_binary = false;
+        infoSLCD("1114");
+    }
+    
+    if (!_cmd("U 23130")) { // Unlock
+        ISP_ERR();
+        return false;
+    }
+
+    FILE* fp = fopen(filename, "rb");
+    if (fp == NULL) {
+        ISP_ERR();
+        return false;
+    }
+
+    int bin_size = 0;
+    Timer t;
+    t.reset();
+    t.start();
+    uint8_t buf[chunk_size];
+    int sector = 0;
+    bool result = false;
+    for(int addr = 0; addr < ROM_SIZE; addr += sizeof(buf)) {
+        if (feof(fp)) {
+            result = true;
+            break;
+        }
+        fread(buf, sizeof(buf), 1, fp);
+        if (!_patch(addr, buf, sizeof(buf))) {
+            break;
+        }
+        bin_size += sizeof(buf);
+        if (!_write_to_ram(RAM, buf, sizeof(buf))) {
+            break;
+        }
+        if ((addr % sector_size) == 0) {
+            sector = addr / sector_size;
+            if (!_cmd("P %u %u", sector, sector)) {
+                break;
+            }
+            if (!_cmd("E %u %u", sector, sector)) { // Erase
+                break;
+            }
+            if (!_cmd("I %u %u", sector, sector)) { // Blank check
+                break;
+            }
+        }
+        if (!_cmd("P %u %u", sector, sector)) {
+            break;
+        }
+        if (!_cmd("C %u %u %u", addr, RAM, sizeof(buf))) { // copy
+            break;
+        }
+        if (!_cmd("M %u %u %u", addr, RAM, sizeof(buf))) { // compare
+            break;
+        }
+    }
+    fclose(fp);
+    infoLED(LED_TX, 0);
+    if (result) {
+        t.stop();
+        ISP_DBG("bin size: %d bytes, %d ms, %d bytes/sec", 
+            bin_size, t.read_ms(), bin_size*1000/t.read_ms());
+        infoSLCD("OK  ");
+    }   
+    return result;
+}
+
+extern void uuencode(const void* src, int srcsize, char* dst); //utils.cpp
+
+bool BaseLpcIsp::_write_to_ram(int addr, uint8_t* buf, int size)
+{
+    if (!_cmd("W %u %u", addr, size)) {
+        return false;
+    }
+    if (plan_binary) {
+        for(int i = 0; i < size; i++) {
+            _target.putc(buf[i]);
+        }
+        return true;
+    }
+    int sum = 0;
+    int line = 0;
+    for(int n = 0; n < size; n += 45) {
+        char tmp[61+1];
+        int size2 = std::min(45, size - n);
+        uuencode(buf+n, size2, tmp);
+        sendln(tmp);
+        for(int i = 0; i < size2; i++) {
+            sum += buf[n+i];
+        }
+        if (++line >= 20 || (n + size2) >= size) {
+            snprintf(tmp, sizeof(tmp), "%u", sum);
+            sendln(tmp);
+            if (!waitln("OK")) {
+                return false;
+            }
+            line = 0;
+            sum = 0;
+        }
+    }
+    return true;
+}
+
+bool BaseLpcIsp::_patch(int addr, uint8_t* buf, int size)
+{
+    const int crp_start = 0x2fc; // Code Read Protection location
+    if (crp_start >= addr && crp_start < addr+size) {
+        uint32_t pat = *reinterpret_cast<uint32_t*>(crp_start-addr+buf);
+        if (pat != 0xffffffff) { // NO_CRP ?
+            ISP_ERR();
+            return false;
+        }
+    }
+    return true;
+}