I am wondering how the ATTiny, specifically the ATTiny24 stores 32 bit unsigned ints in memory. I'm trying to take a 32 bit value and write it to a 32 bit location in the EEPROM. I have attempted to use a simple mask, but every time I try, I get the lower two bytes (lsb) correctly and the upper two bytes are all zeros. For example, when I try to write: 0x12345678 the output is: 0x00005678. Is there a setting in Atmel Studio I need to set, or do I need to use another method other than masking.
Ultimately I want to be able to read a 32 bit counter value and write it to a specific location in the EEPROM. I am working on modifying an existing circuit and thus do not have the luxury to debug with a serial output.
Code Snippets:
In main:
unsigned long test_val = 305419896; //0x12345678
EEprom_Long_Write(0x25,test_val);
Functions:
EEprom_Long_Write:
void EEprom_Long_Write(unsigned char eeadr, unsigned long EE_Data)
{
unsigned char temp=0;
unsigned char count= eeadr + 3;
unsigned long mask=0;
unsigned char position=24;
while (eeadr <= count)
{
mask = ((1<<8)-1) << position;
temp = (EE_Data & mask) >> position;
EEPROM_write(eeadr, temp);
position = position-8;
eeadr++;
}
}
EEPROM_write:
void EEPROM_write(unsigned char ucAddress, unsigned char ucData)
{
while(EECR & (1<<EEPE)); //Wait for completion of previous write
EECR =(0<<EEPM1) | (0>>EEPM0); // Set Programming mode
EEARL = ucAddress; // Setup address and data registers
EEDR = ucData; // Load Data Register
EECR |= (1<<EEMPE); // Write logical one to EEMPE
EECR |= (1<<EEPE); // Start eeprom write be setting EEPE
}
You fell into the pit of integer promotion and coercion. ((1<<8)-1)
is processed as int
, not long
(better: uint32_t
). On AVR, int
has the minimum size allowed by the standard: 16 bits.
As is is anyway too complicated, you can use the following:
uint8_t shift = 32U; // enough is enough
do {
shift -= 8U;
EEPROM_write(eeadr++, (uint8_t)(EE_Data >> shift));
} while ( shift ) ;
This safes you one additional shift and the explicit masking and some registers.
Note my use of stdint.h
types (you have to include the header, of course). You should correct all declarations accordingly. The cast to uint8_t
implies masking.