>I've already had Mark A. Odell answer this question saying this can't be
>done portably. He also sugested me coming to this group with the question
>#define _CLAVE1 ((uint16_t*)0xD000)
if you want to pretend that _CLAVE1 is a uint_16 located at D000, instead
of a pointer, then this should be
>#define _CLAVE1 (*(uint16_t*)0xD000)
now you can write, e.g.,
_CLAVE += 17
--
mac the na�f
Reply by Paul Carpenter●March 31, 20042004-03-31
On Wednesday, in article
<%ICac.4300471$uj6.13822256@telenews.teleline.es>
yodai@spamnot.mail.vu "Mark" wrote:
><snip>
>>
>> The problem with
>> > #define _CLAVE1 ((uint16_t*)0xD000)
>> is that it defines an address and not a variable. You actually want
>> #define _CLAVE1 (*((uint16_t*)0xD000))
>>
>> If 0xD000 is in non volatile memory you could resort to inline assembler
>to
>> initialise your variable from within a C source file, something of the
>form
>>
>> asm_start
>> .org $D000
>> .dw 99
>> asm_end
>>
>> I don't know if this would work with the IAR compiler but it certainly
>does
>> work with other compilers I've used.
>
>
>Ok... This is exactly what I was thinking but it's not adequate. I was
>thinking the only solution would be to initialize this values one single
>time, since it's flash memory, but I don't want my program to do so, because
>this values might be changed by user action. See, these values are the ip of
>a embedded webserver. So, when I want to change them, I need to write them
>on a certain memory position, but, from factory, I need them to have a
>specific value in order to make the webserver work the first time. So my
>idea was to have the application recorded on the non-volatile memory already
>have on memory position 0xd000 the value '192', 0xd002 -- '168'... to have
>the ip number for the webserver located and when wanting to change, opening
>the flash-write lock, writting on my var CLAVE1, and having the new value
>set with no trace of the factory setting.
>
>Is this so impossible? I'm sure it can be achieved somehow......
You seem to be doing something very complicated, for something I do simply,
by three copies of structures.
I have the structures thus:-
Define the structure layout...
e.g. struct init
{
unsigned short count;
unsigned short x;
char b;
....
};
RAM Working system changeable constants
struct init working;
Programme space (.rodata) /* Factory defaults */
struct init default =
{
40,
16,
5,
...
};
External non-volatile (usually a larger flash chip)
struct init *saved; /* pointer defined by boundary
of a flash sector by LINKER */
Then at startup or other checks if flash or just that sector fails its
checksum test, I use the programme defaults. A blank device/sector will
fail its checksum. Otherwise I use the flash copy.
The copy across is only a copy of the size of the structure by memcpy,
all that changes is the source pointer. The working values can be saved at
a predetermined time to the flash a sector/byte at a time, when a section has
changed and been verified or commanded to by the user.
If all fouls up e.g. power fail between erase and write of flash or part
way through writing the flash, revert to factory defaults.
Even if software versions change you can save the version number and counts
in the structure, so a change in number of variables is always added to the
END of the structure and default actions if required added for the extra
variables, as you use the count of bytes from flash to determine how many to
copy over, only copying the known variables across all others have safe default
actions.
Often I start by copying the factory defaults from programme space to RAM
area then copy over the number of valid bytes from flash and work from there.
The addresses of the RAM version and programme space do not matter as they are
specific to the compiled version, and the extra non-volatile set are the ones
that stay at fixed locations whatever the software version.
--
Paul Carpenter | paul@pcserv.demon.co.uk
<http://www.pcserv.demon.co.uk/> Main Site
<http://www.gnuh8.org.uk/> GNU H8 & mailing list info.
<http://www.badweb.org.uk/> For those web sites you hate.
Reply by Steve Schefter●March 31, 20042004-03-31
Hans-Bernhard Broeker <broeker@physik.rwth-aachen.de> wrote in message news:<c4elqm$m5t$1@nets3.rz.RWTH-Aachen.DE>...
> Avoiding this initialization "from inside the program" is a pointless
> exercise. What do you think how this variable will be initialized by
> the compiler if you manage to get it to do it? The effect will be
> exactly the same as if you had done it by an assignment
>
> CLAVE1 = 99;
>
> near the beginning of main(). The only real difference will be that
> it's done by code automatically created by the compiler rather than
> written by you, and that code may be a bit more efficient (it's
> typically a kind of memcpy() from code memory to data memory).
Not quite. From what the OP described, he's talking about initialized
data space. It's where things like "hello world" come from. It is not
setup by code, even compiler generated code. Initialized data spece is
already there in memory reserved for initialized data before any code
runs.
The trouble with putting it in code as you suggested is that everytime
the program is run, it would set the value back to 99 and he said he
didn't want to do that. He wants it initialized once (I'm guessing
when the program is put into static memory).
The original comment about not being able to do it portably in C is
correct. It's a job for assembler if you really want to do it that
way. If you have Linux, see arch/ppc/simple/head.S and its Makefile
and the -T option of ld force segments to specific base addresses.
Note that you won't be just putting one variable at a defined address
when you do this (you'll put the whole segment there), though you'll
have control over specific addresess for each element within that
segment if you wish.
Having said all that, it still isn't a good way to go. I gather you
are wanting to do this so that you can have one nonrelocatable binary
to plunk down into your embedded device. If I were you, I'd make
the setting of the memory in flash a separate step rather than making
this part of downloading your program to the device. This should be
easy to do if your embedded device has a boot loader. With PPCBoot,
for example, it's easy to wipe the flash to all zeros (can you live
with that as the initial value, instead of 99?). This kind of
separate (from code installation) setup is what the folks who make
embedded devices do to set things like serial numbers and MAC
addresses, though I realize you are not looking for unique
initializations the way they are. After that, you can use C to
define a pointer and access that memory.
If you don't have a boot loader (to set memory), then I think
you'll have to do it in assembler. But you are then your own boot
loader and it's not unexpected that that has to involve some assembler.
Regards,
Steve
Reply by Mark●March 31, 20042004-03-31
Ok...enough...
I see there's a much easier way to solve this problem from assembler by just
going
aseg 0x0D000
and then writting each part as if a preprocessor writting.....
Cheers! everyone...
"Mark" <yodai@spamnot.mail.vu> escribi� en el mensaje
news:n9Aac.4297804$uj6.13806894@telenews.teleline.es...
> I've already had Mark A. Odell answer this question saying this can't be
> done portably. He also sugested me coming to this group with the question
> see if anyone here has some idea on how to do this... I am working on a
> MSP430 and using IAR ew compiler...
>
> <reposted>
> Hey all.... I'm trying to do something that should be easy, but my
compiler
> doesn't allow me... I am trying to define a variable into a certain memory
> position and then assign a default value for it....
>
> #define _CLAVE1 ((uint16_t*)0xD000)
>
> //This memory position is located on a flash memory
> //of an embedded system and has to have the
> //startup value of '99' but it will be changed from time
> //to time from inside my program, which writes into the flash...
> // so I try to define it's value, but my compiler says
> // "_CLAVE1 redefined" if I do this
>
> #define ((uint16_t*)0xD000) 99
>
> //I've tried all sorts of combinations, and still, nothing works...
>
>
>
>
> Any idea on how to define a memory position and it's initial value without
> initialising the value from inside the program?
>
>
>
Reply by Sergio Masci●March 31, 20042004-03-31
Mark <yodai@spamnot.mail.vu> wrote in message
news:%ICac.4300471$uj6.13822256@telenews.teleline.es...
> <snip>
> >
> > The problem with
> > > #define _CLAVE1 ((uint16_t*)0xD000)
> > is that it defines an address and not a variable. You actually want
> > #define _CLAVE1 (*((uint16_t*)0xD000))
> >
> > If 0xD000 is in non volatile memory you could resort to inline assembler
> to
> > initialise your variable from within a C source file, something of the
> form
> >
> > asm_start
> > .org $D000
> > .dw 99
> > asm_end
> >
> > I don't know if this would work with the IAR compiler but it certainly
> does
> > work with other compilers I've used.
>
>
> Ok... This is exactly what I was thinking but it's not adequate. I was
> thinking the only solution would be to initialize this values one single
> time, since it's flash memory, but I don't want my program to do so,
because
> this values might be changed by user action. See, these values are the ip
of
> a embedded webserver. So, when I want to change them, I need to write them
> on a certain memory position, but, from factory, I need them to have a
> specific value in order to make the webserver work the first time. So my
> idea was to have the application recorded on the non-volatile memory
already
> have on memory position 0xd000 the value '192', 0xd002 -- '168'... to have
> the ip number for the webserver located and when wanting to change,
opening
> the flash-write lock, writting on my var CLAVE1, and having the new value
> set with no trace of the factory setting.
>
> Is this so impossible? I'm sure it can be achieved somehow......
>
> Cheers!
How about this:
struct MY_SPECIAL_VARS
{
long init_flag;
uint16_t clave1;
int var2, var3, varN;
};
struct MY_SPECIAL_VARS
*my_special_vars = 0xD000;
#define CLAVE1 (my_special_vars->clave1)
int main()
{
if (my_special_vars->init_flag != 0x1234567)
{
my_special_vars->clave1 = 192;
my_special_vars->var2 = 0;
my_special_vars->var3 = 0;
my_special_vars->varN = 0;
my_special_vars->init_flag = 0x1234567;
}
}
Regards
Sergio Masci
http://www.xcprod.com/titan/XCSB - optimising structured PIC BASIC compiler
Reply by Mark●March 31, 20042004-03-31
<snip>
>
> The problem with
> > #define _CLAVE1 ((uint16_t*)0xD000)
> is that it defines an address and not a variable. You actually want
> #define _CLAVE1 (*((uint16_t*)0xD000))
>
> If 0xD000 is in non volatile memory you could resort to inline assembler
to
> initialise your variable from within a C source file, something of the
form
>
> asm_start
> .org $D000
> .dw 99
> asm_end
>
> I don't know if this would work with the IAR compiler but it certainly
does
> work with other compilers I've used.
Ok... This is exactly what I was thinking but it's not adequate. I was
thinking the only solution would be to initialize this values one single
time, since it's flash memory, but I don't want my program to do so, because
this values might be changed by user action. See, these values are the ip of
a embedded webserver. So, when I want to change them, I need to write them
on a certain memory position, but, from factory, I need them to have a
specific value in order to make the webserver work the first time. So my
idea was to have the application recorded on the non-volatile memory already
have on memory position 0xd000 the value '192', 0xd002 -- '168'... to have
the ip number for the webserver located and when wanting to change, opening
the flash-write lock, writting on my var CLAVE1, and having the new value
set with no trace of the factory setting.
Is this so impossible? I'm sure it can be achieved somehow......
Cheers!
Reply by Mark●March 31, 20042004-03-31
<snip>
> Avoiding this initialization "from inside the program" is a pointless
> exercise. What do you think how this variable will be initialized by
> the compiler if you manage to get it to do it? The effect will be
> exactly the same as if you had done it by an assignment
The thing is: this belongs to an embbedded web server's ip. So, from
factory, value will be something like CLAVE1 = 192, CLAVE2=168....
But this value, which is a value "set from factory" can be changed by a user
action and then, I have to be able to write on it's exact memory position
the new value. Since deleting flash memory can only be done in 512bit
chunks, I must locate all variables on the same place and, somehow, give
them names to be able to write them later, but I can not initialize them
from my program since, every time the embbedded webserver would reset or
power on it'd try to reassign the "old" value on them. That's why my main
program cannot have any call to a specific value on those positions,
eventhough I need them to be set as a factory setting....through a #define,
I presume. Any idea on how can I do this? I've been trying some of the
methods posted, but they don't seem very adequate to my specific problem....
Cheers!
>
> CLAVE1 = 99;
>
> near the beginning of main(). The only real difference will be that
> it's done by code automatically created by the compiler rather than
> written by you, and that code may be a bit more efficient (it's
> typically a kind of memcpy() from code memory to data memory).
>
> --
> Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
> Even if all the snow were burnt, ashes would remain.
Reply by Sergio Masci●March 31, 20042004-03-31
Mark <yodai@spamnot.mail.vu> wrote in message
news:n9Aac.4297804$uj6.13806894@telenews.teleline.es...
> I've already had Mark A. Odell answer this question saying this can't be
> done portably. He also sugested me coming to this group with the question
> see if anyone here has some idea on how to do this... I am working on a
> MSP430 and using IAR ew compiler...
>
> <reposted>
> Hey all.... I'm trying to do something that should be easy, but my
compiler
> doesn't allow me... I am trying to define a variable into a certain memory
> position and then assign a default value for it....
>
> #define _CLAVE1 ((uint16_t*)0xD000)
>
> // This memory position is located on a flash memory
> // of an embedded system and has to have the
> // startup value of '99' but it will be changed from time
> // to time from inside my program, which writes into the flash...
> // so I try to define it's value, but my compiler says
> // "_CLAVE1 redefined" if I do this
>
> #define ((uint16_t*)0xD000) 99
>
> // I've tried all sorts of combinations, and still, nothing works...
>
>
>
>
> Any idea on how to define a memory position and it's initial value without
> initialising the value from inside the program?
>
The problem with
> #define _CLAVE1 ((uint16_t*)0xD000)
is that it defines an address and not a variable. You actually want
#define _CLAVE1 (*((uint16_t*)0xD000))
If 0xD000 is in non volatile memory you could resort to inline assembler to
initialise your variable from within a C source file, something of the form
asm_start
.org $D000
.dw 99
asm_end
I don't know if this would work with the IAR compiler but it certainly does
work with other compilers I've used.
Depending on what you really want to do Mark Odell's solution may be the
best route to take.
Regards
Sergio Masci
http://www.xcprod.com/titan/XCSB - optimising structured PIC BASIC compiler
Reply by Hans-Bernhard Broeker●March 31, 20042004-03-31
Mark <yodai@spamnot.mail.vu> wrote:
> Hey all.... I'm trying to do something that should be easy, but my compiler
> doesn't allow me...
Your belief that this should be easy is, unfortunately, misguided.
> I am trying to define a variable into a certain memory
> position and then assign a default value for it....
There's no way you'll manage to express that behaviour in remotely
portable C code.
Your particular C compiler, or rather the linker, in whose domain this
problem actually lies, will undoubtedly offer some way of doing this.
> #define _CLAVE1 ((uint16_t*)0xD000)
As Mark already said, don't use names like this --- they're not yours
to play with.
Furthermore this expression already by its very definition causes
unpredictable results. Constructing a pointer from an integer like
this *may* work, but there's generally no guarantee whatsoever that it
will still work the same way tomorrow, let alone next year, or on a
different compiler (version).
> Any idea on how to define a memory position and it's initial value without
> initialising the value from inside the program?
Avoiding this initialization "from inside the program" is a pointless
exercise. What do you think how this variable will be initialized by
the compiler if you manage to get it to do it? The effect will be
exactly the same as if you had done it by an assignment
CLAVE1 = 99;
near the beginning of main(). The only real difference will be that
it's done by code automatically created by the compiler rather than
written by you, and that code may be a bit more efficient (it's
typically a kind of memcpy() from code memory to data memory).
--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply by Mark A. Odell●March 31, 20042004-03-31
On Wed, 31 Mar 2004 13:59:47 GMT, "Mark" <yodai@spamnot.mail.vu>
wrote:
>I've already had Mark A. Odell answer this question saying this can't be
>done portably. He also sugested me coming to this group with the question
>see if anyone here has some idea on how to do this... I am working on a
>MSP430 and using IAR ew compiler...
>
><reposted>
>Hey all.... I'm trying to do something that should be easy, but my compiler
>doesn't allow me... I am trying to define a variable into a certain memory
>position and then assign a default value for it....
>
>#define _CLAVE1 ((uint16_t*)0xD000)
From a C perspective, avoid creating any user name with a leading '_'
symbol as most permutations of these names are reserved for
implementations.
For this particular set of tools...
Be sure you have your own .xcl file (just copy the default one to
another name and refer to it via xlink -f mylinkerfile.xcl) and create
a new data segment in the .xcl file. Something like:
// Put this in your .xcl file: CODE=FLASH, DATA=RAM
-Z(CODE)CLAVE1=D000-D001
Now, just tell the compiler to emit a section directive to the
compiler in your C source file.
// Put this in your C file. If it is to be read-only add const
// and if it needs to be available to many files drop the static
// extern it in an h file.
#pragma memory=constseg(CLAVE1)
static volatile uint16_t hw_clave1 = 99;
#pragma memory=default
Now you can read and write hw_clave1 without pointer notation.
if (hw_clave1 == 99)
{
// take some action
}