setting up a struct of absolute addressed pointers (to pointers)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

setting up a struct of absolute addressed pointers (to pointers)

1,920 Views
ilya_r
Contributor III


I am working on the S12G processor (9s12g128 specificaly) and am going to be doing 2D and 3D table interpolations.

 

I have my table interpolation function working by using structs:

typedef struct{
  float *X;
  float *Y; 
}Table2D;

typedef struct{
  float *X;
  float *Y;
  float *Table;
}Table3D;

 

Now I want to move my tables into absolute addresses in EEPROM so they can be reprogrammed on the fly

 

I have a number of predefined tables, but their size and values will be flexible.

 

I am trying to structure my code thusly:

float x[5] = {3300, 3400, 3500, 3700, 4000} @ *some_address*

float y[5] = {2150, 1750, 1450, 1300, 1200}; @ *address continued from x*

float *x_pntr = x @ *defined address*

float *y_pntr = y @ *defined address*

 

Table2D SlipPower ={

  *x_pntr,

  *y_pntr

};

 

so if the sized of the table chages, then the addresses of where x and y start can change, but the pointers to those addresses stay in the same place

 

But I can still use the structures I created before so

temp = table->X[index];      //  an example from my interpolation funtion

still works

Original Attachment has been moved to: tables.h.zip

Original Attachment has been moved to: control_gains.h.zip

Original Attachment has been moved to: tables.c.zip

Labels (1)
0 Kudos
10 Replies

1,234 Views
StenS
Contributor III

Why not just let the compiler and linker place your tables in EEPROM, instead of trying to force them to specific adresses? E.g.:

#pragma DATA_SEG EEPROM_DATA

   float x[5];

   float y[5];

#pragma DATA_SEG DEFAULT

in the prm-file's PLACEMENT-section:

   EEPROM_DATA INTO EEPROM;

/Sten

0 Kudos

1,234 Views
ilya_r
Contributor III

Sten,

The reason is the tables will need to vary in size:

if I start with a x[5], y[5] table then y[] starts at adress x+5, but if I need to reflash with a x[6] y[6] table then at adress x+5 is x[5], not y[1].

If you look at my code the interpolation functions measure the size of the table e.g. while(&x[x_size] < &y[0])  x_size++

So I am trying to set up a predefined location in memory that is a pointer to the start of x[] and another pointer to the start of y[] that will be reflashed with a new value if the size of the tables change.  If the size of a table changes then where y[] starts will shift as will every table that comes after.

0 Kudos

1,234 Views
kef
Specialist I
  • If you look at my code the interpolation functions measure the size of the table e.g. while(&x[x_size] < &y[0])  x_size++

IMO it is a bad trick producing not portable and not clean code, which depends on linking order and data alignment.

It is better to use sizeof() to determine size of an array.

  •   for(x_size=1; &table->X[x_size] < table->Y; x_size++){}     /* read size of table in x direction */

This is not a smart at all. It wastes a lot of CPU cycles to determine size of array. Instead you should use sizeof(). Even if you want to export array declaration, which wil make sizeof() unable to determine size of array with undefined dimensions, you still can have something like this:

// h-file

extern const int myarray[];

extern const unsigned int myarraysizeb;

extern const unsigned int myarraysize;

// c-file

const int myarray[] = {1,2,3,4};

const int myarraysizeb = sizeof(myarray); // size, bytes

const int myarraysize = sizeof(myarray)/sizeof(myarray[0]); // size, elements

0 Kudos

1,234 Views
ilya_r
Contributor III

Ed,

Thank you for the suggestion, however:
1- I understand the way I have it coded is using more cycles to compute but I have the resourses to do it and I need to do it that way because:

2- when all said and done I will not be be creating tables in code, but will have pointers to where the tables start, which will run upto the start of the next table so that I can ISP a new tables into the EEPROM and adjust the starting addresses (based on table sizes) while the micro is still running

it will look something like this (not C compliant code, but to get the idea):

*table1_pnt @0x0400

*table2_pnt @0x4002

struct table2D{

     table1_pnt;

     table2_pnt;

}table

for(size=1; &table->(*table1_pntr)[size] < table->(*table2_pnt);size++){}     /* read size of table in x direction */

in this example the table pointers are pointing to the start of the tables, and when I develope the table that will give me my table size so I can load the table and at the same time load the address into the pointer

0 Kudos

1,234 Views
kef
Specialist I

But you can ISP not only pointers and data, but also sizes of your data, isn't it. Maybe it's just micro or milliWatts*second, but still some CPU cycles and power waster. It is always better to use compile time constants instead of calculating the same at runtime.

Unfortunately it is not trivial to make what you do portable, other targets will have different float sizes or struct / array alignment. In case of Codewarrior smartlinker you can rely on optimization out of unused variables to determine array size. Dummy arrays will be optimized out. Hope it will give you some ideas

#define data1 {3300, 3400, 3500, 3700, 4000}
#define data2 {2150, 1750, 1450, 1300, 1200}

float __dummy1[] = data1;
float __dummy2[] = data2;

const struct {
   float *t1ptr;
   float *t2ptr;
   int t1size;
   int t2size;
   float t1[sizeof(__dummy1)/sizeof(__dummy1[0])];
   float t2[sizeof(__dummy2)/sizeof(__dummy2[0])];
} mydata = {
   mydata.t1,
   mydata.t2,
   sizeof(__dummy1)/sizeof(__dummy1[0]),
   sizeof(__dummy2)/sizeof(__dummy2[0]),
   data1,
   data2
};


0 Kudos

1,234 Views
ilya_r
Contributor III

Ed,

I have modified the code for measuring the size of the table to speed up the process:

x_size = (&Y[0] - &X[0]) / sizeof(X[0];

However that still doesn't answer my original question, when trying:

float Torque_x[13] @ 0x460 = {0, 250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000}; // Fan Speed

float Torque_y[13] @ 0x494 = {0,   2,   8,  20,   35,   55,   79,  108,  140,  177,  220,  265,  317}; // Max Variable Fan Speed

void *T_x @ 0x426 = Torque_x;

void *T_y @ 0x428 = Torque_y;

Table2D TorqueCurve={

  (float*)*T_x,

  (float*)*T_y

};

gives me C1806 errors (illegal cast operation) in the struct definition.

What is the proper way to do this?

0 Kudos

1,234 Views
kef2
Senior Contributor IV


It's because of extra star here

(float*)*T_x

0 Kudos

1,234 Views
ilya_r
Contributor III

I wish to take the value 0x460, put it into a variable and then typecast the variable as a float*

so:

float Torque_x[13] @ 0x460 = {0, 250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000}; // Fan Speed

float Torque_y[13] @ 0x494 = {0,   2,   8,  20,   35,   55,   79,  108,  140,  177,  220,  265,  317}; // Max Variable Fan Speed

variable X @ 0x426 = &Torque_x[0];

variable Y@ 0x428 = &Torque_y[0];

Table2D TorqueCurve={

  (float*) X,          // float* to address 0x460

  (float*) Y          // float* to address 0x494

};

0 Kudos

1,234 Views
kef2
Senior Contributor IV

So why don't you

float Torque_x[13] @ 0x460 = {0, 250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000}; // Fan Speed

float Torque_y[13] @ 0x494 = {0, 2, 8, 20, 35, 55, 79, 108, 140, 177, 220, 265, 317}; // Max Variable Fan Speed

Table2D TorqueCurve={

  &Torque_x[0],

  &Torque_y[0]

};

0 Kudos

1,234 Views
ilya_r
Contributor III

Ed,

Thank you, I was already doing that, but your comment helped me realize that I can locate the Tabel2D structure at the address I need:

float Torque_x[13] @ 0x460 = {0, 250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000}; // Fan Speed

float Torque_y[13] @ 0x494 = {0, 2, 8, 20, 35, 55, 79, 108, 140, 177, 220, 265, 317}; // Max Variable Fan Speed

Table2D TorqueCurve @ 0x422 ={

  Torque_x,

  Torque_y

};

0 Kudos