Example of STK500 UART programmer code

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey all,

 

I have an ATmega328PB that is running a (modified) version of Optiboot that come packaged with the MiniCore project for the Arduino IDE.

 

I have a second MCU (a STM32) that is conencted to my ATmega's UART lines.  There is a peripheral subcircuit that resets the ATmega using its reset pin  if the UART_RX line of the ATmega gets pulled low for more than 1 second.

 

I would like to use the STM32 to program my ATmega via the Optiboot bootloader using only these RX and TX lines.

 

I have the following code running on the STM32, however it doesn't seem to work.  I think the STK500 protocol wants me to send a CRC byte after the STK_READ_SIGN command byte... or something....

 


/**
 *
 *

This file contains an application that runs on the Electron which attempts to reset an ATmega328PB
with an optiboot bootloader pre-loaded onto it, and then immediately query the ATmega328PB
for its signature bytes to confirm that the bootloader is functioning correctly.

 *
 */


#include "Particle.h"




/*=============================================>>>>>
= Optiboot-implemented STK-500 command codes =
===============================================>>>>>*/
#define STK_READ_SIGN 0x75


/*= End of Optiboot-implemented STK-500 command codes =*/
/*=============================================<<<<<*/


#define OPTIBOOT_BAUD_RATE 115200




enum serial_test_cmd_codes_t{
   CMD_READ_SIGNATURE_BYTES = 1,
   CMD_RESET_TARGET_MCU = 2
};




//Configure how the app runs within the Particle ecosystem
SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

//Configure Particle system (runs this code before any Particle init code runs):
STARTUP(
   //Configure other Particle runtime parameters
   System.enableFeature(FEATURE_RETAINED_MEMORY);
   //Enable system reset information
   System.enableFeature(FEATURE_RESET_INFO);
   //Make sure that cloud DFU updates are enabled
   System.enableUpdates();
);


//Define log handler using serial monitor (dumps logs to serial monitor)
SerialLogHandler logHandler(
   LOG_LEVEL_ALL, //Particle OS debug level
   {
      {"app"                  , LOG_LEVEL_ALL   }, //All log names with "app" prefix
   }
);
const char* logName = "app.main";
static Logger myLog(logName);  //Logger object used in this "main.cpp" file



void setup(){

   //Start UART peripheral communicating with attached PC via Electron USB port
   Serial.begin(57600);
   //Start UART peripheral communicating with attached ATmega
   Serial1.begin(115200);
}



void loop(){

   if(Serial.available()){
      byte cmd_byte = (byte)(Serial.read());
      //Convert ascii byte into number
      cmd_byte -= 48;

      myLog.info("Received cmd_byte = %u", cmd_byte);

      switch(cmd_byte){

         case CMD_READ_SIGNATURE_BYTES:
         {
            myLog.info("Resetting ATmega");
            //Need to first reset target MCU using UART TX line by holding
            //it low for at least 0.8 seconds
            Serial1.end();
            pinMode(TX, OUTPUT);
            digitalWrite(TX, LOW);
            delay(1500);
            //Debug
            myLog.info("Done - allowing ATmega to reset itself");
            myLog.info("About to boot up ATmega and send STK_READ_SIGN (0x%0X)", STK_READ_SIGN);
            Serial.flush();
            //Start the UART peripheral connected to the ATmega (this should)
            //in turn release the ATmega's reset pin
            Serial1.begin(OPTIBOOT_BAUD_RATE);
            //Wait a few moments for target MCU optiboot to spool up
            delay(1);
            //Request our signature bytes from the target MCU
            Serial1.write(STK_READ_SIGN);
            Serial1.flush();

            //Now wait up to a second for ATmega optiboot to report signature bytes back
            unsigned int timerStart = millis();
            // byte sig_bytes[3] = {0};
            // byte bytesRead = 0;
            bool receivedResponse = false;
            while((millis() - timerStart) < 1000){
               if(Serial1.available()){
                  myLog.info("Received byte: 0X%0X", Serial1.read());
                  timerStart = millis();
                  receivedResponse = true;
               }
               else if (!receivedResponse){
                  Serial1.write(STK_READ_SIGN);
                  delay(10);
               }
            };

            if((millis() - timerStart) > 1000){
               myLog.error("Didn't received signature bytes from ATmega");
            }

         }
         break;

         default:
         {
            myLog.error("Invalid PC command.... going into DFU mode...");
            Serial.flush();
            System.dfu();
         }
      }
   }

}

 

 

 

Can anyone point me to an example of a program that implements the STK500 protocol on a microcontroller in order to flash a secondary microcontroller?

I love the smell of burning silicon in the morning

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can anyone point me to an example of a program that implements the STK500 protocol on a microcontroller

The "ArduinoISP" sketch that comes with the Arduino IDE.

https://github.com/arduino/Arduino/blob/master/build/shared/examples/11.ArduinoISP/ArduinoISP/ArduinoISP.ino

 

(note that this implements "STK500v1", which is pretty much CRC and error-checking free.   There is also STK500v2, which wraps an error-corrected packet protocol around similar (the same?) commands.)

 

Last Edited: Wed. Sep 19, 2018 - 08:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll add these, they use STK500v2.

(these programs have several files, so I link to the one handling the STK500v2 commands as starting point):

https://github.com/microtherion/...

https://github.com/ElTangas/STK2... (yeah, this one is mine)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I took a peek at the ArduinoISP sketch, however I don't think it is what I'm looking for.  That sketch appears to be for acting as a relay for a PC transmitting a hex file to a target MCU using STK500 protocol.

 

In other words, the ArduinoISP sketch knows how to interpret STK500 commands, not how to generate them.

 

Here is an illustration to help clarify what I mean:

 

 

So, I guess I'm asking for an example of an arduino acting as a stand-alone programmer where it itself is generating the STK500 messages/data transfers.  

 

I love the smell of burning silicon in the morning

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, ok, these programs are just bridges between avrdude and the target. So you want to talk to the optiboot bootloader.

I could link you to the avrdude source code: http://svn.savannah.gnu.org/view...

 

But this is a complex program, it will not be easy to find the pieces of code you need in there (but they are there). If it were me, I'd rather write my ".hex" decoder -> STK500 from scratch.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm, this is starting to sound like its above my pay grade...

 

".hex decoder"  eh?  I don't even know what that means.  It sounds like I either need:

 

1) a program that is pretty much ready to go that I can modify slightly that "decodes" the .hex file and sends it to my ATmega via STK500.  --> to this end, how much do you think it would cost to get an AVR guy to write such a program (how long would it take)

 

2) an in-depth understanding of all the facets of the avr build process, including how hex files are encoded, how to decode them, how to compile custom versions of Optiboot, and how to use the STK500 protocol to flash a target MCU.   Once I understand this stuff, I then write my own app.

 

 

I tried to take a look at some of the source files you linked to at svn.savannah.org but I couldn't figure out how to download any of them (it seems like the link you sent is a GUI to a SVN repository history, with no download options).

 

 

I love the smell of burning silicon in the morning

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Welp, I think I'm officially in over my head.  I can't even get a simple test program to work to verify that Optiboot is actually running on my ATmega328PB:

 

Here are the steps I am following:

 

  1. Connect USBTiny ISP to my PC and to my ATmega328PB board via ISP header
  2. Select "burn bootloader" command from within Arduino IDE: Tools-> Burn Bootloader
  3. Verify bootloader was successfully flashed to ATmega328PB using the status window in Arduino IDE
  4. Disconnect ISP header from my ATmega328PB board
  5. Connect my Particle Electron to the ATmega328PB board (only signals are UART_TX, UART_RX... and common ground)
  6. Run app on Particle Electron that resets the ATmega328PB using an external watchdog-based reset circuit connected to UART_TX signal (hold UART_TX low for >0.8seconds will pull ATmega328PB reset line LOW), and then immediately attempts to read the signature bytes from the ATmega328PB using the STK500 READ_SIGN command (sends 0x75, 0x20 bytes --> STK_READ_SIGN, CRC_EOP)

 

Nothing happens (I get no response from the ATmega328PB).

 

Here is a logic analyzer connected to UART signals as well as the reset signal of the ATmega328PB.

 

Am I doing something wrong?

 

 

image
image

 

 

Here is the same process I just described, except instead of sending STK500_READ_SIGN and CRC_EOP immediately, there is a 200 ms delay inserted to allow the ATmega some breathing room after reset:

 

 

image
image

 

As you can see, there is no difference --> the ATmega328PB never responds to the 0x75 0x20 commands... which makes me think that Optiboot is not actually running on the ATmega328PB when these commands are sent to it...

 

 

One strange thing that I note however is that the TX line of the ATmega (i.e. HOST_RX signal in logic analyzer screenshots) gets pulled low for about 2.5µs before the ATmega RST line gets released. This phenomenon is present no matter how long I hold the ATmega reset line LOW... it always appears about 10-15 µs before the reset line gets released.... like it knows that its about to be released or something...

I love the smell of burning silicon in the morning

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wrong baud rate perhaps? 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaza_tom wrote:
".hex decoder" eh? I don't even know what that means. It sounds like I either need:

...

3) 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What happens if you forget all this weird 3rd party stuff and simply try to download a compiled sketch from the Arduino IDE (which will be using avrdude in the background for the comms)?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
What happens if you forget all this weird 3rd party stuff and simply try to download a compiled sketch from the Arduino IDE (which will be using avrdude in the background for the comms)?

 

In order to do that, I will need a USB to Serial adapter with integrated Arduino-style DTR to RST signal conversion (I believe this is how Arduino IDE/avrdude resets an arduino when flashing via USB cable right?)

 

I've ordered one, and will post back here next week when it arrives and I can hook up my logic analyzer to it.

 

In the meantime, I have hooked up my logic analyzer to the UART lines of an Arduino Mega 2560, and taken a peek at what happens when the arduino IDE is used to upload a sketch to it.  Based on my findings, it appears that the bootloader/avrdude config for the Arduino Megaa 2560 uses some form of bootloader running on STK500 V2 protocol:

 

Here is what I get:

 

 

 

 

which appears to be totally reasonable:

 

 

 

Notice that the "message body" is the STK500 SIGN_ON command (0x01)

 

I will note that it has been extremely frustrating to try and use the STK500 Protocol Microchip datasheet because they don't specify what the command codes are... they simply say:

 

The definition of all commands, responses, parameters and other defined values
can be found in the file “command.h”. This file can be downloaded from the Atmel
web site.

 

which is basically the same as saying "type command.h into Google and see if the link that pops up helps you figure out what the hell anything in this document actually means".

 

I eventually did end up finding a "command.h" file in a random github repo that seems to contain the STK500 V2 protocol command codes... so I'm using that to decipher 

 

ARGHGHGHGHG!angry

 

 

Anyways, I modified my Particle Electron code to reset the Arduino Mega 2560 and write those same bytes to it, and lo an behold I get the same response back from its' bootloader.  laugh

 

I tried to then do the same thing with the Optiboot bootloader that is (maybe?) running on my ATmega328PB but did not get anything back (no surprise there... Optiboot should be using STK500 V1 (not V2) ).  But it was worth a shot right?

 

 

I love the smell of burning silicon in the morning

Last Edited: Fri. Sep 21, 2018 - 06:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:
Wrong baud rate perhaps? 

 

I have tried 115200 and 57600.  Same results

I love the smell of burning silicon in the morning

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaza_tom wrote:
I eventually did end up finding a "command.h" file in a random github repo that seems to contain the STK500 V2 protocol command codes... so I'm using that to decipher

 

I already gave you the link for avrdude source in #5. The file you needed is stk500v2_private.h link:http://svn.savannah.gnu.org/view...

 

In the avrdude source there are also headers for other protocols, like plain STK500, you have to look for them, they won't just fall of a tree on your lap...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

jaza_tom wrote:

I eventually did end up finding a "command.h" file in a random github repo that seems to contain the STK500 V2 protocol command codes... so I'm using that to decipher

 

 

I already gave you the link for avrdude source in #5. The file you needed is stk500v2_private.h link:http://svn.savannah.gnu.org/view...

 

In the avrdude source there are also headers for other protocols, like plain STK500, you have to look for them, they won't just fall of a tree on your lap...

 

Thanks for helping me find that.  Still not sure how to download all the files in that repo so that I can do global symbol searches on the files in that repo using a text editor like Atom.

 

 

 

A few things:

 

1) That site has a HORRIBLE interface.  It requires me to know exactly what file I want to look at, and then select a version of that file to view.  Maybe it looks different (i.e. is usable) on your screen?  Here is what it looks like on my screen

 

2) There is no file called "command.h" in that SVN repo

 

3) My point about how horrible the STK500 datasheet is still stands... there is no way to locate a command.h file on the "Atmel site"  (aka Mircochip homepage).

 

4) Without the ability to download all the files in the avrdude repo, the repo is basically useless.

 

 

I don't expect things to magically fall in my lap, I recognize that some digging is required.  However, IMHO finding the correct STK500 V2 command codes from the http://svn.savannah.gnu.org/view... URL is tantamount to trying to find the 453rd word that ends with a letter "d" by reading a dictionary from front to back:  it is an insane endeavor.

 

 

 

 

I love the smell of burning silicon in the morning

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, you're right, the interface sucks. But, avrdude is hosted there and it probably contains the most complete information on AVR programming protocols, so, unfortunately, we have to live with that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Based on my findings, it appears that the bootloader/avrdude config for the Arduino Megaa 2560 uses some form of bootloader running on STK500 V2 protocol

You needed a logic analyzer to figure that out?  When it's widely published, often discussed, and open source!?

 

In fact:

stk500v2 command.h:  https://github.com/arduino/Ardui...

stk500v1 commands: https://github.com/arduino/Ardui...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I got it to work as expected now.

 

The major stumbling blocks for me was:

 

- Using Arduino IDE to burn Optiboot that comes packaged with MiniCore project, and then using the IDE to "upload using external programmer" a Blinky application actually erases the bootloader!  --> Appears that there is no way within Arduino IDE to upload an application using an external programmer while still retaining any pre-existing bootloader angry ... instead the IDE simply deletes the previously existing bootloader silently.

 

- Trying to compile Optiboot from the command line took a few days of mucking around before I could get it to work.  I had to use WinAVR (from 2010), the latest Microchip Toolchain (for latest version of gcc compiler), alter my system PATH variable a bunch of times etc etc.   even after doing all this, Optiboot still won't compile for the ATmega328PB (started a thread on this here)  so I built Optiboot for ATmega328 using following build options:   

 

make atmega328 AVR_FREQ=8000000L BAUD_RATE=38400L LED=D2 LED_START_FLASHES=10

 

 and uploaded it via avrdude using following command:

avrdude -v -p m328p -c usbtiny -F -U flash:w:optiboot_atmega328.hex:i

 

( I needed to use the -F avrdude option in order to force the upload since the signature bytes are different for atmega328 than for atmega328pb)

 

--> Note that uploading opitboot in this fashion took over 2 minutes (why is this?) !!!

 

PS C:\PARTICLE_LOCAL\optiboot\optiboot\bootloaders\optiboot> avrdude -v -p m328p -c usbtiny -U flash:w:optiboot_atmega328.hex:i - F

avrdude.exe: Version 5.10, compiled on Jan 19 2010 at 10:45:23
             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
             Copyright (c) 2007-2009 Joerg Wunsch

             System wide configuration file is "C:\WinAVR-20100110\bin\avrdude.conf"

             Using Port                    : lpt1
             Using Programmer              : usbtiny
             AVR Part                      : ATMEGA328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom        65     5     4    0 no       1024    4      0  3600  3600 0xff 0xff
               flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
               lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

             Programmer Type : USBtiny
             Description     : USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/
avrdude.exe: programmer operation not supported

avrdude.exe: Using SCK period of 10 usec
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude.exe: Device signature = 0x1e9516
avrdude.exe: Expected signature for ATMEGA328P is 1E 95 0F
             Double check chip, or use -F to override this check.

avrdude.exe done.  Thank you.

PS C:\PARTICLE_LOCAL\optiboot\optiboot\bootloaders\optiboot> avrdude -v -p m328p -c usbtiny -F -U flash:w:optiboot_atmega328.hex:i

avrdude.exe: Version 5.10, compiled on Jan 19 2010 at 10:45:23
             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
             Copyright (c) 2007-2009 Joerg Wunsch

             System wide configuration file is "C:\WinAVR-20100110\bin\avrdude.conf"

             Using Port                    : lpt1
             Using Programmer              : usbtiny
             AVR Part                      : ATMEGA328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom        65     5     4    0 no       1024    4      0  3600  3600 0xff 0xff
               flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
               lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

             Programmer Type : USBtiny
             Description     : USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/
avrdude.exe: programmer operation not supported

avrdude.exe: Using SCK period of 10 usec
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude.exe: Device signature = 0x1e9516
avrdude.exe: Expected signature for ATMEGA328P is 1E 95 0F
avrdude.exe: safemode: lfuse reads as E2
avrdude.exe: safemode: hfuse reads as D6
avrdude.exe: safemode: efuse reads as 5
avrdude.exe: NOTE: FLASH memory has been specified, an erase cycle will be performed
             To disable this feature, specify the -D option.
avrdude.exe: erasing chip
avrdude.exe: Using SCK period of 10 usec
avrdude.exe: reading input file "optiboot_atmega328.hex"
avrdude.exe: writing flash (32768 bytes):

Writing | ################################################## | 100% 77.23s



avrdude.exe: 32768 bytes of flash written
avrdude.exe: verifying flash memory against optiboot_atmega328.hex:
avrdude.exe: load data flash data from input file optiboot_atmega328.hex:
avrdude.exe: input file optiboot_atmega328.hex contains 32768 bytes
avrdude.exe: reading on-chip flash data:

Reading | ################################################## | 100% 40.92s



avrdude.exe: verifying ...
avrdude.exe: 32768 bytes of flash verified

avrdude.exe: safemode: lfuse reads as E2
avrdude.exe: safemode: hfuse reads as D6
avrdude.exe: safemode: efuse reads as 5
avrdude.exe: safemode: Fuses OK

avrdude.exe done.  Thank you.

 

 

 

 

I love the smell of burning silicon in the morning

Last Edited: Mon. Sep 24, 2018 - 07:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaza_tom wrote:
Still not sure how to download all the files in that repo so that I can do global symbol searches
you follow the advice on this page...

 

http://savannah.nongnu.org/svn/?...

 

So you need a copy of SVN then you do an "svn co" where co=checkout

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Appears that there is no way within Arduino IDE to upload an application using an external programmer while still retaining any pre-existing bootloader

 This is a CHIP-LEVEL limitation of AVRs.  There is no way to upload an application without erasing the bootloader section as well as the application section using ANY "ISP" programmer.  (it seems to be possible with debugwire...)

 

I'm glad you got things mostly working!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hookay.

 

As you've probably surmised if you've read all the way down to here, I decided to write a STK500 based app that reads a hex file from an SD card and sends the program it contains to another avr target that is running OptiBoot.  I just took a crack at making the code "nice" and "friendly" for Arduino-development.  I originally wrote this to run on a Particle Electron, but it seems to compile at least in Arduino IDE now that I've eliminated Particle dependencies.  I got it working on a Particle Electron.

 

It even compiles with SdFat included within it.  (no need to install separate library)

 

I haven't tested this version, and haven't tried it on an Arduino, but it should be close to working, and at the very least serve someone else well as a template.

 

Fork off eh?  yes

 

Optiboot_App_Flasher on GitHub

I love the smell of burning silicon in the morning

Last Edited: Fri. Sep 28, 2018 - 02:06 AM