Problem with reading eeprom WORD on a Tiny85

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

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!

 

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

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

How are you determining the "failure"?  What value are you reading?  What value do you expect?  What is the specific address being read?

 

If I were concerned, I'd reduce to a small complete test program.  Then we can all play along using the home game.  The .LST files for both can then be examined and compared.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Krupski wrote:
I'm using AVR-GCC
Krupski wrote:
template T

Oh, my -- C++ on a Tiny85?  That is hard for us Luddites.  (or is that neo-Luddites?)

 

So, is this Arduino?  Is there any conflict with timer0 use?  Does the simple C sanity-check program have the same results?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

I’m suspecting your addresses might not be what you want. Run the code in the simulator and see where it actually reads/writes the eeprom data. I’m thinking the data gets overlapped due to word/byte problems.
Your template code works as it does byte addressing.

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

variables non volatile although they are used in both the main program and the interrupt?

Little vs big endian, were high and low byte locations do not match the expectations?

We only get to see the data that is supposedly read back, not the data that is initially stored, and what is expected to be read back.....

pointers that get messed up in the ISR?

as said timer conflicts?

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

Silly question but after you build and you end up with project_name.hex and project_name.eep you are putting the .eep file into the EEPROM as well as the .hex into the flash aren't you?

 

Also show your invocation of sendCmd(). Presumably it is something like:

sendCmd(shutter1);

??

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

theusch wrote:

How are you determining the "failure"?  What value are you reading?  What value do you expect?  What is the specific address being read?

 

If I were concerned, I'd reduce to a small complete test program.  Then we can all play along using the home game.  The .LST files for both can then be examined and compared.

 

Well.......  the whole thing is a small IR remote transmitter.  I am programming in straight C/C++ and compiling with a Makefile.  Therefore, I have complete control of what interrupts and timers are used, etc...

 

I determine the failure by the simple fact that the transmitter doesn't work when using eeprom and eeprom_read_word.  blush

 

I can write up a small serial output function to get the info you asked about, and I can also add AVR-OBJDUMP to the makefile to generate a LST file.

 

Be back in a while with the info.

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

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

Like I said, are you programming the EEP file? Also, if you then change the code and reprogram the flash do you have the EEAVE fuse set? (If not then you have to program both HEX and EEP files every time).

 

(if you change the code in flash it starts with a "chip erase", usually that erases BOTH the flash and the EEPROM, the EESAVE fuse prevents the EEPROM from being touched).

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

Krupski wrote:
Well....... the whole thing is a small IR remote transmitter. I am programming in straight C/C++ and compiling with a Makefile. Therefore, I have complete control of what interrupts and timers are used, etc... I determine the failure by the simple fact that the transmitter doesn't work when using eeprom and eeprom_read_word. blush I can write up a small serial output function to get the info you asked about, and I can also add AVR-OBJDUMP to the makefile to generate a LST file. Be back in a while with the info.

So after all that, is that an affirmation or rejection of

theusch wrote:
reduce to a small complete test program. Then we can all play along using the home game. The .LST files for both can then be examined and compared.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.