2
\$\begingroup\$

Hi and thanks for looking!

Background

After coding and designing a project with the Arduino hardware and IDE, I have been etching my own PCB with a single ATMega328 and related components for the particular project. I include on my boards a six-pin header to which I have been hooking up a generic USBasp programmer and then flash the IC with new code written in the Arduino IDE.

This all works great.

Problem

I am now building a more advanced circuit that requires five ATMega328 ICs--each with it's own code that is unlike the code on the other ICs. I need to be able to flash all five IC's from the single USBasp/SPI six-pin connection, but I don't have a clue how.

I realize that it would be easier to just use a single IC with more pins, but that is not an option for now.

Question

Using my single USBasp/SPI six-pin connection, how can I flash multiple ATMega328 IC's with their respective code that I have written in the Arduino IDE?

\$\endgroup\$
1
\$\begingroup\$

I would take the USBAsp firmware and modify it to run on yet another AVR chip on your board that would manipulate the reset lines of each of your five target Atmegas individually. You would need to work out a way of selecting which target to program. If you are using AVRDUDE as your programmer you could use it's "-x extended_param" for this.

\$\endgroup\$
1
\$\begingroup\$

This is not an easy thing to do. You'd have to prepare an extra on-board programmer as well as code to communicate with it; it's possible this has been done before, but I haven't seen it.

Nick Alexeev's solution would be correct if the select level on the reset pin differed from the programming level, but they're identical in low voltage serial programming, which is the default method. This means the AVRs would end up responding in parallel, possibly damaging their MISO output buffers, and making it impossible to address them individually. The very first time, while all the AVRs are erased, you may get away with leaving the reset pins high instead of low (as the default state of the I/Os is floating). But that basically breaks down on the programming further chips, unless the early ones know to avoid the SPI pins.

pault's solution is closer, but it's not actually enough to manipulate the reset lines individually (although obviously the master AVR needs its own); it's the MISO and SCK lines that need to be separated. The first so the slave AVRs cannot damage each other, the second so they can be individually addressed.

Since you need many SCK lines, this means you probably can't use the SPI port for talking to the slave devices; besides, you need the first SPI to even program the master AVR. That in turn means bitbanging (controlling by software) the programming pins, in addition to reprogramming the serial interface, so the programming firmware modifications are notable.

An option is to use some form of I/O extender chip instead of the master AVR, and let the host do the bitbanging through it. This is likely to be slower, but speed is rarely a problem on chips this size.

In short, it's usually easier just to put an ICSP connector per AVR instead. Atmel simply didn't design the ICSP protocol for multiple chips, although many other SPI chips do support it (via chip selects or daisy chaining). JTAG TAP is similarly desined for daisy chaining.

\$\endgroup\$
1
\$\begingroup\$

Disclaimer: I haven't done this with Arduino or Atmega. But I've done this with PICs.

Synopsis: Connect the SPI lines in parallel, treat RESET_n lines separately. As you wrote, your new schematic will have 5x Atmegas. Add to your schematic 5x shorting blocks (jumper selectors). Each selector has 3 pins.

  • Pin1 goes connected to RESET_n line from the programmer. ( _n at the end means that the line is active-low. There are a few common notations for "active low", this is just one of them.)
  • Pin2 goes to RESET_X_n, where X is an individual controller. RESET_X_n line would have a pullup resistor like a normal reset line.
  • Pin3 goes to GND.

Suppose, you want to program controller_1. Connect RESET_1_n to programmer through its selector. Connect all other reset lines to GND. This will put all other Atmegas into reset, they will float the pins, which got to SPI lines, and not interfere with programming of controller_1 [edit: be sure to read Yann Vernier's comment below and his answer in this thread]. Remove all shorting blocks to run your system.

UPDATE in response to Matthew's comment

"simply plug in the USB programmer and then send code [to multiple controllers]"

If you can get a controller with JTAG interface, what you're asking for would be easy. JTAG is the only "magic bullet" for your problem that I know of. (The other approaches are more complicated, although this is a fun systems engineering problem to toss around in ones head.)

At the same time, you trust user with reprogramming to begin with. Consider trusting her with selectors too.

\$\endgroup\$
  • \$\begingroup\$ Thanks Nick, this sounds great. I was hoping, however, that this could be done without the use of jumpers so that the end-user could simply plug in the USB programmer and then send code. Is this not possible? Thanks again. \$\endgroup\$ – Matt Cashatt Jun 17 '12 at 0:59
  • 1
    \$\begingroup\$ Keeping the other AVRs in reset will enable their programming ports, so they won't float the pins. You need to have them running and not enabling the programming pins for output in that case. Alternatively, configure each to disable low voltage programming so there's a difference between reset and programming voltages. \$\endgroup\$ – Yann Vernier Jul 18 '12 at 9:31
  • \$\begingroup\$ @YannVernier The scheme with low voltage programming, which you're describing is what I had in mind. (This is what I've done with PICs, see disclaimer above.) \$\endgroup\$ – Nick Alexeev Jul 23 '12 at 3:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.