BeagleBone Black: Hvordan få Avbryter Gjennom Linux GPIO

BeagleBone Black er en liten 1Ghz ARM-maskin med 512 MB RAM, 2 GB ombord flash-minne, og viktigst to overskrifter hver med to rader med pins kontakter klar for neste integrert prosjekt. På rundt $ 45 i BeagleBone Svart koster rundt det dobbelte av hva en Arduino styret kan sette deg tilbake. For noen prosjekter på 32KB lagringsplass og kilobyte SRAM tilbys av Arduino kan være tilstrekkelig. Hvis du ønsker å bruke 100 MB RAM mens du snakker med annen maskinvare og deretter noe som BeagleBone Svart kan være den perfekte passform.

En tidligere artikkel sett på forskjellene mellom Arduino og BeagleBone svart på hvordan du går om tilgang chips over SPI. Denne gangen vil det være fokus på hvordan du kan få avbrudd fra jern på BeagleBone svart.

De header pinnene på hver side av BeagleBone Svart kan brukes for General Purpose I /O (GPIO). På denne måten kan du sette spenningen til høy eller lav, eller hvis du leser kan du se om spenningen er for tiden høyt eller lavt på pinnen. Vanligvis høy kan være 3,3 volt og lav ville være det felles jordspenningen. Den GPIO støtte i Linux kan eventuelt generere avbryter når signalet øker fra bakken til en høy spenning, fra høy spenning til jord, eller hvis en av disse tilfellene oppstår.

utsett Pins

Som jeg dekket i "Komme i gang med BeagleBone Black" tilgang til de ulike pinnene i overskriftene på venstre og høyre side av BBB er gjort gjennom Linux-kjernen bruker sin GPIO grensesnitt.

under kode eksponerer pin 42 (GPIO_7) gjennom Linux-kjernen og leser den nåværende verdien av at pin. Først må du kartlegge GPIO_7 pinnen inn i filsystemet. Dette gjøres med å gjenta GPIO pinnen inn i eksportfilen. Som du kan se nedenfor, jeg opprettet den nye gpio7 kobling ved hjelp av eksportfilen for å lese at pin

 root @ bbb. /Sys /class /GPIO # echo 7 > /sys /class /GPIO /exportroot @ bbb: /sys /class /GPIO $ ls -lhtotal 0 - w ------- 1 root root 4.0K 1 juni 10:54 exportlrwxrwxrwx 1 root root 0 1 juni 10 : 54 gpio7 - > ../../devices/virtual/gpio/gpio7lrwxrwxrwx 1 root root 0 1 januar 2000 gpiochip0 - > ../../devices/virtual/gpio/gpiochip0lrwxrwxrwx 1 root root 0 1 januar 2000 gpiochip32 - > ../../devices/virtual/gpio/gpiochip32lrwxrwxrwx 1 root root 0 1 januar 2000 gpiochip64 - > ../../devices/virtual/gpio/gpiochip64lrwxrwxrwx 1 root root 0 1 januar 2000 gpiochip96 - > ../../devices/virtual/gpio/gpiochip96--w------- 1 root root 4.0K 1 januar 2000 unexportroot @ bbb: /sys /class /GPIO # cd gpio7root @ bbb: /sys /klasse /GPIO /gpio7 # cat verdien 0 
Generer Avbryter

En veldig enkel måte å generere avbrudd bruker en trykknapp. Jeg koblet den ene siden av knappen til en av de 3.3v utgangene på P9 header og den andre siden gjennom en motstand til pin 42 (GPIO_7). For å kontrollere at knappen jobbet som forventet jeg leste "verdi" filen for å se 0, deretter holdt knappen nede og fikk en 1 mens du holder nede knappen som ble tilbakestilt til 0 igjen etter at jeg ga ut knappen. Hvis jeg var bruker avbryter jeg kunne ha fått en stigende interrupt rett når ble trykket på knappen og en fallende én rett når den ble utgitt

 root @ bbb. /Sys /class /GPIO /gpio7 # cat verdi 0root bbb: /sys /class /GPIO /gpio7 # cat verdi 1root @ bbb: /sys /class /GPIO /gpio7 # cat verdien 0 

Hvis maskinvaren støtter det for en pin du kan slå på avbrudd av ekko ønsket å sette inn i kanten filen, som vist nedenfor. Jeg si hvis maskinvaren din støtter det fordi GPIO i Linux-kjernen kan tillate deg å lese eller skrive til en pinne, men bare visse pins kan settes opp i maskinvare for å tillate avbrudd som skal genereres. For BeagleBone Svart, "I GPIO modus, hver digital I /O kan produsere avbryter"

 root @ bbb: ~ # echo både >. /sys /class /GPIO /gpio7 /kant 
Sett opp Monitoring

Så du ønsker å se "verdi" fil i gpio7 katalogen. Som du så ovenfor, innholdet i den filen ble endret da jeg holdt inne knappen. Men vi absolutt ikke ønsker å fortsette å se filen på en jevnlig basis for å se om du trykker på knappen eller ikke. Først da tenker på fil overvåking jeg tenkte på inotify, som jeg ikke klarer å konfigurere til å gi meg en hendelse når GPIO verdi filen ble oppdatert av et avbrudd. Så da jeg begynte å skrive et C ++ program for å gjøre filen overvåking. For å forenkle koden litt Jeg brukte glib2 biblioteket i stedet for avstemning () eller velge () funksjoner. Den glib2 biblioteket kan brukes uten UI. Bruke glib2 gjort koden enklere og baner vei for grafiske programmer for å få innspill fra custom hardware.

The main () -funksjonen er vist nedenfor. Først gpio7 /verdi er åpnet og deretter en glib2 kanal opprettet for å utløse onButtonEvent funksjon når gpio7 /verdi-fil som en prioritet hendelse. Merk at onButtonEvent skal kalles med en gang fordi det er tilgjengelige data for gpio7 /verdi-fil. Du kan lese mens gpio7 /verdi-fil for å stoppe denne første samtalen til onButtonEvent om det ville gjøre noe uønsket.

 int main (int argc, røye ** argv) {GMainLoop * sløyfe = g_main_loop_new (0, 0 ); int fd = open ("/sys /class /GPIO /gpio7 /verdi", O_RDONLY | O_NONBLOCK); GIOChannel * kanal = g_io_channel_unix_new (fd); GIOCondition dirigent = GIOCondition (G_IO_PRI); guint id = g_io_add_watch (kanal, dirigent, onButtonEvent, 0); g_main_loop_run (loop);} 
Fix interrupt handler Loops

"interrupt handler" er vist nedenfor. Jeg bruker sitater her fordi dette er bare en vanlig C-funksjon, og er ikke bundet av noen spesielle krav som en mikrokontroller avbryte behandleren kan ha. Den ene tingen de onButtonEvent bør gjøre er å sørge for at den nåværende endringen som utløste glib2 kanalen ikke vil utløse nytt når onButtonEvent avkastning. Ellers onButtonEvent vil bli kalt igjen, og hvis det ikke gjør noe tilfelle vil fortsatt stå og onButtonEvent vil bli kalt igjen, og så videre for alltid. Heldigvis er det en melding vises på konsollen når onButtonEvent kalles slik at du kan oppdage og reparere disse avbryte handler looper ganske enkelt.

Filen for glib2 kanalen er hva som forårsaket onButtonEvent å bli kalt. En måte å fjerne hendelsen og tilfredsstille glib2 at vi har håndtert hendelsen er å lese filen på nytt. Fordi filen er fortsatt på slutten av filen offset, må vi søke til begynnelsen, og deretter kan du lese innholdet for å se om du trykker på knappen eller utgitt. Retur ett fra onButtonEvent funksjon betyr at glib2 ikke vil fjerne tilbakeringing

 statisk gbooleanonButtonEvent (GIOChannel * kanal, GIOCondition tilstand, gpointer user_data) {cerr. ≪ < "onButtonEvent" < < endl; GError * error = 0; gsize = 0 bytes_read; g_io_channel_seek_position (kanal, 0, G_SEEK_SET, 0); GIOStatus rc = g_io_channel_read_chars (kanal, BUF, buf_sz - 1 & bytes_read, & error); cerr < < "rc:" < < rc < < "Data:" < < buf < < endl; //Takk, ringe igjen! tilbake 1;} 

Den bygger prosedyre bare bruker en enkel Makefile som vist nedenfor. I utførelsen har jeg trykket på knappen én gang (data: 1) og sluppet den (data: 0). Den innledende lesning skjedde med en gang fordi koden ikke hadde allerede lest den gpio7 /verdi-fil

 $ cat Makefilewatch-knapp-glib. Watch-button-glib.cpp Makefile g ++ watch-button-glib.cpp -o watch-button-glib `pkg-config glib-2.0 --cflags --libs` $ gjøre $ ./watch-button-glibonButtonEventrc:1 data: 0onButtonEventrc: 1 data: 1onButtonEventrc: 1 data: 0 

Hvis du ekko falle i gpio7 /kantfil da onButtonEvent vil bare bli kalt når du slipper knappen.

Bruk på annen maskinvare

Den samme teknikken kan brukes til å få innspill fra hardware som ser mye mer avansert ved første øyekast. For eksempel har Blackberry Trackballer Breakout fire Hall-effektsensorer som oppdager et magnetfelt som en stund ballen ruller. Hver gang en av disse Hall-effektsensorer utløser det sender et avbrudd ned linjen for sin ledelse av ball bevegelse (opp, ned, venstre, høyre). Alt du trenger å gjøre på BeagleBone Black er overvåke 4 GPIO-porter og justere x-aksen og y-aksen variablene som avbryter kommer i. De følgende modifiserte onButtonEvent funksjons oppdateringer x-aksen og y-aksen som ballen beveger seg og viser deg gjeldende verdi hver gang.

 enum {DIRECTION_UP = 1, DIRECTION_DOWN, DIRECTION_LEFT, DIRECTION_RIGHT}; int x-aksen = 0; int y-aksen = 0; statisk gbooleanonButtonEvent (GIOChannel * kanal, GIOCondition tilstand, gpointer user_data) {cerr < < "onButtonEvent" < < endl; int retning = (int) user_data; GError * error = 0; gsize = 0 bytes_read; g_io_channel_seek_position (kanal, 0, G_SEEK_SET, 0); GIOStatus rc = g_io_channel_read_chars (kanal, BUF, buf_sz - 1 & bytes_read, & error); bryteren ((int) user_data) {case DIRECTION_UP: yAkse ++; gå i stykker; case DIRECTION_DOWN: yaxis--; gå i stykker; case DIRECTION_LEFT: xaxis--; gå i stykker; case DIRECTION_RIGHT: xAkse ++; gå i stykker; } Cerr < < "Retning:« < < retning < < "X:" < < x-aksen < < "Y:" < < y-aksen < < endl; //Takk, ringe igjen! tilbake 1;} 

Jeg brukte GPIO pins 70 gjennom 73 inclusive for innspill fra styrekulen. Disse pinner blir overvåket på samme måte som GPIO 7 i det foregående eksempel. Den user_data pekeren brukes når du setter opp onButtonEvent tilbakeringing er en av retnings enum verdier.

Angi tillatelser

Standard tillatelser på de eksporterte GPIO pins, for eksempel /sys /class /GPIO /gpio72 katalog, tillater alle å lese pinnen, men bare rot å skrive til filene. Dette betyr at du må tillate vanlig Linux brukerkonto for å skrive ut til kanten fil eller oppsett avbruddene på GPIO filer ved sshing inn i BeagleBone svart som root. Endre tillatelsene til /sys /class /GPIO /eksport fil til en brukerkonto fortsatt betyr at når en pin eksporteres, vil laget gpioNN katalogen og filene bare være skrivbar for root. Dette synes å være et problem at regler i udev kan løse.

Å få avbrudd fra dine chips er ganske grei å bruke Linux GPIO grensesnittet. Samlingen av programmeringsspråk og biblioteker tilgjengelig på en Linux installasjon kan du velge hvilken metode som skal brukes til å overvåke dine GPIO /verdi filer og svare på avbrudd. Anmeldelser