Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Code Optimization

Status
Not open for further replies.

desgin

Full Member level 1
Joined
Apr 7, 2017
Messages
96
Helped
1
Reputation
2
Reaction score
1
Trophy points
8
Activity points
813
Hello All,

I am writing code for EEPROM Write and EEPROM read but code is getting so long.
So, I need your help for Code Optimization.
Here, I have to write 5000 bytes in EEPROM one by one.
  • Some Variables/Parameters are of 4 bytes and some are 2 bytes.
  • Only Variables names & location number of EEPROM is getting changed
Here is code:
Code:
      uint32_t write_var;
     
      write_var = (uint32_t)(Sensor1_value);                                     // 4 Bytes data
      EEPROM_Write_data[0] = (write_var>> 24) & (0x000000FF);
      EEPROM_Write_data[1] = (write_var>> 16) & (0x000000FF);
      EEPROM_Write_data[2] = (write_var>> 8) & (0x000000FF);
      EEPROM_Write_data[3] = (write_var) & (0x000000FF);

      write_var = (uint32_t)(Sensor2_value);                                   // 4 Bytes data
      EEPROM_Write_data[4] = (write_var>> 24) & (0x000000FF);
      EEPROM_Write_data[5] = (write_var>> 16) & (0x000000FF);
      EEPROM_Write_data[6] = (write_var>> 8) & (0x000000FF);
      EEPROM_Write_data[7] = (write_var) & (0x000000FF);

      write_var = (uint32_t)(Sensor3_value);                                           // 2 Bytes data
      EEPROM_Write_data[8] = (uint8_t)((write_var>> 8) & (0x00FF));
      EEPROM_Write_data[9] = (uint8_t)((write_var) & (0x00FF));
      .
      .
      .
      .
      .
      write_var = (uint32_t)(Sensor1000_value);                                    // 4 Bytes data
      EEPROM_Write_data[4997] = (write_var>> 24) & (0x000000FF);
      EEPROM_Write_data[4998] = (write_var>> 16) & (0x000000FF);
      EEPROM_Write_data[4999] = (write_var>> 8) & (0x000000FF);
      EEPROM_Write_data[5000] = (write_var) & (0x000000FF);
Please help me
its urgent!
Thanks :) in advance!
 
Last edited by a moderator:

Since its urgent, easiest way for you is to convert all 2byte sensor value to 4byte.
Code:
uint32_t Sensor1_value;
.
.
.
.

#define Sensorvalue(y) ((uint32_t)Sensor##y##_value)
uint8_t EEPROM_Write_data[];
void updateEEPBuffer(void){
    uint32_t write_var;

    for(uint8_t i =0,j=1; i<5000; i+=4,j++){
        write_var = Sensorvalue(j); // 4 Bytes data
        EEPROM_Write_data[i] = (write_var>> 24) & (0x000000FF);
        EEPROM_Write_data[i+1] = (write_var>> 16) & (0x000000FF);
        EEPROM_Write_data[i+2] = (write_var>> 8) & (0x000000FF);
        EEPROM_Write_data[i+3] = (write_var) & (0x000000FF);
    }
}
 
Last edited by a moderator:

Since its urgent, easiest way for you is to convert all 2byte sensor value to 4byte.
Code:
uint32_t Sensor1_value;
.
.
.
.

#define Sensorvalue(y) ((uint32_t)Sensor##y##_value)
uint8_t EEPROM_Write_data[];
void updateEEPBuffer(void){
    uint32_t write_var;

    for(uint8_t i =0,j=1; i<5000; i+=4,j++){
        write_var = Sensorvalue(j); // 4 Bytes data
        EEPROM_Write_data[i] = (write_var>> 24) & (0x000000FF);
        EEPROM_Write_data[i+1] = (write_var>> 16) & (0x000000FF);
        EEPROM_Write_data[i+2] = (write_var>> 8) & (0x000000FF);
        EEPROM_Write_data[i+3] = (write_var) & (0x000000FF);
    }
}
Thanks for your quick reply.
but I can not make 2 bytes data to 4 bytes because this 2 bytes data also using in other functions.
 

but I can not make 2 bytes data to 4 bytes because this 2 bytes data also using in other functions.
Other functions use 2 bytes itself.
You just need to allot dummy 2 bytes in EEPROM_Write_data[.i] & EEPROM_Write_data[i+1] while writing. This is done by typecasting.

#define Sensorvalue(x) ((uint32_t)Sensor##x##_value)

and while reading eeprom back at start up, above 2 dummy values gets ignored automatically.

Code:
void updateSensorValfromEEP(void){
    uint32_t read_var;

    for(uint8_t i =0,j=1; i<5000; i+=4,j++){
        read_var = ((uint32_t)EEPROM_Write_data[i]<<24)|((uint32_t)EEPROM_Write_data[i+1]<<16)|((uint32_t)EEPROM_Write_data[i+2]<<8)|((uint32_t)EEPROM_Write_data[i+3]<<0);
        Sensorvalue(j) = read_var; // if Sensorvalue(j) is 2 byte var, only last 2 bytes copied.
    }
}
 
Since its urgent, easiest way for you is to convert all 2byte sensor value to 4byte.
Code:
uint32_t Sensor1_value;
.
.
.
.

#define Sensorvalue(y) ((uint32_t)Sensor##y##_value)
uint8_t EEPROM_Write_data[];
void updateEEPBuffer(void){
    uint32_t write_var;

    for(uint8_t i =0,j=1; i<5000; i+=4,j++){
        write_var = Sensorvalue(j); // 4 Bytes data
        EEPROM_Write_data[i] = (write_var>> 24) & (0x000000FF);
        EEPROM_Write_data[i+1] = (write_var>> 16) & (0x000000FF);
        EEPROM_Write_data[i+2] = (write_var>> 8) & (0x000000FF);
        EEPROM_Write_data[i+3] = (write_var) & (0x000000FF);
    }
}
Thanks for reply.

Here #define Sensorvalue(y) ((uint32_t)Sensor##y##_value) will work fine ?
because #define will work for constant right ?

and some of my sensorvalue variable(parameter) is in uint32_t and some are having data type float too :-(
in that case how this will work ?
please explain!
 
Last edited:

Here #define Sensorvalue(y) ((uint32_t)Sensor##y##_value) will work fine ?
because #define will work for constant right ?
Oh, sorry! yes you are right. It is a mistake. We cannot use token pasting for a variable.

and some of my sensorvalue variable(parameter) is in uint32_t and some are having data type float too :-(
in that case how this will work ?
You can split floating point number to four 8-bit numbers by copying the floating point variable to a union float variable as defined below.

Code:
typedef union {
    uint8_t c[4];
    float f;
} userfloat;

uint32_t Sensorvalue[1250];

userfloat myuniflt;

void updateSensorArray(void){
    Sensorvalue[0] = Sensor1_value; //4byte sensor
    Sensorvalue[1] = Sensor2_value; //2byte sensor
    myuniflt.f = Sensor3_value; //float sensor
    Sensorvalue[2] = ((uint32_t)myuniflt.c[3]<<24)|((uint32_t)myuniflt.c[2]<<16)|((uint32_t)myuniflt.c[1]<<8)|((uint32_t)myuniflt.c[0]<<0);
}

void updateEEPBuffer(void){
    uint32_t write_var;
    uint32_t j = 0;
    for(uint8_t i =0; i<5000; i+=4,j++){
        write_var = Sensorvalue[j]; //tbd
        EEPROM_Write_data[i] = (write_var>> 24) & (0x000000FF);
        EEPROM_Write_data[i+1] = (write_var>> 16) & (0x000000FF);
        EEPROM_Write_data[i+2] = (write_var>> 8) & (0x000000FF);
        EEPROM_Write_data[i+3] = (write_var) & (0x000000FF);
    }
}
 
Last edited:
Hello!

You should learn about casting!
One example:

Code:
typedef struct my_struct{        //    size        sum
    uint8 variable8;            //    1 byte        1
    uint16 variable16;            //    2 bytes        3
    uint32 variable32;            //    4 bytes        7
    uint64 variable64;            //    8 bytes        15
    float variablefloat;        //    4 bytes        19
    double variabledouble;        //    8 bytes        27
} my_struct;

my_struct msinstance;            //    my_struct instance
// Fill the various fields
msinstance.variable8 = 1;
msinstance.variable16 = 2;
etc...
msinstance.variabledouble = 3.1415926;

char * buf = (char *)(&msinstance);

int i;

for(i = 0 ; i < 27 ; ++i) {
    eeprom_write(buf[i]);
}

And doing this, you save yourself endless conversions with shifts.
And reading is the same.
Note that I used a structure in the case all your variables have different formats.
You can do the same with an array. Suppose you have an array of 500 long ints (2000 bytes),
then you can cast your array to char* and send the chars one by one in a loop. No headache.

Dora.

Addendum: in some cases, with some not-so-smart compilers, you have to take care of the
alignment. A good practice is to sort the variables, the biggest first.
 
Oh, sorry! yes you are right. It is a mistake. We cannot use token pasting for a variable.


You can split floating point number to four 8-bit numbers by copying the floating point variable to a union float variable as defined below.

Code:
typedef union {
    uint8_t c[4];
    float f;
} userfloat;

uint32_t Sensorvalue[1250];

userfloat myuniflt;

void updateSensorArray(void){
    Sensorvalue[0] = Sensor1_value; //4byte sensor
    Sensorvalue[1] = Sensor2_value; //2byte sensor
    myuniflt.f = Sensor3_value; //float sensor
    Sensorvalue[2] = ((uint32_t)myuniflt.c[3]<<24)|((uint32_t)myuniflt.c[2]<<16)|((uint32_t)myuniflt.c[1]<<8)|((uint32_t)myuniflt.c[0]<<0);
}

void updateEEPBuffer(void){
    uint32_t write_var;
    uint32_t j = 0;
    for(uint8_t i =0; i<5000; i+=4,j++){
        write_var = Sensorvalue[j]; //tbd
        EEPROM_Write_data[i] = (write_var>> 24) & (0x000000FF);
        EEPROM_Write_data[i+1] = (write_var>> 16) & (0x000000FF);
        EEPROM_Write_data[i+2] = (write_var>> 8) & (0x000000FF);
        EEPROM_Write_data[i+3] = (write_var) & (0x000000FF);
    }
}
I tried to check this code online but float value is not coming correctly!
and in my code, I have almost 700 variables which are having either uint32_t/float to write as 2 bytes/4 Bytes.
Please provide some solution!

Thanks in advance
--- Updated ---

Hello!

You should learn about casting!
One example:

Code:
typedef struct my_struct{        //    size        sum
    uint8 variable8;            //    1 byte        1
    uint16 variable16;            //    2 bytes        3
    uint32 variable32;            //    4 bytes        7
    uint64 variable64;            //    8 bytes        15
    float variablefloat;        //    4 bytes        19
    double variabledouble;        //    8 bytes        27
} my_struct;

my_struct msinstance;            //    my_struct instance
// Fill the various fields
msinstance.variable8 = 1;
msinstance.variable16 = 2;
etc...
msinstance.variabledouble = 3.1415926;

char * buf = (char *)(&msinstance);

int i;

for(i = 0 ; i < 27 ; ++i) {
    eeprom_write(buf[i]);
}

And doing this, you save yourself endless conversions with shifts.
And reading is the same.
Note that I used a structure in the case all your variables have different formats.
You can do the same with an array. Suppose you have an array of 500 long ints (2000 bytes),
then you can cast your array to char* and send the chars one by one in a loop. No headache.

Dora.

Addendum: in some cases, with some not-so-smart compilers, you have to take care of the
alignment. A good practice is to sort the variables, the biggest first.
Thanks for reply & really this is interesting to learn.
But i am unable to compile this code online :-(
Can you please help me little more to work this code into Online compiler.

Thanks in advance :)
 
Last edited:

Hello!

But i am unable to compile this code online :-(

What do you mean by "online"? (I have never compiled anything online. With the
command line, yes, I have, but online, I don't think so)
Beside this, maybe I made errors since I didn't write it in a development environment,
but it looks like close to workable C. I don't think there is too much effort to make it work.

Dora.
 

@doraemon - your 'struct' will result in mis-aligned variables that may well be seen as errors by some compilers without the 'packed' attribute bring used where this is applicable.
Also I suspect that a union is more appropriate on a 'case by case' basis that the OP seems to be using. On the other hand, using a struct to create the whole of the 'EEPROM_write_data' variable rather than as an array would be more "optimal" (if only from a code writing perspective).
(Personal gripe: @desgin I tend to be put of by request for 'urgent' answers as that implies that I need to make up for your bad planning.)
Susan
 
Hello!

your 'struct' will result in mis-aligned variables that may well be seen as errors by some compilers without the 'packed' attribute bring used where this is applicable.

Yes, that's why I wrote the "addendum" afterwards. Usually the alignment is 4 bytes, and if you start with the biggest items (4 bytes or more), then everything is fine. So yes, the structure I wrote is misleading, it should be written top down. Anyway, I'm doing this everytime and I have never bumped into a major problem.

Dora.
 

@doraemon - your 'struct' will result in mis-aligned variables that may well be seen as errors by some compilers without the 'packed' attribute bring used where this is applicable.
Also I suspect that a union is more appropriate on a 'case by case' basis that the OP seems to be using. On the other hand, using a struct to create the whole of the 'EEPROM_write_data' variable rather than as an array would be more "optimal" (if only from a code writing perspective).
(Personal gripe: @desgin I tend to be put of by request for 'urgent' answers as that implies that I need to make up for your bad planning.)
Susan
Thanks for your reply.

Can you please send me working code according to what you suggested because i am not able to compile this code.

Desgin
 

Hi,

Can you please send me working code
This is not how a forum is meant to work .. but maybe someone writes code for you...
Writing variables to an EEPROM is not new. Many other did this already. Do a search and you will find thousands of solutions, discussions code examples.

I´m not a C specialist. But I´d go with the struct.
But I don´t like the selfmade counting of how many bytes are in a struct.
I´m not sure whether one can use sizeof(struct) to run a loop over the whole struct.
If sizeof(struct) does not work, then you always can use a dummy byte as end_of_struct.

On the other hand: You talk about 700 variables .. thus I guess most of them are in an array (if not, try to use arrays).
And for an array it´s rather simple to store them to the EEPROM in a loop.

Klaus
 

I agree totally with @KlausST about us not writing the code for you, but just as a starter, and based on what you show in your first post, something like teh following pseudo code:

Code:
// Create the struct that holds the values and allocate memory to it
struct sensor_data_struct_name
{
    uint32_t sensor1_data;
    uint32_t sensor2_data;
    unit16_t sensor3_data;
    ....
    uint32_t sensor1000_data;
} eeprom_data;

// Populate the struct members
eeprom_data.sensor1_data = sensor1_value;
....
// Write the struct as a whole to the eeprom
eeprom_write(&eeprom_data, sizeof( eeprom_data), eeprom_address);
As you can see, you create a member in the struct that is the right size for the value you want to hold, and then you simply copy the value into that member. As mentioned above, just be aware of alignment issues if you use char or uint8_t sized values, and even uint16_t if the compiler uses a natural 32-bit alignment for variables. However all that will do is to create gaps in the struct that wastes a bit of space.
Susan
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top