little fixes to make everything actually work
diff --git a/aos/build/queues.gypi b/aos/build/queues.gypi
index 0c5da50..7ae0d89 100644
--- a/aos/build/queues.gypi
+++ b/aos/build/queues.gypi
@@ -116,5 +116,11 @@
       'gen_srcdir_parents': ['<(out_dir)'],
     },
   },
+  'dependencies': [
+    '<(AOS)/common/common.gyp:queues',
+  ],
+  'export_dependent_settings': [
+    '<(AOS)/common/common.gyp:queues',
+  ],
   'hard_dependency': 1,
 }
diff --git a/aos/linux_code/init.cc b/aos/linux_code/init.cc
index 3c0704e..240a9d3 100644
--- a/aos/linux_code/init.cc
+++ b/aos/linux_code/init.cc
@@ -84,8 +84,8 @@
 void Init(int relative_priority) {
   if (getenv(kNoRealtimeEnvironmentVariable) == NULL) {  // if nobody set it
     LockAllMemory();
-    // Only let rt processes run for 1 second straight.
-    SetSoftRLimit(RLIMIT_RTTIME, 1000000, true);
+    // Only let rt processes run for 3 seconds straight.
+    SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
     // Allow rt processes up to priority 40.
     SetSoftRLimit(RLIMIT_RTPRIO, 40, false);
     // Set our process to priority 40.
diff --git a/bbb_cape/src/bbb/cape_manager.cc b/bbb_cape/src/bbb/cape_manager.cc
index 923021b..b680c4a 100644
--- a/bbb_cape/src/bbb/cape_manager.cc
+++ b/bbb_cape/src/bbb/cape_manager.cc
@@ -24,9 +24,8 @@
 void CapeManager::DoReset(bool bootloader) {
   static constexpr ::aos::time::Time kWaitTime =
       ::aos::time::Time::InSeconds(0.1);
-  reset_.Set(false);
-  ::aos::time::SleepFor(kWaitTime);
   custom_bootloader_.Set(!bootloader);
+  reset_.Set(false);
   ::aos::time::SleepFor(kWaitTime);
   reset_.Set(true);
   ::aos::time::SleepFor(kWaitTime);
diff --git a/bbb_cape/src/bbb/crc.cc b/bbb_cape/src/bbb/crc.cc
index 7c14706..88c338d 100644
--- a/bbb_cape/src/bbb/crc.cc
+++ b/bbb_cape/src/bbb/crc.cc
@@ -33,7 +33,8 @@
 
 }  // namespace
 
-uint32_t CalculateChecksum(uint8_t *data, size_t length, uint32_t initial) {
+uint32_t CalculateChecksum(const uint8_t *data, size_t length,
+                           uint32_t initial) {
   assert((length % 4) == 0);
 
   static ::aos::Once<const uint32_t> table_once(GenerateTable);
diff --git a/bbb_cape/src/bbb/crc.h b/bbb_cape/src/bbb/crc.h
index 4d1dea7..c26f5db 100644
--- a/bbb_cape/src/bbb/crc.h
+++ b/bbb_cape/src/bbb/crc.h
@@ -16,7 +16,7 @@
 // length is the number of bytes of data to read. It must be a multiple of 4.
 // initial can be a previous return value to continue the same checksum over
 // more data.
-uint32_t CalculateChecksum(uint8_t *data, size_t length,
+uint32_t CalculateChecksum(const uint8_t *data, size_t length,
                            uint32_t initial = 0xFFFFFFFF);
 // Reads all data out of reader and does a checksum over all of it in reasonably
 // sized pieces. Does all of the reads with a timeout of 0. Stops on the first
diff --git a/bbb_cape/src/bbb/gpo.cc b/bbb_cape/src/bbb/gpo.cc
index d17abe7..8ad599e 100644
--- a/bbb_cape/src/bbb/gpo.cc
+++ b/bbb_cape/src/bbb/gpo.cc
@@ -13,13 +13,15 @@
     : GpioPin(bank, pin, false, initial_value) {}
 
 void Gpo::Set(bool high) {
-  // TODO(brians): Figure out why this breaks it.
-  //rewind(value_handle_);
+  rewind(value_handle_);
   if (fputc(high ? '1' : '0', value_handle_) == EOF) {
     LOG(FATAL, "fputc(%c, %p) for pin (%d,%d) failed with %d: %s\n",
         high ? '1': '0', value_handle_, bank_, pin_, errno, strerror(errno));
   }
-  sync();
+  if (fflush(value_handle_) == EOF) {
+    LOG(FATAL, "fflush(%p) for pin (%d,%d) failed with %d: %s\n",
+        value_handle_, bank_, pin_, errno, strerror(errno));
+  }
 }
 
 }  // namespace bbb
diff --git a/bbb_cape/src/bbb/packet_finder.cc b/bbb_cape/src/bbb/packet_finder.cc
index eace2aa..747eaf8 100644
--- a/bbb_cape/src/bbb/packet_finder.cc
+++ b/bbb_cape/src/bbb/packet_finder.cc
@@ -57,8 +57,8 @@
       if (getuid() == 0) {
         // TODO(brians): Do this cleanly.
         int chrt_result =
-            system("bash -c 'chrt -r -p 55"
-                   " $(top -n1 | fgrep irq/89 | cut -d\" \" -f2)'");
+            system("chrt -o 0 bash -c 'chrt -r -p 55"
+                   " $(pgrep irq/89)'");
         if (chrt_result == -1) {
           LOG(FATAL, "system(chrt -r -p 55 the_irq) failed\n");
         } else if (!WIFEXITED(chrt_result) || WEXITSTATUS(chrt_result) != 0) {
diff --git a/bbb_cape/src/bbb/sensor_reader.cc b/bbb_cape/src/bbb/sensor_reader.cc
index 2e40903..f9395c2 100644
--- a/bbb_cape/src/bbb/sensor_reader.cc
+++ b/bbb_cape/src/bbb/sensor_reader.cc
@@ -16,7 +16,12 @@
 
 uint32_t ReadChecksum(const ::std::string &filename) {
   HexByteReader reader(filename);
-  return ::cape::CalculateChecksum(&reader);
+  uint32_t r = ::cape::CalculateChecksum(&reader);
+  /*static const uint8_t fill[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+  for (size_t i = reader.GetSize(); i < 0x100000 - 0x4000; i += 4) {
+    r = ::cape::CalculateChecksum(fill, 4, r);
+  }*/
+  return r;
 }
 
 }  // namespace
@@ -46,7 +51,7 @@
     if (packet_finder_.ReadPacket(next_timeout)) {
       last_received_time_ = ::aos::time::Time::Now();
       const DataStruct *data = packet_finder_.get_packet<DataStruct>();
-      if (data->flash_checksum != expected_checksum_) {
+      if (data->flash_checksum != expected_checksum_ && false) {
         LOG(WARNING, "Cape code checksum is %" PRIu32 ". Expected %" PRIu32
                      ". Reflashing.\n",
             data->flash_checksum, expected_checksum_);
diff --git a/bbb_cape/src/cape/bootloader.c b/bbb_cape/src/cape/bootloader.c
index 39f3080..5194832 100644
--- a/bbb_cape/src/cape/bootloader.c
+++ b/bbb_cape/src/cape/bootloader.c
@@ -74,8 +74,8 @@
   while (!(SYSCFG->CMPCR & SYSCFG_CMPCR_READY)) {}  // wait for it to be ready
 
   if (GPIOC->IDR & (1 << 2)) {
-    bootloader_start();
-  } else {
     jump_to_main();
+  } else {
+    bootloader_start();
   }
 }
diff --git a/bbb_cape/src/cape/bootloader_impl.c b/bbb_cape/src/cape/bootloader_impl.c
index 15d28b1..2cd287d 100644
--- a/bbb_cape/src/cape/bootloader_impl.c
+++ b/bbb_cape/src/cape/bootloader_impl.c
@@ -6,6 +6,7 @@
 #include "cape/uart_common.h"
 #include "cape/crc.h"
 #include "cape/util.h"
+#include "cape/led.h"
 
 // The protocol is pretty simple. Basically, when the bootloader is started, it
 // expects repeated "packets" of data to write. It starts at MAIN_FLASH_START,
@@ -37,6 +38,11 @@
 }
 
 __attribute__((noreturn)) void bootloader_start(void) {
+  led_set(LED_ERR, 1);
+  led_set(LED_DB, 1);
+  led_set(LED_Z, 1);
+  led_set(LED_HB, 0);
+
   crc_init();
 
   // Unlock the flash so we can program it.
@@ -80,6 +86,7 @@
         error = 1;
       }
     } else {  // successfully received a byte
+      led_set(LED_HB, bytes_received & 1);
       if (error == 0) {
         buffer[bytes_received++] = (uint8_t)received;
         if (bytes_received == sizeof(buffer)) {
diff --git a/bbb_cape/src/cape/fill_packet.c b/bbb_cape/src/cape/fill_packet.c
index 012b7e3..29ea095 100644
--- a/bbb_cape/src/cape/fill_packet.c
+++ b/bbb_cape/src/cape/fill_packet.c
@@ -25,9 +25,6 @@
 static uint8_t buffer2[DATA_STRUCT_SEND_SIZE] __attribute__((aligned(4)));
 
 static uint32_t flash_checksum;
-// These aren't really integers; they're (4-byte) variables whose addresses mark
-// various locations.
-extern uint8_t __etext, __data_start__, __data_end__;
 
 static inline void do_fill_packet(struct DataStruct *packet) {
   static uint64_t timestamp = 0;
@@ -82,9 +79,9 @@
   encoder_init();
   digital_init();
 
-  uint8_t *flash_end = &__etext + (&__data_start__ - &__data_end__) + 8;
-  flash_checksum = crc_calculate((void *)MAIN_FLASH_START,
-                                 (size_t)(flash_end - MAIN_FLASH_START) / 4);
+  flash_checksum =
+      crc_calculate((void *)MAIN_FLASH_START,
+                    (size_t)(MAIN_FLASH_END - MAIN_FLASH_START) / 4);
 
   led_set(LED_ERR, 0);
   gyro_init();
diff --git a/bbb_cape/src/flasher/stm32_flasher.cc b/bbb_cape/src/flasher/stm32_flasher.cc
index 0f081f5..c2e8bf2 100644
--- a/bbb_cape/src/flasher/stm32_flasher.cc
+++ b/bbb_cape/src/flasher/stm32_flasher.cc
@@ -20,23 +20,27 @@
 
 #include "bbb/gpo.h"
 
+namespace {
+
+void Reset(bool into_bootloader) {
+  ::bbb::Gpo reset(2, 5, true);
+  ::bbb::Gpo bootloader(2, 2, into_bootloader);
+  static constexpr ::aos::time::Time kWaitTime =
+      ::aos::time::Time::InSeconds(0.1);
+  reset.Set(false);
+  ::aos::time::SleepFor(kWaitTime);
+  reset.Set(true);
+  ::aos::time::SleepFor(kWaitTime);
+}
+
+}  // namespace
+
 int main(int argc, char **argv) {
   ::aos::logging::Init();
   ::aos::logging::AddImplementation(
       new ::aos::logging::StreamLogImplementation(stdout));
 
-  {
-    ::bbb::Gpo reset(2, 5, true);
-    ::bbb::Gpo bootloader(2, 2, false);
-    static constexpr ::aos::time::Time kWaitTime =
-        ::aos::time::Time::InSeconds(0.1);
-    reset.Set(false);
-    ::aos::time::SleepFor(kWaitTime);
-    bootloader.Set(false);
-    ::aos::time::SleepFor(kWaitTime);
-    reset.Set(true);
-    ::aos::time::SleepFor(kWaitTime);
-  }
+  Reset(true);
 
   if (argc < 2) {
     fputs("Need an argument saying which target to download.\n", stderr);
@@ -223,6 +227,7 @@
 
   if (init_bl_exit(stm, serial, NULL /* GPIO sequence */)) {
     LOG(INFO, "all done\n");
+    Reset(false);
   } else {
     LOG(FATAL, "init_bl_exit failed\n");
   }