I think I bricked my atmeg328p with a bad bootloader

Hi!

I was trying to run my atmega328p with the internal 128KHz oscillator.

I didn't find any existing bootloaders and/or reference material.
So I tried to make my own booloader following pieces of information that I've found around the web.

I've cloned optiboot repository and added my custom boards to the Makefile.custom as follows:

#
# Makefile for "custom" platforms.   Add your board here.
#
# * Copyright 2013-2015 by Bill Westfield.  Part of Optiboot.
# * This software is licensed under version 2 of the Gnu Public Licence.
# * See optiboot.c for details.

rope_atmega328p_128khz: TARGET = rope_atmega328p_128khz
rope_atmega328p_128khz: MCU_TARGET = atmega328p
rope_atmega328p_128khz: CFLAGS += '-DBAUD_RATE=4000'
rope_atmega328p_128khz: AVR_FREQ ?= 128000L
rope_atmega328p_128khz: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
rope_atmega328p_128khz: rope_atmega328p_128khz.hex
rope_atmega328p_128khz: rope_atmega328p_128khz.lst

rope_atmega328p_128khz_isp: rope_atmega328_128khz
rope_atmega328p_128khz_isp: TARGET = rope_atmega328_128khz
rope_atmega328p_128khz_isp: MCU_TARGET = atmega328p
# 256 word / 512 byte boot, SPIEN
rope_atmega328p_128khz_isp: HFUSE ?= DF
# Internal RC (128 KHz) 6CK/14CK+65ms
rope_atmega328p_128khz_isp: LFUSE ?= E3
# 2.7V BOD
rope_atmega328p_128khz_isp: EFUSE ?= FD
rope_atmega328p_128khz_isp: isp


rope_atmega328p_128khz_clkout: TARGET = rope_atmega328p_128khz_clkout
rope_atmega328p_128khz_clkout: MCU_TARGET = atmega328p
rope_atmega328p_128khz_clkout: CFLAGS += '-DBAUD_RATE=4000'
rope_atmega328p_128khz_clkout: AVR_FREQ ?= 128000L
rope_atmega328p_128khz_clkout: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
rope_atmega328p_128khz_clkout: rope_atmega328p_128khz_clkout.hex
rope_atmega328p_128khz_clkout: rope_atmega328p_128khz_clkout.lst

rope_atmega328p_128khz_clkout_isp: rope_atmega328p_128khz_clkout
rope_atmega328p_128khz_clkout_isp: TARGET = rope_atmega328p_128khz_clkout
rope_atmega328p_128khz_clkout_isp: MCU_TARGET = atmega328p
# 256 word / 512 byte boot, SPIEN
rope_atmega328p_128khz_clkout_isp: HFUSE ?= DF
# Internal RC (128 KHz) 6CK/14CK+65ms
rope_atmega328p_128khz_clkout_isp: LFUSE ?= A3
# 2.7V BOD
rope_atmega328p_128khz_clkout_isp: EFUSE ?= FD
rope_atmega328p_128khz_clkout_isp: isp

Actually, I copied the existing configurations for atmega328p and just changed some settings according to my needs:

The baud rate was calculated using the online calculator. The error rate is 0.0% (should be OK).
http://wormfood.net/avrbaudcalc.php?bitrate=4000&clock=0.128&databits=8

The fuses were calculated using the online fuse calculator: http://www.engbedded.com/fusecalc/
Here are my settings:

I selected the 256 word size setting because each word has two bytes, so 256 words = 512 bytes, the amount required by optiboot.

Both my boards are pretty much the same. The only difference is that one outputs the clock rate for measurement and the other don't.

The hex files were built using the appropriate commands (from optiboot directory with Ubuntu and avr-gcc):

make rope_atmega328p_128khz
make rope_atmega328p_128khz_clkout

Both .hex and .lst files were successfully created on optiboot directory.

Then I've created my "boards.txt" file and directory structure in order to upload the bootloaders using my Arduino IDE. I've used the boards txt editor to be sure that no mistakes were made.

rope_atmega328p_128khz.name=RoPE - ATmega328p @128KHz
rope_atmega328p_128khz.build.mcu=atmega328p
rope_atmega328p_128khz.build.f_cpu=128000L
rope_atmega328p_128khz.build.core=arduino:arduino
rope_atmega328p_128khz.build.variant=arduino:standard
rope_atmega328p_128khz.build.board=ROPE_ATMEGA328P_128KHZ
rope_atmega328p_128khz.upload.tool=arduino:avrdude
rope_atmega328p_128khz.upload.protocol=arduino
rope_atmega328p_128khz.upload.maximum_size=32256
rope_atmega328p_128khz.upload.speed=4000
rope_atmega328p_128khz.upload.maximum_data_size=2048
rope_atmega328p_128khz.bootloader.tool=arduino:avrdude
rope_atmega328p_128khz.bootloader.low_fuses=0xE3
rope_atmega328p_128khz.bootloader.high_fuses=0xDF
rope_atmega328p_128khz.bootloader.extended_fuses=0xFD
rope_atmega328p_128khz.bootloader.file=rope/rope_atmega328p_128khz.hex
rope_atmega328p_128khz.bootloader.unlock_bits=0x3F
rope_atmega328p_128khz.bootloader.lock_bits=0x0F

rope_atmega328p_128khz_clkout.name=RoPE - ATmega328p @128KHz (with clock output)
rope_atmega328p_128khz_clkout.build.mcu=atmega328p
rope_atmega328p_128khz_clkout.build.f_cpu=128000L
rope_atmega328p_128khz_clkout.build.core=arduino:arduino
rope_atmega328p_128khz_clkout.build.variant=arduino:standard
rope_atmega328p_128khz_clkout.build.board=ROPE_ATMEGA328P_128KHZ_CLKOUT
rope_atmega328p_128khz_clkout.upload.tool=arduino:avrdude
rope_atmega328p_128khz_clkout.upload.protocol=arduino
rope_atmega328p_128khz_clkout.upload.maximum_size=32256
rope_atmega328p_128khz_clkout.upload.speed=4000
rope_atmega328p_128khz_clkout.upload.maximum_data_size=2048
rope_atmega328p_128khz_clkout.bootloader.tool=arduino:avrdude
rope_atmega328p_128khz_clkout.bootloader.low_fuses=0xA3
rope_atmega328p_128khz_clkout.bootloader.high_fuses=0xDF
rope_atmega328p_128khz_clkout.bootloader.extended_fuses=0xFD
rope_atmega328p_128khz_clkout.bootloader.file=rope/rope_atmega328p_128khz_clkout.hex
rope_atmega328p_128khz_clkout.bootloader.unlock_bits=0x3F
rope_atmega328p_128khz_clkout.bootloader.lock_bits=0x0F

Again, I copied the existing settings for atmega328p (Arduino Uno) and changed the necessary settings (fuses, cpu clock, baud rate). I also changed upload.maximum_data_size to 32256 instead of the default 30720, because 32768 (atmega328p flash size) - 512 (booloader size) = 32256.

After all this process, I assembled an arduino ISP programmer following instructions here and burned the bootloader to my chip.

Aaaaaannnnndddd here is where things went wrong. :frowning: The Arduino IDE reported the famigerated error:

avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.

Error while burning bootloader.

After that the chip became totally useless. I can't upload Arduino sketches and the worst, can'nt record a new booloader. I tried burning the original atmeg328p bootloader using Arduino IDE, but got the same error.

I tried almost EVERY possible solution on the internet but can't get the chip to work anymore.
So... the main two questions are:

  1. Did I really brick my chip? Can I recover it? How?

  2. THE MOST IMPORTANT: why did my chip brick? What i did wrong to cause such much pain??

The only possible solution I can see is to use the AVRISP MKII to completely erase the chip. But I don't have $$$ and I live in Brazil, it's a little bit tricky to get one of these around here.

I really need to run atmeg328p at 128KHz without using an external oscillator. But I can't brick a thousand chips trying to make it work (I already bricked 2 chips)... :frowning:

Any help will be really appreciated

Thanks!!

1 Like

Just some random thoughts:

  1. If you have ISP programming available, it's really hard to brick the chip. You CAN choose a clock source with fuse settings that doesn't exist in which case you will need to supply the missing clock in order to recover. With the internal RC selected for clock source, that should not happen.

  2. I know that with earlier versions of the IDE, your boards.text setting for upload.speed will have no effect. Don't know if that's still a problem with version 1.8.4.

One thing to do with the IDE is enable verbose output during IDE upload and see what the avrdude command line looks like. There should be a "-b4000" or "-b 4000" argument there if your baud rate setting is working.


Can you read fuses on the problem MCUs from the ISP interface? If so then at least you know there is an active clock. If not then try supplying a clock on the XTAL1 pin or re-connecting the resonator/crystal.

Another test you can do is with a fresh MCU is change only the fuse bits required to switch to RC clock source. Then see if you can still read the fuses. Then disconnect the crystal/resonator and see if it still reads fuses. In this state the original bootloader won't work but the fact you can still read fuses with ISP tells you there is a good clock.

I've only used the Atmel ISP hardware and don't know about the home-brew versions. Is there a chance that with the slow RC clock you need to also slow down some baud rate or delay setting in the ISP firmware?

You need to slow down the SCK period on the ISP. This happens a lot. The default for most programmers is too fast for the internal 128KHz oscillator.

Other ideas:

  • The 128kHz oscillator is "low accuracy", so the uart bitrate may be too far off.
  • The bootloader uses the WDT. You MIGHT be running it so slowly that the WDT expires during the initial LED blinking (which is timer-controlled, so also dependent on clock rate.)

AFAIK you can recover the chip via high voltage programming with any fuses/lock bits combination. Making the HV programmer is quite easy, there are guides on the internet or you can follow ATMega Datasheet - everything needed is there.
As said before the 128kHz oscillator is 128kHz NOMINAL. In reality it is (usualy) a bit slower - like 110kHz or so. Since you are able to program the ATMega via ISP it may be easier skip the bootloader at all and use the ISP only?

As a side note: why do you NEED to use the slow oscillator? If you want low power consumption quick execution of code + sleep while idle may be better option.

smeezekitty:
You need to slow down the SCK period on the ISP. This happens a lot. The default for most programmers is too fast for the internal 128KHz oscillator.

smeezekitty, I changed the baud rate to 4000 and CLOCK to 128000 on the ArduinoISP sketch. This way I could burn the original bootloader on the chip. It`s working like a charm again. However I had to run avrdude in the command line to set the baud rate, because the ArduinoIDE fixed it on 19200.

Thank you very much.

Smajdalf:
As a side note: why do you NEED to use the slow oscillator? If you want low power consumption quick execution of code + sleep while idle may be better option.

Smajdalf, I'm already using the sleep in my project. During 90% of the time, the processor is sleeping. However, during the other 10% of the time it is running at full 16MHz speed. I don't need all this speed because all I have to do is to activate a pair of step motors and turn on some leds for a while.

I made some experiments. I reduced the speed from 16MHz to 1MHz and the consumption droped from 50mA to 0.10mA. This is a huge improvement. So I thought that decreasing the speed to 128KHz I could save even more power.

I don't need to run the Arduino for days or weeks. The main goal of reducing the consumption is that I could use a lower capacity battery. Right now I'm using a 3500mA battery to run my project for about 1 hour. Reducing power maybe I could use a 1000mA or 500mA battery.

Driving motors and powering LEDs? They should eat much much more current than ATMega at any speed. In fact it seems impossible ATMega to draw 50mA even at full speed with all peripherals active at maximum voltage - unless you draw the current from IO pins but this should not change with clock speed. I am quite sure there is something else what does this huge difference - you should get about 1/16 of current with 1/16 of speed.
Maybe you could use timers to move the stepper and keep ATMega in Idle slee). Maybe you can sleep for brief periods between steps. Also you can use prescaler to divide the main clock up to 256 times getting to ~30kHz from the 8MHz RC oscillator.
BTW how you got running the processor at 16MHz? You said you cannot/don't want to use a crystal.