Author Topic: Accidentally overwritten Bootloader?  (Read 9156 times)

Lami

  • Newbie
  • *
  • Posts: 13
Accidentally overwritten Bootloader?
« on: April 01, 2013, 07:54:20 am »
During my experiments with Digispark I managed to get it into weird condition. Immediatelly after powering up it starts executing program I uploaded on it last time. No 5s waiting for uploader, it just runs. So I am unable to upload anything more, but it seems I did not fry it yet (there was no other HW connected, just playing with DigiUSB). Compiled code was rather big, about 5.5k. Not sure it fits, IDE reports limit of 6k, but I am not sure 2k bootloader is taken in account. All done using DigisparkArduino 1.0.4, did not meddle with it otherwise.

1) Is there any size limit other than the one IDE reports? If so, is it possible to mess up Digispark uploading code over the limit?

2) Is it possible to reflash Digispark using external programmer? Considering disabled RESET pin, there is no other way than use HVSP programmer to reset fuses, then reprogram it using standard ISP, like http://hlt.media.mit.edu/?p=1695 , am I right?

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Accidentally overwritten Bootloader?
« Reply #1 on: April 01, 2013, 11:21:34 am »
Lami -


First - can you share the code that you uploaded when this happened?


1) The size limit 6010 that the IDE reports is the size limit after the bootloader is taken into account - I've uploaded a sketch that was 6009 byte and it has worked, so as far as my testing goes uploading a large sketch would not cause that.


2) Yes you'd need a HVSP (or make your own) and then once reset was enabled you could program with a Digispark running littlewire or with a AVR programmer or Arduino




Lami

  • Newbie
  • *
  • Posts: 13
Re: Accidentally overwritten Bootloader?
« Reply #2 on: April 01, 2013, 12:19:04 pm »
It might not be exactly same code that is uploaded, because I modified it a bit before I found I can't it upload anymore. But it should be basically same, there was more DigiUSB.refresh() and DigiUSB.delay(x) calls (now most are replaced by get_input()). It is part of converting Arduino's serial debugging to Digispark's USB. I stopped messing with USB when Digispark stared acting weird and returned to old LED-flashing debugging (you can see it in the code). It uses slightly modified Mirf nRF24L01 library (attached), but the Digispark I was testing USB communication was never connected to anyting - I was testing just USB without interfacing it to nRF24L01.

All experiments performed on MacBook Pro (15-inch, Mid 2010, still USB 2.0) with USB extension cable. Programming works mostly reliable (about 80% of attempts succeed on first try).

I left Serial code in (#ifdef'd out) so you can see what I am trying to do.

Code: [Select]
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfSoftwareSpiDriver.h>

#define my_MIRF_PIN_SCK 2
#define my_MIRF_PIN_MOSI 5
// 3 and 4 are USB connections
//#define my_MIRF_CE 3
//#define my_MIRF_CSN 4
// NRF24L01 pins are hardwired to HIGH, tell library not to bother with them
#define my_MIRF_CE mirf_PIN_DONT_USE
// XXX same as status LED
#define my_MIRF_CSN 1
#define my_MIRF_PIN_MISO 0
#define my_STATUS_LED 1
//#define my_USE_SERIAL
#define my_USE_DIGIUSB
#define my_USE_LED

#ifdef my_USE_DIGIUSB
#include <DigiUSB.h>
#endif

void ok(boolean no_serial = false) {
#ifdef my_USE_SERIAL
    if(!no_serial)
        Serial.println("OK");
#endif
#ifdef my_USE_DIGIUSB
    DigiUSB.println("OK");
    get_input();
#endif
#ifdef my_USE_LED
    digitalWrite(my_STATUS_LED, HIGH);
    delay(100);
    digitalWrite(my_STATUS_LED, LOW);
    delay(50);
    digitalWrite(my_STATUS_LED, HIGH);
    delay(100);
    digitalWrite(my_STATUS_LED, LOW);
#if my_STATUS_LED == my_MIRF_CSN
    delay(500);
    // switch CSN back to high (needed for SPI to work)
    digitalWrite(my_MIRF_CSN, HIGH);
#endif
#endif
}

void error() {
#ifdef my_USE_SERIAL
    Serial.println("ERROR");
#endif
#ifdef my_USE_DIGIUSB
    DigiUSB.println("ERR");
    get_input();
#endif
#ifdef my_USE_LED
    while(1) {
        digitalWrite(my_STATUS_LED, HIGH);
        delay(500);
        digitalWrite(my_STATUS_LED, LOW);
        delay(100);
    }
#endif
}

void number(int num) {
#ifdef my_USE_SERIAL
    Serial.println("STEP");
    Serial.println(num);
#endif
#ifdef my_USE_DIGIUSB
    //DigiUSB.print("S ");
    DigiUSB.println(num);
    get_input();
#endif
#ifdef my_USE_LED
    digitalWrite(my_STATUS_LED, HIGH);
    delay(500);
    digitalWrite(my_STATUS_LED, LOW);
    delay(100);
    for (int i = 0; i < num; i++) {
        digitalWrite(my_STATUS_LED, HIGH);
        delay(100);
        digitalWrite(my_STATUS_LED, LOW);
        delay(50);
    }
#if my_STATUS_LED == my_MIRF_CSN
    // switch CSN back to high (needed for SPI to work)
    digitalWrite(my_MIRF_CSN, HIGH);
#endif
    delay(1000);
#endif
}


void get_input() {
#ifdef my_USE_DIGIUSB
  // when there are no characters to read
  while (1) {
    if(DigiUSB.available()){
      //something to read
      DigiUSB.read();
      break;
    }
    // refresh the usb port
    //DigiUSB.refresh();
    DigiUSB.delay(10);
  }
#endif
}

// the setup routine runs once when you press reset:
void setup() {               

#ifdef my_USE_LED
    pinMode(my_STATUS_LED, OUTPUT);
    digitalWrite(my_STATUS_LED, HIGH);
    ok();
#endif

#ifdef my_USE_DIGIUSB
    DigiUSB.begin();
    get_input();
    ok();
#endif

#ifdef my_USE_SERIAL
    Serial.begin(9600);
    Serial.println("Starting wireless...");
#endif

    Mirf.spi = &MirfSoftwareSpiDriver(my_MIRF_PIN_SCK, my_MIRF_PIN_MOSI, my_MIRF_PIN_MISO);
   
    Mirf.init(my_MIRF_CE, my_MIRF_CSN);
    Mirf.setRADDR((byte *)"clie1");
    Mirf.payload = sizeof(unsigned long);
    Mirf.config();
   
    number(1);
   
    // Read and print RF_SETUP
    byte rf_setup = 0;
    Mirf.readRegister( RF_SETUP, &rf_setup, sizeof(rf_setup) );
#ifdef my_USE_SERIAL
    Serial.print( "rf_setup = " );
    Serial.println( rf_setup, BIN );
#endif
#ifdef my_USE_DIGIUSB
    DigiUSB.println( "rf_setup=" );
    DigiUSB.println(rf_setup);
    DigiUSB.delay(100);
#endif
   
    if (rf_setup != 15)
        error();
    else
        ok();
   
}

// the loop routine runs over and over again forever:
void loop() {
}

By the way, is there any documentation for Digispark libraries? Not everything is easy to guess from source code, and USB is rather tricky.

microtherion

  • Newbie
  • *
  • Posts: 15
Re: Accidentally overwritten Bootloader?
« Reply #3 on: April 01, 2013, 12:42:54 pm »

2) Yes you'd need a HVSP (or make your own) and then once reset was enabled you could program with a Digispark running littlewire or with a AVR programmer or Arduino


As it happens, I built a HVSP shield for the digispark this weekend, so I can recommend this as a recreational exercise:

http://www.flickr.com/photos/70181241@N00/8604945254/in/photostream/

The whole thing consists of a Maxim MAX662ACPA+ charge pump, 3 capacitors, and some wires and headers (A really simple circuit, but getting it to fit on a Digispark protoshield was a bit finicky). I wrote some software (which is a few weeks away from release, needing a bit more documentation and testing) for Arduinos that implements the full HVSP, so you can not just change fuses, but also directly reprogram flash and eeprom (the whole thing looks like stk500hvsp to avrdude):

https://github.com/microtherion/ScratchMonkey