mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-22 11:44:53 +08:00
Implement MillisecondTimer in the unix read() and write() functions.
This commit is contained in:
parent
16a024691b
commit
6747711632
120
src/impl/unix.cc
120
src/impl/unix.cc
@ -96,6 +96,14 @@ MillisecondTimer::now ()
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timespec
|
||||||
|
timespec_from_ms (const uint32_t millis)
|
||||||
|
{
|
||||||
|
timespec time;
|
||||||
|
time.tv_sec = millis / 1e3;
|
||||||
|
time.tv_nsec = (millis % (int)1e3) * 1e6;
|
||||||
|
}
|
||||||
|
|
||||||
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
|
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
|
||||||
bytesize_t bytesize,
|
bytesize_t bytesize,
|
||||||
parity_t parity, stopbits_t stopbits,
|
parity_t parity, stopbits_t stopbits,
|
||||||
@ -455,59 +463,29 @@ Serial::SerialImpl::read (uint8_t *buf, size_t size)
|
|||||||
}
|
}
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
// Setup the total_timeout timeval
|
|
||||||
// This timeout is maximum time before a timeout after read is called
|
|
||||||
struct timeval total_timeout;
|
|
||||||
// Calculate total timeout in milliseconds t_c + (t_m * N)
|
// Calculate total timeout in milliseconds t_c + (t_m * N)
|
||||||
long total_timeout_ms = timeout_.read_timeout_constant;
|
long total_timeout_ms = timeout_.read_timeout_constant;
|
||||||
total_timeout_ms += timeout_.read_timeout_multiplier*static_cast<long>(size);
|
total_timeout_ms += timeout_.read_timeout_multiplier*static_cast<long>(size);
|
||||||
total_timeout.tv_sec = total_timeout_ms / 1000;
|
MillisecondTimer total_timeout(total_timeout_ms);
|
||||||
total_timeout.tv_usec = static_cast<int>(total_timeout_ms % 1000);
|
|
||||||
total_timeout.tv_usec *= 1000; // To convert to micro seconds
|
|
||||||
// Setup the inter byte timeout
|
|
||||||
struct timeval inter_byte_timeout;
|
|
||||||
inter_byte_timeout.tv_sec = timeout_.inter_byte_timeout / 1000;
|
|
||||||
inter_byte_timeout.tv_usec =
|
|
||||||
static_cast<int> (timeout_.inter_byte_timeout % 1000);
|
|
||||||
inter_byte_timeout.tv_usec *= 1000; // To convert to micro seconds
|
|
||||||
while (bytes_read < size) {
|
while (bytes_read < size) {
|
||||||
// Setup the select timeout timeval
|
// Timeout for the next select is whichever is less of the total read
|
||||||
struct timeval timeout;
|
// timeout and the inter-byte timeout.
|
||||||
// If the total_timeout is less than the inter_byte_timeout
|
timespec timeout;
|
||||||
if (total_timeout.tv_sec < inter_byte_timeout.tv_sec
|
try {
|
||||||
|| (total_timeout.tv_sec == inter_byte_timeout.tv_sec
|
timeout = timespec_from_ms(std::min(total_timeout.remaining(),
|
||||||
&& total_timeout.tv_usec < inter_byte_timeout.tv_sec))
|
timeout_.inter_byte_timeout));
|
||||||
{
|
} catch (TimerExpiredException) {
|
||||||
// Then set the select timeout to use the total time
|
break;
|
||||||
timeout = total_timeout;
|
|
||||||
} else {
|
|
||||||
// Else set the select timeout to use the inter byte time
|
|
||||||
timeout = inter_byte_timeout;
|
|
||||||
}
|
|
||||||
FD_ZERO (&readfds);
|
|
||||||
FD_SET (fd_, &readfds);
|
|
||||||
// Begin timing select
|
|
||||||
struct timespec start, end;
|
|
||||||
get_time_now (start);
|
|
||||||
// Call select to block for serial data or a timeout
|
|
||||||
int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout);
|
|
||||||
// Calculate difference and update the structure
|
|
||||||
get_time_now (end);
|
|
||||||
// Calculate the time select took
|
|
||||||
struct timespec diff;
|
|
||||||
diff_timespec (start, end, diff);
|
|
||||||
// Update the timeout
|
|
||||||
if (total_timeout.tv_sec <= diff.tv_sec) {
|
|
||||||
total_timeout.tv_sec = 0;
|
|
||||||
} else {
|
|
||||||
total_timeout.tv_sec -= diff.tv_sec;
|
|
||||||
}
|
|
||||||
if (total_timeout.tv_usec <= (diff.tv_nsec / 1000)) {
|
|
||||||
total_timeout.tv_usec = 0;
|
|
||||||
} else {
|
|
||||||
total_timeout.tv_usec -= (diff.tv_nsec / 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FD_ZERO (&readfds);
|
||||||
|
FD_SET (fd_, &readfds);
|
||||||
|
|
||||||
|
// Call select to block for serial data or a timeout
|
||||||
|
int r = pselect (fd_ + 1, &readfds, NULL, NULL, &timeout, NULL);
|
||||||
|
|
||||||
// Figure out what happened by looking at select's response 'r'
|
// Figure out what happened by looking at select's response 'r'
|
||||||
/** Error **/
|
/** Error **/
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -572,41 +550,25 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
|
|||||||
}
|
}
|
||||||
fd_set writefds;
|
fd_set writefds;
|
||||||
size_t bytes_written = 0;
|
size_t bytes_written = 0;
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = timeout_.write_timeout_constant / 1000;
|
// Calculate total timeout in milliseconds t_c + (t_m * N)
|
||||||
timeout.tv_usec = static_cast<int> (timeout_.write_timeout_multiplier % 1000);
|
long total_timeout_ms = timeout_.write_timeout_constant;
|
||||||
timeout.tv_usec *= 1000; // To convert to micro seconds
|
total_timeout_ms += timeout_.write_timeout_multiplier*static_cast<long>(length);
|
||||||
while (bytes_written < length) {
|
MillisecondTimer total_timeout(total_timeout_ms);
|
||||||
|
|
||||||
|
while (bytes_written < length) {
|
||||||
|
timespec timeout;
|
||||||
|
try {
|
||||||
|
timeout = timespec_from_ms(total_timeout.remaining());
|
||||||
|
} catch (TimerExpiredException) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
FD_ZERO (&writefds);
|
FD_ZERO (&writefds);
|
||||||
FD_SET (fd_, &writefds);
|
FD_SET (fd_, &writefds);
|
||||||
// On Linux the timeout struct is updated by select to contain the time
|
|
||||||
// left on the timeout to make looping easier, but on other platforms this
|
|
||||||
// does not occur.
|
|
||||||
#if !defined(__linux__)
|
|
||||||
// Begin timing select
|
|
||||||
struct timespec start, end;
|
|
||||||
get_time_now(start);
|
|
||||||
#endif
|
|
||||||
// Do the select
|
// Do the select
|
||||||
int r = select (fd_ + 1, NULL, &writefds, NULL, &timeout);
|
int r = pselect (fd_ + 1, NULL, &writefds, NULL, &timeout, NULL);
|
||||||
#if !defined(__linux__)
|
|
||||||
// Calculate difference and update the structure
|
|
||||||
get_time_now(end);
|
|
||||||
// Calculate the time select took
|
|
||||||
struct timespec diff;
|
|
||||||
diff_timespec(start, end, diff);
|
|
||||||
// Update the timeout
|
|
||||||
if (timeout.tv_sec <= diff.tv_sec) {
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
} else {
|
|
||||||
timeout.tv_sec -= diff.tv_sec;
|
|
||||||
}
|
|
||||||
if (timeout.tv_usec <= (diff.tv_nsec / 1000)) {
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
} else {
|
|
||||||
timeout.tv_usec -= (diff.tv_nsec / 1000);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Figure out what happened by looking at select's response 'r'
|
// Figure out what happened by looking at select's response 'r'
|
||||||
/** Error **/
|
/** Error **/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user