Data Organization for an existing Project?

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Been going around and around on this, to the point that I hardly know which way is up. Maybe someone can shine a little light on the matter.

 

I read and write a collection of device control values to M348P EEPROM by putting everything into a struct (about 65 bytes) and use eeprom_write_block(), eeprom_read_block(), and eeprom_update_block() from AVR_libc. It works great. 

 

Now, I need to add a set of calibration tables for an acceleration sensor. There can be up to 6 such tables, one for each sensitivity available for the sensor (2g, 4g, 6g, 8g, and so forth). Each table contains three int16_t offset values (one for each axis) and three int32_t 1g values (one for each axis). Now, an important point is that these values are NEVER used at run-time. They are simply carried forward for use by a desktop GUI; this is so that they are positively bound to the unit without the operator having to do anything but read them via the USB terminal port.  That is the "what I need to do", part.

 

The next part is how to organize them for the eeprom. I wonder if I should add this data to the existing struct, or have one struct that holds all of the tables, or one struct per table. I have no clue how page boundaries are handled in the eeprom_xxx_block() functions and don't even know if that is an issue to be concerned with. Also, I don't know how to maintain order, since the existing struct purposely avoids the first eeprom byte. Do new values declared for the eeprom get assigned in the order in which they are declared?

 

The next part is how to organize the tables for easy access to the data within an designated table. An array of tables? Arrays within the tables? Struct per table? Here is where I have really been going around and around, not finding anything that is very attractive.

 

I would really appreciate some constructive thoughts about this. And I do appreciate your contribution.

 

Many thanks

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Thu. Mar 18, 2021 - 05:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

Reading the eeprom is just like reading RAM, writing is a problem as there you need sector writes and those take time.

I think it does not matter if you put everything in a single struct variable or if you make separate struct variables for each table.

You could also make 2 structs... one being the struct you have now and a second holding the tables.

You can even make a struct in a struct in a struct so to say, but that in my oppinion has a high chance of making your code unreadable in the long term, so I personally would go for a struct with the variables that can changes and the variables that will never change so to say.

I think in the end it boils down to what you seem logical.

you could make a struct per table

struct {

int16_t X,Y,Z;

}Cal_Values_Struct

 

and then

 

struct{

Cal_Values_Struct G1, G2, G4, G6, G8;

} Values structure

 

Values_structure eemem EE_Values_Structure;

 

Cal_Values_Struct Readback_Cal_Values; //<- to hold the specific set of values you need to send over USB

 

something like this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Compiler can put variables in memory in any order. But struct components are placed in it in order in they are declared. If You want put parameters and calibration tables in order chosen by You, with empty byte at start, You must declare one big structure with all data structures and tables in it. If You want start each structure or table from begin of a new eeprom page, You must fill space between they with tables that fill space to the end of previous page.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It doesn't matter exactly where you store them, as long as the same location is agreed to by your PC app...for example the PC APP may say read storage location 33, if it knows that corresponds to, say, sensor1, Z offset value.

You may even have a terminal program where you can query any location desired.  Internally, it may be a structured arrangement of some sort, but in a manual (datasheet) it might be referred to by some location number.

 

User manual:

 blah blah.  ...clean with a soft, damp cloth

If desired, the following system values may be queried for use in test program calculations, using the  CALVAL xxx ?  query command   

xxx is provided as:

022, current monitor cal offset value

023, current monitor cal gain value

024, Zaxis offset value

025, Zaxis gain setting

..

068, last calibration month (1-12)

069, last calibration year (99-33)

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think it depends whether an instance of your giant 65-byte struct ever exists in SRAM or only serves to determine the addresses of variables in EEPROM (I.e. a layout definition only).

 

If it is the latter then obviously the new tables must exist in the all encompassing struct.

If the former and you are not under SRAM pressure then the easiest implementation is to simply add them into the existing giant struct.

 

On the other hand; -if the new tables are only ever read/written by COMMS commands for which I recommend using an API to obfuscate the actual EEPROM addresses then I might do the EEPROM reads/ & writes on demand.

 

Personally; I am moving away from the EEPROM access Module "knowing/holding" every other module's persistent variables and I'm considering a Key-Value model for my EEPROM storage. That way each module can load/store it's own persistent variables and manage it's own default initialisers.

 

If I finish that work before this thread is over then I'll report back how it went.

 

Last Edited: Thu. Mar 18, 2021 - 08:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The next part is how to organize them for the eeprom.

I always think it helps to start by sketching out in code what you have described in words. I see it as something like:

typedef enum {
    CALIB_2G = 0,
    CALIB_4G = 1,
    CALIB_6G = 2,
    CALIB_8G = 3,
    CALIB_10G = 4,
    CALIB_12G = 5
} calib_index_e;

typedef struct {
    int16_t offsetX;
    int16_t offsetY;
    int16_t offsetZ;
    int32_t oneG_X;
    int32_t oneG_Y;
    int32_t oneG_Z;
} calib_t;

typedef calib_t calib_arr_t[6];

calib_arr_t EEMEM calibration = {
    { 1234, 2345, 3456, 54321, 65432, 76543 }, //2G
    { 1235, 2346, 3457, 54322, 65433, 76544 }, //4G
    { 1236, 2347, 3458, 54323, 65434, 76545 }, //6G
    { 1237, 2348, 3459, 54324, 65435, 76546 }, //8G
    { 1238, 2349, 3460, 54325, 65436, 76547 }, //10G
    { 1239, 2350, 3461, 54326, 65437, 76548 }, //12G
};

when I build that I get this in the .EEP file:

:10000000D2042909800D31D4000098FF0000FF2A96
:100010000100D3042A09810D32D4000099FF0000A9
:10002000002B0100D4042B09820D33D400009AFF69
:100030000000012B0100D5042C09830D34D40000ED
:100040009BFF0000022B0100D6042D09840D35D43E
:1000500000009CFF0000032B0100D7042E09850D32
:0C00600036D400009DFF0000042B0100BE
:00000001FF

Of course if you have other stuff to go into the EEPROM then maybe something like most of the above then:

typedef struct {
    int n;
    char c;
    long l;
    char unused_padding[20];
    calib_arr_t calibration;
} eelayout_t;

then instantiate as something like:

eelayout_t EEMEM myEElayout = {
    22222,
    'A',
    0xDEADBEEF,
    {0},
    {
        { 1234, 2345, 3456, 54321, 65432, 76543 }, //2G
        { 1235, 2346, 3457, 54322, 65433, 76544 }, //4G
        { 1236, 2347, 3458, 54323, 65434, 76545 }, //6G
        { 1237, 2348, 3459, 54324, 65435, 76546 }, //8G
        { 1238, 2349, 3460, 54325, 65436, 76547 }, //10G
        { 1239, 2350, 3461, 54326, 65437, 76548 }, //12G
    }
};

which results in:

 

:10000000CE5641EFBEADDE00000000000000000053
:100010000000000000000000000000D20429098058
:100020000D31D4000098FF0000FF2A0100D3042AFC
:1000300009810D32D4000099FF0000002B0100D48B
:10004000042B09820D33D400009AFF0000012B011C
:1000500000D5042C09830D34D400009BFF0000025E
:100060002B0100D6042D09840D35D400009CFF001F
:1000700000032B0100D7042E09850D36D400009D06
:07008000FF0000042B01004A
:00000001FF

Or maybe you don't want to initalise the other fields via the EEP in which case you might use something like:

 

eelayout_t EEMEM myEElayout = {
    .calibration = {
        { 1234, 2345, 3456, 54321, 65432, 76543 }, //2G
        { 1235, 2346, 3457, 54322, 65433, 76544 }, //4G
        { 1236, 2347, 3458, 54323, 65434, 76545 }, //6G
        { 1237, 2348, 3459, 54324, 65435, 76546 }, //8G
        { 1238, 2349, 3460, 54325, 65436, 76547 }, //10G
        { 1239, 2350, 3461, 54326, 65437, 76548 }, //12G
    }
};

This uses "designated initializers" which is only available in C not C++ (well not until you reach C++20 anyway). This results in:

:1000000000000000000000000000000000000000F0
:100010000000000000000000000000D20429098058
:100020000D31D4000098FF0000FF2A0100D3042AFC
:1000300009810D32D4000099FF0000002B0100D48B
:10004000042B09820D33D400009AFF0000012B011C
:1000500000D5042C09830D34D400009BFF0000025E
:100060002B0100D6042D09840D35D400009CFF001F
:1000700000032B0100D7042E09850D36D400009D06
:07008000FF0000042B01004A
:00000001FF

where the initial fields are all 0x00.

 

BTW you may wonder about "unused_padding[20]"? That is to allow for "growth" in the variables at the start of the data structure while keeping "calibration" at the same offset. So if you now add three "short" to the data (6 bytes) you would reduce the [20] padding size by 6 to ensure that calibration remains at the same offset.

 

(of course it doesn't matter what offset it is at if the later plan for extraction is simply to refer to it by name).

N.Winterbottom wrote:
I'm considering a Key-Value model for my EEPROM storage
JSON?  I have used an older version of:

 

https://github.com/open-source-p...

 

a lot and it worked very well indeed. One of the appeals is the freedom of the license.

 

EDIT: I forgot to explain my enum. I just typedef'd calib_index_e so that instead of accessing an anonymous looking myEElayout.calibration[3].offsetY you could use myEElayout.calibration[CALIB_8G].offsetY instead which is more documentary.

Last Edited: Thu. Mar 18, 2021 - 11:07 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

However you do it, I'd suggest including a "version" in your stored data.

 

Then, if you want to add new stuff, code can check the version and act accordingly.

 

Of course, you have to ensure that newer stuff doesn't break the older stuff.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is no guarantee what order the linker will use when assembling the various parts of eeprom sections, so putting everything in a single struct will guarantee order. You can also place offset values to the struct 'groups' in a fixed location, but probably only useful if the data will be read by something 'external' which doesn't have the location information (like a bootloader which is used to access the eeprom but may not know that the struct 'group' location may have changed, or something like that).

 

https://godbolt.org/z/GWEsrn

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

curtvm wrote:
There is no guarantee what order the linker will use when assembling the various parts of eeprom sections

This is true.

 

But if you're relying on the Linker to place them then, surely, you'd be referencing them by name - so you shouldn't have to worry about where the linker's put them?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>But if you're relying on the Linker to place them then, surely, you'd be referencing them by name - so you shouldn't have to worry about where the linker's put them?

 

It just depends if the app is the only one accessing the eeprom info. May have to be accessed from outside the app (reading via programmer, bootloader, etc.). There is also the problem of preserving existing eeprom data, if needed, when doing an update/programming.  If an update adds more eeprom usage, but wants to preserve existing data, then its probably going to be nicer to have a fixed/known layout. It also may be something that initially doesn't seem necessary, but may end up being wanted later.

 

Probably in many cases its not important as the app is the only one doing the reading/writing, but even so, I don't think there is any downside to keeping all eeprom data grouped in a single struct. It may also be a good way to keep a handle on eeprom usage vs having various source files all doing their own thing for eeprom vars. If there comes a time where you want to read the eeprom contents from a programmer to see what has been going on, it will be much nicer to be able to use the fixed struct as a guide rather than have to get the map file and match up addresses to vars.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you, everyone.

 

This is an excellent help. My reason for wanting a specific eeprom order is because the existing control struct includes a "special" variable to fill the address 0x0000 location with something that is just a filler. It would not help much if that control struct were put somewhere else!

 

One of the problems I am having is how to associate the data with a particular name. The calibration values will NOT be known at the time the eeprom is initially filled. That will have to be added, later, via terminal interface. So, just as an example, consider the following serial port message:

 

(cal_key_symbol),(sensitivity_code),(axis_code),(full_scale_val),(offset_val)<terminator>

 

By the way, all elements of this message are ASCII.

 

I am having a difficult time devising a method that associates the sensitivity_code AND the axis_code with particular table locations in a way that lets me store full_scale_val and offset_val in the correct places. Hmm, maybe a 2D array? Well two of them, one for full_scale_val and one for offset_val?

 

There may be a problem with that, though. I would have to maintain a 108 byte sram image of those two arrays in order to do an update. And, if that is an integral part of the control struct, the image of that control struct grows from around 60 bytes to around 170 bytes. And, even though that calibration data is never used at run-time except for menu write and read access, that extra 108 bytes would become a permanent memory occupant. That is not so good!

 

Thanks

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Thu. Mar 18, 2021 - 05:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
(cal_key_symbol),(sensitivity_code),(axis_code),(full_scale_val),(offset_val)<terminator>
Show us a real example of that. Do you mean something like
 

3,?,Y,1234,2345

I had no idea what you meant by "sensitivity code" ?? Actually I didn't really understand "cal_key_symbol" either - is this a 0..5 meaning to identify one of the 6 calibration array entries ?

 

If we look at it this way. I suggested some calibration data as:

        { 1234, 2345, 3456, 54321, 65432, 76543 }, //2G
        { 1235, 2346, 3457, 54322, 65433, 76544 }, //4G
        { 1236, 2347, 3458, 54323, 65434, 76545 }, //6G
        { 1237, 2348, 3459, 54324, 65435, 76546 }, //8G
        { 1238, 2349, 3460, 54325, 65436, 76547 }, //10G
        { 1239, 2350, 3461, 54326, 65437, 76548 }, //12G

so suppose you wanted to change (or write the initial value) of the 54325 value I highlighted in this what would you send over the ASCII interface?

 

In C code I would know this thing as myEElayout.calibration[4].oneGX

 

From your description it sounds like the single ASCII "sentence" is going to be passing the offsetX and oneGX values at the same time. So would you be sending:

4,??,X,54325,1238

to set the two X values for entry [4] to the same values as in my example data?

Last Edited: Thu. Mar 18, 2021 - 05:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, what I meant was something like this:

 

"#,2,x,9876,32<CR>", where '#' is the menu key that signifies a calibration data string. In the example, '2' would be the sensitivity symbol and 'x' would be the axis symbol

 

I think that I have a provisional solution. Will make a separate struct to hold the calibration data. The first byte will be a pad byte in case it ends up at the start of eeprom address space, then a version byte, then a 2D int32_t array for full-scale values and a 2D int16_t array for offset values.

 

This will allow the read-modify-write mirror of the eeprom contents to have local, non-static scope while the control struct can persist, separately, with its own scope. Adding the pad-byte allows either struct to be the first one. 

 

Off to try it. Thank you, everyone, for your thoughtful information and suggestions!

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An important point: Will the GUI be built with the EEPROM data?

If so, you can just use avr-nm to automatically give it the correct addresses

and any other information it might need.

 

If not, items should be located with the linker.

Another issue is whether the GUI might have to deal with change.

If not, you can use whatever data structures are convenient and build knowledge of them into the GUI.

 

If I understand the situation, there will be a struct and an array of structs.

Wrap them in a struct.

That struct should start with whatever is necessary to deal with allowed changes,

e.g. address of first nested struct, address of array, number of structs in the array

and the sizes of the structs in the array.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There will really be two GUIs. One to use during production for the purpose of reading data from the instrument in order to determine the calibration values, then load those back into the unit. So, this is (mostly) write only, but will return the calibration table that the most recent data write was related to. That is, if the data write was for the 6g scale, after the write, it will return the entire 6g cal table.

 

The second is part of a user program that downloads data from the unit, then applies the calibration constantds to produce corrected results. This is read-only with respect to the calibrations. 

 

The idea, at this point, is ONE struct containing the one dummy byte in case this struct is located at address 0x0000, a table version byte, a 6x3 int32_t full scale array, and a 6x3 int16_t offset array. The sram mirror will have only local non-static scope so that it does not persist beyond the immediate needs of read-modify-write for the eeprom.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
The idea, at this point, is ONE struct containing the one dummy byte in case this struct is located at address 0x0000
You keep saying "in case". You know you can control this??

 

One way is simply to make EVERYTHING in the EEPROM one big struct. I think you can rely on the linker to place objects from 0x0000 onwards so if there effectively is only ONE object it will go to 0x0000. Then within that object you can simply put a "dummy" at the very start that will occupy the dangerous 0x0000 location and know that everything else is above this.

 

The other way is to pre-empt the linker. When you do:

eelayout_t EEMEM myEElayout = {

the "EEMEM" in that is really little more than __attribute__((section(".eeprom"))) then in the linker script you have:

OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:5)
__TEXT_REGION_ORIGIN__ = DEFINED(__TEXT_REGION_ORIGIN__) ? __TEXT_REGION_ORIGIN__ : 0;
__DATA_REGION_ORIGIN__ = DEFINED(__DATA_REGION_ORIGIN__) ? __DATA_REGION_ORIGIN__ : 0x800060;
__TEXT_REGION_LENGTH__ = DEFINED(__TEXT_REGION_LENGTH__) ? __TEXT_REGION_LENGTH__ : 128K;
__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : 0xffa0;
__EEPROM_REGION_LENGTH__ = DEFINED(__EEPROM_REGION_LENGTH__) ? __EEPROM_REGION_LENGTH__ : 64K;
__FUSE_REGION_LENGTH__ = DEFINED(__FUSE_REGION_LENGTH__) ? __FUSE_REGION_LENGTH__ : 1K;
__LOCK_REGION_LENGTH__ = DEFINED(__LOCK_REGION_LENGTH__) ? __LOCK_REGION_LENGTH__ : 1K;
__SIGNATURE_REGION_LENGTH__ = DEFINED(__SIGNATURE_REGION_LENGTH__) ? __SIGNATURE_REGION_LENGTH__ : 1K;
__USER_SIGNATURE_REGION_LENGTH__ = DEFINED(__USER_SIGNATURE_REGION_LENGTH__) ? __USER_SIGNATURE_REGION_LENGTH__ : 1K;
MEMORY
{
  text   (rx)   : ORIGIN = __TEXT_REGION_ORIGIN__, LENGTH = __TEXT_REGION_LENGTH__
  data   (rw!x) : ORIGIN = __DATA_REGION_ORIGIN__, LENGTH = __DATA_REGION_LENGTH__
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = __EEPROM_REGION_LENGTH__

so this initially puts anything in the .eeprom section from 0x810000 onwards in the ELF  file (this is because ELF only really handles a single, linear address space). Then later on:

"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "mcs7_test.elf" "mcs7_test.eep" || exit 0

as the .eep file is created it reads the .eeprom stuff (at 0x810000 on) from the ELF then the --change-section-lma moves it back to a 0x0000 offset before the .eep is created.

 

So you could just as easily do stuff like:

__attribute__((section(.myEE))) int n = 1234;
__attribute__((section(.myEE))) struct {
    char C;
    long l
} = {
    'X',
    0xDEADBEEF
};

then later:

-Wl,-section-start=.myEE=0x810000

and later on have your own avr-objcopy with a "-j .myEE" and an LMA change to create a hex file for this data.

 

But so far this does nothing but change things from ".eeprom" (that EEMEM uses) to a section who's name you are in control of. However you could take this further:

__attribute__((section(.myEE1))) int n = 1234;
__attribute__((section(.myEE2))) struct {
    char C;
    long l
} = {
    'X',
    0xDEADBEEF
};
-Wl,-section-start=.myEE1=0x810006 -Wl,-section-start=.myEE2=0x81000F

where you are now controlling the location of each individual item. Of course, if you take on the job of being the linker you have to do what it would usually handle and ensure no overlaps/clashes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Of course, if you take on the job of being the linker you have to do what it would usually handle and ensure no overlaps/clashes.
The linker will help with that anyway.

One runs into problems when one directly defines symbols.

The linker will not even know that there are corresponding objects,

much less how big they are.

 

All that said, I think the important thing is what gets built into the GUI and what does not.

The GUI has to have at least one address built in.

For other addresses, either they or a means to find them must be built in.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The GUI has to have at least one address built in.

Well ,not  truly.  I do systems all the time with gui's that read various parameters.  It has no idea where they are & doesn't care.  It only cares that it can get the info or set it:

 

BATTVOLT?          ...report current battery voltage

PULSECAL?          ...report current pulse width calibration value

PULSECAL xxxx    ...set pulse calibration (width in ms)

PnNUM xxxxxxx   ...generate required xxxxxx number of pulses on output channel n (n=0-4)

TDEG?                 ...read current temperatue , degrees F

TOCAL xx             ...set temperature calibration offset

TGCAL  xxxxx       ...set temperature compensation gain cal

TGCAL?                ...report temperature compensation gain

GAINnValxxxx       ...set proportional gain n (n=0-4) to value (333-2765 limit) 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

The GUI has to have at least one address built in.

Well ,not  truly.  I do systems all the time with gui's that read various parameters.  It has no idea where they are & doesn't care.  It only cares that it can get the info or set it:

Without a builtin address, what does it read first?

Even if it searches for a pattern, the search has to start somewhere.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
Without a builtin address, what does it read first?

I wrote the answer to this in #5

N.Winterbottom wrote:
... read/written by COMMS commands for which I recommend using an API to obfuscate the actual EEPROM addresses

This way you can chop & change the EEPROM layout as much as you like; but the GUI program need not change.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Without a builtin address, what does it read first?

The GUI does not know anything about any address at all, unless perhaps it is putting data into a cal table, but that is something different (such as BATTCAL aa IS xxxx    ...batt calibrate table entry aa , value xxxx,,, BATTCAL 27 IS 573)

If you GUI command PULSECAL 738, the AVR takes care of puttjng 738 in the proper storage location. reporting it, and using it to do something useful.

With that in mind, I usually also have direct EEPROM access with PEEK and POKE commands, so the GUI can rig a bypass, if needed (POKE aaaa IS xxx,   POKE 789 IS 136, or  PEEK 789 ?)

 

Winterbottom is on the money!!

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:
skeeve wrote:
Without a builtin address, what does it read first?

I wrote the answer to this in #5

N.Winterbottom wrote:
... read/written by COMMS commands for which I recommend using an API to obfuscate the actual EEPROM addresses

This way you can chop & change the EEPROM layout as much as you like; but the GUI program need not change.

Had forgotten that.

Somehow or another, I had gotten the idea that the GUI was to get its data from a non-running processor and that therefore at least one address would have to be known outside the processor.

 

BTW I'd have chosen hide or conceal rather than obfuscate as in "Obfuscated C Contest".

Obfuscate suggests that one is supposed to not know what one is looking at.

In the case at hand, looking at it is not desired.

To me, using obfuscate would have come off as sarcasm, had sarcasm made any sense.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

EEPROM addresses are totally obfuscated by a menu system that is designed for both manual (e.g. human) access and automated access. 

 

No real issue. It works.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To me, using obfuscate would have come off as sarcasm, had sarcasm made any sense.

sarcasm is the only thing that makes any sense!laugh 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually, I used "obfuscated" inaccurately.

 

"Hidden" would be a better term in this case. When the appropriate command is received, data is read (as a many-value block) from the eeprom into sram. Values are returned from sram. There is no direct access between the serial terminal and the eeprom. It is totally indirect.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!