Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

LPC2129: Problem z funkcją printf oraz sprintf - linkowanie

mklos1 15 Nov 2009 18:44 2139 9
Computer Controls
  • #1
    mklos1
    Level 25  
    Witam.

    Z góry przepraszam za dużo linii w poście.

    Problem dotyczy GNUARM oraz procka LPC2129.

    Mam następujący problem występujący podczas linkowania poniższego kodu:
    
    int main()
    {
    	char bufor[256];
    	unsigned int i = 0;
    	IODIR0 = 0xFF000000;
    	IODIR1 = 0x00FF0000;
    	UART0_init();
    	while (1)
    	{
    		sprintf(bufor, "ZONK %d \n", i);
    		UART0_sendString(bufor);
    		delay(2*del_l);
    	}
    	return 0;
    }


    Jeżeli przez printf lub sprintf chcę przepuścić int'a (czyli w stringu formatującym pojawia się %d), linker rzuca mi następującym błędem:
    arm-elf/bin/ld: section .bss [00000828 -> 0000091b] overlaps section .text [00000000 -> 00008433]


    Może ktoś spotkał się z tym problemem?

    Parametry linkera w Makefile:
    
    LDFLAGS +=  -nostartfiles -T$(SCRIPTLINK).ld -Wl,-Map=$(TARGET).map,--cref


    Oto skrypt linkera:

    /*   Plik konfiguracyjny linkera dla LPC2142 
    	Program umiesczony w pamieci FLASH
    */
    
    
    /* Konfiguracja pamieci */
    
    MEMORY
    {
      ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x0003E000
      RAM (rw) : ORIGIN = 0x40000000, LENGTH = 0x00004000
    }
    
    
    /* Definicje poszczegolnych sekcji */
    
    SECTIONS
    {
    
      /* Sekcja .text zawiera kod programu */
      . = 0;	
      .text :
      {
        *boot.o (.text)         /* Startup code */
        *(.text)                   /* remaining code */
        *(.text.*)
        *(.glue_7t) 
        *(.glue_7)
        *(.gnu.linkonce.t.*)
        *(.gcc_except_table)
      } >CODE
    
      . = ALIGN(4);
    
      
      /* sekcja .rodata  zawiera dane stale */
      .rodata :
      {
       *(.rodata) 
       *(.rodata.*)
       *(.gnu.linkonce.r.*)
      } >CODE
      
      . = ALIGN(4);
    	
    	/* sekcja .ctors zawiera konstruktory */
    	.ctors :
    	{
    		PROVIDE(__ctors_start__ = .);
    		KEEP(*(SORT(.ctors.*)))
    		KEEP(*(.ctors))
    		PROVIDE(__ctors_end__ = .);
    	} >CODE
    	
    	. = ALIGN(4);
    	/* sekcja .dtors zawiera destruktory */
    	.dtors :
    	{
    		PROVIDE(__dtors_start__ = .); 
    		KEEP(*(SORT(.dtors.*)))
    		KEEP(*(.dtors))
    		PROVIDE(__dtors_end__ = .);
    	} >CODE
      
        . = ALIGN(4);
    
      
      _etext = . ;
      PROVIDE (etext = .);
    
      /* sekcja .data  zawiera dane zaincjalizowane */
    
      .data : AT (_etext)
      {
        _data = . ;
        *(.data)
        *(.data.*)
        *(.gnu.linkonce.d.*)
        SORT(CONSTRUCTORS)
      } >DATA
      . = ALIGN(4);
    
      _edata = . ;
       PROVIDE (edata = .);
    
      /* .bss sekcja bss zawiera dane niezaincjalizowane */
    
    
      .bss :
      {
        __bss_start = . ;
        __bss_start__ = . ;
        *(.bss)
        *(.bss.*)
        *(.gnu.linkonce.b.*)
        *(COMMON)
      } >DATA
      . = ALIGN(4);
      __bss_end__ = . ;
      __bss_end__ = . ;
    
      _end = .;
      PROVIDE (end = .);
    
      /* Stabs zawiera sekcje debugera  */
      .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 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) }
    }
    
  • Computer Controls
  • Helpful post
    #2
    Freddie Chopin
    MCUs specialist
    Ten skrypt linkera jest błędny... masz zdefiniowaną pamięć o nazwach ROM i RAM, a sekcje pakujesz do CODE i DATA. No to chyba coś tu nie gra?

    Poza tym masz kompilator i narzędzia sprzed 3 lat, ale to pewnie wiesz...

    4\/3!!
  • Computer Controls
  • #3
    mklos1
    Level 25  
    Czyli początek pliku powinien wyglądać:
    
    MEMORY
    {
      CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x0003E000
      DATA (rw) : ORIGIN = 0x40000000, LENGTH = 0x00004000
    }


    Jeżeli chodzi o ARM'y to jestem świeży więc ściągnąłem plik linkera z przykładu do książki wydane przez BTC (LPC2000). Zmieniałem rozmiar pamięci i danych więc pewnie coś wkleiłem za dużo... Sprawdziłem, działa, dzięki... Nie wiem czemu sam tego nie zauważyłem. Tylko jestem i tak w trochę ciężkim szoku, bo po skompilowaniu ze sprintem HEX ma ponad 100kB... Opcje linkera i kompilatora w postaci:
    
    LDFLAGS +=  -nostartfiles -T$(SCRIPTLINK).ld -Wl,-Map=$(TARGET).map,--cref --gc-sections 
    CFLAGS  += -O$(OPT) -mcpu=$(MCU) -g$(DEBUG) -ffunction-sections -fdata-sections  

    nie dają praktycznie nic...

    Niestety pod SUSE, którego używam kompilowała mi się wersja 4.0.1 bo późniejsze mi się nie kompilowały, a binarki nie działały. Jaki toolchain jest nowszy?

    Oczywiście pod KEIL'em nie mam problemów, ale KEIL ideologicznie mi trochę nie pasuje. ;)
  • #4
    arrevalk
    Level 25  
    mklos1 wrote:
    Niestety pod SUSE, którego używam kompilowała mi się wersja 4.0.1 bo późniejsze mi się nie kompilowały, a binarki nie działały. Jaki toolchain jest nowszy?

    Spróbuj najnowszego CodeSourcery Lite Link wersja 32bit śmiga bez problemu pod 64bit ubuntu, może i na suse pójdzie.
    Nie martw się o "ideologie" bo to gcc ;)
  • #6
    mklos1
    Level 25  
    Freddie Chopin wrote:
    To by się w sumie mogło zgadzać, bo użycie printf() i tym podobnych wciąga dużo kodu.


    Do tej pory siedziałem w AVR'ach. Pamiętam, że na ATmega8, skompilowanie funkcji sprintf, która wyświetlała int'y zajmowało raczej nie dużo (pamiętam, że sprintf z obsługą float'ów zajmował kilka kB - kompleta aplikacja). Przypuszczałem, że tutaj będzie inaczej, bo inna architektura i 32-bitowy procesor, ale nie przypuszczałem, że to będzie 35560B, z czego około przy braku sprintf kod kompiluje się do około 2k...
  • #8
    mklos1
    Level 25  
    Freddie Chopin wrote:
    W nowym CodeSourcery printf(), sprintf() i tym podobne funkcje zajmują około 10-15kB, tyle że dla ARMv7-M, w Thumb2, dla ARMv4 i trybu ARM może być więcej... Nawet dużo więcej...


    Pomimo stosowania opcji -mthumb oraz -mthumb-interwork różnice w kodzie są nieznaczne.
    Z bez opcji -mthumb: 33952 B
    Z opcją -mthumb: 33868 B
    Bez sprintf odpowiednio: 2388 B i 2288 B
    Kodu startowego z pustą funkcją main jest: 2024 B
    Kompilowane za pomocą CodeSourcery Lite (dla mcu ARM7tdmi).
    Rozumiem, że kod funkcji sprintf jest załączany z biblioteki i nie mam na to zbyt dużego wpływu...
  • #9
    Freddie Chopin
    MCUs specialist
    No niezbyt, ale możesz napisać swojego printf(), który robi tylko to co chcesz i zajmuje o wiele mniej. Nie jest to wcale takie trudne i nawet ostatnio takiego popełniłem - obsługuje tylko %d, %x, %c i %s (no i %% <: ). Mogę go udostępnić jak chcesz.

    4\/3!!
  • #10
    mklos1
    Level 25  
    Freddie Chopin wrote:
    No niezbyt, ale możesz napisać swojego printf(), który robi tylko to co chcesz i zajmuje o wiele mniej. Nie jest to wcale takie trudne i nawet ostatnio takiego popełniłem - obsługuje tylko %d, %x, %c i %s (no i %% <: ). Mogę go udostępnić jak chcesz.


    Dzięki. Dawno nie programowałem, więc potrenuję trochę :D