Skip to content

Commit

Permalink
Merge pull request #32 from mndza/board-rev-detect
Browse files Browse the repository at this point in the history
firmware: Add support for hardware revision detection
  • Loading branch information
mossmann authored Jun 12, 2024
2 parents 098cc70 + 6ca82ed commit b0ee905
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 18 deletions.
14 changes: 11 additions & 3 deletions firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ ifeq ($(APOLLO_BOARD), luna)
endif

ifeq ($(BOARD), cynthion_d11)
# These should default to the latest revision but can be set on the command line.
BOARD_REVISION_MAJOR ?= 1
BOARD_REVISION_MINOR ?= 4
# Enable revision autodetection by default if no revision is provided.
ifeq ($(BOARD_REVISION_MAJOR),)
ifeq ($(BOARD_REVISION_MINOR),)
BOARD_REVISION_DETECT := 1
BOARD_REVISION_MAJOR := 255
BOARD_REVISION_MINOR := 255
endif
endif

# On r0.1 or r0.2 boards, we target the SAMD21 configuration.
ifeq ($(BOARD_REVISION_MAJOR), 0)
Expand All @@ -36,6 +41,8 @@ else
BOARD := $(APOLLO_BOARD)
endif

# This should be set to 1 at this point if autodetection is enabled.
BOARD_REVISION_DETECT ?= 0

# Default to using a maximum possible HW version, which means "generic Apollo board".
BOARD_REVISION_MAJOR ?= 255
Expand All @@ -61,6 +68,7 @@ CFLAGS += \
-Wno-unused-parameter \
-Wno-cast-qual \
-fstrict-volatile-bitfields \
-D_BOARD_REVISION_DETECT_=$(BOARD_REVISION_DETECT) \
-D_BOARD_REVISION_MAJOR_=$(BOARD_REVISION_MAJOR) \
-D_BOARD_REVISION_MINOR_=$(BOARD_REVISION_MINOR) \
-D VERSION_STRING=\"$(VERSION_STRING)\" \
Expand Down
25 changes: 25 additions & 0 deletions firmware/src/board_rev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Board revision detection.
*
* This file is part of Apollo.
*
* Copyright (c) 2024 Great Scott Gadgets <[email protected]>
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "board_rev.h"

/**
* Detect hardware revision using a board-specific method.
*/
__attribute__((weak)) void detect_hardware_revision(void)
{
}

/**
* Returns the board revision in bcdDevice format.
*/
__attribute__((weak)) uint16_t get_board_revision(void)
{
return (_BOARD_REVISION_MAJOR_ << 8) | _BOARD_REVISION_MINOR_;
}
26 changes: 26 additions & 0 deletions firmware/src/board_rev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Board revision detection.
*
* This file is part of Apollo.
*
* Copyright (c) 2024 Great Scott Gadgets <[email protected]>
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdint.h>

#ifndef __BOARD_REV_H__
#define __BOARD_REV_H__

/**
* Detect hardware revision using a board-specific method.
*/
void detect_hardware_revision(void);

/**
* Returns the board revision in bcdDevice format.
*/
uint16_t get_board_revision(void);


#endif
20 changes: 17 additions & 3 deletions firmware/src/boards/cynthion_d11/apollo_board.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,32 @@ enum {
*/
enum {
FPGA_PROGRAM = PIN_PA08,
#if ((_BOARD_REVISION_MAJOR_ == 0) && (_BOARD_REVISION_MINOR_ < 6))
#ifdef BOARD_HAS_SHARED_BUTTON
PROGRAM_BUTTON = PIN_PA16,
PHY_RESET = PIN_PA09,
#else
PROGRAM_BUTTON = PIN_PA02,
USB_SWITCH = PIN_PA06,
FPGA_ADV = PIN_PA09,
#endif
#if ((_BOARD_REVISION_MAJOR_ == 1) && (_BOARD_REVISION_MINOR_ > 2))
// FPGA sysCFG pins only in revs >= 1.3.
FPGA_INITN = PIN_PA03,
FPGA_DONE = PIN_PA04,
#endif
};


/**
* Cynthion board revisions as bcdDevice values.
*/
enum {
CYNTHION_REV_UNKNOWN = 0,
CYNTHION_REV_0_6 = (0 << 8) | 6,
CYNTHION_REV_0_7 = (0 << 8) | 7,
CYNTHION_REV_1_0 = (1 << 8) | 0,
CYNTHION_REV_1_1 = (1 << 8) | 1,
CYNTHION_REV_1_2 = (1 << 8) | 2,
CYNTHION_REV_1_3 = (1 << 8) | 3,
CYNTHION_REV_1_4 = (1 << 8) | 4,
};


Expand Down
108 changes: 108 additions & 0 deletions firmware/src/boards/cynthion_d11/board_rev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Board revision detection for Cynthion.
*
* This file is part of Apollo.
*
* Copyright (c) 2024 Great Scott Gadgets <[email protected]>
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdint.h>

#include "apollo_board.h"
#include "board_rev.h"

#include <hpl_pm_config.h>
#include <hpl/pm/hpl_pm_base.h>
#include <hpl/gclk/hpl_gclk_base.h>


#if (_BOARD_REVISION_DETECT_ == 1)

static uint16_t revision = CYNTHION_REV_UNKNOWN;
static bool gsg_production = false;

/**
* Detect hardware revision using Cynthion pin straps.
*/
void detect_hardware_revision(void)
{
_pm_enable_bus_clock(PM_BUS_APBC, ADC);
_gclk_enable_channel(ADC_GCLK_ID, CONF_GCLK_ADC_SRC);

// Initialize ADC device registers.
uint16_t calib_reg = ADC_CALIB_BIAS_CAL((*(uint32_t *)ADC_FUSES_BIASCAL_ADDR >> ADC_FUSES_BIASCAL_Pos))
| ADC_CALIB_LINEARITY_CAL((*(uint64_t *)ADC_FUSES_LINEARITY_0_ADDR >> ADC_FUSES_LINEARITY_0_Pos));

hri_adc_wait_for_sync(ADC);
hri_adc_write_CTRLA_reg(ADC, ADC_CTRLA_SWRST);
hri_adc_wait_for_sync(ADC);

hri_adc_write_CALIB_reg(ADC, calib_reg);
hri_adc_write_REFCTRL_reg(ADC, ADC_REFCTRL_REFCOMP | ADC_REFCTRL_REFSEL_INTVCC1);
hri_adc_write_CTRLB_reg(ADC, ADC_CTRLB_PRESCALER_DIV512 | ADC_CTRLB_RESSEL_12BIT);
hri_adc_write_INPUTCTRL_reg(ADC, ADC_INPUTCTRL_GAIN_DIV2 | ADC_INPUTCTRL_MUXPOS_PIN5 | ADC_INPUTCTRL_MUXNEG_GND);
hri_adc_write_CTRLA_reg(ADC, ADC_CTRLA_ENABLE);

// Configure relevant GPIO to function as an ADC input.
gpio_set_pin_function(PIN_PA07, PINMUX_PA07B_ADC_AIN5);

// Retrieve a single ADC reading.
hri_adc_set_SWTRIG_START_bit(ADC);
while (!hri_adc_get_interrupt_RESRDY_bit(ADC));
uint16_t reading = hri_adc_read_RESULT_reg(ADC);

// Convert ADC measurement to a percentage of the reference voltage.
uint32_t percentage = (((uint32_t)reading * 100) + 2048) >> 12;
if (percentage > 51) {
percentage = 100 - percentage;
gsg_production = true;
}

/*
hardware version | percent of +3V3
___________________________________________
0.6 | 0-1
future versions | 2-20
1.4 | 21-22
1.3 | 23-24
1.2 | 25-26
1.0 | 27-28
1.1 | 29-31
reserved | 32-48
0.7 | 49-51
reserved | 52-68
1.1-production | 69-71
future-production | 72-100
*/

// Identify the board revision by comparing against expected thresholds.
struct {
uint16_t version;
uint8_t threshold;
} revisions[] = {
{ CYNTHION_REV_0_6, 1 },
{ CYNTHION_REV_UNKNOWN, 20 },
{ CYNTHION_REV_1_4, 22 },
{ CYNTHION_REV_1_3, 24 },
{ CYNTHION_REV_1_2, 26 },
{ CYNTHION_REV_1_0, 28 },
{ CYNTHION_REV_1_1, 31 },
{ CYNTHION_REV_UNKNOWN, 48 },
{ CYNTHION_REV_0_7, 51 },
};

int i = 0;
while (percentage > revisions[i].threshold) { ++i; }
revision = revisions[i].version;
}

/**
* Returns the board revision in bcdDevice format.
*/
uint16_t get_board_revision(void)
{
return revision;
}

#endif
21 changes: 11 additions & 10 deletions firmware/src/boards/cynthion_d11/fpga.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "apollo_board.h"
#include "jtag.h"
#include "fpga.h"
#include "board_rev.h"


/*
Expand All @@ -20,17 +21,17 @@
*/
void permit_fpga_configuration(bool enable)
{
#if ((_BOARD_REVISION_MAJOR_ == 1) && (_BOARD_REVISION_MINOR_ > 2))
gpio_set_pin_level(FPGA_INITN, enable);
gpio_set_pin_direction(FPGA_INITN, GPIO_DIRECTION_OUT);
if (get_board_revision() < CYNTHION_REV_1_3) return;

/*
* Delay a bit (in case the FPGA is already initializing) because
* TN-02039 says that PROGRAMN should not have a falling edge during
* initialization.
*/
board_delay(1);
#endif
gpio_set_pin_level(FPGA_INITN, enable);
gpio_set_pin_direction(FPGA_INITN, GPIO_DIRECTION_OUT);

/*
* Delay a bit (in case the FPGA is already initializing) because
* TN-02039 says that PROGRAMN should not have a falling edge during
* initialization.
*/
board_delay(1);
}


Expand Down
2 changes: 2 additions & 0 deletions firmware/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <bsp/board_api.h>
#include <apollo_board.h>

#include "board_rev.h"
#include "led.h"
#include "jtag.h"
#include "fpga.h"
Expand All @@ -49,6 +50,7 @@
int main(void)
{
board_init();
detect_hardware_revision();
tusb_init();

fpga_io_init();
Expand Down
5 changes: 3 additions & 2 deletions firmware/src/mcu/samd11/usb_descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@
*/

#include "tusb.h"
#include "board_rev.h"

#define SERIAL_NUMBER_STRING_INDEX 3

//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
tusb_desc_device_t const desc_device =
tusb_desc_device_t desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
Expand All @@ -50,7 +51,6 @@ tusb_desc_device_t const desc_device =
// These are a unique VID/PID for development LUNA boards.
.idVendor = 0x1d50,
.idProduct = 0x615c,
.bcdDevice = (_BOARD_REVISION_MAJOR_ << 8) | _BOARD_REVISION_MINOR_,

.iManufacturer = 0x01,
.iProduct = 0x02,
Expand All @@ -63,6 +63,7 @@ tusb_desc_device_t const desc_device =
// Application return pointer to descriptor
uint8_t const * tud_descriptor_device_cb(void)
{
desc_device.bcdDevice = get_board_revision();
return (uint8_t const *) &desc_device;
}

Expand Down

0 comments on commit b0ee905

Please sign in to comment.