diff options
Diffstat (limited to 'ports/stm32/adc.c')
-rw-r--r-- | ports/stm32/adc.c | 93 |
1 files changed, 56 insertions, 37 deletions
diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 3549fc29a9..f47e9eaad7 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -51,7 +51,7 @@ /// val = adc.read_core_vref() # read MCU VREF /* ADC definitions */ -#if defined(STM32H5) +#if defined(STM32H5) || defined(STM32N6) // STM32H5 features two ADC instances, ADCx and pin_adc_table are set dynamically #define PIN_ADC_MASK (PIN_ADC1 | PIN_ADC2) #else @@ -107,12 +107,12 @@ #define ADC_CAL2 ((uint16_t *)(ADC_CAL_ADDRESS + 4)) #define ADC_CAL_BITS (12) -#elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) +#elif defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L1) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) #define ADC_SCALE_V (((float)VREFINT_CAL_VREF) / 1000.0f) -#define ADC_CAL_ADDRESS VREFINT_CAL_ADDR -#define ADC_CAL1 TEMPSENSOR_CAL1_ADDR -#define ADC_CAL2 TEMPSENSOR_CAL2_ADDR +#define ADC_CAL_ADDRESS (VREFINT_CAL_ADDR) +#define ADC_CAL1 (TEMPSENSOR_CAL1_ADDR) +#define ADC_CAL2 (TEMPSENSOR_CAL2_ADDR) #define ADC_CAL_BITS (12) // UM2319/UM2570, __HAL_ADC_CALC_TEMPERATURE: 'corresponds to a resolution of 12 bits' #elif defined(STM32H7) @@ -123,22 +123,6 @@ #define ADC_CAL2 ((uint16_t *)(0x1FF1E840)) #define ADC_CAL_BITS (16) -#elif defined(STM32L1) - -#define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f) -#define ADC_CAL_ADDRESS (VREFINT_CAL_ADDR) -#define ADC_CAL1 (TEMPSENSOR_CAL1_ADDR) -#define ADC_CAL2 (TEMPSENSOR_CAL2_ADDR) -#define ADC_CAL_BITS (12) - -#elif defined(STM32L4) || defined(STM32WB) - -#define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f) -#define ADC_CAL_ADDRESS (VREFINT_CAL_ADDR) -#define ADC_CAL1 (TEMPSENSOR_CAL1_ADDR) -#define ADC_CAL2 (TEMPSENSOR_CAL2_ADDR) -#define ADC_CAL_BITS (12) - #else #error Unsupported processor @@ -182,6 +166,9 @@ #define VBAT_DIV (3) #elif defined(STM32L152xE) // STM32L152xE does not have vbat. +#elif defined(STM32N6) +// ADC2 VINP 16 +#define VBAT_DIV (4) #else #error Unsupported processor #endif @@ -263,7 +250,7 @@ static bool is_adcx_channel(int channel) { handle.Instance = ADCx; return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || IS_ADC_CHANNEL(&handle, __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); - #elif defined(STM32H5) + #elif defined(STM32H5) || defined(STM32N6) // The first argument to the IS_ADC_CHANNEL macro is unused. return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) || IS_ADC_CHANNEL(NULL, __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); @@ -276,7 +263,7 @@ static void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t ti uint32_t tickstart = HAL_GetTick(); #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { #else #error Unsupported processor @@ -295,7 +282,7 @@ static void adcx_clock_enable(ADC_HandleTypeDef *adch) { __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); #elif defined(STM32G0) __HAL_RCC_ADC_CLK_ENABLE(); - #elif defined(STM32G4) + #elif defined(STM32G4) || defined(STM32N6) __HAL_RCC_ADC12_CLK_ENABLE(); #elif defined(STM32H5) __HAL_RCC_ADC_CLK_ENABLE(); @@ -368,6 +355,15 @@ static void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.OversamplingMode = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; adch->Init.DMAContinuousRequests = DISABLE; + #elif defined(STM32N6) + adch->Init.GainCompensation = 0; + adch->Init.ScanConvMode = ADC_SCAN_DISABLE; + adch->Init.LowPowerAutoWait = DISABLE; + adch->Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL; + adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; + adch->Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; + adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; + adch->Init.OversamplingMode = DISABLE; #else #error Unsupported processor #endif @@ -400,7 +396,7 @@ static void adc_init_single(pyb_obj_adc_t *adc_obj, ADC_TypeDef *adc) { static void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) { ADC_ChannelConfTypeDef sConfig; - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) sConfig.Rank = ADC_REGULAR_RANK_1; if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel) == 0) { channel = __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel); @@ -432,7 +428,7 @@ static void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES; } else { - sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES; + sConfig.SamplingTime = ADC_SAMPLETIME_16CYCLES; } #elif defined(STM32G0) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { @@ -449,6 +445,18 @@ static void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; + #elif defined(STM32N6) + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { + sConfig.SamplingTime = ADC_SAMPLETIME_246CYCLES_5; + } else { + sConfig.SamplingTime = ADC_SAMPLETIME_11CYCLES_5; + } + sConfig.SingleDiff = ADC_SINGLE_ENDED; + sConfig.OffsetNumber = ADC_OFFSET_NONE; + sConfig.Offset = 0; + sConfig.OffsetSignedSaturation = DISABLE; + sConfig.OffsetSaturation = DISABLE; + sConfig.OffsetSign = ADC_OFFSET_SIGN_POSITIVE; #else #error Unsupported processor #endif @@ -464,10 +472,13 @@ static void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) static uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) { uint32_t value; - #if defined(STM32G4) - // For STM32G4 there is errata 2.7.7, "Wrong ADC result if conversion done late after - // calibration or previous conversion". According to the errata, this can be avoided - // by performing two consecutive ADC conversions and keeping the second result. + #if defined(STM32G4) || defined(STM32WB) + // For STM32G4 errata 2.7.7 / STM32WB errata 2.7.1: + // "Wrong ADC result if conversion done late after calibration or previous conversion" + // states an incorrect reading is returned if more than 1ms has elapsed since the last + // reading or calibration. According to the errata, this can be avoided by performing + // two consecutive ADC conversions and keeping the second result. + // Note: On STM32WB55 @ 64Mhz each ADC read takes ~ 3us. for (uint8_t i = 0; i < 2; i++) #endif { @@ -523,7 +534,7 @@ 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) + #if defined(STM32H5) || defined(STM32N6) // 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; @@ -540,7 +551,7 @@ 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 defined(STM32H5) || defined(STM32N6) if ((pin->adc_num & PIN_ADC2) == PIN_ADC2) { adc = ADC2; pin_adc_table = pin_adc2; @@ -555,7 +566,7 @@ 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 defined(STM32H5) || defined(STM32N6) if (channel < num_adc_pins) { const machine_pin_obj_t *pin = pin_adc_table[channel]; if (pin != NULL) { @@ -576,7 +587,7 @@ static mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ o->base.type = &pyb_adc_type; o->pin_name = pin_obj; o->channel = channel; - #if defined(STM32H5) + #if defined(STM32H5) || defined(STM32N6) adc_init_single(o, adc); #else adc_init_single(o, ADCx); @@ -667,7 +678,7 @@ static mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_ // for subsequent samples we can just set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor @@ -777,7 +788,7 @@ static mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_i // ADC is started: set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1) adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; - #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32H7) || defined(STM32L4) || defined(STM32N6) || defined(STM32WB) SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor @@ -911,6 +922,8 @@ int adc_read_core_temp(ADC_HandleTypeDef *adcHandle) { } else { return 0; } + #elif defined(STM32N6) + int32_t raw_value = 0; // TODO #else int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR); #endif @@ -922,6 +935,10 @@ int adc_read_core_temp(ADC_HandleTypeDef *adcHandle) { static volatile float adc_refcor = 1.0f; float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { + #if defined(STM32N6) + return 0.0f; // TODO + #else + #if defined(STM32G4) || defined(STM32L1) || defined(STM32L4) // Update the reference correction factor before reading tempsensor // because TS_CAL1 and TS_CAL2 of STM32G4,L1/L4 are at VDDA=3.0V @@ -936,7 +953,7 @@ 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) + #elif defined(STM32H5) || defined(STM32WB) 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 @@ -944,6 +961,8 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) { float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 80.0f; #endif return (((float)raw_value * adc_refcor - *ADC_CAL1) / core_temp_avg_slope) + 30.0f; + + #endif } float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) { |