diff --git a/stmhal/Makefile b/stmhal/Makefile index b146a1b37b..7896849c63 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -93,10 +93,10 @@ SRC_C = \ accel.c \ servo.c \ dac.c \ + adc.c \ # timer.c \ # i2c.c \ -# adc.c \ # pybwlan.c \ SRC_S = \ @@ -105,6 +105,8 @@ SRC_S = \ SRC_HAL = $(addprefix $(HAL_DIR)/src/,\ stm32f4xx_hal.c \ + stm32f4xx_hal_adc.c \ + stm32f4xx_hal_adc_ex.c \ stm32f4xx_hal_cortex.c \ stm32f4xx_hal_dac.c \ stm32f4xx_hal_dac_ex.c \ diff --git a/stmhal/adc.c b/stmhal/adc.c new file mode 100644 index 0000000000..dd9e299117 --- /dev/null +++ b/stmhal/adc.c @@ -0,0 +1,322 @@ +#include +#include +#include + +#include "misc.h" +#include "nlr.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "adc.h" +#include "pin.h" +#include "build/pins.h" + +// Usage Model: +// +// adc = pyb.ADC(pin) +// val = adc.read() +// +// adc = pyb.ADC_all(resolution) +// val = adc.read_channel(channel) +// val = adc.read_core_temp() +// val = adc.read_core_vbat() +// val = adc.read_core_vref() + +/* ADC defintions */ +#define ADCx (ADC1) +#define ADCx_CLK_ENABLE __ADC1_CLK_ENABLE +#define ADC_NUM_CHANNELS (19) +#define ADC_NUM_GPIO_CHANNELS (16) + +#if defined(STM32F405xx) || defined(STM32F415xx) || \ + defined(STM32F407xx) || defined(STM32F417xx) || \ + defined(STM32F401xC) || defined(STM32F401xE) +#define VBAT_DIV (2) +#elif defined(STM32F427xx) || defined(STM32F429xx) || \ + defined(STM32F437xx) || defined(STM32F439xx) +#define VBAT_DIV (4) +#endif + +/* Core temperature sensor definitions */ +#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */ +#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */ + +typedef struct _pyb_obj_adc_t { + mp_obj_base_t base; + mp_obj_t pin_name; + int channel; + ADC_HandleTypeDef handle; +} pyb_obj_adc_t; + +void adc_init_single(pyb_obj_adc_t *adc_obj) { + if (!IS_ADC_CHANNEL(adc_obj->channel)) { + return; + } + + if (adc_obj->channel < ADC_NUM_GPIO_CHANNELS) { + // Channels 0-16 correspond to real pins. Configure the GPIO pin in + // ADC mode. + const pin_obj_t *pin = pin_adc1[adc_obj->channel]; + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Pin = pin->pin_mask; + GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure); + } + + ADCx_CLK_ENABLE(); + + ADC_HandleTypeDef *adcHandle = &adc_obj->handle; + adcHandle->Instance = ADCx; + adcHandle->Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; + adcHandle->Init.Resolution = ADC_RESOLUTION12b; + adcHandle->Init.ScanConvMode = DISABLE; + adcHandle->Init.ContinuousConvMode = DISABLE; + adcHandle->Init.DiscontinuousConvMode = DISABLE; + adcHandle->Init.NbrOfDiscConversion = 0; + adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; + adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT; + adcHandle->Init.NbrOfConversion = 1; + adcHandle->Init.DMAContinuousRequests = DISABLE; + adcHandle->Init.EOCSelection = DISABLE; + + HAL_ADC_Init(adcHandle); + + ADC_ChannelConfTypeDef sConfig; + + sConfig.Channel = adc_obj->channel; + sConfig.Rank = 1; + sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; + sConfig.Offset = 0; + + HAL_ADC_ConfigChannel(adcHandle, &sConfig); +} + +uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) +{ + uint32_t rawValue = 0; + + HAL_ADC_Start(adcHandle); + if (HAL_ADC_PollForConversion(adcHandle, 10) == HAL_OK) \ + && HAL_ADC_GetState(adcHandle) == HAL_ADC_STATE_EOC_REG) { + rawValue = HAL_ADC_GetValue(adcHandle); + } + HAL_ADC_Stop(adcHandle); + + return rawValue; +} + +/******************************************************************************/ +/* Micro Python bindings : adc object (single channel) */ + +static void adc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { + pyb_obj_adc_t *self = self_in; + print(env, "pin_name, PRINT_STR); + print(env, " channel=%lu>", self->channel); +} + +static mp_obj_t adc_read(mp_obj_t self_in) { + pyb_obj_adc_t *self = self_in; + + uint32_t data = adc_read_channel(&self->handle); + return mp_obj_new_int(data); +} + +static MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read); + +static const mp_method_t adc_methods[] = { + { "read", &adc_read_obj}, + { NULL, NULL }, +}; + +static const mp_obj_type_t adc_type = { + { &mp_type_type }, + .name = MP_QSTR_ADC, + .print = adc_print, + .methods = adc_methods, +}; + +mp_obj_t pyb_ADC(mp_obj_t pin_obj) { + + uint32_t channel; + + if (MP_OBJ_IS_INT(pin_obj)) { + channel = mp_obj_get_int(pin_obj); + } else { + const pin_obj_t *pin = pin_map_user_obj(pin_obj); + if ((pin->adc_num & PIN_ADC1) == 0) { + // No ADC1 function on that pin + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have ADC capabilities", pin->name)); + } + channel = pin->adc_channel; + } + + if (!IS_ADC_CHANNEL(channel)) { + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Not a valid ADC Channel: %d", channel)); + } + if (pin_adc1[channel] == NULL) { + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Channel %d not available on this board", channel)); + } + + pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t); + memset(o, 0, sizeof(*o)); + o->base.type = &adc_type; + o->pin_name = pin_obj; + o->channel = channel; + adc_init_single(o); + + return o; +} + +MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_obj, pyb_ADC); + +/******************************************************************************/ +/* adc all object */ + +typedef struct _pyb_obj_adc_all_t { + mp_obj_base_t base; + ADC_HandleTypeDef handle; +} pyb_obj_adc_all_t; + +void adc_init_all(pyb_obj_adc_all_t *adc_all, uint32_t resolution) { + + switch (resolution) { + case 6: resolution = ADC_RESOLUTION6b; break; + case 8: resolution = ADC_RESOLUTION8b; break; + case 10: resolution = ADC_RESOLUTION10b; break; + case 12: resolution = ADC_RESOLUTION12b; break; + default: + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "resolution %d not supported", resolution)); + } + + for (uint32_t channel = 0; channel < ADC_NUM_GPIO_CHANNELS; channel++) { + // Channels 0-16 correspond to real pins. Configure the GPIO pin in + // ADC mode. + const pin_obj_t *pin = pin_adc1[channel]; + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Pin = pin->pin_mask; + GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure); + } + + ADCx_CLK_ENABLE(); + + ADC_HandleTypeDef *adcHandle = &adc_all->handle; + adcHandle->Instance = ADCx; + adcHandle->Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; + adcHandle->Init.Resolution = resolution; + adcHandle->Init.ScanConvMode = DISABLE; + adcHandle->Init.ContinuousConvMode = DISABLE; + adcHandle->Init.DiscontinuousConvMode = DISABLE; + adcHandle->Init.NbrOfDiscConversion = 0; + adcHandle->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + adcHandle->Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; + adcHandle->Init.DataAlign = ADC_DATAALIGN_RIGHT; + adcHandle->Init.NbrOfConversion = 1; + adcHandle->Init.DMAContinuousRequests = DISABLE; + adcHandle->Init.EOCSelection = DISABLE; + + HAL_ADC_Init(adcHandle); +} + +uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32_t channel) +{ + ADC_ChannelConfTypeDef sConfig; + sConfig.Channel = channel; + sConfig.Rank = 1; + sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; + sConfig.Offset = 0; + HAL_ADC_ConfigChannel(adcHandle, &sConfig); + + return adc_read_channel(adcHandle); +} + +int adc_read_core_temp(ADC_HandleTypeDef *adcHandle) +{ + int32_t raw_value = adc_config_and_read_channel(adcHandle, ADC_CHANNEL_TEMPSENSOR); + + return ((raw_value - CORE_TEMP_V25) / CORE_TEMP_AVG_SLOPE) + 25; +} + +float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) +{ + uint32_t raw_value = adc_config_and_read_channel(adcHandle, ADC_CHANNEL_VBAT); + + return raw_value * VBAT_DIV / 4096.0f * 3.3f; +} + +float adc_read_core_vref(ADC_HandleTypeDef *adcHandle) +{ + uint32_t raw_value = adc_config_and_read_channel(adcHandle, ADC_CHANNEL_VREFINT); + + return raw_value * VBAT_DIV / 4096.0f * 3.3f; +} + +/******************************************************************************/ +/* Micro Python bindings : adc_all object */ + +static void adc_all_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { + print(env, ""); +} + +static mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) { + pyb_obj_adc_all_t *self = self_in; + + uint32_t chan = mp_obj_get_int(channel); + uint32_t data = adc_config_and_read_channel(&self->handle, chan); + return mp_obj_new_int(data); +} + +static mp_obj_t adc_all_read_core_temp(mp_obj_t self_in) { + pyb_obj_adc_all_t *self = self_in; + + int data = adc_read_core_temp(&self->handle); + return mp_obj_new_int(data); +} + +static mp_obj_t adc_all_read_core_vbat(mp_obj_t self_in) { + pyb_obj_adc_all_t *self = self_in; + + float data = adc_read_core_vbat(&self->handle); + return mp_obj_new_float(data); +} + +static mp_obj_t adc_all_read_core_vref(mp_obj_t self_in) { + pyb_obj_adc_all_t *self = self_in; + + float data = adc_read_core_vref(&self->handle); + return mp_obj_new_float(data); +} + +static MP_DEFINE_CONST_FUN_OBJ_2(adc_all_read_channel_obj, adc_all_read_channel); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_temp_obj, adc_all_read_core_temp); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vbat_obj, adc_all_read_core_vbat); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vref_obj, adc_all_read_core_vref); + +static const mp_method_t adc_all_methods[] = { + { "read_channel", &adc_all_read_channel_obj}, + { "read_core_temp", &adc_all_read_core_temp_obj}, + { "read_core_vbat", &adc_all_read_core_vbat_obj}, + { "read_core_vref", &adc_all_read_core_vref_obj}, + { NULL, NULL }, +}; + +static const mp_obj_type_t adc_all_type = { + { &mp_type_type }, + .name = MP_QSTR_ADC, + .print = adc_all_print, + .methods = adc_all_methods, +}; + +mp_obj_t pyb_ADC_all(mp_obj_t resolution) { + pyb_obj_adc_all_t *o = m_new_obj(pyb_obj_adc_all_t); + o->base.type = &adc_all_type; + adc_init_all(o, mp_obj_get_int(resolution)); + return o; +} + +MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_all_obj, pyb_ADC_all); diff --git a/stmhal/adc.h b/stmhal/adc.h new file mode 100644 index 0000000000..502da20dde --- /dev/null +++ b/stmhal/adc.h @@ -0,0 +1,2 @@ +MP_DECLARE_CONST_FUN_OBJ(pyb_ADC_all_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_ADC_obj); diff --git a/stmhal/boards/make-pins.py b/stmhal/boards/make-pins.py index 8c1bedbf0c..ee11934985 100755 --- a/stmhal/boards/make-pins.py +++ b/stmhal/boards/make-pins.py @@ -94,6 +94,8 @@ class Pin(object): self.alt_fn = [] self.board_name = None self.alt_fn_count = 0 + self.adc_num = 0 + self.adc_channel = 0 def port_letter(self): return chr(self.port + ord('A')) @@ -101,6 +103,15 @@ class Pin(object): def pin_name(self): return '{:s}{:d}'.format(self.port_letter(), self.pin) + def parse_adc(self, adc_str): + if (adc_str[:3] != 'ADC'): + return + (adc,channel) = adc_str.split('_') + for idx in range(3, len(adc)): + adc_num = int(adc[idx]) # 1, 2, or 3 + self.adc_num |= (1 << (adc_num - 1)) + self.adc_channel = int(channel[2:]) + def parse_af(self, af_idx, af_strs_in): if len(af_strs_in) == 0: return @@ -113,10 +124,22 @@ class Pin(object): if alt_fn.is_supported(): self.alt_fn_count += 1 - def alt_fn_name(self): - if self.alt_fn_count > 0: - return 'pin_{:s}_af'.format(self.pin_name()) - return 'NULL' + def alt_fn_name(self, null_if_0=False): + if null_if_0 and self.alt_fn_count == 0: + return 'NULL' + return 'pin_{:s}_af'.format(self.pin_name()) + + def adc_num_str(self): + str = '' + for adc_num in range(1,4): + if self.adc_num & (1 << (adc_num - 1)): + if len(str) > 0: + str += ' | ' + str += 'PIN_ADC' + str += chr(ord('0') + adc_num) + if len(str) == 0: + str = '0' + return str def print(self): if self.alt_fn_count == 0: @@ -128,9 +151,10 @@ class Pin(object): print("// ", end='') print('};') print('') - print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s});'.format( + print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s}, {:s}, {:d});'.format( self.pin_name(), self.port_letter(), self.pin, - self.alt_fn_count, self.alt_fn_name())) + self.alt_fn_count, self.alt_fn_name(null_if_0=True), + self.adc_num_str(), self.adc_channel)) print('') def print_header(self, hdr_file): @@ -162,7 +186,10 @@ class Pins(object): continue pin = Pin(port_num, pin_num) for af_idx in range(af_col, len(row)): - pin.parse_af(af_idx - af_col, row[af_idx]) + if af_idx < af_col + 16: + pin.parse_af(af_idx - af_col, row[af_idx]) + elif af_idx == af_col + 16: + pin.parse_adc(row[af_idx]) self.pins.append(pin) def parse_board_file(self, filename): @@ -198,11 +225,30 @@ class Pins(object): print('') self.print_named('board', self.board_pins) + def print_adc(self, adc_num): + print(''); + print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num)) + for channel in range(16): + adc_found = False + for pin in self.pins: + if (pin.board_name and + (pin.adc_num & (1 << (adc_num - 1))) and (pin.adc_channel == channel)): + print(' &pin_{:s}, // {:d}'.format(pin.pin_name(), channel)) + adc_found = True + break + if not adc_found: + print(' NULL, // {:d}'.format(channel)) + print('};') + + def print_header(self, hdr_filename): with open(hdr_filename, 'wt') as hdr_file: for pin in self.pins: if pin.board_name: pin.print_header(hdr_file) + hdr_file.write('extern const pin_obj_t * const pin_adc1[];\n') + hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n') + hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n') def main(): @@ -254,6 +300,9 @@ def main(): with open(args.prefix_filename, 'r') as prefix_file: print(prefix_file.read()) pins.print() + pins.print_adc(1) + pins.print_adc(2) + pins.print_adc(3) pins.print_header(args.hdr_filename) diff --git a/stmhal/boards/stm32f4xx-af.csv b/stmhal/boards/stm32f4xx-af.csv index fde7fcfc11..0a21fc87d6 100644 --- a/stmhal/boards/stm32f4xx-af.csv +++ b/stmhal/boards/stm32f4xx-af.csv @@ -1,13 +1,13 @@ Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15 -,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,, -PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT -PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT -PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT -PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUT -PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT -PortA,PA5,,TIM2_CH1_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT -PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCK,,EVENTOUT -PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT +,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,,,ADC +PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0 +PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT,ADC123_IN1 +PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT,ADC123_IN2 +PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUTADC123_IN3 +PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT,ADC12_IN4 +PortA,PA5,,TIM2_CH1_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5 +PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCK,,EVENTOUT,ADC12_IN6 +PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT,ADC12_IN7 PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT @@ -16,8 +16,8 @@ PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT PortA,PA13,JTMS-SWDIO,,,,,,,,,,,,,,,EVENTOUT PortA,PA14,JTCK-SWCLK,,,,,,,,,,,,,,,EVENTOUT PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT -PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT -PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT +PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,,,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,AC12_IN8 +PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT,ADC12_IN9 PortB,PB2,,,,,,,,,,,,,,,,EVENTOUT PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCKI2S3_CK,,,,,,,,,EVENTOUT PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,,,,,,,,EVENTOUT @@ -32,12 +32,12 @@ PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_UL PortB,PB13,,TIM1_CH1N,,,,SPI2_SCKI2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,I2S2ext_SD,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT -PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,,,,EVENTOUT -PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT -PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,,,,EVENTOUT -PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,,,,EVENTOUT -PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT -PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT +PortC,PC0,,,,,,,,,,,OTG_HS_ULPI_STP,,,,,EVENTOUT,ADC123_IN10 +PortC,PC1,,,,,,,,,,,,ETH_MDC,,,,EVENTOUT,ADC123_IN11 +PortC,PC2,,,,,,SPI2_MISO,I2S2ext_SD,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,,,,EVENTOUT,ADC123_IN12 +PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,,,,EVENTOUT,ADC123_IN13 +PortC,PC4,,,,,,,,,,,,ETH_MII_RXD0/ETH_RMII_RXD0,,,,EVENTOUT,ADC123_IN14 +PortC,PC5,,,,,,,,,,,,ETH_MII_RXD1/ETH_RMII_RXD1,,,,EVENTOUT,ADC123_IN15 PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,,EVENTOUT PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDIO_D7,DCMI_D1,,EVENTOUT PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT @@ -83,14 +83,14 @@ PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FSMC_D12,,,EVENTOUT PortF,PF0,,,,,I2C2_SDA,,,,,,,,FSMC_A0,,,EVENTOUT PortF,PF1,,,,,I2C2_SCL,,,,,,,,FSMC_A1,,,EVENTOUT PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FSMC_A2,,,EVENTOUT -PortF,PF3,,,,,,,,,,,,,FSMC_A3,,,EVENTOUT -PortF,PF4,,,,,,,,,,,,,FSMC_A4,,,EVENTOUT -PortF,PF5,,,,,,,,,,,,,FSMC_A5,,,EVENTOUT -PortF,PF6,,,,TIM10_CH1,,,,,,,,,FSMC_NIORD,,,EVENTOUT -PortF,PF7,,,,TIM11_CH1,,,,,,,,,FSMC_NREG,,,EVENTOUT -PortF,PF8,,,,,,,,,,TIM13_CH1,,,FSMC_NIOWR,,,EVENTOUT -PortF,PF9,,,,,,,,,,TIM14_CH1,,,FSMC_CD,,,EVENTOUT -PortF,PF10,,,,,,,,,,,,,FSMC_INTR,,,EVENTOUT +PortF,PF3,,,,,,,,,,,,,FSMC_A3,,,EVENTOUT,ADC3_IN9 +PortF,PF4,,,,,,,,,,,,,FSMC_A4,,,EVENTOUT,ADC3_IN14 +PortF,PF5,,,,,,,,,,,,,FSMC_A5,,,EVENTOUT,ADC3_IN15 +PortF,PF6,,,,TIM10_CH1,,,,,,,,,FSMC_NIORD,,,EVENTOUT,ADC3_IN4 +PortF,PF7,,,,TIM11_CH1,,,,,,,,,FSMC_NREG,,,EVENTOUT,ADC3_IN5 +PortF,PF8,,,,,,,,,,TIM13_CH1,,,FSMC_NIOWR,,,EVENTOUT,ADC3_IN6 +PortF,PF9,,,,,,,,,,TIM14_CH1,,,FSMC_CD,,,EVENTOUT,ADC3_IN7 +PortF,PF10,,,,,,,,,,,,,FSMC_INTR,,,EVENTOUT,ADC3_IN8 PortF,PF11,,,,,,,,,,,,,,DCMI_D12,,EVENTOUT PortF,PF12,,,,,,,,,,,,,FSMC_A6,,,EVENTOUT PortF,PF13,,,,,,,,,,,,,FSMC_A7,,,EVENTOUT diff --git a/stmhal/boards/stm32f4xx-prefix.c b/stmhal/boards/stm32f4xx-prefix.c index af3ed325cb..989b8f0048 100644 --- a/stmhal/boards/stm32f4xx-prefix.c +++ b/stmhal/boards/stm32f4xx-prefix.c @@ -21,7 +21,7 @@ .af_fn = (af_ptr) \ } -#define PIN(p_port, p_pin, p_num_af, p_af) \ +#define PIN(p_port, p_pin, p_num_af, p_af, p_adc_num, p_adc_channel) \ { \ { &pin_obj_type }, \ .name = #p_port #p_pin, \ @@ -31,4 +31,6 @@ .pin_mask = (1 << ((p_pin) & 0x0f)), \ .gpio = GPIO ## p_port, \ .af = p_af, \ + .adc_num = p_adc_num, \ + .adc_channel = p_adc_channel, \ } diff --git a/stmhal/exti.c b/stmhal/exti.c index ec6d82e4fd..8aaa99d429 100644 --- a/stmhal/exti.c +++ b/stmhal/exti.c @@ -26,9 +26,7 @@ // def callback(line): // print("line =", line) // -// # Configure the pin as a GPIO input. -// pin = pyb.Pin.board.X1 -// pyb.gpio_in(pin, pyb.PULL_UP) +// # Note: Exti will automatically configure the gpio line as an input. // exti = pyb.Exti(pin, pyb.Exti.MODE_IRQ_FALLING, pyb.PULLUP, callback) // // Now every time a falling edge is seen on the X1 pin, the callback will be diff --git a/stmhal/pin.h b/stmhal/pin.h index d5d769058a..2aa50655b4 100644 --- a/stmhal/pin.h +++ b/stmhal/pin.h @@ -50,6 +50,12 @@ enum { AF_PIN_TYPE_SPI_NSS, }; +enum { + PIN_ADC1 = (1 << 0), + PIN_ADC2 = (1 << 1), + PIN_ADC3 = (1 << 2), +}; + typedef struct { mp_obj_base_t base; uint8_t idx; @@ -70,9 +76,11 @@ typedef struct { typedef struct { mp_obj_base_t base; const char *name; - uint16_t port : 4; - uint16_t pin : 4; - uint16_t num_af : 4; + uint16_t port : 4; + uint16_t pin : 4; + uint16_t num_af : 4; + uint16_t adc_channel : 4; + uint16_t adc_num : 3; // 1 bit per ADC uint16_t pin_mask; GPIO_TypeDef *gpio; const pin_af_obj_t *af; diff --git a/stmhal/pybmodule.c b/stmhal/pybmodule.c index f67b1c03a5..7a4408bc21 100644 --- a/stmhal/pybmodule.c +++ b/stmhal/pybmodule.c @@ -20,6 +20,7 @@ #include "rng.h" #include "rtc.h" #include "usart.h" +#include "adc.h" #include "storage.h" #include "sdcard.h" #include "accel.h" @@ -28,7 +29,6 @@ #if 0 #include "usb.h" #include "i2c.h" -#include "adc.h" #endif #include "pybmodule.h" #include "ff.h" @@ -265,10 +265,8 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_I2C_obj }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_Usart), (mp_obj_t)&pyb_Usart_obj }, -#if 0 { MP_OBJ_NEW_QSTR(MP_QSTR_ADC_all), (mp_obj_t)&pyb_ADC_all_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_ADC_obj }, -#endif #if MICROPY_HW_ENABLE_DAC { MP_OBJ_NEW_QSTR(MP_QSTR_DAC), (mp_obj_t)&pyb_dac_type },