How do I create an empty bootloader?

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

I'm trying to write a simple core to allow you to program a chip (the ATmega1284) using ISP on the Arduino IDE.

 

I've searched on AVR Freaks and found some excellent tutorials on writing bootloaders, but nothing about empty bootloaders.

 

Other cores that allow you to program ATtiny and ATmega chips using ISP allow to program the fuses using the Burn Bootloader command in the Arduino IDE, using fuse definitions in the boards.txt file:

attiny85at1.bootloader.low_fuses=0x62
attiny85at1.bootloader.high_fuses=0xD7
attiny85at1.bootloader.extended_fuses=0xFF
attiny85at1.bootloader.path=empty
attiny85at1.bootloader.file=empty85at1.hex

However, they also provide an empty bootloader file (eg empty85at1.hex), which is not actually empty; the one for the 1MHz ATtiny85 is 942 bytes.

 

My questions:

 

What is this file for, since we are not actually uploading a bootloader?

 

Will I need to create one for the ATmega1284 if I want to be able to use the Burn Bootloader command to burn the fuses? If so, what does it need to contain?

Last Edited: Sun. Apr 24, 2016 - 10:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The tiny85 does not have a proper Bootloader mechanism. Any application that you upload must have the Reset vector kludged. (So that the "boot" code is jumped to first)
.
The mega1284 has a regular BOOTRST fuse and regular lock protected boot areas.
.
Find a ready-built bootloader.hex for your 1284 or build your own. Add the relevant entries to your Boards.txt file. It is important to get the hex location, fuse, lock values correct. Then Burn Bootloader and everything else in the IDE will work fine.
.
If you add a DTR capacitor like on a regular Arduino, your Special1284 board should work just like a regular Uno or Mega2560.

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

Thanks for the reply, but I don't actually want to install a bootloader - I just want to use the Burn Bootloader command to set the fuses. My question is why you need to provide a bootloader hex file in this case.

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

The Burn Bootloader command is designed to make a working Arduino. Or restore an Arduino after you have been fiddling with it.
.
You can program fuses via a regular ISP programmer hardware using regular software e.g. ATMEL-ICE and AS7 or a USBASP and avrdude.
.
If you don't want a Bootloader, don't use "Burn Bootloader"

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

Thank you. So what are these for?

 

https://github.com/SpenceKonde/A...

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

I have no idea. OTOH, you could read all the details in the public Github project and discover for yourself.
.
If you do not want an Arduino and you do not want a Bootloader, you probably do not want this project.
.
You can upload any Arduino sketch via ISP. In the process, you destroy an existing Bootloader.
ISP is more convenient for a little Tiny than adding a software UART and a USB-UART dongle.
With a big Mega1284 it is easier to use a Bootloader.
.
If you want to destroy a bootloader, clear the BOOTRST fuse and lockbits. After all, if you want to shoot your foot, you might just as well do the job properly.
.
David.

Last Edited: Sun. Apr 24, 2016 - 12:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

why you need to provide a bootloader hex file in this case.

 The Arduino IDE uses avrdude to do all the actual programming and bootloader burning.  So when you use the "burn bootloader" command, it takes the parameters from the boards.txt, builds an avrdude command using some simple string replacement, and runs that in a separate fork.  The code isn't (or at least wasn't) flexible enough to handle a null .hex file name, and would put together an invalid avrdude command...

 

I don't know what the empty*.hex files don't actually seem to be empty :-(

 

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

Thank you - it's getting clearer!

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

There's only one file at the link you posted, although it was recently updated (today?), and I recall there being several separate hex files there before.

 

That one file is empty_all.hex:

:0200000002C03C
:00000001FF

That amounts to:

$ avr-objdump -D -m avr empty_all.hex 

empty_all.hex:     file format ihex


Disassembly of section .sec1:

00000000 <.sec1>:
   0:   02 c0           rjmp    .+4             ;  0x6

Which is curious.  Looks like SpenceKonde got it wrong somehow.  Should likely say rjmp .-2

"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

It really does not matter what is in an empty hex file.   This is completely empty:

:00000001FF

The accompanying fuses should disable any Bootlloader if you intend to use ISP to upload your sketches.

And the first sketch that you upload will overwrite your "empty" hex anyway.

 

You should sit down and think about what you actually want to do.

1.  if you have a permanent USB-UART link as on a real Arduino,   a Bootloader is very convenient.

2.  if you do not have a permanent USB-UART,   ISP is a practical alternative (if you have a programmer)

3.  if you want to use AS7 for JTAG debugging,   it is easier to scrap the Bootloader during development.

 

David.

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

What I want to do is use the Arduino IDE to upload a program to the ATmega1284 using ISP, and program the fuses.  

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

johnsondavies wrote:

Thank you. So what are these for?

 

https://github.com/SpenceKonde/A...

I think that's an April Fool's joke! Did you actually look at what's in the hex file?...

:0200000002C03C
:00000001FF

The only data in that is:

:02 0000 00 02C0 3C

That is a 2 byte record at address 0x0000 to hold 0xC002. That is:

here: rjmp here

But as the address is 0x0000 then this seems entirely pointless!

 

EDIT: more coffee needed here - Joey made the same point in #9 - blush

What I want to do is use the Arduino IDE to upload a program to the ATmega1284 using ISP, and program the fuses.  

If you want fuses programmed you must mean using ISP not a bootloader. So are you asking how you can only program the fuses and not affect the flash of an "empty" 1284? Well an "empty" AVR has 0xFF in every location of the flash so I guess you could just construct a hex file that just programs one or more 0xFF into the first byte(s) of an AVR. Such as:

$ cat empty.S
.byte 0xFF, 0xFF
$ avr-gcc -mmcu=atmega1284p -nostartfiles empty.S -o empty.elf
$ avr-objcopy -O ihex -j .text empty.elf empty.hex
$ cat empty.hex
:02000000FFFF00
:00000001FF

That really is a "do nothing" .hex file (more so than their one with the RJMP) as this will have no effect whatsoever on the contents of a truly "empty" AVR.

Last Edited: Wed. Apr 27, 2016 - 11:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

The Arduino Burn Bootloader command fails with the error message "Error while burning bootloader" if you specify a bootloader file containing just:

:00000001FF

but it works (and sets the fuses correctly) if you specify Spence Konde's empty_all.hex containing:

:0200000002C03C
:00000001FF

Note that you have to set the lock and unlock bits as:

atmega1284.bootloader.unlock_bits=0x3F
atmega1284.bootloader.lock_bits=0x3F

because the top two unused bits read back as zero and cause a verify mismatch if you specify them as 0xFF.

 

As far as I'm concerned - problem solved! Thanks for all your suggestions.

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

But that empty_all.hex is NOT empty. It contains a recursive RJMP. Did you try my truly empty hex file I generated above...

:02000000FFFF00
:00000001FF

That is "empty" in the sense that all it does is program 0xFFs on top of what are already bound to be 0xFFs anyway.

 

I suppose, at the end of the day none of this really matter because an AVR with all 0xFFs is just as useless as one with "here: rjmp here". To be of any use the user is going to want to program something "on top" in either case.

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

Yes, that file works too:

:02000000FFFF00
:00000001FF

Thanks!

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

I am intrigued. All this effort just to destroy a bootloader and clear any lockbits.
.
Why would anyone want to use ISP when you could use a bootloader. It is not as if the mega1284 is short of Flash memory.
.
I suppose that it does turn the operation into a one-click and go. But it does rely on the punter being able to connect an ISP programmer correctly. And connect it correctly every time you upload a sketch.
.
Buying a regular Uno or Mega2560 clone seems cheaper and more foolproof.
.
David.

Edit. I can't believe that avrdude objects to an empty HEX record. I will try it for myself.

Last Edited: Wed. Apr 27, 2016 - 03:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
The tiny85 does not have a proper Bootloader mechanism. Any application that you upload must have the Reset vector kludged. (So that the "boot" code is jumped to first)

So how is this done with Atmel Studio 7.0? I have not found any flag for the linker to set the reset vector to jump to a bootloader in upper memory. FAQs tell you how to move code, but not reset to it.

"If you find yourself in an even battle, you didn't plan very well."
www.gameactive.org

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

It's not a flag in Studio. It's something your program must do. Have a read of this which explains the concept...

 

http://jtxp.org/tech/tinysafeboo...

 

(one might then ask - why not just use that bootloader anyway?)

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

Found the linker option.

  -e __ctors_end

will set the reset vector to jump as needed to the start of code (after the vector table).

I used .text=0x0c00 to move all the code up to the far end of Flash, but didn't know how to get there from reset.

The -e (entry) linker option was what I was looking for.

Thanks  for the comment though.

This is an I2C bootloader on a ATtiny85 under Atmel Studio 7.0, I'm basically porting over old AVR112 code to Studio 7.0

 

"If you find yourself in an even battle, you didn't plan very well."
www.gameactive.org

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

Your -e is not going to work. Here's an example...

$ avr-gcc -g -mmcu=attiny85 avr.c -o avr.elf -e 0x123
$ avr-objdump -S avr.elf

avr.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0:	0e c0       	rjmp	.+28     	; 0x1e <__ctors_end>
   2:	15 c0       	rjmp	.+42     	; 0x2e <__bad_interrupt>
   4:	14 c0       	rjmp	.+40     	; 0x2e <__bad_interrupt>
   6:	13 c0       	rjmp	.+38     	; 0x2e <__bad_interrupt>
   8:	12 c0       	rjmp	.+36     	; 0x2e <__bad_interrupt>
   a:	11 c0       	rjmp	.+34     	; 0x2e <__bad_interrupt>
   c:	10 c0       	rjmp	.+32     	; 0x2e <__bad_interrupt>
   e:	0f c0       	rjmp	.+30     	; 0x2e <__bad_interrupt>
  10:	0e c0       	rjmp	.+28     	; 0x2e <__bad_interrupt>
  12:	0d c0       	rjmp	.+26     	; 0x2e <__bad_interrupt>
  14:	0c c0       	rjmp	.+24     	; 0x2e <__bad_interrupt>
  16:	0b c0       	rjmp	.+22     	; 0x2e <__bad_interrupt>
  18:	0a c0       	rjmp	.+20     	; 0x2e <__bad_interrupt>
  1a:	09 c0       	rjmp	.+18     	; 0x2e <__bad_interrupt>
  1c:	08 c0       	rjmp	.+16     	; 0x2e <__bad_interrupt>

0000001e <__ctors_end>:
  1e:	11 24       	eor	r1, r1

The -e had not effect the reset jump is always fixed in the CRT....

 

http://svn.savannah.gnu.org/view...

 

Note this...

50 	        .section .vectors,"ax",@progbits
51 	        .global __vectors
52 	        .func   __vectors
53 	__vectors:
54 	        XJMP    __init
55 	        vector  __vector_1
56 	        vector  __vector_2
...

The XJMP there has a fixed target...

200 	        .section .init0,"ax",@progbits
201 	        .weak   __init
202 	;       .func   __init
203 	__init:
204 	
205 	#ifndef __AVR_ASM_ONLY__
206 	        .weak   __stack
207 	
208 	        /* By default, malloc() uses the current value of the stack pointer
209 	           minus __malloc_margin as the highest available address.
210 	
211 	           In some applications with external SRAM, the stack can be below
212 	           the data section (in the internal SRAM - faster), and __heap_end
213 	           should be set to the highest address available for malloc().  */
214 	        .weak   __heap_end
215 	        .set    __heap_end, 0
216 	
217 	        .section .init2,"ax",@progbits
218 	        clr     __zero_reg__
219 	        out     AVR_STATUS_ADDR, __zero_reg__
220 	        ldi     r28,lo8(__stack)

The __init: entry there has various synonymous names to the linker and one of them also happens to be __ctors_end:

 

As I say you are not going to achieve anything with a -e as this GCC is for AVR not for ARM/x86 where there really is a concept of "entry point". What you need to do is program the app code into place with SPM and then, when you are finished (or while you are doing it) you SPM a replaced RJMP at location 0 which is the entry point for the bootloader.

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

Yup. You're right. Fooled myself because the code just ran up through the FF's (nop) until it got the the code at 0x1800. But, I know now what to put at FLASH 0x0000 to get the the loader.

Any time the loader runs, the first thing it does is write 16 CC to FLASH 0x0000. Verified this by an edit to the FLASH using the Simulator and Debug.

prog 0x0000  16 cc ff ff ff

and then using Go to Disassembly, scrolling back to 0000 finds

00000000  RJMP PC-0x03E9        Relative jump
00000001  NOP         Undefined
00000002  NOP         Undefined

Use Set Next Statement to position the PC at 00000000, then Step Into lands me at

  00000C16  RJMP PC+0x017A        Relative jump
>00000C17  CLR R1        Clear Register
  00000C18  OUT 0x3F,R1        Out to I/O location
  00000C19  LDI R28,0x5F        Load immediate

right at the end of the jump table where the normal reset vector goes to with its

00000C00  RJMP PC+0x0017        Relative jump

 

Plan to test it by reading back the FLASH after programming it.

 

 

"If you find yourself in an even battle, you didn't plan very well."
www.gameactive.org