Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 49 additions & 7 deletions ports/stm32/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,14 @@
/// val = adc.read_core_vref() # read MCU VREF

/* ADC definitions */
#if defined(STM32H5)
// STM32H5 features two ADC instances, ADCx and pin_adc_table are set dynamically
#define PIN_ADC_MASK (PIN_ADC1 | PIN_ADC2)
#else
#define ADCx (ADC1)
#define PIN_ADC_MASK PIN_ADC1
#define pin_adc_table pin_adc1
#endif

#if defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || \
defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
Expand Down Expand Up @@ -352,7 +357,7 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) {
adch->Init.DataAlign = ADC_DATAALIGN_RIGHT;
adch->Init.DMAContinuousRequests = DISABLE;
#elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB)
#if defined(STM32G4)
#if defined(STM32G4) || defined(STM32H5)
adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
#else
adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
Expand All @@ -379,8 +384,8 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) {
#endif
}

STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
adc_obj->handle.Instance = ADCx;
STATIC void adc_init_single(pyb_obj_adc_t *adc_obj, ADC_TypeDef *adc) {
adc_obj->handle.Instance = adc;
adcx_init_periph(&adc_obj->handle, ADC_RESOLUTION_12B);

#if (defined(STM32G4) || defined(STM32L4)) && defined(ADC_DUALMODE_REGSIMULT_INJECSIMULT)
Expand All @@ -395,7 +400,7 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) {
ADC_ChannelConfTypeDef sConfig;

#if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
sConfig.Rank = ADC_REGULAR_RANK_1;
if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel) == 0) {
channel = __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel);
Expand Down Expand Up @@ -439,7 +444,7 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel)
if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) {
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
} else {
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5;
}
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
Expand Down Expand Up @@ -495,7 +500,15 @@ STATIC uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32

STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_obj_adc_t *self = MP_OBJ_TO_PTR(self_in);
#if defined STM32H5
unsigned adc_id = 1;
if (self->handle.Instance == ADC2) {
adc_id = 2;
}
mp_printf(print, "<ADC%u on ", adc_id);
#else
mp_print_str(print, "<ADC on ");
#endif
mp_obj_print_helper(print, self->pin_name, PRINT_STR);
mp_printf(print, " channel=%u>", self->channel);
}
Expand All @@ -510,6 +523,13 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
// 1st argument is the pin name
mp_obj_t pin_obj = args[0];

#if defined(STM32H5)
// STM32H5 has two ADC instances where some pins are only available on ADC1 or ADC2 (but not both).
// Assume we're using a channel of ADC1. Can be overridden for ADC2 later in this function.
ADC_TypeDef *adc = ADC1;
const pin_obj_t *const *pin_adc_table = pin_adc1;
uint32_t num_adc_pins = MP_ARRAY_SIZE(pin_adc1);
#endif
uint32_t channel;

if (mp_obj_is_int(pin_obj)) {
Expand All @@ -520,6 +540,13 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
// No ADC function on the given pin.
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Pin(%q) doesn't have ADC capabilities"), pin->name);
}
#if defined(STM32H5)
if ((pin->adc_num & PIN_ADC2) == PIN_ADC2) {
adc = ADC2;
pin_adc_table = pin_adc2;
num_adc_pins = MP_ARRAY_SIZE(pin_adc2);
}
#endif
channel = pin->adc_channel;
}

Expand All @@ -528,20 +555,32 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
}

// If this channel corresponds to a pin then configure the pin in ADC mode.
#if defined(STM32H5)
if (channel < num_adc_pins) {
const pin_obj_t *pin = pin_adc_table[channel];
if (pin != NULL) {
mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0);
}
}
#else
if (channel < MP_ARRAY_SIZE(pin_adc_table)) {
const pin_obj_t *pin = pin_adc_table[channel];
if (pin != NULL) {
mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0);
}
}
#endif

pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t);
memset(o, 0, sizeof(*o));
o->base.type = &pyb_adc_type;
o->pin_name = pin_obj;
o->channel = channel;
adc_init_single(o);

#if defined(STM32H5)
adc_init_single(o, adc);
#else
adc_init_single(o, ADCx);
#endif
return MP_OBJ_FROM_PTR(o);
}

Expand Down Expand Up @@ -897,6 +936,9 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) {
return 0;
}
float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 100.0f;
#elif defined(STM32H5)
int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR);
float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 100.0f;
#else
int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR);
float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 80.0f;
Expand Down