I have an ATXMega64A3U, and I want to read some calibration values in software (DAC and ADC calibration).
The code I have works fine if the appliation starts up directly (no flashloader --> fuse bits set to "application reset"). However, if I start the application through a flashloader (which is the default case, unless I debug my code), the LPM instruction reads nonsensical values from the calibration row. Those nonsensical values are always the same for each Byte I read, and they are always consistent. I also get the same rubbish if I step-by-step debug through my code - I can accept that and blame it on some timing issues. But I should get the correct values from the NVM controller, regardless if the application got started directly (reset vector = application start) or through a flashloader (which just does a JMP 0x0000) - right?
Is there anything that could cause the NVM to behave this way?
Here's the code I use to read one calibration byte (ASM, the rest of my application is C):
#include <avr/io.h> .global NVM_fn_ReadByte .type NVM_fn_ReadByte, @function NVM_fn_ReadByte: /* With avr-gcc: u8NVM_CMD in r24, u16Address in r22:r23 (LSB:MSB). Return value (uint8_t) in r24. */ push r0 in r0, SREG /* Remember SREG */ cli /* Disable interrupts */ movw ZL, r22 /* Copy u16Address to Z-pointer */ sts NVM_CMD, r24 /* Copy CMD byte to NVM_CMD register */ lpm r24, Z sts NVM_CMD, r1 /* Set NVM_CMD to zero (important!) */ out SREG, r0 /* Restore SREG */ pop r0 ret
Here's the header, which I include in any C file which uses this function (pretty trivial):
#include <stdint.h> /* Read one byte from NVM. */ uint8_t NVM_fn_ReadByte(uint8_t u8NVM_CMD, uint16_t u16Address);
And a snippet, where I call the calibration values for both DAC channels on the chip:
/* Load DAC calibration values */ DACB_CH0OFFSETCAL = NVM_fn_ReadByte(NVM_CMD_READ_CALIB_ROW_gc, 0x0032); DACB_CH0GAINCAL = NVM_fn_ReadByte(NVM_CMD_READ_CALIB_ROW_gc, 0x0033); DACB_CH1OFFSETCAL = NVM_fn_ReadByte(NVM_CMD_READ_CALIB_ROW_gc, 0x0036); DACB_CH1GAINCAL = NVM_fn_ReadByte(NVM_CMD_READ_CALIB_ROW_gc, 0x0037);
Thanks a lot!