I'm using the XMega128a1 bootloader hack (AVR109) that damien_d posted a while back. I want to call the sp_driver.S functions from application code. I'm running on Linux so I don't have easy access to a debugger.
I took a look at the bootloader FAQ and nothing jumped out to me there as far as doing something wrong. I know that it is recommended not to hardcode a jump table, but that is what I am trying right now because I can't modify the bootloader under Linux. I will clean it up once I can use the MKII programmer with avrdude under Linux.
I'm trying to read and write to the User Signature Row. The application code looks like this:
////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// static void LoadAppTableWord(uint16_t tableAddress, uint8_t lowByte, uint8_t highByte) { /* Perform word load. */ SP_LoadFlashWord(tableAddress, ((uint16_t) highByte << 8) | lowByte); /* Wait for NVM to finish. */ SP_WaitForSPM(); } ///////////////////////////////////////////////////////////////////////////////////// // assumes address is 6 bytes ///////////////////////////////////////////////////////////////////////////////////// void write_mac_address(uint8_t *address) { /* Erase the user signature row. */ SP_EraseUserSignatureRow(); /* Wait for NVM to finish. */ SP_WaitForSPM(); //load in mac address LoadAppTableWord(0, address[0], address[1]); LoadAppTableWord(2, address[2], address[3]); LoadAppTableWord(4, address[4], address[5]); /* Write the Flash buffer to the user signature row. */ SP_WriteUserSignatureRow(); /* Wait for NVM to finish. */ SP_WaitForSPM(); } ///////////////////////////////////////////////////////////////////////////////////// // assumes address is 6 bytes ///////////////////////////////////////////////////////////////////////////////////// void read_mac_address(uint8_t *address) { int i; for(i=0;i<6;i++) { address[i] = SP_ReadUserSignatureByte(i); } }
And the jump table looks like this:
.global SP_ReadByte SP_ReadByte: jmp 0x20a9c .global SP_ReadWord SP_ReadWord: jmp 0x20aa8 .global SP_ReadCalibrationByte SP_ReadCalibrationByte: jmp 0x20ab6 .global SP_ReadUserSignatureByte SP_ReadUserSignatureByte: jmp 0x20aba .global SP_ReadFuseByte SP_ReadFuseByte: jmp 0x20abe .global SP_WriteLockBits SP_WriteLockBits: jmp 0x20ad4 .global SP_ReadLockBits SP_ReadLockBits: jmp 0x20adc .global SP_EraseUserSignatureRow SP_EraseUserSignatureRow: jmp 0x20ae2 .global SP_WriteUserSignatureRow SP_WriteUserSignatureRow: jmp 0x20aea .global SP_EraseApplicationSection SP_EraseApplicationSection: jmp 0x20af2 .global SP_EraseApplicationPage SP_EraseApplicationPage: jmp 0x20afa .global SP_LoadFlashWord SP_LoadFlashWord: jmp 0x20b06 .global SP_LoadFlashPage SP_LoadFlashPage: jmp 0x20bca .global SP_ReadFlashPage SP_ReadFlashPage: jmp 0x20b10 .global SP_WriteApplicationPage SP_WriteApplicationPage: jmp 0x20b32 .global SP_EraseWriteApplicationPage SP_EraseWriteApplicationPage: jmp 0x20b3e
There is a header file with prototypes for all the SP_xxx functions. I'm not up much on assembly these days, but the output from GCC seems OK. Any thoughts on why this doesn't work?