got the gyro code at least starting up
diff --git a/bbb_cape/src/cape/Makefile b/bbb_cape/src/cape/Makefile
index d74e700..2439b89 100644
--- a/bbb_cape/src/cape/Makefile
+++ b/bbb_cape/src/cape/Makefile
@@ -84,7 +84,7 @@
 $(OBJECTS:%=%.s): %.s: %.c
 	$(CC) $(CPPFLAGS) $(CFLAGS) -S -o $@ $<
 %.s: %.S
-	$(CC) $(CPPFLAGS) $(ASFLAGS) -S -o $@ $<
+	$(CC) $(CPPFLAGS) $(ASFLAGS) -S -o $@ $< > $@
 
 # So that you can see the assembly of the whole .elf file.
 $(OUTPUTS:%=elf_%.s): elf_%.s: $(OBJDIR)%.elf
diff --git a/bbb_cape/src/cape/analog.c b/bbb_cape/src/cape/analog.c
index 58a1563..14c45a1 100644
--- a/bbb_cape/src/cape/analog.c
+++ b/bbb_cape/src/cape/analog.c
@@ -5,9 +5,10 @@
 #include <STM32F2XX.h>
 
 #include "cape/util.h"
+#include "cape/led.h"
 
 #define SPI SPI2
-#define SPI_IRQHander SPI2_IRQHandler
+#define SPI_IRQHandler SPI2_IRQHandler
 #define SPI_IRQn SPI2_IRQn
 #define RCC_APB1ENR_SPIEN RCC_APB1ENR_SPI2EN
 #define TIM TIM14
@@ -45,16 +46,14 @@
     analog_readings[current_channel] = value & 0x3FF;
     CSEL_GPIO->BSRRH = 1 << CSEL_NUM;
 
-    TIM->CR1 = TIM_CR1_UDIS;
-    TIM->CCR1 = 1;
+    TIM->CR1 = TIM_CR1_UDIS | TIM_CR1_OPM;
     TIM->EGR = TIM_EGR_UG;
     TIM->CR1 |= TIM_CR1_CEN;
   }
 }
 
 void TIM_IRQHandler(void) {
-  TIM->CR1 &= ~TIM_CR1_CEN;
-  TIM->SR = TIM_SR_CC1IF;
+  TIM->SR = ~TIM_SR_CC1IF;
 
   start_read((current_channel + 1) % NUM_CHANNELS);
 }
@@ -77,15 +76,18 @@
   NVIC_SetPriority(TIM_IRQn, 6);
   NVIC_EnableIRQ(TIM_IRQn);
 
-  TIM->CR1 = TIM_CR1_UDIS;
+  TIM->CR1 = TIM_CR1_UDIS | TIM_CR1_OPM;
   TIM->DIER = TIM_DIER_CC1IE;
   TIM->CCMR1 = 0;
   // Make each tick take 500ns.
-  TIM->PSC = (30 * 500 / 1000) - 1;
+  TIM->PSC = (60 * 500 / 1000) - 1;
+  // Call the interrupt after 1 tick.
+  TIM->CCR1 = 1;
 
   SPI->CR1 = 0;  // make sure it's disabled
   SPI->CR1 =
       SPI_CR1_DFF /* 16 bit frame */ |
+      SPI_CR1_SSM | SPI_CR1_SSI | /* don't watch for other masters */
       1 << 3 /* 30MHz/4 = 7.5MHz */ |
       SPI_CR1_MSTR /* master mode */;
   SPI->CR2 = SPI_CR2_RXNEIE;
diff --git a/bbb_cape/src/cape/bootloader.c b/bbb_cape/src/cape/bootloader.c
index 3ff86af..042255b 100644
--- a/bbb_cape/src/cape/bootloader.c
+++ b/bbb_cape/src/cape/bootloader.c
@@ -58,7 +58,7 @@
   RCC->AHB1ENR |=
       RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
   led_init();
-  led_set(LED_ERR, 1);
+  led_set(LED_HB, 1);
 
   setup_main_clock();
 
@@ -67,7 +67,6 @@
   while (!(SYSCFG->CMPCR & SYSCFG_CMPCR_READY)) {}  // wait for it to be ready
   TODO(brians): Figure out what the story with this is.
 #endif
-  led_set(LED_DB, 1);
 
   jump_to_main();
 }
diff --git a/bbb_cape/src/cape/crc.c b/bbb_cape/src/cape/crc.c
index fcce8b9..8182610 100644
--- a/bbb_cape/src/cape/crc.c
+++ b/bbb_cape/src/cape/crc.c
@@ -6,9 +6,10 @@
   RCC->AHB1ENR |= RCC_AHB1ENR_CRCEN;
 }
 
-uint32_t crc_calculate(uint32_t *restrict data, size_t words) {
+uint32_t crc_calculate(uint32_t *data, size_t words) {
   CRC->CR = 1;  // reset it
-  for (; data < data + words; ++data) {
+  uint32_t *end = data + words;
+  for (; data < end; ++data) {
     CRC->DR = *data;
   }
   return CRC->DR;
diff --git a/bbb_cape/src/cape/encoder.c b/bbb_cape/src/cape/encoder.c
index 31374db..768d3c0 100644
--- a/bbb_cape/src/cape/encoder.c
+++ b/bbb_cape/src/cape/encoder.c
@@ -44,7 +44,7 @@
 // 3.A
 void TIM1_TRG_COM_TIM11_IRQHandler(void) {
   uint32_t inputs = GPIOC->IDR;
-  TIM9->SR = TIM_SR_CC1IF;
+  TIM9->SR = ~TIM_SR_CC1IF;
   if (((inputs >> 1) ^ inputs) & (1 << 2)) {
     ++encoder3_value;
   } else {
diff --git a/bbb_cape/src/cape/fill_packet.c b/bbb_cape/src/cape/fill_packet.c
index ad7396e..870541b 100644
--- a/bbb_cape/src/cape/fill_packet.c
+++ b/bbb_cape/src/cape/fill_packet.c
@@ -14,6 +14,7 @@
 #include "cape/analog.h"
 #include "cape/robot.h"
 #include "cape/digital.h"
+#include "cape/led.h"
 
 #define TIMESTAMP_TIM TIM6
 #define RCC_APB1ENR_TIMESTAMP_TIMEN RCC_APB1ENR_TIM6EN
@@ -74,13 +75,15 @@
   crc_init();
   analog_init();
   encoder_init();
-  gyro_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);
 
+  led_set(LED_ERR, 0);
+  //gyro_init();
+
   uart_common_configure(3000000);
   uart_dma_configure(DATA_STRUCT_SEND_SIZE, buffer1, buffer2);
 }
diff --git a/bbb_cape/src/cape/gyro.c b/bbb_cape/src/cape/gyro.c
index 43006fd..98c2b42 100644
--- a/bbb_cape/src/cape/gyro.c
+++ b/bbb_cape/src/cape/gyro.c
@@ -90,6 +90,7 @@
   gyro_output.last_reading_bad = gyro_output.gyro_bad = 1;
   gyro_output.initialized = 1;
   gyro_output.zeroed = 0;
+  led_set(LED_ERR, 1);
 }
 
 static void gyro_enable_csel(void) {
@@ -257,6 +258,14 @@
     uint16_t value = SPI->DR;
     if (__builtin_parity(value) != 1) {
       parity_error = 1;
+      for (int i = -2; i < 16; ++i) {
+        led_set(LED_Z, i < 0);
+        for (int ii = 0; ii < 1000000; ++ii) {
+          led_set(LED_ERR, i >= 0 && ii < 500000);
+          if (i >= 0) led_set(LED_DB, value & (1 << i));
+          else led_set(LED_DB, 0);
+        }
+      }
     }
     if (receive_byte == 0) {
       receive_byte = 1;
@@ -273,7 +282,7 @@
 
 void TIM_IRQHandler(void) {
   TIM->CR1 &= ~TIM_CR1_CEN;
-  TIM->SR = TIM_SR_CC1IF;
+  TIM->SR = ~TIM_SR_CC1IF;
   switch (state) {
     case STATE_SETUP0:
       if (setup_counter++ < 100) {
@@ -379,11 +388,13 @@
   TIM->CR1 = TIM_CR1_UDIS;
   TIM->DIER = TIM_DIER_CC1IE;
   TIM->CCMR1 = 0;
-  TIM->PSC = 30000 - 1;
+  // Make it generate 1 tick every ms.
+  TIM->PSC = 60000 - 1;
 
   SPI->CR1 = 0;  // make sure it's disabled
   SPI->CR1 =
       SPI_CR1_DFF /* 16 bit frame */ |
+      SPI_CR1_SSM | SPI_CR1_SSI | /* don't watch for other masters */
       1 << 3 /* 30MHz/4 = 7.5MHz */ |
       SPI_CR1_MSTR /* master mode */;
   SPI->CR2 = SPI_CR2_RXNEIE;
diff --git a/bbb_cape/src/cape/main.c b/bbb_cape/src/cape/main.c
index be97171..390112b 100644
--- a/bbb_cape/src/cape/main.c
+++ b/bbb_cape/src/cape/main.c
@@ -7,12 +7,13 @@
 extern uint32_t _vectors;
 
 void _start(void) {
+  led_set(LED_ERR, 1);
+  led_set(LED_HB, 0);
   // Change the vector table offset to use our vector table instead of the
   // bootloader's.
   SCB->VTOR = (uint32_t)&_vectors;
   // Data Memory Barrier to make sure it gets the updated vector table.
   __asm__ __volatile__("dmb");
-  led_set(LED_DB, 0);
 
   fill_packet_start();
 
@@ -21,8 +22,6 @@
   // registers for the first one.
   SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
 
-  led_set(LED_ERR, 0);
-
   // This seems like the perfect place to use WFI, but Brian on 2013-12-13
   // couldn't find anything verifying that WFI doesn't increase the latency for
   // the first interrupt handled, and we should never actually get here anyways,
diff --git a/bbb_cape/src/cape/uart_byte.h b/bbb_cape/src/cape/uart_byte.h
index 7a82e76..e037e36 100644
--- a/bbb_cape/src/cape/uart_byte.h
+++ b/bbb_cape/src/cape/uart_byte.h
@@ -7,7 +7,7 @@
 void uart_byte_configure(void);
 
 // Spins until 1 byte is received or some amount of time. The timeout is
-// timeout_count*(timeout_divider+1)/30MHz.
+// timeout_count*(timeout_divider+1)/60MHz.
 // The result is <0 for timeout or the received byte.
 int uart_byte_receive(uint16_t timeout_count, uint16_t timeout_divider);