Calc page addr for ISP cmd Write Program Memory Page

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

The actual project is my own ISP firmware.

Host and Target controller are both ATmega8. Download software is AVR-Studio with STK500 protocol version 2. This protocol version is also implemented in host controller. Both controller are connted via SPI interface and communicating through serial programming instruction set.

AVR-Studio sends data page by page, 64 bytes/32 words per message. Loading program memory page into target controller is no problem and works as expected. Then, I send a "write the memory page", also no problem as long as I use a fixed page address.

I have trouble to calculated the address during flash process for each page. I'm not sure if the "write memory page" command uses word or byte addressing.

When I tried to write one page at the time to different locations I found the following page address locations:

	Write Memory Page Cmd
Page	Addr 				Range in Memory in Byte
1	0x0000				0x0000-0x003F
2	0x0020				0x0040-0x007F
3	0x0040				0x0080-0x00BF
4	0x0060				0x00C0-0x00FF
5	0x0100				0x0100-0x013F
6	0x0120				0x0140-0x017F
7	0x0140				0x0180-0x01BF
8	0x0160				0x01C0-0x01FF
9	0x0200				0x0200-0x023F
10	0x0220				0x0240-0x027F

...and so on.

If I send the 16 bit address only in WORD count, then I lost 4 pages after 4 pages written.
Memory content looks like this then:
Page1Page2Page3Page4Page9Page10Page11Page12...and so on.

Page5-8 is lost because address count was 0x0080, 0x00A0, 0x00C0 and 0xE0. Which seems are no valid addresses for "write memory page" command.

So how do I calculate this address?
I would appreciate any help.

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

Looking at the 12/03 ATmega8 data sheet, table 93 on page 224 said the page size is 32 words per page and 128 pages total. The value 32 takes 5 bits to represent it and 128 takes 7 bits.

The Serial Programming Instruction Set on table 98 of page 235 gives the format of the Write Program Memory Page command.

Byte 2 is:
0000 aaaa (where aaaa is the address high bits)

Byte 3 is:
bbbx xxxx (where bbb is the address low bits)

Byte 2 and 3 of the Write Program Memory Page command has the 7 bit page address.

If this command used byte oriented page addresses, then it would require an 8 bit page word, which is not the case. Therefore, it must be a word page address. This assumes that if they were using 32 bytes per page instead of 32 words per page, then there would be 256 pages total.

Because the address of the contents of the page is not technically part of the page address, they could use a 5 bit 32 words per page, or a 6 bit 64 bytes per page addressing scheme. Because the serial programming Load Program Memory Page instruction has 5 bits, then it must be using word addressing (it only writes 1 byte of the word to the same 5 bit address at a time, low byte first then high byte).

A 7 bit page address with a 5 bit content address (12 bits total) has a maximum value of 4096. Since there are 4096 words in the ATmega8, this confirms the contents are addressed as words.

The SPM instruction used with the SPMCR register also writes word oriented pages with a 7 bit page address.

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

Load Program Memory Page instruction uses word addressing thats sure and works. Normally the address counter is the same for content and page. For page addressing the target controller ignores the content address bits.

But, when we count in words for page adressing, I would expect something like this:

Page - Address
1 = 0x0000
2 = 0x0020
3 = 0x0040
4 = 0x0060
5 = 0x0080
6 = 0x00A0
7 = 0x00C0
8 = 0x00E0
9 = 0x0100
10 = 0x0120
and so on...

But I found that the page address is invalid if bit 7 in byte 3 from Write Program Memory Page is set.

See the two attached files what is the result when I use a word addressing.

Btw: I tried three ATmega8 targets, always same behavior.

Last Edited: Mon. Apr 11, 2005 - 07:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made a log for protocol version 1 running on my STK500.

50 20 	Enter Prog Mode
55 00 00 20 Load Page Address 0x0000 	
64 00 40 46 Prog Page 1
32 C0 4B C0 4A C0 49 C0 48 C0 47 C0 47 C0 45 C0 44 C0 43 C0 42 Page Data 64 Byte
20 Sync_CRC_EOP	
55 20 00 20 Load Page Address 0x0020
64 00 40 46 Prog Page 2
AA C3 A9 C3 A8 C3 65 C3 66 C3 68 C3 A4 C3 68 C3 6A C3 61 C3 60 Page Data 64 Byte	
20 Sync_CRC_EOP
55 40 00 20 Load Page Address 0x0040
64 00 40 46 Prog Page 3
0D 92 A0 36 B1 07 D9 F7 10 E0 A0 E6 B0 E0 01 C0 1D 92 A1 36 B1 Page Data 64 Byte
20 Sync_CRC_EOP	
55 60 00 20 Load Page Address 0x0060
64 00 40 46 Prog Page 4
60 00 80 91 60 00 88 23 E1 F7 08 95 5F 9B FE CF 8C B1 99 27 08 Page Data 64 Byte
20 Sync_CRC_EOP
55 80 00 20 Load Page Address 0x0080
64 00 40 46 Prog Page 5
87 B3 8C 62 87 BB 81 E5 8D B9 C2 9A 82 E0 D7 DF C2 98 82 E0 D4 Page Data 64 Byte
20 Sync_CRC_EOP
55 A0 00 20 Load Page Address 0x00A0
64 00 40 46 Prog Page 6
84 30 91 05 1C F4 02 97 3C F4 03 C0 06 97 4C F0 0D C0 8D B1 8C Page Data 64 Byte
20 Sync_CRC_EOP
55 C0 00 20 Load Page Address 0x00C0
64 00 40 46 Prog Page 7
08 95 8F B9 77 9B FE CF 8F B1 99 27 08 95 0F 93 1F 93 8C 01 81 Page Data 64 Byte
20 Sync_CRC_EOP
55 E0 00 20 Load Page Address 0x00E0
64 00 40 46 Prog Page 8
BB 27 DF DF BB 27 A1 2F 90 2F 8F 2D DA DF 8E 2D D8 DF 99 27 1F Page Data 64 Byte
20 Sync_CRC_EOP
55 00 01 20 Load Page Address 0x0100

So Write Memory Page uses for sure word addressing, and 0x8, 0x0A, 0x0C and 0x0E are valid page addresses.

The problem seems to be in my code then :(

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

Your page tables should start with page 0, not page 1.
page 0 = 0x0000
page 1 = 0x0020
page 2 = 0x0040
page 3 = 0x0060

I have never written a program that serial programs an ATmega, but I am confused by what I saw in your version 1 protocol log. I assume the values shown in your log are hexadecimal.

From the ATmega8 documentation (table 98 page 235 12/03) I would expect to see something more like this (where zz = programming data):

AC 53 00 00 Enter program mode

40 00 00 zz Load low byte to page word 0
48 00 00 zz Load high byte to page word 0
.....
40 00 1F zz Load low byte to page word 31
48 00 1F zz Load high byte to page word 31
4C 00 00 00 Write all 32 loaded page words into page 0

40 00 00 zz Load low byte to page word 0
48 00 00 zz Load high byte to page word 0
.....
40 00 1F zz Load low byte to page word 31
48 00 1F zz Load high byte to page word 31
4C 00 00 20 Write all 32 loaded page words into page 1
etc.

The ..... represents the low/high pairs of Load Program Memory Page instructions to load the other page words 1 through 30 with programming data bytes zz (it would take too much space to show all 64 low/high byte writes to each of the 32 page words). All serial programming instructions are 4 bytes and the above values are in hex, even though they are not proceeded by the 0x prefix.

I can not figure out what the values in your version 1 protocol log mean.

The Serial Programming Algorithm section on page 233 explains the rest of the details. Things like when sending the 3rd byte of the
AC 53 00 00 Enter program mode instruction, the 53 value must echo back or else you need to start over again.

Last Edited: Mon. Apr 4, 2005 - 05:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Your page tables should start with page 0, not page 1.

Sorry for confusing, page 1 is the first page starting at 0x0000.
Quote:
I can not figure out what the values in your version 1 protocol log mean.

The log from version 1 is NOT the data stream from SPI. It's a log from AVR-Studio to STK500 protocol version 1 via RS232 in hexadecimal.

Quote:
4B 00 00 00 Write all 32 loaded page words into page 0

I think you mean 4C 00 00 00, from the table in my mega8 datasheet(Rev. O, page 237 10/04)

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

Mr MIC wrote:
I think you mean 4C 00 00 00, from the table in my mega8 datasheet(Rev. O, page 237 10/04)

You are quite correct. A big DUH on my part. I have corrected it.

I found application note AVR061, which explains the type of programming you are using (the old protocol standard anyway). The addressing (word or byte) would be entirely determined by the protocol and it may not be based on the regular programming conventions. The type of serial programming from the data sheet I was talking about could only possibly work with the STK500 0x56 Universal Command. I will work through the 061 application note later and get back to you.

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

A snippet of code tells more than a thousand words...

void flash_load_byte(uint8_t byte, uint16_t offset)
{
	send_byte(0x40 | (((offset&1))<<3));
	send_byte(0x00);
	send_byte((offset>>1)&0x1F);
	send_byte(byte);
}

void flash_write_page(uint16_t offset)
{
	send_byte(0x4C);
	send_byte(*(((uint8_t*)&offset)+1)>>1);
	send_byte((offset>>1)&0xE0);
	send_byte(0x00);

	while (busy())
		;
}

At least this is how I've done it. 'offset' is the offset in _bytes_. I hope this will help you. I have to admit that I hadn't had time to test the code that much, so it's possible that it might not work. And I wrote this code to program a Mega48, altough I've checked with the datasheet and it should be the same procedure as for the Mega8.

These are some lines that show how to use the functions:

// Fill the page with data
for (i=0;i<64;i++)
    flash_load_byte(flash_data[i], i);

// Finally, write the page to the Flash
flash_write_byte(i-1);

// To load the next page 'i' would start at 64...
for (i=64;i<128;i++)
    ...

btw, I assume you have done a "Programming Enable" and checked the return value?

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

Thanks for you help and code, I will try.

Quote:
I assume you have done a "Programming Enable" and checked the return value?

Yes, it's done and reports an error if there is no device connected. Also all other operations works well (R/W Eeprom, R/W Fuses, R/W Locks, R Flash Memory, Erase Device...).

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

Sorry, it took me awhile to realize what you were asking for and get myself on the same page (pun intended).

Looking at the AVR061 application note, command 0x42 Set Device Programming Parameters wants a 16 bit value of the page size in bytes and a 32 bit FLASH size in bytes:

1 byte pagesizehigh - Page size in bytes for pagemode parts, High Byte of 16- bit value.
1 byte pagesizelow - Page size in bytes for pagemode parts, Low Byte of 16- bit value.
You need to set pagesizehigh = 0 and pagesizelow = 0x40 which is 64 decimal bytes per page.

1 byte flashsize4: FLASH size in bytes, byte 4 (High Byte) of 32-bit value.
1 byte flashsize3 FLASH size in bytes, byte 3 of 32-bit value.
1 byte flashsize2 FLASH size in bytes, byte 2 of 32-bit value.
1 byte flashsize1 ; FLASH size in bytes, byte 1 (Low Byte) of 32-bit value.
You need to set flashsize4 = 0, flashsize3 = 0, flashsize2 = 0x20 and flashsize1 = 0. This will make the 32 bit value 0x00002000 which is 8192 decimal FLASH bytes.

BTW, there are other 0x42 parameters to set.

The 0x64 command Program Page has a bunch of parameters:

1 byte bytes_high: High byte of data block size.
1 byte bytes_low: Low byte of data block size.
1 byte memtype: Memory type: “E” = EEPROM, “F” = FLASH (0x46 is an ASCII F)
a full block of data: Data to program into FLASH or EEPROM.

It looks like it would be 0x64, 0x00, 0x40, 0x46, low data byte, high data byte, low data byte, high data byte, .... (64 data bytes total).

From the note in the 0x55 Load Address command, it appears this command is used with the 0x64 command Program Page and 0x74 command Read Page. Its parameters are:

1 byte addr_low: LSB byte of address
1 byte addr_high: MSB byte of address

For the reasons below, I suspect your page value in the 0x55 command is wrong.

There is no indication of exactly what units value the address uses (bytes or words, on a page boundary or an arbitrary page number). The application note should really clarify this. Going by the 0x42 Set Device Programming Parameters for pagesize and flashsize we can make some assumptions. Since flashsize is a 32 bit number, a 0x55 command 16 bit address used as a byte address, will never be able to completely address this 32 bit flashsize number. However, a 0x42 command 16 bit page size in bytes combined with a 0x55 command 16 bit address will be able to generate up to a 32 bit flashsize value. In other words, it appears that if the address in the 0x55 command was in bytes, it would have to be 32 bits itself, not 16 bits. Also, if it was just a 7 bit page value, then it would never be able to fully use a 32 bit flashzise address range. It would be silly to create a 32 bit flashsize value if there were no other commands in the STK500 protocol that could match its 32 bit size range.

This makes me think:

1 byte addr_low: LSB byte of address
1 byte addr_high: MSB byte of address

appears to simply be an address starting at 0, then 1, then 2, then 3, etc. My guess is the 0x55 commands should look more like this:

0x55, 0x00, 0x00 for page 0
0x55, 0x01, 0x00 for page 1
0x55, 0x02, 0x00 for page 2
etc.

Of course this all depends on the 0x42 Set Device Programming Parameters command information. If my analysis is correct, then the address value units above represent pages of whatever size is set in the 0x42 command. The STK500 would translate all this back into a 5 bit content address and a 7 bit page address for the chip serial programming.

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

I think you mixed everything up now :wink:

My problem is not RS232 link dependent. There is no problem in communication between AVR-Studio and my programmer hardware. Also I don't work with protocol version 1 but with version 2.

Anyway, the problem is in "Write Memory Page" (4C 00 00 00) command send from host controller to target controller via SPI.

But thanks for your help so far, I will see if I get things up and running.

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

@ cykze

Tried your code, it gives the same result as mine. From 10 pages 4 are not written. Page0-3 are ok, then comes 8 and 9. 4-7 are lost.
:(

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

Are you using the "Data Polling Flash" method described in the datasheet to verify the data in a page, before you start loading the next page?

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

Problem found and fixed. :D
It was never the "Write Page Command" but the read out routine was buggy, so I searched the whole time in wrong code part :oops:
Testing your own code makes you blind sometimes :wink: