Newsgroup: it.comp.programmare.win32
Titolo: micro delay su windows con VC

ciao,
ho la seguente esigenza: dovrei fare delle delay di molto sotto al 
millisecondo,
in particolare devo attendere per il tempo di un bit su una seriale a 9600 
bit/s, quindi
diciamo 105 microsecondi... (no, non posso settare due bit di stop, troppo 
comodo...)
se uso le Sleep() mi sogno anche solo di arrivare ad 1ms, figuriamoci sotto,
coi cicli for manco a parlarne... e poi dipende da macchina a macchina, da 
quanti processi girano etc etc.
Suggerimenti su come fare?
A me viene in mente di usare le QueryPerformanceFrequency() e 
QueryPerformanceCounter()
ma devo fare un bel po' di conti... magari c'e' un sistema piu' semplice...
Ah, nota: lo so che il tempo non e' sempre garantito, ma sempre meglio che 
aspettare SEMPRE 10-20ms!!
grazie e ciao,
GCL 

 QueryPerformanceCounter()
QueryPerformanceCounter (con tutti i problemi di coerenza che possono 
esistere a seconda della piattaforma hardware su cui gira) è la più precisa 
ma ...
... Windows non è un OS realtime (WinCE lo è ma è un'altra storia) così come 
la maggior parte degli OS in giro. La priority "realtime" usata nei thread 
significa in realtà massima priorità ma non è vero realtime.
Quindi non hai alcuna garanzia che il tuo thread che usa quella API abbia il 
controllo sufficientemente frequentemente da avere la certezza di stare 
*nell'intervallo* di tempo desiderato.
Se hai problematiche hardware, la cosa di gran lunga più semplice è di usare 
un piccolo microcontroller che si smazzi i problemi di realtime (io uso i 
PIC per esempio) e poi questo parla con la rilassatezza necessaria con il 
PC.
Diversamente dovresti scriverti un driver kernel mode per acquisire maggiore 
controllo e anche in questo caso i problemi non sarebbero da poco. Questa 
strada te la sconsiglio assolutamente.
-- 
Raffaele Rialdi
Microsoft .NET MVP 
http://mvp.support.microsoft.com
 -
http://italy.mvps.org
 UGIdotNET - User Group Italiano .NET
http://www.ugidotnet.org
 Weblog: 
http://blogs.ugidotnet.org/raffaele

 comodo...)
Perché non puoi?
-- 
emboliaschizoide.splinder.com

> Perché non puoi?
beh non volevo entrare troppo nei dettagli per non andare off-topic, ma la 
stessa seriale
e'condivisa tra due dispositivi selezionati da un multiplexer hardware,
un dispositivo e' una smartcard conforme allo standard 7816, che richiede 
quindi
due bit di stop, mentre l'altro e' un microcontrollore che funziona con un 
solo bit di stop
(in trasmissione ovviamente, ma quando setto la seriale setto entrambe le 
direzioni in un colpo solo, quindi...).
Morale: se setto 2 bit di stop non ricevo piu' dal microcontrollore (anche 
se ovviamente posso trasmettere)
quindi la mia soluzione sarebbe: setto un solo bit di parita' e nel caso in 
cui da PC parlo
con la smartcard aggiungo un piccolo delay; purtroppo il minimo delay che so 
introdurre e'
circa 100 volte il necessario...
spero di non essere stato troppo sintetico nella spiegazione...
GCL 

 circa 100 volte il necessario...
Se proprio non riesci a fare altrimenti, direi che l'unica soluzione sia
quella che ti ha già consigliato Raffaele Rialdi (escludendo di scrivere un
driver, che mi sembrerebbe eccessivo). Usando i multimedia timer o RDTSC
(che poi è la stessa cosa, credo) e facendo dei busy wait occuperai la CPU
al 100%, ma a parte i momenti in cui lo scheduler ti sospenderà
momentaneamente il task dovresti ottenere ritardi discretamente giusti.
-- 
emboliaschizoide.splinder.com

 wrote in
news:WBAmh.14387$
AA....@tornado.fastwebnet.it
: 

Con Windows non puoi ottenere delay affidabili all'interno di 
un'applicazione. 
Puoi provare a usare busy loops, multimedia timers etc, ma non avrai 
mai la garanzia che il tuo delay sia costante perchè tutto dipende 
dallo scheduler.
O passi a un sistema operativo real-time (CE, come diceva Raffaele, ad 
esempio), usi delle estensioni real-time di XP oppure provi a fare un 
driver (ma anche in quel caso dovrai verificare bene che non ci siano 
altri driver fatti male che mettono in crisi il tuo...).
-- 
Valter Minute
(the reply address of this message is invalid)
(l'indirizzo di reply di questo messaggio non è valido)

O passi a un sistema operativo real-time (CE, come diceva Raffaele, ad
se fosse CE cosa dovrei fare ad esempio?
e' automatico? basta la Sleep?
non vorrei andare off-topic, solo una indicazione...
GCL 

 non vorrei andare off-topic, solo una indicazione...
Non credo sia OT.


 Non credo sia OT.
bene :-) altrimenti adesso mi uccidevano!!
grazie
GCL 

 bene :-) altrimenti adesso mi uccidevano!!
Non ci sono newsgroup in italiano su CE, AFAIK e le API di CE sono 
compatibili con le Win32. Non credo sia così off-topic. 


 rimpiazzato da un evento.
si' ora mi e' chiaro,
per la seriale invece, esiste una WaitOnCommEvent o qualcosa del genere 
vero?
grazie mille!! 

 genere vero?
Sě.
Comunque le chiamate a readfile e writefile bloccano il thread 
chiamante fino a che arrivano i dati (se imposti i timeout 
correttamente), senza occupare CPU.
-- 
Valter Minute
(the reply address of this message is invalid)
(l'indirizzo di reply di questo messaggio non č valido)

 correttamente), senza occupare CPU.
strano, a me la ReadFile rende FALSE se non trova dati ed esce 
immediatamente,
tanto che avevo fatto il famoso loop con la Sleep anche qui...
bye
GCL 

 tanto che avevo fatto il famoso loop con la Sleep anche qui...
Come hai impostato i timeout con SetCommTimeout?
Quanti byte leggi?
Tieni presente che su XP l'I/O seriale può essere asincrono, su CE è 
sempre sincrono.
-- 
Valter Minute
(the reply address of this message is invalid)
(l'indirizzo di reply di questo messaggio non è valido)

 po' di tatto.
gli passo questo post, non essendo mio superiore ci parliamo senza problemi 
:-)
grazie di tutti i consigli!!!
PS: sei mica in zona milano-torino? potrei aver bisogno di una bella 
consulenza aziendale su questi temi...
bye
GCL

 sempre sincrono.
allora: al momento solo la parallela e' stata testata su CE, la seriale per 
il colloquio con la smartcard/FreeScale la sto usando su XP,
ed ero confidente che non variasse, visto che uso le CreateFile,
la funzione per lettura byte e' la seguente
UCHAR rxByte(UCHAR *byte)
{
 int numRxBytes;
 if(!ReadFile(sCommHandle, byte, 1, &numRxBytes, NULL) || (numRxBytes != 1))
    return(FALSE);
 return(TRUE);
} // rxByte()
(francamente ho dei dubbi sulla OR, ma la ha fatta un collega...e va...)
timeouts.ReadIntervalTimeout = 1000;
 timeouts.ReadTotalTimeoutMultiplier = 1;
 timeouts.ReadTotalTimeoutConstant = 0;
GCL

  timeouts.ReadTotalTimeoutConstant = 0;
In questo modo aspetti un millisecondo per ogni carattere (quindi 
1ms) e la read ritorna se per un secondo non riceve caratteri dopo 
averne ricevuto uno. Guarda l'help di SetCommTimeouts e vedrai che 
puoi metterci dei valori un po' più sensati.
Se il collega è anche un tuo superiore... faglielo notare con un 
po' di tatto.
-- 


 bella consulenza aziendale su questi temi...
Nord ovest di Milano.
L'e-mail non è valido, ma basta togliere gli _ per ricostruirlo.


 Nord ovest di Milano.
ti contatto :-)
GCL 

 ti contatto :-)
ok. L'e-mail di questo messaggio, senza _, è valido.
