Messages in this thread | | | Date | Tue, 27 Jul 1999 14:28:14 +0200 | From | Christer Weinigel <> | Subject | Re: Microsecond resolution timers - final word |
| |
Robert Norris wrote: > No. It's not parallel port based (hell, it's not even pc based). Its a custom > bit of hardware that uses three lines on the parallel port, and communicates > using a simple serial-esque protocol. It transfers bytes bit-by-bit, using > an ACK and DATA line. > > Here's an example. I send a bit on the data line, and the device responds > by bringing the ACK line high .. I then have to bring ACK low and send the > next data bit within 20-40 usecs. > > Is gettimeofday accurate enough for this?
If you have to handle this kind of timing my guess is that you ahve to to do a busy wait with the interrupts disabled.
To perform a _short_ busy wait, use the udelay() function, it will sit in a tight loop for the specified number of microseconds.
It probably would be possible to use gettimeofday to wait for a short while but it would be overkill and on a slow computer such as an i486 it would take longer than 20 microseconds anyway.
[BTW, internally the udelay function is just a tight loop doing:
int loops = usecs * loops_per_usec; while (loops--) ;
this is what the BogoMIPS calibration at bootup is for, it figures out what value loops_per_usec should have.]
A code fragment to send one byte of data might look like this:
send_byte(unsigned char data) { int i; int loops; long flags;
/* save the flags and clear the interrupts, interrupt processing would break the tight timing requirements of this loop */ save_flags(flags); cli();
for (i = 0; i < 8; i++) { /* Wait for ACK */ while (!(inb(STATUS_PORT) & ACK)) ;
/* Wait at least 20 microseconds */ udelay(20);
/* output the data and respond to the ACK */ outb(data & 1, DATA_PORT) outb(RESPONSE, CONTROL_PORT);
data = data >> 1; }
restore_flags(); }
There are a few things to be aware of though:
First of all, busy waiting with the interrupts disabled should not be done for too long, it might cause other things relying on fast interrupt response to break. For example a serial port receiving data at 115200 bps will get receiver overruns and drop data when the interrupts are disabled for more than one millisecond.
Never _ever_ wait longer than one jiffy (1/100 seconds on ix86, 1/1000 on an Alpha) because then you'll start losing timer interrupts and the system clock will slow down.
Also, the above code ought to have some kind of counter to abort the transfer if a timeout occurs, since if an ACK is never seen, the machine would hang forever. (Remember that since the interrupts are disabled the jiffies variable won't be advanced and can't be used to determine how long has passed.)
The inner loop waiting for the ACK could be changed to this:
timeout = 1000; /* abort if no ACK seen for a 1000 loops each loop takes at least 1 microsecond */
while (!(inb(STATUS_PORT) & ACK)) { if (--timeout <= 0) goto abort; udelay(1); }
Hope this helps, Christer
-- Christer Weinigel Cendio Systems AB Email: wingel@cendio.se Teknikringen 8 Phone: +46-13-21 46 00 583 30 Linköping Fax: +46-13-21 47 00 Sweden
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |