Timer Raspberry Pi

We kunnen in Raspbian Linux door middel van gettimeofday(&gettime_now, NULL);start_time = gettime_now.tv_nsec; wel een redelijk nauwkeurige timer maken maar deze timer zal niet altijd nauwkeurig zijn. Alleen de aanroepen van deze functies kost al 100 nanoseconden en kan onderbroken worden door een task switch van de kernel of een kernel proces. Dit gaat ook op voor de functie usleep() die alleen de garantie geeft dat er “minimaal” de slaaptijd gewacht zal worden, maar waar de slaaptijd best wel het tienvoudige kan zijn. Linux is helaas geen realtime besturingssysteem en elke embedded ontwikkelaar wil graag een realtime besturingssysteem om nog enige controle te hebben. Desondanks wordt de Rasberry Pi veel gebruikt in bijvoorbeeld robots waar de enorme voorraad aan programmacode en bibliotheken wel weer een enorm voordeel is.

Een stabiele en nauwkeurige timer is geen standaard onderdeel van de ARM specificatie maar de meeste ARM gebaseerde SoC's hebben ergens wel een timer. De Raspberry Pi is geen uitzondering, het uitlezen van deze timer in Linux vergt wel enig hackwerk. Volgens de officiële Broadcom 2835 documentatie zit er een 'free-running 1MHz timer' op ARM adres 0x20003004 die als we het goed bekijken op I/O base 0x20000000 zit met een offset van 0x3000 en de vrij lopende 1MHz teller op offset 0x0004. Dit klinkt goed maar hoe kunnen we deze teller gebruiken? In het ontwerp van Unix zit een methode om rechtstreeks het fysieke geheugen te lezen, via de device driver “/dev/mem”. Maar hoe kunt u dit gebruiken om de teller te lezen? Volgens de man pagina's geeft dit device de geheugen adressen identiek aan het fysieke geheugen. Wanneer we een klein stuk geheugen rechtstreeks willen benaderen dan kunnen we dit doen met de functie mmap(). Er zit een kleine adder onder het gras en dat is dat de geheugenadressen van de timer alleen leesbaar zijn, er naar toe proberen te schrijven (vanuit user space) zal fatale gevolgen hebben. Omdat dergelijke "raw" toegang tot het geheugen beveiligingsinformatie kan vrijgeven en het systeem wagenwijd open kan zetten is het gebruik van /dev/mem beperkt tot root gebruiker. Hier staat een eenvoudige demonstratie programma dat timing informatie van een lus in microseconden afgedrukt.

Voorbeeld code

#include 
#include  
#include  
#include  
#include  
#include   

#define ST_BASE (0x20003000) 
#define TIMER_OFFSET (4)  

int main(int argc, char *argv[]) {    
long long int t, prev, *timer; // 64 bit timer 
int fd;     
void *st_base;
 
  if (-1 == (fd = open("/dev/mem", O_RDONLY))) {
      fprintf(stderr, "open() failed.\n");
      return -1;     
  }
  if (MAP_FAILED == (st_base = mmap(NULL, 4096,
       PROT_READ, MAP_SHARED, fd, ST_BASE))) {
     fprintf(stderr, "mmap() failed.\n");
     return -2;
   }
   timer = (long long int *)((char *)st_base + TIMER_OFFSET); 
   prev = *timer;
   sleep(1);
   while (1==1) { 
       t = *timer;
       printf("Timer diff = %lld    \r", t – prev);
       prev = t;
       sleep(1);
   } // zal hier nooit komen
   return 0; 
} 

Uitleg code

De eerste stap om toegang te krijgen tot de timer is de open () functie, de mmap() en het instellen van de timer pointer. Wanneer we de TIMER_OFFSET toevoegen aan st_base en deze casten naar een pointer naar "long long int" (64 bits), dan wordt dit een pointer naar de 1 MHz free running timer. Door deze waarde te lezen kunt u eenvoudig lezen hoeveel microseconden verstreken zijn zonder dat dit door aanroepen van functies of kernel processen verstoord kan worden. Het bovenstaande programma is een proof-of-concept voor het lezen van de timer. Het begint met het voor de eerste keer lezen van de timer waarde, 1 seconde slapen en dan de timer weer lezen om te zien hoeveel microseconden nu werkelijk verstreken zijn. slapen voor 1 seconde, dan is het lezen van een andere timer waarde en het afdrukken van het verschil. Op een 600 Mhz Raspbeery Pi is de typische afwijking slechts 1.000.225 microseconden. Al met al een zeer nauwkeurig timer waarmee u bijvoorbeeld afstand bepaling kunt doen door middel van ultrasone sensoren. In elk realtime programma zoals bijvoorbeeld code voor een robot is zeer nauwkeurige timing soms erg belangrijk.

Last update: 02-03-2015
 Binnen dit thema



 Meer thema's


 Lees hier de privacyverklaring van deze site.

Disclaimer.

Hoewel de heer Hein Pragt de informatie beschikbaar op deze pagina met grote zorg samenstelt, sluit de heer Pragt alle aansprakelijkheid uit met betrekking tot de informatie die, in welke vorm dan ook, via zijn site wordt aangeboden. Het opnemen van een afbeelding of verwijzing is uitsluitend bedoeld als een mogelijke bron van informatie voor de bezoeker en mag op generlei wijze als instemming, goedkeuring of afkeuring worden uitgelegd, noch kunnen daaraan rechten worden ontleend. Op de artikelen van de heer Pragt op deze Internetsite rust auteursrecht. Overname van informatie (tekst en afbeeldingen) is uitsluitend toegestaan na voorafgaande schriftelijke toestemming van de rechthebbende. Voor vragen over copyright en het gebruik van de informatie op deze site kunt u contact opnemen met: (email: mail@heinpragt.com). Dit is mijn