OptiLoader port to Particle and SPI clock stretching

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

(cross posted to WestfW/OptiLoader on GitHub)

 

Hi all ,

 

I'm trying to port OptiLoader over to the Particle Platform so that I can use an Electron to flash Optiboot to an ATmega328PB 

I'm having difficulties that I believe are arising from the peculiar timing of SPI signals used to implement the AVR ISP protocol.

Here is a logic analyzer grab of my AVR pocket programmer burning Optiboot:

 

Overview

 

 

 

 

Programming Enable Instruction

 

 

 

 

WTF

 

Am I seeing things correctly? It would appear that there is some sort of SPI clock stretching going on here....  I didn't think SPI could do that.....

 

When I try OptiLoader on a Particle Electron, I get the same as above except the SCK signal is at 117 kHz and it never stretches, and all I get is 0xFF back from the ATmega

 

It actually _did_ work once out of 30 times but I wasn't able to replicate upon further testing.

 

 

My problems:

 

  • Slowest the SPI peripheral of the Electron can go is 30/256 Mhz = 117 kHz (the AVR pocket programmer goes at ~87 kHz)
  • SPI clock stretching is not supported by the peripheral

 

 

So, questions for @westfw (cross posted to the OptiLoader GitHub)

 

  • Does OptiLoader implement SPI clock stretching?
  • Can you see any reason why a non-clock-stretched sketch using a hardware SPI peripheral running at 117 kHz would not work?

 

 

 

I love the smell of burning silicon in the morning

Last Edited: Tue. Feb 12, 2019 - 03:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look at the functions start_pmode and end_pmode - they toggle the spi port bits directly.

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

It would appear that there is some sort of SPI clock stretching going on here....  I didn't think SPI could do that.....

It's a synchronous protocol, totally under control of the transmitter.  Stuff should happen at the appropriate clock edge, and the spacing between clocks can be as random as it wants to be.  (usually I see "clock stretching" used to refer to some method that the slave device has of making the master go slower.  As far as I know, SPI can't do that, and that's not what is happening here.)

 

USBTiny runs on an ATtiny2313, and it's implementation of SPI is done completely in software.  It's also servicing USB data, a byte at a time, in an ISR.  I suspect that what you are seeing is some sort of USB traffic arriving during the SPI transaction.

 

Optiloader uses the ATmega SPI peripheral, so it would look signficantly different.

 

  • Can you see any reason why a non-clock-stretched sketch using a hardware SPI peripheral running at 117 kHz would not work?

No.   But you should understand that to write OptiLoader, I took the "already working" "Arduino as ISP" sketch and replaced the com channel with code that read an image from PROGMEM instead, so I never got too far in-depth WRT SPI.

 

SPI does have a bunch of configurable options, including which clock edge is significant, and which bit order is used, and so on.  If you have one of those different than required by the AVR ISP protocol, it probably won't work...

 

all I get is 0xFF back from the ATmega

But I'd think you would get SOMETHING other than 0xFF...

 

So... WHICH Photon?  I see an STM32 photon and several Nordic versions...

 

 

You could consider bit-banging the SPI on the photon.  SPI is really trivial.  Here's the code from USBTinyISP:

// ----------------------------------------------------------------------
// Issue one SPI command.
// ----------------------------------------------------------------------
static	void	spi ( byte_t* cmd, byte_t* res, int i )
{
	byte_t	c;
	byte_t	r;
	byte_t	mask;

	while (i != 0)
	{
	  i--;
		c = *cmd++;
		r = 0;
		for	( mask = 0x80; mask; mask >>= 1 )
		{
			if	( c & mask )
			{
				PORT |= MOSI_MASK;
			}
			delay();
			PORT |= SCK_MASK;
			delay();
			r <<= 1;
			if	( PIN & MISO_MASK )
			{
				r++;
			}
			PORT &= ~ MOSI_MASK;
			PORT &= ~ SCK_MASK;
		}
		*res++ = r;
	}
}

 

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

Did a bunch more testing today.  I wanted to establish a baseline of functionality in terms of getting Optiboot installed using different "working" methods.  As described below, all methods but one failed.

 

I've attached the logic analyzer captures for Saleae Logic 8 software (available for free download here) if you want to peruse them.

 

Programmer: USBtinyISP

 

  • Worked 100% of the time flashing my ATmega328PB on my custom PCB with no error messages in Arduino IDE
  • Worked ~90% of the time flashing my Arduino MEGA 2560, but would take more than 20 seconds and would always display the following error messages in the Arduino activity monitor:

 

C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/bin/avrdude -CC:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/etc/avrdude.conf -v -patmega2560 -cusbtiny -e -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xD8:m -Ulfuse:w:0xFF:m 

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/etc/avrdude.conf"

         Using Port                    : usb
         Using Programmer              : usbtiny
avrdude: usbdev_open(): Found USBtinyISP, bus:device: bus-0:\\.\libusb0-0001--0x1781-0x0c9f
         AVR Part                      : ATmega2560
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         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    10     8    0 no       4096    8      0  9000  9000 0x00 0x00
           flash         65    10   256    0 yes    262144  256   1024  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 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, https://learn.adafruit.com/usbti...
avrdude: programmer operation not supported

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

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9801 (probably m2560)
avrdude: erasing chip
avrdude: Using SCK period of 10 usec
avrdude: reading input file "0x3F"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3F:
avrdude: load data lock data from input file 0x3F:
avrdude: input file 0x3F contains 1 bytes
avrdude: reading on-chip lock data:

C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/bin/avrdude -CC:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/etc/avrdude.conf -v -patmega2560 -cusbtiny -Uflash:w:C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.207/bootloaders/stk500v2/stk500boot_v2_mega2560.hex:i -Ulock:w:0x0F:m 

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/etc/avrdude.conf"

         Using Port                    : usb
         Using Programmer              : usbtiny
Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of lock verified
avrdude: reading input file "0xFD"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xFD:
avrdude: load data efuse data from input file 0xFD:
avrdude: input file 0xFD contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0xD8"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xD8:
avrdude: load data hfuse data from input file 0xD8:
avrdude: input file 0xD8 contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xFF"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xFF:
avrdude: load data lfuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude done.  Thank you.

avrdude: usbdev_open(): Found USBtinyISP, bus:device: bus-0:\\.\libusb0-0001--0x1781-0x0c9f
         AVR Part                      : ATmega2560
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         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    10     8    0 no       4096    8      0  9000  9000 0x00 0x00
           flash         65    10   256    0 yes    262144  256   1024  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 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, https://learn.adafruit.com/usbti...
avrdude: programmer operation not supported

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

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9801 (probably m2560)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: Using SCK period of 10 usec
avrdude: reading input file "C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.207/bootloaders/stk500v2/stk500boot_v2_mega2560.hex"
avrdude: writing flash (261406 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 261406 bytes of flash written
avrdude: verifying flash memory against C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.207/bootloaders/stk500v2/stk500boot_v2_mega2560.hex:
avrdude: load data flash data from input file C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.207/bootloaders/stk500v2/stk500boot_v2_mega2560.hex:
avrdude: input file C:\Users\Boompy\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.207/bootloaders/stk500v2/stk500boot_v2_mega2560.hex contains 261406 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
Error while burning bootloader.
avrdude: verification error, first mismatch at byte 0x3e000
         0xff != 0x0d
avrdude: verification error; content mismatch

avrdude done.  Thank you.

s take >20 seconds and have the following error logs posted to Arduino activity monitor:

 

USBTinyISP flashing the ATmega328PB - entire transaction:

 

USBTinyISP flashing the ATmega328PB - serial programming command:

 

 

USBTinyISP flashing the Arduino MEGA 2560 - entire transaction (more than 20 seconds!):

 

 

 

Arduino MEGA 2560 Running ArduinoISP

 

  • This failed 100% of the time in flashing bootloader to anything at all
  • When target was another Arduino ATmega2560, MOSI and MISO lines were stuck high
  • When target was my ATmega328PB on custom PCB, MOSI and MISO lines actually twiddled, but MISO still ended up being all 0XFF

 

 

for example:

 

Arduino MEGA 2560 running ArduinoISP flashing bootloader to ATmega328PB on custom PCB - powered off programmer 5V power header pin

 

Arduino MEGA 2560 running ArduinoISP flashing bootloader to another Arduino 2560 powered off programmer 5V power header pin

 

 

Arduino MEGA 2560 Running OptiLoader

 

  • This failed 100% of the time in flashing bootloader to anything at all as well
  • Note that MOSI and MISO lines are high throughout entire capture

 

 

Arduino MEGA 2560 running OptiLoader flashing bootloader to another Arduino 2560 powered off programmer 5V power header pin