|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Apr 2006
Città: V.E. (na)
Messaggi: 115
|
[c]Temporizzazione ad elevata precisione in linux
ho scritto questo programma che dovrebbe eseguire eseguire delle istruzioni di output
temporizzate in modo preciso. Codice:
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <asm/io.h>
int main(void)
{
int i;
struct timeval now;
struct timeval after;
if (ioperm(0x80,1,1) )
{
perror("ioperm(0x80)");
exit(1);
}
if (ioperm(0x378,1,1) )
{
perror("ioperm(0x378) ");
exit(1);
}
while(1)
{
gettimeofday(&now, NULL);
outb(1,0x378);
usleep (1500);//primo sleep
outb(0,0x378);
usleep (30000);
gettimeofday(&after, NULL);
printf("%d\n",after.tv_usec-now.tv_usec);
}
return 0;
}
Codice:
36218 31586 31864 34117 31589 31577 31749 31569 31572 31586 32310 37199 34089 31578 31574 31571 33305 32306 31591 31570 33859 33916 come posso aumentare la precisione soprattutto del primo usleep, l'altro ha poca importanza ma il primo deve essere preciso al massimo. ho provato anche a eseguire tante istruzioni inb(80) ma il risultato è peggiore. grazie per le risposte |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Credo che il modo migliore sia un'attesa attiva controllando continuamente il tempo, magari intervallata da delle usleep molto piccole per non impallare il sistema (tipo 20 microsecondi).
|
|
|
|
|
|
#3 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
uhm, comunque faccia il multitasking del sistema operativo ci sarà sempre; interessante notare come la maggior parte dei valori sia poco maggiore di 31500, tranne ogni tanto che salta un po' di più; in quei punti evidentemente ci sono dei process switch verso processi che tardano a rilasciare la CPU perché hanno da lavorare. credo che la soluzione migliore sia alzare al massimo la priorità del processo (non so come si faccia su Linux), e poi casomai riabbassarla dopo il primo intervallo, che hai detto che è il più importante.
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Come puoi pretendere una granularità di 500us se lo scheduler viaggia a 1khz?
Il tuo usleep(1500) è decisamente critico, non puoi ottenerlo così. La tecnica da adottare dipende da quanta tolleranza puoi permetterti sui 1500us.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 Ultima modifica di ilsensine : 11-08-2007 alle 22:37. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
e già che ci sei, puoi sostituire l'accesso diretto alle porte di i/o (outb, ecc.) con il driver ppdev.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Mar 2002
Città: Capua (CE)
Messaggi: 317
|
googlando ho trovato una pagina con spunti interessanti:
http://www.pluto.it/files/ildp/HOWTO...ramming-4.html
__________________
Se pensi di sapere, sappi che non sai di non saperlo! Le mie statistiche - "real man uses Duron!" Ho fatto affari con: schumyFast, navale, The_Nameless_One, Sonic80, diamante.picci, Downset88, ilviandante, tecno789 |
|
|
|
|
|
#7 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
mi stavo giusto chiedendo come fosse possibile che quella cosa funzionasse... Linux permette ai programmi user-mode di accedere direttamente alle porte di I/O?
|
|
|
|
|
|
#8 | |
|
Member
Iscritto dal: Apr 2006
Città: V.E. (na)
Messaggi: 115
|
Quote:
ho letto sulla guida di eliano di impostare il processo in soft realtime con sched_setscheduler() per utilizzare nanosleep ma non so come fare. |
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
12 microsecondi è davvero poco...imho ti servirebbe un kernel realtime.
L'unico modo per farlo imho è un'attesa attiva in quel secondo e mezzo... Codice:
do
{
gettimeofday(&after, NULL);
}
while(after.tv_usec - now.tv_usec < 1488);
E' comunque importante, come ti hanno detto, impostare l'applicazione ad una priorità molto alta. |
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Se ti serve:
Codice:
#include <sched.h>
int set_real-time_priority(void)
{
struct sched_param schp;
/*
* set the process to real-time privs
*/
memset(&schp, 0, sizeof(schp));
schp.sched_priority = sched_get_priority_max(SCHED_FIFO);
if (sched_setscheduler(0, SCHED_FIFO, &schp) != 0) {
perror("sched_setscheduler");
return -1;
}
return 0;
}
|
|
|
|
|
|
#11 |
|
Member
Iscritto dal: Apr 2006
Città: V.E. (na)
Messaggi: 115
|
avevo gia provato cosi ma gli effetti sono gli stessi
pero non ho provato ad aumentare la priorita perche non so come si fa. il fatto è per quello che sto facendo e importante che non ci siano impulsi di durata parecchio elevata tipo 1800 . e poi che almeno la media sia di 1500 perche gli impulsi sono sempre piu grandi di 1500 e mai piu piccoli |
|
|
|
|
|
#12 |
|
Member
Iscritto dal: Apr 2006
Città: V.E. (na)
Messaggi: 115
|
aumentando la priorita va leggermente meglio
Codice:
21538 22604 21538 21815 21556 21537 -978447 21546 21537 21834 22585 21523 22257 22056 21541 22360 21532 21516 22425 21555 21523 23637 21538 21519 21574 22909 21817 21526 21537 23236 21549 21535 cos' è il kernel realtime? |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Feb 2002
Città: Modena
Messaggi: 592
|
https://www.rtai.org/
Me l'hanno fatto usare all'università per dei progetti di Controlli Automatici! Ciauz |
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
- busy loop per 1500 us: è la soluzione più semplice (e forse la più efficace, in congiunzione con SCHED_FIFO). La misurazione dell'intervallo dipende però dalla velocità del processore. - utilizzo del driver rtc: unitamente a un kernel realtime e allo scheduler realtime, potresti avvicinarti a tolleranze della decina di us. Come vedi, non è un problema banale.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Ci sarebbe anche il kernel low-latency che magari potrebbe sarti una mano...dipende da che distro hai, ad esempio su ubuntu si può installare da apt.
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
IMHO ci sono anche altri problemi di misura...hai detto che l'importante sono i primi 1500 us, ma te stai misurando i 1500 us + i 20K us...è chiaro che le approssimazioni aumentano.
Fai quindi una misura separata dei due intervalli. |
|
|
|
|
|
#18 | |
|
Member
Iscritto dal: Apr 2006
Città: V.E. (na)
Messaggi: 115
|
Quote:
ma in questo caso lo scheduler non puo interrompere comunque il processo lo stesso . io avevo provato con tanti inb(0x80) che avevano una durata fissa di 2 us devo riprovare con il processo ad alta priorità |
|
|
|
|
|
|
#19 |
|
Member
Iscritto dal: Apr 2006
Città: V.E. (na)
Messaggi: 115
|
il codice è questo
Codice:
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <asm/io.h>
#include <string.h>
#include <sched.h>
int set_real_time_priority(void);
int main(void)
{
int i;
struct timeval now;
struct timeval after;
if (ioperm(0x80,1,1) )
{
perror("ioperm(0x80)");
exit(1);
}
if (ioperm(0x378,1,1) )
{
perror("ioperm(0x378) ");
exit(1);
}
set_real_time_priority();
for(i=0;i<50;i++)
{
gettimeofday(&now, NULL);
outb(1,0x378);
usleep(1480);
gettimeofday(&after, NULL);
printf("%d\n",after.tv_usec-now.tv_usec);
outb(0,0x378);
usleep (20000);
}
return 0;
}
int set_real_time_priority(void)
{
struct sched_param schp;
/*
* set the process to real-time privs
*/
memset(&schp, 0, sizeof(schp));
schp.sched_priority = sched_get_priority_max(SCHED_FIFO);
if (sched_setscheduler(0, SCHED_FIFO, &schp) != 0) {
perror("sched_setscheduler");
return -1;
}
return 0;
}
Codice:
1537 1525 1511 1511 1521 1511 1512 1510 1525 1522 1511 1512 1511 1510 1534 1510 1513 1511 1522 1521 1509 1525 1529 1511 1528 1509 1518 1510 1524 1528 1509 1511 1510 1524 1521 1614 1510 1511 1523 1532 1510 1520 1529 1511 1526 1511 1524 1527 1524 1521 ora ci siamo quasi se con questo busy loop si puo miglorare ancora bene se no mi accontento. |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Già meglio
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 04:10.



















