[Home] [Downloads] [Search] [Help/forum]

Gammon Software Solutions forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  Electronics
. -> [Folder]  Microprocessors
. . -> [Subject]  Atmega bootloader programmer
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

Atmega bootloader programmer

Postings by administrators only.

[Refresh] Refresh page


Posted by Nick Gammon   Australia  (19,497 posts)  [Biography] bio   Forum Administrator
Date Sun 06 May 2012 09:52 PM (UTC)  quote  ]

Amended on Mon 23 Dec 2013 09:06 PM (UTC) by Nick Gammon

Message
This sketch was inspired by the Optiloader sketch written for the Arduino. However it is a total rewrite, in order to accomodate the Mega2560 board, which the original one did not handle, due to the larger address space.


Code


http://gammon.com.au/Arduino/Atmega_Board_Programmer.zip

Download the above file, unzip it, and place the resulting folder into your Arduino "sketches" folder.

If you try to compile under older versions of the Arduino IDE, which do not support the F macro, you will get errors. You can get a copy of that here:

http://arduiniana.org/libraries/flash/

You can also get the code from GitHub (this will also show recent changes):

https://github.com/nickgammon/arduino_sketches

Programming cable


For boards which have an ICSP header, it helps to make up a programming cable (although not essential). You can do this by getting a 6-pin IDC cable, and cutting the 5th wire out of circuit and soldering a pin onto it, like this:



This wire (the reset signal) gets plugged into D10 on the Arduino with the programming sketch on it, as in the images below.

If you don't have such a cable, just connect together the pins as described below.

Programming a board


Upload above sketch to the "programming" Uno. Connect programming cable as shown.

Wiring for Uno and similar




(Ruggeduino depicted with programming cable)



(Uno depicted with "manual" programming cable)


Arduino Uno      Target Uno

D10 (SS)            Reset
D11 (MOSI)          D11
D12 (MISO)          D12
D13 (SCK)           D13

Gnd                 Gnd
+5V                 +5V


Example output for Uno



Atmega chip programmer.
Written by Nick Gammon.
Entered programming mode OK.
Signature = 0x1E 0x95 0x0F 
Processor = ATmega328P
Flash memory size = 32768 bytes.
LFuse = 0xFF 
HFuse = 0xDE 
EFuse = 0xFD 
Lock byte = 0xCF 
Bootloader address = 0x7E00
Bootloader length = 512 bytes.
Type 'G' to program the chip with the bootloader ...


Once you see the above, type "G" into the serial monitor to commence programming ...


Erasing chip ...
Writing bootloader ...
Committing page starting at 0x7E00
Committing page starting at 0x7E80
Committing page starting at 0x7F00
Committing page starting at 0x7F80
Written.
Verifying ...
No errors found.
Writing fuses ...
LFuse = 0xFF 
HFuse = 0xDE 
EFuse = 0xFD 
Lock byte = 0xCF 
Done.
Type 'C' when ready to continue with another chip ...


This takes one second.

[EDIT] The more recent versions of the sketch ask this question:


Type 'L' to use Lilypad (8 MHz) loader, or 'U' for Uno (16 MHz) loader ...


Type "U" if you are using a Uno (or any board running at 16 MHz) or "L" if you are using an 8 MHz board.

[EDIT] (23 December 2013) Sketch version 1.21 onwards automatically clears the "divide clock by 8" fuse bit before programming.

Wiring for Mega2560 and similar





Arduino Uno      Target Mega2560

D10 (SS)            Reset
D11 (MOSI)          D51
D12 (MISO)          D50
D13 (SCK)           D52

Gnd                 Gnd
+5V                 +5V


Example output for Mega2560



Atmega chip programmer.
Written by Nick Gammon.
Entered programming mode OK.
Signature = 0x1E 0x98 0x01 
Processor = ATmega2560
Flash memory size = 262144 bytes.
LFuse = 0xFF 
HFuse = 0xD8 
EFuse = 0xFD 
Lock byte = 0xCF 
Bootloader address = 0x3E000
Bootloader length = 8192 bytes.
Type 'G' to program the chip with the bootloader ...


Once you see the above, type "G" into the serial monitor to commence programming ...


Erasing chip ...
Writing bootloader ...
Committing page starting at 0x3E000
Committing page starting at 0x3E100
Committing page starting at 0x3E200
Committing page starting at 0x3E300
Committing page starting at 0x3E400
Committing page starting at 0x3E500
Committing page starting at 0x3E600
Committing page starting at 0x3E700
Committing page starting at 0x3E800
Committing page starting at 0x3E900
Committing page starting at 0x3EA00
Committing page starting at 0x3EB00
Committing page starting at 0x3EC00
Committing page starting at 0x3ED00
Committing page starting at 0x3EE00
Committing page starting at 0x3EF00
Committing page starting at 0x3F000
Committing page starting at 0x3F100
Committing page starting at 0x3F200
Committing page starting at 0x3F300
Committing page starting at 0x3F400
Committing page starting at 0x3F500
Committing page starting at 0x3F600
Committing page starting at 0x3F700
Committing page starting at 0x3F800
Committing page starting at 0x3F900
Committing page starting at 0x3FA00
Committing page starting at 0x3FB00
Committing page starting at 0x3FC00
Committing page starting at 0x3FD00
Committing page starting at 0x3FE00
Committing page starting at 0x3FF00
Written.
Verifying ...
No errors found.
Writing fuses ...
LFuse = 0xFF 
HFuse = 0xD8 
EFuse = 0xFD 
Lock byte = 0xCF 
Done.
Type 'C' when ready to continue with another chip ...


This takes three seconds.

Programming a "bare bones" board





Atmega chip programmer.
Written by Nick Gammon.
Entered programming mode OK.
Signature = 0x1E 0x95 0x0F 
Processor = ATmega328P
Flash memory size = 32768 bytes.
LFuse = 0xFF 
HFuse = 0xDA 
EFuse = 0xFC 
Lock byte = 0xFF 
Bootloader address = 0x7E00
Bootloader length = 512 bytes.
Type 'G' to program the chip with the bootloader ...
Erasing chip ...
Writing bootloader ...
Committing page starting at 0x7E00
Committing page starting at 0x7E80
Committing page starting at 0x7F00
Committing page starting at 0x7F80
Written.
Verifying ...
No errors found.
Writing fuses ...
LFuse = 0xFF 
HFuse = 0xDE 
EFuse = 0xFD 
Lock byte = 0xCF 
Done.
Type 'C' when ready to continue with another chip ...


Note that the fuses were changed after the board was programmed.

Programming a RBB (really bare bones board)





Atmega chip programmer.
Written by Nick Gammon.
Entered programming mode OK.
Signature = 0x1E 0x95 0x0F 
Processor = ATmega328P
Flash memory size = 32768 bytes.
LFuse = 0xFF 
HFuse = 0xDA 
EFuse = 0xFD 
Lock byte = 0xCF 
Bootloader address = 0x7E00
Bootloader length = 512 bytes.
Type 'G' to program the chip with the bootloader ...
Erasing chip ...
Writing bootloader ...
Committing page starting at 0x7E00
Committing page starting at 0x7E80
Committing page starting at 0x7F00
Committing page starting at 0x7F80
Written.
Verifying ...
No errors found.
Writing fuses ...
LFuse = 0xFF 
HFuse = 0xDE 
EFuse = 0xFD 
Lock byte = 0xCF 
Done.
Type 'C' when ready to continue with another chip ...



Adding other bootloaders


In order to convert the .hex bootloader files on disk for use with this sketch I ran this Lua script:


-- Do MD5 sumcheck of Arduino bootloader .hex file
-- Nick Gammon
-- 5 May 2012

require "getlines"

loader = nil
adder = 0

-- given a start address, deduce where the bootloader ends
end_addresses = {
  [0x1C00] = 0x2000,
  [0x1D00] = 0x2000,
  [0x1E00] = 0x2000,
  [0x3800] = 0x4000,
  [0x3E00] = 0x4000,
  [0x7000] = 0x8000,
  [0x7800] = 0x8000,
  [0x7E00] = 0x8000,
  [0xF800] = 0x10000,
  [0x1F000] = 0x20000,
  [0x1FC00] = 0x20000,
  [0x3E000] = 0x40000,
  }

function process (size, address, rectype, data)

  size = tonumber (size, 16)
  address = tonumber (address, 16) + adder
  rectype = tonumber (rectype)
  local binarydata = utils.fromhex (data)

  if rectype == 2 then  -- Extended Segment Address Record
    adder = tonumber (data, 16) * 16  -- high order address byte    
  elseif rectype == 0 then -- data record
    if loader == nil then
      start_address = address
      end_address = end_addresses [address]
      if end_address == nil then
        ColourNote ("red", "", "Don't know end address for " .. bit.tostring (address, 16))
        ColourNote ("red", "", "Please add to table: end_addresses")
        error "Cannot continue"
      end -- if end address not found

      -- work out loader length
      length = end_address - address
      -- pre-fill with 0xFF in case not every byte supplied
      loader = string.rep ("\255", length)
      print (string.format ("// Loader start: %X, length: %i", address, length))
    end -- no loader yet

    -- insert data over where the 0xFF was
    if address >= start_address and (address + size) <= end_address then
      loader = loader:sub (1, address - start_address) .. 
               binarydata .. 
               loader:sub (address - start_address + size + 1, length)
    else
      ColourNote ("red", "", "Address " .. bit.tostring (address, 16) .. " out of expected range.")
    end  -- if in range
  end -- if

end -- function process

print (string.rep ("-", 60))

-- get bootloader file
filename = utils.filepicker ("Choose a bootloader", nil, "hex", { hex = "Hex files" })

-- none chosen, give up
if not filename then return end

-- show file
local fn = string.match (filename, "\\([^\\]+)$")
print ("// File = ", fn)

-- process each line
for line in io.lines (filename) do
  size, address, rectype, data = string.match (line, "^:(%x%x)(%x%x%x%x)(%x%x)(%x+)%s*$")
  if size then 
    process (size, address, rectype, data:sub (1, -3))
  else
    ColourNote ("red", "", "Discarded line: " .. line)
  end -- if
end -- for loop

--print (utils.tohex (loader))

-- sumcheck it
Tell ("// MD5 sum = ")
md5sum = utils.tohex (utils.md5 (loader))
print ((string.gsub (md5sum, "(%x%x)", "%1 ")))

print ""

--     show bootloader in hex

-- convert into C array
print (string.format ("byte PROGMEM %s [] = {",
       string.gsub (fn, "[^%a%d]", "_")))
for i = 1, #loader do
  Tell (string.format ("0x%02X, ", loader:sub (i, i):byte ()))
  if (i - 1) % 16 == 15 then print "" end
end -- of for each byte
print (string.format ("}; // end of %s", string.gsub (fn, "[^%a%d]", "_")))


Because it uses a few special features (like a file picker, MD5 sum calculator etc.) you need to run this from within MUSHclient ... a MUD game client available for free download from this site.

Just download MUSHclient (see the downloads page) and install. Then make a "dummy" world file (File menu -> New World) and type in "Arduino" as the world name and "0.0.0.0" as the TCP/IP address, as shown:



Close the world configuration, and then type Ctrl+I to open the Immediate programming window (Game menu -> Immediate) and paste the above script into it, then hit Run, as shown:



A file-picker will open, you can navigate to the bootloader .hex file that you want to process, and then (all being well) the appropriate hex codes will be shown in the main window. Close the Immediate window, and then just copy and paste into your bootloader sketch (make a separate xxxx.h tab like I did for the other bootloaders).

You will then need to fill in the appropriate figures into the signatures table, such as the bootloader start address, size, programming page size (see the datasheet) and the correct fuse and lock bits. The fuse bytes will probably be the ones mentioned in the boards.txt file in the Arduino environment, for the chip in question.


Checking what bootloader is installed


The thread below describes a sketch that does a MD5 sumcheck of your bootloader, so you can see what bootloader you have installed:

http://www.gammon.com.au/forum/?id=11633


Alternate clock source


As an alternative to a crystal or resonator, the sketch also outputs an 8 MHz clock on pin D9 of the programming board (using Timer 1). Thus you just need to connect D9 on the programming board to XTAL1 of the target board and this will provide a clock signal, enabling this sketch to run.

Atmega1280


Updated on 9 September 2013 to use the Optiboot loader for the Atmega1280. This is smaller and avoids certain issues like the inability to upload a sketch with "!!!" in it.

However please note that if you burn a bootloader for the 1280 chip you need to add this to the end of the boards.txt in the Arduino distribution folder:


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

megao.name=Arduino Mega1280 Optiboot
megao.upload.protocol=arduino
megao.upload.maximum_size=130048
megao.upload.speed=115200
megao.bootloader.low_fuses=0xff
megao.bootloader.high_fuses=0xdc
megao.bootloader.extended_fuses=0xf5
megao.bootloader.path=optiboot
megao.bootloader.file=optiboot_atmega1280.hex
megao.bootloader.unlock_bits=0x3F
megao.bootloader.lock_bits=0x0F
megao.build.mcu=atmega1280
megao.build.f_cpu=16000000L
megao.build.core=arduino
megao.build.variant=mega


In my case the file was in:


/Applications/Arduino_1.0.5.app/Contents/Resources/Java/hardware/arduino/boards.txt


However you would need to find where it is in your distribution.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (19,497 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Mon 28 Oct 2013 11:50 PM (UTC)  quote  ]
Message
Using a Mega2560 as the programmer


The sketch above will also run on a Mega2560 board. However since it uses hardware SPI the wiring will be different.

Programming with custom cable


Simplest is to use the custom cable described above.



As for the Uno, you just connect the SPI headers together, except that pin 10 on the "programming" board is connected to Reset on the target board.

Programming a Uno with a Mega2560





Mega2560      Target Arduino Uno    
                 
  D10         Reset      
  D51         D11 (MOSI)     
  D50         D12 (MISO)     
  D52         D13 (SCK)      
                 
  Gnd         Gnd            
  +5V         +5V            


Programming a breadboard Atmega328P


See this link for making a breadboard Atmega328P:

http://www.gammon.com.au/forum/?id=11637

You can program your breadboard "Arduino" with the following wiring, using a Mega2560:




Mega2560      Target Atmega328P   
                 
  D10         Pin  1 (Reset)      
  D51         Pin 17 (MOSI)     
  D50         Pin 18 (MISO)     
  D52         Pin 19 (SCK)      
                 
  Gnd         Gnd            
  +5V         +5V   

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


46,462 views.

Postings by administrators only.

[Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

[Home]

Written by Nick Gammon - 5K

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( http://www.gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Web site powered by FutureQuest.Net]