Saving User Data in Program Space

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

In a previous post I asked if it was possible to make use of unused program flash to store user code. Here is how I actually made it work. There are two pieces to the task, a bootloader that supports sharing access to its' SPM functions with the application, and a way for the application to actually call these functions. Here is the first part, a snglet of my xboot based bootloader:

typedef void (*fptr)(void); 

#define JMP_TABLE_ENTRY(x) __asm__ __volatile__ ("jmp "#x)

void jumptable_fn(void) __attribute__ ((naked));
void jumptable_fn(void) {
	JMP_TABLE_ENTRY(SP_ReadByte);							
	JMP_TABLE_ENTRY(SP_ReadWord);							
	JMP_TABLE_ENTRY(SP_ReadCalibrationByte);				
	JMP_TABLE_ENTRY(SP_ReadFuseByte);						
	JMP_TABLE_ENTRY(SP_WriteLockBits);						
	JMP_TABLE_ENTRY(SP_ReadLockBits);						
	JMP_TABLE_ENTRY(SP_ReadUserSignatureByte);				
	JMP_TABLE_ENTRY(SP_EraseUserSignatureRow);				
	JMP_TABLE_ENTRY(SP_WriteUserSignatureRow);				
	JMP_TABLE_ENTRY(SP_EraseApplicationSection);			
	JMP_TABLE_ENTRY(SP_EraseApplicationPage);			       
	JMP_TABLE_ENTRY(SP_EraseWriteApplicationPage);
	JMP_TABLE_ENTRY(SP_WriteApplicationPage);
	JMP_TABLE_ENTRY(SP_LoadFlashWord);
	JMP_TABLE_ENTRY(SP_LoadFlashPage);
	JMP_TABLE_ENTRY(SP_ReadFlashPage);
	JMP_TABLE_ENTRY(SP_EraseFlashBuffer);
	JMP_TABLE_ENTRY(SP_EraseBootPage);
	JMP_TABLE_ENTRY(SP_EraseWriteBootPage);
	JMP_TABLE_ENTRY(SP_WriteBootPage);
	JMP_TABLE_ENTRY(SP_ApplicationCRC);
	JMP_TABLE_ENTRY(SP_BootCRC);
	JMP_TABLE_ENTRY(SP_LockSPM);
	JMP_TABLE_ENTRY(SP_WaitForSPM);
}

const fptr jumptable[] __attribute__((progmem)) = { 
	jumptable_fn+0,
	jumptable_fn+4,
	jumptable_fn+8,
	jumptable_fn+12,
	jumptable_fn+16,
	jumptable_fn+20,
	jumptable_fn+24,
	jumptable_fn+28,
	jumptable_fn+32,
	jumptable_fn+36,
	jumptable_fn+40,
	jumptable_fn+44,
	jumptable_fn+48,
	jumptable_fn+52,
	jumptable_fn+56,
	jumptable_fn+60,
	jumptable_fn+64,
	jumptable_fn+68,
	jumptable_fn+72,
	jumptable_fn+76,
	jumptable_fn+80,
	jumptable_fn+84,
	jumptable_fn+88,
	jumptable_fn+92,
};	

// Main code
int main(void)
{
	uint32_t pJmpTable;

	//save the address in program space of the jump table
 pJmpTable = (uint32_t)&jumptable_fn;

 GPIOR0 = pJmpTable & 0x000000ff;  //LSB
 GPIOR1 = (pJmpTable >> 8) &0xff;  //MSB
 GPIOR2 = (pJmpTable >> 16) &0xff; //extended pointer should be 2, but will be zero 

....

The next part is a set of stub routines in the application that actually call these functions through the jumptable. See the attached file:

Note that the compiler generated a 16 bit pointer to the jump table and we need a full 24 bit pointer to actually call the jump functions in the table. However we DO know what the actual upper byte of the pointer IS. (On the xmega256 it is 0x02). I didn't implement a stub for every SPM function, I only needed the functions that WRITE to the program space. We can read from the program space using the available FAR program space macros in avrlibc.

Attachment(s): 

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

Hi, I don't understand this.

Why do you need 2 jump tables?

Why do you need jump tables at all?

avrfreaks does not support Opera. Profile inactive.

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

There is only one jump table created. How else would you code an indirect jump to functions in the boot space? The bootloader ONLY passes to the application the start address of the jump table. The application 'calls' (actually jumps) to the function by 'returning to' the address of the table entry pushed onto the stack.