Programming the programmer : AVR

Well, as the name says it all, this post is indeed all about programming mumbo jumbo of AVRs.  First lets get the picture as it is normally seen.

C/C++ Code ->Compiler->linker(&/|)loader->avr-objcopy->hex file->avrdude->running program.

So, the above order seems simple enough but every stage is a big process in itself.   What I in this post gonna do is
1. The explanation of last part.(how  code goes into controller’s flash)
2. How can you do it yourself. 

For any program that we write in C/C++ code using AVR studio, Arduino IDE, or any other IDE is compiled and has to be written in the controller’s flash which is sometimes referred as burning of code.

How code burns ? What is the strategy/protocol or mean by which my pc/laptop sends this whole program into the controller’s flash ?

Generally there are two ways,
1.  Controller is already having a bootloader.
2.  We are using an external programmer.

I am specifically going to talk about external programmer’s deal here i.e. how it works!  Well, I always follow the command as recommended to use the datasheet and here it goes.
The section we are interested about is Serial Programming of any AVR controller.  So simply jump to Serial Programming section inside the BIGG datasheet of any AVR that you work on.  ex- Atmega16/32/64/128/ Atmega8,168,328,2560 etc.

I am following this datasheet of general Atmega 8 bit series controller of genre 328.

DATASHEET

There can be no other FACT than what is written in DATASHEET.  When RESET is pulled, the SPI is automatically active) because of the Fuse bit thus set in the fuse registers.

One can even Turn off/on the RESET button and SPI programming enable settings in fuse registers, but as obvious it can be, it will render the controller useless for further serial programming.
It can surely be changed using Parallel Programmer.

Steps:

1. Power-up sequence:
Apply power between VCC and GND while RESET and SCK are set to “0”. In some systems, the programmer can not guarantee that SCK is held low during power-up. In this case, RESET must be given a positive pulse of at least two CPU clock cycles duration after SCK has been set to “0”.

2. Wait for at least 20ms and enable serial programming by sending the Programming Enable serial instructionto pin MOSI.

3. The serial programming instructions will not work if the communication is out of synchronization. When in sync. the second byte (0x53), will echo back when issuing the third byte of the Programming Enable instruc-tion. Whether the echo is correct or not, all four bytes of the instruction must be transmitted. If the 0x53 did not echo back, give RESET a positive pulse and issue a new Programming Enable command.
4. The Flash is programmed one page at a time. The memory page is loaded one byte at a time by supplying the 6 LSB of the address and data together with the Load Program Memory Page instruction. To ensure correct loading of the page, the data low byte must be loaded before data high byte is applied for a given address. The Program Memory Page is stored by loading the Write Program Memory Page instruction with the 7 MSB of the address. If polling (RDY/BSY) is not used, the user must wait at least t WD_FLASH before issuing the next page (See Table 28-18). Accessing the serial programming interface before the Flash write operation completes can result in incorrect programming.
5. A: The EEPROM array is programmed one byte at a time by supplying the address and data together with the appropriate Write instruction. An EEPROM memory location is first automatically erased before new data is written. If polling (RDY/BSY) is not used, the user must wait at least t WD_EEPROM before issuing the
next byte (See Table 28-18). In a chip erased device, no 0xFFs in the data file(s) need to be programmed.
B: The EEPROM array is programmed one page at a time. The Memory page is loaded one byte at a time by supplying the 6 LSB of the address and data together with the Load EEPROM Memory Page instruction. The EEPROM Memory Page is stored by loading the Write EEPROM Memory Page Instruction with the 7 MSB of the address. When using EEPROM page access only byte locations loaded with the Load
EEPROM Memory Page instruction is altered. The remaining locations remain unchanged. If polling (RDY/BSY) is not used, the used must wait at least t WD_EEPROM before issuing the next byte (See Table 28-18). In a chip erased device, no 0xFF in the data file(s) need to be programmed.

6. Any memory location can be verified by using the Read instruction which returns the content at the selected address at serial output MISO.

7. At the end of the programming session, RESET can be set high to commence normal operation.

8. Power-off sequence (if needed):Set RESET to “1”.  Turn V CC power off.

 

Yeah, Yeah.. that is what datasheet says, and it is quite tedious to follow.  So I am going to actually do the above steps in Code.
Lets understand two things here.
1.  AVR Atmega series of controller are programmable in Serial mode using the SPI protocol which obviously I am going to discuss in next post.
2.  The controller behaves normally when it is not in RESET mode, otherwise if RESET is activated, it is ready to go into programming mode, so one has to pull the reset high/low accordingly to make it enter in programming mode.
In programming mode, we have access to all of the things inside controller i.e. its flash and EEPROM.

When the RESET is pulled, the controller goes into RESET mode, then in order to make it enter into the programming mode, we have to open the gate using the Magic words because for obvious reasons the gate can’t be open all the time, otherwise the data can get corrupted every other time reset if pulled.

So, our steps,
1.  Pull reset line
2.  Speak the Magic Words i.e. send particular Data on the SPI line that lets us into the programming mode.
3.  Once entered, Read whats written in fuses, whats there in Flash, Is there a bootloader, what is in the registers ?? and a lot more.

Much of saying, lets see the above three simple steps in code.  I am using Arduino SPI libraries to expedite the process.

//Code is all free to use and distribute

#include <SPI.h>

int reset_pin=10;
byte return_bytes[4]={0,0,0,0};

void setup()
{
Serial.begin(115200);
Serial.println(“Get signature program”);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV64);
start_programming()
get_signatures();

}
void loop()
{

}
void start_programming()
{
pinMode(reset_pin,OUTPUT);
digitalWrite(reset_pin,LOW);
delay(25);

do{
return_bytes[0]=SPI.transfer(0xAC);
return_bytes[1]=SPI.transfer(0x53);
return_bytes[2]=SPI.transfer(0);
return_bytes[3]=SPI.transfer(0);

Serial.print(return_bytes[0],HEX);
Serial.print(“\t”);
Serial.print(return_bytes[1],HEX);
Serial.print(“\t”);
Serial.print(return_bytes[2],HEX);
Serial.print(“\t”);
Serial.println(return_bytes[3],HEX);
}

while (return_bytes[2]!=83);

}

void get_signatures()
{
SPI.transfer(0x30);
SPI.transfer(0x00);
SPI.transfer(0x00);
byte add1=SPI.transfer(0);
Serial.print(“signature address 1 is \t”);
Serial.println(add1, HEX);

SPI.transfer(0x30);
SPI.transfer(0x00);
SPI.transfer(0x01);
byte add2=SPI.transfer(0);
Serial.print(“signature address 2 is \t”);
Serial.println(add2, HEX);

SPI.transfer(0x30);
SPI.transfer(0x00);
SPI.transfer(0x02);
byte add3=SPI.transfer(0);
Serial.print(“signature address 3 is \t”);
Serial.println(add3, HEX);

}

What’s in the code?
Explanation:
Setup Function is called first in Arduino IDE usually (others can be called first obviously).  Inside setup function,
Line 1 & 2 :Serial Initialization and a debugging message.
Line 3 & 4 :SPI initialization and setting the clock, that depends on your clock source and setting.
Line 5 : Call to start_programming function
Well, inside the start_programming function we have to write exactly as the datasheet says,
pulling the reset line
giving sufficient delay
sending the magic words, i.e. $AC,$53,$0,$0

The whole AVR Atmega programming protocol is 4 byte protocol.  One has to send 4 continuous bytes to MOSI line i.e. has to call SPI.transfer with appropriate arguments.

The protocol says, that if correctly done the target controller that is the one which is to be programmed will reply with $83 on sending third byte.  Thus, I am using a do-while loop and making it stuck in there till I receive the require byte.
If 83 is received, and we have sent the fourth byte also, then we are in programming mode.

Congratulations!!!  

 

Now to verify if we are actually in Programming Mode i.e. inside “Area 51”, we can check by trying to read the fuses or signature of the controller.
Every controller has a signature that makes it unique.

The Atmel people have this very strict rule for it, they have assigned 3 bytes for this signature.
1. The first byte $1E tells about the company i.e. Atmel
2. The second byte is usually like $94 which tells the size of flash on controller i.e
$94 tells that it is having 2^4 Kbytes of flash,
$95 will say that it is having 2^5 Kbytes of Flash and so on.
3.  Third byte is for individual allotment of controller with same amount of memory.

Here is the list of whole commands that can be used to read different sections of controller.

SPI_Programming

 

Reading and Writing of the flash is too easy using just above four commands.

A typical example with serial print messages removed is:

Get signature program
0 0 53 0
signature address 1 is 1E
signature address 2 is 94
signature address 3 is 3

The next post will be about SPI protocol.