MPS E3 - U-Boot


Formål
Formålet med denne øvelse er at erfare hvordan U-Boot er et vigtigt værktøj til debugging af hardware i en typisk embedded Linux platform. Du vil opleve hvordan du med med U-Boot har direkte adgang til processorens rå ressourcer og kan tilgå disse. Dette er i modsætning til senere når vi benytter Linux og den abstraktion som operativ systemet giver over hardwaren.
Forberedelse
Du skal have et funktionelt VM-Ware Image, et Devkit8000 og et USB-serial konverter kabel (med mindre din PC er så gammel at den har en RS-232 port direkte)
Øvelses Steps
U-Boot er udover at være en platform for booting af et operativsystem også et godt værktøj til den første debugging af hardware. Som du vil se i øvelsen kan vi tilgå processorens enheder direkte og afvikle simple testprogrammer direkte fra U-Boot.
Som vi gennemgik i lektionen omkring busser, så har vi i OMAP processoren et stort memory map, indeholdende en masse forskellige enheder og konfigurations registre til disse. Da enhederne er mappet direkte i memory kan disse tilgås direkte på deres fysiske adresse vha U-Boot.
I OMAP3530’s reference manual, kapitel 25, finder vi sektionen omkring GPIO. GPIO (General Purpose Input/Output), er simple pins på processoren som kan konfigureres til hhv in- og output. Hvis pin’en er sat til output, kan vi tilskrive den en værdi og omvendt læse fra den, hvis den er sat op til input.
Til styring af dette har OMAP’en 3 vigtige registre:
§  GPIO_OE – Styring af pin direction (in/out)
§  GPIO_DATAIN – Værdi læst fra pin (’1’ / ’0’)
§  GPIO_DATAOUT – Værdi som skal sættes på pin
Du kan finde mere om disse register i 1.6.2.9-1.6.2.11 i OMAP3530 ref manualen kapitel 25.


Nogle af OMAP’ens GPIO pins er forbundet direkte til lysdioder og knapper på devkit8000.
Det er disse som vi skal lege lidt med i denne øvelse.
Der er 192 GPIO’er på OMAP kredsen. Disse er internt grupperet i 6 forskellige banke af 32-bit hver. Hver GPIO pin på en bank kan således beskrives vha en bit i bankens tilhørende registre. Den følgende figure er taget fra manualen og illustrerer hvordan at de forskellige GPIO porte er mappet ind på de forskellige banke.

Som det ses af figuren føres GPIO[31:0] ind på GPIO bank 1. Skal vi arbejde med GPIO3 skal vi arbejde på bit 3 i bank 1.
Øvelse 1: Brug U-Boot til at tænde/slukke lysdioder på Devkit8000
Hvis man gerne vil læse / skrive til memory i U-Boot, kan man benytte kommandoerne:
md.<address> <no elements to read>
mw.<b/w/l> <address> <value>

Benyt OMAP ref manualen til at finde beskrivelsen af de 3 førnævnte registre. Brug herefter md til at udlæse værdien af de enkelte registre samt mw til at sætte en ønsket værdi. Husk at b = 8-bit, w=16-bit og l=32-bit. Husk at bevare værdierne af de bits som du ikke skal ændre på. Ændrer du på disse, ændrer du på porte som har forbindelser til andre enheder på DevKittet. Dette gøres ved først at læse værdien af registret, og bagefter skrive værdien tilbage incl de ændringer som du har. 
a) Benyt Devkit8000 schematic (findes på devkit8000 wiki’en) til at finde ud hvilke IOs som følgende er forbundet til?
§  USER_KEY
  • GPIO_26
  • OE is located at 0x48310034
  • Is located at 0x48310038
§  SYS_LED3
  • GPIO163
  • OE is located at 0x49058034
  • Is located at 0x4905803c
b) I user manualen (spruf98c) skal du i afsnittet om ”General Purpose I/O Interface”, CH 24 (spuf98v), finde ud af hvilke GPIO banke (1-6) er førnævnte I/Os forbundet til (brug figur 24-4 (spuf98v)):
§  USER_KEY
  • GPIO1 module
§  SYS_LED3
  • GPIO6 module

Når du er nået så langt, ved du hvilken GPIO bank som de forskellige lysdioder er forbundet til. Dette skal du bruge i det følgende hvor du skal tilgå disses data registre direkte. \\ Se afsnittet "General-Purpose Interface Register Manual" i kapitlet, her vil du se en oversigt over alle gpio registrene, vi vil fokusere på de tidligere nævnte ”GPIO_OE”, ”GPIO_DATAIN” og ”GPIO_DATAOUT”. Så fortsæt om til beskrivelsen af disse på de følgende sider. Bemærk hvorledes at der er angivet adresser for de respektive GPIO banke. Dvs. læser du noget læser du noget fra adresse 0x49050000 har du fat i GPIO bank 2, dvs. gpio [63:32], hvor bit 0 afspejler GPIO 32 osv.


c) Verificer om GPIO_OE værdien for hhv. USER_KEY (input) og SYS_LED3 (output) er korrekte og korriger i fald at det ikke er tilfældet (Benyt md.l [address] [length] og mw).

Brug af: md.l md.w md.b



Læser GPIO bank 1, GPIO1_OE (User_Key)

Dvs. alle pins i bank 1 er inputs, hvilket er godt nok!


Læser GPIO bank 6, GPIO6_OE, (SYS_LED3)

Dvs. alle bits er inputs.


Laver GPIO6 om til outputs, der sidder SYS_LED3

Læser inputregisteret for GPIO6, hvor SYS_LED3 sidder

d) Læs GPIO_DIN værdien for USER_KEY’s GPIO bank og verificer om en bit skifter værdi når knappen er trykket ned eller ej.

Bemærk Little endian

e) Skriv til GPIO_DOUT værdien for SYS_LED3 og verificér at lysdioden tænder/slukker.
Styrer outputtet.


Øvelse 2: Skriv et program til at aktivere lysdioderne
Du/I skal nu skrive et C-program som kan udlæse status af USER_KEY og benytte denne til at tænde og slukke for lysdioden SYS_LED3.
Tag udgangspunkt i hello_world.c som findes under /user/stud/source/u-boot/standalone/examples. 
a)     U-Boot skal kompileres før en vi kan lave vore prog
b)    ram: i /home/stud/source/u-boot/ skriver du/I: 
$ make CROSS_COMPILE=arm-angstrom-linux-gnueabi- distclean
$ make CROSS_COMPILE=arm-angstrom-linux-gnueabi- devkit8000_config
$ make CROSS_COMPILE=arm-angstrom-linux-gnueabi-
Alle registre er direkte memory mappede, det vil sige at vi kan tilgå deres fysiske adresse direkte. Skal vi gøre dette direkte i et c-program, skal vi huske tilbage på pointere.
volatile unsigned long *GpioOE_ptr = 0xdeadbeef;     // Oprettelse af pointer til
                                                     // fysisk adresse 0xdeadbeef
unsigned long gpioOE;                                // Oprettelse af variabel til
                                                     // at holde værdi
gpioOE = *GpioOE_ptr;                                // Læsning af værdi fra
                                                     // fysisk adresse.
*gpioOE_ptr = gpioOE;                                // Skrivning til fysisk adresse
b) Benyt en simpel teksteditor (ex kate) til at ændre hello_world.c til at kunne udlæse status af USER_BUTTON og i en efterfølgende iteration benytte værdien af denne til at sætte værdien af SYS_LED3



c) Kompilér programmet. (Du/I skal du/I stå i u-boot folderen og skrive):
/home/stud/source/u-boot/$ make CROSS_COMPILE=arm-angstrom-linux-gnueabi-
Filerne beskrevet i Makefile’en under ./standalone/examples bliver herved bygget med variabler fra u-boot’s make scripts.
d) Overfør programmet til U-Boot på target. Vi benytter Y-Modem protokollen og der den ikke installeret i Ubunto, skriver du/I:
$ sudo apt-get install lrzsz
Vi skal bruge en usb-serial port konverter (samt et null-modem kabel) for at forbinde til devkittet. Du/I skal forbinde null-modem kablet til serial port 0 som er den der sidder umiddelbart under power-afbryderen. USB-serial konverteren plugges i din PC og forbindes in i VMWare. Ved Ubunto prompten kan du/I checke om den er forbundet ind i Linux:
$ ls /dev/ttyU*
Der skulle gerne ligge en fil som hedder ttyUSB0 i device folderen. Vi kommer nærmere ind på hvad det betyder i en senere lektion. Nu skal vi have fat i target, så vi starter en seriel terminal i vores Ubunto miljø, vi benytter i dette tilfælde minicom:
$ sudo apt-get install minicom
$ minicom
Bemærk at minicom har en default terminal og at denne terminal ikke nødvendigvis er det samme som den du/I ønsker. Læs derfor man siderne og find ud af hvilken option der skal bruges for at vælge en specifik terminal.

Når I har startet minicom op, så verificer den serielle opsætning. Den skal gerne ser ud som følgende:
Hardware Flow Control: No
Software Flow Control: No
115200 8N1.
Start Devkit8000 og tryk en taste for at afbryde boot. Ved U-Boot propmten taster du/I:
OMAP3 DevKit8000 # loady 0x80300000
Bemærk at vi loader et program til den adresse i memory, som vi kompilerede programmet til.
Tast ctrl-a og derefter ’z’ for at åbne menu’en i minicom. Tast her ’s’ for ”send”, vælg ”Ymodem” og vælg filen i det rette bibliotek. PgUp / PgDown virker og tryk to gange på mellemrumstasten for at hoppe ind i et bibl. Under /home/stud/source/u-boot/examples/standalone vælges hello_world.bin med mellemrumstasten og sender vha ’enter’.
Når filen er loaded, startes programmet med:
OMAP3 DevKit8000 # go 0x80300000
Eventuelle argumenter skrives efter adressen, præcis som når vi kalder et program i dos/linux.
Nu skulle du/I gerne kunne styre lysdioden præcis som fra prompten.
Hvis duII ikke får jeres funktioner udført, kan det være fordi du/I har tilføjet flere hvilket kan få den konsekvens at main funktionen hello_world() ikke længere ligger præcist på 0x80300000.
Ved skrive:
$ arm-angstrom-linux-gnueabi-nm -n examples/standalone/hello_world
får du/I noget som ligner det her:
80300000 T ledEnable                                                                                                          
8030002c T ledToggle                                                                                                         
80300058 T hello_world                                                                                                        
80300100 T dummy      
... snip ...
Her kan det tydelig ses at hello_world() funktionen ikke længere ligger på 0x80300000, men det gør funktionen ledEnable() derimod. Så faktisk er det kun denne der vil blive udført hvis der skrives go 0x80300000.
Derfor for at få hello_world() funktionen udført skal du/I skrive:
OMAP3 DevKit8000 # go 0x80300058

Ingen kommentarer:

Send en kommentar