wrote the code for the BBB side
diff --git a/bbb_cape/src/bbb/bbb.gyp b/bbb_cape/src/bbb/bbb.gyp
new file mode 100644
index 0000000..a2d62ea
--- /dev/null
+++ b/bbb_cape/src/bbb/bbb.gyp
@@ -0,0 +1,14 @@
+{
+  'targets': [
+    {
+      'target_name': 'crc',
+      'type': 'static_library',
+      'dependencies': [
+        '<(AOS)/common/common.gyp:once',
+      ],
+      'sources': [
+        'crc.cc',
+      ],
+    },
+  ],
+}
diff --git a/bbb_cape/src/bbb/crc.cc b/bbb_cape/src/bbb/crc.cc
new file mode 100644
index 0000000..b770f37
--- /dev/null
+++ b/bbb_cape/src/bbb/crc.cc
@@ -0,0 +1,42 @@
+#include "bbb/crc.h"
+
+#include "aos/common/once.h"
+
+// There are various implementations that look a lot like this scattered around
+// the internet.
+
+namespace cape {
+namespace {
+
+const uint32_t kPolynomial = 0x04c11db7;
+
+const uint32_t *GenerateTable() {
+  static uint32_t table[256];
+
+  for (int i = 0; i < 256; ++i) {
+    uint32_t c = i << 24;
+    for (int j = 8; j > 0; --j) {
+      c = c & 0x80000000 ? ((c << 1) ^ kPolynomial) : (c << 1);
+    }
+    table[i] = c;
+  }
+
+  return table;
+}
+
+}  // namespace
+
+uint32_t CalculateChecksum(uint8_t *data, size_t length) {
+  static ::aos::once<const uint32_t> table_once(GenerateTable);
+  const uint32_t *const table = table_once.Get();
+
+  uint32_t r = 0xFFFFFFFF;
+
+  for (size_t i = 0; i < length; ++i) {
+    r = (r << 8) ^ table[(r >> 24) ^ data[i]];
+  }
+
+  return ~r;
+}
+
+}  // namespace cape
diff --git a/bbb_cape/src/bbb/crc.h b/bbb_cape/src/bbb/crc.h
new file mode 100644
index 0000000..b353efc
--- /dev/null
+++ b/bbb_cape/src/bbb/crc.h
@@ -0,0 +1,14 @@
+#ifndef BBB_CRC_H_
+#define BBB_CRC_H_
+
+#include <stdint.h>
+
+namespace cape {
+
+// Calculates a CRC32 checksum for data. This is definitely the same one as the
+// cape MCU does in hardware which seems to be the same one as Ethernet etc use.
+uint32_t CalculateChecksum(uint8_t *data, size_t length);
+
+}  // namespace cape
+
+#endif  // BBB_CRC_H_