EmbDev.net

Forum: ARM programming with GCC/GNU tools Virtual Functions and you well, me


von Jim K. (ancaritha)


Rate this post
useful
not useful
I'm having a problem with virtual functions.  It seems as though the
linker is not connecting them properly (at least thats what I think is
happening).

Code time! (I'm going to try to include everything that is relevant, but
I might miss some stuff, so just yell and I'll go find it)


struct BaoUiPg {
private:
   ...
protected:
   ...
public:
    virtual void appSetup(int nID);
    ...
};

struct BaoUiPgOutPower : public BaoUiPg {
private:
    ...
public:
    virtual void appSetup(int nID);
};

the InPower, BattStats etc are of similar make-up to BaoUiPgOutPower

static BaoUiPgOutPower          s_PageOutPower;
static BaoUiPgInPower           s_PageInPower;
static BaoUiPgBattStats         s_PageBatteryStats;
static BaoUiPgScavenger         s_PageScavenger;
static BaoUiPgInPriority        s_PageInputPriority;
static BaoUiPgChrgCtrl          s_PageChargeControl;
static BaoUiPgFcPwrLvl          s_PageFcPwrLvl;
static BaoUiPgFcOpMode          s_PageFcOpMode;
static BaoUiPgVersion           s_PageVersion;

static BaoUiPg * s_pPageList[] =
{
    &s_PageOutPower,
    &s_PageInPower,
    &s_PageBatteryStats,
    &s_PageScavenger,
    &s_PageInputPriority,
    &s_PageChargeControl,
    &s_PageFcPwrLvl,
    &s_PageFcOpMode,
    &s_PageVersion,
};

When this code is executed
s_pPageList[0]->appSetup(0);
the program hangs.  I went into the GDB insight debugger and this jumps
to a random point in memory and says <undefined>.


My makefile stuff:

# Flags for C and C++ (arm-elf-gcc/arm-elf-g++)
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -Wall -Wcast-align -Wimplicit
CFLAGS += -Wpointer-arith -Wswitch
CFLAGS += -Wredundant-decls -Wreturn-type -Wshadow -Wunused
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))

# flags only for C
CONLYFLAGS += -Wnested-externs
CONLYFLAGS += $(CSTANDARD)

# flags only for C++ (arm-elf-g++)
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CDEFS) $(CINCS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -Wall -Wno-cast-align -Wimplicit -Wno-non-virtual-dtor
CPPFLAGS += -Wpointer-arith -Wswitch
CPPFLAGS += -Wredundant-decls -Wreturn-type -Wshadow -Wunused
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))

#    --cref:    add cross reference to  map file
LDFLAGS = -nostartfiles -Wl,-Map=$(OBJDIR)/$(OUTTARGET).map,--cref
LDFLAGS += -lc
LDFLAGS += $(NEWLIBLPC) $(MATH_LIB)
LDFLAGS += -lc -lgcc
LDFLAGS += $(CPLUSPLUS_LIB)


# Link: create ELF output file from object files.
.SECONDARY : $(OBJDIR)/$(OUTTARGET).elf
.PRECIOUS : $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM)
%.elf:  $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM)
  @echo
  @echo $(MSG_LINKING) $@
#  $(CC) $(THUMB) $(ALL_CPPFLAGS) $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ)
$(CPPOBJ) $(CPPOBJARM) --output $@ $(LDFLAGS)
  $(CPP) $(THUMB) $(ALL_CPPFLAGS) $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ)
$(CPPOBJ) $(CPPOBJARM) --output $@ $(LDFLAGS)

# Compile: create object files from C source files. ARM/Thumb
$(COBJ) : $(OBJDIR)/%.o : %.c
  @echo
  @echo $(MSG_COMPILING) $<
  $(CC) -c $(THUMB) $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $(OBJDIR)/$(@F)

# Compile: create object files from C source files. ARM-only
$(COBJARM) : $(OBJDIR)/%.o : %.c
  @echo
  @echo $(MSG_COMPILING_ARM) $<
  $(CC) -c $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $(OBJDIR)/$(@F)

# Compile: create object files from C++ source files. ARM/Thumb
$(CPPOBJ) : $(OBJDIR)/%.o : %.cpp
  @echo
  @echo $(MSG_COMPILINGCPP) $<
#  $(CC) -c $(THUMB) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< -o $(OBJDIR)/$(@F)
  $(CPP) -c $(THUMB) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< -o $(OBJDIR)/$(@F)

# Compile: create object files from C++ source files. ARM-only
$(CPPOBJARM) : $(OBJDIR)/%.o : %.cpp
  @echo
  @echo $(MSG_COMPILINGCPP_ARM) $<
#  $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< -o $(OBJDIR)/$(@F)
  $(CPP) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< -o $(OBJDIR)/$(@F)

# Assemble: create object files from assembler source files. ARM/Thumb
$(AOBJ) : $(OBJDIR)/%.o : %.S
  @echo
  @echo $(MSG_ASSEMBLING) $<
  $(CC) -c $(THUMB) $(ALL_ASFLAGS) $< -o $(OBJDIR)/$(@F)


# Assemble: create object files from assembler source files. ARM-only
$(AOBJARM) : $(OBJDIR)/%.o : %.S
  @echo
  @echo $(MSG_ASSEMBLING_ARM) $<
  $(CC) -c $(ALL_ASFLAGS) $< -o $(OBJDIR)/$(@F)


Note: If I build this for a Win32 platform it works correctly.


If anyone has any suggestions I'm all ears.  I was playing around with
some linker flags, but the GCC doc seems to be lacking when it comes to
documenting all the flags, so there could very well be a simple flag
that I'm missing which I just couldn't find.  Thanks in advance
everyone!

von Martin Thomas (Guest)


Rate this post
useful
not useful
Jim Kaz wrote:
> I'm having a problem with virtual functions.  It seems as though the
> linker is not connecting them properly (at least thats what I think is
> happening).

So - how about the linker-script? For C++ some extra entries are needed
compared to C (has been discussed before, try a "manual seach" thru the
topic-pages). Are the entries included in the used script? Maybe the
default linker-script (arm-elf-ld --verbose) or one of my examples has
same useful information.
Example:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/#lpc_cpp1
It might be too simple but at least virtual functions are used and I
have tested it successfully with an LPC2129.

Martin Thomas

von Jim K. (ancaritha)


Rate this post
useful
not useful
Martin Thomas wrote:
> So - how about the linker-script?

Linker scripts!  Never would have thought to look there :)

I'm executing in ROM, but I have interrupts executing in RAM, so I'll
add both., even though I'm pretty sure none of the virtual functions
will ever execute in an interrupt. I just downloaded the zip file for
the LPC2129, so I'll start looking at that now.  I did a manual search
through this forum earlier (stupid search function not working) but I
didn't see anything new.  I probably missed it, I'll check again.



/*---------------------------------------------------------------------- 
-----*/
/*-         ATMEL Microcontroller Software Support  -  ROUSSET  -
*/
/*---------------------------------------------------------------------- 
-----*/
/* The software is delivered "AS IS" without warranty or condition of
any    */
/* kind, either express, implied or statutory. This includes without
*/
/* limitation any warranty or condition with respect to merchantability
or   */
/* fitness for any particular purpose, or against the infringements of
*/
/* intellectual property rights of others.             */
/*---------------------------------------------------------------------- 
-----*/
/*- File source          : GCC_FLASH.ld
*/
/*- Object               : Linker Script File for Flash Workspace
*/
/*- Compilation flag     : None
*/
/*-
*/
/*- 1.0 11/Mar/05 JPP    : Creation SAM7A3
*/
/*---------------------------------------------------------------------- 
-----*/

/*
//*** <<< Use Configuration Wizard in Context Menu >>> ***
*/


/*
// <h> Memory Configuration
//   <h> Code (Read Only)
//     <o>  Start <0x0-0xFFFFFFFF>
//     <o1> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Data (Read/Write)
//     <o2> Start <0x0-0xFFFFFFFF>
//     <o3> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Top of Stack (Read/Write)
//     <o4> STACK <0x0-0xFFFFFFFF>
//   </h>
// </h>
*/

/* Memory Definitions */

MEMORY
{
  CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
  DATA (rw) : ORIGIN = 0x00200000, LENGTH = 0x00008000
  STACK (rw) : ORIGIN = 0x00208000,LENGTH = 0x00000000
}


/* Section Definitions */

SECTIONS
{
  /* first section is .text which is used for code */
  . = 0x0000000;
  .text : { *cstartup.o (.text) }>CODE =0
  .text :
  {
    *(.text)                   /* remaining code */

    *(.glue_7t) *(.glue_7)

  } >CODE =0

  . = ALIGN(4);

  /* .rodata section which is used for read-only data (constants) */

  .rodata :
  {
    *(.rodata)
  } >CODE

  . = ALIGN(4);

  _etext = . ;
  PROVIDE (etext = .);

  /* .data section which is used for initialized data */

  .data : AT (_etext)
  {
    _data = . ;
    *(.data)
    SORT(CONSTRUCTORS)
  } >DATA
  . = ALIGN(4);

  _edata = . ;
   PROVIDE (edata = .);

  /* .bss section which is used for uninitialized data */

  .bss :
  {
    __bss_start = . ;
    _bss_start_ = . ;
    *(.bss)
    *(COMMON)
  }
  . = ALIGN(4);
  _bss_end_ = . ;
  _bss_end_ = . ;
  _end = .;
    . = ALIGN(4);
   .int_data :
   {
   *(.internal_ram_top)
   }> STACK

  PROVIDE (end = .);

  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the
beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }

}

/*---------------------------------------------------------------------- 
-----*/
/*-         ATMEL Microcontroller Software Support  -  ROUSSET  -
*/
/*---------------------------------------------------------------------- 
-----*/
/* The software is delivered "AS IS" without warranty or condition of
any    */
/* kind, either express, implied or statutory. This includes without
*/
/* limitation any warranty or condition with respect to merchantability
or   */
/* fitness for any particular purpose, or against the infringements of
*/
/* intellectual property rights of others.             */
/*---------------------------------------------------------------------- 
-----*/
/*- File source          : GCC_RAM.ld
*/
/*- Object               : Linker Script File for RAM Workspace
*/
/*- Compilation flag     : None
*/
/*-
*/
/*- 1.0 11/Mar/05 JPP    : Creation SAM7A3
*/
/*---------------------------------------------------------------------- 
-----*/


/*
//*** <<< Use Configuration Wizard in Context Menu >>> ***
*/


/*
// <h> Memory Configuration
//   <h> Code (Read Only)
//     <o>  Start <0x0-0xFFFFFFFF>
//     <o1> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Data (Read/Write)
//     <o2> Start <0x0-0xFFFFFFFF>
//     <o3> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Top of Stack (Read/Write)
//     <o4> STACK <0x0-0xFFFFFFFF>
//   </h>
// </h>
*/

/* Memory Definitions */

MEMORY
{
  CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00007000
  DATA (rw) : ORIGIN = 0x00007000, LENGTH = 0x00001000
  STACK (rw) : ORIGIN = 0x00007000,LENGTH = 0x00000000
}


/* Section Definitions */

SECTIONS
{
  /* first section is .text which is used for code */
  . = 0x0000000;
  .text : { *cstartup.o (.text) }>CODE =0
  .text :
  {
    *(.text)                   /* remaining code */

    *(.glue_7t) *(.glue_7)

  } >CODE =0

  . = ALIGN(4);

  /* .rodata section which is used for read-only data (constants) */

  .rodata :
  {
    *(.rodata)
  } >CODE

  . = ALIGN(4);

  _etext = . ;
  PROVIDE (etext = .);

  /* .data section which is used for initialized data */

  .data : AT (_etext)
  {
    _data = . ;
    *(.data)
    SORT(CONSTRUCTORS)
  } >DATA
  . = ALIGN(4);

  _edata = . ;
   PROVIDE (edata = .);

  /* .bss section which is used for uninitialized data */

  .bss :
  {
    __bss_start = . ;
    _bss_start_ = . ;
    *(.bss)
    *(COMMON)
  }
  . = ALIGN(4);
  _bss_end_ = . ;
  _bss_end_ = . ;
  _end = .;
    . = ALIGN(4);
   .int_data :
   {
   *(.internal_ram_top)
   }> STACK

  PROVIDE (end = .);

  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the
beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }

}

von Jim K. (ancaritha)


Rate this post
useful
not useful
My new modded ROM linker script.  I made a most of the initialization
stuff to look identical toyours, the only exception to this being the
stack declaration stuff at the very end, I kept that the same way that
Atmel had it.  I did the same thing to the RAM file, still no luck.  I'm
gonna go search through the boards again, thought I'd give the linker
script a shot first.

/*---------------------------------------------------------------------- 
-----*/
/*-         ATMEL Microcontroller Software Support  -  ROUSSET  -
*/
/*---------------------------------------------------------------------- 
-----*/
/* The software is delivered "AS IS" without warranty or condition of
any    */
/* kind, either express, implied or statutory. This includes without
*/
/* limitation any warranty or condition with respect to merchantability
or   */
/* fitness for any particular purpose, or against the infringements of
*/
/* intellectual property rights of others.             */
/*---------------------------------------------------------------------- 
-----*/
/*- File source          : GCC_FLASH.ld
*/
/*- Object               : Linker Script File for Flash Workspace
*/
/*- Compilation flag     : None
*/
/*-
*/
/*- 1.0 11/Mar/05 JPP    : Creation SAM7A3
*/
/*---------------------------------------------------------------------- 
-----*/

/*
//*** <<< Use Configuration Wizard in Context Menu >>> ***
*/


/*
// <h> Memory Configuration
//   <h> Code (Read Only)
//     <o>  Start <0x0-0xFFFFFFFF>
//     <o1> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Data (Read/Write)
//     <o2> Start <0x0-0xFFFFFFFF>
//     <o3> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Top of Stack (Read/Write)
//     <o4> STACK <0x0-0xFFFFFFFF>
//   </h>
// </h>
*/

/* Memory Definitions */

MEMORY
{
  ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
  RAM (rw) : ORIGIN = 0x00200000, LENGTH = 0x00008000
  STACK (rw) : ORIGIN = 0x00208000,LENGTH = 0x00000000
}


/* Section Definitions */

SECTIONS
{
  /* first section is .text which is used for code */
   .text :
  {
  *SAM7Ainit.o (.text)            /* Startup code */
  *(.text .text.*)           /* remaining code */
  *(.gnu.linkonce.t.*)
  *(.glue_7)
  *(.glue_7t)
  *(.gcc_except_table)
  *(.rodata)                 /* read-only data (constants) */
  *(.rodata*)
  *(.gnu.linkonce.r.*)
  } > ROM

  /***** old:
  .text :
  {
    *crt0.o (.text)
    *(.text)
    *(.rodata)
    *(.rodata*)
    *(.glue_7)
    *(.glue_7t)
  } > ROM
  *****/

  . = ALIGN(4);

  /* .ctors .dtors are used for c++ constructors/destructors */
  /* added by Martin Thomas 4/2005 based on Anglia Design example */
  .ctors :
  {
    PROVIDE(_ctors_start_ = .);
    KEEP(*(SORT(.ctors.*)))
    KEEP(*(.ctors))
    PROVIDE(_ctors_end_ = .);
  } >ROM

  .dtors :
  {
    PROVIDE(_dtors_start_ = .);
    KEEP(*(SORT(.dtors.*)))
    KEEP(*(.dtors))
    PROVIDE(_dtors_end_ = .);
  } >ROM

    . = ALIGN(4);
  /* mthomas - end */

  _etext = . ;
  PROVIDE (etext = .);

  /* .data section which is used for initialized data */
  .data : AT (_etext)
  {
    _data = .;
    *(.data)
  *(.data.*)
  *(.gnu.linkonce.d*)
  SORT(CONSTRUCTORS) /* mt 4/2005 */
  . = ALIGN(4);
  *(.fastrun) /* !!!! "RAM-Function" example */
  } > RAM

  . = ALIGN(4);
  _edata = . ;
  PROVIDE (edata = .);

  /* .bss section which is used for uninitialized data */
  .bss (NOLOAD) :
  {
    __bss_start = . ;
    _bss_start_ = . ;
    *(.bss)
  *(.gnu.linkonce.b*)
    *(COMMON)
    . = ALIGN(4);
  } > RAM

  . = ALIGN(4);
  _bss_end_ = . ;
  PROVIDE (__bss_end = .);

  . = ALIGN(4);
   .int_data :
   {
   *(.internal_ram_top)
   }> STACK

  _end = . ;
  PROVIDE (end = .);

  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the
beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }

}

von Clifford S. (clifford)


Rate this post
useful
not useful
Jim Kaz wrote:
>                                           ...I was playing around with
> some linker flags, but the GCC doc seems to be lacking when it comes to
> documenting all the flags, so there could very well be a simple flag
> that I'm missing which I just couldn't find.
>

For linker flags you should perhaps consult the linker documentation
rather than the compiler documentation! ;-)
http://www.gnu.org/software/binutils/manual/ld-2.9.1/ld.html However, I
don't thing linker flags are going to help much.

Is it only this code that fails or any virtual function calls? If the
latter, post a simpler example, it would be easier at least to discount
your code as the problem if that is the case. If it is only this code, I
would suggest that the problem may not be where you think it is, and may
be in your code - perhaps even an unrelated memory error corrupting. In
these cases posting just fragments may be inadequate.

When you call s_pPageList[0]->appSetup(0); in the debugger, and you
checked s_pPageList[0] at that point to determine if it is a valid
object?

Clifford

von Martin Thomas (Guest)


Rate this post
useful
not useful
. = ALIGN(4);
   _bss_end_ = . ;
   PROVIDE (__bss_end = .);

+   _end = . ;
+   PROVIDE (end = .);

   . = ALIGN(4);
    .int_data :
    {
    *(.internal_ram_top)
    }> STACK

-   _end = . ;
-   PROVIDE (end = .);

von Jim K. (ancaritha)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> Is it only this code that fails or any virtual function calls? If the
> latter, post a simpler example, it would be easier at least to discount
> your code as the problem if that is the case. If it is only this code, I
> would suggest that the problem may not be where you think it is, and may
> be in your code - perhaps even an unrelated memory error corrupting. In
> these cases posting just fragments may be inadequate.
>
> When you call s_pPageList[0]->appSetup(0); in the debugger, and you
> checked s_pPageList[0] at that point to determine if it is a valid
> object?

I'm not sure if other virtual functions fail.  This was something I
started to investigate but then got side tracked by the whole linker
script thing.  I do know that calling other virtual functions does not
cause the system to crash, but I don't know if those functions are
actually being jumped to.  I ran the GDB insight debugger and attempted
to step into those functions, but it never seemed to work, so I don't
know if its because if the code is not actually jumping to them, or the
debugger decided to not step into the function, which I've noticed it
does some time.  Putting a break point inside one of those functions
also didn't cause the debugger to halt...

I want to say that s_pPageList[0] is a valid object, but I can't
remember for certain and won't be able to check again until Monday.

I know this code works using the compiler that comes with Visual Studios
8 (we have simulator code and the like), but if the VS compiler is
anything like Internet Explorer, it probably does not conform to
regulations, so things that shouldn't work do work.


I'll try those changes on Monday, thanks Martin!  Also, in the LPC code,
there is.. uhh  ENTRY(_boot) I think was the name, at the top of the ROM
script and _startup at the top of the RAM script.  Are those important
to have?  Should they be in the Assembly file?  I modded my assembly
file a bit to include these, but the SAM7A file looked very different
from the LPC file (don't know if this is because different chip types,
or just different coding styles), so I likely placed _boot and _startup
in the incorrect places.

Thanks for all the help guys!

von Jim K. (ancaritha)


Rate this post
useful
not useful
Ok.. still trying to get these damn virtual functions to work...
Martin, at the top of your LPC ROM linker script there is an
ENTRY(_boot) and at the top the RAM one there is ENTRY(_start).  These
appear in the assembly file as well.  These two thinks are the only
things missing from my linker scripts.  However, the SAM7 assembly files
are vastly different than the LPC ones.

As far as I can tell, your SAM7S examples are more or less identical to
my SAM7A3 file.  However, those files aren't designed to handle virtual
functions.  Is there anything I need to add to my assembly file?  Do I
need to add _start and _boot functions somewhere (and then add them to
the top of my linker scripts as well)?

Any further help you can contribute would be greatly appreciated.


/*---------------------------------------------------------------------- 
--------
//*-         ATMEL Microcontroller Software Support  -  ROUSSET  -
//*--------------------------------------------------------------------- 
---------
//* The software is delivered "AS IS" without warranty or condition of
any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability
or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*--------------------------------------------------------------------- 
--------
//*- File source          : Cstartup.s
//*- Object               : Generic CStartup for KEIL and GCC No Use
REMAP
//*- Compilation flag     : None
//*-
//*- 1.0 10/Mar/05 JPP    : Creation
//*- 1.1 01/Apr/05 JPP    : save SPSR
//*--------------------------------------------------------------------- 
--------*/

     .equ   IRQ_Stack_Size,     0x00000060

/* #include "AT91SAM7A3_inc.h"    */

  .equ AIC_IVR,         (256)
  .equ AIC_FVR,         (260)
  .equ AIC_EOICR,       (304)
  .equ AT91C_BASE_AIC,  (0xFFFFF000)

#;---------------------------------------------------------------------- 
--------
#;- Section Definition
#;-----------------
#;-  Section
#;- .internal_ram_top   Top_Stack: used by the cstartup for vector
initalisation
#;-      management defined by ld and affect from ldscript
#;---------------------------------------------------------------------- 
--------
  .section   .internal_ram_top
  .code 32
  .align   0
  .global  Top_Stack
Top_Stack:

/*---------------------------------------------------------------------- 
--------
*- Area Definition
*----------------------------------------------------------------------- 
-------
* .text is used instead of .section .text so it works with arm-aout too.
*/
        .section   .reset
        .text
        .global _startup
        .func   _startup
_startup:
reset:
/*---------------------------------------------------------------------- 
--------
//*- Exception vectors
//*--------------------
//*- These vectors can be read at address 0 or at RAM address
//*- They ABSOLUTELY requires to be in relative addresssing mode in
order to
//*- guarantee a valid jump. For the moment, all are just looping.
//*- If an exception occurs before remap, this would result in an
infinite loop.
//*- To ensure if a exeption occurs before start application to infinite
loop.
//*--------------------------------------------------------------------- 
---------*/

                B           InitReset           /* 0x00 Reset handler */
undefvec:
                B           undefvec            /* 0x04 Undefined
Instruction */
swivec:
                B           swivec              /* 0x08 Software
Interrupt */
pabtvec:
                B           pabtvec             /* 0x0C Prefetch Abort
*/
dabtvec:
                B           dabtvec             /* 0x10 Data Abort */
rsvdvec:
                B           rsvdvec             /* 0x14 reserved  */
irqvec:
                B           IRQ_Handler_Entry   /* 0x18 IRQ   */
fiqvec:                                   /* 0x1c FIQ  */
/*---------------------------------------------------------------------- 
--------
//*- Function             : FIQ_Handler_Entry
//*- Treatments           : FIQ Controller Interrupt Handler.
//*- Called Functions     : AIC_FVR[interrupt]
//*--------------------------------------------------------------------- 
---------*/

FIQ_Handler_Entry:

/*- Switch in SVC/User Mode to allow User Stack access for C code   */
/* because the FIQ is not yet acknowledged*/

/*- Save and r0 in FIQ_Register */
            mov         r9,r0
          ldr         r0 , [r8, #AIC_FVR]
            msr         CPSR_c,#I_BIT | F_BIT | ARM_MODE_SVC

/*- Save scratch/used registers and LR in User Stack */
            stmfd       sp!, { r1-r3, r12, lr}

/*- Branch to the routine pointed by the AIC_FVR */
            mov         r14, pc
            bx          r0

/*- Restore scratch/used registers and LR from User Stack */
            ldmia       sp!, { r1-r3, r12, lr}

/*- Leave Interrupts disabled and switch back in FIQ mode */
            msr         CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ

/*- Restore the R0 ARM_MODE_SVC register */
            mov         r0,r9

/*- Restore the Program Counter using the LR_fiq directly in the PC */
            subs        pc,lr,#4
  .align 0
.RAM_TOP:
  .word  Top_Stack

InitReset:
/*---------------------------------------------------------------------- 
--------
/*- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit
/*---------------------------------------------------------------------- 
--------*/
              .extern   AT91F_LowLevelInit
/*- minumum C initialization */
/*- call  AT91F_LowLevelInit( void) */

            ldr     r13,.RAM_TOP            /* temporary stack in
internal RAM */
/*--Call Low level init function in ABSOLUTE through the Interworking 
*/
          ldr      r0,=AT91F_LowLevelInit
            mov     lr, pc
          bx      r0
/*---------------------------------------------------------------------- 
--------
//*- Stack Sizes Definition
//*------------------------
//*- Interrupt Stack requires 2 words x 8 priority level x 4 bytes when
using
//*- the vectoring. This assume that the IRQ management.
//*- The Interrupt Stack must be adjusted depending on the interrupt
handlers.
//*- Fast Interrupt not requires stack If in your application it
required you must
//*- be definehere.
//*- The System stack size is not defined and is limited by the free
internal
//*- SRAM.
//*--------------------------------------------------------------------- 
---------*/

/*---------------------------------------------------------------------- 
--------
//*- Top of Stack Definition
//*-------------------------
//*- Interrupt and Supervisor Stack are located at the top of internal
memory in
//*- order to speed the exception handling context saving and restoring.
//*- ARM_MODE_SVC (Application, C) Stack is located at the top of the
external memory.
//*--------------------------------------------------------------------- 
---------*/

    .EQU    IRQ_STACK_SIZE,    (3*8*4)
          .EQU    ARM_MODE_FIQ,       0x11
          .EQU    ARM_MODE_IRQ,       0x12
          .EQU    ARM_MODE_SVC,       0x13

          .EQU    I_BIT,              0x80
          .EQU    F_BIT,              0x40

/*---------------------------------------------------------------------- 
--------
//*- Setup the stack for each mode
//*-------------------------------*/
                mov     r0,r13

/*- Set up Fast Interrupt Mode and set FIQ Mode Stack*/
                msr     CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
/*- Init the FIQ register*/
              ldr     r8, =AT91C_BASE_AIC

/*- Set up Interrupt Mode and set IRQ Mode Stack*/
                msr     CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
                mov     r13, r0                     /* Init stack IRQ */
                sub     r0, r0, #IRQ_Stack_Size
/*- Set up Supervisor Mode and set Supervisor Mode Stack*/
                msr     CPSR_c, #ARM_MODE_SVC
                mov     r13, r0                     /* Init stack Sup */

/*- Enable interrupt & Set up Supervisor Mode and set Supervisor Mode
Stack*/

# Relocate .data section (Copy from ROM to RAM)
                LDR     R1, =_etext
                LDR     R2, =_data
                LDR     R3, =_edata
LoopRel:        CMP     R2, R3
                LDRLO   R0, [R1], #4
                STRLO   R0, [R2], #4
                BLO     LoopRel

# Clear .bss section (Zero init)
                MOV     R0, #0
                LDR     R1, =__bss_start__
                LDR     R2, =__bss_end__
LoopZI:         CMP     R1, R2
                STRLO   R0, [R1], #4
                BLO     LoopZI

    ldr  lr,=exit
    ldr  r0,=main
    bx  r0

        .size   _startup, . - _startup
        .endfunc

/* "exit" dummy added by mthomas to avoid sbrk write read etc. needed
   by the newlib default "exit" */
        .global exit, abort
        .func   exit, abort
exit:
abort:
        b    .
    .size   exit, . - exit
        .endfunc

/*---------------------------------------------------------------------- 
--------
//*- Manage exception
//*---------------
//*- This module The exception must be ensure in ARM mode
//*--------------------------------------------------------------------- 
---------
//*--------------------------------------------------------------------- 
---------
//*- Function             : IRQ_Handler_Entry
//*- Treatments           : IRQ Controller Interrupt Handler.
//*- Called Functions     : AIC_IVR[interrupt]
//*--------------------------------------------------------------------- 
---------*/
        .global IRQ_Handler_Entry
        .func   IRQ_Handler_Entry

IRQ_Handler_Entry:

/*- Manage Exception Entry  */
/*- Adjust and save LR_irq in IRQ stack  */
            sub         lr, lr, #4
            stmfd       sp!, {lr}

/*- Save SPSR need to be saved for nested interrupt */
            mrs         r14, SPSR
            stmfd       sp!, {r14}

/*- Save and r0 in IRQ stack  */
            stmfd       sp!, {r0}

/*- Write in the IVR to support Protect Mode  */
/*- No effect in Normal Mode  */
/*- De-assert the NIRQ and clear the source in Protect Mode */
            ldr         r14, =AT91C_BASE_AIC
      ldr         r0 , [r14, #AIC_IVR]
      str         r14, [r14, #AIC_IVR]

/*- Enable Interrupt and Switch in Supervisor Mode */
            msr         CPSR_c, #ARM_MODE_SVC

/*- Save scratch/used registers and LR in User Stack */
            stmfd       sp!, { r1-r3, r12, r14}

/*- Branch to the routine pointed by the AIC_IVR  */
            mov         r14, pc
            bx          r0
/*- Restore scratch/used registers and LR from User Stack*/
            ldmia       sp!, { r1-r3, r12, r14}

/*- Disable Interrupt and switch back in IRQ mode */
            msr         CPSR_c, #I_BIT | ARM_MODE_IRQ

/*- Mark the End of Interrupt on the AIC */
            ldr         r14, =AT91C_BASE_AIC
            str         r14, [r14, #AIC_EOICR]

/*- Restore SPSR_irq and r0 from IRQ stack */
            ldmia       sp!, {r0}

/*- Restore SPSR_irq and r0 from IRQ stack */
            ldmia       sp!, {r14}
            msr         SPSR_cxsf, r14

/*- Restore adjusted  LR_irq from IRQ stack directly in the PC */
            ldmia       sp!, {pc}^

        .size   IRQ_Handler_Entry, . - IRQ_Handler_Entry
        .endfunc
/*---------------------------------------------------------------
//* ?EXEPTION_VECTOR
//* This module is only linked if needed for closing files.
//*---------------------------------------------------------------*/
        .global AT91F_Default_FIQ_handler
        .func   AT91F_Default_FIQ_handler
AT91F_Default_FIQ_handler:
            b     AT91F_Default_FIQ_handler
        .size   AT91F_Default_FIQ_handler, . - AT91F_Default_FIQ_handler
        .endfunc

        .global AT91F_Default_IRQ_handler
        .func   AT91F_Default_IRQ_handler
AT91F_Default_IRQ_handler:
            b     AT91F_Default_IRQ_handler
        .size   AT91F_Default_IRQ_handler, . - AT91F_Default_IRQ_handler
        .endfunc

        .global AT91F_Spurious_handler
        .func   AT91F_Spurious_handler
AT91F_Spurious_handler:
            b     AT91F_Spurious_handler
        .size   AT91F_Spurious_handler, . - AT91F_Spurious_handler
        .endfunc

        .end

von Jim K. (ancaritha)


Rate this post
useful
not useful
I found what is likely the missing piece in my assembly file:

    LDR   r0, =__ctors_start__
    LDR   r1, =__ctors_end__
ctor_loop:
    CMP   r0, r1
    BEQ   ctor_end
    LDR   r2, [r0], #4
    STMFD   sp!, {r0-r1}
    MOV   lr, pc
---->    MOV   pc, r2
    LDMFD   sp!, {r0-r1}
    BLO    ctor_loop
ctor_end:


Sadly, the marked line causes much devastation to occur in my program
(I.E. it never makes it to main()).  I'm thinking that R2 is loaded with
a bogus value so the PC gets loaded with a bogus value, and then there
is much death.  I have looked at ARM assembly very very very very
little, but thankfully I do have a handy dandy ARM architecture book :)

von Martin Thomas (Guest)


Rate this post
useful
not useful
Jim Kaz wrote:
> I found what is likely the missing piece in my assembly file:
>
>     LDR   r0, =__ctors_start__
>     LDR   r1, =__ctors_end__
> ctor_loop:
>     CMP   r0, r1
>     BEQ   ctor_end
>     LDR   r2, [r0], #4
>     STMFD   sp!, {r0-r1}
>     MOV   lr, pc
> ---->    MOV   pc, r2
>     LDMFD   sp!, {r0-r1}
>     BLO    ctor_loop
> ctor_end:
>
>
> Sadly, the marked line causes much devastation to occur in my program
> (I.E. it never makes it to main()).  I'm thinking that R2 is loaded with
> a bogus value so the PC gets loaded with a bogus value, and then there
> is much death.  I have looked at ARM assembly very very very very
> little, but thankfully I do have a handy dandy ARM architecture book :)

The loop calls the constructors of static objects. I have not tested
this myself and I am not sure but it may be a "thumb-address-problem".
For a first test rebuild the complete project without thumb/thumb-iw. It
if works try to replace the MOV pc,r2 with BX r2 and rebuild with
thumb/thumb-iw activated. If it still does not work create a minimal
example (linker-script, makefile, startup-code, minimal application
source-code), place it somewhere on a web-space and send the link or
attach it to an e-mail to mthomas AT rhrk DOT uni-kl. DOT de and I will
place it on the "WinARM-server". If I have some time left I will try to
create a C++-example for the SAM7S.

Martin Thomas

von Jim K. (ancaritha)


Rate this post
useful
not useful
Well, I made a minimally sized project and tried out some virtual
functions.  I discovered that local virtual functions work, global
virtual functions did not.

After I changed the MOV pc,r2 to BX r2, tada!  It worked.

http://users.wpi.edu/~jimmykaz/Arm/Sam7A3_Virt_Fnct.rar


Sadly though, the actual application I've been writing still fails, even
after making this change in its respective assembly file.  Back to the
drawing board...  yar matie, Yar.


Thanks for all the help Martin!  Your name has been given its due place
of importance in the linker scripts and assembly file.  Well, at the
very least the linker scripts, I'll have to double check on the assembly
file...

von Jim K. (ancaritha)


Rate this post
useful
not useful
Jim Kaz wrote:
> Sadly though, the actual application I've been writing still fails, even
> after making this change in its respective assembly file.  Back to the
> drawing board...  yar matie, Yar.


So!  Fun tid bits of information.

1) Virtual functions like being called from inside static functions.
There is much failure to be had otherwise (at least with how my
architecture is set up).

2) GDB Insight will hate you for life if you try to step into a virtual
function.  It will either ignore you, and just pass right over it
(although it does actually execute the function, it will never ever show
you), or it will jump to an undefined vector and crash.  I've noticed
that on certain virtual functions, if I hit step into, it will crash, if
I hit step over, it keeps on chugging.  Go figure.


All the way back to my original post, I had s_pPageList[0]->appSetup(0);
Well, it was really inside a for loop that went up to 9.  Well, I got up
to 3 working!  After the third one the inheritances of the classes
changes and there is much breaking to be had by all.  But I'm a hell of
a lot closer than I used to be, thank you every for the help!

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.