Hi all,
I'm using AVR-GCC version 4.9.4 with avr-libc version 2.0.0 and have run into a strange problem with reading a WORD (uint16_t) from eeprom. Specifically, wrong data is returned. Same code, compiler and libc works just fine on a 328P or MEGA2560.
This is the specific code that I use to read the EEPROM:
// send IR command from array
// *cmd -> pointer to timing data array
void sendCmd (const uint16_t *cmd)
{
uint16_t idx; // data block index
uint16_t data; // read IR pulse width info
while (busy); // in case ISR is busy
idx = 0; // init index
while (1) {
data = eeprom_read_word ((const uint16_t *)(cmd + idx)); // read data
idx++;
if (data == 0) { // zero == end of table
break;
} else {
cli(); // disable interrupts
busy = 1; // flag ISR busy
enable = (data >> 15); // bit 15 is IR on/off bit
count = (data << 1); // (count * 2) for full cycle
sei(); // enable interrupts
while (busy); // wait while ISR is done sending
}
}
}
The data I am reading:
///////////////////////////////////////////////////////////////////////////////
// Sony camera shutter release code 0xB4B8F (focus and shoot)
///////////////////////////////////////////////////////////////////////////////
static const uint16_t shutter1[] EEMEM = {
// header
0x8060, 0x0018,
// data
0x8030, 0x0018, 0x8018, 0x0018, 0x8030, 0x0018, 0x8030, 0x0018, // B
0x8018, 0x0018, 0x8030, 0x0018, 0x8018, 0x0018, 0x8018, 0x0018, // 4
0x8030, 0x0018, 0x8018, 0x0018, 0x8030, 0x0018, 0x8030, 0x0018, // B
0x8030, 0x0018, 0x8018, 0x0018, 0x8018, 0x0018, 0x8018, 0x0018, // 8
0x8030, 0x0018, 0x8030, 0x0018, 0x8030, 0x0018, 0x8030, 0x01C8, // F
// end of data block
0x0000,
};
...and the ISR that does the work:
// IR carrier generator & timer
ISR (TIMER0_COMPA_vect)
{
if (count) {
count--;
enable ? IO_INP = IR_BIT : 0;
} else {
busy = 0; // flag ISR is done
}
}
As I said, on any other processor, this code works fine. If I instead put the data into flash and use pgm_read_word it also works fine. ONLY eeprom and ONLY reading a word fails.
Anyone have any ideas as to why this might be?
By the way, I've "solved" the problem by writing a generic eeprom read function (see below) but I shouldn't have to do this.
// universal eeprom READ
template <class T> T eepromRead (const T *addr)
{
uint8_t x;
uint8_t *ptr;
T value;
x = sizeof (T);
ptr = ((uint8_t *)(void *)(&value));
while (x--) {
*(ptr + x) = (eeprom_read_byte ((uint8_t *)(addr) + x));
}
return value;
}
Any assistance will be greatly appreciated. Thanks!