[Fwd: Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-14 Thread Robert von Knobloch
Robert,

Could you please forward this to the list? My posts are still being
blocked. The one below was sent only to the list, but it's not there on
http://lists.gnu.org/pipermail/avr-gcc-list .

Thanks,
Erik

On Mon, May 11, 2009 at 10:30:40PM +1000, Erik Christiansen wrote:
 On Mon, May 11, 2009 at 02:13:41PM +0200, Jan Waclawek wrote:
  Robert,
  
  There is some difference, though: you can't count on such variables to be 
  initialised to zero.
  
 
 Unless you add a custom  initialisation loop to crt0, or similar. ;-)
 
 Erik

OK Erik, forwarded.

Robert





___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


[Fwd: Re: [Re: [avr-gcc-list] Allocating variables to a fixed address]]

2009-05-14 Thread Robert von Knobloch
On Wed, May 13, 2009 at 01:16:31PM +0200, Robert von Knobloch wrote:

 
 Curiously I could not use e.g.
 
 asm (test_pgm_read_byte:jmp pgm_read_byte);
 undefined reference to 'pgm_read_byte' although it is defined and in
 scope.
 
 Where pgm_read_byte is a library function from avr-libc.
 I had to supply a stub function of my own [flash_read_byte()] to, in
 turn,  call pgm_read_byte()
 and then it was happy :-)

Did you have a .global pgm_read_byte in your assembler code?;-)
That is needed to make the symbol public across compile units, and I
can't see it in your example.

Could you please forward this to the list also, because I'm still
not able to post.

mfG,
Erik

OK Erik -forwarded.
No, I didn't - but now fixed.
Thanks,

Robert





___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


[Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-13 Thread Robert von Knobloch
Stu Bell wrote:

  If I had your problem, this is how I would solve it: Define a real table
  of function pointers instead of trying to get the linker to create one
  for you.
  
typedef void (*TestProc) (void*);
  
NOINLINE void test_lcd_2(void* pStr) {PGM_P string = (PGM_P) pStr;
  prog_lcd_string2(string); }
  
NOINLINE void test_lcd_string(void* pStr) { PGM_P string = (PGM_P)
  pStr; prog_lcd_string(string); }
  
NOINLINE void test_clearlcd2(void* ign) { clearlcd2(); }
  
NOINLINE void test_lcd_hex4out(void* pByte) { uint8_t byte = *
  (uint8_t*) pByte; return lcd_hex4out(byte); }
  
...
  
const TestProc* TestTable[TEST_VECTORS] FUNCTION_SECTION = {
   test_lcd_2,
   test_lcd_string,
...
};
  
  You will need to modify your calls to either send the pointer to the
  argument (this forces all calls to have a single parameter of,
  essentially, a word) or to always send a word.  In either case, the
  receiving routine will then cast the argument to the proper value before
  passing it on. 
  
  Do not place the routines or other constants in the same linker section
  as the function table.  If you leave the table in a section of its own,
  it will always be placed at the head of the section without interference
  from anything else.
  
  Calling the function requires you to pull the function out of the table
  before calling it:
  
 #define TESTPROC_LCD_2  0
 #define TESTPROC_LCD_STRING 1
 . . .
  
 uint16_t test_proc;
  
 test_proc = pgm_read_word( (uint16_t) TestTable[ TESTPROC_LCD_2 ] );
 *(TestProc*)test_proc( myarg );
  
 . . .
  
  You could probably enclose the above stuff in a macro to make your code
  far more readable:
  
 #define CallTestProc(proc,arg) \ 
do {\
 uint16_t test_proc;\
 test_proc = pgm_read_word( (uint16_t) TestTable[ (proc) ] );
  \
 *(TestProc*)test_proc( (arg) ); \
} while (0);
   
  . . .
  
  CallTestProc( TESTPROC_LCD_2, myarg );
  
  That's my inspiration for the day.  It's probably wrong somewhere, but
  it's how I would approach the problem.
Hi Stu,

This solution, while a purer 'C' solution would require me to have all
my 'internal' functions with similar call/return requirements.
This is not, and cannot be, the case. I fear that the magig 'array of
function pointers' has only limited use and is unsuitable here.
But many thanks for your thoughts, every comment here makes me re-think
the problem, which is good.

Cheers,

Robert


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


[Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-13 Thread Robert von Knobloch
Thanks to all who have helped me to get the best solution.
I have eventually decided that an assembler jump table was really the
best in my application:
/*
 **
 *   Function entry points for independent test routines
 **
 */

// Function declarations
void test_lcd_2(PGM_P);
void test_lcd_string(PGM_P);
.
. //Snip/
.
void test_flash_read(uint16_t);
void test_flash_write(uint8_t, uint8_t);

void jumptable(void) __attribute__((__naked__));
FUNCTION_SECTION void jumptable(void)
{
asm (test_lcd_2:jmp prog_lcd_string2);
asm (test_lcd_string:jmp prog_lcd_string);
.
. //Snip/av
.
asm (test_pgm_read_byte:jmp flash_read_byte);
asm (test_pgm_read_word:jmp flash_read_word);
 }
==

Curiously I could not use e.g.

asm (test_pgm_read_byte:jmp pgm_read_byte);
undefined reference to 'pgm_read_byte' although it is defined and in
scope.

Where pgm_read_byte is a library function from avr-libc.
I had to supply a stub function of my own [flash_read_byte()] to, in
turn,  call pgm_read_byte()
and then it was happy :-)

Thanks to all,

Robert.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-13 Thread Bernard Fouché


Robert von Knobloch wrote:

Curiously I could not use e.g.

asm (test_pgm_read_byte:jmp pgm_read_byte);
undefined reference to 'pgm_read_byte' although it is defined and in
scope.

Where pgm_read_byte is a library function from avr-libc.
  

I think this is because pgm_read_byte() is a macro.

Now another mechanism could have been setup: using an external interrupt 
pin to generate a software interrupt, and using that software interrupt 
to perform calls to functions in a PC BIOS way: in that case the caller 
need not to know the location of the called functions, the interrupt 
driver compiled and linked with the main application uses its own jump 
table which is not exposed to external modules. However the API setup is 
more complex since you have to pass the 'function id' of the called 
functions in some register before generating the software interrupt.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-12 Thread Robert von Knobloch
David Kelly wrote:
 On Mon, May 11, 2009 at 08:21:37AM -0600, Weddington, Eric wrote:
   
 Sounds to me as if you are making the bootloader too big and
 should simply link an entire application for every possible 
 target. What you are doing would make more sense if the loadable
 modules could run out of RAM.
 
 That would be no use, the loadables must be non-volatile. This is a
 tester that will be sent to a factory (somewhere). When a new
 product is to be tested, I can e-mail them the test routine which
 they then burn into flash (each of these is 0x900 bytes, there can
 be up to 0x0a of them).
   
 Why is this method superior to having a regular bootloader, and you
 have N applications, where each application is the individual test
 routine and the common portion? Why do you have create this custom
 interface which has its own set of problems? Alternatively, creating a
 custom Makefile to handle building 10 different applications is
 certainly easier in comparison.
 

 I agree, thats how I would handle it. Either build a custom linked
 application for each customer or provide the customer with the tools to
 build one of their own. What he is trying to do is in effect create a
 run time program linker.

   
Eric, David etc.,

Thanks for the suggestions but it seems I haven't explained the problem
properly.
The end users of this equipment will be factory operators who cannot
compile, link or do any of these software things.
Thus I have developed an extremely simple (read idiot-proof [i hope])
interface to use with a terminal program (minicom, teraterm etc.).
This is far more simple than any existing boot loader (OK, I *could*
write my own, but I'm too far along now).
The loadable elements are small (0x900) and will only ever be updated
one at a time.
If I compiled and linked the whole lot, then each small change would
requite the sending  loading of 64k of code, which I think is much too
much for these people (and, for compatibilty with modern PCs, the comms.
is run over a USB virtual RS-232 port which produces far too many serial
errors for my liking - but that's another issue).
I have the entire application written and am knocking the last bugs out now.
I confess that GCC seems to me to be mostly something to fight with,
perhaps I have been spoiled in the past using manufacturer's C compliers
that were tailored especially for the target.
I simply require a way to fix absolutely this jump table in memory.
Whether I write it in C or assembler seems to me to be irrelevant, as is
using an array of pointer to functions, because I still have the problem
of fixing these at absolute addresses.

If anyone knows a way to do this, I would very much appreciate it.

Many thanks for all the input,

Robert.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-12 Thread Robert von Knobloch
Erik Christiansen wrote:
 I confess that GCC seems to me to be mostly something to fight with,
 perhaps I have been spoiled in the past using manufacturer's C compliers
 that were tailored especially for the target.
 

 It just requires leisure time for study and experimentation. ;-)

   
 I simply require a way to fix absolutely this jump table in memory.
 Whether I write it in C or assembler seems to me to be irrelevant, as is
 using an array of pointer to functions, because I still have the problem
 of fixing these at absolute addresses.

 If anyone knows a way to do this, I would very much appreciate it.
 

 Robert, if the table is made __attribute__ ((section(.table))) , and
 section .table is linked in after the vectors, but prior to any code, then
 its location will be fixed, won't it? In the old linker script I have to
 hand, that places it here:-.
|
   .text :  |
   {|
  __code_start = . ;|
 *(.vectors)   /
 *(.table)   '
  __ctors_start = . ;
  *(.ctors)

 Having shipped firmware to similarly skill constrained recipients, I saw
 from the OP why you're doing it this way. Nor would I hesitate to do the
 same, as need (or convenience) arises. After all, how much does it
 differ from the fixed addresses of BIOS calls in CP/M, or its imitator,
 MS-DOS?

 The method seems particularly attractive where the operators would load
 combinations of modules, perhaps with multiples of some, without the
 need for you to build every combination. (Most painful where there could
 be hundreds of them.)

 mfG,

 Erik

 P.S. If this post doesn't appear on the list, would you mind forwarding
  it? For the last half year, none of my posts have gone through,
  AFAIR.
   
Aha !
Yes Erik, this is exactly the way I think. In fact it's slightly more
complex because I use the same download mechanism to load images that
will be flashed into target products with embedded AVR processors. These
are, of course, not native code for my host programmer.
It is from this necessity that I devised the original method and
extended it to the test routines.
I am not exactly a young programmer and grew up with many operating
systems and machines (Intel ISIS - Motorola Exorset, OS9 etc.). All of
the used a similar approach as does indeed BIOS (to call MSDOS an
imitator of CP/M insults CP/M IMHO but still..)
My solution (non-working till now) is, in principle, the same as your
suggestion except I chose a section originating at 0xff00 (after all the
.text sections) which may not work well with GCC - it randomises the
order of my 'vector table'. (Old experience with Motorola processors
makes one tend toward the high address end, of course the AVR
architecture is different here). Would you know why this won't happen if
I relocate the table as you suggest - just because it would then be
before any real code ?
I have had another promising suggestion (off-list) that makes the main
code write the addresses of its public functions to the eeprom, where
the loadable code could find them and use as function pointers.
I will try both and see how far I get.
Have included your posting in my answer so that it gets on the list.

Many thanks,

Robert



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-12 Thread Jan Waclawek
I simply require a way to fix absolutely this jump table in memory.
Whether I write it in C or assembler seems to me to be irrelevant, as is
using an array of pointer to functions, because I still have the problem
of fixing these at absolute addresses.

If anyone knows a way to do this, I would very much appreciate it.


The attachment illustrates what I mean by jumptable in asm, and its usage (see 
main). Address of .mysection was fixed to 0x00FF by passing it to the linker 
through avr-gcc (-Wl,--section-start,.mysection=0xFF00). 

It of course can be a separate asm file, and the individual lines can be 
generated by a handy macro; but those are only unimportant details.

Enjoy! ;-)

JW



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


[Fwd: Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-12 Thread Robert von Knobloch
Jan Waclawek wrote:
 I simply require a way to fix absolutely this jump table in memory.
 Whether I write it in C or assembler seems to me to be irrelevant, as is
 using an array of pointer to functions, because I still have the problem
 of fixing these at absolute addresses.

 If anyone knows a way to do this, I would very much appreciate it.
 


 The attachment illustrates what I mean by jumptable in asm, and its usage 
 (see main). Address of .mysection was fixed to 0x00FF by passing it to the 
 linker through avr-gcc (-Wl,--section-start,.mysection=0xFF00). 

 It of course can be a separate asm file, and the individual lines can be 
 generated by a handy macro; but those are only unimportant details.

 Enjoy! ;-)

 JW



   
Thanks Jan,
This is effectively what I have done, except I used C stubs instead of
assembler:

[.section origin is at 0xff00]
void test_func_1(uint16_t foo)
{
func_1(foo);
}
void test_func_2(uint16_t foo)
{
func_2(foo);
}

Why would the compiler respect assembler any more than my C calls (it
changes the order of them as they are stored in memory, so I cannot
guarantee the address of test_func_1())

If GCC will respect the order of the assembler jumps (and thus the
absolute address) then that is my easiest solution. At the moment I
can't really see any difference between assembler and C here. Or does
someone know better ?

You see I really distrust the compiler now :-)

Robert




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-12 Thread Graham Davies

Robert von Knobloch wrote:

Why would the compiler respect assembler any more than my C calls (it
changes the order of them as they are stored in memory, so I cannot
guarantee the address of test_func_1())


There is nothing in the C language that tells the compiler to preserve the 
ordering of global and static objects.  GCC is perfectly within its rights 
to change the order of your functions.  To preserve their relative order, 
you need to use function pointers and make them elements in a single array 
or structure which, if you avoid padding, will have the memory layout you 
expect.  Or, use assembler, which the compiler won't mess with.


Graham.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [Fwd: Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-12 Thread Robert von Knobloch
Jan Waclawek wrote:
 Why would the compiler respect assembler any more than my C calls 
 


 Because the compiler knows nothing on assembly language. It simply passes it 
 as a string to the assembler: it does not attempt to parse it (except for the 
 escape sequences), so it has no chance to modify the order of anything.

 On the other hand, a compiler is free to do whatever it wants to do with 
 statements you pass to it: it can reorder and insert voids wherever and 
 whenever it wants. This is the very principle of high level languages: you 
 give up part of control in exchange of increase in convenience. If you want 
 to re-gain control for whatever reason, the best thing to do is to revert to 
 assembler.

 As I said, you can make this a standalone assembler source, if you feel more 
 comfortable with it, and the link it together. The same thing can be done 
 with variables, see attachment - this avoids the need to put all variables 
 into a single struct (to ensure their fixed order); but I don't say this is 
 the best way to do with variables.

 JW
Jan,

OK, sounds good, If GCC really will leave my assembler alone then that
would be the best way to go.
I am no longer so worried about the variables, although they were my
original concern - I have written helper functions which make them
transparent to the 'other side' and I think this is better practice. All
I need now is the jump table...

David,
 While it's good practice to design your protocol to handle errors,
you shouldn't be seeing ANY errors wether or not the port is USB.  I'd
look to solving  that problem.  Are you sure that your baud rate is
correct?

Yes, quite sure. This is a known (to me) issue with FDDI USB to serial
chips. If use a level converter and 'proper' RS-232 with the same setup
I never ever get an error. The receive side uses a circular buffer with
high  low water marks and therefore can do 'proper' handshaking.
 It's just that i cannot rely on a modern (cheap) PC having a serial
bus. The errors are only very occasionally, hardly an issue with my data
volumes. They would become a problem if I started transferring large chunks.
Tracking the FDDI down will have to wait.

Many thanks for all your comments, they are really a big help,

Robert


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [Fwd: Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-12 Thread Robert von Knobloch
Erik Christiansen wrote:
 On Tue, May 12, 2009 at 02:26:38PM +0200, Jan Waclawek wrote:
   
 On the other hand, a compiler is free to do whatever it wants to do
 with statements you pass to it: it can reorder and insert voids
 wherever and whenever it wants. This is the very principle of high
 level languages: you give up part of control in exchange of increase
 in convenience. If you want to re-gain control for whatever reason,
 the best thing to do is to revert to assembler.
 

 While I would, based on experience with gcc on various targets, have
 expected multiple functions from one compile unit to end up in .text in
 the same order as they appear in the source code, we can enforce the
 order if that doesn't happen. Just put each of the ten functions (there
 were 0x0a of them, IIRC) in a separate section, e.g. mit_gewalt_0 to
 mit_gewalt_9, using __attribute__ ((section(.xxx))) . Then in the
 linker script:

   /* Ok, it is the table which was to be */
.mit_gewalt_0 0xff00 : /* at 0xff00? Use another address to   */
{ .mit_gewalt_0 }  text   /* fix the location of the functions?  */

.mit_gewalt_1 : AT ( ADDR(.mit_gewalt_0) + SIZEOF(.mit_gewalt_0) )
{ .mit_gewalt_1 }  text

.mit_gewalt_2 : AT ( ADDR(.mit_gewalt_1) + SIZEOF(.mit_gewalt_1) )
{ .mit_gewalt_2 }  text
etc.

 One caveat: It's a while since I did such things regularly, so there
 might be a typo|thinko in there, given the hour and the fact I'm not
 allowed coffee.

 The gnu tools are flexible enough to do most thing several ways, either
 in C or assembler, or (often conveniently) with a mix.

 In a post which I don't yet see on the list, Robert wrote:

   
 I chose a section originating at 0xff00 (after all the .text sections)
 which may not work well with GCC - it randomises the order of my
 'vector table'.
 

 But if that is just an array of function pointers, then it's the
 programmer who initialises it, isn't it? Then the order of entries is
 fixed in code, and only the pointer values may be randomised if care is
 not taken to prevent the possibility.

 mfG,
 Erik

 P.S. Aaaah, when I cut my teeth on the Siemens grey version of the Intel
 ISIS blue box, you could count the macros being assembled,
 by the one long and four short head seeks on the 8.5 floppy drives,
 taking several seconds. There was more than time enough for too much
 coffee back then. :-)

 P.P.S. Looks like this needs to be forwarded to the list too.
(Perhaps the dynamic IP range that I'm in is blocked?)
   
Hi Erik,

it seems that your block has been lifted.

I had the ISIS box (8008 I think) plus the drives (they were 7,
following the sizes of music records at first).
The head seeks were often drowned by the teleprinter I had as hard copy
device, but yes, you got used to the rhythms and knew when an assembly
was finishing.
/nostalgia

Thinking about your answer, yes an array of pointers (and nothing else
in the section) could be a good answer. GCC can't randomise the subscripts.
I had simply written a sequence of stub functions, but their written
order is not the order they appear in in code.
I like your 'mit Gewalt' solution, it could also work - just need to be
careful not to waste too much space - i.e. know the sizes of the functions.

Many thanks,

Robert



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread Jan Waclawek
Robert,

There is some difference, though: you can't count on such variables to be 
initialised to zero.

JW


- Original Message ---

Schwichtenberg, Knut wrote:
 Robert,

 there is no difference in handling. So create your special section and put 
 the variables into it as you would do it with the flash.

 Cheers
 Knut 

   
 -Original Message-

 Is there any way of 'fixing' a few, specific global variables 
 at a known
 
Thanks Knut, I couldn't find this documented and I expected the Harvard
architecture to make life difficult.
It's nice when the answer is simple.



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


[Fwd: Re: [avr-gcc-list] Allocating variables to a fixed address]

2009-05-11 Thread Robert von Knobloch
Jan Waclawek wrote:
 Robert,

 There is some difference, though: you can't count on such variables to be 
 initialised to zero.

 JW
   
This is obvious, I think, but thanks for the tip anyway.

Robert




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread Weddington, Eric
 

 -Original Message-
 From: 
 avr-gcc-list-bounces+eric.weddington=atmel@nongnu.org 
 [mailto:avr-gcc-list-bounces+eric.weddington=atmel@nongnu.
 org] On Behalf Of Robert von Knobloch
 Sent: Monday, May 11, 2009 3:39 AM
 To: avr-gcc-list@nongnu.org
 Subject: [avr-gcc-list] Allocating variables to a fixed address
 
 Is there any way of 'fixing' a few, specific global variables 
 at a known
 location?
 In flash, I can use a '.section' to do this. Is there an 
 equivalent for ram?
 I notice that the compiler puts static variables before globals, which
 make it impossible to predict where the globals will be.
 I am writing modular software and to be version independant, I must
 define a simple API.
 I have flash under control, but now ram is the problem.

Why do you need global variables to be at a specific address?


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread Robert von Knobloch
Weddington, Eric wrote:
 Why do you need global variables to be at a specific address?
   
Because my software consists of a:
A fixed part - main plus User Interface - This is test equipment for
small electronic products
and
Several loadable parts which can be loaded via rs232 as Intel hex and
'blown' into the flash as required - These are custom-built for each
product.
The entire code is one entity, loadables will be added and removed and I
cannot have this affecting the main code.

I need separation so that updates to any part of the software do not
disturb the relationship between the main part and the 'loadable' parts.
To this end, I need to fix all calls  variables that are common to the
2 parts of the system - what I am calling an 'API'.

I thought that I had the flash part all under control but now see that
the compiler is out to get me again:

I have defined all cross-module routines and give them 'psuedo-calls' in
a vector table so:

/*
**
* Function entry points for independent test routines
**
*/

// LCD Display
FUNCTION_SECTION NOINLINE void test_lcd_2(PGM_P string)
{
prog_lcd_string2(string);
}

FUNCTION_SECTION NOINLINE void test_lcd_string(PGM_P string)
{
prog_lcd_string(string);
}

FUNCTION_SECTION NOINLINE void test_clearlcd2(void)
{
clearlcd2();
}

FUNCTION_SECTION NOINLINE void test_lcd_hex4out(uint8_t byte)
{
return lcd_hex4out(byte);
}

FUNCTION_SECTION NOINLINE void test_lcd_hex8out(uint8_t byte)
{
return lcd_hex8out(byte);
}

FUNCTION_SECTION NOINLINE void test_lcd_hex16out(uint16_t word)
{
return lcd_hex16out(word);
}
../snip

Where FUNCTION_SECTION is located at 0xff00

Now I see that the compiler is no longer preserving the order of these
vectors:

avr-nm -n main.elf gives:

ff00 T test_read_mSecDownCnt
ff10 T test_write_mSecDownCnt
ff1e T test_geta2d
ff3c T test_nSec400Wait
ff42 T test_lcd_hex4out
ff48 T test_lcd_hex8out
ff4e T test_lcd_hex16out
ff54 T test_lcd_string
ff5a T test_clearlcd2
ff60 T test_lcd_2
ff66 T test_milliSecDelay
ff6c T test_getkey
ff72 T test_getkey_blink
ff78 T test_pollkey
ff7e T test_isp_connect
ff84 T test_flash_read
ff8a T test_flash_write
ff90 T test_eeprom_read
ff96 T test_eeprom_write
ff9c T test_fuse_read
ffa2 T test_fuse_write
ffa8 T test_isp_disconnect

Is there a way to achieve this? The project is much too big for
assembler (not enough time  maintenance).
I can force variable access through functions, of couse. But this
doesn't help when I can't trust my vector table to stay constant.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread David Kelly
On Mon, May 11, 2009 at 02:55:17PM +0200, Robert von Knobloch wrote:
 Weddington, Eric wrote:
  Why do you need global variables to be at a specific address?

 Because my software consists of a:
 A fixed part - main plus User Interface - This is test equipment for
 small electronic products
 and
 Several loadable parts which can be loaded via rs232 as Intel hex and
 'blown' into the flash as required - These are custom-built for each
 product.
 The entire code is one entity, loadables will be added and removed and I
 cannot have this affecting the main code.

Sounds to me as if you are making the bootloader too big and should
simply link an entire application for every possible target. What you
are doing would make more sense if the loadable modules could run out of
RAM.

-- 
David Kelly N4HHE, dke...@hiwaay.net

Whom computers would destroy, they must first drive mad.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread Robert von Knobloch
David Kelly wrote:
 Sounds to me as if you are making the bootloader too big and should
 simply link an entire application for every possible target. What you
 are doing would make more sense if the loadable modules could run out of
 RAM.
That would be no use, the loadables must be non-volatile.
This is a tester that will be sent to a factory (somewhere).
When a new product is to be tested, I can e-mail them the test routine
which they then burn into flash (each of these is 0x900 bytes, there can
be up to 0x0a of them).
This will never be so often as to compromise the flash lifetime, but I
must create a system whereby the 'resident' code is fixed (but
maintainable) and the loadable parts can be freely added, overwritten
etc. I think you will see that this needs the interface to be completely
fixed (variable access, call locations) for all common parts, while the
internals of e.g. the resident part is immaterial to the loadables.
Provided strict adherence to the interface is observed, then a working
system is realisable (I have written such systems in the past but not
with AVRs or GCC).
To realise this interface (API), I must be able define the
variables/function calls in the resident part at known (or. at least
fixed) addresses.

Robert


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread Weddington, Eric
 

 -Original Message-
 From: 
 avr-gcc-list-bounces+eric.weddington=atmel@nongnu.org 
 [mailto:avr-gcc-list-bounces+eric.weddington=atmel@nongnu.
 org] On Behalf Of Robert von Knobloch
 Sent: Monday, May 11, 2009 7:57 AM
 To: avr-gcc-list@nongnu.org
 Subject: Re: [avr-gcc-list] Allocating variables to a fixed address
 
 David Kelly wrote:
  Sounds to me as if you are making the bootloader too big 
 and should
  simply link an entire application for every possible 
 target. What you
  are doing would make more sense if the loadable modules 
 could run out of
  RAM.
 That would be no use, the loadables must be non-volatile.
 This is a tester that will be sent to a factory (somewhere).
 When a new product is to be tested, I can e-mail them the test routine
 which they then burn into flash (each of these is 0x900 
 bytes, there can
 be up to 0x0a of them).

Why is this method superior to having a regular bootloader, and you have N 
applications, where each application is the individual test routine and the 
common portion? Why do you have create this custom interface which has its own 
set of problems? Alternatively, creating a custom Makefile to handle building 
10 different applications is certainly easier in comparison.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread Weddington, Eric

The jumptable could just as easily be written in C. 

 -Original Message-
 From: 
 avr-gcc-list-bounces+eric.weddington=atmel@nongnu.org 
 [mailto:avr-gcc-list-bounces+eric.weddington=atmel@nongnu.
 org] On Behalf Of Jan Waclawek
 Sent: Monday, May 11, 2009 8:21 AM
 To: Robert von Knobloch; avr-gcc-list@nongnu.org
 Subject: Re: [avr-gcc-list] Allocating variables to a fixed address
 
 
 I'd write the *jumptable* in asm. That's easy and means one 
 less degree of freedom for the compiler and co.
 
 JW
 
 -Original Message-
 To realise this interface (API), I must be able define the
 variables/function calls in the resident part at known (or. at least
 fixed) addresses.
 
 
 
 
 ___
 AVR-GCC-list mailing list
 AVR-GCC-list@nongnu.org
 http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
 


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread Stu Bell
 I have defined all cross-module routines and give them 
 'psuedo-calls' in a vector table so:
 
 /*
 **
 
 * Function entry points for independent test routines
 **
 
 */
 
 // LCD Display
 FUNCTION_SECTION NOINLINE void test_lcd_2(PGM_P string) { 
 prog_lcd_string2(string); }
 
 FUNCTION_SECTION NOINLINE void test_lcd_string(PGM_P string) 
 { prog_lcd_string(string); }
 
 FUNCTION_SECTION NOINLINE void test_clearlcd2(void) { clearlcd2(); }
 
. . .
 Where FUNCTION_SECTION is located at 0xff00
 
 Now I see that the compiler is no longer preserving the order of these
 vectors:
 
 avr-nm -n main.elf gives:
 
 ff00 T test_read_mSecDownCnt
 ff10 T test_write_mSecDownCnt
 ff1e T test_geta2d
 ff3c T test_nSec400Wait
 ff42 T test_lcd_hex4out
 ff48 T test_lcd_hex8out
. . .
 Is there a way to achieve this? The project is much too big 
 for assembler (not enough time  maintenance).
 I can force variable access through functions, of couse. But 
 this doesn't help when I can't trust my vector table to stay constant.
 


If I had your problem, this is how I would solve it: Define a real table
of function pointers instead of trying to get the linker to create one
for you.

  typedef void (*TestProc) (void*);

  NOINLINE void test_lcd_2(void* pStr) {PGM_P string = (PGM_P) pStr;
prog_lcd_string2(string); }

  NOINLINE void test_lcd_string(void* pStr) { PGM_P string = (PGM_P)
pStr; prog_lcd_string(string); }

  NOINLINE void test_clearlcd2(void* ign) { clearlcd2(); }

  NOINLINE void test_lcd_hex4out(void* pByte) { uint8_t byte = *
(uint8_t*) pByte; return lcd_hex4out(byte); }

  ...

  const TestProc* TestTable[TEST_VECTORS] FUNCTION_SECTION = {
 test_lcd_2,
 test_lcd_string,
  ...
  };

You will need to modify your calls to either send the pointer to the
argument (this forces all calls to have a single parameter of,
essentially, a word) or to always send a word.  In either case, the
receiving routine will then cast the argument to the proper value before
passing it on. 

Do not place the routines or other constants in the same linker section
as the function table.  If you leave the table in a section of its own,
it will always be placed at the head of the section without interference
from anything else.

Calling the function requires you to pull the function out of the table
before calling it:

   #define TESTPROC_LCD_2  0
   #define TESTPROC_LCD_STRING 1
   . . .

   uint16_t test_proc;

   test_proc = pgm_read_word( (uint16_t) TestTable[ TESTPROC_LCD_2 ] );
   *(TestProc*)test_proc( myarg );

   . . .

You could probably enclose the above stuff in a macro to make your code
far more readable:

   #define CallTestProc(proc,arg) \ 
  do {\
   uint16_t test_proc;\
   test_proc = pgm_read_word( (uint16_t) TestTable[ (proc) ] );
\
   *(TestProc*)test_proc( (arg) ); \
  } while (0);
 
. . .

CallTestProc( TESTPROC_LCD_2, myarg );

That's my inspiration for the day.  It's probably wrong somewhere, but
it's how I would approach the problem.

Best regards, 

Stu Bell 
DataPlay (DPHI, Inc.) 






___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread David Kelly
On Mon, May 11, 2009 at 03:56:34PM +0200, Robert von Knobloch wrote:
 David Kelly wrote:
  Sounds to me as if you are making the bootloader too big and
  should simply link an entire application for every possible target.
  What you are doing would make more sense if the loadable modules
  could run out of RAM.

 That would be no use, the loadables must be non-volatile.
 This is a tester that will be sent to a factory (somewhere).
 When a new product is to be tested, I can e-mail them the test routine
 which they then burn into flash (each of these is 0x900 bytes, there
 can be up to 0x0a of them).

Yes, what I said before, link an entire application for every possible
target. If a factory needs a new module added to their tester then link
an application with all the modules they need if you are not able to
make a single application that supports all known modules.

Another way to pull this off would be to ship the avr-ln application,
object files, and let the customer link their selected module set to
flash the tester. You could wrap everything up and hide the process in a
script or application. Strip the debugging stubs from the object files
but leave the linking symbols.

Otherwise for an example of how to statically allocate global variables
look in the include files for how registers are defined.

-- 
David Kelly N4HHE, dke...@hiwaay.net

Whom computers would destroy, they must first drive mad.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Allocating variables to a fixed address

2009-05-11 Thread David Kelly
On Mon, May 11, 2009 at 08:21:37AM -0600, Weddington, Eric wrote:
   Sounds to me as if you are making the bootloader too big and
   should simply link an entire application for every possible 
   target. What you are doing would make more sense if the loadable
   modules could run out of RAM.
  That would be no use, the loadables must be non-volatile. This is a
  tester that will be sent to a factory (somewhere). When a new
  product is to be tested, I can e-mail them the test routine which
  they then burn into flash (each of these is 0x900 bytes, there can
  be up to 0x0a of them).
 
 Why is this method superior to having a regular bootloader, and you
 have N applications, where each application is the individual test
 routine and the common portion? Why do you have create this custom
 interface which has its own set of problems? Alternatively, creating a
 custom Makefile to handle building 10 different applications is
 certainly easier in comparison.

I agree, thats how I would handle it. Either build a custom linked
application for each customer or provide the customer with the tools to
build one of their own. What he is trying to do is in effect create a
run time program linker.

-- 
David Kelly N4HHE, dke...@hiwaay.net

Whom computers would destroy, they must first drive mad.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list