Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Cortex M4F] - [Bleeding toolchain / brak obsługi FPU]

bkawlatow 12 Dec 2013 21:26 2025 11
Computer Controls
  • #1
    bkawlatow
    Level 10  
    Witam,

    Od jakiegoś czasu staram się uporać z problemem który częściowo był poruszany w temacie : https://www.elektroda.pl/rtvforum/topic2249496.html .

    Do rzeczy:
    Po użyciu instrukcji dana=sqrtf(dana*dana*dana) i deasemblacji zamiast instrukcji vsqrt dostaję instrukcję skoku pod __ieee754_sqrtf. Wynik po deasemblacji jest następujący:

    Code: c
    Log in, to see the code


    W makefile dodaję :
    CORE_FLAGS = -mcpu=$(CORE) -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffast-math

    Czy o czymś zapomniałem? Wcześniej procesor używa instrukcji Vxxx a więc kooprocesor jest uruchomiony. Próbowałem kompilować kod na różnych poziomach optymalizacji oraz w różnych projektach, ale wynik jest ten sam ( brak użycia VSQRT).
    Jakieś pomysły?
  • Computer Controls
  • #2
    Freddie Chopin
    MCUs specialist
    Nie można mieć wszystkiego (; Nie wiem jednak czemu twierdzisz, że bleeding-edge-toolchain czegoś nie obsługuje, skoro widać jak na dłoni, że mnożenia masz załatwione jednak przy użyciu FPU...

    Przy okazji...

    -O3

    Code:
       volatile float dana = 1.0f;
    
    140001a2:   f04f 537e    mov.w   r3, #1065353216   ; 0x3f800000
    140001a6:   9300         str   r3, [sp, #0]
       
       dana=sqrtf(dana*dana*dana);
    140001a8:   ed9d 7a00    vldr   s14, [sp]
    140001ac:   eddd 6a00    vldr   s13, [sp]
    140001b0:   eddd 7a00    vldr   s15, [sp]
    140001b4:   ee26 0a87    vmul.f32   s0, s13, s14

       volatile uint32_t count, count_max = 10000000;
    140001b8:   f249 6480    movw   r4, #38528   ; 0x9680
     
    int main(void)
    {
       volatile float dana = 1.0f;
       
       dana=sqrtf(dana*dana*dana);
    140001bc:   ee60 0a27    vmul.f32   s1, s0, s15
     */

    static void fpu_enable(void)
    {
    #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
       SCB->CPACR |= ((3UL << 10 * 2)|(3UL << 11 * 2));   // set CP10 and CP11 Full Access
    140001c0:   f44f 456d    mov.w   r5, #60672   ; 0xed00
     
    int main(void)
    {
       volatile float dana = 1.0f;
       
       dana=sqrtf(dana*dana*dana);
    140001c4:   eeb1 1ae0    vsqrt.f32   s2, s1


    -Os

    Code:
       volatile float dana = 1.0f;
    
    140001a0:   f04f 537e    mov.w   r3, #1065353216   ; 0x3f800000
    140001a4:   9300         str   r3, [sp, #0]
       
       dana=sqrtf(dana*dana*dana);
    140001a6:   eddd 7a00    vldr   s15, [sp]
    140001aa:   eddd 6a00    vldr   s13, [sp]
    140001ae:   ed9d 7a00    vldr   s14, [sp]
    140001b2:   ee26 0aa7    vmul.f32   s0, s13, s15

       volatile uint32_t count, count_max = 10000000;
    140001b6:   4837         ldr   r0, [pc, #220]   ; (14000294 <main+0xf8>)
     */

    static void fpu_enable(void)
    {
    #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
       SCB->CPACR |= ((3UL << 10 * 2)|(3UL << 11 * 2));   // set CP10 and CP11 Full Access
    140001b8:   4937         ldr   r1, [pc, #220]   ; (14000298 <main+0xfc>)
    {
       volatile uint32_t count;
       uint32_t m, n, real_frequency, best_m = 0, best_n = 0, best_real_frequency = 0;

       // enable crystal oscillator, crystal < 15MHz - low frequency, crystal >= 15MHz - high frequency
       LPC_CGU->XTAL_OSC_CTRL = crystal < 15000000 ? 0 : CGU_XTAL_OSC_CTRL_HF_Pos;
    140001ba:   4d38         ldr   r5, [pc, #224]   ; (1400029c <main+0x100>)
     
    int main(void)
    {
       volatile float dana = 1.0f;
       
       dana=sqrtf(dana*dana*dana);
    140001bc:   ee60 0a07    vmul.f32   s1, s0, s14
    {
       volatile uint32_t count;
       uint32_t m, n, real_frequency, best_m = 0, best_n = 0, best_real_frequency = 0;

       // enable crystal oscillator, crystal < 15MHz - low frequency, crystal >= 15MHz - high frequency
       LPC_CGU->XTAL_OSC_CTRL = crystal < 15000000 ? 0 : CGU_XTAL_OSC_CTRL_HF_Pos;
    140001c0:   2700         movs   r7, #0
     
    int main(void)
    {
       volatile float dana = 1.0f;
       
       dana=sqrtf(dana*dana*dana);
    140001c2:   eeb1 1ae0    vsqrt.f32   s2, s1


    -O2

    Code:
       dana=sqrtf(dana*dana*dana);
    
    140001a8:   ed9d 7a00    vldr   s14, [sp]
    140001ac:   eddd 6a00    vldr   s13, [sp]
    140001b0:   eddd 7a00    vldr   s15, [sp]
    140001b4:   ee26 0a87    vmul.f32   s0, s13, s14

       volatile uint32_t count, count_max = 10000000;
    140001b8:   f249 6480    movw   r4, #38528   ; 0x9680
     
    int main(void)
    {
       volatile float dana = 1.0f;
       
       dana=sqrtf(dana*dana*dana);
    140001bc:   ee60 0a27    vmul.f32   s1, s0, s15
     */

    static void fpu_enable(void)
    {
    #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
       SCB->CPACR |= ((3UL << 10 * 2)|(3UL << 11 * 2));   // set CP10 and CP11 Full Access
    140001c0:   f44f 456d    mov.w   r5, #60672   ; 0xed00
     
    int main(void)
    {
       volatile float dana = 1.0f;
       
       dana=sqrtf(dana*dana*dana);
    140001c4:   eeb1 1ae0    vsqrt.f32   s2, s1


    Na -O1 mi się już nie chce sprawdzać. Na -O0 oczywiście jest wywołanie funkcji.

    Code:
    >make
    
    Assembling file: startup_ARMv7-M_E_.S
    arm-none-eabi-gcc -x assembler-with-cpp -c -mcpu=cortex-m4 -mthumb -mfloat-abi=h
    ard -mfpu=fpv4-sp-d16 -ffast-math -g -ggdb3 -Wa,-amhls=out/startup_ARMv7-M_E_.ls
    t  -DCORE_M4  -DCMSIS_BITPOSITIONS  -MD -MP -MF out/startup_ARMv7-M_E_.d -I.  -I
    inc startup_ARMv7-M_E_.S -o out/startup_ARMv7-M_E_.o

    Compiling file: main.c
    arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
    -ffast-math -O2 -ffunction-sections -fdata-sections -Wall -Wstrict-prototypes -W
    extra -std=gnu89 -g -ggdb3 -fverbose-asm -Wa,-ahlms=out/main.lst  -DCORE_M4  -DC
    MSIS_BITPOSITIONS  -MD -MP -MF out/main.d -I.  -Iinc main.c -o out/main.o

    Compiling file: vectors_LPC43xx_Cortex-M4.c
    arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
    -ffast-math -O2 -ffunction-sections -fdata-sections -Wall -Wstrict-prototypes -W
    extra -std=gnu89 -g -ggdb3 -fverbose-asm -Wa,-ahlms=out/vectors_LPC43xx_Cortex-M
    4.lst  -DCORE_M4  -DCMSIS_BITPOSITIONS  -MD -MP -MF out/vectors_LPC43xx_Cortex-M
    4.d -I.  -Iinc vectors_LPC43xx_Cortex-M4.c -o out/vectors_LPC43xx_Cortex-M4.o

    Linking target: out/lpc4330_blink_led.elf
    arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ff
    ast-math -TLPC4330_50_SPIFI_4MB.ld -g -Wl,-Map=out/lpc4330_blink_led.map,--cref,
    --no-warn-mismatch -Wl,--gc-sections -nostartfiles  out/startup_ARMv7-M_E_.o out
    /main.o out/vectors_LPC43xx_Cortex-M4.o    -o out/lpc4330_blink_led.elf

    Creating extended listing: out/lpc4330_blink_led.lss
    arm-none-eabi-objdump --demangle -S out/lpc4330_blink_led.elf > out/lpc4330_blin
    k_led.lss

    Creating memory dump: out/lpc4330_blink_led.dmp
    arm-none-eabi-objdump -x --syms out/lpc4330_blink_led.elf > out/lpc4330_blink_le
    d.dmp

    Creating IHEX image: out/lpc4330_blink_led.hex
    arm-none-eabi-objcopy -O ihex out/lpc4330_blink_led.elf out/lpc4330_blink_led.he
    x

    Creating binary image: out/lpc4330_blink_led.bin
    arm-none-eabi-objcopy -O binary out/lpc4330_blink_led.elf out/lpc4330_blink_led.
    bin

    Size of modules:
    arm-none-eabi-size -B -t --common out/startup_ARMv7-M_E_.o out/main.o out/vector
    s_LPC43xx_Cortex-M4.o
       text    data     bss     dec     hex filename
        136       0       0     136      88 out/startup_ARMv7-M_E_.o
        384       0       0     384     180 out/main.o
        544       0       0     544     220 out/vectors_LPC43xx_Cortex-M4.o
       1064       0       0    1064     428 (TOTALS)

    Size of target .elf file:
    arm-none-eabi-size -B out/lpc4330_blink_led.elf
       text    data     bss     dec     hex filename
       1084       0    1024    2108     83c out/lpc4330_blink_led.elf



    4\/3!!
  • #3
    bkawlatow
    Level 10  
    Czyli jak? Ten sam toolchain, ten sam kod, a mimo to inny rezultat?
  • Computer Controls
  • #5
    bkawlatow
    Level 10  
    Siedzę na STM32F4 a kod po okrojeniu kilku funkcji jest taki:

    Code: c
    Log in, to see the code


    ,gdzie enable_fpu jest żywcem wzięte z Twojego przykładu. Makefile także z Twojego stm32f4_blink_led. Jakieś sugestie?
  • #7
    bkawlatow
    Level 10  
    Na O1 przy niewykorzystywaniu zmiennej dana faktycznie ją usuwał. Niemniej jednak przy O0 nic nie zostało usunięte, przy pracy krokowej mogłem wejść do wywołania sqrtfa itd.
  • Helpful post
    #8
    Freddie Chopin
    MCUs specialist
    No ale czemu przy zerowej optymalizacji spodziewasz się ... optymalizacji? Poza O1 i O0 są jeszcze 3 inne wartości tej flagi, które - w przeciwieństwie do tych poprzednich - mają jakiś sens...

    Czy aby na pewno sprawdziłeś że kompilator nie robi tego co chcesz, czy może będzie to kolejna cegiełka do mojej kolekcji "znalazłem błąd w kompilatorze, sam na 100% robię wszystko dobrze"?

    4\/3!!
  • #9
    bkawlatow
    Level 10  
    Skoro nie działa, zakładam że gdzieś jest błąd. W celu jego rozwiązania napisałem tutaj.
    Wynik kompilacji:

    Code: c
    Log in, to see the code
  • Helpful post
    #10
    Freddie Chopin
    MCUs specialist
    Po raz trzeci pytam, dlaczego przy ustawionej ZEROWEJ optymalizacji oczekujesz żeby kompilator coś zoptymalizował. Wychodzi na to, że próbowałeś na różnych poziomach optymalizacji i na zerowym wywołuje funkcję (tak właśnie jest u mnie i tak ma być), natomiast na innych wywala cały ten kod jako zbędny (również napisałem co z tym zrobić) - wniosek - "kompilator nie obsługuje FPU"...

    4\/3!!
  • #11
    bkawlatow
    Level 10  
    Uzyskałem oczekiwany wynik. Tak jak mówiłeś Freddie, kolejny głupi błąd. Edytowałem makefile "z palca" w notatniku a nie z poziomu środowiska. Niestety był to make z innego projektu...
    Obecna postać:
    Code: c
    Log in, to see the code

    Teraz wszystko działa jak należy. Przy okazji przyszło mi do głowy jeszcze jedno pytanie: przy projekcie obsługi wyświetlacza LCD wyłączonych optymalizacjach wszystko działa jak należy. Po włączeniu optymalizacji (jakichkolwiek) program przestaje działać (brak obsługi LCD). Jakie mogą być przyczyny? Źle inicjalizowane zmienne? Złe typy funkcji? Prześledzę jeszcze krok po kroku działanie programu od startu proca, na pewno dojdę do tego co wycina optymalizacja, jednak fajnie byłoby wiedzieć na co zwracać uwagę.
    Dzięki za wcześniej poświęcony czas :)
  • Helpful post
    #12
    Freddie Chopin
    MCUs specialist
    bkawlatow wrote:
    fajnie byłoby wiedzieć na co zwracać uwagę.

    Na funkcje opóźniające w postaci pustych pętli z inkrementacją zwykłych zmiennych. No i na wszelkie zależności czasowe.

    4\/3!!