logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

LPC2129: Problem z funkcją printf oraz sprintf - linkowanie

mklos1 15 Lis 2009 18:44 2253 9
REKLAMA
  • #1 7264989
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    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) }
    }
    
  • REKLAMA
  • Pomocny post
    #2 7265007
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    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!!
  • #3 7265105
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    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. ;)
  • REKLAMA
  • #4 7265955
    arrevalk
    Poziom 25  
    Posty: 450
    Pomógł: 94
    Ocena: 7
    mklos1 napisał:
    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 ;)
  • REKLAMA
  • #5 7266601
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    mklos1 napisał:
    Tylko jestem i tak w trochę ciężkim szoku, bo po skompilowaniu ze sprintem HEX ma ponad 100kB...

    To by się w sumie mogło zgadzać, bo użycie printf() i tym podobnych wciąga dużo kodu.

    4\/3!!
  • #6 7269003
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    Freddie Chopin napisał:
    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...
  • REKLAMA
  • #7 7269788
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    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...

    4\/3!!
  • #8 7270184
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    Freddie Chopin napisał:
    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 7270226
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    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 7270281
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    Freddie Chopin napisał:
    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

Podsumowanie tematu

LABEL_AI_GENERATED
Użytkownik zgłosił problem z linkowaniem kodu w projekcie opartym na procesorze LPC2129, związany z użyciem funkcji printf i sprintf, co prowadziło do błędu dotyczącego nakładania się sekcji pamięci. Odpowiedzi wskazały na błędną konfigurację skryptu linkera, sugerując poprawki w definicjach pamięci. Użytkownik zauważył, że rozmiar skompilowanego kodu z użyciem sprintf jest znacznie większy niż oczekiwano, co jest typowe dla architektur ARM. Proponowano również stworzenie własnej, uproszczonej wersji funkcji printf, aby zredukować rozmiar kodu.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA