ISP example program.
Dependencies: SLCD mbed USBLocalFileSystem
FRDM-KL46Z | LPC810 | |
---|---|---|
UART RXD | PTE23 | p2(P0_4) |
UART TXD | PTE22 | p8(P0_0) |
nRESET | D6 | p1(P0_5) |
nISP | D8 | p5(P0_1) |
GND | GND | p7 |
3.3V | P3V3 | p6 |
Copy binary image to the disk called LPC81ISP.
Push sw1 or sw3, start write to LPC810 flash.
Diff: src/BaseLpcIsp.cpp
- Revision:
- 0:ad2b1fc04955
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/BaseLpcIsp.cpp Sat Feb 15 10:15:42 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; +}