This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

*** How to define a structure as a Variable?

I have the following structure.

__infomem__ const struct info_mem_s nv_parms =
{
    {
    {
        0xFFFF,
#if defined(SELF_TEST_SUPPORT)
        0xFFFF,
        0xFFFF,
#endif
#if !defined(SINGLE_PHASE)
        {
#endif
            {
                {
#if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR_A},
    #if defined(LIMP_MODE_SUPPORT)
                    {DEFAULT_I_RMS_LIMP_SCALE_FACTOR_A},
    #endif
                    0,
#endif
#if GAIN_STAGES == 1
                    DEFAULT_P_SCALE_FACTOR_A_LOW,
#else
                    {DEFAULT_P_SCALE_FACTOR_A_LOW, DEFAULT_P_SCALE_FACTOR_A_HIGH},
#endif
                    DEFAULT_I_DC_ESTIMATE << 16,
#if defined(PHASE_CORRECTION_SUPPORT)
    #if GAIN_STAGES == 1
                    DEFAULT_BASE_PHASE_A_CORRECTION_LOW,
    #else
                    {DEFAULT_BASE_PHASE_A_CORRECTION_LOW, DEFAULT_BASE_PHASE_A_CORRECTION_HIGH},
    #endif
#endif
                },
#if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR_A,
    #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_RMS_LIMP_SCALE_FACTOR_A,
    #endif
#endif
                DEFAULT_V_DC_ESTIMATE << 16,
#if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_LIMP_DC_ESTIMATE << 16,
#endif
            },
#if !defined(SINGLE_PHASE)
            {
                {
    #if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR_B},
        #if defined(LIMP_MODE_SUPPORT)
                    {DEFAULT_I_RMS_LIMP_SCALE_FACTOR},
        #endif
                    0,
    #endif
    #if GAIN_STAGES == 1
                    DEFAULT_P_SCALE_FACTOR_B_LOW,
    #else
                    {DEFAULT_P_SCALE_FACTOR_B_LOW, DEFAULT_P_SCALE_FACTOR_B_HIGH},
    #endif
                    DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
        #if GAIN_STAGES == 1
                    DEFAULT_BASE_PHASE_B_CORRECTION_LOW,
        #else
                    {DEFAULT_BASE_PHASE_B_CORRECTION_LOW, DEFAULT_BASE_PHASE_B_CORRECTION_HIGH},
        #endif
    #endif
                },
    #if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR_B,
        #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_RMS_LIMP_SCALE_FACTOR,
        #endif
    #endif
                DEFAULT_V_DC_ESTIMATE << 16,
    #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_LIMP_DC_ESTIMATE << 16,
    #endif
            },
            {
                {
    #if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR_C},
        #if defined(LIMP_MODE_SUPPORT)
                    {DEFAULT_I_RMS_LIMP_SCALE_FACTOR},
        #endif
                    0,
    #endif
    #if GAIN_STAGES == 1
                    DEFAULT_P_SCALE_FACTOR_C_LOW,
    #else
                    {DEFAULT_P_SCALE_FACTOR_C_LOW, DEFAULT_P_SCALE_FACTOR_C_HIGH},
    #endif
                    DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
        #if GAIN_STAGES == 1
                    DEFAULT_BASE_PHASE_C_CORRECTION_LOW,
        #else
                    {DEFAULT_BASE_PHASE_C_CORRECTION_LOW, DEFAULT_BASE_PHASE_C_CORRECTION_HIGH},
        #endif
    #endif
                },
    #if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR_C,
        #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_RMS_LIMP_SCALE_FACTOR,
        #endif
    #endif
                DEFAULT_V_DC_ESTIMATE << 16,
    #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_LIMP_DC_ESTIMATE << 16,
    #endif
            }
        },
#endif
#if defined(NEUTRAL_MONITOR_SUPPORT)
        {
    #if defined(IRMS_SUPPORT)
            DEFAULT_I_RMS_SCALE_FACTOR_NEUTRAL,
        #if defined(LIMP_MODE_SUPPORT)
            DEFAULT_I_RMS_LIMP_SCALE_FACTOR_NEUTRAL,
        #endif
            0,
    #endif
            DEFAULT_P_SCALE_FACTOR_NEUTRAL,
            DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
            DEFAULT_NEUTRAL_BASE_PHASE_CORRECTION,
    #endif
        },
#endif
#if defined(TEMPERATURE_SUPPORT)
        25,
        DEFAULT_TEMPERATURE_OFFSET,
        DEFAULT_TEMPERATURE_SCALING,
#endif
#if defined(CORRECTED_RTC_SUPPORT)
        0,
#endif
        {
            0,
            0,
            0,
            0,
            0,
            0
        },
        0,
        "",
        "",
        ""
    }
    }
};

As you can see from the code above, it is a constant one. However, I do not like it and I want some constants to be variables.  When I changed "const" to "__no_init", the compiler gives me error. So, is there any way to make this structure defined as a constant?

  • Hi CaEngineer,

    This sounds more like a generic C question rather than MSP430 specific.

    However, if your structure is in info memory, then you are not going to be able to modify it as a variable.

    On the other side, if you declare your structure as __no_init, then you are telling the compiler that the structure doesn't have to be initialized.
    Are you using the __no_init because you are skipping the low level initialization of variables (by using __low_level_init or _system_pre_init)? if you are not, then you don't need __no_init in order to declare variables.

    If you are not skipping the low level initialization, you could declare a structure with constants and variables like:
    typedef struct
    {
    const uint8_t a;
    uint16_t b;
    uint8_t c;
    const uint16_t d;
    }Mystruct_t;

    Mystruct_t mystruct =
    {
    .a = 1,
    //b is initialized as 0x00
    .c = 3,
    .d = 4
    };

    Now, this structure will be placed in RAM but all the values will be initialized with their respective values by the low level initialization. The only effect of the "const" declaration is that it will tell the compiler that write access to these variables is not allowed. Note that the variable is still in RAM, so you can still modify it but not by writing directly to mystruct.a/mystruct.d.

    Now, another option would be to have 2 structures, one with constants that can be allocated in info memory, and one with variables which will be in RAM. You could even declare a third object with pointers to each structure if you want to have them in a single object.

    Regards,
    Luis R
  • Luis,

    No, I do not want to leave this structure without initializing. However, I would like to have this opportunity to change the values inside the structure later on.

    Having more than one Structure does not seem to be logical as I am running out of memory. Unless, as you said I define in a way that it sits in RAM not in the INFO-MEM.

    I will check this and get back to you shortly!

    Thanks!
  • Luis,

    I trimmed my structure and I was ended up with the following.

    __infomem__ const struct info_mem_s nv_parms =  
    { 
              0 ,
    
        {
             {{{SF_I__A},0, SF_P__A,0, SF_PH__A,}, SF_V__A,},
             {{{SF_I__B},0, SF_P__B,0, SF_PH__B,}, SF_V__B,},
             {{{SF_I__C},0, SF_P__C,0, SF_PH__C,}, SF_V__C,}
         }
        
    };
    
    
    

    SF_I__A, and so on are constant values. However, I want them to be defined as variables.  I took your advice and use "typedef" to define the structure. However, as you know the format of INFO-MEM does not let me make this change.

    The point is define them as global variables to change it anywhere in different parts of the code. However, there is an uncertainty here as follows.

    I am seeing that nv_parms is called in other parts of the firmware and I can put a break point and see that my Scaling Factors are changing as I change the firmware by using a serial port! But I do not understand how this can be done in the body of my Main.C!

    On the other words as you Said if I go ahead and use RAM. I think the compiler gives me some error and tells me it is not possible to define my Struct as variable.

  • Hi,

    Sorry for the delay, but I think I missed your response.

    I have to say that I'm not sure I understand what you are trying to do.

    Each different declaration has its use:
    - If you declare the structure as shown above, then you can't modify any of the members of the structure in your code. You can, however, write some Flash routines to erase/write the structure.
    - If you replace "const" by "no_init", then you can't pre-initialize the values. However, you could initialize them in code.
    - If you just remove "const" then the structure will be placed in RAM. The values of the structure will be initialized by a C initialization routine. The default values are copied from Flash, however, your code will only access the RAM structure and any changes on the values structure won't be copied to the Flash initialization values.

    Dividing a structure in 2 doesn't necessarily mean that it will use more memory. My previous suggestion was to declare a "const" structure for values which are not expected to change, and a RAM structure (initialized or non-initialized) for variables which are expected to change.
    Again, I don't know your exact needs so I'm not sure if this will work for you or not.

    But please post the declaration that is causing problems and the error given by the compiler

    Regards,
    Luis R
  • Luis R,

    I am back to you but I guess too late! However I know what I want more clearly now if you are still available! (hope so)

    Now, I would like to define a structure and later on alter it. So the question is as follows.

    Does a structure work like an array?

    Seems not! So, how can I reinitialize it?

    nv_parms[1]  ==> This does not call the first item in the structure

    How can I call it in my program?

  • Yes you can initialize a const structure in info

    const char ssidstruct[] @"INFOD"  = {0,3,9,10, 192,...

    Can even use just do a few of the structures members by using the dot.

    alarmstruct alarm =  {  .config.minutespeed = 1,  // a typedef structure
                                                  .config.flags = 0 };

    If complier gives you problems about  writing to const structure (as it does not understand flashwrite can be enabled)
    skip the const but instead add __no_init, and you manualy fill it with you default values with flashwrite.

    Or use pointers and complier don't care that you are writing to flash memory that is considered const.

    Char* mempoint = (*)0x1040;

  • Got back after so long time, coz busy with something else! 

    If I define my structure like the following:

    __infomem__ __no_init struct info_mem_s nv_parms =

    I will get the following errors:

    Warning[Pa034]: initialized variable can not have __no_init attribute, discarded C:\Users\carma\Desktop\Oct.18th2015\UsingEEPROM\MODIFIED emeter-ng\emeter-main.c 159

    Error[Be010]: segment/section name not allowed (object must have static storage duration and be const or __no_init) C:\Users\carma\Desktop\Oct.18th2015\UsingEEPROM\MODIFIED emeter-ng\emeter-main.c 159

    So, what do you say?

  • with __no_init the cstartup code does not fill any in data on reset.
    You can use __no_init const
    but compiler may give you warnings that you are trying to change a member in read-only memory when it gets to the flashwrite routine (if you have that)

    But using a empty structure is still useful as all the blank memory locations have a .name (dot operator)

    Your want a onetime fill in of data, 3 options:
    1: write you own code that checks if it is empty (all 0xff) and flash write memcopy it in with default values.

    2: temporary remove _no_init and allow erase of info in ide-settings, use struct = {.yourdata = 10, ....}
        compile and send to mcu, don't start the code, now remove allow-erase-of-info and put _no_init back, put // in front of ={

    3:for production programming, you will use the version with _no_init but simple paste in the @0x1000 snippet you will get when you don't use no init
       in to this ti.txt file. 

  • Oh shoot! You know what! This is defined on the top of the Main.C! I have to have a constant values!

    No! I need to change the variables inside the Structure nv_parms!

    I did not get your explanation. All I am saying is it does not accept the __no_init!

  • With const, the members gets its values from the debuggers jtag flashwrite routine, so that is a onetime shot.
    if you don't specify a member value is the same thing as =0; e.g it will not skip over a member leaving you with a unknown or 0xff value.

    regular vars, get there values from cstartup as the compiler bunch all vars together in two blocks in ram and use memclr for the ones that has not a declared value and memcpy from a flash block for those that are declared to a non-zero value.

    Having modifiable vars at a absolute memory read-only location, breaks these rules.

    using __no_init, you don't have to worry about those rules, but you can not initialize any values, not from jtag programming or cstartup.
    They will be set to 0xff if you allow erase-of-info, you can flash write individual bytes without erasing the block first (but check if it's 0xff)

    So if you want a mix of initialized values and flashwrite enabled values, use const and  just set the later members to 0xffff.

    So what is the plan where these vars in Info gets their first set values?

  • Let me explain what the structure is made of as follows.

    I have the main structure:

    __infomem__ const struct info_mem_s nv_parms =
    {
    and the information definition as the following.

    #define __infomem__ _Pragma("location=\"INFO\"")

    And the info_mem_s:

    struct info_mem_s
    {
    union
    {
    struct nv_parms_s s;
    int8_t x[128];
    } seg_a;
    };

    So, as you can see I have structure within structure and it is a little bit complicated to change the definition!

    Then, what do you advise me to do for changing it to a variable structure?
  • You have a union so the nv_pams_s s can also be referenced to using the x array.
    But struct padding my put some unused bytes here and there, so don't use x array[specific location] to guess a members location.

    As you're placing it in flash it will never be accepted by the compiler as "regular" vars,

    So what is it your are trying to do?

    A: These vars get set by a BSL loader?, sure works just fine, just use __no_init const
    B: Some vars gets set after the programs boots up?, just use const with nv_parms = {.member = 0xffff,

    C: These vars get set as backup values at powerloss, as you have diode+ capacitor to provide time to just do this at power failure?
    and you want to copy the whole segment you call seg_a?
    typedef struct simplify as you can you do: } info_mem_s, *info_mem_s_ptr; to declare a pointer reference to structure at the same time.

  • Let me explain it more. nv_parms structure keeps our scaling factors for Voltage, Current, Active Power, and the power factor. So, we have a constant scaling factors are there and waiting to be used by the code in the loop further in the firmware.

    However, we want to load the other values which are the ones that we have stored them in the EEPROM and if they are not blank (FF), we want to replace them with the above-mentioned values. So, it is just one time replacement.

    We need to check the EEPROM and if it is not blank change the contents of the structures by the EEPROM values. Otherwise go ahead and us the defaults.

    So, that's why we need it to be a variable.

    A: We use IAR and JTAG. When use __no_init it is complaining!

    B: No before starting the program it should be checked and replace from the EEPROM.

    C: I could have a LPM0 before the startup but I believe I won't need that.

    Yes, the program starts by calling the reference:


    for (;;)
    {


    #if !defined(ESP_SUPPORT) && defined(PHASE_CORRECTION_SUPPORT) && !defined(DYNAMIC_PHASE_CORRECTION_SUPPORT)
    #if !defined(SINGLE_PHASE)
    for (ch = 0; ch < NUM_PHASES; ch++)
    {
    // spot#1


    phase = &chan[ch];

    phase_nv = &nv_parms.seg_a.s.chan[ch];
  • Why use msp flash that emulates eeprom, but still use eeprom?
    How did the values get in the eeprom, why not put them in msp flash in the first place?
    Or is the calibration process so tedious that incase of firmware update that could change struct or erase info by mistake?

    Why not put the initialized structure in ram and overwrite specific members from eeprom everytime? 
    unless you're low on ram?
     
     
    If you want default values in info, just use const.
    If you after boot-up check eeprom and see that it has values, if the data in info does not match: flash erase and copy the data over.
    This way it does not erase+copy ever time the mcu resets.

  • Tony Philipsson said:
    Why use msp flash that emulates eeprom, but still use eeprom?

    Do you mean the part that you can only flash some specific part of the memory? Well, it is a long story but I was asked to go ahead and use the EEPROM just in case if in the future we don't use the IAR or other risks to lose the data.

    Tony Philipsson said:
    How did the values get in the eeprom, why not put them in msp flash in the first place?

    We want to save the calibrated value into the EEPROM and save them there. However, as the calibration module is not ready yet, we can test it and read from where we had written some specific value.

    Tony Philipsson said:
    Or is the calibration process so tedious that incase of firmware update that could change struct or erase info by mistake?

    They want to calibrate the meter then reflash it without losing the value! That's why they picked EEPROM!

    Tony Philipsson said:
    Why not put the initialized structure in ram and overwrite specific members from eeprom everytime? 

    Well, you have good ideas on your mind and previously we used multiple structures...#2 #3 and ...

    We are not low on RAM and we can add more structures. But please tell me how can I use the second one and put the EEPROM value? We used the same as #1 previously!

    Tony Philipsson said:
    If you want default values in info, just use const.
    If you after boot-up check eeprom and see that it has values, if the data in info does not match: flash erase and copy the data over.
    This way it does not erase+copy ever time the mcu resets.

    Ok I will leave the constant structure the way it is but not quite sure how to cope the data over? Can you guide me through please?

  • Yes you can tell IAR to never erase Info, and infoA is even more secure as it have a lock but you would have to copy it first before you erase it so you don't loose TI's calibration data when you write the block back, and TI started to include TLV values so less space but maybe you don't need them all.

    If you have to read the eeprom every time to see if it have values and if the values match what the msp have every time it resets,
    why not just use ram?
    cstartup will copy default values to the struct, you then check eeprom if it have values , you overwrite the struct members.
    and the program then goes on its merry way, not knowing or even caring if the values are default or calibrations values.

  • Tony Philipsson said:
    Yes you can tell IAR to never erase Info, and infoA is even more secure as it have a lock but you would have to copy it first before you erase it so you don't loose TI's calibration data when you write the block back, and TI started to include TLV values so less space but maybe you don't need them all.

    Yes, but as I explained it before I have to use EEPROM and other stuff such as Serial numbers and so on are the next data to put into it. 

    Tony Philipsson said:
    If you have to read the eeprom every time to see if it have values and if the values match what the msp have every time it resets,
    why not just use ram?

    No, don't get me wrong I don't want to erase the EEPROM at all. Every time the program starts up I would like to have my data retrieve from the EEPROM except the first time that takes from the RAM.

    Tony Philipsson said:
    you overwrite the struct members

    How can I overwrite it? Ok let me show you my whole main.c in order to give you a better view and guide me through.

    Here you can find my main.c. After for (;;) loop the nv_parms getting the data from the default scaling factors.

    http://hostcode.sourceforge.net/view/4183

  • You can put serial number info, and does not even have fill it in at the same time as long you leave bytes to be written later as 0xff.

    I did not say to erase eeprom. I said: use the structure as normal, no location specification, not const, no __no_init.
    but do use = {default1, default2,....
    What happens is that compiler will put this data in flash but instruct cstartup to fill in the struck at reset.
    step2: you now read eeprom, if it have data , copy that data

    It now depends if the data it has is a copy of the structure or put in by hand,
    as struct-padding have to be taken in to account if you mix char and int etc.

    If the eeprom layout is not 100% the same as the struct, copy one member at a time.

    if the eeprom matches the struct (as it was copied from this same struct at one time)
    Just instruct the eeproms i2c routine to read its data and direct-write starting at *struct_location++ with sizeof(struct) number of bytes.
    If the buffer pointer can not be specified, copy buffer to *struct_location after you read all bytes.

    typedef struct is easier, but creating a pointer to the start of struct by hand is not to hard. google it.

  • Ok, I see. Thanks man! I got the an idea even though in practice is harder to apply!
  • BTW, where can I find the variable and changeable structure examples in the TI Forums or somewhere else please? I wanna see the real examples.
  • As this is a general C questions as it does not even include the special rules of using Info (as that was unnecessary step) as that could made this a C msp specific question, so instead go here:
    www.tutorialspoint.com/.../c_structures.htm

    Don't send large stuct's to a function as it copies it to the stack, but use pointers.
    They don't show typdef struct, but with it, you can just add ,*mystructpnt; at the end

    And when you need to set a pointer to a one of the stuct's (as you have many of the same type)
    you would just do: mystructpnt s = &mystruct2, then simple use s->membername inside the function etc.

    -> is used instead of the dot when you are using pointers to structures, It's the same as (*s).membername

  • yes yes let's say for calling the voltage scaling factor we do: i = phase_nv->V_rms_scale_factor;
    but here is the thing my definition for the structure is right but as it is involved with infomem makes me confused!

    if I use struct nv_parms

    instead of


    __infomem__ const struct info_mem_s nv_parms =

    it is complaining: Error[Pe040]: expected an identifier C:\Users\carma\Desktop\Dec.18th2015\UsingEEPROM\MODIFIED emeter-ng\emeter-main.c 172



    identifire!

    It is said I don't have identifier!

    Can you please explain this?
  • struct info_mem_s nv_parms ={default,...

    info_mem_s is the struct prototype declaration you need to identify for the compiler. (though probably should change its name to nv_struct etc)

    As a declaration is reusable so even if you only plan to use it once you still have "move" the declaration to a structname (e.g nv_parms )

  • get back to you after the weekend!

    So, in order to define a variable structure I have to have that prototype. Um... Let me try it and get back to you soon! Thanks for your replies!

  • I wrongly referred to it as a prototype, it's called a declaration as you can give members a name and not just its type.

    A struct is by default a variable one, just leave out const and of course don't try to force a flash location on it.

    When you set up the layout of the struct, this is the declaration and not a struct name you can use in your code directly

    You have to:
    struct declarationstruct mynewstuctname;  // declaration is reusable for many instances or array of the same struct layout.

    You can initialize values by :
    struct declarationstruct mynewstuctname ={11,20};   // the rest will be set to zero

    Or by referring to members .name
    struct declarationstruct mynewstuctname ={.name2=20};  // members not mentioned will be set to zero

    C will then do what it does to any variable that is initialized to a value,
    it sets up a block in flash to copy to ram at bootup to fill in same data at every reset.
    But you can change this data after that, as in your case they are just default values.

    If you have to pass the start address to a function or memcpy etc:
    struct declarationstruct *pnt = &mynewstuctname;  // To declare and define pnt as a pointer of type declarationstruct

    You can then do indirect addressing, something that in asm is easier to understand as you do: @R15  or  0x02(R15)
    If a function can work on many instances of the same declarationstruct,
    function would use pnt->membername, and the compiler will handle the start address and use indirect addressing for member location offset.

  • Ok here we go! I again have the following error.

    I change my structure to the following:

    struct Henri nv_parms =
    {
    int y;
    };

    and it says:

    Error[Pe029]: expected an expression C:\Users\carma\Desktop\Dec.21st2015\UsingEEPROM\MODIFIED emeter-ng\emeter-main.c 161
    Error[Pe067]: expected a "}" C:\Users\carma\Desktop\Dec.21st2015\UsingEEPROM\MODIFIED emeter-ng\emeter-main.c 161
    Error[Pe169]: expected a declaration C:\Users\carma\Desktop\Dec.21st2015\UsingEEPROM\MODIFIED emeter-ng\emeter-main.c 162
    Error while running C/C++ compiler

    Why I need a constant one?!!!
  • Ok I realized that, there is no complaint on this:



    struct Henri2
    {
    int g;
    };

    But I need to have that prototype defined!
  • struct nv_struct {
    int RMS_SCALE_FACTOR_A;
    int SCALE_FACTOR_A_LOW;
    };

    struct nv_struct nv_data = { .RMS_SCALE_FACTOR_A=2, .SCALE_FACTOR_A_LOW=10};

    To change it to (if there is one) calibrated data
    int main(void){
    nv_data.RMS_SCALE_FACTOR_A = getfromeeprom(0,2); //example or copy the whole block if layout is 100% same

    Side effect:
    1: Uses ram even though it's "constants",
    but you if use #if  to manually tell code to only use default the compiler should put it in flash or internal scratchpad as it notice it's never modified.
    2: It will go through the copy-from-eeprom at every reset,
    but as to see if the stuct it has is a default or calib you would have to compare the whole struct anyway,
    unless you used some keyword in header to flag that this is the data from eeprom and don't read eeprom again (if burned to flash)

  • Thanks for making this more clear for me. But I still have one uncertainty!

    If I leave my constant in a way that it is like:

    __infomem__ const struct info_mem_s nv_parms =
    {
    {
    {
    0xFFFF,

    #if !defined(SINGLE_PHASE)
    {
    #endif
    {
    {
    #if defined(IRMS_SUPPORT)
    {I_SF_A},0,
    #endif
    #if GAIN_STAGES == 1
    P_SF_A_LO,

    ...

    And add one the way you explained above:

    struct nv_struct nv_data{
    SF1, Sf2,...

    }

    The info_mem_s with the following definition is still needed to be redefine:

    struct info_mem_s // There is no need to use other segments like b or c or so on ...
    {
    union
    {
    struct nv_parms_s s;
    int8_t x[128];
    } seg_a;
    };

    Do you know what I mean?

    Coz nv_parms_s has another structure inside!

    I am going to define it as:

    struct info_mem_s
    {

    struct nv_parms_s s;

    };

    to get rid of the section and will let you know!
  • Having all these #ifdef is so messy, why not just let them all in to the struct and your code later decide what to use.
    You have to reserves space for worse case scenario anyway, were they all could be included?
    And all these nested const or what you would call it brings nightmares for next programmer.
    And the block copy from eeprrom will not be the same if you keep switching struct layout all the time.

    Don't put a single struct inside a struct as I don't see a need for a union.
    union would only be good if you for some reason need to fill in the struct but using a different type (e.g a byte array instead)
    But pointing to struct and sizeof(struct) there should be no need for this.

  • Your general idea is totally understandable! However, I have to have something like:

    struct info_mem_s
    {
    union
    {
    struct nv_parms_s s;
    int8_t x[128];
    } seg_a;
    };


    I am fighting through!
  • Ok then, I will get rid of the union and the info_mem! Still need to tell him where to get the variables!
  • Let me clear this more for you!
    I have the main structure as follows.

    hostcode.sourceforge.net/.../4215

    Then the infomem as

    struct info_mem_s // There is no need to use other segments like b or c or so on ...
    {
    union
    {
    struct nv_parms_s s;
    int8_t x[128];
    } seg_a;
    };

    and nv_parms_s itself:

    hostcode.sourceforge.net/.../4216

    and finally it goes to the followings to read the calibrated scaling factors:

    hostcode.sourceforge.net/.../4217
  • Is this some generic motor driver that uses nested "tricks" to be modifiable for many types of motors, code you borrowed from the internet?
    I would write my own from scratch so I know what it does, just for the type of motor and calibration I needed.
    But that is up to you, but a bug in that I would think would be hard to find.

    Step1: Did you get it to work as is (the original example from code library etc) with just default values?
    Step2: force that const struct in to info, still works? or now change plan and remove any const reference and use ram

    Step3: if sticking to flash add a new int to the top of struct: int password.
    it will be set to zero when compiler use default values, your flashwrite will write 0x5a67 to the location (could come from the eeprom or you write it manually in after flashwrite routine filled in the data)
    This way you check if key is present and you don't erase flash and read eeprom again after every reset.

    Step4: memcpy or instruct the i2c routine that buffer and struct is as same location, a union may be necessary if you don't want to modify the i2c routine to use pointers instead of an array name. (though leaving flashwrite enabled while doing other stuff like i2c is not recommended)

    But I would make the union the master of location, so don't set that in struct.
    And a struct around a union is not need, and union can be anonymous.

    union {
    struct nv_stuct nv_data;
    char eeprom_buffer[128};
    } @0x1000;

    Though were setting default values for the nv_data, I have not tested.

  • I know that I am such a pain man! Let me get back to you! I guess I am getting there!
  • Good news is I was able to change the scale factor within the program but I have changed everything and the code is so naked! Let me get it right will get back to you shortly!

**Attention** This is a public forum