/* * This file is part of Espruino, a JavaScript interpreter for Microcontrollers * * Copyright (C) 2013 Gordon Williams * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * ---------------------------------------------------------------------------- * Bootloader entry point * ---------------------------------------------------------------------------- */ #include "platform_config.h" #include "utils.h" #define BOOTLOADER_MAJOR_VERSION 3 // needed for Ext Erase in stm32loader.py #define BOOTLOADER_MINOR_VERSION 0 #define CMD_GET (0x00) #define CMD_GET_ID (0x02) #define CMD_READ (0x11) #define CMD_WRITE (0x31) #define CMD_EXTERASE (0x44) #define FLASH_START 0x08000000 #define BOOTLOADER_SIZE (10*1024) #define ACK (0x79) #define NACK (0x1F) typedef enum { BLS_UNDEFINED, BLS_INITED, // Has got 0x7F byte... BLS_COMMAND_FIRST_BYTE, // Got first byte of command - waiting for inverted byte BLS_EXPECT_DATA, } BootloaderState; void setLEDs(int l) { jshPinOutput(LED1_PININDEX, l&1); jshPinOutput(LED2_PININDEX, (l>>1)&1); jshPinOutput(LED3_PININDEX, (l>>2)&1); } int main(void) { initHardware(); int flashy = 0; BootloaderState state = BLS_UNDEFINED; char currentCommand = 0; while (1) { if (!jshIsUSBSERIALConnected()) { jshPinOutput(LED2_PININDEX, 0); // reset, led off } else { int f = (flashy>>9) & 0x7F; if (f&0x40) f=128-f; jshPinOutput(LED3_PININDEX, ((flashy++)&0xFF)=0) { // if we have data if (state==BLS_EXPECT_DATA) { } else if (state==BLS_INITED) { currentCommand = d; state = BLS_COMMAND_FIRST_BYTE; } else if (state==BLS_COMMAND_FIRST_BYTE) { if (currentCommand == d^0xFF) { unsigned int addr,i; char chksum, buffer[256]; unsigned int nBytesMinusOne, nPages; // confirmed switch (currentCommand) { case CMD_GET: // get bootloader info putc(ACK); putc(5); // 6 bytes // now report what we support putc(BOOTLOADER_MAJOR_VERSION<<4 | BOOTLOADER_MINOR_VERSION); // Bootloader version // list supported commands putc(CMD_GET); putc(CMD_GET_ID); putc(CMD_READ); putc(CMD_WRITE); putc(CMD_EXTERASE); // erase putc(ACK); // last byte break; case CMD_GET_ID: // get chip ID putc(ACK); putc(1); // 2 bytes // now report what we support putc(0x04); // 0x30 F1 XL density // 0x14 F1 high density putc(0x30); // TODO: really? putc(ACK); // last byte break; case CMD_READ: // read memory putc(ACK); addr = getc_blocking() << 24; addr |= getc_blocking() << 16; addr |= getc_blocking() << 8; addr |= getc_blocking(); chksum = getc_blocking(); // TODO: check checksum putc(ACK); nBytesMinusOne = getc_blocking(); chksum = getc_blocking(); // TODO: check checksum putc(ACK); for (i=0;i<=nBytesMinusOne;i++) putc(((unsigned char*)addr)[i]); break; case CMD_WRITE: // write memory putc(ACK); addr = getc_blocking() << 24; addr |= getc_blocking() << 16; addr |= getc_blocking() << 8; addr |= getc_blocking(); chksum = getc_blocking(); // TODO: check checksum and address&3==0 putc(ACK); setLEDs(2); // green = wait for data nBytesMinusOne = getc_blocking(); for (i=0;i<=nBytesMinusOne;i++) buffer[i] = getc_blocking(); chksum = getc_blocking(); setLEDs(1); // red = write // TODO: check checksum and (nBytesMinusOne+1)&3==0 FLASH_UnlockBank1(); for (i=0;i<=nBytesMinusOne;i+=4) { unsigned int realaddr = addr+i; if (realaddr >= (FLASH_START+BOOTLOADER_SIZE)) // protect bootloader FLASH_ProgramWord(realaddr, *(unsigned int*)&buffer[i]); } FLASH_LockBank1(); setLEDs(0); // off putc(ACK); break; case CMD_EXTERASE: // erase memory putc(ACK); nPages = getc_blocking() << 8; nPages |= getc_blocking(); chksum = getc_blocking(); // TODO: check checksum if (nPages == 0xFFFF) { // all pages (except us!) setLEDs(1); // red = write FLASH_UnlockBank1(); for (i=BOOTLOADER_SIZE;i