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!
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
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) }
}
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) } }
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
. = ALIGN(4); _bss_end_ = . ; PROVIDE (__bss_end = .); + _end = . ; + PROVIDE (end = .); . = ALIGN(4); .int_data : { *(.internal_ram_top) }> STACK - _end = . ; - PROVIDE (end = .);
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!
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
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 :)
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
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...
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
Log in with Google account
No account? Register here.