Optiboot help needed

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

I'm back at a project that I intended to start months ago and never got rolling on.

 

I have an application with a Pro Mini (ATMega 328P), that talks to smartphones via BLE (both iPhone and Android).  The application on the Pro Mini talks over the BLE modem using the Tx and Rx pins.  There is no initialization code needed to talk over the BLE modem.

 

I want to update the bootloader on the Pro Mini so that I can upload new application code to it from a smartphone.  I also want to retain compatibility with the existing bootloader so that I can continue to upload my code using Atmel Studio.

 

I am a very experienced C/C++ programmer, but don't know much about bootloaders.  I'm looking at Optiboot (recommended in an old thread I started on this topic).  It looks like a good choice, although I have a hard time seeing the forest for the trees, with all the conditional complication directives the source contains.

 

Questions:

1) Do you recommend Optiboot?  Will that be compatible with the existing bootloader so that I can use Atmel Studio to upload hex files?

 

2) Can you tell me how to compile it and upload it to the Pro Mini?  The optiboot project I found here:

https://github.com/Optiboot/optiboot

 

contains an Atmel Studio project called "xplained328p"...  Can I use that to build the bootloader?  How do I upload it?  (I didn't see any documentation on that, please point me to it if there is any!)

 

3) Is there any source anywhere for what sits at the other end of Optiboot?  Would that be avrdude?  If there's "tighter" code that only talks whatever Optiboot talks - that would be preferable.  I need to port something to both iPhone and Android, so the less unneeded code the better. 

 

- Dave

 

 

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

Optiboot talks a subset of stk500v1.

http://www.atmel.com/images/doc2525.pdf

https://www.google.ca/search?q=stk500v1

 

A self-updating bootloader is not a trivial task.  It is also a questionable goal.  The point of a bootloader is that it be rock-solid from the get-go.  A bug in application code, or a failed bootload, should never render the device inoperable.  The bootloader should >>always<< be able to recover by loading new app code.  With a self-updating bootloader, if the bootloader update procedure fails half-complete, or if the new bootloader has a critical flaw, it's 'game over'.

 

Why do you think you need the ability to update the bootloader over-the-air?

 

If you're having trouble understanding the Optiboot code because of the compile-time conditionals, just edit a copy of the code to purge them.  For example, knowing:

#define LED_START_FLASHES 0

... with no #define for SOFT_UART, and an m328p target, then this:

#if LED_START_FLASHES > 0
  // Set up Timer 1 for timeout counter
  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
#endif
#ifndef SOFT_UART
#ifdef __AVR_ATmega8__
  UCSRA = _BV(U2X); //Double speed mode USART
  UCSRB = _BV(RXEN) | _BV(TXEN);  // enable Rx & Tx
  UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);  // config USART; 8N1
  UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
#else
  UCSR0A = _BV(U2X0); //Double speed mode USART0
  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
#endif
#endif

... becomes this:

  UCSR0A = _BV(U2X0); //Double speed mode USART0
  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Nov 3, 2015 - 10:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry - I guess I wasn't clear.  I don't want a self updating bootloader.  I want to modify the bootloader to support OTA updates over BLE.  Once I get my bootloader working, and put it on the Pro Mini, I won't need to update it again.  I'll put it on once, then use it to support OTA updates of my application firmware.  I'd also like it to continue to work with Atmel Studio so I can push builds to the Pro Mini during development.

 

I realize I can edit the code the way you say.  I really do know C/C++ quite well, spent over 20 years coding in it, trained teams in it, yada yada.  Maybe I'll do what you say.  A bit of a hassle, but not a huge deal.  But from what I see, many of those constants aren't explained anywhere.  Since Optiboot was written to support many different "flavors", it obfuscates it relative to what the code would look like if it only needed to do what I need it to do.  Oh well, it is a starting point.

 

If you know of anything that would be cleaner as a starting point for me, let me know.  Otherwise, if you or someone else could help me get started with this and Optiboot, I'd appreciate it!

 

(Update - sorry, I should have said earlier.  I use an Atmel Ice to update the Pro Mini from Atmel Studio, if it matters...)

Last Edited: Tue. Nov 3, 2015 - 10:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is it that you need some method of INVOKING the boot loader, from the phone?

 

 

 

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

many of those constants aren't explained anywhere

I'd say most are pretty self-documenting.  For the rest, the project itself is pretty well documented too:

https://github.com/Optiboot/optiboot

 

Some, like __AVR_ATmega8__, are defined by the toolchain.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Yes, I guess that's what I'm saying.  I want to be able to send my application (a hex file) from the phone.  The phone talks to the Pro Mini through a BLE modem connected to Rx/Tx.  I have the phone communicating fine with the Pro Mini, but need to modify the bootloader so it can accept files from the phone.

 

Does that make sense?

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

Quote:
Does that make sense?
Yes but how will you invoke the bootloader?  Generally, a bootloader like runs after a reset.  In the case of optiboot, it detects what the reset source was, and if it was external, it waits listens for commands.  If they don't come before a timeout (2 seconds?), it launches the app.  On an Arduino, the programming software (avrdude) issues a device reset via the serial port's DTR line.

 

How will you achieve this over BLE?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I can continue to use avrdude connected as it is now (via the Atmel ICE), for development.  So "my" bootloader needs to continue to support that.  For BLE, I suppose what I had in mind was that my application software would get a command telling it to jump into the bootloader.  It would jump into the bootloader in such a way that it knows that a new hex file is about to be sent.  Then it would wait for bootloader commands, which if they don't come, it would go back into the app. 

 

Or something like that.

 

Seems pretty straightforward.

 

So I need to know how to modify the bootloader so that it can accept data from the Tx/Rx lines, and I need some source code that I can use as a starting point to write my version of avrdude to run on the smartphone.

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

dptdpt wrote:
I suppose what I had in mind was that my application software would get a command telling it to jump into the bootloader.
I wouldn't.  If you bootload a broken app, or if bootloading fails (entirely possible with any wireless link), then how would you invoke the bootloader?  Don't rely on the app to launch the bootloader.

 

Look into your BLE module and the BT serial modem support.  Perhaps there is a DTR or similar secondary signal which you could use to trigger a reset in a manner similar to that used by Arduino/avrdude already.

 

Quote:
So I need to know how to modify the bootloader so that it can accept data from the Tx/Rx lines,
That's how it already works.

 

Quote:
and I need some source code that I can use as a starting point to write my version of avrdude to run on the smartphone.
You don't need source code.  You need a protocol specification.  I have already provided you with a link to that.  Or you could port avrdude to Android/iOS/whatever.  It's open source.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

1) Do you recommend Optiboot?  Will that be compatible with the existing bootloader so that I can use Atmel Studio to upload hex files?

Sort of.  optiboot isn't directly compatible with Atmel Studio; you have to use avrdude or other "external" tool.

 

2) Can you tell me how to compile it and upload it to the Pro Mini?  The optiboot project I found here:

https://github.com/Optiboot/optiboot

contains an Atmel Studio project called "xplained328p"...  Can I use that to build the bootloader?

optiboot is nominally a command-line/Makefile based tool.   I recently added the "project" files to make it easier for Atmel Studio users.   The xplained328p project should run on any 328 or 328p; the only thing special for Xplained is the serial speed is set to 57600 instead of 115200.

Have you looked at the wiki that is part of the github page?   There is quite a bit of documentation there (not much specific to Atmel Studio.)   The AS build will produce a .hex file that you then need to burn into the chip using "your choice of programmer" (and making sure that you also set the fuses appropriately.)

 

3) Is there any source anywhere for what sits at the other end of Optiboot?  Would that be avrdude?

 Yes, that would be avrdude.  Which isn't very readable :-(

I think someone has written an Arduino sketch that speaks the upload protocol, but it's a bit hard to search for :-(

 

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

Ok, thanks.  So if you know of the best source code to start from for me to write the "client" end of the bootload (anything more readable than avrdude?) - please let me know. 

 

Is there any way I can debug the bootloader?  I have an Atmel ICE and Atmel Studio.  Is there a way to debug the bootloader, as you do with application firmware?  You say that Atmel Studio can't directly upload the bootloader...  Presumably, I can invoke avrdude from Atmel Studio to do the upload, but that doesn't help me with debugging.

 

And I am unable to build optiboot using AS.  Maybe it's an issue with the latest version? (I'm on AS 7.0.594).  Here's the output from AS when I try to build xplained328p:

 

------ Build started: Project: xplained328p, Configuration: Debug AVR ------
Build started.
Project "xplained328p.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "C:\Users\owner\Documents\Arduino\AmicusBorgBootLoader\optiboot-master\optiboot\AtmelStudio\xplained328p.cproj" (target "Build" depends on it):
 Task "RunCompilerTask"
  Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
  C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe -C "C:\Users\owner\Documents\Arduino\AmicusBorgBootLoader\optiboot-master\optiboot\AtmelStudio\..\bootloaders\optiboot" -f "makefile" xplained328p 
  "C:\Program: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x4227d3)
 Done executing task "RunCompilerTask" -- FAILED.
Done building target "CoreBuild" in project "xplained328p.cproj" -- FAILED.
Done building project "xplained328p.cproj" -- FAILED.

Build FAILED.
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========

Any suggestions?

 

Thanks for the help!

 

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

Is there any way I can debug the bootloader? 

If you have a board that has a debugging connection (SWD for ATmega328p, I guess), you can debug the bootloader with AS by importing the binaries.  Note that the usual Arduino auto-reset circuitry interferes with SWD, so you'll need different (or patched) hardware.  I've debugged the 1284 version of Optiboot using JTAG.  Optiboot uses the WDT for starting the application and/or timing out the bootload, so debugging it can be a bit tricky.

The Atmel Xplained Mini board is probably a good choice; once you upgade the mEDBG firmware it supports both auto-reset AND debugging.

 

You say that Atmel Studio can't directly upload the bootloader

AS can't upload THROUGH the bootloader, but if you have an AS-supported programmer, there isn't any problem using the "Device programming" dialog to upload the bootloader itself.  I don't appear to have made the cproj correct to allow the "debug" commands to work, though.

 

 

  "C:\Program: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x4227d3)

That's pretty weird.  Looks like command or make crashing, rather than something specific to optiboot.  It works here (7.0.594 on W8.1):

------ Build started: Project: xplained328pb, Configuration: Debug AVR ------
Build started.
Project "xplained328pb.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "C:\Users\westf_000\Documents\Atmel Studio\optiboot-master\optiboot\AtmelStudio\xplained328pb.cproj" (target "Build" depends on it):
    Using "RunCompilerTask" task from assembly "C:\Program Files (x86)\Atmel\Studio\7.0\Extensions\Application\AvrGCC.dll".
    Task "RunCompilerTask"
        Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
        C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe -C "C:\Users\westf_000\Documents\Atmel Studio\optiboot-master\optiboot\AtmelStudio\..\bootloaders\optiboot" -f "makefile" xplained328pb
        make: Entering directory `C:/Users/westf_000/Documents/Atmel Studio/optiboot-master/optiboot/bootloaders/optiboot'
        C:/Program Files (x86)/Atmel/Studio/7.0/shellUtils/make atmega328 AVR_FREQ=16000000L BAUD_RATE=57600
        make[1]: Entering directory `C:/Users/westf_000/Documents/Atmel Studio/optiboot-master/optiboot/bootloaders/optiboot'
        avr-gcc (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2
        Copyright (C) 2014 Free Software Foundation, Inc.
        This is free software; see the source for copying conditions.  There is NO
        warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
        process_begin: CreateProcess(NULL, bash baudcheck.tmp.sh, ...) failed.
        make (e=2): The system cannot find the file specified.
        make[1]: [baudcheck] Error 2 (ignored)
        avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p -DF_CPU=16000000L  -DBAUD_RATE=57600 -DLED_START_FLASHES=3        -c -o optiboot.o optiboot.c
        avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -mmcu=atmega328p -DF_CPU=16000000L  -DBAUD_RATE=57600 -DLED_START_FLASHES=3      -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe -Wl,--relax -nostartfiles -nostdlib -o optiboot_atmega328.elf optiboot.o -lc
        avr-size optiboot_atmega328.elf
           text       data        bss        dec        hex    filename
            464          0          0        464        1d0    optiboot_atmega328.elf
        avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_atmega328.elf optiboot_atmega328.hex
        avr-objdump -h -S optiboot_atmega328.elf > optiboot_atmega328.lst
        rm optiboot.o optiboot_atmega328.elf
        make[1]: Leaving directory `C:/Users/westf_000/Documents/Atmel Studio/optiboot-master/optiboot/bootloaders/optiboot'
        mv optiboot_atmega328.hex optiboot_xplained328pb.hex
        mv optiboot_atmega328.lst optiboot_xplained328pb.lst
        make: Leaving directory `C:/Users/westf_000/Documents/Atmel Studio/optiboot-master/optiboot/bootloaders/optiboot'
    Done executing task "RunCompilerTask".

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

Thanks for the help!

 

So, I found the problem with Make.  Described here: http://hdrlab.org.nz/articles/windows-development/make-interrupt-exception-caught-code-0xc00000fd-addr-0x4217b/

 

Basically, there's a bug in Make that causes it to crash if you have any parenthesis in your path environment variable.  I do - since I'm on Windows 64 bit.  I was able to fix it by editing my path.

 

Regarding your other feedback:

 

* I don't know what all your abbreviations refer to.  I was able to figure out that "WDT" refers to watchdog timer.  But what's "SWD"?

 

* I ordered an "Atmel xplained mini board".  I'd never heard of that, and still don't know exactly what it is, but I was able to find it on Atmel's site.  I don't know what the "mEDBG firmware" is.  Some googling didn't clear it up.  Would you mind pointing me to some documentation?  Especially on how to upload a bootloader onto it and how to debug it.  I'd rather not have to keep bugging you, but I need some docs to get me started.

 

* And any general documentation on bootloaders - how to burn them, etc, would be helpful.  I'm still pretty green on the whole bootloader business.

 

- Dave

 

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

there's a bug in Make that causes it to crash if you have any parenthesis in your path

Thanks for finding that!

 

But what's "SWD"?

"Single Wire Debug", I think?  It looks like I should have said "debugWire", which is the Atmel term on the AVRs.  A lot of microcontrollers have debugging capabilities that will communicate over a small number of pins, which is useful on microcontrollers with not very many pins to start with.  The Atmel AVR version (debugWire, in the datasheet) uses the RESET pin, and the circuitry that a normal Arduino has on the reset pin interferes with it.

 

 

* I ordered an "Atmel xplained mini board".  I ... don't know exactly what it is ...  I don't know what the "mEDBG firmware" is.

The Atmel "Xplained" boards are evaluation boards for various chips (I hope you ordered the right one.)  They have two microcontrollers; one is the chip you're supposed to "evaluate", and the other provides an interface to the Atmel Studio Debugger, and a USB/Serial function.   The Xplained "mini" boards have an Arduino-compatible pin layout (but not actual connectors), and the "Xplained Mini 328p" is real close to being equivalent to an Arduino Uno (only cheaper, and with a debugger interface.)  Since the 2nd "debugger interface" chip is also a microcontroller, it also has firmware, and Atmel has changed that firmware since the time they decided "hey, wouldn't it be a good idea if this board worked with the Arduino IDE as well as with Studio?"  (Firmware will normally be updated automatically when you try to use the board with AS.)

There's a user guide: http://www.atmel.com/Images/Atme...

 

 

* And any general documentation on bootloaders - how to burn them, etc, would be helpful.

Aside from the Optiboot wiki on github, and the various discussions on the Arduino forums and elsewhere that talk a lot about the Arduino bootloader, there is this FAQ: https://www.avrfreaks.net/forum/f...

And Atmel has several App notes on the topic.  (although. IMO, Atmel generally confuses the issue by re-using Programmer Communications Protocols as bootloader protocols.

A bootloader isn't really any different than any other AVR application (and is burnt using the same or similar tools.)  In the particular case of Optiboot and Atmel Studio, there is the complication that the "AS Project" meta-data is kludged together on top of a structure that is NOT an AS Project, and the single button "compile, load, and start debugging" buttons don't work.  (I might be still working on making them work anyway, but ... not yet.)

 

 

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

Thanks for the help, Westfw!

 

I'm now wondering if I even need to write my own bootloader.  If the bootloader preinstalled on the AVR is using Rx/Tx to communicate, then it should be able to already read the app hex file from the BLE modem.  I still have to write the other end of the connection though - what runs on the smartphone.

 

Would you happen to know which bootloader is preinstalled on my AVRs (Arduino Pro Mini)?  Is it https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/bootloaders ?  Do you know if that uses Rx/Tx for communication?  If so - won't it work already with my BLE modem - or am I missing something?

 

The bootloader above uses the stk500 protocol - correct?

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

Look in your "boards.txt".   On my PC it is at C:\Program Files (x86)\Arduino-1.6.5\hardware\arduino\avr

 

##############################################################

pro.name=Arduino Pro or Pro Mini

pro.upload.tool=avrdude
pro.upload.protocol=arduino

pro.bootloader.tool=avrdude
pro.bootloader.unlock_bits=0x3F
pro.bootloader.lock_bits=0x0F

pro.build.board=AVR_PRO
pro.build.core=arduino
pro.build.variant=eightanaloginputs

## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328
## -------------------------------------------------
pro.menu.cpu.16MHzatmega328=ATmega328 (5V, 16 MHz)

pro.menu.cpu.16MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328.upload.speed=57600

pro.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0x05
pro.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex

pro.menu.cpu.16MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328.build.f_cpu=16000000L

## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
## --------------------------------------------------
pro.menu.cpu.8MHzatmega328=ATmega328 (3.3V, 8 MHz)

pro.menu.cpu.8MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.8MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.8MHzatmega328.upload.speed=57600

pro.menu.cpu.8MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.8MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.8MHzatmega328.bootloader.extended_fuses=0x05
pro.menu.cpu.8MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex

pro.menu.cpu.8MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.8MHzatmega328.build.f_cpu=8000000L

Yes the bootloader uses stk500v1 protocol.   (-c arduino means stk500v1 with DTR pulse)

 

You can change bootloader if you want.    Make sure that you edit boards.txt accordingly.

The existing bootloader would work via BLE if you have a suitable baud rate and a method of triggering Reset.

 

David.

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

Thanks David.

 

So boyoboyoboy - I'm struggling with the best way to approach this.  I'd thought I'd just port avrdude over to run on the smartphone.  But I'm looking at the avrdude source, and there is sooo much there - most of it not really needed for what I'm trying to do.  So unless there's a tighter upload application that's better documented, I think working with avrdude is a non-starter.

 

So that puts me back to square one.  I'm now thinking the easiest way to do this would be to go back to optiboot as my bootloader, and just code the other end of the connection from scratch.  So that would be an implementation of something that uses the stk500 protocol to send the compiled hex file of my application - correct?   I'm looking at the stk500 protocol definition, and that doesn't quite walk me through what I need to do though.  It documents the protocol - the commands and responses, but I still need an overview that talks about the order of the commands - the general flow or algorithm.  Is that documented anywhere?  It's also confusing because the documentation talks about "the stk500".  What is that?  Some kind of device that speaks the stk500 protocol?

 

And optiboot's design goal seems to be to produce tight fast code.  That's great, but it makes it a little harder for me to decipher.  So if anyone knows of a more simple (perhaps larger), and well commented and documented - bootloader, please let me know.

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

Uncle Google will answer most of your questions.

 

If you explain exactly what you want to do,    I am sure that you would get some useful advice.    You don't need avrdude source code or anything complex.

 

It comes down to what sort of access you have to a device.     For example,   if you have it in your hand,  you can start a bootloader,  connect to some remote server by BLE,   upload some new firmware.

 

Equally,   you could do this from a running program.   i.e. IAP (In Application Programming)

 

The "Server" end of your BLE has only got to read a disk,  send and receive packets according to stk500v1 (or other) protocol.    Your AVR receives the packets and sends "handshakes",   programs Flash pages,   continues the Application (IAP) or starts the new Application (Bootloader)

 

Think about it.   Your PC exchanges packets over an error-prone Internet with a protocol.   i.e. verifies good packets,   asks for repeat or new packet etc.    A phone line,  radio link,  satellite link,  ... are never perfect.

 

David.

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

Ok, folks - I'm temporarily stuck. I want to jump to the start address of the Bootloader when my application gets a command that the client wants to send a new hex file. What is the starting address of the default Bootloader on the atmega328? I tried Uncle Google, but haven't had any luck.

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

People have had troubles in the past, trying to run the standard bootloaders over a wireless link.  I'll confess to not having paid as much attention to this as perhaps I should have, and I'm not sure whether there are just reset problems, or timing issues, or what...

 

What is the starting address of the default Bootloader on the atmega328?

 0x7E00, or perhaps half of that, depending on whether the code you're using wants word addresses or byte addresses.  (probably word addresses, if you're jumping there, depending on whether the C compiler munges the address for you.  So 0x3F00.

 

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

The bootloader address depends on the fuses.   I suspect that your BLE link is slower than 115k or even 57k baud.

 

Regular BlueTooth works very well on my PC for a display Terminal.   e.g. no messy USB or RS232 cables.

 

As westfw says,   you might get some timing glitches.   The BT at either end has to build packets to send and decode / verify packets it receives.   Any software will need to allow for this.    I guess that BLE does exactly the same but slower.

 

David.

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

Not making much progress here.

 

So I thought I'd just try sending some stuff to the bootloader and see what happened.  Based on that, see if I wanted to try working with the existing bootloader, or replace it with Optiboot.

 

So I'm jumping to the bootloader at 0x7E00, and nothing is there.  I don't understand what you're saying about C interpreting addresses as word addresses.  I don't see how it could do that - if it did, you'd never be able to reference odd offsets into character arrays, for example.

 

So I first tried:

void (*boot)(void)= (void(*)(void))0x7E00; 

// Call (jump into) the bootloader
boot();

I stepped through that code in Atmel Studio (I have an Atmel ICE), and switched the debugger to "View Disassembly".  That call instruction takes you to the instruction pointer 3F00, not 7E00.  So it's the instruction pointer that treats addresses as word addresses -  not C - correct? 

 

So the issue is that there's no code at 7E00 (3F00 word address).  It's just memory that's filled with 0x80. 

 

Meanwhile, just to see what would happen, I changed my code to actually use assembler to jump to the bootloader.  So I did:

 

File: CallBootloader.s

; Jump into the bootloader at 0x7E00

.global call_bootloader

call_bootloader:
 jmp 0x7E00

 

My C code:

extern "C" void call_bootloader();

  call_bootloader();

That did the same thing - went to 3F00.

 

Just for grins, I scrolled down to 7E00 in the AS debugger, and there's no code there either.

 

So any other thoughts as to where the bootloader is?

 

And - regarding the ST500 protocol, I'm using this for doc:

http://www.atmel.com/dyn/resources/prod_documents/doc2525.pdf

 

It describes the commands and responses, but not the actual protocol.  Is there no packeting of the messages?  Or to send a command, do I just send the single command byte over the link?

 

I think (hope) that these are simple questions and really appreciate everyone's time who's helping here.  Hopefully I'll get this working soon and we can get on with our lives!

 

- Dave

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

I don't think that AS makes it easy to debug code that is in the device FLASH, but not in your project .elf file; I'm not sure what it will do if your jump to the bootloader address...

I'll do some experiments...

 

Is there no packeting of the messages? 

 Nope; just individual bytes.   This overly simplistic "protocol" is updated in STK500v2...

 

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

(also, note that if you upload a program with Atmel Studio using one of the usual hardware programmers, it will erase the bootloader.  In order NOT to erase the bootloader, you must upload the .hex file WITH the bootloader.  Which may make it difficult for AS to attach debugging to it.)

 

(or, build a merged bootloader/app file and let AS upload that...)

 

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

Yikes.  I didn't know that.  So, assuming that "one of the usual hardware programmers" includes Atmel ICE, that would explain why there's no bootloader at 0x7E00 when I look there with AS.  Thanks!  I'm not sure I would have ever figured that out on my own.  I had thought that I'd used the Arduino IDE to upload an application after having used Atmel Studio, but maybe not...

 

So it sounds like building a merged bootloader/app file is the way to go. Then I can step through my app in AS, jmp to the bootloader, and step through that.  That would be awesome!  Once I have access to debuggable source code at both ends of the link, I'll be well through my current roadblocks.   I think I saw instructions as to how to combine a hex file with a bootloader somewhere - but if you can explain, I'd appreciate it! 

 

If that works, maybe I don't need the "Atmel xplained mini board".  I still have that on order, hasn't come yet.  Or maybe that will be useful, still not sure...

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

Or use avrdude and upload the second hex file with -D

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I'm trying to upload optiboot using AVRDude, and am getting an error.  The error is on the read verify after the upload.  Here's my command line:

 

"C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avrdude" -C"C:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -U flash:w:xx.hex

 

(I renamed the optiboot_xplained328p.hex to "xx.hex" because avrdude doesn't like underscores in the file name.  Ugh.  Took me a while to figure that out.

 

But after doing that, here's the output I get:


"C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avrdude" -C"C:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf" -v -patmega328
p -carduino -PCOM6 -b57600 -D -U flash:w:xx.hex

avrdude: Version 6.0.1, compiled on Jan 15 2015 at 16:58:43
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf"

         Using Port                    : COM6
         Using Programmer              : arduino
         Overriding Baud Rate          : 57600
         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    20     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 : Arduino
         Description     : Arduino
         Hardware Version: 2
         Firmware Version: 1.16
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e950f
avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: reading input file "xx.hex"
avrdude: input file xx.hex auto detected as Intel Hex
avrdude: writing flash (32768 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 32768 bytes of flash written
avrdude: verifying flash memory against xx.hex:
avrdude: load data flash data from input file xx.hex:
avrdude: input file xx.hex auto detected as Intel Hex
avrdude: input file xx.hex contains 32768 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x7e00
         0x0e != 0x1f
avrdude: verification error; content mismatch

avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK (H:00, E:00, L:00)

avrdude done.  Thank you.

 

Any suggestions?

Last Edited: Mon. Nov 9, 2015 - 01:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dptdpt wrote:
(I renamed the optiboot_xplained328p.hex to "xx.hex" because avrdude doesn't like underscores in the file name.  Ugh.  Took me a while to figure that out.
Rubbish.  Underscores pose no problems for avrdude.  If you're having trouble with that, there's something seriously wrong with your setup.

 

Your programmer:

dptdpt wrote:
"C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avrdude" -C"C:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -U flash:w:xx.hex

... >>is<< Optiboot, or another Optiboot-compatible bootloader.  What I mean is, the -c arduino command line option tells avrdude to talk to the bootloader on the COM port.  If you are trying to upload a bootloader to a bootloader, it won't work.

 

Note that the Pro Mini probably came preloaded with a bootloader.  Probably ATmegaBOOT_168_atmega328.hex, or ATmegaBOOT_168_atmega328_pro_8MHz.hex if it's a 3.3V 8 MHz Pro Mini.

 

What is your programmer?  Do you have it connected to your target?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Mon. Nov 9, 2015 - 02:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm.  You are correct about the rubbish.  I was getting an "error parsing update operation" error on the file, and I found something on the web where someone said avrdude didn't like underscores in the file name.  So I renamed the file, but at the same time I took out the long path prepending the file name.  Looks like it isn't the underscore, it's that avrdude has a max path size it can handle in the file name argument.  No biggie.  If I run it out of the directory where the file resides, I don't need the path.

 

And I see what you mean about overwriting the bootloader with the bootloader.  The problem I am trying to solve is to get a bootloader on there in the first place.  Westfw said that uploading my application with Atmel ICE had caused the bootloader to be erased, and that's why there is no code at 0x7E00.  So I guess I have no bootloader?  My goal is to have both the bootloader and the application on the pro mini.  Then I can jump into the bootloader from my application and start debugging.

 

So what would be the easiest way to get the bootloader and the application on the pro mini?  I have the optiboot source - I could use that.  For a programmer, I have the Atmel ICE.  I also have a Sparkfun FTDI breakout board (https://www.sparkfun.com/products/9716).

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

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Yes, avrdude -D.  That's what I'm trying to do.  So my programmer would be ... the Atmel ICE, I guess.

 

So will this work?  I upload my application with the Atmel ICE by pressing "start debugging and break".  That uploads the program and breaks on the first line of the application.  It also erases the bootloader - correct?  Then - I go to a command prompt and use avrdude to update the bootloader, using the hex file for optiboot.  Seems like avrdude won't be able to talk over the atmel ICE connection while Atmel Studio is using it, but I haven't tried that yet.

 

And assuming that the above would work - could you help me with the command line syntax for avrdude, to use the atmel ICE?

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

I wouldn't know how to accomplish it in AS or with the Atmel ICE, but basically, you want to upload one (say the bootloader) with avrdude >>without<< -D, then upload the second (say the app) with avrdude >>with<< -D.

 

As for debugging the whole lot in AS/AtmelICE, I'm afraid I won't be of any help.  I'm not certain you can accomplish what your attempting i.e. debugging two applications (the app & the bootloader) at the same time.  Wiser men than me perhaps can help you.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Gotcha.  Seems like avrdude isn't going to be the way to go because it doesn't let me connect to the running code with the Atmel ICE debugger.

 

Perhaps I could combine the application and the bootloader (optiboot) in the same Atmel Studio project?   Then I'd have both sets of code on the AVR, and all the source in one project and could debug to my heart's content.  I think I saw somewhere that that could be done.  Does anyone know if it can, and if so - how?

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

Correct, avrdude is merely programmer software, not a debugging front-end.  There may be a way to first start a debug session with AS/AtmelICE, suspend or stop that in order to release the ICE for use by avrdude, load the second component with avrdude and -D, then resume the debugging session.  I don't know how debugging sessions are/can-be started and stopped, or whether this is even possible.  I think that when you make changes to the debug environment like adding/removing/changing breakpoints, the device is reprogrammed, so even if you can do it this way it means that you'd have to redo the whole schemiel every time.

 

Again, smarter folks than I would need need to chime in with some sanity.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Can anyone out there help with this?

 

I need to know how I can add the optiboot sources to my Visual Studio project such that optiboot is compiled and linked with my project and uploaded to the AVR along with the project - thus putting me in a state where I can do source-level debugging of both my application and the bootloader.

 

Seems like this should be doable.

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

I re-iterate my warning that you not rely upon your application to launch the bootloader.  Doing so is begging for trouble.  The moment you upload a buggy application which is unable to launch the bootloader, you are hosed.  The moment a bootload fails part-way through because your BLE link goes down, you are hosed.  You must have an application-independent method of invoking the bootloader.

 

This will have the handy side-effect that you will no longer need to debug the app and the bootloader at the same time.

 

Look into how you can get your BLE widget to trigger an external reset of the AVR via the equivalent of a DTR or RTS signal from the smartphone end.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Joey - I explained this already, so either I'm not understanding you or you're not understanding me.

 

I do want to jump into the bootloader from my application, but only if the application gets a request to upload a new firmware version.  My plan is to have the bootloader continue to run on startup or reset.  So the bootloader can be invoked two ways - either at startup/reset, or as a result of being jumped into by the application.  And the bootloader would write some bytes at the end of application upload so it can verify that there's a valid application in the application section.

 

Do you see a problem with that?

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

Or - if nobody knows how to combine the bootloader and my application into one VS project, can anyone direct me as to how to create an AS project such that I can source debug the bootloader using the Atmel ICE?  That simplifies things and should be fairly doable - no?

 

The only real reason I wanted to combine my app and the bootloader was so I could step through the code where the app jumps into the bootloader.  But that's not a deal breaker.  It's just a single "jmp" that I don't really need to debug.  Seems like it would be nice to combine both into a single project anyway, but it's not a huge deal.

 

So I tried to build the optiboot makefile inside AS and step into it with the debugger.  AS seemed to "think" it had uploaded the bootloader, but when it went to break at the start of the code, there was nothing there.  It broke at the supposed start address of 3C00, but there was nothing there (a bunch of NOPs). 

 

I know that westfw said I should use the Atmel xplained mini board, but I'm not sure why that is necessary.  For debugging, I can temporarily comment out the WDT code so I can sit in the debugger and step through code - no?

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

No, I understand.

dptdpt wrote:
I do want to jump into the bootloader from my application, but only if the application gets a request to upload a new firmware version.  My plan is to have the bootloader continue to run on startup or reset.  So the bootloader can be invoked two ways - either at startup/reset, or as a result of being jumped into by the application.  And the bootloader would write some bytes at the end of application upload so it can verify that there's a valid application in the application section.
The right way for an application to invoke the bootloader is by the same mechanism used by a fresh bootload, i.e. a device reset.  If you want your app to be able to trigger a bootload, then either provide a mechanism for a GPIO pin to pull /RESET low for a minimum time (say, with a simple RC+diode circuit), or use a WDT reset.  The bootloader will need to treat a WDT reset no differently than an external reset.  This can present its own problems (i.e. normal use of WDT reset protection within an app will need to coordinate with the bootloader, or the bootloader will need to leave WDRF untouched while still avoiding a WDT reset of its own).

 

Either way, there should be no real reason to debug both the bootloader and the application at the same time, with some minor exceptions.  If you use a GPIO pin to trigger an external reset, you'll have some difficulty debugging that since /RESET is used by the debugger on the 328p.  If you use a WDT reset, you'll need to contrive some test code to stand in for the app while debugging the bootloader, and some test code to stand in for the bootloader while debugging the app.

 

IMO, it's a bad idea to jump into the bootloader from app code, since this requires that the app have knowledge of the bootloader, and more importantly that the bootloader be tolerant of non-default states of the device.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Ok.  I suppose I could trigger a WDT reset from the app.  That would be easy.  But I'm still not having a problem with the app jumping into the bootloader.  It can and will know what address the bootloader is at.

 

Anyway, my priority at this point is just to get a working bootloader.  I need to write the code at the other end of the BLE connection.  So to do this, I need to be able to debug the bootloader end of the connection.

 

Any thoughts as to how I can upload/debug optiboot using AS?  This, I think, is a much simpler question and I'd think it's been done many times.  But my level of understanding of the upload process, fuse settings, etc - is still low. 

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

Yes you can jump into the bootloader from the app and it may 'work', but my point is that the bootloader may very likely rely upon the post-reset default state of any number of device registers.  Many bootloaders do exactly that in order to reduce code size and fit into a smaller BLS.  If your app changes those before jumping to the bootloader, you're hosed.  You would need to make sure that the bootloader is bullet proof, i.e. explicitly configures >>all<< registers which could affect its operation.

 

The bootloader >>must  not<< rely upon the app for >>anything<<.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

So can anyone help me get going with debugging?  At this point, I'm just trying to connect to the AVR with AS and my Atmel ICE, after having uploaded optiboot.  I'll worry about loading optiboot with my application another time.

 

I can upload applications over DebugWire using the Atmel ICE and AS.  And when I try to load/debug Optiboot, it appears to load it, but "start debugging and break" stops at the address 3C00, and there's nothing there but a bunch of NOPs.

 

I'm using the xplained328p AS project in Optiboot.

 

Seems like it didn't really upload the bootloader although it "thinks" it did.

 

I'd just as soon configure the AS project to directly build the bootloader, rather than have it use an external makefile, but I don't know how to do that...

 

 

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

I'd just as soon configure the AS project to directly build the bootloader, rather than have it use an external makefile, but I don't know how to do that...

 You could build a new "C project" in AS, and import/copy the needed source files from Optiboot.  It's small, so that shouldn't be TOO much trouble...

 

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

Yes - sure, I could easily do that, and have something that compiled all the source code.  But I'm pretty fuzzy on what I'd need to do in the project to do things like set fuses and lock bits (whatever those are), the start address to load to, loading the program, and whatever else there is.  I don't know what I don't know. 

 

Is that how you think I should best approach getting something to work that I can upload and debug from AS/Atmel ICE?  I'm willing to give it a shot, and google around to figure things out, but I might need some help.

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

Try this...

 

Attachment(s): 

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

Thanks westfw!  That helps a ton!

 

 

So now using your excellent stripped down AS project, I am now able to build optiboot.  I still can't get debugging to work with the Atmel ICE.

 

 

I first tried the project as you sent it.  When I do "start debugging and break" in AS, it loads the bootloader code into my AVR, and runs it, but doesn't break.  So I thought it might have something to do with loading the bootloader into the bootloader section of the AVR memory.  Does that make sense? 

 

 

So I made a copy of the "Debug" configuration in your AS project, and took out the lines in the linker "Memory Settings" section:

.text=0x3f00

.version=0x3fff

 

 

That seemed to help.  Now AS breaks after loading the code.  But - where it breaks doesn't look like the start of main().  Here's what I see in the debugger (it breaks at location 0):

 

00000000  PUSH R1  Push register on stack 
00000001  IN R28,0x3D  In from I/O location 
00000002  IN R29,0x3E  In from I/O location 
00000003  CLR R1  Clear Register 
00000004  IN R24,0x34  In from I/O location 
00000005  OUT 0x34,R1  Out to I/O location 
00000006  MOV R25,R24  Copy register 
00000007  ANDI R25,0x0D  Logical AND with immediate 
00000008  BREQ PC+0x02  Branch if equal 
00000009  RCALL PC+0x00D8  Relative call subroutine 
0000000A  LDI R24,0x05  Load immediate 
0000000B  STS 0x0081,R24  Store direct to data space 
0000000D  LDI R24,0x02  Load immediate 
0000000E  STS 0x00C0,R24  Store direct to data space 
00000010  LDI R24,0x18  Load immediate 
00000011  STS 0x00C1,R24  Store direct to data space 
00000013  LDI R24,0x06  Load immediate 
00000014  STS 0x00C2,R24  Store direct to data space 
00000016  LDI R24,0x10  Load immediate 
00000017  STS 0x00C4,R24  Store direct to data space 
00000019  LDI R24,0x0E  Load immediate 
0000001A  RCALL PC+0x00B2  Relative call subroutine 
0000001B  SBI 0x04,5  Set bit in I/O register 
0000001C  LDI R24,0x06  Load immediate 
0000001D  LDI R18,0x30  Load immediate 
0000001E  LDI R19,0xFC  Load immediate 
0000001F  LDI R25,0x01  Load immediate 
00000020  STS 0x0085,R19  Store direct to data space 
00000022  STS 0x0084,R18  Store direct to data space 
00000024  OUT 0x16,R25  Out to I/O location 

and so on...

 

If I try to set a breakpoint in your code at the start of main(), it says "the current selected device is unable to set breakpoints during runtime".

 

I went back and loaded another project in AS and tried to debug that, and that still works fine.

 

Any ideas?

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

where it breaks doesn't look like the start of main().

Looks right to me.   See the "listing" (.lss) file:


/* main program starts here */
int main(void) {
    7e00:	1f 92       	push	r1
    7e02:	cd b7       	in	r28, 0x3d	; 61
    7e04:	de b7       	in	r29, 0x3e	; 62
  //  SP points to RAMEND
  //  r1 contains zero
  //
  // If not, uncomment the following instructions:
  // cli();
  asm volatile ("clr __zero_reg__");
    7e06:	11 24       	eor	r1, r1
   * modified Adaboot no-wait mod.
   * Pass the reset reason to app.  Also, it appears that an Uno poweron
   * can leave multiple reset flags set; we only want the bootloader to
   * run on an 'external reset only' status
   */
  ch = MCUSR;
    7e08:	84 b7       	in	r24, 0x34	; 52
  MCUSR = 0;
    7e0a:	14 be       	out	0x34, r1	; 52
  if (ch & (_BV(WDRF) | _BV(BORF) | _BV(PORF)))
    7e0c:	98 2f       	mov	r25, r24
    7e0e:	9d 70       	andi	r25, 0x0D	; 13
    7e10:	09 f0       	breq	.+2      	; 0x7e14 <main+0x14>
      appStart(ch);
    7e12:	d7 d0       	rcall	.+430    	; 0x7fc2 <appStart>

 

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

Ok, I guess you're right. That is main(), I didn't check against the compiled assembler. The real issue though is that AS isn't showing me the source code when it breaks. It's only letting me step through the assembler. It doesn't let me set break points in the source code, inspect variables, etc.

Any thoughts as to why that isn't working? And should I be able to have it load and step through the code where the Bootloader is supposed to reside, at 0x7E00?

Last Edited: Wed. Nov 11, 2015 - 06:25 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

should I be able to have it load and step through the code where the Bootloader is supposed to reside, at 0x7E00?

Yes.  I had only run it in the simulator when I first posted it, but now I've connected up an Xplained Mini 328 (whose mEDBG debug interface is supposed to be quite similar to the Atmel ICE), and it works OK, *EXCEPT* for figuring out where to do that initial breakpoint.  Trying manually adding a breakpoint on the "asm volatile ("clr __zero_reg__");" statement.

 

(There were also a series of questions about programming the "Enable DEBUGWIRE" fuse, which was a possible source of problem since it's not in the fuses in the source code.   But it seemed to fix things automagically, given the OK to do so.)

 

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

Any thoughts as to why that isn't working? And should I be able to have it load and step through the code where the Bootloader is supposed to reside, at 0x7E00?

A debugger only knows that location 0x1234 is function add_two_numbers() or that RAM location 0x456 is the variable counter because there is an entry in the symbol table of the ELF that tells it that. So if you have two programs in an AVR (bootloader and app) but only have the ELF details loaded for one of them then only that will be symbolically annotated (might even include C source if the ELF was built with -g). The other will just be a sea of AVR opcodes and the only thing the debugger can do to help is to run them through its disassembler. I guess that's exactly what is happening here. You should, however still be able to single-step and place breakpoints even if it is just raw Asm. To understand what the Asm is doing is you need to just read the .lss file as westfw showed above.

 

EDIT: forgot to say: use "avr-nm project.elf" on the ELF file the debugger will be using to find out what variable and function name symbols it "knows".

Last Edited: Wed. Nov 11, 2015 - 10:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, thanks.  Yes, I know about symbol tables.  Right now, I'm just trying to load and debug optiboot using the AS project that westfw gave me.  It doesn't seem to know about the source files/line numbers.  When I do a "stop debugging and break", it breaks in the disassembly window, it doesn't break in the source code.  In the disassembly window at the top, it says "No source file".  And it won't let me set breakpoints in the source code.   Maybe there's a compiler or linker setting missing that puts the line numbers in the elf file?  I compared the compiler and linker settings from the optiboot project and another project I have that ~does~ let me step through the source code, and I don't see anything missing from the optiboot project.  But maybe I'm missing something.

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

All those symptoms sound like -g is disabled. Was this a "Release" rather than a "Debug" build by any chance - usually the only thing (apart from optimisation level) that differs between those two is whether it is -g or not (which is actually a REALLY stupid decision on Atmel's part - but that's an argument for another day!).

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

No, it is a debug build.  It has -g2 in the compile settings.  Below are the compiler and linker settings.  Can you spot anything wrong?

 

Compile:

-x c -funsigned-bitfields -DDEBUG -DF_CPU=16000000L  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.90\include"  -Os -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.90\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"

 

Link:

-nostartfiles -nostdlib -Wl,-Map="$(OutputFileName).map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -mrelax -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.90\gcc\dev\atmega328p"

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

It works fine here, in both AS 6.2 on WXP and AS 7.0 on W8.

Here we have W8/AS7 , after setting a breakpoint manually on the clr instruction, using "start debugging and break", and one "step into" click.

 

Attachment(s): 

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

At a command line just try "avr-objdump -S output.elf" replacing output with project name. Does that reveal source annotation or not?

 

The fact is that the way -g works is that it does not embed the actual C code into the ELF file. It simply embeds things like "these 3 opcodes generated by c:\project\location\foo.c line 17". If when you try to use the debugger (or avr-objdump -S) foo.c is not in location c:\project\location\ then you won't get to see the C. Maybe this is what's happening?

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

 

 

Last Edited: Sun. Nov 15, 2015 - 01:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been away from this for a couple days.  Unfortunately, that doesn't mean that my problem went away.  I'm still unable to set breakpoints in AS in the Optiboot source code.

 

Westfw:

When I start up, it takes me straight to the disassembly window.  I am able to set breakpoints there.  This is what I see:

 

But if I try to set a breakpoint in the source code, I see this:

 

I'm also still not able to have it break at all (even in the disassembly window) if I load the code at 7E00.  From your screenshot above, it looks like that works for you.  Is it because I'm on an Atmel ICE and you're on an Atmel xPlained?

 

Clawson:

When I run the object dump as per your instructions above, I do see the source listing with the assembly.  I'm running it from a command prompt in the directory where the elf resides.  That's where I should run it from, right?  Here's what I see:

 


optiboot328.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <main>:
#define appstart_vec (0)
#endif // VIRTUAL_BOOT_PARTITION


/* main program starts here */
int main(void) {
   0: 1f 92        push r1
   2: cd b7        in r28, 0x3d ; 61
   4: de b7        in r29, 0x3e ; 62
  //  SP points to RAMEND
  //  r1 contains zero
  //
  // If not, uncomment the following instructions:
  // cli();
  asm volatile ("clr __zero_reg__");
   6: 11 24        eor r1, r1
   * modified Adaboot no-wait mod.
   * Pass the reset reason to app.  Also, it appears that an Uno poweron
   * can leave multiple reset flags set; we only want the bootloader to
   * run on an 'external reset only' status
   */
  ch = MCUSR;
   8: 84 b7        in r24, 0x34 ; 52
  MCUSR = 0;
   a: 14 be        out 0x34, r1 ; 52
  if (ch & (_BV(WDRF) | _BV(BORF) | _BV(PORF)))
   c: 98 2f        mov r25, r24
   e: 9d 70        andi r25, 0x0D ; 13
  10: 09 f0        breq .+2       ; 0x14 <__zero_reg__+0x13>
      appStart(ch);
  12: d7 d0        rcall .+430     ; 0x1c2 <appStart>

#if LED_START_FLASHES > 0
  // Set up Timer 1 for timeout counter
  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
  14: 85 e0        ldi r24, 0x05 ; 5
  16: 80 93 81 00  sts 0x0081, r24
  UCSRA = _BV(U2X); //Double speed mode USART
  UCSRB = _BV(RXEN) | _BV(TXEN);  // enable Rx & Tx
  UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);  // config USART; 8N1
  UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
#else
  UART_SRA = _BV(U2X0); //Double speed mode USART0
  1a: 82 e0        ldi r24, 0x02 ; 2
  1c: 80 93 c0 00  sts 0x00C0, r24
  UART_SRB = _BV(RXEN0) | _BV(TXEN0);
  20: 88 e1        ldi r24, 0x18 ; 24
  22: 80 93 c1 00  sts 0x00C1, r24
  UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
  26: 86 e0        ldi r24, 0x06 ; 6
  28: 80 93 c2 00  sts 0x00C2, r24
  UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
  2c: 80 e1        ldi r24, 0x10 ; 16
  2e: 80 93 c4 00  sts 0x00C4, r24
#endif
#endif

  // Set up watchdog to trigger after 1s
  watchdogConfig(WATCHDOG_1S);
  32: 8e e0        ldi r24, 0x0E ; 14
  34: b1 d0        rcall .+354     ; 0x198 <watchdogConfig>

#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH)
  /* Set LED pin as output */
  LED_DDR |= _BV(LED);
  36: 25 9a        sbi 0x04, 5 ; 4
  38: 86 e0        ldi r24, 0x06 ; 6
}

#if LED_START_FLASHES > 0
void flash_led(uint8_t count) {
  do {
    TCNT1 = -(F_CPU/(1024*16));
  3a: 20 e3        ldi r18, 0x30 ; 48
  3c: 3c ef        ldi r19, 0xFC ; 252
    TIFR1 = _BV(TOV1);
  3e: 91 e0        ldi r25, 0x01 ; 1
}

#if LED_START_FLASHES > 0
void flash_led(uint8_t count) {
  do {
    TCNT1 = -(F_CPU/(1024*16));
  40: 30 93 85 00  sts 0x0085, r19
  44: 20 93 84 00  sts 0x0084, r18
    TIFR1 = _BV(TOV1);
  48: 96 bb        out 0x16, r25 ; 22
    while(!(TIFR1 & _BV(TOV1)));
  4a: b0 9b        sbis 0x16, 0 ; 22
  4c: fe cf        rjmp .-4       ; 0x4a <__SREG__+0xb>
#if defined(__AVR_ATmega8__)  || defined (__AVR_ATmega32__)
    LED_PORT ^= _BV(LED);
#else
    LED_PIN |= _BV(LED);
  4e: 1d 9a        sbi 0x03, 5 ; 3
}
#endif

// Watchdog functions. These are only safe with interrupts turned off.
void watchdogReset() {
  __asm__ __volatile__ (
  50: a8 95        wdr
  52: 81 50        subi r24, 0x01 ; 1
    LED_PORT ^= _BV(LED);
#else
    LED_PIN |= _BV(LED);
#endif
    watchdogReset();
  } while (--count);
  54: a9 f7        brne .-22      ; 0x40 <__SREG__+0x1>
  56: 81 2c        mov r8, r1
  58: 91 2c        mov r9, r1
      * Start the page erase and wait for it to finish.  There
      * used to be code to do this while receiving the data over
      * the serial link, but the performance improvement was slight,
      * and we needed the space back.
      */
     __boot_page_erase_short((uint16_t)(void*)address);
  5a: 13 e0        ldi r17, 0x03 ; 3
      */
     do {
  uint16_t a;
  a = *bufPtr++;
  a |= (*bufPtr++) << 8;
  __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
  5c: 01 e0        ldi r16, 0x01 ; 1
     } while (len -= 2);

     /*
      * Actually Write the buffer to flash (and wait for it to finish.)
      */
     __boot_page_write_short((uint16_t)(void*)address);
  5e: 25 e0        ldi r18, 0x05 ; 5
  60: f2 2e        mov r15, r18
     boot_spm_busy_wait();
#if defined(RWWSRE)
     // Reenable read access to flash
     boot_rww_enable();
  62: 31 e1        ldi r19, 0x11 ; 17
  64: e3 2e        mov r14, r19
#endif

  /* Forever loop: exits by causing WDT reset */
  for (;;) {
    /* get character from UART */
    ch = getch();
  66: 8c d0        rcall .+280     ; 0x180 <getch>

    if(ch == STK_GET_PARAMETER) {
  68: 81 34        cpi r24, 0x41 ; 65
  6a: 79 f4        brne .+30      ; 0x8a <__SREG__+0x4b>
      unsigned char which = getch();
  6c: 89 d0        rcall .+274     ; 0x180 <getch>
      verifySpace();
  6e: 89 83        std Y+1, r24 ; 0x01
  70: 99 d0        rcall .+306     ; 0x1a4 <verifySpace>
      /*
       * Send optiboot version as "SW version"
       * Note that the references to memory are optimized away.
       */
      if (which == 0x82) {
  72: 89 81        ldd r24, Y+1 ; 0x01
  74: 82 38        cpi r24, 0x82 ; 130
  76: 11 f4        brne .+4       ; 0x7c <__SREG__+0x3d>
   putch(optiboot_version & 0xFF);
  78: 82 e0        ldi r24, 0x02 ; 2
  7a: 05 c0        rjmp .+10      ; 0x86 <__SREG__+0x47>
      } else if (which == 0x81) {
  7c: 81 38        cpi r24, 0x81 ; 129
  7e: 11 f4        brne .+4       ; 0x84 <__SREG__+0x45>
   putch(optiboot_version >> 8);
  80: 86 e8        ldi r24, 0x86 ; 134
  82: 01 c0        rjmp .+2       ; 0x86 <__SREG__+0x47>
      } else {
 /*
  * GET PARAMETER returns a generic 0x03 reply for
         * other parameters - enough to keep Avrdude happy
  */
 putch(0x03);
  84: 83 e0        ldi r24, 0x03 ; 3
  86: 75 d0        rcall .+234     ; 0x172 <putch>
  88: 71 c0        rjmp .+226     ; 0x16c <__SREG__+0x12d>
      }
    }
    else if(ch == STK_SET_DEVICE) {
  8a: 82 34        cpi r24, 0x42 ; 66
  8c: 11 f4        brne .+4       ; 0x92 <__SREG__+0x53>
      // SET DEVICE is ignored
      getNch(20);
  8e: 84 e1        ldi r24, 0x14 ; 20
  90: 03 c0        rjmp .+6       ; 0x98 <__SREG__+0x59>
    }
    else if(ch == STK_SET_DEVICE_EXT) {
  92: 85 34        cpi r24, 0x45 ; 69
  94: 19 f4        brne .+6       ; 0x9c <__SREG__+0x5d>
      // SET DEVICE EXT is ignored
      getNch(5);
  96: 85 e0        ldi r24, 0x05 ; 5
  98: 8d d0        rcall .+282     ; 0x1b4 <getNch>
  9a: 68 c0        rjmp .+208     ; 0x16c <__SREG__+0x12d>
    }
    else if(ch == STK_LOAD_ADDRESS) {
  9c: 85 35        cpi r24, 0x55 ; 85
  9e: 49 f4        brne .+18      ; 0xb2 <__SREG__+0x73>
      // LOAD ADDRESS
      uint16_t newAddress;
      newAddress = getch();
  a0: 6f d0        rcall .+222     ; 0x180 <getch>
  a2: d8 2e        mov r13, r24
      newAddress = (newAddress & 0xff) | (getch() << 8);
  a4: 6d d0        rcall .+218     ; 0x180 <getch>
  a6: 8d 2c        mov r8, r13
  a8: 91 2c        mov r9, r1
  aa: 98 2a        or r9, r24
#ifdef RAMPZ
      // Transfer top bit to RAMPZ
      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
#endif
      newAddress += newAddress; // Convert from word address to byte address
  ac: 88 0c        add r8, r8
  ae: 99 1c        adc r9, r9
  b0: 5c c0        rjmp .+184     ; 0x16a <__SREG__+0x12b>
      address = newAddress;
      verifySpace();
    }
    else if(ch == STK_UNIVERSAL) {
  b2: 86 35        cpi r24, 0x56 ; 86
  b4: 21 f4        brne .+8       ; 0xbe <__SREG__+0x7f>
      // UNIVERSAL command is ignored
      getNch(4);
  b6: 84 e0        ldi r24, 0x04 ; 4
  b8: 7d d0        rcall .+250     ; 0x1b4 <getNch>
      putch(0x00);
  ba: 80 e0        ldi r24, 0x00 ; 0
  bc: e4 cf        rjmp .-56      ; 0x86 <__SREG__+0x47>
    }
    /* Write memory, length is big endian and is in bytes */
    else if(ch == STK_PROG_PAGE) {
  be: 84 36        cpi r24, 0x64 ; 100
  c0: 09 f0        breq .+2       ; 0xc4 <__SREG__+0x85>
  c2: 36 c0        rjmp .+108     ; 0x130 <__SREG__+0xf1>
      // PROGRAM PAGE - we support flash programming only, not EEPROM
      uint8_t desttype;
      uint8_t *bufPtr;
      pagelen_t savelength;

      GETLENGTH(length);
  c4: 5d d0        rcall .+186     ; 0x180 <getch>
  c6: 5c d0        rcall .+184     ; 0x180 <getch>
  c8: d8 2e        mov r13, r24
      savelength = length;
      desttype = getch();
  ca: 5a d0        rcall .+180     ; 0x180 <getch>
  cc: c8 2e        mov r12, r24
  ce: a1 2c        mov r10, r1
  d0: bb 24        eor r11, r11
  d2: b3 94        inc r11

      // read a page worth of contents
      bufPtr = buff;
      do *bufPtr++ = getch();
  d4: 55 d0        rcall .+170     ; 0x180 <getch>
  d6: f5 01        movw r30, r10
  d8: 81 93        st Z+, r24
  da: 5f 01        movw r10, r30
      while (--length);
  dc: de 12        cpse r13, r30
  de: fa cf        rjmp .-12      ; 0xd4 <__SREG__+0x95>

      // Read command terminator, start reply
      verifySpace();
  e0: 61 d0        rcall .+194     ; 0x1a4 <verifySpace>
 * void writebuffer(memtype, buffer, address, length)
 */
static inline void writebuffer(int8_t memtype, uint8_t *mybuff,
          uint16_t address, pagelen_t len)
{
    switch (memtype) {
  e2: f5 e4        ldi r31, 0x45 ; 69
  e4: cf 12        cpse r12, r31
  e6: 01 c0        rjmp .+2       ; 0xea <__SREG__+0xab>
  e8: ff cf        rjmp .-2       ; 0xe8 <__SREG__+0xa9>
      * Start the page erase and wait for it to finish.  There
      * used to be code to do this while receiving the data over
      * the serial link, but the performance improvement was slight,
      * and we needed the space back.
      */
     __boot_page_erase_short((uint16_t)(void*)address);
  ea: f4 01        movw r30, r8
  ec: 17 bf        out 0x37, r17 ; 55
  ee: e8 95        spm
     boot_spm_busy_wait();
  f0: 07 b6        in r0, 0x37 ; 55
  f2: 00 fc        sbrc r0, 0
  f4: fd cf        rjmp .-6       ; 0xf0 <__SREG__+0xb1>
  f6: a4 01        movw r20, r8
  f8: a0 e0        ldi r26, 0x00 ; 0
  fa: b1 e0        ldi r27, 0x01 ; 1
     /*
      * Copy data from the buffer into the flash write buffer.
      */
     do {
  uint16_t a;
  a = *bufPtr++;
  fc: 2c 91        ld r18, X
  fe: 12 96        adiw r26, 0x02 ; 2
 100: cd 01        movw r24, r26
 102: 01 97        sbiw r24, 0x01 ; 1
  a |= (*bufPtr++) << 8;
 104: fc 01        movw r30, r24
 106: 80 81        ld r24, Z
 108: 30 e0        ldi r19, 0x00 ; 0
 10a: 38 2b        or r19, r24
  __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
 10c: fa 01        movw r30, r20
 10e: 09 01        movw r0, r18
 110: 07 bf        out 0x37, r16 ; 55
 112: e8 95        spm
 114: 11 24        eor r1, r1
  addrPtr += 2;
 116: 4e 5f        subi r20, 0xFE ; 254
 118: 5f 4f        sbci r21, 0xFF ; 255
     } while (len -= 2);
 11a: da 12        cpse r13, r26
 11c: ef cf        rjmp .-34      ; 0xfc <__SREG__+0xbd>

     /*
      * Actually Write the buffer to flash (and wait for it to finish.)
      */
     __boot_page_write_short((uint16_t)(void*)address);
 11e: f4 01        movw r30, r8
 120: f7 be        out 0x37, r15 ; 55
 122: e8 95        spm
     boot_spm_busy_wait();
 124: 07 b6        in r0, 0x37 ; 55
 126: 00 fc        sbrc r0, 0
 128: fd cf        rjmp .-6       ; 0x124 <__SREG__+0xe5>
#if defined(RWWSRE)
     // Reenable read access to flash
     boot_rww_enable();
 12a: e7 be        out 0x37, r14 ; 55
 12c: e8 95        spm
 12e: 1e c0        rjmp .+60      ; 0x16c <__SREG__+0x12d>
      writebuffer(desttype, buff, address, savelength);


    }
    /* Read memory block mode, length is big endian.  */
    else if(ch == STK_READ_PAGE) {
 130: 84 37        cpi r24, 0x74 ; 116
 132: 71 f4        brne .+28      ; 0x150 <__SREG__+0x111>
      uint8_t desttype;
      GETLENGTH(length);
 134: 25 d0        rcall .+74      ; 0x180 <getch>
 136: 24 d0        rcall .+72      ; 0x180 <getch>
 138: d8 2e        mov r13, r24

      desttype = getch();
 13a: 22 d0        rcall .+68      ; 0x180 <getch>

      verifySpace();
 13c: 33 d0        rcall .+102     ; 0x1a4 <verifySpace>
 13e: 54 01        movw r10, r8
     __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address): "1" (address));
#else
     // read a Flash byte and increment the address
     __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address): "1" (address));
#endif
     putch(ch);
 140: f5 01        movw r30, r10
 142: 85 91        lpm r24, Z+
 144: 5f 01        movw r10, r30
 146: 15 d0        rcall .+42      ; 0x172 <putch>
 } while (--length);
 148: da 94        dec r13
 14a: d1 10        cpse r13, r1
 14c: f9 cf        rjmp .-14      ; 0x140 <__SREG__+0x101>
 14e: 0e c0        rjmp .+28      ; 0x16c <__SREG__+0x12d>

      read_mem(desttype, address, length);
    }

    /* Get device signature bytes  */
    else if(ch == STK_READ_SIGN) {
 150: 85 37        cpi r24, 0x75 ; 117
 152: 39 f4        brne .+14      ; 0x162 <__SREG__+0x123>
      // READ SIGN - return what Avrdude wants to hear
      verifySpace();
 154: 27 d0        rcall .+78      ; 0x1a4 <verifySpace>
      putch(SIGNATURE_0);
 156: 8e e1        ldi r24, 0x1E ; 30
 158: 0c d0        rcall .+24      ; 0x172 <putch>
      putch(SIGNATURE_1);
 15a: 85 e9        ldi r24, 0x95 ; 149
 15c: 0a d0        rcall .+20      ; 0x172 <putch>
      putch(SIGNATURE_2);
 15e: 8f e0        ldi r24, 0x0F ; 15
 160: 92 cf        rjmp .-220     ; 0x86 <__SREG__+0x47>
    }
    else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
 162: 81 35        cpi r24, 0x51 ; 81
 164: 11 f4        brne .+4       ; 0x16a <__SREG__+0x12b>
      // Adaboot no-wait mod
      watchdogConfig(WATCHDOG_16MS);
 166: 88 e0        ldi r24, 0x08 ; 8
 168: 17 d0        rcall .+46      ; 0x198 <watchdogConfig>
      verifySpace();
    }
    else {
      // This covers the response to commands like STK_ENTER_PROGMODE
      verifySpace();
 16a: 1c d0        rcall .+56      ; 0x1a4 <verifySpace>
    }
    putch(STK_OK);
 16c: 80 e1        ldi r24, 0x10 ; 16
 16e: 01 d0        rcall .+2       ; 0x172 <putch>
  }
 170: 7a cf        rjmp .-268     ; 0x66 <__SREG__+0x27>

00000172 <putch>:
}

void putch(char ch) {
#ifndef SOFT_UART
  while (!(UART_SRA & _BV(UDRE0)));
 172: 90 91 c0 00  lds r25, 0x00C0
 176: 95 ff        sbrs r25, 5
 178: fc cf        rjmp .-8       ; 0x172 <putch>
  UART_UDR = ch;
 17a: 80 93 c6 00  sts 0x00C6, r24
 17e: 08 95        ret

00000180 <getch>:
      [uartBit] "I" (UART_RX_BIT)
    :
      "r25"
);
#else
  while(!(UART_SRA & _BV(RXC0)))
 180: 80 91 c0 00  lds r24, 0x00C0
 184: 87 ff        sbrs r24, 7
 186: fc cf        rjmp .-8       ; 0x180 <getch>
    ;
  if (!(UART_SRA & _BV(FE0))) {
 188: 80 91 c0 00  lds r24, 0x00C0
 18c: 84 fd        sbrc r24, 4
 18e: 01 c0        rjmp .+2       ; 0x192 <getch+0x12>
}
#endif

// Watchdog functions. These are only safe with interrupts turned off.
void watchdogReset() {
  __asm__ __volatile__ (
 190: a8 95        wdr
       * don't care that an invalid char is returned...)
       */
    watchdogReset();
  }

  ch = UART_UDR;
 192: 80 91 c6 00  lds r24, 0x00C6
  LED_PIN |= _BV(LED);
#endif
#endif

  return ch;
}
 196: 08 95        ret

00000198 <watchdogConfig>:
    "wdr\n"
  );
}

void watchdogConfig(uint8_t x) {
  WDTCSR = _BV(WDCE) | _BV(WDE);
 198: e0 e6        ldi r30, 0x60 ; 96
 19a: f0 e0        ldi r31, 0x00 ; 0
 19c: 98 e1        ldi r25, 0x18 ; 24
 19e: 90 83        st Z, r25
  WDTCSR = x;
 1a0: 80 83        st Z, r24
 1a2: 08 95        ret

000001a4 <verifySpace>:
  do getch(); while (--count);
  verifySpace();
}

void verifySpace() {
  if (getch() != CRC_EOP) {
 1a4: ed df        rcall .-38      ; 0x180 <getch>
 1a6: 80 32        cpi r24, 0x20 ; 32
 1a8: 19 f0        breq .+6       ; 0x1b0 <verifySpace+0xc>
    watchdogConfig(WATCHDOG_16MS);    // shorten WD timeout
 1aa: 88 e0        ldi r24, 0x08 ; 8
 1ac: f5 df        rcall .-22      ; 0x198 <watchdogConfig>
    while (1)         // and busy-loop so that WD causes
      ;          //  a reset and app start.
 1ae: ff cf        rjmp .-2       ; 0x1ae <verifySpace+0xa>
  }
  putch(STK_INSYNC);
 1b0: 84 e1        ldi r24, 0x14 ; 20
 1b2: df cf        rjmp .-66      ; 0x172 <putch>

000001b4 <getNch>:
    ::[count] "M" (UART_B_VALUE)
  );
}
#endif

void getNch(uint8_t count) {
 1b4: cf 93        push r28
 1b6: c8 2f        mov r28, r24
  do getch(); while (--count);
 1b8: e3 df        rcall .-58      ; 0x180 <getch>
 1ba: c1 50        subi r28, 0x01 ; 1
 1bc: e9 f7        brne .-6       ; 0x1b8 <getNch+0x4>
  verifySpace();
}
 1be: cf 91        pop r28
}
#endif

void getNch(uint8_t count) {
  do getch(); while (--count);
  verifySpace();
 1c0: f1 cf        rjmp .-30      ; 0x1a4 <verifySpace>

000001c2 <appStart>:

void appStart(uint8_t rstFlags) {
  // save the reset flags in the designated register
  //  This can be saved in a main program by putting code in .init0 (which
  //  executes before normal c init code) to save R2 to a global variable.
  __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));
 1c2: 28 2e        mov r2, r24

  watchdogConfig(WATCHDOG_OFF);
 1c4: 80 e0        ldi r24, 0x00 ; 0
 1c6: e8 df        rcall .-48      ; 0x198 <watchdogConfig>
  // Note that appstart_vec is defined so that this works with either
  // real or virtual boot partitions.
  __asm__ __volatile__ (
 1c8: e0 e0        ldi r30, 0x00 ; 0
 1ca: ff 27        eor r31, r31
 1cc: 09 94        ijmp

 

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

Be sure to set the breakpoint BEFORE you start debugging (or after issuing a "break all")

I don't think you can add breakpoints to a running target

 

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

I am setting the breakpoint before I start debugging.  It lets me set it, but when I "start debugging and break", and go to the source window, the solid red circle you get when you set a breakpoint has changed to a hollow red circle.  If I hover the cursor over the circle, I get what you see above - it pops up the warning "The breakpoint will not currently be hit...". 

 

I can normally set breakpoints in source code during runtime, just not with this optiboot build.  But it will let me set breakpoints during runtime on assembly lines - just not in the source code.

 

The issue seems to be that it doesn't have the mapping between the source and symbols and the assembly.  I thought Clawson was onto something, but the objdump of the elf file looks ok to me. 

 

Ugh.  Any other suggestions?

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

A clue!  I just tried running it in the simulator, and I have the same issue.  Don't see source code in the debugger and can't set source breakpoints.  So whatever is going on doesn't seem to be related to the ICE.  This is so bizarre.  Why would it work for Westfw and not me, with the same project.  I'm on AS 7.0.594, Windows 7...

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

 

Perhaps a Studio bug? Maybe to do with the use of -nostartfiles ?

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

You'd think, but Westfw isn't having this problem. Seems like it's something to do with my setup. If it isn't too much trouble, would you mind trying it to see if you have the problem? Westfw linked the project zip back in post number 45.

Last Edited: Sun. Nov 15, 2015 - 03:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I cannot run Studio.

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

No Studio?? Horrors! How can you live?

Ok, I am going to try installing AS7 on a fresh machine and see if it still happens there.

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

Progress!  On a fresh install of AS7 on another computer, I'm able to step through source code in the simulator.  So it's something wrong with the install on my dev't machine.  I'm going to try reinstalling AS7...

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

That did it!  An uninstall/reinstall of AS7 fixed it.  Now I can see and step through the source in the debugger.  Very strange since I was able to debug 2 or 3 other applications I had tried.  I didn't think there could be anything wrong with my install of AS7.

 

So now I could use some help testing this.  My plan is to use avrdude to upload an application, and look at what it sends as a way to verify that my BLE version of avrdude on the smartphone does the same thing.  I will comment out the watchdog timer stuff in the bootloader while debugging, so the AVR just sits in the bootloader waiting for ST500 messages.

 

I'm struggling with how to get avrdude to talk to the bootloader while debugging.  My options for connecting to the pro mini are the Atmel ICE and a Sparkfun FTDI breakout board (https://www.sparkfun.com/products/9716).

 

The Atmel ICE is busy debugging the bootloader, so can't be used to upload applications to test the bootloader - correct?  

 

With the FTDI breakout board, I am able to upload applications to the AVR if AS isn't connected.  But if I connect AS via the ICE, avrdude can no longer talk to the board.  Also, after I disconnect AS, avrdude still can't talk to the board unless I turn off the debugwire fuse (DWEN). 

 

So is there a way to get this to work?  To have avrdude able to upload applications with DWEN enabled?

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

An uninstall/reinstall of AS7 fixed it. 

 Good.  I was starting to wonder whether it might be something like that, but I don't really use AS enough to suggest it.   Did you re-install Visual Micro as well?  That was the only difference between your setup and mine that I noticed (but you weren't using it, so I'm not sure how it would have broken anything.)

 

I'm not sure how avrdude/bootloader will interact with the debugger.   There's a lot of timing-sensitive stuff in there that may or may not allow for the delays associated with debugging.

I'll try to do some experiments...

 

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

I'm back to having problems breaking in the debugger with the Atmel ICE.  It was working earlier, then stopped.

 

When I do a "start debugging and break", it runs optiboot, but doesn't break.  I set a breakpoint on the first line of code, and it doesn't break there.

 

It will break in the simulator, just not in the ICE.

 

So I thought something might be wrong with the ICE, but I can break in other applications, just not optiboot.  I also tried using the squid cable with the ICE, talking to a pro mini on a breadboard, but that doesn't work either.  It works with other applications, just not optiboot.

 

So I thought I had inadvertently messed up the optiboot source, so went back to the original source from post #45 in this thread.  Still no go.

 

I have tried several pro minis, including two fresh from the box.  Still no go.  Did an uninstall/reinstall of AS, rebooted several times, etc.

 

Aaaargh!!  Always one step forward, two steps back.

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

I have tried several pro minis

 You'll have to remove the Arduino auto-reset cap before debugwire will work correctly on a "stock" arduino board.  It might manifest as being "flakey" - debugwire sends commands at moderate data rates over the RESET pin, and the arduinos have a capacitor connected to reset that will interfere with the waveforms.  (I thought I mentioned that earlier.  But it could have been a different thread.)

 

 

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

I did remove the reset CAP from some of these.

 

I just did a lot more testing.  Here's what I found (right now I'm on a Pro mini with no reset CAP).

 

If I try "start debugging and break" using the Atmel ICE, it loads and runs the program, but doesn't break on entering main().  If I have a breakpoint set on the first executable line of code, it doesn't break there either.

 

If I do the same as above but in the simulator, it breaks on my breakpoint, but still doesn't break on main().

 

QUESTION: Why doesn't "start debugging and break" break on startup?  My other applications do.  It's not big deal that it doesn't - I can set a breakpoint manually, but the fact that this isn't working might be a clue to my other issues...

 

So I'm unable to debug on the Atmel ICE with this version of the code.

 

Then I decided to test and see if it mattered that the code wasn't running at 0000, so I made a copy of the "Debug" configuration in the project and modified the copy to remove the linker settings to locate the code at 0x3F00 (-section-start=.text=0x7e00, -section-start=.version=0x7ffe).  I called the modified copy "Debug at 0000".

 

Then if I run "Debug at 0000" in the simulator, it breaks at the start of main(), but doesn't have any symbols.  It just breaks in the disassembly.  So one difference from above is that at least it breaks at main(), unlike the original "Debug" configuration.

 

Then I ran "Debug at 0000" on the ICE, and had the same results as above.  It broke at the start of main(), but no symbols.

 

I did an avr-objdump on the elf file of "Debug at 0000", and it looks fine.

 

Question: Why do I lose symbols when I relocate the code to 0000.

 

So to summarize:

*  The default "Debug" configuration of the optiboot project won't let me debug on the ICE.  Breakpoints are ignored.

*  If I make a copy of the configuration that runs the code at 0000 (which would be fine for my testing), it can debug, but I don't get any source.

 

Any ideas?

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

So any thoughts as to whether or how I can use the ICE to debug the bootloader where it belongs (0x3F00)?

 

I made some progress from yesterday - I can step through the bootloader code, with source, on the ICE, if I set it to run at low addresses above 0.  For example, if I set .text=0x10, I get source, and can debug.  (At 0, it breaks, but without source).

But what I really need to do is to load the bootloader at 0x3F00 and be able to debug with debugwire.  For some reason, the ICE won't let me debug the code there.  Is it because it's in the NRWW section of flash?

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

I've gone ahead and developed/debugged a version of optiboot that supports my Bluetooth modem, by loading the code in the application space.  I still am not able to use the ICE if I load it at 3F00.

 

So now I'm ready to test it.  The first thing I want to verify is that it still works with avrdude.  It doesn't.  I'm testing uploading the "blink" program, using the Arduino IDE. 

 

So I tried just uploading the original optiboot bootloader, from Westfw's zip file above, and the Arduino IDE can't talk to that either.

 

Looks like I'm doing something wrong.

 

I uploaded optiboot by building it in Atmel Studio, and the uploading it through the ICE, using the "Device Programming" screen:

 

Shouldn't that work?

 

Here's the verbose output from the arduino IDE:


C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10601 -DARDUINO_AVR_PRO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\eightanaloginputs C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\Blink.cpp -o C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\Blink.cpp.o 
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\hooks.c.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\WInterrupts.c.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\wiring.c.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\wiring_analog.c.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\wiring_digital.c.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\wiring_pulse.c.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\wiring_shift.c.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\abi.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\CDC.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\HardwareSerial.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\HardwareSerial0.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\HardwareSerial1.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\HardwareSerial2.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\HardwareSerial3.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\HID.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\IPAddress.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\main.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\new.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\Print.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\Stream.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\Tone.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\USBCore.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\WMath.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\WString.cpp.o
Using previously compiled file: C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\core.a
C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avr-gcc -w -Os -Wl,--gc-sections -mmcu=atmega328p -o C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp/Blink.cpp.elf C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp\Blink.cpp.o C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp/core.a -LC:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp -lm 
C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp/Blink.cpp.elf C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp/Blink.cpp.eep 
C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avr-objcopy -O ihex -R .eeprom C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp/Blink.cpp.elf C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp/Blink.cpp.hex 

Sketch uses 1,030 bytes (3%) of program storage space. Maximum is 30,720 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2,039 bytes for local variables. Maximum is 2,048 bytes.
C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avrdude -CC:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:C:\Users\owner\AppData\Local\Temp\build6155813861600170582.tmp/Blink.cpp.hex:i 

avrdude: Version 6.0.1, compiled on Jan 15 2015 at 16:58:43
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf"

         Using Port                    : COM6
         Using Programmer              : arduino
         Overriding Baud Rate          : 57600
avrdude: ser_open(): can't open device "\\.\COM6": Access is denied.



avrdude done.  Thank you.

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xfb
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xfb

avrdude done.  Thank you.

Problem uploading to board.  See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avr-g++ -c -g -Os -w ... -DARDUINO_AVR_PRO -DARDUINO_ARCH_AVR ... Blink.cpp.o 

Sketch uses 1,030 bytes (3%) of program storage space. Maximum is 30,720 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2,039 bytes for local variables. Maximum is 2,048 bytes.
avrdude -CC:\Program Files (x86)\Arduino/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w

Ahh.  You have your "board" set to be "pro mini"; A pro-mini normally uses an older bootloader, NOT optiboot.  Once you've put optiboot on your 328, you should tell arduino-like environments that you have an "Uno."

 

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

Thanks.  That was it.  I had edited the boot.ini file to change the baud rate to 9600, which my BLE modem is using.  But I didn't realize I needed to change the board type.

 

So I've made much progress!  I've isolated my wacky ICE behavior to be something to do with my power source.  I'm using one of these: https://www.pololu.com/product/2842/specs as a voltage source.  I'm feeding it 24v, and it seems to be outputting a clean 5V signal.  But when that's the power source to my Pro Mini, the debugger has the issues I was describing (can only step through the code if it's loaded to certain addresses), and some other issues - such as an inability to read the "device signature" in the "Device Programming" screen in Atmel Studio, which means I can't program the Pro Mini from AS.  But - if I power the same Pro Mini via USB, using this: https://www.sparkfun.com/products/9716, then I can use the ICE to step through the code, and program it via Device Programming in AS.

 

Any ideas what's causing this behavior??

 

Now I'm trying to debug, and am still having issues.  Although the code seems to think it's updating the FLASH, the hex file I'm trying to upload isn't being written there.  Nothing seems to be getting written.  Also, if I try to load the hex file using the Device Programming dialog, I need to check the "Erase device before programming" option.  If I don't, only some of the bytes get written.  It looks like maybe every other byte gets written.  Is that a clue?

 

Sorry to be asking for so much help on this.  You guys must think I'm crazy with all these wacky issues. 

 

Last Edited: Tue. Nov 24, 2015 - 08:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I figured out what's going on.  One of the chips on my board is using the D13 pin, which doubles as the "SCK" pin used by the ISP interface from the ICE.  This seems to be causing my "Device Programming" issue when I'm powering the board via that voltage converter.  I'll do some more testing to see where I'm at.

 

(By the way, Westfw - I don't think I said, but the "Release" configuration in that AS project you uploaded above is missing a few things, such as the start address of optiboot.)

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

the "Release" configuration in that AS project you uploaded above is missing a few things

 I'll take a look.  I wasn't aware that I had to configure the "release" build separately from the "debug" version (aside from, presumably, debug flags.)

 

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

I have my bootloader pretty much working - I'm able to upload firmware via BLE.  For debugging, I commented out the watchdog timer code, so I didn't have to deal with the WDT interrupts happening.

 

Now I'm trying to turn the WDT back on, and am having some issues I could use help with.

 

Basically, the watchdog timer seems to be going on continuously.  I'm not clear on how it's supposed to work.  Once it fires, shouldn't it not fire again?  Or is there something in the code that is supposed to turn it off after it fires once?  I don't see where that is done.

 

Also - where in the code or project does it set the ISR vector for the watchdog timer?  I don't see where that's done.

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

Once it fires, shouldn't it not fire again?

No, you have to explicitly turn it off.  It specifically is NOT turned off by RESET (although IIRC, RESET does set the timeout to the default (small number) instead of whatever it WAS set to.   So you need to turn off the watchdog quite early in initialization.)

 

(This was a common Arduino problem with earlier/different bootloaders that did not use or disable the watchdog.  If a user application turned in on, it would stay on and result in a loop where the chip would never get out of the bootloader code.)

 

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

Ok, thanks.  I didn't knowingly touch that code, so I'm not sure what's going on.  Would you mind pointing me to the section in the Optiboot code where it turns off the WDT?  Seems like it's not working somehow, or not getting called.  And where it sets the ISR vector?

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

It's this code in appStart() (Note that in the case of a watchdog reset, appStart() is called immediately from main()):

 

void appStart(uint8_t rstFlags) {
  // save the reset flags in the designated register
  //  This can be saved in a main program by putting code in .init0 (which
  //  executes before normal c init code) to save R2 to a global variable.
  __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));

  watchdogConfig(WATCHDOG_OFF);
  // Note that appstart_vec is defined so that this works with either
  // real or virtual boot partitions.
  __asm__ __volatile__ (
    // Jump to 'save' or RST vector
    "ldi r30,%[rstvec]\n"
    "clr r31\n"
    "ijmp\n"::[rstvec] "M"(appstart_vec)
  );
}

 

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

I hadn't touched that code.  But I figured out my problem.  When I was having issues with the debugger a while back, I had turned optimization off for the debug build in the project (-O0).  That messed up the watchdogConfig() function.  The extra instructions in there meant that the call to set the timer value wasn't within the requisite 4 cycles.  It might be better if watchdogConfig() was implemented with __asm__() directives, like much of the other timing dependent code.

 

And while I have you - do you know where the __asm__ directive is documented?  Google didn't find it for me.  I'm not clear on the syntax.

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

And a new issue.  My version of optiboot is able to send and receive on the hardware uart (Rx/Tx) lines, but only if I don't start the app.  Once the app starts (which also uses Rx and Tx - through the HardwareSerial class), optiboot doesn't see any input.  So if I start optiboot and stay in the main loop, it receives data fine.  But if it jumps into the app, which receives some data, then jumps back into optiboot - optiboot doesn't see any data.

 

I have verified that optiboot does run when the app jumps back into it. It gets stuck in getch() in the main loop.

 

It's as if the app is doing something to the hardware UART such that optiboot can't talk to it anymore.

 

Any ideas?

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

do you know where the __asm__ directive is documented?

http://www.nongnu.org/avr-libc/u... I'm not sure what the difference between asm() and __asm__(); It may just  be conformance related ("non-standard compiler variables/functions should have underscores"?)

 

 

if it jumps into the app, which receives some data, then jumps back into optiboot - optiboot doesn't see any data.

 This is because jumping into the bootloader is not the same as resetting the chip.  Unless you explicitly unconfigure them, various peripherals will retain whatever configuration they had in the applications, which may or may not be compatible with the bootloader.   In particular, if you're talking about an Arduino sketch, the UART is going to be set up to cause interrupts, and those will still jump off into the application code and modify buffers that are probably not compatible with the bootloader.  And timer0 too.   this is why people use the watchdog to restart the chip; it assures that everything (except the watchdog itself) is returned to the "reset" configuration.  You can manually un-configure peripherals, but stuff you didn't know about can lead you on a merry chase!

 

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

Ah - ok, thanks!  I thought it was something like that, and had looked at the source for HardwareSerial, and didn't see anything that was setting an ISR.  But I just looked further, and now do think I see it, something in this gobbledygook (I think there is way too much conditional compilation in Arduino code, makes it pretty hard to read!):

 

#if defined(HAVE_HWSERIAL0)

#if defined(USART_RX_vect)
  ISR(USART_RX_vect)
#elif defined(USART0_RX_vect)
  ISR(USART0_RX_vect)
#elif defined(USART_RXC_vect)
  ISR(USART_RXC_vect) // ATmega8
#else
  #error "Don't know what the Data Received vector is called for Serial"
#endif
  {
    Serial._rx_complete_irq();
  }

#if defined(UART0_UDRE_vect)
ISR(UART0_UDRE_vect)
#elif defined(UART_UDRE_vect)
ISR(UART_UDRE_vect)
#elif defined(USART0_UDRE_vect)
ISR(USART0_UDRE_vect)
#elif defined(USART_UDRE_vect)
ISR(USART_UDRE_vect)
#else
  #error "Don't know what the Data Register Empty vector is called for Serial"
#endif
{
  Serial._tx_udr_empty_irq();
}

 

So any idea how to handle this?  Generating a hard reset isn't an option for me, at least with my current board design.  Can I generate a reset from software somehow?  A WDT reset clears everything (right?), but optiboot is set up so that the WDT reset causes it to start the app.  I need to do a reset such that when the bootloader start up, it doesn't start the app.

 

Or maybe I should just disable the UART IRQs and hope there are no other "merry chase" issues.  Don't know how to do that either...

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

https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html

https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

The asm keyword is a GNU extension. When writing code that can be compiled with -ansi and the various -std options, use __asm__ instead of asm (see Alternate Keywords).

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I think I finally got it all working.  I ended up triggering a WDT reset from within my app, as the way to enter the bootloader when the app gets a message telling it that a firmware upload is pending.  I use a byte in EEPROM so the bootloader can tell if the WDT reset came from within the app (meaning that bootloader messages are pending), or from within the bootloader itself (meaning that for whatever reason a bootload message sequence got interrupted).  The EEPROM byte also tells the bootloader if there's a fully loaded app, and it will just sit in the bootloader if a partial app download was interrupted.

 

I had another bizarre problem today, for some reason the optimizer in the compiler removed any calls I had to the function eeprom_read_byte().  I had to make a separate copy of eeprom.h and mess with the function prototype in order to get the compiler to compile the call.

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

Just a final update on this - everything is working like a charm!  Thanks again for all the help!!

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

It is a pleasure to help those who keep plugging away at a problem.  Too often, advice seems to disappear (along with the original poster) into a black hole. :-(

 

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

Hi, sorry for opening an old thread, but i think i'm trying to do the same thing!

I have a pro Mini with Optiboot recompiled with a Baud rate of 57600, I switch to Optiboot as i had thought the WDT would cause a full reboot and invoke the boot loader but it seems it doesn't!

 

so how did you get it to call the bootloader using the WDT? 

 

thnaks

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

The bootloader is invoked using the reset line if memory serves me correctly.

 

Here is a good link that explains this:

 

https://github.com/Optiboot/opti...

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Thanks Jim, interesting is :
On reset, Optiboot starts and reads the reset reason from MCUSR. For any cause other than "external reset", the application is started immediately. Otherwise, optiboot attempts to download new application software:

Now to find how to set MCUSR so it thinks it's an external reset!?

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

You can't set MCUSR. Bits therein can only be set by hardware via a reset. You can only clear them.
If you want to trigger Optiboot, either modify the source code to trigger on WDT and rebuild/upload the modified bootloader, or have your app use an I/O pin to pull /RESET low. There are pitfalls with either approach.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Ok thanks