diff options
| author | Tim <cpldcpu@gmail.com> | 2015-06-06 22:40:52 +0200 | 
|---|---|---|
| committer | Tim <cpldcpu@gmail.com> | 2015-06-06 22:40:52 +0200 | 
| commit | 1548e70077127c079a801c396e2d790763b23e08 (patch) | |
| tree | 233cd87a07fd1fdbb91d710e9870dd9a28111d2b /commandline | |
| parent | 21d57991d6b321e1cc3690df9addb3b26e4145aa (diff) | |
| parent | f0bb13678d45c2c87fb3439aef50e92de1f0e52b (diff) | |
| download | micronucleus-1548e70077127c079a801c396e2d790763b23e08.tar.gz micronucleus-1548e70077127c079a801c396e2d790763b23e08.tar.bz2 micronucleus-1548e70077127c079a801c396e2d790763b23e08.zip  | |
Merge pull request #43 from micronucleus/testing-V2-New
First release of V2.0 to master.
Diffstat (limited to 'commandline')
| -rw-r--r-- | commandline/Makefile | 5 | ||||
| -rwxr-xr-x | commandline/builds/OSX/micronucleus | bin | 124292 -> 0 bytes | |||
| -rw-r--r--[-rwxr-xr-x] | commandline/builds/Windows/micronucleus.exe | bin | 26126 -> 27662 bytes | |||
| -rw-r--r-- | commandline/library/micronucleus_lib.c | 173 | ||||
| -rw-r--r-- | commandline/library/micronucleus_lib.h | 16 | ||||
| -rw-r--r-- | commandline/micronucleus.c | 66 | ||||
| -rw-r--r-- | commandline/micronucleus.exe | bin | 0 -> 27662 bytes | 
7 files changed, 208 insertions, 52 deletions
diff --git a/commandline/Makefile b/commandline/Makefile index 3c52cb4..e8aadfd 100644 --- a/commandline/Makefile +++ b/commandline/Makefile @@ -20,6 +20,11 @@ else ifeq ($(shell uname), Darwin)  	# USBLIBS += -framework IOKit  	# Uncomment these to create a dual architecture binary:  	# OSFLAG += -arch x86_64 -arch i386 +else ifeq ($(shell uname), OpenBSD) +	USBFLAGS=$(shell libusb-config --cflags || libusb-legacy-config --cflags) +	USBLIBS=$(shell libusb-config --libs || libusb-legacy-config --libs) +	EXE_SUFFIX = +	OSFLAG = -D OPENBSD  else  	USBFLAGS = -I C:\MinGW\include  	USBLIBS = -L C:\MinGW\lib -lusb diff --git a/commandline/builds/OSX/micronucleus b/commandline/builds/OSX/micronucleus Binary files differdeleted file mode 100755 index 3ae62c4..0000000 --- a/commandline/builds/OSX/micronucleus +++ /dev/null diff --git a/commandline/builds/Windows/micronucleus.exe b/commandline/builds/Windows/micronucleus.exe Binary files differindex bfdb56b..aa4752f 100755..100644 --- a/commandline/builds/Windows/micronucleus.exe +++ b/commandline/builds/Windows/micronucleus.exe diff --git a/commandline/library/micronucleus_lib.c b/commandline/library/micronucleus_lib.c index 6e574f5..0569dbe 100644 --- a/commandline/library/micronucleus_lib.c +++ b/commandline/library/micronucleus_lib.c @@ -1,8 +1,10 @@  /*    Created: September 2012 -  by ihsan Kehribar <ihsan@kehribar.me> - +  (c) 2012 by ihsan Kehribar <ihsan@kehribar.me> +  Changes for Micronucleus protocol version V2.x +  (c) 2014 T. Bo"scke +      Permission is hereby granted, free of charge, to any person obtaining a copy of    this software and associated documentation files (the "Software"), to deal in    the Software without restriction, including without limitation the rights to @@ -28,7 +30,7 @@  #include "micronucleus_lib.h"  #include "littleWire_util.h" -micronucleus* micronucleus_connect() { +micronucleus* micronucleus_connect(int fast_mode) {    micronucleus *nucleus = NULL;    struct usb_bus *busses; @@ -60,17 +62,64 @@ micronucleus* micronucleus_connect() {          nucleus->device = usb_open(dev); -        // get nucleus info -        unsigned char buffer[4]; -        int res = usb_control_msg(nucleus->device, 0xC0, 0, 0, 0, (char *)buffer, 4, MICRONUCLEUS_USB_TIMEOUT); -        assert(res >= 4); - -        nucleus->flash_size = (buffer[0]<<8) + buffer[1]; -        nucleus->page_size = buffer[2]; -        nucleus->pages = (nucleus->flash_size / nucleus->page_size); -        if (nucleus->pages * nucleus->page_size < nucleus->flash_size) nucleus->pages += 1; -        nucleus->write_sleep = buffer[3]; -        nucleus->erase_sleep = nucleus->write_sleep * nucleus->pages; +        if (nucleus->version.major>=2) {  // Version 2.x +          // get nucleus info +          unsigned char buffer[6]; +          int res = usb_control_msg(nucleus->device, USB_ENDPOINT_IN| USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, 0, (char *)buffer, 6, MICRONUCLEUS_USB_TIMEOUT); + +          // Device descriptor was found, but talking to it was not succesful. This can happen when the device is being reset. +          if (res<0) return NULL;   +           +          assert(res >= 6); + +          nucleus->flash_size = (buffer[0]<<8) + buffer[1]; +          nucleus->page_size = buffer[2]; +          nucleus->pages = (nucleus->flash_size / nucleus->page_size); +          if (nucleus->pages * nucleus->page_size < nucleus->flash_size) nucleus->pages += 1; +           +          nucleus->bootloader_start = nucleus->pages*nucleus->page_size; +           +          if ((nucleus->version.major>=2)&&(!fast_mode)) { +            // firmware v2 reports more aggressive write times. Add 2ms if fast mode is not used. +            nucleus->write_sleep = (buffer[3] & 127) + 2;          +          } else {   +            nucleus->write_sleep = (buffer[3] & 127); +          }       +           +          // if bit 7 of write sleep time is set, divide the erase time by four to  +          // accomodate to the 4*page erase of the ATtiny841/441 +          if (buffer[3]&128) { +               nucleus->erase_sleep = nucleus->write_sleep * nucleus->pages / 4;         +          } else { +               nucleus->erase_sleep = nucleus->write_sleep * nucleus->pages;         +          }                   +           +          nucleus->signature1 = buffer[4]; +          nucleus->signature2 = buffer[5];            +           +        } else {  // Version 1.x         +          // get nucleus info +          unsigned char buffer[4]; +          int res = usb_control_msg(nucleus->device, USB_ENDPOINT_IN| USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, 0, (char *)buffer, 4, MICRONUCLEUS_USB_TIMEOUT); +           +          // Device descriptor was found, but talking to it was not succesful. This can happen when the device is being reset. +          if (res<0) return NULL;   +             +          assert(res >= 4); + +          nucleus->flash_size = (buffer[0]<<8) + buffer[1]; +          nucleus->page_size = buffer[2]; +          nucleus->pages = (nucleus->flash_size / nucleus->page_size); +          if (nucleus->pages * nucleus->page_size < nucleus->flash_size) nucleus->pages += 1; +           +          nucleus->bootloader_start = nucleus->pages*nucleus->page_size; +           +          nucleus->write_sleep = (buffer[3] & 127); +          nucleus->erase_sleep = nucleus->write_sleep * nucleus->pages;        +           +          nucleus->signature1 = 0; +          nucleus->signature2 = 0;            +        }        }      }    } @@ -80,7 +129,7 @@ micronucleus* micronucleus_connect() {  int micronucleus_eraseFlash(micronucleus* deviceHandle, micronucleus_callback progress) {    int res; -  res = usb_control_msg(deviceHandle->device, 0xC0, 2, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT); +  res = usb_control_msg(deviceHandle->device, USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE, 2, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT);    // give microcontroller enough time to erase all writable pages and come back online    float i = 0; @@ -122,6 +171,7 @@ int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_siz    unsigned int  page_address; // address within this page when copying buffer    unsigned int  res;    unsigned int  pagecontainsdata; +  unsigned int  userReset;    for (address = 0; address < deviceHandle->flash_size; address += deviceHandle->page_size) {      // work around a bug in older bootloader versions @@ -142,12 +192,99 @@ int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_siz        }      } +    // Reset vector patching is done in the host tool in micronucleus >=2     +    if (deviceHandle->version.major >=2) +    { +      if ( address == 0 ) { +        // save user reset vector (bootloader will patch with its vector) +        unsigned int word0,word1; +        word0 = page_buffer [1] * 0x100 + page_buffer [0]; +        word1 = page_buffer [3] * 0x100 + page_buffer [2]; +         +        if (word0==0x940c) {  // long jump +          userReset = word1;           +        } else if ((word0&0xf000)==0xc000) {  // rjmp +          userReset = (word0 & 0x0fff) - 0 + 1;     +        } else { +          fprintf(stderr, +                  "The reset vector of the user program does not contain a branch instruction,\n" +                  "therefore the bootloader can not be inserted. Please rearrage your code.\n" +                  ); +          return -1;          +        }  +         +        // Patch in jmp to bootloader.  +        if (deviceHandle->bootloader_start > 0x2000) { +          //  jmp +          unsigned data = 0x940c; +          page_buffer [ 0 ] = data >> 0 & 0xff; +          page_buffer [ 1 ] = data >> 8 & 0xff; +          page_buffer [ 2 ] = deviceHandle->bootloader_start >> 0 & 0xff; +          page_buffer [ 3 ] = deviceHandle->bootloader_start >> 8 & 0xff;         +        } else { +          // rjmp +          unsigned data =  0xc000 | ((deviceHandle->bootloader_start/2 - 1) & 0x0fff);         +          page_buffer [ 0 ] = data >> 0 & 0xff; +          page_buffer [ 1 ] = data >> 8 & 0xff; +        } +         +      } +       +      if ( address >= deviceHandle->bootloader_start - deviceHandle->page_size ) { +        // move user reset vector to end of last page +        // The reset vector is always the last vector in the tinyvectortable +        unsigned int user_reset_addr = (deviceHandle->pages*deviceHandle->page_size) - 4; +         +        if (user_reset_addr > 0x2000) { +          //  jmp +          unsigned data = 0x940c; +          page_buffer [user_reset_addr - address + 0] = data >> 0 & 0xff; +          page_buffer [user_reset_addr - address + 1] = data >> 8 & 0xff; +          page_buffer [user_reset_addr - address + 2] = userReset >> 0 & 0xff; +          page_buffer [user_reset_addr - address + 3] = userReset >> 8 & 0xff;         +        } else { +          // rjmp +          unsigned data =  0xc000 | ((userReset - user_reset_addr/2 - 1) & 0x0fff);         +          page_buffer [user_reset_addr - address + 0] = data >> 0 & 0xff; +          page_buffer [user_reset_addr - address + 1] = data >> 8 & 0xff; +        } +      } +    }    +     +             // always write last page so bootloader can insert the tiny vector table -    if ( address >= deviceHandle->flash_size - deviceHandle->page_size ) +    if ( address >= deviceHandle->bootloader_start - deviceHandle->page_size )        pagecontainsdata = 1;      // ask microcontroller to write this page's data      if (pagecontainsdata) { + +      if (deviceHandle->version.major == 1) { +        // Firmware rev.1 transfers a page as a single block +        // ask microcontroller to write this page's data +        res = usb_control_msg(deviceHandle->device, +               USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE, +               1, +               page_length, address, +               page_buffer, page_length, +               MICRONUCLEUS_USB_TIMEOUT); +      } else if (deviceHandle->version.major >= 2) { +        // Firmware rev.2 uses individual set up packets to transfer data +        res = usb_control_msg(deviceHandle->device, USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, page_length, address, NULL, 0, MICRONUCLEUS_USB_TIMEOUT); +        if (res) return -1; +        int i; +         +        for (i=0; i< page_length; i+=4) +        { +          int w1,w2; +          w1=(page_buffer[i+1]<<8)+(page_buffer[i+0]<<0); +          w2=(page_buffer[i+3]<<8)+(page_buffer[i+2]<<0); +           +          res = usb_control_msg(deviceHandle->device, USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE, 3, w1, w2, NULL, 0, MICRONUCLEUS_USB_TIMEOUT); +          if (res) return -1; +        }      +      }   +    /*        res = usb_control_msg(deviceHandle->device,               USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE,               1, @@ -156,7 +293,7 @@ int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_siz               MICRONUCLEUS_USB_TIMEOUT);        if (res != page_length) return -1; - +    */        // give microcontroller enough time to write this page and come back online        delay(deviceHandle->write_sleep);      } @@ -174,7 +311,7 @@ int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_siz  int micronucleus_startApp(micronucleus* deviceHandle) {    int res; -  res = usb_control_msg(deviceHandle->device, 0xC0, 4, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT); +  res = usb_control_msg(deviceHandle->device, USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE, 4, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT);    if(res!=0)      return -1; diff --git a/commandline/library/micronucleus_lib.h b/commandline/library/micronucleus_lib.h index 9118ace..b691fa4 100644 --- a/commandline/library/micronucleus_lib.h +++ b/commandline/library/micronucleus_lib.h @@ -3,7 +3,9 @@  /*    Created: September 2012 -  by ihsan Kehribar <ihsan@kehribar.me> +  (c) 2012 by ihsan Kehribar <ihsan@kehribar.me> +  Changes for Micronucleus protocol version V2.x +  (c) 2014 T. Bo"scke    Permission is hereby granted, free of charge, to any person obtaining a copy of    this software and associated documentation files (the "Software"), to deal in @@ -44,11 +46,12 @@  #define MICRONUCLEUS_VENDOR_ID   0x16D0  #define MICRONUCLEUS_PRODUCT_ID  0x0753  #define MICRONUCLEUS_USB_TIMEOUT 0xFFFF -#define MICRONUCLEUS_MAX_MAJOR_VERSION 1 +#define MICRONUCLEUS_MAX_MAJOR_VERSION 2 +  /*******************************************************************************/  /******************************************************************************** -* Declearations +* Declarations  ********************************************************************************/  //typedef usb_dev_handle micronucleus;  // representing version number of micronucleus device @@ -57,6 +60,8 @@ typedef struct _micronucleus_version {    unsigned char minor;  } micronucleus_version; +#define MICRONUCLEUS_COMMANDLINE_VERSION "Commandline tool version: 2.0a5" +  // handle representing one micronucleus device  typedef struct _micronucleus {    usb_dev_handle *device; @@ -64,9 +69,12 @@ typedef struct _micronucleus {    micronucleus_version version;    unsigned int flash_size;  // programmable size (in bytes) of progmem    unsigned int page_size;   // size (in bytes) of page +  unsigned int bootloader_start; // Start of the bootloader    unsigned int pages;       // total number of pages to program    unsigned int write_sleep; // milliseconds    unsigned int erase_sleep; // milliseconds +  unsigned char signature1; // only used in protocol v2 +  unsigned char signature2; // only used in protocol v2  } micronucleus;  typedef void (*micronucleus_callback)(float progress); @@ -77,7 +85,7 @@ typedef void (*micronucleus_callback)(float progress);  * Try to connect to the device  *     Returns: device handle for success, NULL for fail  ********************************************************************************/ -micronucleus* micronucleus_connect(); +micronucleus* micronucleus_connect(int fast_mode);  /*******************************************************************************/  /******************************************************************************** diff --git a/commandline/micronucleus.c b/commandline/micronucleus.c index b7d49ab..14c1761 100644 --- a/commandline/micronucleus.c +++ b/commandline/micronucleus.c @@ -1,7 +1,9 @@  /* -  Created: September 2012 -  by ihsan Kehribar <ihsan@kehribar.me> - +Created: September 2012 +  (c) 2012 by ihsan Kehribar <ihsan@kehribar.me> +  Changes for Micronucleus protocol version V2.x +  (c) 2014 T. Bo"scke +      Permission is hereby granted, free of charge, to any person obtaining a copy of    this software and associated documentation files (the "Software"), to deal in    the Software without restriction, including without limitation the rights to @@ -54,6 +56,7 @@ static char* progress_friendly_name; // name of progress section  static int dump_progress = 0; // output computer friendly progress info  static int use_ansi = 0; // output ansi control character stuff  static int erase_only = 0; // only erase, dont't write file +static int fast_mode = 0; // normal mode adds 2ms to page writing times and waits longer for connect.  static int timeout = 0;  /*****************************************************************************/ @@ -69,17 +72,22 @@ int main(int argc, char **argv) {    int run = 0;    int file_type = FILE_TYPE_INTEL_HEX;    int arg_pointer = 1; -  char* usage = "usage: micronucleus [--run] [--dump-progress] [--type intel-hex|raw] [--no-ansi] [--timeout integer] [--erase-only] filename"; +  #if defined(WIN) +  char* usage = "usage: micronucleus [--help] [--run] [--dump-progress] [--fast-mode] [--type intel-hex|raw] [--timeout integer] [--erase-only] filename"; +  #else +  char* usage = "usage: micronucleus [--help] [--run] [--dump-progress] [--fast-mode] [--type intel-hex|raw] [--timeout integer] [--erase-only] filename [--no-ansi]"; +  #endif     progress_step = 0;    progress_total_steps = 5; // steps: waiting, connecting, parsing, erasing, writing, (running)?    dump_progress = 0;    erase_only = 0; +  fast_mode=0;    timeout = 0; // no timeout by default -  //#if defined(WIN) -  //  use_ansi = 0; -  //#else +  #if defined(WIN) +    use_ansi = 0; +  #else      use_ansi = 1; -  //#endif +  #endif    while (arg_pointer < argc) {      if (strcmp(argv[arg_pointer], "--run") == 0) { @@ -104,19 +112,25 @@ int main(int argc, char **argv) {        puts("                           for driving GUIs");        puts("             --erase-only: Erase the device without programming. Fills the");        puts("                           program memory with 0xFFFF. Any files are ignored."); +      puts("              --fast-mode: Speed up the timing of micronucleus. Do not use if"); +      puts("                           you encounter USB errors. ");        puts("                    --run: Ask bootloader to run the program when finished");        puts("                           uploading provided program"); -      //#ifndef WIN +      #ifndef WIN        puts("                --no-ansi: Don't use ANSI in terminal output"); -      //#endif +      #endif        puts("      --timeout [integer]: Timeout after waiting specified number of seconds");        puts("                 filename: Path to intel hex or raw data file to upload,");        puts("                           or \"-\" to read from stdin"); +      puts(""); +      puts(MICRONUCLEUS_COMMANDLINE_VERSION);        return EXIT_SUCCESS;      } else if (strcmp(argv[arg_pointer], "--dump-progress") == 0) {        dump_progress = 1;      } else if (strcmp(argv[arg_pointer], "--no-ansi") == 0) {        use_ansi = 0; +    } else if (strcmp(argv[arg_pointer], "--fast-mode") == 0) { +      fast_mode = 1;      } else if (strcmp(argv[arg_pointer], "--erase-only") == 0) {        erase_only = 1;        progress_total_steps -= 1; @@ -149,7 +163,7 @@ int main(int argc, char **argv) {    while (my_device == NULL) {      delay(100); -    my_device = micronucleus_connect(); +    my_device = micronucleus_connect(fast_mode);      time(¤t_time);      if (timeout && start_time + timeout < current_time) { @@ -164,28 +178,20 @@ int main(int argc, char **argv) {    printf("> Device is found!\n"); -  // wait for CONNECT_WAIT milliseconds with progress output -  float wait = 0.0f; -  setProgressData("connecting", 2); -  while (wait < CONNECT_WAIT) { -    printProgress((wait / ((float) CONNECT_WAIT)) * 0.9f); -    wait += 50.0f; -    delay(50); +  if (!fast_mode) { +    // wait for CONNECT_WAIT milliseconds with progress output +    float wait = 0.0f; +    setProgressData("connecting", 2); +    while (wait < CONNECT_WAIT) { +      printProgress((wait / ((float) CONNECT_WAIT)) * 0.9f); +      wait += 50.0f; +      delay(50); +    }    } - -  //my_device = micronucleus_connect();    printProgress(1.0); -  // if (my_device->page_size == 64) { -  //   printf("> Device looks like ATtiny85!\n"); -  // } else if (my_device->page_size == 32)  { -  //   printf("> Device looks like ATtiny45!\n"); -  // } else { -  //   printf("> Unsupported device!\n"); -  //   return EXIT_FAILURE; -  // } -    printf("> Device has firmware version %d.%d\n",my_device->version.major,my_device->version.minor); +  if (my_device->signature1) printf("> Device signature: 0x1e%02x%02x \n",(int)my_device->signature1,(int)my_device->signature2);    printf("> Available space for user applications: %d bytes\n", my_device->flash_size);    printf("> Suggested sleep time between sending pages: %ums\n", my_device->write_sleep);    printf("> Whole page count: %d  page size: %d\n", my_device->pages,my_device->page_size); @@ -239,7 +245,7 @@ int main(int argc, char **argv) {      int deciseconds_till_reconnect_notice = 50; // notice after 5 seconds      while (my_device == NULL) {        delay(100); -      my_device = micronucleus_connect(); +      my_device = micronucleus_connect(fast_mode);        deciseconds_till_reconnect_notice -= 1;        if (deciseconds_till_reconnect_notice == 0) { diff --git a/commandline/micronucleus.exe b/commandline/micronucleus.exe Binary files differnew file mode 100644 index 0000000..c5aeedc --- /dev/null +++ b/commandline/micronucleus.exe  | 
