mikrocontroller.net

Forum: Compiler & IDEs GNU ARM Linker Problem, LPC3250 Code soll auf HITEX USB Stick auf RAM ausgeführt werden


Autor: Christian Kutschenreiter (kutschi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 >>>>

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Christian Kutschenreiter (kutschi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.