diff --git a/firmware/Makefile b/firmware/Makefile index 69f095b8..4eec868e 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -145,7 +145,7 @@ VPATH += src_board src_sam3s cmsis $(USB_PATHS) src_simtrace src_libosmocore # Objects built from C source files C_CMSIS = core_cm3.o C_LOWLEVEL = board_cstartup_gnu.o board_lowlevel.o syscalls.o exceptions.o -C_LIBLEVEL = spi.o pio.o pmc.o usart.o pio_it.o pio_capture.o uart_console.o iso7816_4.o wdt.o led.o tc.o unique_id.o +C_LIBLEVEL = spi.o pio.o pmc.o usart.o pio_it.o pio_capture.o uart_console.o iso7816_4.o wdt.o led.o tc.o unique_id.o boardver_adc.o C_CCID = cciddriver.o USBD.o USBDDriver.o USBD_HAL.o USBRequests.o USBDCallbacks.o USBDescriptors.o USBDDriverCallbacks.o C_SIMTRACE = simtrace_iso7816.o usb.o ccid.o sniffer.o mitm.o ringbuffer.o host_communication.o iso7816_fidi.o tc_etu.o req_ctx.o card_emu.o mode_cardemu.o i2c.o wwan_led.o wwan_perst.o C_OSMOCORE = timer.o rbtree.o diff --git a/firmware/include_board/boardver_adc.h b/firmware/include_board/boardver_adc.h new file mode 100644 index 00000000..a89d630b --- /dev/null +++ b/firmware/include_board/boardver_adc.h @@ -0,0 +1,3 @@ +#pragma once + +int get_board_version_adc(void); diff --git a/firmware/include_board/qmod/board.h b/firmware/include_board/qmod/board.h index e9704473..86a7ee4c 100644 --- a/firmware/include_board/qmod/board.h +++ b/firmware/include_board/qmod/board.h @@ -53,6 +53,8 @@ #define PIN_PERST2 {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_PULLUP} #define PINS_PERST { PIN_PERST1, PIN_PERST2 } +#define PIN_VERSION_DET {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT} + #define SIMTRACE_VENDOR_ID 0x1d50 #define SIMTRACE_PRODUCT_ID 0x60e3 /* FIXME */ #define USB_VENDOR_ID SIMTRACE_VENDOR_ID diff --git a/firmware/src_board/boardver_adc.c b/firmware/src_board/boardver_adc.c new file mode 100644 index 00000000..ca3d1fe2 --- /dev/null +++ b/firmware/src_board/boardver_adc.c @@ -0,0 +1,83 @@ +#include "board.h" +#include "boardver_adc.h" + +/* FIXME: share this with mode_cardemu.c */ +#define UV_PER_LSB ((3300 * 1000) / 4096) +static uint32_t adc2uv(uint16_t adc) +{ + uint32_t uv = (uint32_t) adc * UV_PER_LSB; + return uv; +} + +/*********************************************************************** + * ADC for board version detection + ***********************************************************************/ + +#ifdef PIN_VERSION_DET + +static int adc_sam3s_reva_errata = 0; + +static const Pin pin_version_det = PIN_VERSION_DET; + +/* Warning: Don't call this while other code (like the SIM VCC voltage + * reading) is running. The idea is you call this once during board + * startup and cache the result in a (global) variable if you need it + * later throughout the code */ +int get_board_version_adc(void) +{ + uint32_t chip_arch = CHIPID->CHIPID_CIDR & CHIPID_CIDR_ARCH_Msk; + uint32_t chip_ver = CHIPID->CHIPID_CIDR & CHIPID_CIDR_VERSION_Msk; + uint16_t sample; + uint32_t uv; + + PIO_Configure(&pin_version_det, 1); + + PMC_EnablePeripheral(ID_ADC); + + ADC->ADC_CR |= ADC_CR_SWRST; + if (chip_ver == 0 && + (chip_arch == CHIPID_CIDR_ARCH_SAM3SxA || + chip_arch == CHIPID_CIDR_ARCH_SAM3SxB || + chip_arch == CHIPID_CIDR_ARCH_SAM3SxC)) { + TRACE_INFO("Enabling Rev.A ADC Errata work-around\r\n"); + adc_sam3s_reva_errata = 1; + } + + if (adc_sam3s_reva_errata) { + /* Errata Work-Around to clear EOCx flags */ + volatile uint32_t foo; + int i; + for (i = 0; i < 16; i++) + foo = ADC->ADC_CDR[i]; + } + + /* Initialize ADC for AD2, fADC=48/24=2MHz */ + ADC->ADC_MR = ADC_MR_TRGEN_DIS | ADC_MR_LOWRES_BITS_12 | + ADC_MR_SLEEP_NORMAL | ADC_MR_FWUP_OFF | + ADC_MR_FREERUN_OFF | ADC_MR_PRESCAL(23) | + ADC_MR_STARTUP_SUT8 | ADC_MR_SETTLING(3) | + ADC_MR_ANACH_NONE | ADC_MR_TRACKTIM(4) | + ADC_MR_TRANSFER(1) | ADC_MR_USEQ_NUM_ORDER; + /* enable AD2 channel only */ + ADC->ADC_CHER = ADC_CHER_CH2; + + /* Make sure we don't use interrupts as that's what the SIM card + * VCC ADC code is using */ + ADC->ADC_IER = 0; + NVIC_DisableIRQ(ADC_IRQn); + + ADC->ADC_CR |= ADC_CR_START; + + /* busy-wait, actually read the value */ + do { } while (!(ADC->ADC_ISR & ADC_ISR_EOC2)); + /* convert to voltage */ + sample = ADC->ADC_CDR[2]; + uv = adc2uv(sample); + TRACE_INFO("VERSION_DET ADC=%u => %u uV\r\n", sample, uv); + + /* FIXME: convert to board version based on thresholds */ + + return 0; +} + +#endif /* PIN_VERSION_DET */ diff --git a/firmware/src_simtrace/main.c b/firmware/src_simtrace/main.c index d44cc44d..97f9b912 100644 --- a/firmware/src_simtrace/main.c +++ b/firmware/src_simtrace/main.c @@ -9,6 +9,7 @@ #include "req_ctx.h" #include "wwan_led.h" #include "wwan_perst.h" +#include "boardver_adc.h" #include "osmocom/core/timer.h" uint32_t g_unique_id[4]; @@ -320,6 +321,9 @@ extern int main(void) TRACE_INFO("Detected Quad-Modem ST34\r\n"); } + /* Obtain the circuit board version (currently just prints voltage */ + get_board_version_adc(); + TRACE_INFO("USB init...\r\n"); SIMtrace_USB_Initialize();