ATMega328P-PU with Arduino as programmer + NRF24L01

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

Hi,

I'm sure this question has been answered somewhere before, but I am getting really confused googling around for my answer so I thought I'd ask the experts directly.

I have an Arduino UNO, and an ATMega328P-PU. I want to be able to load regular avr programs onto the ATMega using only the Arduino (I have a usbasp programmer on order but that will take 3 weeks to get here), but I'm confused as to whether I need a bootloader or is that for a different purpose?

I've tried this tutorial (on a completely fresh ATMega328P-PU) for using the Arduino as an ISP: http://hackaday.com/2010/10/25/a... and used the wiring on this page http://arduino.cc/en/Tutorial/Ar... (the bottom left one with no capacitors) but I get a "Yikes! Invalid device signature." from avrdude.

Do I need different wiring? Do I need a bootloader here? Do I need to change the command I send to avrdude (I changed the m168 to m328p)?

My goal is to start learning more about avrs since I am doing my thesis this year and will be working on a telemetry system for a UAV with an XMega and XBees + Processing. I want to be able to firstly put a program on the ATMega328P-PU I have, then when I'm comfortable with that I'll connect one of the two NRF24L01s RF modules I have to it, and another to my Arduino to simulate my telemetry setup sending data back and forth wirelessly(I start my thesis in a month).

Any guidance for setting up my ATMega or anything else in my post would be greatly appreciated.

Thanks,
Rik.

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

The Arduino ISP tutorials are excellent. Just obey the instructions meticulously.

Yes, the ArduinoISP sketch will program all megas and all Tinys (except for t4/5/9/10/20/40).

Note that the Arduino runs at 5V. You must be careful with programming a 3V target. (you need level-shifters)

Also the target AVR must have a clock. All non-USB AVRs come out of the factory with an internal 1MHz clock.

David.

p.s. when you start using the NRF24L01 you need to use 3.3V for its VCC.

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

david.prentice wrote:
The Arduino ISP tutorials are excellent. Just obey the instructions meticulously.

Yes, the ArduinoISP sketch will program all megas and all Tinys (except for t4/5/9/10/20/40).

Note that the Arduino runs at 5V. You must be careful with programming a 3V target. (you need level-shifters)

Also the target AVR must have a clock. All non-USB AVRs come out of the factory with an internal 1MHz clock.

David.

p.s. when you start using the NRF24L01 you need to use 3.3V for its VCC.

Oh.. I used the hackaday tutorial and just used the http://arduino.cc/en/Tutorial/Ar... for the wiring diagram at the bottom left (ie only wires, no crystal, resistor, or capacitors). The one on the arduino.cc website seems to be for burning a bootloader, is that what I should do?

Also, I was using the 5V output from the Arduino for the ATMega as it shows in the wiring diagram, but you're saying to use 3V? I hope I didn't ruin it.

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

I think the problem may have been not including a 10uF capacitor across RESET and GND on the Uno. I will try this when I reach home. I think if I follow the hackaday tutorial with the circuit from arduino.cc(bottom left, no crystal), that should work right?

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

Burning a bootloader, or burning any other hex program, is the same process.

The capacitor shouldn't be needed.

I've used am Arduino Unos as a "recovery" ISP when my normal ISP died a while back, and just following the tutorial on the Arduino.cc site works (without the capacitor) assuming a few things:

- you have a clock for the target
- the programming frequency is not too fast for the clock on the target
- you are powering the target

I used avrdude from the command line to actually program, after uploading the ArduinoISP sketch through the Arduino IDE.

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

jwatte wrote:
Burning a bootloader, or burning any other hex program, is the same process.

The capacitor shouldn't be needed.

I've used am Arduino Unos as a "recovery" ISP when my normal ISP died a while back, and just following the tutorial on the Arduino.cc site works (without the capacitor) assuming a few things:

- you have a clock for the target
- the programming frequency is not too fast for the clock on the target
- you are powering the target

I used avrdude from the command line to actually program, after uploading the ArduinoISP sketch through the Arduino IDE.

By clock, do you mean the crystal? I don't have one of those.

I've googled around and people seem to say that a capacitor is required to disable auto reset for ISP with the Arduino.

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

Also, and this may be a stupid question, but what exactly is a bootloader for? Is it so you can store multiple programs, and so that the AVR can independently pick and run these programs?

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

Well, that is not a stupid question at all and I hope my answer is not too stupid (else, if there is a better one, ill delete it):
a bootloader (for avrs) eats other programs which are stored on a PC and executes them /it; as the avr has no menu system, only one program (different from the bootloader) can reside in the AVR -else, that would be too complicated for the user, trying to remember different combinations of switches).
*You* have to choose the program (which else would remain lonely and idle in your PC) to give the AVR....

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

dbrion0606 wrote:
Well, that is not a stupid question at all and I hope my answer is not too stupid (else, if there is a better one, ill delete it):
a bootloader (for avrs) eats other programs which are stored on a PC and executes them /it; as the avr has no menu system, only one program (different from the bootloader) can reside in the AVR -else, that would be too complicated for the user, trying to remember different combinations of switches).
*You* have to choose the program (which else would remain lonely and idle in your PC) to give the AVR....
I'm not sure I understand. Are you saying that it has to be connected to a PC at all times, and the PC sends the program which the AVR then runs?

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

No : it must be connected to the PC each time you want a new program; then, there are special switches (say, for a given card) which allow the program to be executed or the bootloader to eat from the PC; if your card is not connected to the PC, your program should start automatically but the bootloader remains...

Edited (I read David Prentice) : if the bootloader remains, it eats flash (and therefore avoiding it is better : I hope I did not misinterpret).

Last Edited: Thu. Feb 7, 2013 - 01:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The Arduino ISP tutorials are excellent. Just obey the instructions meticulously.

Do not take any notice of "stories on the net"

If you have a genuine question about 10uF capacitor, by all means ask. However you should only believe the author from the original respected tutorial.

Of course you can ask the question here, but please quote where you got the original "story" from.

David.

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

david.prentice wrote:
Quote:
The Arduino ISP tutorials are excellent. Just obey the instructions meticulously.

Do not take any notice of "stories on the net"

If you have a genuine question about 10uF capacitor, by all means ask. However you should only believe the author from the original respected tutorial.

Of course you can ask the question here, but please quote where you got the original "story" from.

David.

I don't quite understand what you mean.
I was following the hackaday tutorial and in one of the steps it referred to the arduino.cc tutorial for wiring up the circuit. I only needed the barebones circuit which was the bottom left one so I missed the part at the top that said for arduino UNO you needed a capacitor between ground and reset (hackaday tutorial was using a duemilanove which doesn't need a capacitor).

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

Use the wiring from "Circuit (targeting an AVR on a breadboard)" on the http://arduino.cc/en/Tutorial/ArduinoISP

The graphic shows a mega168. It could be any AVR. Just connect the wires to the relevant RST, SCK, MISO, MOSI, VCC, GND pins. (note that a mega64/128 uses DI and DO instead of MISO, MOSI pins)

Also note that any pcb or breadboard should have 100nF decoupling capacitor(s) between VCC and GND.

I suggest that you do NOT use a bootloader on a breadboard. Simply use your ArduinoISP setup to program any breadboard target AVR via ISP.

If you want to use UART etc, use the Arduino as-is. i.e. don't use an AVR on a breadboard.

David.

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

"If you want to use UART etc,"...."don't use an AVR on a breadboard. "

Why (stray capacitances as a quartz is needed for reliable UART, shaky contacts or other reasons I did not figure out)?

What is funny is that one can find an arduino on a broad beard http://www.lextronic.fr/P20103-k... ....

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

I am not making any hard and fast assertion. Purely a practical observation.

1. If you have an Arduino, make full use of it.
2. If you need extra electronics, put this on the breadboard with a few flying wires back to the Arduino.
3. Whatever you do, the easier and more reliable your 'system' is, the better.
4. The same applies to a STK500 or any dev board. Try to make best use of the onboard facilities. Minimise your external wiring.

Many Arduino tutorials show an AVR on a breadboard with wires back to the Arduino to achieve UART comms, bootload etc. It all gets a little messy.

Yes, you can put crystals, AVR, regulators, ... on the breadboard. If you are careful with your wiring, it will work too.

Think about it. You need no prayers to the breadboard god or the wiring fairies. The Arduino works every time.

@dbrion0606,
Are those French electrolytic capacitors?
I can't see any 100nF ceramic/poly capacitors in the 'electronic components'

David.

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

I just tried the exact configuration (bottom left diagram and with a 10uF capacitor from ground to reset) on the arduino.cc website for ArduinoISP, but I am getting the same "Yikes .. Invalid Device Signature" problem.

Could it be that I need a crystal (16MHz)?

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

Well,it is unlikely electrolytic capacitors are French ..

In the picture, ceramic/poly capacitors are 2.54 mm (0.1") and can be seen (with luck...) between the 9v battery coupler and the electrolytics (4 : I guess / bet , but the components are tiny enough I can not read their values...
2 *22pf for the cristal,
2*100n for the decoupling the arduino, the 5 v regulator being decoupled by 2 electrolytics )
in http://arduino.cc/en/Main/Standa..., they omit/forgot? the 100 nf, but in the picture I linked to, they "claim" to ship 4 non electrolytic caps...

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

cozmicf wrote:
I just tried the exact configuration (bottom left diagram and with a 10uF capacitor from ground to reset) on the arduino.cc website for ArduinoISP, but I am getting the same "Yikes .. Invalid Device Signature" problem.

Could it be that I need a crystal (16MHz)?

Where did you get this "story" about a 10uF capacitor?

If you bought a regular mega328 chip from a regular distributor, it will come with "1MHz internal RC" clock fuses. So you do not need a crystal.

If you bought it from an Arduino shop, it probably is pre-programmed for an Arduino. You must have a crystal.

Of course, this only applies to virgin or freshly purchased AVRs. However, you can easily program the wrong fuses into a perfectly good AVR. (you may not even realise that you did it)

David.

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

david.prentice wrote:
cozmicf wrote:
I just tried the exact configuration (bottom left diagram and with a 10uF capacitor from ground to reset) on the arduino.cc website for ArduinoISP, but I am getting the same "Yikes .. Invalid Device Signature" problem.

Could it be that I need a crystal (16MHz)?

Where did you get this "story" about a 10uF capacitor?

If you bought a regular mega328 chip from a regular distributor, it will come with "1MHz internal RC" clock fuses. So you do not need a crystal.

If you bought it from an Arduino shop, it probably is pre-programmed for an Arduino. You must have a crystal.

Of course, this only applies to virgin or freshly purchased AVRs. However, you can easily program the wrong fuses into a perfectly good AVR. (you may not even realise that you did it)

David.

It is in step 5 in the arduino.cc tutorial I linked above. I have seen it in other tutorials as well but I am on my mobile right now so I can't link the sites. It is apparently to disable auto reset on the arduino uno only.

Edit:
These pages also say to use a 10uF capacitor:
http://hlt.media.mit.edu/?p=1695
http://arduino.cc/forum/index.ph...
http://www.ernstc.dk/arduino/231...

I am using IDE 1.01. I wonder if this is a problem since I also read that IDE 1.0 doesn't work with ArduinoISP.

Last Edited: Thu. Feb 7, 2013 - 03:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also, so far I have only received the 'yikes invalid signature' error and no other so I hope that means I haven't actually altered anything on my atmega and potentially damaged something.

If a crystal isn't needed, why am I still getting the error, I have double checked my wiring.

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

Well, I ran ArduinoISP on both a Demilanove and a UNO.

My target chip was ATtiny4313 with no 10uF capacitor on RESET. ( 10uF would prevent the tiny4313 using debugWIRE )

Duemilanove is on COM5

avrdude -c stk500v1 -b 19200 -P com5 -p ATtiny4313

UNO is on COM20

avrdude -c stk500v1 -b 19200 -P com20 -p ATtiny4313

You have never answered about where you bought your mega328 chip.

If you have not got a crystal, I can post you a modified ArduinoISP sketch that provides an external clock signal on digital#3 pin.

David.

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

david.prentice wrote:
Well, I ran ArduinoISP on both a Demilanove and a UNO.

My target chip was ATtiny4313 with no 10uF capacitor on RESET. ( 10uF would prevent the tiny4313 using debugWIRE )

Duemilanove is on COM5

avrdude -c stk500v1 -b 19200 -P com5 -p ATtiny4313

UNO is on COM20

avrdude -c stk500v1 -b 19200 -P com20 -p ATtiny4313

You have never answered about where you bought your mega328 chip.

If you have not got a crystal, I can post you a modified ArduinoISP sketch that provides an external clock signal on digital#3 pin.

David.

This is the atmega I bought: http://www.ebay.com.au/itm/16076...

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

These are the steps I took to upload a hex file to my atmega328 using my Arduino UNO as an ISP:
1. Installed the latest WinAVR which comes with avrdude.
2. Connected Arduino to PC, uploaded ArduinoISP using Arduino IDE 1.01 [board selected is the UNO].
3. Wired up my atmega exactly like this:

4. Downloaded "main.hex" from this page http://hackaday.com/2010/10/25/a... under heading "Flashing firmware with AVRdude
" - this is supposed to be a program that blinks an LED. This is what it looked like except I had 5V running from the Arduino to the 5V rail like in the picture above (and no other power source).

[This is a picture from the hackaday website, not one that I took]
5. Opened up command prompt, navigated to the directory with the .hex file, and used:
avrdude -P COM7 -b 19200 -c avrisp -p m328p -U flash:w:main.hex where COM7 is the port my Arduino was connected to [I got this line from the hackaday tutorial].

Then when I found out I may need a 10uF capacitor between GND and RESET on the Arduino, I repeated all the steps from step 3 onwards with the capacitor in. Note that I had no other capacitors or a crystal. This is a fresh ATMega328P-PU that I got from here: http://www.ebay.com.au/itm/16076...

Both ways yielded an invalid device signature (I think it was 0x000000) error immediately. Forcing it with -F took about a minute to complete with a few different steps going from 0-100%, but verification at the end failed [I suspect it didn't connect/upload at all].

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

I don't regard Ebay as a 'proper' distributor like Farnell or DigiKey. So quite honestly I don't trust the "New: Never Used".

I would also be happier if you had posted your photo. And I really dislike the battery in the photo that you did post. You will kill an AVR if you use 9V.

If your Arduino works ok, just supply an external clock to XTAL1. This is an ArduinoISP sketch modified to output 1MHz on digital#3.

Save it as "ArduinoISP_extclock"

// ArduinoISP version 04m3
// Copyright (c) 2008-2011 Randall Bohn
// If you require a license, see 
//     http://www.opensource.org/licenses/bsd-license.php
//
// This sketch turns the Arduino into a AVRISP
// using the following arduino pins:
//
// pin name:    not-mega:         mega(1280 and 2560)
// slave reset: 10:               53 
// MOSI:        11:               51 
// MISO:        12:               50 
// SCK:         13:               52 
//
// CLOCK_1MHZ    3:               .kbv
//
// Put an LED (with resistor) on the following pins:
// 9: Heartbeat   - shows the programmer is running
// 8: Error       - Lights up if something goes wrong (use red if that makes sense)
// 7: Programming - In communication with the slave
//
// 23 July 2011 Randall Bohn
// -Address Arduino issue 509 :: Portability of ArduinoISP
// http://code.google.com/p/arduino/issues/detail?id=509
//
// October 2010 by Randall Bohn
// - Write to EEPROM > 256 bytes
// - Better use of LEDs:
// -- Flash LED_PMODE on each flash commit
// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress)
// - Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync.
// - Use pins_arduino.h (should also work on Arduino Mega)
//
// October 2009 by David A. Mellis
// - Added support for the read signature command
// 
// February 2009 by Randall Bohn
// - Added support for writing to EEPROM (what took so long?)
// Windows users should consider WinAVR's avrdude instead of the
// avrdude included with Arduino software.
//
// January 2008 by Randall Bohn
// - Thanks to Amplificar for helping me with the STK500 protocol
// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
// - The SPI functions herein were developed for the AVR910_ARD programmer 
// - More information at http://code.google.com/p/mega-isp

#include "pins_arduino.h"
#define RESET     SS

#define LED_HB    9
#define LED_ERR   8
#define LED_PMODE 7
#define PROG_FLICKER true

#define HWVER 2
#define SWMAJ 1
#define SWMIN 18

// STK Definitions
#define STK_OK      0x10
#define STK_FAILED  0x11
#define STK_UNKNOWN 0x12
#define STK_INSYNC  0x14
#define STK_NOSYNC  0x15
#define CRC_EOP     0x20 //ok it is a space...

void pulse(int pin, int times);

void setup() {
  Serial.begin(19200);
  pinMode(LED_PMODE, OUTPUT);
  pulse(LED_PMODE, 2);
  pinMode(LED_ERR, OUTPUT);
  pulse(LED_ERR, 2);
  pinMode(LED_HB, OUTPUT);
  pulse(LED_HB, 2);
// .kbv these next statements provide a 1MHz clock signal
  DDRD |= (1<<3);                    // make o/p
  OCR2A = F_CPU/2/1000000 - 1;       // CTC toggle @ 1MHz
  OCR2B = OCR2A;                     // match B 
  TCCR2A = (1<<COM2B0)|(1<<WGM21);   // Toggle OC2B in CTC mode
  TCCR2B = (1 << CS20);              // run timer2 at div1
}

int error=0;
int pmode=0;
// address for reading and writing, set by 'U' command
int here;
uint8_t buff[256]; // global block storage

#define beget16(addr) (*addr * 256 + *(addr+1) )
typedef struct param {
  uint8_t devicecode;
  uint8_t revision;
  uint8_t progtype;
  uint8_t parmode;
  uint8_t polling;
  uint8_t selftimed;
  uint8_t lockbytes;
  uint8_t fusebytes;
  int flashpoll;
  int eeprompoll;
  int pagesize;
  int eepromsize;
  int flashsize;
} 
parameter;

parameter param;

// this provides a heartbeat on pin 9, so you can tell the software is running.
uint8_t hbval=128;
int8_t hbdelta=8;
void heartbeat() {
  if (hbval > 192) hbdelta = -hbdelta;
  if (hbval < 32) hbdelta = -hbdelta;
  hbval += hbdelta;
  analogWrite(LED_HB, hbval);
  delay(20);
}


void loop(void) {
  // is pmode active?
  if (pmode) digitalWrite(LED_PMODE, HIGH); 
  else digitalWrite(LED_PMODE, LOW);
  // is there an error?
  if (error) digitalWrite(LED_ERR, HIGH); 
  else digitalWrite(LED_ERR, LOW);

  // light the heartbeat LED
  heartbeat();
  if (Serial.available()) {
    avrisp();
  }
}

uint8_t getch() {
  while(!Serial.available());
  return Serial.read();
}
void fill(int n) {
  for (int x = 0; x < n; x++) {
    buff[x] = getch();
  }
}

#define PTIME 30
void pulse(int pin, int times) {
  do {
    digitalWrite(pin, HIGH);
    delay(PTIME);
    digitalWrite(pin, LOW);
    delay(PTIME);
  } 
  while (times--);
}

void prog_lamp(int state) {
  if (PROG_FLICKER)
    digitalWrite(LED_PMODE, state);
}

void spi_init() {
  uint8_t x;
  SPCR = 0x53;
  x=SPSR;
  x=SPDR;
}

void spi_wait() {
  do {
  } 
  while (!(SPSR & (1 << SPIF)));
}

uint8_t spi_send(uint8_t b) {
  uint8_t reply;
  SPDR=b;
  spi_wait();
  reply = SPDR;
  return reply;
}

uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  uint8_t n;
  spi_send(a); 
  n=spi_send(b);
  //if (n != a) error = -1;
  n=spi_send(c);
  return spi_send(d);
}

void empty_reply() {
  if (CRC_EOP == getch()) {
    Serial.print((char)STK_INSYNC);
    Serial.print((char)STK_OK);
  } 
  else {
    error++;
    Serial.print((char)STK_NOSYNC);
  }
}

void breply(uint8_t b) {
  if (CRC_EOP == getch()) {
    Serial.print((char)STK_INSYNC);
    Serial.print((char)b);
    Serial.print((char)STK_OK);
  } 
  else {
    error++;
    Serial.print((char)STK_NOSYNC);
  }
}

void get_version(uint8_t c) {
  switch(c) {
  case 0x80:
    breply(HWVER);
    break;
  case 0x81:
    breply(SWMAJ);
    break;
  case 0x82:
    breply(SWMIN);
    break;
  case 0x93:
    breply('S'); // serial programmer
    break;
  default:
    breply(0);
  }
}

void set_parameters() {
  // call this after reading paramter packet into buff[]
  param.devicecode = buff[0];
  param.revision   = buff[1];
  param.progtype   = buff[2];
  param.parmode    = buff[3];
  param.polling    = buff[4];
  param.selftimed  = buff[5];
  param.lockbytes  = buff[6];
  param.fusebytes  = buff[7];
  param.flashpoll  = buff[8]; 
  // ignore buff[9] (= buff[8])
  // following are 16 bits (big endian)
  param.eeprompoll = beget16(&buff[10]);
  param.pagesize   = beget16(&buff[12]);
  param.eepromsize = beget16(&buff[14]);

  // 32 bits flashsize (big endian)
  param.flashsize = buff[16] * 0x01000000
    + buff[17] * 0x00010000
    + buff[18] * 0x00000100
    + buff[19];

}

void start_pmode() {
  spi_init();
  // following delays may not work on all targets...
  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, HIGH);
  pinMode(SCK, OUTPUT);
  digitalWrite(SCK, LOW);
  delay(50);
  digitalWrite(RESET, LOW);
  delay(50);
  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  spi_transaction(0xAC, 0x53, 0x00, 0x00);
  pmode = 1;
}

void end_pmode() {
  pinMode(MISO, INPUT);
  pinMode(MOSI, INPUT);
  pinMode(SCK, INPUT);
  pinMode(RESET, INPUT);
  pmode = 0;
}

void universal() {
  int w;
  uint8_t ch;

  fill(4);
  ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
  breply(ch);
}

void flash(uint8_t hilo, int addr, uint8_t data) {
  spi_transaction(0x40+8*hilo, 
  addr>>8 & 0xFF, 
  addr & 0xFF,
  data);
}
void commit(int addr) {
  if (PROG_FLICKER) prog_lamp(LOW);
  spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
  if (PROG_FLICKER) {
    delay(PTIME);
    prog_lamp(HIGH);
  }
}

//#define _current_page(x) (here & 0xFFFFE0)
int current_page(int addr) {
  if (param.pagesize == 32)  return here & 0xFFFFFFF0;
  if (param.pagesize == 64)  return here & 0xFFFFFFE0;
  if (param.pagesize == 128) return here & 0xFFFFFFC0;
  if (param.pagesize == 256) return here & 0xFFFFFF80;
  return here;
}


void write_flash(int length) {
  fill(length);
  if (CRC_EOP == getch()) {
    Serial.print((char) STK_INSYNC);
    Serial.print((char) write_flash_pages(length));
  } 
  else {
    error++;
    Serial.print((char) STK_NOSYNC);
  }
}

uint8_t write_flash_pages(int length) {
  int x = 0;
  int page = current_page(here);
  while (x < length) {
    if (page != current_page(here)) {
      commit(page);
      page = current_page(here);
    }
    flash(LOW, here, buff[x++]);
    flash(HIGH, here, buff[x++]);
    here++;
  }

  commit(page);

  return STK_OK;
}

#define EECHUNK (32)
uint8_t write_eeprom(int length) {
  // here is a word address, get the byte address
  int start = here * 2;
  int remaining = length;
  if (length > param.eepromsize) {
    error++;
    return STK_FAILED;
  }
  while (remaining > EECHUNK) {
    write_eeprom_chunk(start, EECHUNK);
    start += EECHUNK;
    remaining -= EECHUNK;
  }
  write_eeprom_chunk(start, remaining);
  return STK_OK;
}
// write (length) bytes, (start) is a byte address
uint8_t write_eeprom_chunk(int start, int length) {
  // this writes byte-by-byte,
  // page writing may be faster (4 bytes at a time)
  fill(length);
  prog_lamp(LOW);
  for (int x = 0; x < length; x++) {
    int addr = start+x;
    spi_transaction(0xC0, (addr>>8) & 0xFF, addr & 0xFF, buff[x]);
    delay(45);
  }
  prog_lamp(HIGH); 
  return STK_OK;
}

void program_page() {
  char result = (char) STK_FAILED;
  int length = 256 * getch();
  length += getch();
  char memtype = getch();
  // flash memory @here, (length) bytes
  if (memtype == 'F') {
    write_flash(length);
    return;
  }
  if (memtype == 'E') {
    result = (char)write_eeprom(length);
    if (CRC_EOP == getch()) {
      Serial.print((char) STK_INSYNC);
      Serial.print(result);
    } 
    else {
      error++;
      Serial.print((char) STK_NOSYNC);
    }
    return;
  }
  Serial.print((char)STK_FAILED);
  return;
}

uint8_t flash_read(uint8_t hilo, int addr) {
  return spi_transaction(0x20 + hilo * 8,
  (addr >> 8) & 0xFF,
  addr & 0xFF,
  0);
}

char flash_read_page(int length) {
  for (int x = 0; x < length; x+=2) {
    uint8_t low = flash_read(LOW, here);
    Serial.print((char) low);
    uint8_t high = flash_read(HIGH, here);
    Serial.print((char) high);
    here++;
  }
  return STK_OK;
}

char eeprom_read_page(int length) {
  // here again we have a word address
  int start = here * 2;
  for (int x = 0; x < length; x++) {
    int addr = start + x;
    uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF);
    Serial.print((char) ee);
  }
  return STK_OK;
}

void read_page() {
  char result = (char)STK_FAILED;
  int length = 256 * getch();
  length += getch();
  char memtype = getch();
  if (CRC_EOP != getch()) {
    error++;
    Serial.print((char) STK_NOSYNC);
    return;
  }
  Serial.print((char) STK_INSYNC);
  if (memtype == 'F') result = flash_read_page(length);
  if (memtype == 'E') result = eeprom_read_page(length);
  Serial.print(result);
  return;
}

void read_signature() {
  if (CRC_EOP != getch()) {
    error++;
    Serial.print((char) STK_NOSYNC);
    return;
  }
  Serial.print((char) STK_INSYNC);
  uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
  Serial.print((char) high);
  uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
  Serial.print((char) middle);
  uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
  Serial.print((char) low);
  Serial.print((char) STK_OK);
}
//////////////////////////////////////////
//////////////////////////////////////////


////////////////////////////////////
////////////////////////////////////
int avrisp() { 
  uint8_t data, low, high;
  uint8_t ch = getch();
  switch (ch) {
  case '0': // signon
    error = 0;
    empty_reply();
    break;
  case '1':
    if (getch() == CRC_EOP) {
      Serial.print((char) STK_INSYNC);
      Serial.print("AVR ISP");
      Serial.print((char) STK_OK);
    }
    break;
  case 'A':
    get_version(getch());
    break;
  case 'B':
    fill(20);
    set_parameters();
    empty_reply();
    break;
  case 'E': // extended parameters - ignore for now
    fill(5);
    empty_reply();
    break;

  case 'P':
    start_pmode();
    empty_reply();
    break;
  case 'U': // set address (word)
    here = getch();
    here += 256 * getch();
    empty_reply();
    break;

  case 0x60: //STK_PROG_FLASH
    low = getch();
    high = getch();
    empty_reply();
    break;
  case 0x61: //STK_PROG_DATA
    data = getch();
    empty_reply();
    break;

  case 0x64: //STK_PROG_PAGE
    program_page();
    break;

  case 0x74: //STK_READ_PAGE 't'
    read_page();    
    break;

  case 'V': //0x56
    universal();
    break;
  case 'Q': //0x51
    error=0;
    end_pmode();
    empty_reply();
    break;

  case 0x75: //STK_READ_SIGN 'u'
    read_signature();
    break;

    // expecting a command, not CRC_EOP
    // this is how we can get back in sync
  case CRC_EOP:
    error++;
    Serial.print((char) STK_NOSYNC);
    break;

    // anything else we will return STK_UNKNOWN
  default:
    error++;
    if (CRC_EOP == getch()) 
      Serial.print((char)STK_UNKNOWN);
    else
      Serial.print((char)STK_NOSYNC);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just tried your code, and connected Digital Output 3 to XTAL1, and I am successfully uploading with the same command as before! It is even verifying now :)

Thankyou so much. Does this mean my circuit needed a crystal? Does that mean it may already have something on it [because I thought fresh ones were programmed to use their own 1MHz clock]?

Can (and should) I program my avr (fuses?) to set an internal clock at 8MHz?

Thanks again!

Ps, I also found what I think looks like a crystal from an old modem PCI card. It says KSE28.224 on it and googling that doesn't turn up any relevant results.

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

Do some research on avrdude. You will see how to READ the fuses. Or a no-brain method is:

avrdude -c stk500v1 -b 19200 -P com7 -p ATmega328P -v

Your googling will also show you how to WRITE fuses too.

No, don't try scrap crystals. Simply set the fuses for "Int 8MHz RC" and remove the CLKDIV8 fuse.

Then your AVR will run safely at 8MHz without you worrying. I would only use a crystal when you have soldered your circuit.

David.

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

I have not had a chance to read my fuses yet, but I used the fuse calculator at http://www.engbedded.com/fusecalc for the atmega328p. I am using the Feature configuration section, and I have unchecked CKDIV8 so the only checked option is SPIEN.

The first drop down box is: "Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms; [CKSEL =0010 SUT=10]; default value"

The second drop down box says: "Boot Flash section size=2048 words Boot start address=$3800; [BOOTSZ=00] ; default value" and the third drop down box is: "Brown-out detection disabled; [BODLEVEL=111].

This comes out to a fuse setting of: "-U lfuse:w:0xe2:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m"

Is this right? I've heard setting the fuses wrong can brick the chip so I want to be sure.

Then would I use this command for my Arduino as an ISP: "avrdude -P COM7 -b 19200 -c avrisp -p m328p -U lfuse:w:0xe2:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m"

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

Yup, your command is fine. And using the online calculator is the best way of selecting fuses.

Since you have an Arduino, you should be able to recover from any fuse mishaps anyway. The only thing that can mess up your chip is RSTDISBL. Everything else is fixable with the Arduino. (even DWEN)

Good luck with your breadboard.
All the same, I would always use the Arduino in preference.

David.

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

david.prentice wrote:
Yup, your command is fine. And using the online calculator is the best way of selecting fuses.

Since you have an Arduino, you should be able to recover from any fuse mishaps anyway. The only thing that can mess up your chip is RSTDISBL. Everything else is fixable with the Arduino. (even DWEN)

Good luck with your breadboard.
All the same, I would always use the Arduino in preference.

David.

The original fuse values were FF, DE, and 5 which seems like it wasn't the right default value. So I used "avrdude -P COM7 -b 19200 -c avrisp -p m328p -U lfuse:w:0xe2:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m" to set it to use its own clock at 8MHz.

As it was changing the fuses though it threw a verification error with the efuse: "avrdude: safemode: efuse changed! Was ff, and is now 7. Would you like this fuse to be changed back [y/n]"

I chose 'y', and it froze, the RX and TX lights were constantly green on the Arduino for over a minute so I closed the terminal. I reopened the terminal and printed verbose output and now my fuses are E2, D9, and 7.

Not sure exactly what 7 is for efuse but now I can use the regular ArduinoISP code [and no need for the clock on digital #3 in your code now] to upload to my ATMega, which means the clock is now set.

Thanks again!

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

As I suspected, your virgin AVR was in fact pre-programmed for putting in an Arduino.

On most AVRs the "efuse" only uses a few bits.
The "lfuse" and "hfuse" have 8 bits and use all of them.

It is a "feature" of the existing avrdude configuration file that they don't handle a 3-bit fusebyte very well. Hence you got the rather frightening verification message. If you had asked for 0x07 instead of 0xFF for efuse, avrdude might have been happier. i.e. you are still setting the 3-bits to all-ones. 0x07 is 0b00000111.

On the online fuse calculator site, there is a message in red ink about the efuse.

Anyway, you have got your chip fuses to a sensible state. And you can be confident that the ArduinoISP_extclock sketch can get you out of most scrapes in the future.

Happy programming !

David.

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

Thank you!

Had a very long search for find your solution on the Internet. It's was necessary to apply frequency to the processor!!!. I have a mistake to detect my CPU in arduino IDE and either programmers .
Invalid device signature. Device signature = 0x000000
It seems that I used the wrong fuse before to program CPU. No frequency working and processor just a stone.

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

Quote:

Had a very long search for find your solution on the Internet. It's was necessary to apply frequency to the processor!!!

Tip for the future - start here in the Tutorial Forum:

How to recover a "locked" AVR

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

hi,
I'm a new user!
I think that i've bricked my atmega328p-AU.
I don't have an oscillator.
I use arduino uno as ISP, with your code (clawson), to program the bricked chip. All connections are correct.
Arduino----->atmega238p-AU
pin 10------>rst
pin 11------>MOSI
pin 12------>MISO
pin 13------>SCK
pin 3------>XTAL1

My command:

-c stk500v1 -p m328p -P COM6 -b 19200 -e -U lfuse:w:0xFF:m -U hfuse:w:0xDA:m -U efuse:w:0x05:m 

Output:

avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.03s

avrdude.exe: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.03s

avrdude.exe: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.03s

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


avrdude.exe done.  Thank you.

with your tutorial doesn't work
Can you help me please?? :? :? :? :? :?

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

Quote:

with your tutorial doesn't work

You mean you have tried injecting a clock signal into XTAL1? What did you use for that?

If a clock injection doesn't recover it then bing a 328P I would guess one of two things:

1) DWEN

2) RSTDISBL

If it's (1) then you should be able to recover but if it's (2) you are going to need a high voltage programmer.

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

For clock injecting I use the pin 3 of arduino, on arduino there is code of david.pretince.
Not your code, sorry.

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

your tutorial says:
"One key thing to note is that ISP must always run at less than 1/4 of the clock frequency of the AVR. So if you apply a 1MHz clock signal to the XTAL1 pin then the ISP programmer must be set to run at 250kHz or less. "

How can I set the speed at 250kHz using my metod?

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

Quote:

How can I set the speed at 250kHz using my metod?

No idea - I don't know what an Arduino is doing with pin 3. But on nay micro you can make a pin toogle:

int main(void) {
  DDRB = 0xFF;
  while(1) {
    PORTB ^= 0xFF;
  }
}

That just generates a clock on every pin of PORTB. If it's found to be "too fast" then slow it down:

int main(void) {
  DDRB = 0xFF;
  while(1) {
    PORTB ^= 0xFF;
    _delay_us(50);
  }
}

Adjust the 50 until you get the period/frequency you want.