added a timeout to reading packets from the cape
diff --git a/bbb_cape/src/bbb/bbb.gyp b/bbb_cape/src/bbb/bbb.gyp
index 37f60f4..c954482 100644
--- a/bbb_cape/src/bbb/bbb.gyp
+++ b/bbb_cape/src/bbb/bbb.gyp
@@ -8,45 +8,65 @@
{
'target_name': 'crc',
'type': 'static_library',
+ 'sources': [
+ 'crc.cc',
+ ],
'dependencies': [
'<(AOS)/common/common.gyp:once',
],
+ },
+ {
+ 'target_name': 'byte_reader',
+ 'type': 'static_library',
'sources': [
- 'crc.cc',
+ # 'byte_reader.h',
+ ],
+ 'dependencies': [
+ '<(AOS)/common/common.gyp:time',
+ ],
+ 'export_dependent_settings': [
+ '<(AOS)/common/common.gyp:time',
],
},
{
'target_name': 'uart_reader',
'type': 'static_library',
- 'dependencies': [
- '<(AOS)/build/aos.gyp:logging',
- ],
'sources': [
'uart_reader.cc',
'uart_reader_termios2.c',
],
+ 'dependencies': [
+ '<(AOS)/build/aos.gyp:logging',
+ '<(AOS)/common/common.gyp:time',
+ 'byte_reader',
+ ],
+ 'export_dependent_settings': [
+ '<(AOS)/common/common.gyp:time',
+ 'byte_reader',
+ ],
},
{
'target_name': 'cows_test',
'type': 'executable',
+ 'sources': [
+ 'cows_test.cc',
+ ],
'dependencies': [
'<(EXTERNALS):gtest',
'<(DEPTH)/bbb_cape/src/cape/cape.gyp:cows',
],
- 'sources': [
- 'cows_test.cc',
- ],
},
{
'target_name': 'packet_finder_test',
'type': 'executable',
+ 'sources': [
+ 'packet_finder_test.cc',
+ ],
'dependencies': [
'<(EXTERNALS):gtest',
'packet_finder',
'<(AOS)/common/common.gyp:queue_testutils',
- ],
- 'sources': [
- 'packet_finder_test.cc',
+ '<(AOS)/common/common.gyp:time',
],
},
{
@@ -59,9 +79,13 @@
'<(DEPTH)/bbb_cape/src/cape/cape.gyp:cows',
'<(AOS)/build/aos.gyp:logging',
'crc',
+ '<(AOS)/common/common.gyp:time',
+ 'byte_reader',
],
'export_dependent_settings': [
'<(AOS)/build/aos.gyp:logging',
+ '<(AOS)/common/common.gyp:time',
+ 'byte_reader',
],
},
{
@@ -80,26 +104,27 @@
{
'target_name': 'uart_reader_main',
'type': 'executable',
+ 'sources': [
+ 'uart_reader_main.cc',
+ ],
'dependencies': [
'uart_reader',
'<(AOS)/build/aos.gyp:logging',
'<(AOS)/atom_code/atom_code.gyp:init',
'packet_finder',
'data_struct',
- ],
- 'sources': [
- 'uart_reader_main.cc',
+ '<(AOS)/common/common.gyp:time',
],
},
{
'target_name': 'gpios',
'type': 'static_library',
- 'dependencies': [
- '<(AOS)/build/aos.gyp:logging',
- ],
'sources': [
'gpios.cc',
],
+ 'dependencies': [
+ '<(AOS)/build/aos.gyp:logging',
+ ],
},
],
}
diff --git a/bbb_cape/src/bbb/byte_reader.h b/bbb_cape/src/bbb/byte_reader.h
index 8319ccb..7818407 100644
--- a/bbb_cape/src/bbb/byte_reader.h
+++ b/bbb_cape/src/bbb/byte_reader.h
@@ -3,6 +3,8 @@
#include <sys/types.h>
+#include "aos/common/time.h"
+
namespace bbb {
class ByteReader {
@@ -12,8 +14,10 @@
// Implemented by subclasses to provide a data source
// for these algorithms.
- // Returns the number of bytes read or -1 if there is an error in errno.
- virtual ssize_t ReadBytes(AlignedChar *dest, size_t max_bytes) = 0;
+ // Returns the number of bytes read, -1 if there is an error in errno, or -2
+ // if reading takes longer than timeout.
+ virtual ssize_t ReadBytes(AlignedChar *dest, size_t max_bytes,
+ const ::aos::time::Time &timeout) = 0;
};
} // namespace bbb
diff --git a/bbb_cape/src/bbb/packet_finder.cc b/bbb_cape/src/bbb/packet_finder.cc
index a6b108c..447d3a8 100644
--- a/bbb_cape/src/bbb/packet_finder.cc
+++ b/bbb_cape/src/bbb/packet_finder.cc
@@ -2,6 +2,7 @@
#include <errno.h>
#include <inttypes.h>
+#include <stdlib.h>
#include <algorithm>
@@ -9,6 +10,8 @@
#include "bbb_cape/src/cape/cows.h"
#include "bbb/crc.h"
+using ::aos::time::Time;
+
namespace bbb {
PacketFinder::PacketFinder(ByteReader *reader, size_t packet_size)
@@ -24,22 +27,41 @@
delete unstuffed_data_;
}
-// TODO(brians): Figure out why this (sometimes) gets confused right after
-// flashing the cape.
-bool PacketFinder::FindPacket() {
+bool PacketFinder::FindPacket(const ::Time &timeout_time) {
// How many 0 bytes we've found at the front so far.
int zeros_found = 0;
while (true) {
size_t already_read = ::std::max(0, packet_bytes_);
ssize_t new_bytes =
- reader_->ReadBytes(buf_ + already_read, packet_size_ - already_read);
+ reader_->ReadBytes(buf_ + already_read, packet_size_ - already_read,
+ timeout_time - ::Time::Now());
if (new_bytes < 0) {
- LOG(ERROR, "ReadBytes(%p, %zd) failed with %d: %s\n",
- buf_ + already_read, packet_size_ - already_read,
- errno, strerror(errno));
+ if (new_bytes == -1) {
+ LOG(ERROR, "ReadBytes(%p, %zd) failed with %d: %s\n",
+ buf_ + already_read, packet_size_ - already_read, errno,
+ strerror(errno));
+ } else if (new_bytes == -2) {
+ LOG(WARNING, "timed out\n");
+ } else {
+ LOG(WARNING, "bad ByteReader %p returned %zd\n", reader_, new_bytes);
+ }
return false;
}
+ if (!irq_priority_increased_) {
+ // TODO(brians): Do this cleanly.
+ int chrt_result = system(
+ "bash -c 'chrt -r -p 55 $(top -n1 | fgrep irq/89 | cut -d\" \" -f2)'");
+ if (chrt_result == -1) {
+ LOG(FATAL, "system(chrt -r -p 55 the_irq) failed\n");
+ } else if (!WIFEXITED(chrt_result) || WEXITSTATUS(chrt_result) != 0) {
+ LOG(FATAL, "$(chrt -r -p 55 the_irq) failed, return value = %d\n",
+ WEXITSTATUS(chrt_result));
+ }
+
+ irq_priority_increased_ = true;
+ }
+
if (packet_bytes_ == -1) {
for (size_t to_check = already_read; to_check < already_read + new_bytes;
++to_check) {
@@ -92,8 +114,8 @@
return true;
}
-bool PacketFinder::ReadPacket() {
- if (!FindPacket()) return false;
+bool PacketFinder::ReadPacket(const ::Time &timeout_time) {
+ if (!FindPacket(timeout_time)) return false;
if (!ProcessPacket()) {
packet_bytes_ = -1;
diff --git a/bbb_cape/src/bbb/packet_finder.h b/bbb_cape/src/bbb/packet_finder.h
index ae7cb14..b86c0c9 100644
--- a/bbb_cape/src/bbb/packet_finder.h
+++ b/bbb_cape/src/bbb/packet_finder.h
@@ -5,6 +5,7 @@
#include <string.h>
#include "aos/common/logging/logging.h"
+#include "aos/common/time.h"
#include "bbb/byte_reader.h"
@@ -17,8 +18,11 @@
explicit PacketFinder(ByteReader *reader, size_t packet_size);
~PacketFinder();
- // Returns true if it succeeds or false if it gets an I/O error first.
- bool ReadPacket();
+ // Returns true if it succeeds or false if it gets an I/O error (or timeout)
+ // first.
+ // timeout_time is when this method should give up trying to read a packet and
+ // return false.
+ bool ReadPacket(const ::aos::time::Time &timeout_time);
// Gets a reference to the received packet.
// The most recent call to ReadPacket() must have returned true or the data
@@ -37,7 +41,7 @@
// Reads bytes until there are 4 zeros and then fills up buf_.
// Returns true if it finds one or false if it gets an I/O error first or the
// packet is invalid in some way.
- bool FindPacket();
+ bool FindPacket(const ::aos::time::Time &timeout_time);
// Processes a packet currently in buf_ and leaves the result in
// unstuffed_data_.
@@ -54,6 +58,9 @@
// How many bytes of the packet we've read in (or -1 if we don't know where
// the packet is).
int packet_bytes_ = -1;
+
+ // Whether we've increased the priority of the IRQ yet.
+ bool irq_priority_increased_ = false;
};
} // namespace bbb
diff --git a/bbb_cape/src/bbb/packet_finder_test.cc b/bbb_cape/src/bbb/packet_finder_test.cc
index e2e820a..437bf8d 100644
--- a/bbb_cape/src/bbb/packet_finder_test.cc
+++ b/bbb_cape/src/bbb/packet_finder_test.cc
@@ -3,6 +3,7 @@
#include "gtest/gtest.h"
#include "aos/common/queue_testutils.h"
+#include "aos/common/time.h"
#include "bbb/byte_reader.h"
@@ -21,7 +22,9 @@
TestByteReader(const void *data, size_t data_size)
: data_(data), data_size_(data_size), bytes_left_(data_size) {}
- virtual ssize_t ReadBytes(AlignedChar *dest, size_t max_bytes) {
+ virtual ssize_t ReadBytes(AlignedChar *dest, size_t max_bytes,
+ const ::aos::time::Time &/*timeout_time*/)
+ override {
size_t to_transfer = ::std::min(max_bytes, bytes_left_);
memcpy(dest, static_cast<const uint8_t *>(data_) + data_size_ - bytes_left_,
to_transfer);
@@ -115,7 +118,7 @@
};
TestByteReader reader(kTestData, sizeof(kTestData));
PacketFinder packet_finder(&reader, 144);
- EXPECT_TRUE(packet_finder.ReadPacket());
+ EXPECT_TRUE(packet_finder.ReadPacket(::aos::time::Time(0, 0)));
}
} // namespace testing
diff --git a/bbb_cape/src/bbb/uart_reader.cc b/bbb_cape/src/bbb/uart_reader.cc
index 6d65330..f4ebaca 100644
--- a/bbb_cape/src/bbb/uart_reader.cc
+++ b/bbb_cape/src/bbb/uart_reader.cc
@@ -32,10 +32,10 @@
} // extern "C"
UartReader::UartReader(int32_t baud_rate)
- : fd_(open(device, O_RDWR | O_NOCTTY)) {
+ : fd_(open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)) {
if (fd_ < 0) {
- LOG(FATAL, "open(%s, O_RDWR | O_NOCTTY) failed with %d: %s."
+ LOG(FATAL, "open(%s, O_RDWR | O_NOCTTY | O_NOBLOCK) failed with %d: %s."
" Did you read my note in bbb/uart_reader.cc?\n",
device, errno, strerror(errno));
}
@@ -44,14 +44,30 @@
LOG(FATAL, "aos_uart_reader_set_tty_options(%d) failed with %d: %s\n",
fd_, errno, strerror(errno));
}
+
+ FD_ZERO(&fd_set_);
+ FD_SET(fd_, &fd_set_);
}
UartReader::~UartReader() {
if (fd_ > 0) close(fd_);
}
-ssize_t UartReader::ReadBytes(AlignedChar *dest, size_t max_bytes) {
+ssize_t UartReader::ReadBytes(AlignedChar *dest, size_t max_bytes,
+ const ::aos::time::Time &timeout) {
do {
+ struct timeval timeout_timeval = timeout.ToTimeval();
+ switch (select(fd_ + 1, &fd_set_, NULL, NULL, &timeout_timeval)) {
+ case 0:
+ return -2;
+ case -1:
+ continue;
+ case 1:
+ break;
+ default:
+ LOG(WARNING, "unknown select return value\n");
+ return -1;
+ }
ssize_t r = read(fd_, dest, max_bytes);
if (r != -1) return r;
} while (errno == EINTR);
diff --git a/bbb_cape/src/bbb/uart_reader.h b/bbb_cape/src/bbb/uart_reader.h
index f87af1b..2d038ea 100644
--- a/bbb_cape/src/bbb/uart_reader.h
+++ b/bbb_cape/src/bbb/uart_reader.h
@@ -3,6 +3,9 @@
#include <stdint.h>
#include <string.h>
+#include <sys/select.h>
+
+#include "aos/common/time.h"
#include "bbb/byte_reader.h"
@@ -13,10 +16,13 @@
UartReader(int32_t baud_rate);
virtual ~UartReader();
- virtual ssize_t ReadBytes(AlignedChar *dest, size_t max_bytes);
+ virtual ssize_t ReadBytes(AlignedChar *dest, size_t max_bytes,
+ const ::aos::time::Time &timeout) override;
private:
const int fd_;
+ // Gets initialized to only contain fd_.
+ fd_set fd_set_;
};
} // namespace bbb
diff --git a/bbb_cape/src/bbb/uart_reader_main.cc b/bbb_cape/src/bbb/uart_reader_main.cc
index 2196e81..46c8a8e 100644
--- a/bbb_cape/src/bbb/uart_reader_main.cc
+++ b/bbb_cape/src/bbb/uart_reader_main.cc
@@ -1,9 +1,9 @@
#include <stdint.h>
#include <inttypes.h>
-#include <stdlib.h>
#include "aos/atom_code/init.h"
#include "aos/common/logging/logging_impl.h"
+#include "aos/common/time.h"
#include "bbb/uart_reader.h"
#include "bbb/packet_finder.h"
@@ -14,19 +14,10 @@
::bbb::UartReader reader(750000);
::bbb::PacketFinder receiver(&reader, DATA_STRUCT_SEND_SIZE - 4);
- receiver.ReadPacket();
- // TODO(brians): Do this cleanly.
- int chrt_result = system(
- "bash -c 'chrt -r -p 55 $(top -n1 | fgrep irq/89 | cut -d\" \" -f2)'");
- if (chrt_result == -1) {
- LOG(FATAL, "system(chrt -r -p 55 the_irq) failed\n");
- } else if (!WIFEXITED(chrt_result) || WEXITSTATUS(chrt_result) != 0) {
- LOG(FATAL, "$(chrt -r -p 55 the_irq) failed, return value = %d\n",
- WEXITSTATUS(chrt_result));
- }
while (true) {
- if (!receiver.ReadPacket()) {
+ if (!receiver.ReadPacket(::aos::time::Time::Now() +
+ ::aos::time::Time::InSeconds(1.5))) {
LOG(WARNING, "Could not read a packet.\n");
continue;
}