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

Raspberry pi 3 A+ bare metal - mini uart

_lazor_ 02 Gru 2018 21:30 2427 11
  • Raspberry pi 3 A+ bare metal - mini uart

    1. Wstęp

    Raspbbery Pi jako platforma edukacyjna dla linuksa okazała się wielkim sukcesem . Dalszy rozwój platformy zaowocował zastosowaniem rdzeni cortex-A53 o architekturze 64bit oraz 4 rdzeniach. Zachęcam jak najbardziej do używania linuksa i jego nauki. Z drugiej strony czy jest możliwe programowanie maliny, niczym mikrokontrolera bez systemu operacyjnego?
    Oczywiście, że jest to możliwe, chociaż jest to trochę bardziej złożone, gdyż sercem maliny nie jest cortex-A, tylko VC (VideoCore) od którego wszystko się zaczyna.

    2. Proces bootup'u

    Na początku wstaje VC, który uruchamia pierwszy bootloader zawarty w pamięci nieulotnej samego VC. Jego zadaniem jest skonfigurować układ aby mógł odczytać kolejny bootloader: bootcode.bin. Ten kawałek kodu zostaje przekopiowany do pamięci L2 i uruchomiony przez VC. Kontynuuje konfigurację (konfiguracja SDRAM) i wczytuje trzeci już bootloader: start.elf. Zostaje zaczytany plik konfiguracyjny config.txt, który jest substytutem BIOS, zostają uruchomione rdzenie cortex-A oraz kernel linuksa zostaje skopiowany do pamięci SDRAM. Kernel linuksa zaczyna być wykonywany przez rdzenie cortex-A53. Piszę tutaj o kernelu linuksa a artykuł ma być na temat bare metal na raspberry Pi 3 A+, tak więc gdzie ten bare metal?
    Już odpowiadam. Podmienimy plik kernel7.img naszym własnym kodem.

    Więcej o pliku config.txt można przeczytać tutaj:
    https://elinux.org/RPiconfig

    Oczywiście można również zmodyfikować sam bootcode.bin aby wyświetlić informacje z procesu bootup’u na mini UART:

    https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/README.md

    Raspberry pi 3 A+ bare metal - mini uart

    3. Narzędzia

    Zanim przejdziemy do pisania kodu, musimy uzbroić się w odpowiednie narzędzia:

    - Kompilator dla architektury AArch64:
    https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads




    lub
    https://www.linaro.org/downloads/

    - Emulator terminala (na przykład Termite)
    - cygwin (z make), mingw lub inny substytut make na windows (nie dotyczy linuksa)
    - Konwerter UART/USB
    - quemu

    4. Podłączenie konwertera USB/UART

    GND konwertera do pinu 6 (GND)
    RXD konwertera do pinu 8 (GPIO14 – TXD0)
    TXD konwertera do pinu 10 (GPIO15 – RXD0)

    Raspberry pi 3 A+ bare metal - mini uart

    5. startup.S

    start.S

    Kod: S
    Zaloguj się, aby zobaczyć kod


    W przeciwieństwie do cortex-M, cortex-A nie startuje z predefiniowanej sekwencji, a po inicjalizacji przez GPU od razu zaczyna wykonywać kod. Warto zwrócić uwagę na to, że wszystkie 4 rdzenie startują jednocześnie i w aktualnym przykładzie nie wszystkie nam będą potrzebne, dlatego zatrzymujemy je, wchodząc w nieskończoną pętle. Kolejną różnica między cortex-M a cortex-A jest adres stosu. W tym przypadku musimy go samodzielnie ustawić.
    Jako, że kernel linuksa zostaje skopiowany do pamięci SRAM, nie mamy potrzeby samodzielnego przenoszenia sekcji .data do RAM, gdyż robi to za nas bootloader. Nadal jednak mamy sekcję .bss, którą należy wyzerować.

    6. skrypt linkera

    link.ld
    Kod: ld
    Zaloguj się, aby zobaczyć kod


    Skrypt linkera rozpoczyna wrzucanie kodu pod adres 0x8000 wynikający z konwencji kernela linuksa. W naszym wypadku nie jest wymagane, ale jako że raspberry pi jest tworem dedykowanym dla linuksa, warto się jej trzymać:
    http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html

    Ważne by sekcja .text.boot była pierwszą sekcją pod adresem 0x8000 oraz aby nie została zoptymalizowana przez AS z powodu braku referencji do tej sekcji, aby temu zapobiec używamy KEEP().
    Sekcja .data nie wymaga przenoszenia, gdyż robi to za nas bootloader.

    7. main

    main.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    W naszym main nie dzieje się za wiele. Najpierw inicjalizujemy mini uart, piszemy słowo „Hello” i wchodzimy w nieskończoną pętle, która będzie odsyłała każdy znak jaki prześlemy po mini uart.

    8. Obsługa mini uart

    uart.h
    Kod: h
    Zaloguj się, aby zobaczyć kod


    uart.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Bez dokumentacji tym razem się już nie obejdzie. Niestety dokumentacja jest dość skromna i zawiera bardzo wiele błędów to można z niej wygrzebać interesujące nas informacje. Jedno ostrzeżenie, broadcom nie podołał jakże trudnemu zadaniu zmiany rysunków i tyczą się one SoC BCM2835, chociaż tekście są już poprawne adresy.
    https://github.com/raspberrypi/documentation/files/1888662/

    Co nas interesuje? Adres pod którym zaczynają się rejestry peryferiów:
    „Physical addresses range from 0x3F000000 to 0x3FFFFFFF for peripherals.”

    Najstarszy bajt się nie zmienia, więc zdefiniujmy go jako:
    #define MMIO_BASE 0x3F000000

    Dzięki temu pozostałe adresy będą pozbawione ciągle powtarzającego się wspólnego początku.
    W rozdziale 2.2.1 mamy opis działania mini uart. Chociaż w dokumentacji mamy adres 0x7E21 5040, ale odnosi się do video core CPU Bus, ale poprzez VC/ARM MMU (memory menagment unit) jest zmapowany jako adres fizyczny ARM 0x3F21 5040.
    Reszta kodu jest już bardzo łatwa do analizy i pozostawiam ją Tobie, jako forma ćwiczenia.

    9. Makefile, qemu i termite

    Kod: makefile
    Zaloguj się, aby zobaczyć kod


    Tak jak i w poprzednim przykładzie dla cortex-M:

    https://www.elektroda.pl/rtvforum/viewtopic.php?p=17597051#17597051

    Budujemy nasz kod bez użycia standardowych bibliotek. Nowym elementem jest nowa opcja run. Ta opcja uruchamia emulator qemu, dzięki któremu możemy testować nasz kod bez ciągłego uciążliwego przekładania karty SD.
    Po zainstalowaniu qemu i dodaniu go zmiennej środowiskowej PATH możemy wywołać opcję run i przetestować działanie

    Raspberry pi 3 A+ bare metal - mini uart

    Aby uruchomić nasz program na malinie musimy przygotować naszą kartę SD według polecenia raspberry pi fundation:
    https://www.raspberrypi.org/documentation/installation/sdxc_formatting.md
    Następnie kopiujemy na kartę następujące elementy:
    - bootcode.bin
    - fixup.dat
    - start.elf
    - kernel8.img

    Pierwsze trzy są dostępne tutaj:
    https://github.com/raspberrypi/firmware/tree/master/boot
    a kernel8.img jest wynikiem kompilacji naszego projektu. Uruchamiamy termite i konfigurujemy go jak na obrazku (com7 będzie mieć inną wartość):

    Raspberry pi 3 A+ bare metal - mini uart

    Wsuwamy kartę SD do maliny podpinamy konwerter USB/UART i zasilamy układ. Naszym oczom powinien się pokazać tekst wysłany z maliny:

    Raspberry pi 3 A+ bare metal - mini uart

    10. podsumowanie

    Pisanie kodu bare metal na raspberry pi jest możliwe i otwiera bardzo wiele możliwości, to niestety sama platforma nie jest przyjazna do tego typu pracy. Jednocześnie jest to stosunkowo tania i popularna platforma by zaznajomić się z rdzeniami cortex-A, które są znacznie bardziej złożone od cortex-M.
    Jeśli jednak chcemy zapoznać się w programowaniu układów 64bit, zbudować własny bardziej zaawansowany system operacyjny, potrzeba nam większej mocy obliczeniowej, zacząć zabawę z układami wielordzeniowymi, zapoznać się z cortex-A czy wszystko jednocześnie to myślę że jest to układ dla Ciebie.
    W sieci jest wiele dostępnych tutoriali, które pozwolą na lepszym zapoznaniu się z platformą niż mój dość skromny artykuł, który ma tylko zwrócić uwagę na to że tego typu programowanie jest możliwe na raspberry pi i nie jest to żaden „rocket science”.


    Linki warte uwagi:

    https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/README.md

    http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

    https://wiki.beyondlogic.org/index.php?title=Understanding_RaspberryPi_Boot_Process

    https://github.com/bztsrc/raspi3-tutorial

    https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/

    https://github.com/s-matyukevich/raspberry-pi-os


    Fajne! Ranking DIY
  • CControls
  • #3 04 Gru 2018 10:22
    _lazor_
    Moderator Projektowanie

    Myślę, że raspberry pi 3 A+ nie będzie miała gorszych osiągów niż jej poprzedniczki a znalazłem w sieci taki benchmark:
    http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/

    Wynika z tego, że można osiągnąć do 22Mhz z jeszcze jako takim kształtem prostokąta.

  • #4 07 Gru 2018 20:44
    stmx
    Poziom 16  

    Szczerze powiedziawszy szkoda zawracać sobie cztery litery taką metodą tworzenia bare metal kodu na RPI.

    Jedyną realną (czyli nie powodującą ataków furii spowodowanych przekładaniem kart SD) jest zastosowanie J-TAG-a. jak to zrobić - w sumie prosto - trzeba tylko aby kernel.img przestawił odpowiednie GPIO w odpowiedni tryb ALT.

    Ma to następujące zalety: \
    - programujesz i debugujesz programy używając swojego ulubionego debuggera / IDE, bez przekładania kart SD.
    - możesz debugować kernel-a linuxa z poziomu J-TAG-a (oczywiście proces włączenia obsługi J-TAG będzie inny. Jak przydatne jest to, to chyba potwierdzi każdy, kto coś tam grzebie w kernelu.

    Nie będę tu podawać jak, ani generalnie nawet linkować żadnych stron bo:
    Primo: jak ktoś nie wie o co chodzi to i tak tego nie zrobi
    Secundo: google jest bezpłatne


    Szczerze powiedziawszy gdybym mógł minusować, to bym zminusował ten artykuł. Spodziewałem się czegoś więcej po Kol. @_lazor_ . Już choćby napisania UART bootloadera w tym naszym nieszczęsnym pliku kernel.img aby załadował naszą bare metal aplikację do pamięci bez wachlowania kartami. Wtedy by to miało jakiś sens.

  • CControls
  • #5 07 Gru 2018 21:12
    _lazor_
    Moderator Projektowanie

    W sumie dobra uwaga, jeśli można się dobrać do jtag to już można trochę poszaleć. A samo uruchomienie debugowania dla więcej niż jednego core może być cennym doświadczeniem.

    Jednak warto pamiętać, że oprócz ARMów jest tak VideoCore, na którego nie mamy i tak dużego wpływu.

    Ten artykuł ma raczej pokazać, że większe procesory również nie są czarną magią i może kogoś to zachęci do pogłębiania swojej wiedzy, chociaż nie jest to trywialne zagadnienie.

  • #6 07 Gru 2018 21:37
    stmx
    Poziom 16  

    _lazor_ napisał:
    Jednak warto pamiętać, że oprócz ARMów jest tak VideoCore, na którego nie mamy i tak dużego wpływu.
    Mamy taki jaki chcemy - Broadcom ze 4 lata temu udostępnił dokumentację + jakieś tam źródła stosu graficznego. Przyznam szczerze, że nie zajmuję się programowaniem grafiki - to mnie to średnio interesowało. Ale są jakieś tam nawet backendy do gcc llvm, dostępny makroasembler - więc wpływ masz jaki tylko chcesz :).

    Programowanie RPI bare metal jest ciekawostką generalnie (raczej tego nikt nie robi bo i po co), ale sprzętowe debugowanie przy pisaniu np kernel driverów jest nieocenioną pomocą.

    _lazor_ napisał:
    A samo uruchomienie debugowania dla więcej niż jednego core może być cennym doświadczeniem.
    Jeżeli ktoś dojdzie to momentu kiedy wejdzie w multicore debugging to raczej nie będzie miał problemu z opanowaniem tematu. Zresztą do bare metal lepiej sbie sprawić jakaś płytkę developerską z multicore mikrokontorlerem i tam się bawić.

  • #7 07 Gru 2018 21:54
    _lazor_
    Moderator Projektowanie

    Płytki developerskie są stosunkowo drogie, ale są faktycznie znacznie ciekawsze od raspberry pi. Popatrzmy na takiego beaglebone-x15:

    Cytat:

    Processor: TI AM5728 2×1.5-GHz ARM® Cortex-A15
    2GB DDR3 RAM
    4GB 8-bit eMMC on-board flash storage
    2D/3D graphics and video accelerators (GPUs)
    2×700-MHz C66 digital signal processors (DSPs)
    2×ARM Cortex-M4 microcontrollers (MCUs)
    4×32-bit programmable real-time units (PRUs)


    Wypas board, ale koszt ponad 1000zł jest dość dyskusyjny jak na zabawy w pojedynkę (inna sprawa, że ciężko w pojedynkę wykorzystać pełen potencjał z tej płytki).

  • #8 07 Gru 2018 22:07
    stmx
    Poziom 16  

    _lazor_ napisał:
    Wypas board, ale koszt ponad 1000zł jest dość dyskusyjny
    Ale to jest płytka z procesorem aplikacyjnym a nie mikrokontrelem multicore takim jak np. LPC43xx. (taką płytkę kupisz za 100zł pewnie) Używanie procesorów aplikacyjnych bez OS-a jest IMO całkowicie bez sensu.

    Zresztą nawet multiucore miktokontrolery tez raczej bez RTOS-a się nie podejdzie (i to takiego gotowego dla multicorem albo z wasnymi dopiskami aby jednak te cory mogły się jakoś ze sobą komunikować).

    Ale ich użycie tez jest już raczej zaawansowaną sprawą - wątpię aby było wiele osób zajmujących się tym tu na elektrodzie.

    Są też zresztą "hybrydy" typu A9/M4 etc. Je też nie programuje się raczej bez OS-a (typu Linux na A9 - RTOS na M4)

  • #9 07 Gru 2018 22:26
    _lazor_
    Moderator Projektowanie

    No cóż mi jest dane pracować przy systemie bare metal z wieloma rdzeniami, więc nie mówię czegoś z kapelusza tylko jak jest u mnie. Oczywiście nie jestem architektem, trochę mi jeszcze wiedzy i doświadczenia brakuje, ale praca przy takim systemie jest bezcenna.

    Inna sprawa, że mi w moim przypadku zależy na naprawdę szybkim zegarze (ponad 1Ghz) z instrukcjami DSP. A jak wiadomo ARM cortex-A ma NEON, którego jak najbardziej chce się nauczyć. To ma być srogie przetwarzanie sygnału. Dlaczego? Bo klepie to w domu i mogę :D
    Na początku chciałem użyć TI delfino, który ma również dwa rdzenie, trochę PRU, tani(board 200zł) oraz jest rdzeniem DSP, ale zegar 200Mhz to nie jest coś co mnie zadowoli.

  • #10 08 Gru 2018 14:39
    stmx
    Poziom 16  

    _lazor_ napisał:
    No cóż mi jest dane pracować przy systemie bare metal z wieloma rdzeniami,
    Pytanie tylko po co. I tak musisz zaimplementować mechanizmy do pracy wielowątkowej. Nie jest to proste, a przede wszystkim trudne w debugowaniu. Lepiej (bez praktycznej straty na wydajności) zastosować coś co ma te mechanizmy gotowe i to tego przetestowane.,

  • #11 08 Gru 2018 15:08
    _lazor_
    Moderator Projektowanie

    Jeśli układ jest customowy (nie jest to coś nadzwyczajnego, że duże firmy dostają zabawki tylko dla siebie) to raczej nie skorzystasz z gotowych rozwiązań.

  • #12 08 Gru 2018 17:44
    stmx
    Poziom 16  

    _lazor_ napisał:
    Jeśli układ jest customowy (nie jest to coś nadzwyczajnego, że duże firmy dostają zabawki tylko dla siebie) to raczej nie skorzystasz z gotowych rozwiązań.
    przyznam ze nie rozumiem. A co przeszkadza w zastosowaniu sprawdzonych rozwiązań? Jak się ma custom chipy to się ma custom porty