3939#include <libopencm3/cm3/cortex.h>
4040#include <libopencm3/usb/dwc/otg_fs.h>
4141#include <libopencm3/stm32/spi.h>
42+ #include <libopencm3/stm32/adc.h>
4243
4344jmp_buf fatal_error_jmpbuf ;
4445volatile uint32_t magic [2 ] __attribute__((section (".noinit" )));
46+ static void adc_init ();
4547
4648void platform_init (void )
4749{
@@ -144,6 +146,7 @@ void platform_init(void)
144146
145147 /* By default, do not drive the SWD bus too fast. */
146148 platform_max_frequency_set (2000000 );
149+ adc_init ();
147150}
148151
149152void platform_nrst_set_val (bool assert )
@@ -156,9 +159,41 @@ bool platform_nrst_get_val(void)
156159 return gpio_get (NRST_PORT , NRST_PIN ) == 0 ;
157160}
158161
162+ static void adc_init (void )
163+ {
164+ rcc_periph_clock_enable (RCC_ADC1 );
165+ gpio_mode_setup (GPIOA , GPIO_MODE_ANALOG , GPIO_PUPD_NONE , GPIO0 );
166+ adc_power_off (ADC1 );
167+ adc_disable_scan_mode (ADC1 );
168+ adc_set_sample_time (ADC1 , ADC_CHANNEL0 , ADC_SMPR_SMP_480CYC );
169+ adc_power_on (ADC1 );
170+ }
171+
172+ static uint16_t platform_adc_read (void )
173+ {
174+ const uint8_t channel = ADC_CHANNEL0 ;
175+ adc_set_regular_sequence (ADC1 , 1 , & channel );
176+ adc_start_conversion_regular (ADC1 );
177+ while (!adc_eoc (ADC1 ))
178+ continue ;
179+ uint32_t value = adc_read_regular (ADC1 );
180+ return value ;
181+ }
182+
159183const char * platform_target_voltage (void )
160184{
161- return "Unknown" ;
185+ static char msg [8 ] = "0.000V" ;
186+ const uint16_t vtref_sample = platform_adc_read ();
187+ /* Convert 0-4095 full-scale code to 0-3300 integer millivolts */
188+ const uint32_t vtref_mv = vtref_sample * 3300U / 4095U ;
189+ /* Avoid printf_float */
190+ //utoa_upper(vtref_mv, vtref_dec, 10);
191+ msg [0 ] = '0' + vtref_mv / 1000U ;
192+ msg [1 ] = '.' ;
193+ msg [2 ] = '0' + vtref_mv % 1000U / 100U ;
194+ msg [3 ] = '0' + vtref_mv % 100U / 10U ;
195+ msg [4 ] = '0' + vtref_mv % 10U ;
196+ return msg ;
162197}
163198
164199/*
0 commit comments