Cross Posting: Pointer to functions

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

Hi,

the bootloader I'm using has a function jump-table at the beginning. I will extend this jump table with some other functions. For debugging purposes as well as for accessing the functions normally I've created the following:

This is for debugging:
__attribute__ ((section (".boot"))) void start(void)
{
asm volatile(
"\tjmp boot_0\n" // Hardware reset ...
"\tjmp boot_1\n" // Entry point if..
);
}
The used segment is located by the linker to the correct address. Later this structre will reside as a separate object in the flash.

Within my C-function I defined the following, which might be too small to describe the assembler jump's:

typedef struct {
void (* boot_0) (void);
void (* boot_1) (void);
} t_Blif;

t_Blif bvect; // Bootloader Vector

int main (void) {
...
void (*bvect) (void)= 0x7000; // Which is 0x3800 *1
bvect(); // This is valid
bvect.boot_1(); // This is not valid *2
...
}

GCC-3.4.6 messages:
*1: warning: initialization makes pointer from integer without a cast
*2: error: request for member `boot_1' in something not a structure or union

What's wrong with both marked lines? I would like to access functions in the bootloader area from the application by a structure element name. I've seen some examples showing the usage of an array instead of a structure - which I don't like.

Any comments are welcome.

Knut

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

But the scope of the local "bvect" you are defining inside main() will hide the global bvect structure outside. Try calling the two variables of different types different names!

Cliff

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

Yup, the following compiles without error:

#include 

typedef struct { 
void (* boot_0) (void); 
void (* boot_1) (void); 
} t_Blif; 

t_Blif gbvect; // Bootloader Vector 

int main (void) { 
void (*bvect) (void)= 0x7000; // Which is 0x3800 *1 
 bvect(); // This is valid 
 gbvect.boot_1(); // This is not valid *2 
}

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

Cliff,
thanks for your reply. It points me to the right direction, but it's also not all :wink:

clawson wrote:
Yup, the following compiles without error:

#include 

typedef struct { 
void (* boot_0) (void); 
void (* boot_1) (void); 
} t_Blif; 

t_Blif gbvect; // Bootloader Vector 

int main (void) { 
void (*bvect) (void)= 0x7000; // Which is 0x3800 *1 
 bvect(); // This is valid 
 gbvect.boot_1(); // This is not valid *2 
}


The point is gbvect.boot_1 should point to 0x3802 which is not done by your solution. I've tried:

t_Blif * gbvect; // Bootloader Vector 
gbvect = (t_Blif *) 0x7000;
gbvect->boot_0();

That compiles but leads to wrong assembler:

lds	r30, 0x7000
lds	r31, 0x7001
icall          

What I want to see is (or mostly...)

ldi	r30, 00
ldi	r31, 0x70
icall          

Knut

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

typedef struct {
  void (* boot_0) (void);
  void (* boot_1) (void);
} t_Blif;

static const t_Blif gbvect = {
  .boot_0 = (void (*)(void)) 0x7000,
  .boot_1 = (void (*)(void)) 0x7002
};

int main (void) {
  gbvect.boot_0(); 
  gbvect.boot_1(); 

  return 42;
}

Resulting assembly code:

        .file   "foo.c"
        .arch atmega32
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
        .global __do_copy_data
        .global __do_clear_bss
        .text
.global main
        .type   main, @function
main:
/* prologue: frame size=0 */
/* prologue end (size=0) */
        ldi r30,lo8(28672)
        ldi r31,hi8(28672)
        icall
        ldi r30,lo8(28674)
        ldi r31,hi8(28674)
        icall
        ldi r24,lo8(42)
        ldi r25,hi8(42)
/* epilogue: frame size=0 */
        ret
/* epilogue end (size=1) */
/* function main size 9 (8) */
        .size   main, .-main
/* File "foo.c": code    9 = 0x0009 (   8), prologues   0, epilogues   1 */

(28672 == 0x7000)

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Knut meanwhile wrote me an email that he sees this is OK, but he
didn't like it, and I finally started to understand what he was
*really* thinking of.

Knut, how about that one?

#include 

typedef void (*vector_entry) (void);

static const vector_entry *vectable = (const vector_entry *)0x7000;

int main (void) {
  vectable[0]();
  vectable[1]();

  return 42;
}

Generated assembly:

	.file	"knut.c"
	.arch atmega32
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
	.global __do_copy_data
	.global __do_clear_bss
	.text
.global	main
	.type	main, @function
main:
/* prologue: frame size=0 */
/* prologue end (size=0) */
	lds r30,28672
	lds r31,(28672)+1
	icall
	lds r30,28674
	lds r31,(28674)+1
	icall
	ldi r24,lo8(42)
	ldi r25,hi8(42)
/* epilogue: frame size=0 */
	ret
/* epilogue end (size=1) */
/* function main size 13 (12) */
	.size	main, .-main
/* File "knut.c": code   13 = 0x000d (  12), prologues   0, epilogues   1 */

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Jörg,

thanks for this next solution, - but again I'm not really happy :). This is also more a philosophical question.

dl8dtl wrote:

#include 

typedef void (*vector_entry) (void);

static const vector_entry *vectable = (const vector_entry *)0x7000;

int main (void) {
  vectable[0]();
  vectable[1]();

  return 42;
}


I don't like the array - and here it becomes a question of philosophy. Hard arry indices is nothing to be maintainable. A 'define' could be a solution to get around this I thought a structure is easier for debugging and afterwards if some changes the bootloader vector table. My main issue is to have a simple interface especially for maintenance - hopefully only one place to change the Bootloader vectortable and the application interface.

Thanks

Knut

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

Yes, a define or enum might be a solution for that.

As you are German, you might also want to have a look at this
"shared library" implementation draft:

http://www.mikrocontroller.net/t...

I wonder whether I should make that a full avr-libc example, probably
in your context (i.e. jump table vector into boot loader, rather than
a separate shared lib).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Jörg,

dl8dtl wrote:

As you are German, you might also want to have a look at this
"shared library" implementation draft:

http://www.mikrocontroller.net/t...

I wonder whether I should make that a full avr-libc example, probably
in your context (i.e. jump table vector into boot loader, rather than
a separate shared lib).

I think we could stop the discussion here. There are several other advantages of the shared lib solution - e.g. function specific prototypes, func. spec. parameter,... I'll follow your shared lib example and forward the results later to you.

Thanks

Knut