mirror of
https://github.com/jeelabs/esp-link.git
synced 2026-02-20 02:31:19 +01:00
Bits and pieces for flashing an Arduino Mega. (#290)
This commit is contained in:
committed by
Thorsten von Eicken
parent
c0cd698860
commit
bc87885a5f
1167
esp-link/cgimega.c
Normal file
1167
esp-link/cgimega.c
Normal file
File diff suppressed because it is too large
Load Diff
14
esp-link/cgimega.h
Normal file
14
esp-link/cgimega.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2016-2017 by Danny Backx, see LICENSE.txt in the esp-link repo
|
||||
|
||||
#ifndef CGIMEGA_H
|
||||
#define CGIMEGA_H
|
||||
|
||||
#include <httpd.h>
|
||||
|
||||
int ICACHE_FLASH_ATTR cgiMegaSync(HttpdConnData *connData);
|
||||
int ICACHE_FLASH_ATTR cgiMegaData(HttpdConnData *connData);
|
||||
int ICACHE_FLASH_ATTR cgiMegaRead(HttpdConnData *connData);
|
||||
int ICACHE_FLASH_ATTR cgiMegaFuse(HttpdConnData *connData);
|
||||
int ICACHE_FLASH_ATTR cgiMegaRebootMCU(HttpdConnData *connData);
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,10 @@
|
||||
// Copyright (c) 2015 by Thorsten von Eicken, see LICENSE.txt in the esp-link repo
|
||||
|
||||
// Some code moved to esp-link/pgmshared.c to avoid code duplication.
|
||||
// Those changes are Copyright (c) 2017 by Danny Backx.
|
||||
|
||||
// Protocol used : https://github.com/Optiboot/optiboot/wiki/HowOptibootWorks
|
||||
|
||||
#include <esp8266.h>
|
||||
#include <osapi.h>
|
||||
#include "cgi.h"
|
||||
@@ -11,6 +16,8 @@
|
||||
#include "mqtt_cmd.h"
|
||||
#include "serled.h"
|
||||
|
||||
#include "pgmshared.h"
|
||||
|
||||
#define INIT_DELAY 150 // wait this many millisecs before sending anything
|
||||
#define BAUD_INTERVAL 600 // interval after which we change baud rate
|
||||
#define PGM_TIMEOUT 20000 // timeout after sync is achieved, in milliseconds
|
||||
@@ -43,33 +50,12 @@ static short ackWait; // counter of expected ACKs
|
||||
static uint16_t optibootVers;
|
||||
static uint32_t baudRate; // baud rate at which we're programming
|
||||
|
||||
#define RESP_SZ 64
|
||||
static char responseBuf[RESP_SZ]; // buffer to accumulate responses from optiboot
|
||||
static short responseLen = 0; // amount accumulated so far
|
||||
#define ERR_MAX 128
|
||||
static char errMessage[ERR_MAX]; // error message
|
||||
|
||||
#define MAX_PAGE_SZ 512 // max flash page size supported
|
||||
#define MAX_SAVED 512 // max chars in saved buffer
|
||||
// structure used to remember request details from one callback to the next
|
||||
// allocated dynamically so we don't burn so much static RAM
|
||||
static struct optibootData {
|
||||
char *saved; // buffer for saved incomplete hex records
|
||||
char *pageBuf; // buffer for received data to be sent to AVR
|
||||
uint16_t pageLen; // number of bytes in pageBuf
|
||||
uint16_t pgmSz; // size of flash page to be programmed at a time
|
||||
uint16_t pgmDone; // number of bytes programmed
|
||||
uint32_t address; // address to write next page to
|
||||
uint32_t startTime; // time of program POST request
|
||||
HttpdConnData *conn; // request doing the programming, so we can cancel it
|
||||
bool eof; // got EOF record
|
||||
} *optibootData;
|
||||
|
||||
// forward function references
|
||||
static void optibootTimerCB(void *);
|
||||
static void optibootUartRecv(char *buffer, short length);
|
||||
static bool processRecord(char *buf, short len);
|
||||
static bool programPage(void);
|
||||
static void armTimer(uint32_t ms);
|
||||
static void initBaud(void);
|
||||
|
||||
@@ -176,30 +162,6 @@ int ICACHE_FLASH_ATTR cgiOptibootSync(HttpdConnData *connData) {
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
// verify that N chars are hex characters
|
||||
static bool ICACHE_FLASH_ATTR checkHex(char *buf, short len) {
|
||||
while (len--) {
|
||||
char c = *buf++;
|
||||
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
|
||||
continue;
|
||||
DBG("OB non-hex\n");
|
||||
os_sprintf(errMessage, "Non hex char in POST record: '%c'/0x%02x", c, c);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// get hex value of some hex characters
|
||||
static uint32_t ICACHE_FLASH_ATTR getHexValue(char *buf, short len) {
|
||||
uint32_t v = 0;
|
||||
while (len--) {
|
||||
v = (v<<4) | (uint32_t)(*buf & 0xf);
|
||||
if (*buf > '9') v += 9;
|
||||
buf++;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
//===== Cgi to write firmware to Optiboot, requires prior sync call
|
||||
int ICACHE_FLASH_ATTR cgiOptibootData(HttpdConnData *connData) {
|
||||
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
|
||||
@@ -229,6 +191,7 @@ int ICACHE_FLASH_ATTR cgiOptibootData(HttpdConnData *connData) {
|
||||
errorResponse(connData, 400, "Out of memory");
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
optibootData->mega = false;
|
||||
optibootData->pageBuf = pageBuf;
|
||||
optibootData->saved = saved;
|
||||
optibootData->startTime = system_get_time();
|
||||
@@ -333,80 +296,6 @@ int ICACHE_FLASH_ATTR cgiOptibootData(HttpdConnData *connData) {
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
// verify checksum
|
||||
static bool ICACHE_FLASH_ATTR verifyChecksum(char *buf, short len) {
|
||||
uint8_t sum = 0;
|
||||
while (len >= 2) {
|
||||
sum += (uint8_t)getHexValue(buf, 2);
|
||||
buf += 2;
|
||||
len -= 2;
|
||||
}
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
// Process a hex record -- assumes that the records starts with ':' & hex length
|
||||
static bool ICACHE_FLASH_ATTR processRecord(char *buf, short len) {
|
||||
buf++; len--; // skip leading ':'
|
||||
// check we have all hex chars
|
||||
if (!checkHex(buf, len)) return false;
|
||||
// verify checksum
|
||||
if (!verifyChecksum(buf, len)) {
|
||||
buf[len] = 0;
|
||||
os_sprintf(errMessage, "Invalid checksum for record %s", buf);
|
||||
return false;
|
||||
}
|
||||
// dispatch based on record type
|
||||
uint8_t type = getHexValue(buf+6, 2);
|
||||
switch (type) {
|
||||
case 0x00: { // data
|
||||
//DBG("OB REC data %ld pglen=%d\n", getHexValue(buf, 2), optibootData->pageLen);
|
||||
uint32_t addr = getHexValue(buf+2, 4);
|
||||
// check whether we need to program previous record(s)
|
||||
if (optibootData->pageLen > 0 &&
|
||||
addr != ((optibootData->address+optibootData->pageLen)&0xffff)) {
|
||||
//DBG("OB addr chg\n");
|
||||
if (!programPage()) return false;
|
||||
}
|
||||
// set address, unless we're adding to the end (programPage may have changed pageLen)
|
||||
if (optibootData->pageLen == 0) {
|
||||
optibootData->address = (optibootData->address & 0xffff0000) | addr;
|
||||
//DBG("OB set-addr 0x%lx\n", optibootData->address);
|
||||
}
|
||||
// append record
|
||||
uint16_t recLen = getHexValue(buf, 2);
|
||||
for (uint16_t i=0; i<recLen; i++)
|
||||
optibootData->pageBuf[optibootData->pageLen++] = getHexValue(buf+8+2*i, 2);
|
||||
// program page, if we have a full page
|
||||
if (optibootData->pageLen >= optibootData->pgmSz) {
|
||||
//DBG("OB full\n");
|
||||
if (!programPage()) return false;
|
||||
}
|
||||
break; }
|
||||
case 0x01: // EOF
|
||||
DBG("OB EOF\n");
|
||||
// program any remaining partial page
|
||||
if (optibootData->pageLen > 0)
|
||||
if (!programPage()) return false;
|
||||
optibootData->eof = true;
|
||||
break;
|
||||
case 0x04: // address
|
||||
DBG("OB address 0x%x\n", getHexValue(buf+8, 4) << 16);
|
||||
// program any remaining partial page
|
||||
if (optibootData->pageLen > 0)
|
||||
if (!programPage()) return false;
|
||||
optibootData->address = getHexValue(buf+8, 4) << 16;
|
||||
break;
|
||||
case 0x05: // start address
|
||||
// ignore, there's no way to tell optiboot that...
|
||||
break;
|
||||
default:
|
||||
DBG("OB bad record type\n");
|
||||
os_sprintf(errMessage, "Invalid/unknown record type: 0x%02x", type);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Poll UART for ACKs, max 50ms
|
||||
static bool pollAck() {
|
||||
char recv[16];
|
||||
@@ -427,7 +316,7 @@ static bool pollAck() {
|
||||
}
|
||||
|
||||
// Program a flash page
|
||||
static bool ICACHE_FLASH_ATTR programPage(void) {
|
||||
bool ICACHE_FLASH_ATTR optibootProgramPage(void) {
|
||||
if (optibootData->pageLen == 0) return true;
|
||||
armTimer(PGM_TIMEOUT); // keep the timerCB out of the picture
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "cgimqtt.h"
|
||||
#include "cgiflash.h"
|
||||
#include "cgioptiboot.h"
|
||||
#include "cgimega.h"
|
||||
#include "cgiwebserversetup.h"
|
||||
#include "auth.h"
|
||||
#include "espfs.h"
|
||||
@@ -69,8 +70,16 @@ HttpdBuiltInUrl builtInUrls[] = {
|
||||
{ "/flash/next", cgiGetFirmwareNext, NULL },
|
||||
{ "/flash/upload", cgiUploadFirmware, NULL },
|
||||
{ "/flash/reboot", cgiRebootFirmware, NULL },
|
||||
|
||||
{ "/pgm/sync", cgiOptibootSync, NULL },
|
||||
{ "/pgm/upload", cgiOptibootData, NULL },
|
||||
|
||||
{ "/pgmmega/sync", cgiMegaSync, NULL }, // Start programming mode
|
||||
{ "/pgmmega/upload", cgiMegaData, NULL }, // Upload stuff
|
||||
{ "/pgmmega/read/*", cgiMegaRead, NULL }, // Download stuff (to verify)
|
||||
{ "/pgmmega/fuse/*", cgiMegaFuse, NULL }, // Read or write fuse
|
||||
{ "/pgmmega/rebootmcu", cgiMegaRebootMCU, NULL }, // Get out of programming mode
|
||||
|
||||
{ "/log/text", ajaxLog, NULL },
|
||||
{ "/log/dbg", ajaxLogDbg, NULL },
|
||||
{ "/log/reset", cgiReset, NULL },
|
||||
|
||||
149
esp-link/pgmshared.c
Normal file
149
esp-link/pgmshared.c
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright (c) 2015 by Thorsten von Eicken, see LICENSE.txt in the esp-link repo
|
||||
// Copyright (c) 2016-2017 by Danny Backx
|
||||
|
||||
#include <esp8266.h>
|
||||
#include <osapi.h>
|
||||
#include "cgi.h"
|
||||
#include "config.h"
|
||||
#include "uart.h"
|
||||
#include "stk500v2.h"
|
||||
#include "serbridge.h"
|
||||
#include "serled.h"
|
||||
|
||||
#include "pgmshared.h"
|
||||
|
||||
struct optibootData *optibootData;
|
||||
|
||||
char responseBuf[RESP_SZ]; // buffer to accumulate responses from optiboot
|
||||
short responseLen = 0; // amount accumulated so far
|
||||
char errMessage[ERR_MAX]; // error message
|
||||
|
||||
// verify that N chars are hex characters
|
||||
bool ICACHE_FLASH_ATTR checkHex(char *buf, short len) {
|
||||
while (len--) {
|
||||
char c = *buf++;
|
||||
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
|
||||
continue;
|
||||
DBG("OB non-hex\n");
|
||||
os_sprintf(errMessage, "Non hex char in POST record: '%c'/0x%02x", c, c);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// get hex value of some hex characters
|
||||
uint32_t ICACHE_FLASH_ATTR getHexValue(char *buf, short len) {
|
||||
uint32_t v = 0;
|
||||
while (len--) {
|
||||
v = (v<<4) | (uint32_t)(*buf & 0xf);
|
||||
if (*buf > '9') v += 9;
|
||||
buf++;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// verify checksum
|
||||
static bool ICACHE_FLASH_ATTR verifyChecksum(char *buf, short len) {
|
||||
uint8_t sum = 0;
|
||||
while (len >= 2) {
|
||||
sum += (uint8_t)getHexValue(buf, 2);
|
||||
buf += 2;
|
||||
len -= 2;
|
||||
}
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
// We've not built one function that works on both, but kept the different functions.
|
||||
// This calls one or the other
|
||||
static bool ICACHE_FLASH_ATTR programPage() {
|
||||
if (optibootData->mega)
|
||||
return megaProgramPage();
|
||||
return optibootProgramPage();
|
||||
}
|
||||
|
||||
// Process a hex record -- assumes that the records starts with ':' & hex length
|
||||
bool ICACHE_FLASH_ATTR processRecord(char *buf, short len) {
|
||||
buf++; len--; // skip leading ':'
|
||||
// check we have all hex chars
|
||||
if (!checkHex(buf, len)) return false;
|
||||
// verify checksum
|
||||
if (!verifyChecksum(buf, len)) {
|
||||
buf[len] = 0;
|
||||
os_sprintf(errMessage, "Invalid checksum for record %s", buf);
|
||||
return false;
|
||||
}
|
||||
// dispatch based on record type
|
||||
uint8_t type = getHexValue(buf+6, 2);
|
||||
switch (type) {
|
||||
case 0x00: { // Intel HEX data record
|
||||
//DBG("OB REC data %ld pglen=%d\n", getHexValue(buf, 2), optibootData->pageLen);
|
||||
uint32_t addr = getHexValue(buf+2, 4);
|
||||
// check whether we need to program previous record(s)
|
||||
if (optibootData->pageLen > 0 &&
|
||||
addr != ((optibootData->address+optibootData->pageLen)&0xffff)) {
|
||||
//DBG("OB addr chg\n");
|
||||
//DBG("processRecord addr chg, len %d, addr 0x%04x\n", optibootData->pageLen, addr);
|
||||
if (!programPage()) return false;
|
||||
}
|
||||
// set address, unless we're adding to the end (programPage may have changed pageLen)
|
||||
if (optibootData->pageLen == 0) {
|
||||
optibootData->address = (optibootData->address & 0xffff0000) | addr;
|
||||
//DBG("OB set-addr 0x%lx\n", optibootData->address);
|
||||
}
|
||||
// append record
|
||||
uint16_t recLen = getHexValue(buf, 2);
|
||||
for (uint16_t i=0; i<recLen; i++)
|
||||
optibootData->pageBuf[optibootData->pageLen++] = getHexValue(buf+8+2*i, 2);
|
||||
// program page, if we have a full page
|
||||
if (optibootData->pageLen >= optibootData->pgmSz) {
|
||||
//DBG("OB full\n");
|
||||
DBG("processRecord %d, call programPage() %08x\n", optibootData->pgmSz, optibootData->address + optibootData->segment);
|
||||
if (!programPage()) return false;
|
||||
}
|
||||
break; }
|
||||
case 0x01: // Intel HEX EOF record
|
||||
DBG("OB EOF\n");
|
||||
// program any remaining partial page
|
||||
#if 1
|
||||
if (optibootData->pageLen > 0) {
|
||||
// DBG("processRecord remaining partial page, len %d, addr 0x%04x\n", optibootData->pageLen, optibootData->address + optibootData->segment);
|
||||
if (!programPage()) return false;
|
||||
}
|
||||
optibootData->eof = true;
|
||||
#else
|
||||
if (optibootData->pageLen > 0) {
|
||||
// HACK : fill up with 0xFF
|
||||
while (optibootData->pageLen < 256) {
|
||||
optibootData->pageBuf[optibootData->pageLen++] = 0xFF;
|
||||
}
|
||||
if (!programPage()) return false;
|
||||
}
|
||||
optibootData->eof = true;
|
||||
#endif
|
||||
break;
|
||||
case 0x04: // Intel HEX address record
|
||||
DBG("OB address 0x%x\n", getHexValue(buf+8, 4) << 16);
|
||||
// program any remaining partial page
|
||||
if (optibootData->pageLen > 0) {
|
||||
DBG("processRecord 0x04 remaining partial page, len %d, addr 0x%04x\n",
|
||||
optibootData->pageLen, optibootData->address + optibootData->segment);
|
||||
if (!programPage()) return false;
|
||||
}
|
||||
optibootData->address = getHexValue(buf+8, 4) << 16;
|
||||
break;
|
||||
case 0x05: // Intel HEX start address (MDK-ARM only)
|
||||
// ignore, there's no way to tell optiboot that...
|
||||
break;
|
||||
case 0x02: // Intel HEX extended segment address record
|
||||
// Depending on the case, just ignoring this record could solve the problem
|
||||
// optibootData->segment = getHexValue(buf+8, 4) << 4;
|
||||
DBG("OB segment 0x%08X\n", optibootData->segment);
|
||||
return true;
|
||||
default:
|
||||
// DBG("OB bad record type\n");
|
||||
DBG(errMessage, "Invalid/unknown record type: 0x%02x, packet %s", type, buf);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
54
esp-link/pgmshared.h
Normal file
54
esp-link/pgmshared.h
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2015 by Thorsten von Eicken, see LICENSE.txt in the esp-link repo
|
||||
// Copyright (c) 2017 by Danny Backx
|
||||
|
||||
#ifndef _PGM_SHARED_H_
|
||||
#define _PGM_SHARED_H_
|
||||
|
||||
#include "user_config.h"
|
||||
|
||||
#define RESP_SZ 64
|
||||
#define ERR_MAX 128
|
||||
|
||||
extern char responseBuf[RESP_SZ];
|
||||
extern short responseLen;
|
||||
extern char errMessage[ERR_MAX];
|
||||
|
||||
// structure used to remember request details from one callback to the next
|
||||
// allocated dynamically so we don't burn so much static RAM
|
||||
extern struct optibootData {
|
||||
char *saved; // buffer for saved incomplete hex records
|
||||
char *pageBuf; // buffer for received data to be sent to AVR
|
||||
uint16_t pageLen; // number of bytes in pageBuf
|
||||
uint16_t pgmSz; // size of flash page to be programmed at a time
|
||||
uint32_t pgmDone; // number of bytes programmed
|
||||
uint32_t address; // address to write next page to
|
||||
uint32_t segment; // for extended segment addressing, added to the address field
|
||||
uint32_t startTime; // time of program POST request
|
||||
HttpdConnData *conn; // request doing the programming, so we can cancel it
|
||||
bool eof; // got EOF record
|
||||
|
||||
// Whether to use the Mega (STK500v2) protocol
|
||||
bool mega;
|
||||
|
||||
// STK500v2 variables
|
||||
int hardwareVersion,
|
||||
firmwareVersionMajor,
|
||||
firmwareVersionMinor,
|
||||
vTarget;
|
||||
uint8_t signature[3];
|
||||
uint8_t lfuse, hfuse, efuse;
|
||||
} *optibootData;
|
||||
|
||||
bool ICACHE_FLASH_ATTR checkHex(char *buf, short len);
|
||||
uint32_t ICACHE_FLASH_ATTR getHexValue(char *buf, short len);
|
||||
bool ICACHE_FLASH_ATTR processRecord(char *buf, short len);
|
||||
bool megaProgramPage(void);
|
||||
bool optibootProgramPage(void);
|
||||
|
||||
#ifdef OPTIBOOT_DBG
|
||||
#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define DBG(format, ...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
114
esp-link/stk500v2.h
Normal file
114
esp-link/stk500v2.h
Normal file
@@ -0,0 +1,114 @@
|
||||
//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************
|
||||
//*
|
||||
//* Title: AVR068 - STK500 Communication Protocol
|
||||
//* Filename: command.h
|
||||
//* Version: 1.0
|
||||
//* Last updated: 31.01.2005
|
||||
//*
|
||||
//* Support E-mail: avr@atmel.com
|
||||
//*
|
||||
//**************************************************************************
|
||||
|
||||
// *****************[ STK message constants ]***************************
|
||||
|
||||
#define MESSAGE_START 0x1B //= ESC = 27 decimal
|
||||
#define TOKEN 0x0E
|
||||
|
||||
// *****************[ STK general command constants ]**************************
|
||||
|
||||
#define CMD_SIGN_ON 0x01
|
||||
#define CMD_SET_PARAMETER 0x02
|
||||
#define CMD_GET_PARAMETER 0x03
|
||||
#define CMD_SET_DEVICE_PARAMETERS 0x04
|
||||
#define CMD_OSCCAL 0x05
|
||||
#define CMD_LOAD_ADDRESS 0x06
|
||||
#define CMD_FIRMWARE_UPGRADE 0x07
|
||||
|
||||
|
||||
// *****************[ STK ISP command constants ]******************************
|
||||
|
||||
#define CMD_ENTER_PROGMODE_ISP 0x10
|
||||
#define CMD_LEAVE_PROGMODE_ISP 0x11
|
||||
#define CMD_CHIP_ERASE_ISP 0x12
|
||||
#define CMD_PROGRAM_FLASH_ISP 0x13
|
||||
#define CMD_READ_FLASH_ISP 0x14
|
||||
#define CMD_PROGRAM_EEPROM_ISP 0x15
|
||||
#define CMD_READ_EEPROM_ISP 0x16
|
||||
#define CMD_PROGRAM_FUSE_ISP 0x17
|
||||
#define CMD_READ_FUSE_ISP 0x18
|
||||
#define CMD_PROGRAM_LOCK_ISP 0x19
|
||||
#define CMD_READ_LOCK_ISP 0x1A
|
||||
#define CMD_READ_SIGNATURE_ISP 0x1B
|
||||
#define CMD_READ_OSCCAL_ISP 0x1C
|
||||
#define CMD_SPI_MULTI 0x1D
|
||||
|
||||
// *****************[ STK PP command constants ]*******************************
|
||||
|
||||
#define CMD_ENTER_PROGMODE_PP 0x20
|
||||
#define CMD_LEAVE_PROGMODE_PP 0x21
|
||||
#define CMD_CHIP_ERASE_PP 0x22
|
||||
#define CMD_PROGRAM_FLASH_PP 0x23
|
||||
#define CMD_READ_FLASH_PP 0x24
|
||||
#define CMD_PROGRAM_EEPROM_PP 0x25
|
||||
#define CMD_READ_EEPROM_PP 0x26
|
||||
#define CMD_PROGRAM_FUSE_PP 0x27
|
||||
#define CMD_READ_FUSE_PP 0x28
|
||||
#define CMD_PROGRAM_LOCK_PP 0x29
|
||||
#define CMD_READ_LOCK_PP 0x2A
|
||||
#define CMD_READ_SIGNATURE_PP 0x2B
|
||||
#define CMD_READ_OSCCAL_PP 0x2C
|
||||
|
||||
#define CMD_SET_CONTROL_STACK 0x2D
|
||||
|
||||
// *****************[ STK HVSP command constants ]*****************************
|
||||
|
||||
#define CMD_ENTER_PROGMODE_HVSP 0x30
|
||||
#define CMD_LEAVE_PROGMODE_HVSP 0x31
|
||||
#define CMD_CHIP_ERASE_HVSP 0x32
|
||||
#define CMD_PROGRAM_FLASH_HVSP 0x33
|
||||
#define CMD_READ_FLASH_HVSP 0x34
|
||||
#define CMD_PROGRAM_EEPROM_HVSP 0x35
|
||||
#define CMD_READ_EEPROM_HVSP 0x36
|
||||
#define CMD_PROGRAM_FUSE_HVSP 0x37
|
||||
#define CMD_READ_FUSE_HVSP 0x38
|
||||
#define CMD_PROGRAM_LOCK_HVSP 0x39
|
||||
#define CMD_READ_LOCK_HVSP 0x3A
|
||||
#define CMD_READ_SIGNATURE_HVSP 0x3B
|
||||
#define CMD_READ_OSCCAL_HVSP 0x3C
|
||||
|
||||
// *****************[ STK status constants ]***************************
|
||||
|
||||
// Success
|
||||
#define STATUS_CMD_OK 0x00
|
||||
|
||||
// Warnings
|
||||
#define STATUS_CMD_TOUT 0x80
|
||||
#define STATUS_RDY_BSY_TOUT 0x81
|
||||
#define STATUS_SET_PARAM_MISSING 0x82
|
||||
|
||||
// Errors
|
||||
#define STATUS_CMD_FAILED 0xC0
|
||||
#define STATUS_CKSUM_ERROR 0xC1
|
||||
#define STATUS_CMD_UNKNOWN 0xC9
|
||||
|
||||
// *****************[ STK parameter constants ]***************************
|
||||
#define PARAM_BUILD_NUMBER_LOW 0x80
|
||||
#define PARAM_BUILD_NUMBER_HIGH 0x81
|
||||
#define PARAM_HW_VER 0x90
|
||||
#define PARAM_SW_MAJOR 0x91
|
||||
#define PARAM_SW_MINOR 0x92
|
||||
#define PARAM_VTARGET 0x94
|
||||
#define PARAM_VADJUST 0x95
|
||||
#define PARAM_OSC_PSCALE 0x96
|
||||
#define PARAM_OSC_CMATCH 0x97
|
||||
#define PARAM_SCK_DURATION 0x98
|
||||
#define PARAM_TOPCARD_DETECT 0x9A
|
||||
#define PARAM_STATUS 0x9C
|
||||
#define PARAM_DATA 0x9D
|
||||
#define PARAM_RESET_POLARITY 0x9E
|
||||
#define PARAM_CONTROLLER_INIT 0x9F
|
||||
|
||||
// *****************[ STK answer constants ]***************************
|
||||
|
||||
#define ANSWER_CKSUM_ERROR 0xB0
|
||||
|
||||
114
megaflash
Executable file
114
megaflash
Executable file
@@ -0,0 +1,114 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# Flash an Arduino Mega with STK500v2 using the esp-link built-in programmer
|
||||
# Basically we first reset the AVR and get in sync, and then send the hex file
|
||||
#
|
||||
# ----------------------------------------------------------------------------
|
||||
# "THE BEER-WARE LICENSE" (Revision 42):
|
||||
# Thorsten von Eicken wrote this file. As long as you retain
|
||||
# this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
# and you think this stuff is worth it, you can buy me a beer in return.
|
||||
#
|
||||
# Danny Backx wrote the changes for Arduino Mega.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
show_help() {
|
||||
cat <<EOT
|
||||
Usage: ${0##*/} [-options...] hostname sketch.hex
|
||||
Flash the Mega running optiboot attached to esp-link with the sketch.
|
||||
Note : this is for stk500v2 MCUs, use avrflash for Arduino Uno etc instead.
|
||||
-v Be verbose
|
||||
-h show this help
|
||||
|
||||
Example: ${0##*/} -v esp-link mysketch.hex
|
||||
${0##*/} 192.168.4.1 mysketch.hex
|
||||
EOT
|
||||
}
|
||||
|
||||
if ! which curl >/dev/null; then
|
||||
echo "ERROR: Cannot find curl: it is required for this script." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
start=`date +%s`
|
||||
|
||||
# ===== Parse arguments
|
||||
|
||||
verbose=
|
||||
|
||||
while getopts "hvx:" opt; do
|
||||
case "$opt" in
|
||||
h) show_help; exit 0 ;;
|
||||
v) verbose=1 ;;
|
||||
x) foo="$OPTARG" ;;
|
||||
'?') show_help >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Shift off the options and optional --.
|
||||
shift "$((OPTIND-1))"
|
||||
|
||||
# Get the fixed arguments
|
||||
if [[ $# != 2 ]]; then
|
||||
show_help >&2
|
||||
exit 1
|
||||
fi
|
||||
hostname=$1
|
||||
hex=$2
|
||||
|
||||
re='[-A-Za-z0-9.]+'
|
||||
if [[ ! "$hostname" =~ $re ]]; then
|
||||
echo "ERROR: hostname ${hostname} is not a valid hostname or ip address" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -r "$hex" ]]; then
|
||||
echo "ERROR: cannot read hex file ($hex)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ===== Get AVR in sync
|
||||
|
||||
[[ -n "$verbose" ]] && echo "Resetting AVR with http://$hostname/pgmmega/sync" >&2
|
||||
v=; [[ -n "$verbose" ]] && v=-v
|
||||
sync=`curl -m 10 $v -s -w '%{http_code}' -XPOST "http://$hostname/pgmmega/sync"`
|
||||
if [[ $? != 0 || "$sync" != 204 ]]; then
|
||||
echo "Error resetting AVR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
# sync=`curl -m 10 $v -s "http://$hostname/pgmmega/sync"`
|
||||
sync=`curl $v -s "http://$hostname/pgmmega/sync"`
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Error checking sync" >&2
|
||||
exit 1
|
||||
fi
|
||||
case "$sync" in
|
||||
SYNC*)
|
||||
echo "AVR in $sync" >&2
|
||||
break;;
|
||||
"NOT READY"*)
|
||||
[[ -n "$verbose" ]] && echo " Waiting for sync..." >&2
|
||||
;;
|
||||
*)
|
||||
echo "Error checking sync: $sync" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
# ===== Send HEX file
|
||||
|
||||
[[ -n "$verbose" ]] && echo "Sending HEX file for programming" >&2
|
||||
sync=`curl -m 20 $v -s -g -d "@$hex" "http://$hostname/pgmmega/upload"`
|
||||
echo $sync
|
||||
if [[ $? != 0 || ! "$sync" =~ ^Success ]]; then
|
||||
echo "Error programming AVR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sec=$(( `date +%s` - $start ))
|
||||
echo "Success, took $sec seconds" >&2
|
||||
exit 0
|
||||
Reference in New Issue
Block a user