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;
     }