AVR231 Bootloader GCC Port not working with Flashsize >64

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

Hey Guys,

I come again to you with a problem with the GCC Port of AVR 231 Bootloader published on this site:

https://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=3330&showinfo=1

But first I wanted to thank you all for being helpful and always pointing me in the right direction, I learned lots and lots by going through the forum and really appreciate the support ;-)

Now the problem: Recently I switched from Atmega645 to Atmega1281 due to codesize going beyond 60k (+4k for bootloader).

I expected the bootloader to be compatible with this µC as the documentation of AVR231 specifies compability with Atmega128.

Apparently though the GCC Port does not support Flash >64k.

First is that memcpy_P is used to load the key tables from flash instead of memcpy_PF. Even switching to memcpy_PF doesn't do the trick, apparently something about the toolchain is already precompiled and therefore does not support the use of ELPM for the extended memory as described here:

http://savannah.nongnu.org/patch/?6352

This is relatively easy to work around with something like this:

void* memcpy_P_far(uint8_t* destination, uint_farptr_t source, uint16_t length)
{
	for (uint8_t i = 0; i < length; i++, source++)
	{
		destination[i] = pgm_read_byte_far(source);
	}
	RAMPZ = 0;
	return destination;
}

as pgm_read_byte_far works fine.

Second problem is the programming of the flash memory. This is done with assembler scripts and those also have been heavily modified in the GCC port, everything regarding RAMPZ and ELPM seems to have been removed.

e.g.:
original release of AVR231

//=============================================================================
// Executes self-programming command

spmSPM:
	movw	r31:r30, r17:r16

	rcall	spmWait

	in		r20, SREG
	cli

	#ifdef __RAMPZ__
		in		r21, RAMPZ
		out		RAMPZ, r18
	#endif

	#ifdef __MEMSPM__
		sts		SPMREG, r22
	#else		
		out		SPMREG, r22
	#endif
	
	#ifdef __RAMPZ__
		espm
	#else
		spm
	#endif
		
	dw		0xFFFF
	nop
		
	#ifdef __RAMPZ__
		out		RAMPZ, r21
	#endif
	
	out		SREG, r20
	ret

spmWait:
	#ifdef __MEMSPM__
		lds		r23, SPMREG
		andi	r23, (1 << SPMEN)
		brne	spmWait	
	#else
		in		r23, SPMREG
		sbrc	r23, SPMEN
		rjmp	spmWait
	#endif

	ret

GCC Port:

//=============================================================================
// Executes self-programming command
//=============================================================================

spmSPM:

spmWait:
    LOAD	r23, SPMCR
	sbrc	r23, SPMEN
	rjmp	spmWait

	movw	ZL, r24

	STORE   SPMCR, r19
	spm
	nop

	clr		r1		// clear the zero reg
	ret

I can understand some of this but have no actual experience with assembler, did someone at some point write a fix for this?

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

Well you need to add RAMPZ handling as it's effectively the upper address bits of the area you are programming (so 0 for the first 64K and 1 for the next 64K). Only thing is that the AVR231 code you are using there is making some assumption about what is in R18. I assume what it's saying is that a 24 bit address is passed in using registers R18:R17:R16. The code also uses an opcode called "ESPM". That is most odd. While larger (>64K) AVRs have two versions of LPM (LPM and ELPM) as far as I know there only ever is one SPM opcode and it's called SPM so I don't know why that code is using something called ESPM in the case where RAMPZ exists.

Certainly the 1281 (and all >64K AVRs) will have RAMPZ available in GCC:

C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.1002\avr8-gnu-toolchain\avr\include\avr>grep -w RAMPZ iom*.
h
iom103.h:#define RAMPZ  _SFR_IO8(0x3B)
iom128.h:#define RAMPZ     _SFR_IO8(0x3B)
iom128.h:/* RAM Page Z select register - RAMPZ */
iom1284.h:#define RAMPZ   _SFR_IO8(0x3B)
iom1284p.h:#define RAMPZ _SFR_IO8(0x3B)
iom1284rfr2.h:#define RAMPZ   _SFR_IO8(0x3B)
iom128a.h:#define RAMPZ   _SFR_IO8(0x3B)
iom128rfa1.h:#define RAMPZ                           _SFR_IO8(0x3B)
iom128rfa1.h:  /* RAMPZ */
iom128rfr2.h:#define RAMPZ   _SFR_IO8(0x3B)
iom16u4.h:#define RAMPZ _SFR_IO8(0x3B)
iom2564rfr2.h:#define RAMPZ   _SFR_IO8(0x3B)
iom256rfr2.h:#define RAMPZ   _SFR_IO8(0x3B)
iom32u4.h:#define RAMPZ _SFR_IO8(0x3B)
iomxx0_1.h:#define RAMPZ   _SFR_IO8(0X3B)

It's the very last of those that will be used for 1281.

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

Well my bad,

I just checked the original files from the port and everything in there is fine, my predecessor just removed anything regarding RAMPZ from our project to make the bootloader as small as possible. I put it back in and now it works like a charm. Thx anyway, at least I learned a lot about assembler :-)