diff options
author | Mark Meserve <mark.meserve@ni.com> | 2019-04-11 15:14:37 -0500 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-04-11 15:21:53 -0700 |
commit | c1e0e7329615806516d9ec3391a3fbf9e3a08852 (patch) | |
tree | 5c9d4c6e69a7e61a2cf8bd3f6fdd201b56ebff3a /firmware/fx3/b200/common | |
parent | 3642ac013e9b7eaf7d454790c6a1c7387b0238c4 (diff) | |
download | uhd-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.h | 51 | ||||
-rw-r--r-- | firmware/fx3/b200/common/common_descriptors.c | 237 | ||||
-rw-r--r-- | firmware/fx3/b200/common/common_descriptors.h | 50 | ||||
-rw-r--r-- | firmware/fx3/b200/common/common_helpers.c | 199 | ||||
-rw-r--r-- | firmware/fx3/b200/common/common_helpers.h | 34 |
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 */ |