Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Computer ControlsComputer Controls
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

STM32F1XX @ codesourcery lite - Linkowanie obiektów problem ze skokiem (BL)

09 Gru 2012 00:09 1365 7
  • Poziom 14  
    Witam,

    zacząłem bawić się w poznawanie cortexa od podstaw i natrafiłem na problem
    którego nie potrafię rozwiązać/ nie mogę znaleźć przyczyny:

    otóż mam dwa pliki źródłowe w jednym z nich procedurę którą chcę
    zawołać z poziomu drugiego pliku.

    czyli w pliku main.s

    mam zadeklarowaną procedurę Init_Clock jako globalną
    (Init_Clock) jest zdefiniowana z pliku routines.s

    /* main.s */
    Code:
    .equ STACK_TOP, 0x20000800
    

    .text
    .global _start
    .global InitClock
    .code 16
    .syntax unified
    .type _start, function
    _start:
    /* poczatek programu */
    .word STACK_TOP
     movs R0, #3
     movs R1, #4
     add R2, R0, R1 /* oczekiwane R2 = R0 + R1 */
     movs R3, #0
    loop:
     add R3, #1      /* inkrementuj */
     cmp R3, #10   /* porownaj 10  */
     BLT loop      /* skocz do loop jesli mniejsze */
     movs R4, #0
     bl InitClock   /* skocz do podprocedury zdefw innym module */
     /*
     LDR R0,=InitClock
     BLX R0
     */
     /* bl lokalna */
    endlessloop:
     b endlessloop



     /* inna podprocedura */

     lokalna:
      nop
      nop
      nop
      movs R0,#25
      BX lr


    /* routines.s */

    Code:
    .text
    
    .code 16
    .global InitClock
    .syntax unified

    .equ RAM_START, 0x20000000
    .equ VAR_1,      RAM_START+4

    InitClock:
       nop      ;
       ldr R0, =VAR_1; /* try to load by pseudo instruction */
       BX LR   ; /* return from subroutine */



    /* makefile */

    Code:
    #moj makefile from scrath
    

    TARGET=main

    CC=arm-none-eabi-gcc
    AS=arm-none-eabi-as
    LD=arm-none-eabi-ld
    OBJCP=arm-none-eabi-objcopy
    OBJDUMP=arm-none-eabi-objdump

    COMPILE_OPTS =-mcpu=cortex-m3 -mthumb -Wall -g3 -O0
    INCLUDE_DIRS =-I .
    USR_LIBS=
    LINKER_SCRIPT=stm32_ld.ld


    CFLAGS=$(COMPILE_OPTS) $(INCLUDE_DIRS)
    #ASMFLAGS=-mcpu=cortex-m3 -mthumb -Wall -g3 -ahls=$*.lst
    ASMFLAGS=-mcpu=cortex-m3 -mthumb
    #LDFLAGS =-nostartfiles -Wl,-M,-Map=$(TARGET).map -T$(LINKER_SCRIPT)
    #LDFLAGS =-Wl,-M,-Map=$(TARGET).map
    LDFLAGS =-Ttext=0x8000000 -Map=$(TARGET).map

    OBJCPFLAGS = -O
    ODFLAGS= -S

    %.o:%.c Makefile
       $(CC) $(CFLAGS) $<
       
    %.o:%.s Makefile
       $(AS) $(ASMFLAGS) $< -o $@
       $(info Assembluje $(AS) $(ASMFLAGS) $<)
       $(info parametry $(ASMFLAGS))
       
    CSRC=
    ASRC=main.s   \
        routines.s
       
    C_OBJS=$(CSRC:.c=.o)   
    A_OBJS=$(ASRC:.s=.o)
       
    SRC_FILES=$(CSRC) $(ASRC)   
    OBJ_FILES=$(C_OBJS) $(A_OBJS)

    TARGET_BIN=$(TARGET).bin
    TARGET_HEX=$(TARGET).hex    
    TARGET_ELF=$(TARGET).elf
    TARGET_LST=$(TARGET)_lst.lst   
       
    $(TARGET_ELF): $(USR_LIBS) $(OBJ_FILES)
       $(info Linkuje obiekty $(OBJ_FILES))
       $(LD) $(LDFLAGS) $(OBJ_FILES)  --output $@
       
       
       
    $(TARGET_BIN): $(TARGET_ELF)
       $(OBJCP) $(TARGET_ELF) -O binary $@   
       $(OBJDUMP) $(ODFLAGS) $(TARGET_ELF) > $(TARGET_LST) 

    $(TARGET_HEX): $(TARGET_ELF)
       $(OBJCP) $(TARGET_ELF) -O ihex $@   
       
       
    all:   $(TARGET_BIN) $(TARGET_HEX)
       
    clean:
       rm -f *.o
       rm -f *.map
       rm -f *.elf
       rm -f *.bin
       rm -f *.hex


    i tu pojawia się problem po zlinkowaniu widzę (zrzut objdumpem)

    8000018: f000 e806 blx 8000028 <InitClock>

    po zlinkowaniu mam instrukcje BLX zamiast BL i program idzie mi w maliny.

    Problemu nie ma gdy wykonam skok do podprocedury z użyciem rozkazu BL
    jeśli ta podprocedura jest zdefiniowana w tym samym pliku.

    Co robię nie tak?
    Sprawdzałem objdumpem moje programy napisane w C i tam były skoki do funkcji zdefiniowanych w innym pliku/obiekcie i był użyty rozkaz BL.

    W załączniku wrzucam moje "mini-środowisko" z dwoma plikami źródłowymi i plikiem makefile
  • Computer ControlsComputer Controls
  • Poziom 28  
    A czy po
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Nie powinieneś podać jeszcze adresu początku programu zamiast kodu programu?
    Code:
    8000000:   20000800    .word   0x20000800
    
    8000004:   2003         movs   r0, #3

    Tak to raczej nie zadziała :/
    No i warto zostawić miejsce na obsługę chociażby wyjątków rdzenia (Bus fault itp).
  • Computer ControlsComputer Controls
  • Specjalista - Mikrokontrolery
    Ściągnij sobie z mojej strony przykład dla Cortex-M3 i zobacz jakie dodatkowe parametry są potrzebne w pliku assemblerowym, bo "trochę" Ci jeszcze brakuje.

    Pozatym do linkowania TRZEBA używać gcc, a nie ld.

    P.S. Co to za moda na assembler dla ARMów?

    4\/3!!
  • Poziom 14  
    Witam, posiedziałem odrobinę i większość problemów się rozwiązała.

    <Pituś Bajtuś> oczywiście masz całkowitą rację. Po adresie początku stosu ma być
    tablica wyjątków/przerwań a nie instrukcje.

    Tak się ciekawie złożyło że kod się uruchamiał (ale pewnie tylko pod debuggerem )
    czyli głupi ma zawsze szczęście jeśli nawet jest ono złudne ;)

    dodałem obsługę podstawowych wyjątków:

    reset_handler
    nmi_handler
    hard_fault_handler
    mem_manage_handler
    bus_fault_handler
    usage_fault_handler

    Przy okazji wyszło jeszcze parę rzeczy:

    Jeśli w kodzie nie użyję dyrektywy:
    .type nazwa_handlera, function

    to przy wyrównaniu do słowa

    dyrektywa .word reset_handler powodowała że w tablicę został wpisany
    wprost adres procedury reset_handler a więc adres parzysty.
    przy próbie uruchomienia generowany był wyjątek.

    czyli zachodził +/- przypadek:
    Cytat:
    Accidentally Switching to the ARM State
    One of the most common causes of usage faults is accidentally trying to switch the
    processor to ARM mode. This can happen if you load a new value to PC with the
    LSB equal to 0—for example, if you try to branch to an address in a register (BX LR)
    without setting the LSB, have zero in the LSB of a vector in the exception vector table,
    or the stacked PC value to be read by POP {PC} is modifi ed manually, leaving the LSB
    cleared. When these situations happen, the usage fault exception will take place with the
    INVSTATE bit in the UFSR set.


    tyle że nie przy instrukcji skoku tylko obsłudze przerwania

    Mój problem z BL label również polegał na braku dyrektywy
    mówiącej że label jest funkcją. Jeśli brakowało tej dyrektywy
    generowana była instrukcja 0xf000e816 co objdump pokazywał jako blx
    a co powodowało wyjątek, jeśli użyliśmy dyrektywy .type label, function
    instrukcja została poprawnie zakodowana (0xf000f816) i wszystko działa ;)

    <Freddie>: co do moich zabaw z assemblerem dla ARMów to nie przejaw mody ale chęci głębszego zrozumienia działania tych procesorów.
    Chciałbym popróbować się z wyjątkami, przełączaniem między poziomami uprzywilejowania, może jakieś instrukcje atomiczne i ochrona pamięci + jakieś mruganie diodą na koniec ;)
    Myślę że lepiej to zrobić z poziomu assemblera niż C.
    Druga korzyścią jaką widzę z tej zabawy to że może się przydać w debuggowaniu
    różnych problemów zwłaszcza z użyciem zamkniętych bibliotek.
    Udało mi się popełnić kilka mini-projektów na STM32 w C po dostosowaniu "startupu" czy OSa assembler nie był mi do niczego potrzebny gorzej jak pojawiły
    się nieoczekiwane błędy, myślę ze taka wiedza pomogłaby mi szybciej rozwiązać takie problemy.
    Najmniej rzeczywiście chyba przyda się przy optymalizacji ale nigdy nie wiadomo...


    co do linkera to wydawało mi się ze gcc też woła ld

    Pozdrawiam i dzięki za odpowiedzi

    Dodano po 3 [minuty]:

    I mój poprawiony kod. Jeśli byłby dla kogoś pomocny.
  • Użytkownik usunął konto  
  • Poziom 14  
    Code:
    #LDFLAGS =-nostartfiles -mthumb -mcpu=cortex-m3 - -Wl,-M,-Map=$(TARGET).map -T$(LINKER_SCRIPT)

    Linker musi wiedzieć dla jakiej platformy generować adresy. Adres musi mieć najmniej znaczący bit ustawiony na 1.
  • Użytkownik usunął konto