Recent

Author Topic: [SOLVED] Variable addresses in SRAM  (Read 6422 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Variable addresses in SRAM
« Reply #15 on: September 24, 2022, 06:00:23 pm »
I noticed one thing with constants: although I have {$WRITEABLECONST OFF} if I use typed constant like below they go into SRAM.

That doesn't sound right, since a few days ago Sven said

Quote
if you declare the constant as {$WRITEABLECONST OFF} ... the storage location will be the binary's rdata (aka read only data!) section

https://forum.lazarus.freepascal.org/index.php/topic,60466.msg452560.html#msg452560

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Variable addresses in SRAM
« Reply #16 on: September 24, 2022, 09:48:53 pm »
So your TInt16_array is dynamic and goes on the heap, and is possibly reallocated (possibly resulting in fragmentation) during operation.

All arrays are with defined boundaries, but I have types declared like this:
Code: Pascal  [Select][+][-]
  1. TInt16_array = array of Int16;

i don't think that you can use dynamic array's without using the heapmgr unit ...

I must check in assembler, but I don't think it is used as dynamic array. Array is not declared as dynamic array, I just use this type so in my other unit I don't have to know size of the array.

And what is the value for SizeOf(TInt16_array) then ?

Code: Pascal  [Select][+][-]
  1. var
  2.    data: array [0..10] of Int16;
  3.    sz1, sz2, adr1, adr2: IntPtr;
  4. type
  5.   TInt16_array = array of Int16;
  6. begin
  7.    sz1 := SizeOf(data);
  8.    sz2 := SizeOf(TInt16_array(data));
  9.  
  10.    adr1 := Integer(Pointer(@data[1]));
  11.    adr2 := Integer(Pointer(@TInt16_array(data)[1]));
  12.  
  13.    WriteLN( sz1: 16,  sz2: 16, adr1: 16, adr2: 16);
  14. end;
  15.  

Do values match?

This type IS dynamic array. And then a variable of dynarray type is a POINTER to array (see documentaiton about fundamental types implementation in FPC or Delphi)

If you typecast static array to dynamic array, then you typecast array to pointer.

The correct way to access would be either declare STATIC array [0..High(integer) div sizeof(elementtype)] of elementtype as accessor type, or to use Pointer Math/Arythmetics

https://www.freepascal.org/daily/doc/prog/progsu113.html
https://forum.lazarus.freepascal.org/index.php?topic=45986.0
https://docwiki.embarcadero.com/RADStudio/Sydney/en/Pointer_Math_(Delphi)
« Last Edit: September 24, 2022, 10:24:16 pm by Arioch »

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Variable addresses in SRAM
« Reply #17 on: September 24, 2022, 11:54:22 pm »
Code: Pascal  [Select][+][-]
  1. var
  2.    data: array [0..10] of Int16;
  3.    sz1, sz2, adr1, adr2: IntPtr;
  4. type
  5.   TInt16_array = array of Int16;
  6. begin
  7.    sz1 := SizeOf(data);
  8.    sz2 := SizeOf(TInt16_array(data));
  9.  
  10.    adr1 := Integer(Pointer(@data[1]));
  11.    adr2 := Integer(Pointer(@TInt16_array(data)[1]));
  12.  
  13.    WriteLN( sz1: 16,  sz2: 16, adr1: 16, adr2: 16);
  14. end;
  15.  

Do values match?

This doesn't compile.

If I change lines 8 and 11 to the code below I got the same address.

Code: Pascal  [Select][+][-]
  1.    sz2 := SizeOf(TInt16_array(@data));
  2.    adr2 := Integer(Pointer(@TInt16_array(@data)[1]));


Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Variable addresses in SRAM
« Reply #18 on: September 25, 2022, 01:35:29 am »
You did not show your actual code, so i can only be guessing how you do accessing with type override...

> This doesn't compile.

Again, you did not show the exact error.

I suggest you to google for ESR's "how to ask questions smart way" - it is a harsh reading, from a man who wrote "a right to be rude", but it is helpful.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. type
  4.   TInt16_array = array of Int16;
  5.   PInt16_array = ^TInt16_array;
  6.   TData = packed array [0..10] of Int16;
  7.   PData=^TData;
  8. var
  9.    data: TData;
  10.    ptr1: PData; ptr2: PInt16_array;
  11.    sz0, sz1, sz2, adr0, adr1, adr2: IntPtr;
  12. begin
  13.    ptr1 := @data;
  14.    ptr2 := Pointer(ptr1);  // erase pointer type information, make different pointers compatible
  15.  
  16.   // make sure those pointer are equal, reference one and the same memory
  17.    writeln ( Integer(ptr1): 16, Integer(ptr2): 16, Integer(@data): 16);  
  18.  
  19.    sz1 := SizeOf(ptr1^);  // size of array typed to the pointer's type
  20.    sz2 := SizeOf(ptr2^);
  21.    sz0 := SizeOf(data);
  22.  
  23.    adr1 := Integer(Pointer(@ptr1^[1]));
  24.    adr2 := Integer(Pointer(@ptr2^[1]));
  25.    adr0 := Integer(Pointer(@data[1]));
  26.  
  27.    WriteLN(  sz0: 16,  sz1: 16,  sz2: 16);
  28.    WriteLN( adr0: 16, adr1: 16, adr2: 16);
  29.  
  30.    ReadLN;
  31. end.
  32.  

Win64:

Code: [Select]
           73744           73744           73744
              22              22               8
           73746           73746               2
« Last Edit: September 25, 2022, 01:41:04 am by Arioch »

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Variable addresses in SRAM
« Reply #19 on: September 25, 2022, 01:50:23 am »
Also read this: https://stackoverflow.com/questions/30410064/pascal-pointer-to-an-array-of-unknown-size



If I change lines 8 and 11 to the code below I got the same address.

Code: Pascal  [Select][+][-]
  1.    sz2 := SizeOf(TInt16_array(@data));
  2.    adr2 := Integer(Pointer(@TInt16_array(@data)[1]));

because here you convert not the array but the pointer to the array!

but dynarray is not merely pointer to values, the dynarray has a whole frame of ARC data BEFORE the values, and compiler would automatically change the data in that "before values" frame with you deal it with dynarrays.

so frankly, FPC should had baffled here and denied such a type miscast, if he denied my original one

but okay, for the sake as uniformity and completeness;

Code: Pascal  [Select][+][-]
  1.  
  2. type
  3.    Tint16_original = array[0..10] of int16;
  4. .....
  5.    adr1 := Integer(Pointer(@TInt16_original(@data)[1]));
  6.    adr2 := Integer(Pointer(@TInt16_array(@data)[1]));

Will it compile? No?
Well, if it will - you would see addresses do not match.

If it won't - you see those types are FUNDAMENTALLY DIFFERENT.
One only compiling with "@data" - pointer, not values. Another only compiling with "data" - value not pointer.



Frankly, i do not see what you say you see.
To me typecasts with @data do not compile, never and no way.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. type
  4.   ti = smallint;
  5.   pi = ^ti;
  6.  
  7.   tsa = array [0..4] of ti;
  8.   tpa = packed array [0..4] of ti;
  9.   tda = array of ti;
  10.  
  11.   psa = ^tsa;
  12.   ppa = ^tpa;
  13.   pda = ^tda;
  14.  
  15. var
  16.   p0: Pointer;
  17.   p1: pi;
  18.   data: array [0..4] of ti;
  19.  
  20. begin
  21. // {$T-}  or  {$T+}
  22.  
  23.   p1 := @data[1];
  24.  
  25.   p0 := @data;
  26.  
  27. // all those three are compiled fine
  28.   p0 := @tsa(data);
  29.   p0 := @tpa(data);
  30.   p0 := @tda(data);
  31.  
  32. // those three are not compiled, but errors differ
  33.   p0 := @tsa(@data);
  34.   p0 := @tpa(@data);
  35.   p0 := @tda(@data);
  36.  
  37. { if T- mode was set, then the errors would be:
  38.  
  39. project1.lpr(33,10) Error: Illegal type conversion: "Pointer" to "tsa"
  40. project1.lpr(34,10) Error: Illegal type conversion: "Pointer" to "tpa"
  41. project1.lpr(35,14) Error: Can't assign values to an address
  42.  
  43. if T+ mode was set, then the errors would be:
  44.  
  45. project1.lpr(33,10) Error: Illegal type conversion: "^Array[0..4] Of SmallInt" to "tsa"
  46. project1.lpr(34,10) Error: Illegal type conversion: "^Array[0..4] Of SmallInt" to "tpa"
  47. project1.lpr(35,14) Error: Can't assign values to an address
  48. }
  49.  
  50.   ReadLN;
  51. end.  

Also note that merely typecasting somethign to dynarray type already tries to WRITE somewhere into the @data
Did you expect it?
« Last Edit: September 25, 2022, 02:08:26 am by Arioch »

ccrause

  • Hero Member
  • *****
  • Posts: 845
Re: Variable addresses in SRAM
« Reply #20 on: September 25, 2022, 09:53:26 am »
I noticed one thing with constants: although I have {$WRITEABLECONST OFF} if I use typed constant like below they go into SRAM.

That doesn't sound right, since a few days ago Sven said

Quote
if you declare the constant as {$WRITEABLECONST OFF} ... the storage location will be the binary's rdata (aka read only data!) section

https://forum.lazarus.freepascal.org/index.php/topic,60466.msg452560.html#msg452560

MarkMLl

A simple example suggests otherwise:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$WRITEABLECONST OFF}
  4. const
  5.   x: dword = $AABBCCDD;
  6.  
  7. begin
  8.   writeln(x);
  9. end.

Compiled on Linux 64 bit with FPC 3.2.2 and searching for the constant in the generated executable:
Code: [Select]
objdump -j .data  -s project1 | grep ccbb
 42a120 00000000 00000000 ddccbbaa 00000000  ................

Back to the AVR situation: currently FPC can either treat a const as a literal, or store the value in flash and copy to SRAM during startup.  In principle read-only data could be accessed in flash, but there is no compiler support for this (at the moment).

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Variable addresses in SRAM
« Reply #21 on: September 25, 2022, 12:14:10 pm »
You did not show your actual code, so i can only be guessing how you do accessing with type override...

I showed code in post #5 (copied directly from my project).


Quote
Again, you did not show the exact error.

I don't have errors with arrays, they work as I want them too.

Quote
I suggest you to google for ESR's "how to ask questions smart way" - it is a harsh reading, from a man who wrote "a right to be rude", but it is helpful.

I don't want to be rude, but I think you should read with understanding my first post.

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Variable addresses in SRAM
« Reply #22 on: September 25, 2022, 12:22:29 pm »
Code: Pascal  [Select][+][-]
  1. project1.lpr(35,14) Error: Can't assign values to an address

mere typecast to dynarray makes compiler write into ARC data frame time and again.

accessor should be a typed pointer (with pointer math one) or a static array of maximum attainable size

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Variable addresses in SRAM
« Reply #23 on: September 25, 2022, 12:34:19 pm »
Back to the AVR situation: currently FPC can either treat a const as a literal, or store the value in flash and copy to SRAM during startup.  In principle read-only data could be accessed in flash, but there is no compiler support for this (at the moment).

I managed to reduce SRAM usage by removing type from const declaration, so this consts are treated as a literal now. I still have a couple of strings which I'll move to flash with '.progmem'.

All in all, thank you all for help, especially you (https://github.com/ccrause/freepascal/wiki/%5BAVR%5D-Investigating-stack-and-heap-management) and d.ioannidis.

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Variable addresses in SRAM
« Reply #24 on: September 25, 2022, 02:53:50 pm »
accessor should be a typed pointer (with pointer math one) or a static array of maximum attainable size

You are correct regarding other platforms, but AFAIK in AVR platform dynamic arrays aren't supported, and it works like I did it. Nevertheless, I will rewrite it to avoid dynamic arrays in case that dynamic arrays become supported in AVR platform.


Regarding the original question: __bss_end is address location which I was looking for - stack pointer must stay above it not to corrupt variable data.

From ccrause's github account:
Code: Pascal  [Select][+][-]
  1. var
  2.   bss_end: pointer external name '__bss_end';

ccrause

  • Hero Member
  • *****
  • Posts: 845
Re: Variable addresses in SRAM
« Reply #25 on: September 25, 2022, 05:28:45 pm »
Regarding the original question: __bss_end is address location which I was looking for - stack pointer must stay above it not to corrupt variable data.

From ccrause's github account:
Code: Pascal  [Select][+][-]
  1. var
  2.   bss_end: pointer external name '__bss_end';

This may not always be accurate, at the time I didn't realize there is one more section that follows __bss_end, the .noinit section. If variables are located in .noinit, then __bss_end does not point to the end of all allocated data.  For reference, a more robust end of allocated data reference would be:
Code: Pascal  [Select][+][-]
  1. var
  2.   endOfAllocatedData: pointer external name '__noinit_end';

PascalDragon

  • Hero Member
  • *****
  • Posts: 5448
  • Compiler Developer
Re: Variable addresses in SRAM
« Reply #26 on: September 25, 2022, 09:18:21 pm »
No recursive functions, only consts, vars, arrays, records.

Any strings (as distinct from shortstrings) or dynamic arrays?

MarkMLl

In all units I have {$H-} on the top. Additionally, all strings are declared as String[10], String[16] or String[20].

All arrays are with defined boundaries, but I have types declared like this:
Code: Pascal  [Select][+][-]
  1. TInt16_array = array of Int16;

I use to access this array:
Code: Pascal  [Select][+][-]
  1. var vars_Int16: array [0 .. vars_Int16_num - 1] of Int16;

like this (Fvars_Int16 is pointer to vars_Int16):
Code: Pascal  [Select][+][-]
  1. editInt16 := TInt16_array(Fvars_Int16)[FCurrentItem.miVar];

These are not compatible. Don't use this. If it works for you it's by accident and not guaranteed to continue working.

Old style object, like this:

Just checking, because of the naming ambiguity :-)

In the context of AVR this isn't ambiguous, because Delphi-style classes aren't by default enabled on that target.

I noticed one thing with constants: although I have {$WRITEABLECONST OFF} if I use typed constant like below they go into SRAM.

That doesn't sound right, since a few days ago Sven said

Quote
if you declare the constant as {$WRITEABLECONST OFF} ... the storage location will be the binary's rdata (aka read only data!) section

https://forum.lazarus.freepascal.org/index.php/topic,60466.msg452560.html#msg452560

I should have clarified this a bit more: the location is read only data if the OS supports it and the compiler utilizes it correctly. On AVR this currently isn't supported and on Linux there are problems with relocations if variables are put into the .rdata section (at least that's what I remember).

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Variable addresses in SRAM
« Reply #27 on: September 25, 2022, 09:32:51 pm »
I should have clarified this a bit more: the location is read only data if the OS supports it and the compiler utilizes it correctly. On AVR this currently isn't supported and on Linux there are problems with relocations if variables are put into the .rdata section (at least that's what I remember).

Thanks for that.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Variable addresses in SRAM
« Reply #28 on: September 25, 2022, 11:12:04 pm »
No recursive functions, only consts, vars, arrays, records.

Any strings (as distinct from shortstrings) or dynamic arrays?

MarkMLl

In all units I have {$H-} on the top. Additionally, all strings are declared as String[10], String[16] or String[20].

All arrays are with defined boundaries, but I have types declared like this:
Code: Pascal  [Select][+][-]
  1. TInt16_array = array of Int16;

I use to access this array:
Code: Pascal  [Select][+][-]
  1. var vars_Int16: array [0 .. vars_Int16_num - 1] of Int16;

like this (Fvars_Int16 is pointer to vars_Int16):
Code: Pascal  [Select][+][-]
  1. editInt16 := TInt16_array(Fvars_Int16)[FCurrentItem.miVar];

These are not compatible. Don't use this. If it works for you it's by accident and not guaranteed to continue working.

Thanks, noted

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Variable addresses in SRAM
« Reply #29 on: September 25, 2022, 11:12:29 pm »
Regarding the original question: __bss_end is address location which I was looking for - stack pointer must stay above it not to corrupt variable data.

From ccrause's github account:
Code: Pascal  [Select][+][-]
  1. var
  2.   bss_end: pointer external name '__bss_end';

This may not always be accurate, at the time I didn't realize there is one more section that follows __bss_end, the .noinit section. If variables are located in .noinit, then __bss_end does not point to the end of all allocated data.  For reference, a more robust end of allocated data reference would be:
Code: Pascal  [Select][+][-]
  1. var
  2.   endOfAllocatedData: pointer external name '__noinit_end';

Thank you

 

TinyPortal © 2005-2018