1
0
mirror of https://github.com/wjwwood/serial.git synced 2026-01-22 19:54:57 +08:00

Potential timing fix for read and write.

Fixes #27
This commit is contained in:
William Woodall 2013-05-22 21:45:20 -07:00
parent 4ed3889979
commit 060634bf91

View File

@ -389,7 +389,8 @@ Serial::SerialImpl::available ()
} }
} }
inline void get_time_now(struct timespec &time) inline void
get_time_now (struct timespec &time)
{ {
# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time # ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock; clock_serv_t cclock;
@ -404,6 +405,19 @@ inline void get_time_now(struct timespec &time)
# endif # endif
} }
inline void
diff_timespec (timespec &start, timespec &end, timespec &result) {
if (start.tv_sec > end.tv_sec) {
throw SerialExecption ("Timetravel, start time later than end time.");
}
result.tv_sec = end.tv_sec - start.tv_sec;
result.tv_nsec = end.tv_nsec - start.tv_nsec;
if (result.tv_nsec < 0) {
result.tv_nsec = 1e9 - result.tv_nsec;
result.tv_sec -= 1;
}
}
size_t size_t
Serial::SerialImpl::read (uint8_t *buf, size_t size) Serial::SerialImpl::read (uint8_t *buf, size_t size)
{ {
@ -452,19 +466,18 @@ Serial::SerialImpl::read (uint8_t *buf, size_t size)
// Calculate difference and update the structure // Calculate difference and update the structure
get_time_now (end); get_time_now (end);
// Calculate the time select took // Calculate the time select took
struct timeval diff; struct timespec diff;
diff.tv_sec = end.tv_sec - start.tv_sec; diff_timespec (start, end, diff);
diff.tv_usec = static_cast<int> ((end.tv_nsec - start.tv_nsec) / 1000);
// Update the timeout // Update the timeout
if (total_timeout.tv_sec <= diff.tv_sec) { if (total_timeout.tv_sec <= diff.tv_sec) {
total_timeout.tv_sec = 0; total_timeout.tv_sec = 0;
} else { } else {
total_timeout.tv_sec -= diff.tv_sec; total_timeout.tv_sec -= diff.tv_sec;
} }
if (total_timeout.tv_usec <= diff.tv_usec) { if (total_timeout.tv_usec <= (diff.tv_nsec / 1000)) {
total_timeout.tv_usec = 0; total_timeout.tv_usec = 0;
} else { } else {
total_timeout.tv_usec -= diff.tv_usec; total_timeout.tv_usec -= (diff.tv_nsec / 1000);
} }
// Figure out what happened by looking at select's response 'r' // Figure out what happened by looking at select's response 'r'
@ -552,19 +565,18 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
// Calculate difference and update the structure // Calculate difference and update the structure
get_time_now(end); get_time_now(end);
// Calculate the time select took // Calculate the time select took
struct timeval diff; struct timespec diff;
diff.tv_sec = end.tv_sec - start.tv_sec; diff_timespec(start, end, diff);
diff.tv_usec = static_cast<int> ((end.tv_nsec - start.tv_nsec) / 1000);
// Update the timeout // Update the timeout
if (timeout.tv_sec <= diff.tv_sec) { if (timeout.tv_sec <= diff.tv_sec) {
timeout.tv_sec = 0; timeout.tv_sec = 0;
} else { } else {
timeout.tv_sec -= diff.tv_sec; timeout.tv_sec -= diff.tv_sec;
} }
if (timeout.tv_usec <= diff.tv_usec) { if (timeout.tv_usec <= (diff.tv_nsec / 1000)) {
timeout.tv_usec = 0; timeout.tv_usec = 0;
} else { } else {
timeout.tv_usec -= diff.tv_usec; timeout.tv_usec -= (diff.tv_nsec / 1000);
} }
#endif #endif