aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/fx3/b200/common
diff options
context:
space:
mode:
authorMark Meserve <mark.meserve@ni.com>2019-04-11 15:14:37 -0500
committerMartin Braun <martin.braun@ettus.com>2019-04-11 15:21:53 -0700
commitc1e0e7329615806516d9ec3391a3fbf9e3a08852 (patch)
tree5c9d4c6e69a7e61a2cf8bd3f6fdd201b56ebff3a /firmware/fx3/b200/common
parent3642ac013e9b7eaf7d454790c6a1c7387b0238c4 (diff)
downloaduhd-c1e0e7329615806516d9ec3391a3fbf9e3a08852.tar.gz
uhd-c1e0e7329615806516d9ec3391a3fbf9e3a08852.tar.bz2
uhd-c1e0e7329615806516d9ec3391a3fbf9e3a08852.zip
b200: add custom bootloader
- Adds custom bootloader code - Refactor common functions in firmware and bootloader
Diffstat (limited to 'firmware/fx3/b200/common')
-rw-r--r--firmware/fx3/b200/common/common_const.h51
-rw-r--r--firmware/fx3/b200/common/common_descriptors.c237
-rw-r--r--firmware/fx3/b200/common/common_descriptors.h50
-rw-r--r--firmware/fx3/b200/common/common_helpers.c199
-rw-r--r--firmware/fx3/b200/common/common_helpers.h34
5 files changed, 571 insertions, 0 deletions
diff --git a/firmware/fx3/b200/common/common_const.h b/firmware/fx3/b200/common/common_const.h
new file mode 100644
index 000000000..1b40a7fdd
--- /dev/null
+++ b/firmware/fx3/b200/common/common_const.h
@@ -0,0 +1,51 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef _COMMON_CONST_H
+#define _COMMON_CONST_H
+
+#define EEPROM_REV_UNRECOGNIZED -1
+
+#define EEPROM_SIGNATURE_ADDR 0x0000
+#define EEPROM_SIGNATURE_LENGTH 4
+
+#define EEPROM_REV0_SIGNATURE 0xB2145943
+#define EEPROM_REV1_OR_GREATER_SIGNATURE 0xB01A5943
+
+#define EEPROM_REV0_VID_ADDR 0x0006
+#define EEPROM_REV1_VID_ADDR 0x7F06
+#define EEPROM_VID_LENGTH 2
+
+#define VID_ETTUS_RESEARCH 0x2500
+#define VID_NATIONAL_INSTRUMENTS 0x3923
+#define VID_CYPRESS 0x04B4
+
+#define EEPROM_REV0_PID_ADDR 0x0004
+#define EEPROM_REV1_PID_ADDR 0x7F08
+#define EEPROM_PID_LENGTH 2
+
+#define PID_ETTUS_B200_B210 0x0020
+#define PID_NI_USRP_2900 0x7813
+#define PID_NI_USRP_2901 0x7814
+#define PID_CYPRESS_DEFAULT 0x00F0
+
+#define EEPROM_REV0_SERIAL_ADDR 0x04F7
+#define EEPROM_REV1_SERIAL_ADDR 0x7F23
+#define EEPROM_SERIAL_LENGTH 9
+
+#define EEPROM_REV1_MAGIC_ADDR 0x7F00
+#define EEPROM_MAGIC_LENGTH 2
+#define EEPROM_EXPECTED_MAGIC 0xB200
+
+#define EEPROM_REV1_REV_ADDR 0x7F02
+#define EEPROM_REV_LENGTH 2
+#define EEPROM_EXPECTED_REV 1
+
+#define EEPROM_REV1_COMPAT_ADDR 0x7F04
+#define EEPROM_COMPAT_LENGTH 2
+#define EEPROM_EXPECTED_COMPAT 1
+
+#endif /* _COMMON_CONST_H */
diff --git a/firmware/fx3/b200/common/common_descriptors.c b/firmware/fx3/b200/common/common_descriptors.c
new file mode 100644
index 000000000..7cb670a4a
--- /dev/null
+++ b/firmware/fx3/b200/common/common_descriptors.c
@@ -0,0 +1,237 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+/* This file contains all descriptors that are common between the bootloader
+ and firmware code. Non-const descriptors are modified at runtime based on
+ information read from the EEPROM. */
+
+/* Standard Device Descriptor for USB 2.0 */
+unsigned char common_usb2_dev_desc[] =
+{
+ 0x12, /* Descriptor size */
+ 0x01,/* CY_U3P_USB_DEVICE_DESCR Device descriptor type */
+ 0x10,0x02, /* USB 2.10 */
+ 0xFF, /* Device class */
+ 0x00, /* Device sub-class */
+ 0x00, /* Device protocol */
+ 0x40, /* Maxpacket size for EP0 : 64 bytes */
+ 0xB4,0x04, /* Vendor ID */
+ 0xF0,0x00, /* Product ID */
+ 0x00,0x00, /* Device release number */
+ 0x01, /* Manufacture string index */
+ 0x02, /* Product string index */
+ 0x03, /* Serial number string index */
+ 0x01 /* Number of configurations */
+};
+
+/* Standard Device Descriptor for USB 3.0 */
+unsigned char common_usb3_dev_desc[] =
+{
+ 0x12, /* Descriptor size */
+ 0x01,/* CY_U3P_USB_DEVICE_DESCR Device descriptor type */
+ 0x00,0x03, /* USB 3.0 */
+ 0xFF, /* Device class */
+ 0x00, /* Device sub-class */
+ 0x00, /* Device protocol */
+ 0x09, /* Maxpacket size for EP0 : 2^9 */
+ 0xB4,0x04, /* Vendor ID */
+ 0xF0,0x00, /* Product ID */
+ 0x00,0x00, /* Device release number */
+ 0x01, /* Manufacture string index */
+ 0x02, /* Product string index */
+ 0x03, /* Serial number string index */
+ 0x01 /* Number of configurations */
+};
+
+/* Standard Device Qualifier Descriptor */
+const unsigned char common_dev_qual_desc[] =
+{
+ 0x0A, /* Descriptor size */
+ 0x06,/* CY_U3P_USB_DEVQUAL_DESCR Device qualifier descriptor type */
+ 0x00,0x02, /* USB 2.0 */
+ 0xFF, /* Device class */
+ 0x00, /* Device sub-class */
+ 0x00, /* Device protocol */
+ 0x40, /* Maxpacket size for EP0 : 64 bytes */
+ 0x01, /* Number of configurations */
+ 0x00 /* Reserved */
+};
+
+/* Standard Binary Device Object Store Descriptor */
+const unsigned char common_usb_bos_desc[] =
+{
+ 0x05, /* Descriptor size */
+ 0x0F,/* CY_U3P_BOS_DESCR Device descriptor type */
+ 0x16,0x00, /* Length of this descriptor and all sub descriptors */
+ 0x02, /* Number of device capability descriptors */
+
+ /* USB 2.0 extension */
+ 0x07, /* Descriptor size */
+ 0x10,/* CY_U3P_DEVICE_CAPB_DESCR Device capability type descriptor */
+ 0x02,/* CY_U3P_USB2_EXTN_CAPB_TYPE USB 2.0 extension capability type */
+ 0x02,0x00,0x00,0x00, /* Supported device level features: LPM support */
+
+ /* SuperSpeed device capability */
+ 0x0A, /* Descriptor size */
+ 0x10,/* CY_U3P_DEVICE_CAPB_DESCR Device capability type descriptor */
+ 0x03,/* CY_U3P_SS_USB_CAPB_TYPE SuperSpeed device capability type */
+ 0x00, /* Supported device level features */
+ 0x0E,0x00, /* Speeds supported by the device : SS, HS and FS */
+ 0x03, /* Functionality support */
+ 0x00, /* U1 Device Exit latency */
+ 0x00,0x00 /* U2 Device Exit latency */
+};
+
+/* Standard Language ID String Descriptor */
+const unsigned char common_string_lang_id_desc[] =
+{
+ 0x04, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ 0x09,0x04 /* Language ID supported */
+};
+
+
+/* Ettus Manufacturer String Descriptor */
+const unsigned char common_ettus_manufacturer_desc[] =
+{
+ 0x26, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ 'E',0x00,
+ 't',0x00,
+ 't',0x00,
+ 'u',0x00,
+ 's',0x00,
+ ' ',0x00,
+ 'R',0x00,
+ 'e',0x00,
+ 's',0x00,
+ 'e',0x00,
+ 'a',0x00,
+ 'r',0x00,
+ 'c',0x00,
+ 'h',0x00,
+ ' ',0x00,
+ 'L',0x00,
+ 'L',0x00,
+ 'C',0x00
+};
+
+/* NI Manufacturer String Descriptor */
+const unsigned char common_ni_manufacturer_desc[] =
+{
+ 0x36, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ 'N',0x00,
+ 'a',0x00,
+ 't',0x00,
+ 'i',0x00,
+ 'o',0x00,
+ 'n',0x00,
+ 'a',0x00,
+ 'l',0x00,
+ ' ',0x00,
+ 'I',0x00,
+ 'n',0x00,
+ 's',0x00,
+ 't',0x00,
+ 'r',0x00,
+ 'u',0x00,
+ 'm',0x00,
+ 'e',0x00,
+ 'n',0x00,
+ 't',0x00,
+ 's',0x00,
+ ' ',0x00,
+ 'C',0x00,
+ 'o',0x00,
+ 'r',0x00,
+ 'p',0x00,
+ '.',0x00
+};
+
+
+/* Ettus Product String Descriptor */
+const unsigned char common_b200_product_desc[] =
+{
+ 0x14, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ 'U',0x00,
+ 'S',0x00,
+ 'R',0x00,
+ 'P',0x00,
+ ' ',0x00,
+ 'B',0x00,
+ '2',0x00,
+ '0',0x00,
+ '0',0x00
+};
+
+/* NI-USRP 2900 Product String Descriptor */
+const unsigned char common_niusrp_2900_product_desc[] =
+{
+ 0x1A, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ 'N',0x00,
+ 'I',0x00,
+ ' ',0x00,
+ 'U',0x00,
+ 'S',0x00,
+ 'R',0x00,
+ 'P',0x00,
+ '-',0x00,
+ '2',0x00,
+ '9',0x00,
+ '0',0x00,
+ '0',0x00
+};
+
+/* NI-USRP 2901 Product String Descriptor */
+const unsigned char common_niusrp_2901_product_desc[] =
+{
+ 0x1A, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ 'N',0x00,
+ 'I',0x00,
+ ' ',0x00,
+ 'U',0x00,
+ 'S',0x00,
+ 'R',0x00,
+ 'P',0x00,
+ '-',0x00,
+ '2',0x00,
+ '9',0x00,
+ '0',0x00,
+ '1',0x00
+};
+
+/* Unknown Product String Descriptor */
+const unsigned char common_unknown_desc[] =
+{
+ 0x10, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ 'U',0x00,
+ 'n',0x00,
+ 'k',0x00,
+ 'n',0x00,
+ 'o',0x00,
+ 'w',0x00,
+ 'n',0x00
+};
+
+unsigned char common_dev_serial_desc[] =
+{
+ 0x14, /* Descriptor Size */
+ 0x03,/* CY_U3P_USB_STRING_DESCR Device Descriptor Type */
+ '0', 0x00,
+ '0', 0x00,
+ '0', 0x00,
+ '0', 0x00,
+ '0', 0x00,
+ '0', 0x00,
+ '0', 0x00,
+ '0', 0x00,
+ '0', 0x00
+};
diff --git a/firmware/fx3/b200/common/common_descriptors.h b/firmware/fx3/b200/common/common_descriptors.h
new file mode 100644
index 000000000..15acac3fa
--- /dev/null
+++ b/firmware/fx3/b200/common/common_descriptors.h
@@ -0,0 +1,50 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef _COMMON_DESCRIPTORS_H
+#define _COMMON_DESCRIPTORS_H
+
+/* This file contains all descriptors that are common between the bootloader
+ and firmware code. Non-const descriptors are modified at runtime based on
+ information read from the EEPROM. */
+
+/* Standard Device Descriptor for USB 2.0 */
+extern unsigned char common_usb2_dev_desc[];
+
+/* Standard Device Descriptor for USB 3.0 */
+extern unsigned char common_usb3_dev_desc[];
+
+/* Standard Device Qualifier Descriptor */
+extern const unsigned char common_dev_qual_desc[];
+
+/* Standard Binary Device Object Store Descriptor */
+extern const unsigned char common_usb_bos_desc[];
+
+/* Standard Language ID String Descriptor */
+extern const unsigned char common_string_lang_id_desc[];
+
+/* Ettus Manufacturer String Descriptor */
+extern const unsigned char common_ettus_manufacturer_desc[];
+
+/* NI Manufacturer String Descriptor */
+extern const unsigned char common_ni_manufacturer_desc[];
+
+/* Ettus Product String Descriptor */
+extern const unsigned char common_b200_product_desc[];
+
+/* NI-USRP 2900 Product String Descriptor */
+extern const unsigned char common_niusrp_2900_product_desc[];
+
+/* NI-USRP 2901 Product String Descriptor */
+extern const unsigned char common_niusrp_2901_product_desc[];
+
+/* Unknown Product String Descriptor */
+extern const unsigned char common_unknown_desc[];
+
+/* Common Serial String Descriptor */
+extern unsigned char common_dev_serial_desc[];
+
+#endif \ No newline at end of file
diff --git a/firmware/fx3/b200/common/common_helpers.c b/firmware/fx3/b200/common/common_helpers.c
new file mode 100644
index 000000000..5a21a2106
--- /dev/null
+++ b/firmware/fx3/b200/common/common_helpers.c
@@ -0,0 +1,199 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include "common_helpers.h"
+#include "common_const.h"
+#include "common_descriptors.h"
+
+#define UNREAD 0xFFFF
+
+/* Check the rev, magic value, and eeprom compatibility field to determine if
+ our eeprom map is up-to-date with what is written on the device */
+int eeprom_is_readable(eeprom_read_t read_fn) {
+ /* Only check this once, then store that info */
+ static int is_readable = UNREAD;
+
+ if (is_readable != UNREAD) {
+ return is_readable;
+ }
+
+ int rev = get_rev(read_fn);
+
+ if (rev == EEPROM_REV_UNRECOGNIZED)
+ {
+ is_readable = 0;
+ return is_readable;
+ }
+
+
+ /* If rev is 0, there's no further checks available */
+ if (rev == 0)
+ {
+ is_readable = 1;
+ return is_readable;
+ }
+
+ /* For rev 1, check the EEPROM magic value and compat number */
+
+ if (rev == 1) {
+ {
+ uint8_t buffer[EEPROM_MAGIC_LENGTH];
+ read_fn(EEPROM_REV1_MAGIC_ADDR, buffer, EEPROM_MAGIC_LENGTH);
+ if ((buffer[1] << 8 | buffer[0]) != EEPROM_EXPECTED_MAGIC) {
+ is_readable = 0;
+ return is_readable;
+ }
+ }
+ {
+ uint8_t buffer[EEPROM_COMPAT_LENGTH];
+ read_fn(EEPROM_REV1_COMPAT_ADDR, buffer, EEPROM_COMPAT_LENGTH);
+ if ((buffer[1] << 8 | buffer[0]) > EEPROM_EXPECTED_COMPAT) {
+ is_readable = 0;
+ return is_readable;
+ }
+ }
+ is_readable = 1;
+ return is_readable;
+ }
+
+ /* some other unrecognized rev */
+ is_readable = 0;
+ return is_readable;
+}
+
+/* Read the EEPROM layout revision number from EEPROM using the function
+ specified */
+int get_rev(eeprom_read_t read_fn)
+{
+ /* Only check the rev once, then store that info */
+ static int rev = UNREAD;
+
+ if (rev != UNREAD) {
+ return rev;
+ }
+
+ uint8_t buffer[EEPROM_SIGNATURE_LENGTH];
+ read_fn(EEPROM_SIGNATURE_ADDR, buffer, EEPROM_SIGNATURE_LENGTH);
+
+ const uint32_t signature = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8
+ | buffer[0];
+ if (signature == EEPROM_REV0_SIGNATURE) {
+ rev = 0;
+ } else if (signature == EEPROM_REV1_OR_GREATER_SIGNATURE) {
+ rev = 1;
+ } else {
+ rev = EEPROM_REV_UNRECOGNIZED;
+ }
+ return rev;
+}
+
+
+
+/* Read the vendor ID from EEPROM using the function specified*/
+uint16_t get_vid(eeprom_read_t read_fn)
+{
+ static uint16_t vid = UNREAD;
+
+ if (vid != UNREAD) {
+ return vid;
+ }
+
+ if (!eeprom_is_readable(read_fn)) {
+ vid = VID_CYPRESS;
+ return vid;
+ }
+
+ // eeprom_is_readable guarantees rev is valid
+ int rev = get_rev(read_fn);
+
+ const uint16_t addr = (rev == 0) ? EEPROM_REV0_VID_ADDR : EEPROM_REV1_VID_ADDR;
+
+ uint8_t buffer[EEPROM_VID_LENGTH];
+ read_fn(addr, buffer, EEPROM_VID_LENGTH);
+ vid = buffer[1] << 8 | buffer[0];
+ return vid;
+}
+
+/* Read the product ID from EEPROM using the function specified*/
+uint16_t get_pid(eeprom_read_t read_fn)
+{
+ static uint16_t pid = UNREAD;
+
+ if (pid != UNREAD) {
+ return pid;
+ }
+
+ if (!eeprom_is_readable(read_fn)) {
+ pid = PID_CYPRESS_DEFAULT;
+ return pid;
+ }
+
+ // eeprom_is_readable guarantees rev is valid
+ int rev = get_rev(read_fn);
+
+ const uint16_t addr = (rev == 0) ? EEPROM_REV0_PID_ADDR : EEPROM_REV1_PID_ADDR;
+
+ uint8_t buffer[EEPROM_PID_LENGTH];
+ read_fn(addr, buffer, EEPROM_PID_LENGTH);
+ pid = buffer[1] << 8 | buffer[0];
+ return pid;
+}
+
+/* Read the vendor ID from EEPROM using the function specified */
+const uint8_t* get_serial_string_descriptor(eeprom_read_t read_fn)
+{
+ static uint8_t* serial_string_descriptor = 0;
+ if (serial_string_descriptor) {
+ return serial_string_descriptor;
+ }
+
+ /* All code paths will eventually return this value, but some will modify
+ it beforehand */
+ serial_string_descriptor = common_dev_serial_desc;
+
+ if (!eeprom_is_readable(read_fn)) {
+ return serial_string_descriptor;
+ }
+
+ // eeprom_is_readable guarantees rev is valid
+ int rev = get_rev(read_fn);
+
+ const uint16_t addr = (rev == 0) ? EEPROM_REV0_SERIAL_ADDR : EEPROM_REV1_SERIAL_ADDR;
+
+ uint8_t buffer[EEPROM_SERIAL_LENGTH];
+ read_fn(addr, buffer, EEPROM_SERIAL_LENGTH);
+ int i;
+ for (i = 0; i < EEPROM_SERIAL_LENGTH; ++i) {
+ common_dev_serial_desc[2 + i * 2] = buffer[i];
+ }
+ return serial_string_descriptor;
+}
+
+/* Return the string descriptor based on the VID given */
+const uint8_t* get_manufacturer_string_descriptor(uint16_t vid)
+{
+ if (vid == VID_ETTUS_RESEARCH) {
+ return common_ettus_manufacturer_desc;
+ } else if (vid == VID_NATIONAL_INSTRUMENTS) {
+ return common_ni_manufacturer_desc;
+ } else {
+ return common_unknown_desc;
+ }
+}
+
+/* Return the string descriptor based on the PID given */
+const uint8_t* get_product_string_descriptor(uint16_t pid)
+{
+ if (pid == PID_ETTUS_B200_B210) {
+ return common_b200_product_desc;
+ } else if (pid == PID_NI_USRP_2900) {
+ return common_niusrp_2900_product_desc;
+ } else if (pid == PID_NI_USRP_2901) {
+ return common_niusrp_2901_product_desc;
+ } else {
+ return common_unknown_desc;
+ }
+}
diff --git a/firmware/fx3/b200/common/common_helpers.h b/firmware/fx3/b200/common/common_helpers.h
new file mode 100644
index 000000000..8ff28fb09
--- /dev/null
+++ b/firmware/fx3/b200/common/common_helpers.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef _COMMON_HELPERS_H
+#define _COMMON_HELPERS_H
+
+#include "cyu3types.h"
+
+typedef void (*eeprom_read_t)(uint16_t, uint8_t*, uint8_t);
+
+/* Read the EEPROM layout revision number from EEPROM using the function
+ specified */
+int get_rev(eeprom_read_t read_fn);
+
+/* Read the vendor ID from EEPROM using the function specified*/
+uint16_t get_vid(eeprom_read_t read_fn);
+
+/* Read the product ID from EEPROM using the function specified*/
+uint16_t get_pid(eeprom_read_t read_fn);
+
+/* Read the vendor ID from EEPROM using the function specified
+ Buffer must be at least length 20 */
+const uint8_t* get_serial_string_descriptor(eeprom_read_t read_fn);
+
+/* Return the string descriptor based on the VID given */
+const uint8_t* get_manufacturer_string_descriptor(uint16_t vid);
+
+/* Return the string descriptor based on the PID given */
+const uint8_t* get_product_string_descriptor(uint16_t pid);
+
+#endif /* _COMMON_HELPERS_H */