Reply by Alex Colvin April 1, 20042004-04-01
>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&#4294967295; 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 }