dantheman
dantheman

Reputation: 275

sprintf is outputting some strange data

I am working an embedded project which involves reading/writing a struct into EEPROM. I am using sprintf to make it easy to display some debugging information.

There are two problems with this code for some reason. The first; sprintf is printing a very strange output. When I print 'addr++' it will follow a pattern '0, 1, 2, 3, 4, 32, ...' which doesn't make sense.

void ee_read(char * buf, unsigned int addr, unsigned int len) {
    unsigned int i;

    sprintf(bf1, "Starting EEPROM read of %u bytes.\r\n", len); // Debug output
    debugr(bf1);

    IdleI2C1();
    StartI2C1();
    WriteI2C1(EE_ADDR | EE_W);
    IdleI2C1();
    WriteI2C1((unsigned char)addr>>8); // Address to start reading data from
    IdleI2C1();
    WriteI2C1((unsigned char)addr&0xFF);
    IdleI2C1();
    RestartI2C1();
    WriteI2C1(EE_ADDR | EE_R);
    IdleI2C1();
    for (i=0; i<len; i++) {
        buf[i] = ReadI2C1(); // Read a byte from EEPROM

        sprintf(bf1, "Addr: %u Byte: %c\r\n", addr, buf[i]); // Display the read byte and the address
        debugr(bf1);

        addr++; // Increment address

        IdleI2C1();
        if (i == len-1) { // This makes sure the last byte gets 'nAcked'
            NotAckI2C1();
        } else {
            AckI2C1();
        }
    }
    StopI2C1();
}

The output from the above is here: https://gist.github.com/3803316 Please note that the about output was taken with %x for the address value (so addr is hex)

The second problem, which you may have noticed with the output, is that it doesn't stop when i > len. It continues further than the output I have supplied, and doesn't stop until the microcontroller's watch dog restarts.

Edit: Calling the function

Location loc;
ee_read(&loc, 0, sizeof(Location));

Declarations:

struct location_struct {
    char lat[12]; // ddmm.mmmmmm
    char latd[2]; // n/s
    char lon[13]; // dddmm.mmmmmm
    char lond[2]; // e/w
    char utc[11]; // hhmmss.sss
    char fix[2]; // a/v
};

typedef struct location_struct Location;

char bf1[BUFFER_SIZE];

I don't think it's a race condition. I disable the interrupts which use bf1. Even then, it would corrupt the whole debug string if that happened, and it certainly wouldn't be so repeatable.

Edit The value of addr starts as zero, which can be seen here: https://gist.github.com/3803411

Edit What this is supposed to do it copy the location structure byte by byte into the EEPROM, and then recall it when it is needed.

Closure So I never did solve this problem. The project moved away from the EEPROM, and I have since changed OS, compiler and IDE. It's unlikely I will replicate this problem.

Upvotes: 2

Views: 783

Answers (1)

paxdiablo
paxdiablo

Reputation: 881633

I'll tell you one thing wrong with your code, this line:

(unsigned char)addr>>8

doesn't do what you seem to need.

It converts the value in addr into an unsigned char which (assuming 8-bit char and either 16-bit int or only using the lower 16 bits of a wider int), will will always give you the lower eight bits.

If you then right shift that by eight bits, you'll always end up with zero.

If your intent is to get the upper eight bits of the address, you need to use:

(unsigned char)(addr>>8)

so that the shift is done first.

Upvotes: 1

Related Questions