Atmega328p writing operation.

Hi

Can someone tell me the reason why we must send to the MCU a 0x40 writing page instruction when we have an even address and 0x48 for the odd addresses ? I did many research in the official datasheet and I couldn't find anything related to this. However, I got the solution from USBASP Source code. How did they know that ?

Anyone have an explanation for that and if you can indicate me which datasheet have you found containing this information.

Thanks.

BlackSharp:
Can someone tell me the reason why we must send to the MCU a 0x40 writing page instruction when we have an even address and 0x48 for the odd addresses ? I did many research in the official datasheet and I couldn't find anything related to this.

Are you sure it's odd/even pages, not high byte/low byte?

Section 27.8 of the Mega 328 datasheet has a big table called "Serial Programming Instruction set". In there it says:

Load Program Memory Page,      High byte $48     $00    adr LSB     high data byte in
Load Program Memory Page,      Low byte $40     $00    adr LSB     low data byte in

Hi,

Thanks for your reply.

I know that in the datasheet they mentionned the 8bits LSB & 8bits MSB but it didn't work for me. This is why I've followed this link Electronics The King of Hobbies!: My own AVR ISP programmer using PIC16f877a and python!. His article contain a code that test for even/odd addresses and the written code is for Atmega8, 16, 32. Also, if you can see in the USBASP source code especially in isp.c file you will find a test like:

ispTransmit(0x40|((address&1)<<3));

This is the code that I've created following the atmel datasheet to program Atmega using arduino, I can get such as (Signature, sync code, program, lock bits, fuses) but no writing:

#define ENABLE_PROGRAMMING 0xAC530000L
#define CHIP_ERASE         0xAC800000L

#define READ_BYTE_LSB      0x20000000L
#define READ_BYTE_MSB      0x28000000L

#define WRITE_BYTE         0x4C000000L

#define LOAD_BYTE_MSB      0x48000041L
#define LOAD_BYTE_LSB      0x40000041L

#define SIGNATURE0         0x30000000L
#define SIGNATURE1         0x30000100L
#define SIGNATURE2         0x30000200L

#define READ_LOCK_BITS     0x58000000L
#define WRITE_LOCK_BITS    0xACE00000L

#define LOCKB_NOPROTECT    0x000000FFL
#define LOCKB_NOPROGRAM    0x000000FEL
#define LOCKB_ALLPROTECT   0x000000FCL

int RST_P = 9;
int MOSI_P = 10;
int MISO_P = 11;
int CLK_P  = 12;

void setup()
{
  Serial.begin(9600);
  
  pinMode(8, OUTPUT);
  
  pinMode(MOSI_P, OUTPUT);
  pinMode(MISO_P, INPUT);
  pinMode(RST_P, OUTPUT);
  pinMode(CLK_P, OUTPUT);
  
  digitalWrite(RST_P, HIGH);
  digitalWrite(MOSI_P, HIGH);
  digitalWrite(CLK_P, LOW);
}

void sendCmd(long cmd, boolean output)
{
  boolean counter_bool = false;
  int counter = 0;
  
  for (int i=31; i>=0; i--)
  {
    if (cmd&bit(i))
    {
      digitalWrite(MOSI_P, HIGH);
    }
    else
    {
      digitalWrite(MOSI_P, LOW);
    }
    
    digitalWrite(CLK_P, HIGH);
    delay(1);
    
    if (output/*&&counter_bool*/)
    Serial.print(digitalRead(MISO_P));
    
    digitalWrite(CLK_P, LOW);
  }
  Serial.println("");
}

void programmingEnable(boolean x)
{ 
  int  c = 0;
  
  if (x)
  {
    digitalWrite(MOSI_P, LOW);
    digitalWrite(CLK_P, LOW);
    digitalWrite(RST_P, LOW);
    
    //A LED indicator
    for (int i=0; i<4; i++) {
    delay(40);
    digitalWrite(8, c=(~c));
    } 
    //digitalWrite(CLK_P, HIGH);
  }
  else
  {
    digitalWrite(RST_P, HIGH);
    digitalWrite(MOSI_P, HIGH);
    digitalWrite(CLK_P, HIGH);
  }
  
  delay(1);
  
}

void programChip(char *program)
{
  long address = 0x00000000;
  int counter = 0;
  int len = strlen(program);
  while (counter != len)
  {
    for (;;)
    counter ++;
  }
}

void loop()
{  
  programmingEnable(true);
  sendCmd(ENABLE_PROGRAMMING, false);
  sendCmd(LOAD_BYTE_LSB, false);
  sendCmd(LOAD_BYTE_MSB, false);
  sendCmd(WRITE_BYTE, false);
  sendCmd(READ_BYTE_LSB, true);
  
  while(1);
}

What do you think guys ?

You mean this?

unsigned char ispWriteFlash(unsigned int address, unsigned char data) {
    spi_write(0x40 | ((address & 1) << 3));
    spi_write(address >> 9);
    spi_write(address >> 1);
    spi_write(data);
    return 0;
}

Arduino flash memory addresses refer to 2 bytes of data (all instructions are 16 bits).

The first byte of data goes in address 0x0000, the second byte also goes in address 0x0000 (that's what the "address>>9" and "address>>1" are for).

The 0x40/0x48 tells it which half of that location you're writing to.

So, the code that I put is correct or not ? I wrote a define which contain an instruction to write to the chip "0x40000041" and "0x48000041" and I send them using "sendCmd()". According to the datasheet, I think I did what they say am I wrong ?

BlackSharp:
So, the code that I put is correct or not ? I wrote a define which contain an instruction to write to the chip "0x40000041" and "0x48000041" and I send them using "sendCmd()". According to the datasheet, I think I did what they say am I wrong ?

I think that should write 0x4141 to the first two locations of flash memory.

OTOH I have no idea if "sendCmd()" is working (or anything else in your program)

Please would like to explain me one thing:

Load Program Memory Page,      High byte $48     $00    adr LSB     high data byte in
Load Program Memory Page,      Low byte $40     $00    adr LSB     low data byte in

High data byte in:
Data byte that will be the first 8 bits of 16 bits

Low data byte in:
Data byte that will be the last 8 bits of 16 bits.

So, I assume that I want to write 41 41 to the address 0x0000, correct me if I'm wrong:
0x40 00 00 41 0x48 00 00 41
| | | | | | | |
instruction xxx LSB address data instruction xxx LSB address (Is this MSB no ?) data

thanks

Yes, and don't forget you also have to do a "Write Program Memory Page" ($4C) to actually transfer the data to memory.

This is what I did in the program, and I could get the signature byte, program fuse bits, lock bits ... this explain that my code is working no ? But anyway I will retest all of that and get you informed if something goes wrong.

Hi,

Can somone please explain me what the 6 LSB & 7 MSB mean to write in atmega328p memory page. Also, I'll appreciate if you can give me an example of this.

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 tWD_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.

thanks.

Least Significant Bits - the bits at the bottom of the address
Most Significant Bits - the bits at the top of the address

Thanks Fungus.

Yes I know what LSB and MSB mean. What I wanna know is why should send 6 LSB and 7 MSB. To be more specific, I can't understand how the flash memory is programmed and how is organized. What I understood till now, the flash contains multiple pages and each page has an address. I must select a page at first and fill this page with "low bytes" and after "high bytes". Is that correct ?

questions:
how the pages are selected ?
if there is any way to do it, is the pages are selected automatically when 64 words are filled ?

Thanks for giving me a detailed explanations.

BlackSharp:
Thanks Fungus.

Yes I know what LSB and MSB mean. What I wanna know is why should send 6 LSB and 7 MSB. To be more specific, I can't understand how the flash memory is programmed and how is organized. What I understood till now, the flash contains multiple pages and each page has an address. I must select a page at first and fill this page with "low bytes" and after "high bytes". Is that correct ?

questions:
how the pages are selected ?
if there is any way to do it, is the pages are selected automatically when 64 words are filled ?

Thanks for giving me a detailed explanations.

I've never done it but the way I read the datasheet the "page" is created in some sort of internal buffer (using $40 and $48) then you transfer the entire page to flash using $4C.