Hallo, ich hab einen HITEX 3250 USB STICK, bin damit eigentlich ganz zufrieden, hab jedoch ein grosses Problem. Ich möchte meine Applikation bzw. einige Routinen aus Performancegründen (kurze Interruptlatenzzeiten für internen ADC welcher mit 400kHz laufen soll, (geringerer Jitter, ENOB des internen ADC sollen weitest möglich genutzt werden)) im internen RAM ausführen lassen. Nachdem ich ein Neuling mit der GNU ARM toolchain bin, habe ich der Einfachkeit halber auf ein Beispiel von Hitex aufgesetzt. Möchte die Linker Datei jetzt jedoch so abändern, daß der Code im internen RAM ausgeführt wird und bin kläglich daran gescheitert. Ich muss zugeben das Linker File ist ziemlich komplex aus meiner Sicht und wirklich viel zu o.g. Thema konnte ich bislang leider nicht finden. Daher anbei ein paar Files mit der Hoffnung/Bitte, daß mir jemand vielleicht ein paar zielführende Tipps geben kann, wär echt super! Der Sourcecode usw. fehlen, um die Mail nicht endgültig explodieren zu lassen. Mein Ziel wäre nur eine interne RAM Sektion für Code und Daten, sowie im SDRAM Speicher für das LCD Display (wie gehabt) sowie meinen zeitlich unkritischen Sourcecode einzurichten. Vielen Dank im Voraus Grüsse Kutschi /*********************************************************************** ***** Filename: startupextern.scr ************************************************************************ ***/ // we have a bootloader and the bootloader initializes // the external memory and moves internal RAM to 0x0! RESET TARGET PAUSE 1 CHANGE 0x4003C004 = 0x00 0x00 0x00 0x00 OUTPUT DWORD TO 0x40004014 COUNT 1 = 1 OUTPUT DWORD TO 0x400040C8 COUNT 1 = 0 // Adjust start address to external RAM %pc = 0x80000000 /*********************************************************************** ***** Filename: LPC3000Template.ld ************************************************************************ ***/ SEARCH_DIR( "$(TOOLDIR)\..\arm-hitex-elf\lib\arm926ej-s" ) SEARCH_DIR( "$(TOOLDIR)\..\lib\gcc\arm-hitex-elf\4.1.1\arm926ej-s" ) SEARCH_DIR( ".\Lib\lpc") SEARCH_DIR( ".\Lib\csps\lpc32xx") /******************************************* Define Files *******************************************/ INPUT ( $(LinkObjects) ) INPUT (lpc.a lpc32.a) /* Define the supported output formats - elf32-littlearm is the default */ OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") /* Define the target architecture */ OUTPUT_ARCH(arm) /******************************************* Memory Definitions *******************************************/ MEMORY { INTRAM(rx) : ORIGIN = 0x00000000, LENGTH = 0x30000 /* used only for IRQ */ /* STACK(rw) : ORIGIN = 0x00034000, LENGTH = 16k */ ENET(rw) : ORIGIN = 0x00010000, LENGTH = 24k /* Ethernet data area */ TT(rw) : ORIGIN = 0x0003C000, LENGTH = 16k /* MMU Translation Table */ EXTCODE(rx) : ORIGIN = 0x80000000, LENGTH = 512k /* code area */ EXTDATA(rw) : ORIGIN = 0x80080000, LENGTH = 128k /* data area */ LCDBUFFER(rw) : ORIGIN = 0x81000000, LENGTH = 320*240*4 /* LCD Buffer 0x4b000 */ } /******************************************* Section Definitions *******************************************/ SECTIONS { /*******************************************/ TOP_OF_STACK = 0x80080000 ; PROVIDE (TOP_OF_STACK = 0x80080000); ENET_DATA_AREA = 0x00010000; PROVIDE (ENET_DATA_AREA = 0x00010000); LCD_GRAPHIC_BUFFER = 0x81000000; PROVIDE (LCD_GRAPHIC_BUFFER = 0x81000000); .text : { _code_start_ = .; *(.gnu.linkonce.t.*) *(.glue_7) *(.glue_7t) *(.gcc_except_table) *(.gnu.linkonce.r.*) } >EXTCODE = 0 . = ALIGN(4); /* .rodata section which is used for read-only data (constants) */ .rodata . : { *(.rodata) *(.rodata.*) } >EXTCODE . = ALIGN(4); /*******************************************/ /* CPP is disabled */ /*******************************************/ _etext = . ; PROVIDE (etext = .); /*******************************************/ .data : AT (_etext) { /* used for initialized data */ _data_start_ = . ; PROVIDE (_data_start_ = .) ; *(.data) *(.data.*) *(.gnu.linkonce.d*) SORT(CONSTRUCTORS) _data_end_ = . ; PROVIDE (_data_end_ = .) ; } >EXTDATA . = ALIGN(4); _edata = . ; PROVIDE (edata = .); /*******************************************/ .bss : { /* used for uninitialized data */ __bss_start = . ; _bss_start_ = . ; *(.bss) *(.gnu.linkonce.b*) . = ALIGN(4); _bss_end_ = . ; } >EXTDATA /*******************************************/ .bss2 : { /* used for uninitialized data */ __bss2_start = . ; _bss2_start_ = . ; *(COMMON) . = ALIGN(4); _bss2_end_ = . ; } >EXTDATA /*******************************************/ _end = .; PROVIDE (end = .); /*******************************************/ .translationtable : { PROVIDE (TT_BASE = .); } >TT /*******************************************/ .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) } } /* ************************************************************************ *** \file: startup.c ************************************************************************ ***/ /* # --------------------------------------------- # Application specific constants # --------------------------------------------- # Stack definitions # size in words! */ #define UND_Stack_Size 256 #define SVC_Stack_Size 256 #define ABT_Stack_Size 256 #define FIQ_Stack_Size 256 #define IRQ_Stack_Size 1024 #define USR_Stack_Size 2048 #define Mode_USR 0x10 #define Mode_FIQ 0x11 #define Mode_IRQ 0x12 #define Mode_SVC 0x13 #define Mode_ABT 0x17 #define Mode_UND 0x1B #define Mode_SYS 0x1F #define T_BIT 0x20 /* when T bit is set, thumb mode active */ #define I_BIT 0x80 /* when I bit is set, IRQ is disabled */ #define F_BIT 0x40 /* when F bit is set, FIQ is disabled */ #define MIC_BASE_ADDR 0x40008000 /* Base address of VIC1 */ #define SIC1_BASE_ADDR 0x4000C000 /* Base address of VIC2 */ #define SIC2_BASE_ADDR 0x40010000 /* Offset to vectored status */ #define IRQ_STATUS_OFF 8 /* Non-vectored address offset */ /* Import external symbols */ extern void main(int param); extern void __data_start__( void ); extern void __data_end__( void ); extern void __bss_start__( void ); extern void __bss_end__( void ); extern void __bss2_start__( void ); extern void __bss2_end__( void ); extern void _etext( void ); extern void _edata( void ); extern void SVCInit(void); extern void FIQInit(void); /* # --------------------------------------------- # Hardware specific constants # --------------------------------------------- */ extern void * TOP_OF_STACK( void ); #define UND_STACK TOP_OF_STACK #define SVC_STACK UND_STACK - (UND_Stack_Size*4) #define ABT_STACK SVC_STACK - (SVC_Stack_Size*4) #define FIQ_STACK ABT_STACK - (ABT_Stack_Size*4) #define IRQ_STACK FIQ_STACK - (FIQ_Stack_Size*4) #define USR_STACK IRQ_STACK - (IRQ_Stack_Size*4) /* unsigned int UND_Stack[UND_Stack_Size]; unsigned int SVC_Stack[SVC_Stack_Size]; unsigned int ABT_Stack[ABT_Stack_Size]; unsigned int FIQ_Stack[FIQ_Stack_Size]; unsigned int IRQ_Stack[IRQ_Stack_Size]; unsigned int USR_Stack[USR_Stack_Size]; */ /* const unsigned int ConfigurationTable[6][2]={ {(Mode_UND|I_BIT|F_BIT), &UND_Stack[UND_Stack_Size-1] }, {(Mode_ABT|I_BIT|F_BIT), &ABT_Stack[ABT_Stack_Size-1] }, {(Mode_IRQ|I_BIT|F_BIT), &IRQ_Stack[IRQ_Stack_Size-1] }, {(Mode_SVC|I_BIT|F_BIT), &SVC_Stack[SVC_Stack_Size-1] }, {(Mode_FIQ|I_BIT|F_BIT), &FIQ_Stack[FIQ_Stack_Size-1] }, {(Mode_SYS|I_BIT|F_BIT), &USR_Stack[USR_Stack_Size-1] } }; */ const unsigned int ConfigurationTable[6][2]= { {(Mode_UND|I_BIT|F_BIT), (unsigned int)UND_STACK }, {(Mode_ABT|I_BIT|F_BIT), (unsigned int)ABT_STACK }, {(Mode_IRQ|I_BIT|F_BIT), (unsigned int)IRQ_STACK }, {(Mode_SVC|I_BIT|F_BIT), (unsigned int)SVC_STACK }, {(Mode_FIQ|I_BIT|F_BIT), (unsigned int)FIQ_STACK }, {(Mode_SYS|I_BIT|F_BIT), (unsigned int)USR_STACK } }; /* --------------------------------------------- Interrupt vector table at address 0 --------------------------------------------- */ #define _ASM_CODE__ __attribute_ (( naked)) void lpc32xx_reset_vector( void ) _ASM_CODE_; void lpc32xx_irq_handler( void ) _ASM_CODE_; void LowInit( void ) _ASM_CODE_; void lpc32xx_reset_vector( void ) { __asm( ".global vec_reset_handler\n"); __asm( ".global vec_undefined_handler\n"); __asm( ".global vec_swi_handler"); __asm( ".global vec_prefetch_handler\n"); __asm( ".global vec_abort_handler\n"); __asm( ".global vec_irq_handler\n"); __asm( ".global vec_fiq_handler\n"); __asm( "LDR PC, vec_reset_handler \n"); __asm( "LDR PC, vec_undefined_handler \n"); __asm( "LDR PC, vec_swi_handler \n"); __asm( "LDR PC, vec_prefetch_handler \n"); __asm( "LDR PC, vec_abort_handler \n"); __asm( ".word 0x000 /* Reserved Vector */ \n"); __asm( "LDR PC, vec_irq_handler \n"); __asm( "LDR PC, vec_fiq_handler /* Calling the FIQ handler */ \n"); __asm( "vec_reset_handler: .word LowInit \n"); __asm( "vec_undefined_handler: .word Undef_Handler\n"); __asm( "vec_swi_handler: .word SWI_Handler \n"); __asm( "vec_prefetch_handler: .word PAbt_Handler \n"); __asm( "vec_abort_handler: .word DAbt_Handler \n"); __asm( "vec_irq_handler: .word lpc32xx_irq_handler \n"); __asm( "vec_fiq_handler: .word FIQ_Handler \n"); // ident for bootloader __asm( "hitex_id: .word 0x00585448"); __asm( "appl_start: .word _code_start_ \n"); __asm( "appl_end: .word _etext+0x1000 \n"); } /* init section with uninitialised variables */ void ClearSection( unsigned int *start, unsigned int *end ) { while (start<end) { *start++=0; } } /* Copy section with initialised variables */ void CopySection( unsigned int *Src, unsigned int *Dest, unsigned int *DestEnd ) { while (Dest<DestEnd ) { *Dest++=*Src++;; } } void LowInit( void ) { __asm( "ldr r4, =ConfigurationTable" ); /* Configure UND Mode */ __asm( "ldr r1, [r4]"); __asm( "msr CPSR_c, r1"); __asm( "ldr r13, [r4, #4]"); /* Configure ABT Mode */ __asm( "ldr r1, [r4, #8]"); __asm( "msr CPSR_c, r1"); __asm( "ldr r13, [r4, #12]"); /* Configure IRQ Mode */ __asm( "ldr r1, [r4, #16]"); __asm( "msr CPSR_c, r1"); __asm( "ldr r13, [r4, #20]"); /* Configure SVC Mode */ __asm( "ldr r1, [r4, #24]"); __asm( "msr CPSR_c, r1"); __asm( "ldr r13, [r4, #28]"); SVCInit(); /* Configure FIQ Mode */ __asm( "ldr r1, [r4, #32]"); __asm( "msr CPSR_c, r1"); __asm( "ldr r13, [r4, #36]"); FIQInit(); /* Configure SYS Mode */ __asm( "ldr r1, [r4, #40]"); __asm( "msr CPSR_c, r1"); __asm( "ldr r13, [r4, #44]"); CopySection((unsigned int*)&_etext, (unsigned int*)&__data_start__, (unsigned int*)&_edata); ClearSection((unsigned int*)&__bss_start__, (unsigned int*)&__bss_end__); ClearSection((unsigned int*)&__bss2_start__, (unsigned int*)&__bss2_end__); // __asm("b main"); main(1); __asm("b ."); } void EnableIRQ(void) { /* enable interrupts */ __asm( "mrs r1, CPSR"); __asm( "bic r1, r1, #0x80"); __asm( "msr CPSR, r1"); } void lpc32xx_irq_handler( void ) { __asm(".EQU MIC_BASE_ADDR, 0x40008000"); /* Base address of VIC1 */ __asm(".EQU SIC1_BASE_ADDR, 0x4000C000"); /* Base address of VIC2 */ __asm(".EQU SIC2_BASE_ADDR, 0x40010000"); /* Offset to vectored status */ __asm(".EQU IRQ_STATUS_OFF, 0x08"); /* Non-vectored address offset */ __asm("SUB lr, lr, #4"); /* Get return address */ __asm("STMFD sp!, {r0-r12, lr}"); /* Save registers */ /* Read the MIC interrupt status registers */ __asm("LDR r2, =MIC_BASE_ADDR"); __asm("LDR r3, [r2, #IRQ_STATUS_OFF]"); __asm("AND r3, r3, #0x3FFFFFFC"); __asm("MOV r4, #0"); /* If there the MIC IRQ status is 0, then there are no MIC interrupts pending. That means, go service SIC1 interrupts instead. */ __asm("service_mic:"); __asm("CMP r3, #0"); __asm("BNE int_found"); /* The interrupt was not from MIC */ __asm("service_sic1:"); /* Read the SIC1 interrupt status registers */ __asm("LDR r2, =SIC1_BASE_ADDR "); __asm("LDR r3, [r2, #IRQ_STATUS_OFF]"); __asm("MOV r4, #32"); /* If there the SIC1 IRQ status is 0, then there are no SIC1 interrupts pending. That means, go service SIC2 interrupts instead. */ __asm("CMP r3, #0 "); __asm("BNE int_found "); /* The interrupt was not from SIC1 */ /* Read the SIC2 interrupt status registers */ __asm("service_sic2: LDR r2, =SIC2_BASE_ADDR "); __asm("LDR r3, [r2, #IRQ_STATUS_OFF]"); __asm("MOV r4, #64"); __asm("CMP r3, #0 "); __asm("BEQ int_exit "); /* The interrupt was not from SIC2 */ __asm("int_found: CLZ r1, r3"); __asm("RSB r1, r1, #31"); __asm("ADD r1, r1, r4"); __asm("LDR r0, =irq_func_ptrs"); /* Get address of jump table */ __asm("ADD r0, r0, r1, LSL #2"); /* Add by interrupt offset */ __asm("LDR r0, [r0]"); /* Get handler address */ __asm("CMP r0, #0"); /* Is handler address NULL? */ __asm("BEQ int_exit"); /* If null, the exit */ __asm("MOV lr, pc"); /* Will return to int_exit */ __asm("BX r0"); /* Jump to handler */ __asm("int_exit:"); __asm("LDMFD sp!, {r0-r12, pc}^"); /* Restore registers and exit */ } // <<<< end of file >>>>
Es ist einfach. Man muss die entsprechende Funktion(en) mit dem long-call Attribut ausstatten wie: void foo(void) _attribute_ ((long_call, section (".fastrun"))) { ... } Jetzt, das Segment '.fastrun' im Linker definieren. In die Linker-Datei eine neue Zeile einfügen (mit .fastrun): .data : AT (_etext) { /* used for initialized data */ data_start = . ; PROVIDE (data_start = .) ; *(.data) *(.data.*) *(.fastrun) /* place '.fastrun' code behind the data */ *(.gnu.linkonce.d*) Es sollte funktionieren. Tom
Hallo Tom, vielen herzlichen Dank für die Info, hat zwar nicht ganz auf Anhieb geklappt (verkehrte Section), aber ich hab gewußt wo ich Ansetzen muss. Mittlerweile funktionierts! Danke und schöne Weihnachtsfeiertage Gruß Christian
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.