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

[ARM-Assembler][STM32] Co na początek ?

30 Kwi 2011 17:16 10639 20
  • Poziom 15  
    Witam,

    Chcę rozpocząć przygodę z tą architekturą od samych "podstaw" (od środka). Na wstępie od razu zaznaczam że nie chcę zaczynać przygody zaczynając od C (później jak najbardziej tak) ponieważ chcę się dobrać do bebechów, grzebać w rejestrach poznać wszystko od najniższego poziomu.
    Dlaczego ? Może dlatego że lubię i mogę.

    Oczywiście są 2 osobne sprawy z tym związane:
    - poznanie instrukcji/składni dla ARM
    - poznanie architektury procka

    Pierwsze pozwoli na swobodne przemieszczanie się pomiędzy różnymi uC jak i pomiędzy różnymi producentami co nie ogranicza się do uczenia jednego API
    Drugie przyda się wszędzie, jak już się przejdzie przez jeden uC to z resztą będzie łatwiej


    Więc tak:
    - jestem w trakcie lektury poznawania instrukcji assemblerowych (Thumb i Thumb2) ARM and Thumb Instructions

    -Dokumentacja procka STM32F103VET (na razie tylko trochę przeglądałem)
    *DATASHEET
    *APPLICATION NOTES
    *PROGRAMMING MANUALS itp


    -Fora internetowe niestety większość (jak nie wszyscy) jadą z bibliotek C więc nic ciekawego nie znalazłem.

    -Książki są dobre tak samo jak ich ceny np: "ARM Assembly Language: Fundamentals and Technique" - 85$
    Rodzime produkcje są ale nie dla ARM ASM.


    Jeśli chodzi o mnie to jakoś ta dokumentacja ST do mnie nie przemawia. Może dlatego że przejrzałem tylko parę dokumentów bez dogłębnego przeczytania...

    Więc przechodząc do pytania, może już ktoś zaczynał coś takiego od podstaw.
    Wie w jaką dokumentacje trzeba się zaopatrzyć (co się przyda a co nie), ma jakieś dobre rady odnośnie "startu", książki , kursy itp .......


    Pozdrawiam.
  • PCBway
  • Poziom 33  
    Weź jakieś środowisko bezpłatne na początek i coś w nim napisz w asemblerze.
    Np. https://www.keil.com/demo/eval/arm.htm
    Napiszesz źle to Cię poprawi.
    Potem przylutuj kilka diod LED do procesora i wyjście na uart.
    Podłącz oscyloskop. Podepnij jakis prosty programator.
    Szkoda czasu na szukanie przykładów w sieci.
    Po co poprawiać cudze błędy jak można zrobić swoje.

    N.
  • PCBway
  • Pomocny post
    Poziom 13  
    Zajmuje się programowaniem w asemblerze procesorów ARM a dokładnie programuje układy oparte na rdzeniu Cortex-M0 (LPC111x) ale swój kod przenosiłem także na rdzeń Cortex-M3 (LPC13xx) taki sam jak w procesorach którymi ty jesteś zainteresowany (STM32). Postaram się teraz udzielić odpowiedzi na twoje pytania:

    1.
    Cytat:
    Wie w jaką dokumentacje trzeba się zaopatrzyć (co się przyda a co nie),..


    Na pewno będziesz potrzebował materiałów ze strony ARM-a które są dostępne po zarejestrowaniu się a dokładnie: DDI0403C_arm_architecture_v7m_reference_manual_errata_markup_3_0.pdf

    Będziesz potrzebował także pełnej dokumentacji do układu a nie jakiegoś ochłapu a możesz pobrać go stąd: http://www.keil.com/dd/chips/stmicroelectronics/arm.htm i klikasz na twój układ a następnie pobierasz Reference Manual.

    I masz też trochę literatury za darmo (pierwszy rozdział książki jest za darmo dostępny ale niestety tobie cała książka raczej nie przyda się więc nie polecam jej zakupu) http://www.btc.pl/pliki/stm32wp_rozdz1.pdf

    2.
    Cytat:
    ma jakieś dobre rady odnośnie "startu"


    Mam rade która może być bardzo pomocna a dokładnie nauczyć się korzystać z objdump-a służącego do deasemblacji plików (ja używam tego narzędzia na plikach o rozszerzeniu axf) jest to narzędzie zawarte standardowo w GCC. Musisz też pamiętać że to nie jest AVR i tu na przykład porty wejścia/wyjścia w układzie NXP będą inaczej zrealizowane niż na przykład w układzie z rodziny STM32. Z powyższego powodu wynika między innymi fakt że kod odpowiedzialny za mruganie diodą, SPI, UART na jednym układzie będzie wyglądał zupełnie inaczej niż u innego producenta w tym samym rdzeniu. Możesz być często skazany na deasemblacje pliku wynikowego powstałego z kodu napisanego w C i późniejszą wnikliwą analizę co tam zachodzi, żeby na przykład poprawnie zainicjować UART.

    3.
    Cytat:
    książki , kursy itp .......

    Nie zdziwiłbym się gdyby takie coś co ty chcesz robić nie byłoby nigdy wcześniej wykonywane więc na kursy nie licz a wątki o programowaniu ARM-ów w asemblerze (szczególnie rdzeni z rodziny Cortex) są często bez odpowiedzi. Ja może za jakiś czas coś udostępnię związanego z tym tematem bo dość sporo bawiłem się ARM-ami i pisałem w asemblerze ale niestety dla ciebie moja robota była związana z układami produkowanymi przez NXP.

    Jeżeli masz jeszcze jakieś pytania to chętnie na nie udzielę ci odpowiedzi.
  • Poziom 15  
    Witam,

    Dzięki wielki wujcio24 & tymon_x za informacje.
    Na początek te 3 pozycje mi w zupełności wystarczą:
    - arm_architecture_v7m_reference_manual
    - Reference Manual for STM32F103VE
    - The Definitive Guide to the ARM Cortex-M3

    Teraz chyba czas aby pomrugać trochę LED'em :)

    Pozdrawiam.
  • Poziom 35  
    asm cortexa-m3 jest naprawdę prosty. wystarczy się zapoznać z dokumentacją, którą producent rdzenia udostępnia.

    Ja pisałem całe funkcje w tym asmie, bo inline assembler nie jest obslugiwany w keilu dla rozkazów thumb2 (nie wiem czemu, czasami byloby wygodnie).

    Często jednak jest tak, że kod C wygenerowany przez kompilator jest jednak lepszy niż to, co napisze się samemu. Lecz czasami warto, głównie tu, gdzie uzywa się instrukcji których kompilator nie uzywa, np. CLZ

    Stosuje się równiez w tym celu osobne funkcyjki, które są całe w asmie napisane, przyjmują argumenty w r0 i r1, i zwracają w r0. Wtedy te funkcyjki można wywoływać z kodu pisanego czysto w C.
  • Poziom 15  
    Assembler jak każdy inny język programowania da się strawić.
    Problem jest z poprawnym i zwięzłym posługiwaniu się tym językiem w przypadku rdzenia Cortex M3 razem z tak bardzo rozbudowanymi (peryferia) uC jakimi są produkty firmy ST.

    Jednak wydaje mi się że cała zabawa właśnie na tym polega. Podkreślam zabawa :)

    Pozdrawiam.
  • Poziom 13  
    Cytat:
    Stąd pytanie czy ktoś z was pisze całe programy w asm czy tylko wstawki asm w C ?


    Ja pisze prawie całe programy w asemblerze. Prawie całe ponieważ inicjacje mam w C ze względu na IDE w jakim pracuje - LCPXpresso. Funkcja main natomiast jest już w całości napisana w asemblerze. Pisze głównie dla układów z rdzeniem Cortex-M0 (LPC111x) ponieważ ten rdzeń jest prostszy od Cortex-M3(dla tego rdzenia także odpalałem swoje programy) więc pisanie w asemblerze ma sens. Poza tym LPC111x to jest świetna alternatywa dla układów 8-bitowych a jakbym potrzebował większej mocy to zawsze mogę swoje programy odpalić na Cortex-M3 (LPC13xx lub LPC17xx).

    A tutaj mój program dla przykładu który miga diodą po naciśnięciu przycisku:
    Mam też świadomość że ten program jest napisany w sposób nie optymalny ale to w celu dydaktycznym.

    Code:
        .syntax unified
    
        .cpu cortex-m0
        .align   2
        .global   main
        .thumb
        .thumb_func
    main:
             push   {r7, lr}

          //DIR
          //ustawienie kierunku pracy - wejscie(0)/wyjscie(1)   | 64(7 bit led1), 128(8 bit led2)
          movs r0, #192
          LDR R2, =0x50008000
          STR r0, [r2]

          //DATA
          //ustawienie stanu na pinie - wysoki(1)/niski(0)
          //gaszenie drugiej diody i zerowanie pozostalych bitow
          movs r0, #128
          LDR R2, =0x50003FFC
          STR r0, [r2]
    led:
          //DATA mask
          //gaszenie drugiej diody z użyciem maski
          movs r0, #128
          ldr r2, =0x50000200
          str r0, [r2]

    button:
          //sprawdzanie czy dziala przycisk z zastosowaniem maskowania
          //joy - P0_3 - 6bit
          movs r3, #0x8
          ldr r2, =0x50000020
          ldr r2, [r2]
          cmp r2, r3

          beq led

          //DATA mask
          //wlaczenie drugiej diody z wykorzystaniem maskowania
          movs r0, #0
          ldr r2, =0x50000200      //bit na 7 pozycji
          str r0, [r2]
          b button

    LOOP:
          nop
          b LOOP
            pop   {r7, pc}
  • Poziom 19  
    Niejako nawiązując do tematu:
    Czy jeśli w nocie napisano że rozkaz wykonuje się w jednym cyklu to np: przy taktowaniu rdzenia zegarem o f=72MHz czas wykonania tego rozkazu będzie trwał t = 1/f ?
    Podejrzałem w debugerze jak kompilator zamienił kod regulatora PI napisany w C na asm. I np instrukcję
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Przetłumaczył na:
    Kod: asm
    Zaloguj się, aby zobaczyć kod



    Gdy kod napisany w C jest następujący:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    To w ASM:

    Kod: asm
    Zaloguj się, aby zobaczyć kod


    Który kod wykona się szybciej (Chyba będzie bez różnicy bo MLA zastąpione zostało przez MUL i ADD)?
    Rozkaz MLA Multiply accumulate wykonuje się przez 2 cykle.
    STM to nie DSP, ale czy już ten rokaz MLA przyśpiesza cyfrowe przetwarzanie danych czy to jeszcze nie to, jeśli trwa przez 2 cykle to w zasadzie nic nie przyśpiesza?
    [/code]
  • Poziom 15  
    Witam,

    Cytat:
    Czy jeśli w nocie napisano że rozkaz wykonuje się w jednym cyklu to np: przy taktowaniu rdzenia zegarem o f=72MHz czas wykonania tego rozkazu będzie trwał t = 1/f ?

    Tak, np jeden cykl przy kwarcu 1MHz bedzie trwal 1us, duzo instrukcji assemblera wykonuje sie w czasie tego jednego cyklu (niektóre trwają dłużej).

    MLA trwa tyle samo co MUL i ADD lecz to pierwsze jest bardziej rekomendowane do świadomego używania. Jednak są też triki umożliwiające zrobić to szybciej niż MLA.

    Pozdrawiam.
  • Poziom 19  
    Mam przed sobą Cortex™-M3
    Revision r2p1
    Technical Reference Manual
    i tam napisane jest iż MLA trwa dwa cykle a np ADD, MUL jeden czyli ja zysku nie widzę przy wykorzystaniu tego rozkazu (Czasowego bo to tylko chyba objętościowy zysk). Staram się w sposób świadomy pisać w C tak aby kod wykonywał się jak najszbiciej.
    ale jeśli nie ma różnicy w czasie wykonania między
    suma_uchyb =suma_uchyb + uchyb*Ki;
    wyjscie = suma_uchyb + Kp * uchyb;[/syntax]
    a
    Kod: c
    Zaloguj się, aby zobaczyć kod

    To z pewnych względów wolę drugi zapis.

    Następnie drodzy forumowicze co tak naprawdę oznacza wait state przy odczycie z pamięci flash w stm32?? Czy dzięki zastosowaniu przetwarzania potokowego czas ten nie zwalania mi wykonywanie kodu przez uC?
  • Poziom 15  
    Cytat:
    i tam napisane jest iż MLA trwa dwa cykle a np ADD, MUL jeden czyli ja zysku nie widzę przy wykorzystaniu tego rozkazu

    Moja odpowiedz mogła być trochę źle zrozumiana ale MLA trwa tyle samo (2 cykle) co (ADD 1cykl + MUL 1 cykl) no i tak jest, jednak czytałem że zaleca się używanie MLA.

    Cytat:
    Następnie drodzy forumowicze co tak naprawdę oznacza wait state przy odczycie z pamięci flash w stm32?? Czy dzięki zastosowaniu przetwarzania potokowego czas ten nie zwalania mi wykonywanie kodu przez uC?


    Myślę że tu znajdziesz odpowiedz.

    Cytat:
    When we looked at the system architecture of the STM32 we saw that the Cortex-M3 core is connected to the
    internal FLASH by a dedicated I-Bus. This bus is running at the same frequency as the CPU, so with the PLL
    enabled the core will be trying to run at the full 72 MHz. Since the Cortex CPU is essentially a single cycle
    machine, it will be trying to access the FLASH every 1.3ns. When the STM32 starts up it is running from the
    internal oscillator at 8 MHz, so the access time of the internal FLASH is not an issue. However, once the PLL is
    enabled and becomes the clock source, the FLASH access time is simply too long (35 ns.) to allow the Cortex
    CPU to run at maximum performance. In order to allow the Cortex CPU to run at 72 MHz with zero waitstates, the
    FLASH memory has a prefetch buffer which is made up of two 64-bit buffers. Both of these buffers can do a 64-
    bit-wide read of the FLASH memory and then pass the individual 16 or 32-bit instructions to the Cortex CPU for
    execution. This technique works well with the conditional execution features of the Thumb-2 instruction set and
    the branch prediction of the Cortex pipeline. During normal operation the programmer does not need to take any
    special precautions because of the FLASH buffer. However you must make sure that it is enabled before
    switching to the PLL as the main clock source. The FLASH buffer is controlled by the FLASH access control
    register. As well as enabling the prefetch buffer, you must tune the number of waitstates required for the FLASH
    prefetch buffer to read the 8 bytes of instructions from the FLASH memory. The latency settings are as follows:

    0< SYSCLK <24MHz 0 waitstate
    24< SYSCLK <48MHz 1 waitstate
    48<SYSCLK <72MHz 2 waitstate

    These waitstates are between the prefetch buffer and the FLASH memory and do not impact on the Cortex CPU.
    As the CPU is executing instructions held in the first half of the buffer, the second half is loading so that the CPU
    can seamlessly continue execution at its optimum rate.
  • Poziom 15  
    Witajcie,

    Kontynuując moją przygodę "chirurga ARM" doszedłem (i zatrzymałem się) do plików startup'owych i linkera. Przeglądając czarne zakamarki internetu znalazłem jakieś przykłady (Fredie'go też) lecz nie rozumiem na jakiej podstawie one powstały. Jako główne źródło podawana jest biblioteka standardowa STM i zawarte tam przykłady. Interesuje mnie głównie jakiś opis składni i podstawowa zawartość tych plików (stos, flash, przerwania itp).
    Chcę pozostać przy samym asamberze więc pytanie brzmi czy naprawdę pliki te są potrzebne ?? Nie wystarczy tego umieścić w pliku głównym *.S ??
    Jeśli nie (a na pewno tak będzie :) ) to jak te pliki powinny wyglądać mi wyglądają na pliki przystosowane do c.

    wujcio24 napisałeś wcześniej że przepisywałeś swoje programy w assemblerze na Cortex'a M3, masz może możliwość ich udostępnienia (startup & ld) ?


    Update:
    - Do linkera jest manual z CodeSourcery :)Linker (raczej dam radę)
    - Do startup'u (czy naprawdę potrzebny ?), znalazłem fajną stronkę :Assembler-STM32 gdzie nie ma pliku startupowego (wszystko jest w głównym pliku programu)


    Pozdrawiam.
  • Poziom 13  
    Zamieszczam wyeksportowany plik z LPCXpresso z programem napisanym w asemblerze. Program ten mruga diodą w równych odstępach czasu które są odmierzane przez 32-bitowy timer. Program ten był testowany na tej płytce http://www.kamami.pl/index.php?ukey=product&productID=136174 na układzie LPC1343. W pliku jest wszystko co niezbędne - skrypty linkera i startup (zapomniałem o hex-ie). Wrzuciłbym wcześniej ten plik ale nie miałem przez pewien czas dostępu do kompa na którym to miałem.
  • Poziom 18  
    A ma ktoś czasem jakiś przykładowy projekt w asemblerze dla STM32 najlepiej pisany w środowisku Eclipse ?
  • Specjalista - Mikrokontrolery
    r00cky napisał:
    Assembler jak każdy inny język programowania da się strawić.
    Problem jest z poprawnym i zwięzłym posługiwaniu się tym językiem w przypadku rdzenia Cortex M3 razem z tak bardzo rozbudowanymi (peryferia) uC jakimi są produkty firmy ST.

    Assembler ARMów został wymyślony dla kompilatorów, nie dla ludzi. W 99% przypadków człowiek nie stworzy lepszego kodu niż kompilator. W pozostałym procencie i tak pewnie więcej oszczędzi się poprawiając algorytm czy program "całościowo".

    Cytat:
    Jednak wydaje mi się że cała zabawa właśnie na tym polega. Podkreślam zabawa :)

    Bardziej masochizm, no ale - jak już gdzieś dziś pisałem - są różne zboczenia... [;

    4\/3!!
  • Poziom 35  
    Freddie Chopin napisał:
    Assembler ARMów został wymyślony dla kompilatorów, nie dla ludzi.

    Radykalne stwierdzenie... Ja powiedziałbym, że assembler ARMów został wymyślony dla... ARMów. Nawet najlepszy kompilator nie jest w stanie zupełnie zastąpić człowieka, i bywa, ze da się coś napisać lepiej samemu w asmie, niż wygenerował kompilator (a Keil jest naprawdę dobry i cięzko go gdziekolwiek poprawić). Ale tu mówię tylko o wstawkach...

    A asm ARMów jest prosty i logiczny - nie rozumiem jak można go nie rozumieć... ;] IMHO asm dsPICa jest bardziej poplątany niz ten ARMa.
  • Specjalista - Mikrokontrolery
    nsvinc napisał:
    Radykalne stwierdzenie... Ja powiedziałbym, że assembler ARMów został wymyślony dla... ARMów.

    Radykalne czy nie, to fakt. Zestaw instrukcji ARM został stworzony w taki a nie inny sposób po to, aby jak najlepiej były go w stanie wykorzystać kompilatory C. Bardzo duża ortogonalność (porównaj z czymkolwiek innym) pod względem rejestrów (np AVR w którym niektóre instrukcje mogą korzystać tylko z konkretnych rejestrów), adresowania, dodatkowych manewrów (barrel-shifter) itd. Thumb czy Thumb-2 jest już nieco przycięty, ale "normalny" tryb ARM jest nieziemsko ortogonalny (każda instrukcja może być warunkowa, może operować na bajtach, półsłowach czy całych słowach, ...). Te wszystkie tricki są tam po to, żeby odzwierciedlić typową pracę kompilatora.

    Cytat:
    Nawet najlepszy kompilator nie jest w stanie zupełnie zastąpić człowieka, i bywa, ze da się coś napisać lepiej samemu w asmie, niż wygenerował kompilator (a Keil jest naprawdę dobry i cięzko go gdziekolwiek poprawić).

    No właśnie - w ilu procentach przypadków warto poprawiać kompilator i jaki z tego zysk?

    Cytat:
    Ale tu mówię tylko o wstawkach...

    Exactly - czy cały (rozbudowany) program napisany w assemblerze może być lepszy niż napisany w C? Osobiście wątpię. Na pewno napisanie go zajmie wielokrotnie dłużej, a dowolna poprawka będzie wielokrotnie trudniejsza (i zajmie wielokrotnie więcej czasu).

    Nie mówiąc już o takich prostych rzeczach do zrobienia w assemblerze jak liczby zmiennoprzecinkowe czy bardziej zakręcone konstrukty programistyczne znane z C++ (listy, obiekty, dziedziczenie, funkcje wirtualne, ...).

    Cytat:
    A asm ARMów jest prosty i logiczny - nie rozumiem jak można go nie rozumieć... ;]

    Czy ktoś tu mówi, że nie rozumie tego assemblera? [;

    4\/3!!
  • Poziom 35  
    Freddie Chopin napisał:
    Radykalne czy nie, to fakt. Zestaw instrukcji ARM został stworzony w taki a nie inny sposób po to, aby jak najlepiej były go w stanie wykorzystać kompilatory C. Bardzo duża ortogonalność (porównaj z czymkolwiek innym) pod względem rejestrów (np AVR w którym niektóre instrukcje mogą korzystać tylko z konkretnych rejestrów), adresowania, dodatkowych manewrów (barrel-shifter) itd. Thumb czy Thumb-2 jest już nieco przycięty, ale "normalny" tryb ARM jest nieziemsko ortogonalny (każda instrukcja może być warunkowa, może operować na bajtach, półsłowach czy całych słowach, ...). Te wszystkie tricki są tam po to, żeby odzwierciedlić typową pracę kompilatora.

    I właśnie dlatego tak cudownie miło pisze się w asmie ARMa. W szczególności ARM i T2.
    Nie trzeba pamiętać o jakichś dziwnych specjalnych rejestrach, nie trzeba pamietac ktory rejestr czego nie potrafi, wogole nic nie trzeba pamietać ;]

    Jedyne czego mi bardzo brakuje w rdzonkach ARMa to brak natywnej obsługi prostego formatu stałoprzecinkowego np. Q15 (czy jak mu tam); asmowa emulacja tego to i tak 3..5 instrukcji, zamiast JEDNEJ. W przerwaniu które miałoby tłuc co 3us to jednak jest różnica...

    Freddie Chopin napisał:
    Exactly - czy cały (rozbudowany) program napisany w assemblerze może być lepszy niż napisany w C?

    Ja wiem ze nie może, ale wstawki bardzo lubię pisać. Najczęsciej w miejscach, gdzie dysponuję informacjami o danym algorytmie takimi, ktorych kompilator się nigdy nie domyśli.

    Freddie Chopin napisał:
    o właśnie - w ilu procentach przypadków warto poprawiać kompilator i jaki z tego zysk?

    W niewielu. Ale jak już faktycznie warto, to zysk jest spory, na jednej funkcji zamiast np. 16x LDRB i 16x ORR 8bit , mam 4xLDR, 4x ORR 32bit, 2x ORR 16bit, 2x ORR 8bit . W szczególności różnica między 16x LDRB a 4xLDR jest znacząca gdy w systemie pracuje DMA, bo AHB ma do wykonania mniej transakcji; o dostępie do EXTI już nie wspominając. Dodatkowo cała funkcja wykonuje się szybciej...

    Oczywiście można to męczyć w C, ręcznie rzutować na u32* czy inne szopki robić, ale po co ;]