---------------------------------------------------------------------- Patch name: patch.add-start-cmd-Z Author: Bryce Denney Date: Wed Jun 12 20:54:32 EDT 2002 Detailed description: This patch adds a "--start" command to UISP, which is very very useful when working with an ATmega with self programming. When you use appnote AVR109 code for self-programming, the transition between programming the application and actually starting the application is very clumsy. When the boot loader starts, it tests pin PD4 to decide whether to continue in the boot loader or jump to the application code. Once you have entered the boot loader, there is no way (that I have found) to ask it to jump to the application code. As AVR109 is currently written you must power down, adjust a jumper on PD4, then power up again to run the application. So I edited the AVR109 code and made a way to start the application. I just added a command 'Z' which sends a "success" code back to the programmer and then jumps to the application code at address 0. Very simple. This is the new code in main.c from avr109: else if (val=='Z') // Start application { sendchar('\r'); funcptr(); // Jump to Reset vector 0x0000 in Application Section } Now in order to actually send the start application code 'Z', the programmer software must know about it too. This patch adds the --start command to uisp which makes it send the magic 'Z' code. Now I use uisp as follows: uisp -dprog=avr910 .... --erase --upload --verify --start if=FILENAME Programmers that don't support the 'Z' command will just return a '?'. The transition from application back to the boot loader is a little more complicated, so I'll try to deal with it in a separate patch. I want the application to be able to use the serial port as well, and it should jump to the boot loader when a certain command arrives. Hack solution: if the application only supports uisp, we know that uisp will send a 'V' first. If the application sees 'V', it can respond with the version number '2' and '3' and then jump to the boot loader. The next command will be handled by the boot loader. :) I'd like to do better than that... Maybe there's some way to jump into the boot loader in a way that allows the boot loader to interpret the first character? Patch was created with: cvs diff -u Apply patch to what version: cvs checked out on DATE, release version VER Instructions: To patch, go to main uisp directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- Index: src/AvrAtmel.C =================================================================== RCS file: /usr/src/CVSROOT/uisp/src/AvrAtmel.C,v retrieving revision 1.7 diff -u -r1.7 AvrAtmel.C --- src/AvrAtmel.C 2002/06/12 20:03:30 1.7 +++ src/AvrAtmel.C 2002/06/13 01:00:19 @@ -404,6 +404,22 @@ EnableAvr(); } +bool TAvrAtmel::StartApplication(){ + TByte startApp [1] = { 'Z' }; + Send (startApp, 1); + // Very few programmers will ever support this command, so don't panic if it + // returns '?' instead of '\r'. The StartApplication command tells the boot + // loader to jump to the top of the application code. + try { + CheckResponse(startApp [0]); + silent_destructor = true; + return true; + } catch (Error_Device ed) { + // don't complain + return false; + } +} + void TAvrAtmel::WriteLockBits(TByte bits){ TByte lockTarget [2] = { 'l', 0xF9 | ((bits << 1) & 0x06) }; Send (lockTarget, 2, 1); @@ -508,6 +524,7 @@ desired_avrcode=0xff; const char* desired_partname = GetCmdParam("-dpart"); bool got_device=false; + silent_destructor = false; if (desired_partname!=NULL) { if (desired_partname[0] >= '0' && desired_partname[0] <= '9'){ @@ -592,5 +609,6 @@ /* leave programming mode! Due to this procedure, enableAvr had to be taken out of TAtmelAvr::TAtmelAvr func. */ - LeaveProgrammingMode(); + if (!silent_destructor) + LeaveProgrammingMode(); } Index: src/AvrAtmel.h =================================================================== RCS file: /usr/src/CVSROOT/uisp/src/AvrAtmel.h,v retrieving revision 1.7 diff -u -r1.7 AvrAtmel.h --- src/AvrAtmel.h 2002/06/12 20:03:30 1.7 +++ src/AvrAtmel.h 2002/06/13 01:00:19 @@ -81,6 +81,8 @@ /* Chip Erase */ void ChipErase(); + bool StartApplication(); + bool silent_destructor; /* Write lock bits */ void WriteLockBits(TByte bits); Index: src/AvrDummy.C =================================================================== RCS file: /usr/src/CVSROOT/uisp/src/AvrDummy.C,v retrieving revision 1.6 diff -u -r1.6 AvrDummy.C --- src/AvrDummy.C 2002/06/12 20:03:30 1.6 +++ src/AvrDummy.C 2002/06/13 01:00:19 @@ -485,6 +485,11 @@ EnableAvr(); } +bool TAvrDummy::StartApplication(){ + throw Error_Device ("TAvrDummy::StartApplication not implemented"); +} + + /* 0 = program (clear bit), 1 = leave unchanged bit 0 = LB1 Index: src/AvrDummy.h =================================================================== RCS file: /usr/src/CVSROOT/uisp/src/AvrDummy.h,v retrieving revision 1.5 diff -u -r1.5 AvrDummy.h --- src/AvrDummy.h 2002/06/12 20:03:30 1.5 +++ src/AvrDummy.h 2002/06/13 01:00:19 @@ -66,6 +66,8 @@ /* Chip Erase */ void ChipErase(); + bool StartApplication(); + /* Transfer Statistics */ unsigned int GetPollCount(); float GetMinPollTime(); Index: src/Global.h =================================================================== RCS file: /usr/src/CVSROOT/uisp/src/Global.h,v retrieving revision 1.8 diff -u -r1.8 Global.h --- src/Global.h 2002/06/12 20:03:30 1.8 +++ src/Global.h 2002/06/13 01:00:19 @@ -98,6 +98,10 @@ /* Chip Erase */ virtual void ChipErase()=0; + + /* for AVR109 self programming devices, add command that runs the + application code */ + virtual bool StartApplication()=0; /* lock bits */ virtual void WriteLockBits(TByte bits)=0; Index: src/Main.C =================================================================== RCS file: /usr/src/CVSROOT/uisp/src/Main.C,v retrieving revision 1.8 diff -u -r1.8 Main.C --- src/Main.C 2002/06/12 20:03:30 1.8 +++ src/Main.C 2002/06/13 01:11:53 @@ -75,7 +75,7 @@ "\n" " [--upload] [--verify] [--erase] [--lock] [if=input_file]\n" " [--download] [of=output_file]\n" -" [--segment=flash|eeprom|fuse] [--terminal]\n\n" +" [--segment=flash|eeprom|fuse] [--terminal] [--start]\n\n" "Programming Methods:\n" " -dprog=avr910 Standard Atmel Serial Programmer/Atmel Low Cost Programmer\n" " pavr http://avr.jpk.co.nz/pavr/pavr.html\n" @@ -125,6 +125,8 @@ " --erase Erase device.\n" " --lock Write lock bits.\n" " --segment Set active segment (auto-select for AVA Motorola output)\n" +" --start Leave boot loader and enter application code (supported\n" +" for AVR109 with StartApplication patch)\n" "\n" "Files:\n" " if Input file for the --upload and --verify functions in\n" @@ -275,6 +277,23 @@ if (GetCmdParam("--terminal", false)){terminal.Run();} + /* start application command */ + if (GetCmdParam("--start", false)){ + /* The StartApplication command only makes sense for a boot loader. + * It tells the boot loader to jump to the application code segment + * at address zero. The only boot loader that supports the command + * is the AVR109 code with a patch by Bryce Denney at + * http://tlw.com/bryce/robot/avr/patch.avr109-start-cmd-Z + */ + if (device->StartApplication()) { + Info (1, "Running application code at 0x0000\n"); + Info (1, "Device left the bootloader, so uisp will exit.\n"); + exit (1); + } else { + Info (1, "WARNING: This device does not support the --start command.\n"); + } + } + /* Check bad command line parameters */ for (int i=1; i