Skip to content

Commit ced2f74

Browse files
Merge pull request #5513 from bcostm/fix_adc_inited
STM32: Initialize ADC peripheral for each AnalogIn object creation
2 parents cfa9e47 + c54e907 commit ced2f74

File tree

11 files changed

+465
-621
lines changed

11 files changed

+465
-621
lines changed

targets/TARGET_STM/TARGET_STM32F0/analogin_api.c renamed to targets/TARGET_STM/TARGET_STM32F0/analogin_device.c

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@
3333
#include "mbed_wait_api.h"
3434
#include "cmsis.h"
3535
#include "pinmap.h"
36-
#include "PeripheralPins.h"
3736
#include "mbed_error.h"
37+
#include "PeripheralPins.h"
38+
#include <stdbool.h>
3839

39-
int adc_inited = 0;
40-
41-
void analogin_init(analogin_t *obj, PinName pin) {
40+
void analogin_init(analogin_t *obj, PinName pin)
41+
{
42+
static bool adc_calibrated = false;
4243
uint32_t function = (uint32_t)NC;
4344

4445
// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
@@ -47,14 +48,14 @@ void analogin_init(analogin_t *obj, PinName pin) {
4748
if ((pin < 0xF0) || (pin >= 0x100)) {
4849
// Normal channels
4950
// Get the peripheral name from the pin and assign it to the object
50-
obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC);
51+
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC);
5152
// Get the functions (adc channel) from the pin and assign it to the object
5253
function = pinmap_function(pin, PinMap_ADC);
5354
// Configure GPIO
5455
pinmap_pinout(pin, PinMap_ADC);
5556
} else {
5657
// Internal channels
57-
obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC_Internal);
58+
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC_Internal);
5859
function = pinmap_function(pin, PinMap_ADC_Internal);
5960
// No GPIO configuration for internal channels
6061
}
@@ -66,40 +67,38 @@ void analogin_init(analogin_t *obj, PinName pin) {
6667
// Save pin number for the read function
6768
obj->pin = pin;
6869

69-
// The ADC initialization is done once
70-
if (adc_inited == 0) {
71-
adc_inited = 1;
72-
73-
// Enable ADC clock
74-
__ADC1_CLK_ENABLE();
75-
76-
// Configure ADC
77-
obj->handle.State = HAL_ADC_STATE_RESET;
78-
obj->handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
79-
obj->handle.Init.Resolution = ADC_RESOLUTION12b;
80-
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
81-
obj->handle.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
82-
obj->handle.Init.EOCSelection = EOC_SINGLE_CONV;
83-
obj->handle.Init.LowPowerAutoWait = DISABLE;
84-
obj->handle.Init.LowPowerAutoPowerOff = DISABLE;
85-
obj->handle.Init.ContinuousConvMode = DISABLE;
86-
obj->handle.Init.DiscontinuousConvMode = DISABLE;
87-
obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
88-
obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
89-
obj->handle.Init.DMAContinuousRequests = DISABLE;
90-
obj->handle.Init.Overrun = OVR_DATA_OVERWRITTEN;
91-
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
92-
error("Cannot initialize ADC");
93-
}
94-
// Run the ADC calibration
95-
if (HAL_ADCEx_Calibration_Start(&obj->handle) != HAL_OK) {
96-
error("Cannot Start ADC_Calibration");
97-
}
70+
// Configure ADC object structures
71+
obj->handle.State = HAL_ADC_STATE_RESET;
72+
obj->handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
73+
obj->handle.Init.Resolution = ADC_RESOLUTION_12B;
74+
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
75+
obj->handle.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
76+
obj->handle.Init.EOCSelection = EOC_SINGLE_CONV;
77+
obj->handle.Init.LowPowerAutoWait = DISABLE;
78+
obj->handle.Init.LowPowerAutoPowerOff = DISABLE;
79+
obj->handle.Init.ContinuousConvMode = DISABLE;
80+
obj->handle.Init.DiscontinuousConvMode = DISABLE;
81+
obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
82+
obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
83+
obj->handle.Init.DMAContinuousRequests = DISABLE;
84+
obj->handle.Init.Overrun = OVR_DATA_OVERWRITTEN;
85+
86+
__HAL_RCC_ADC1_CLK_ENABLE();
87+
88+
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
89+
error("Cannot initialize ADC");
90+
}
91+
92+
// ADC calibration is done only once
93+
if (!adc_calibrated) {
94+
adc_calibrated = true;
95+
HAL_ADCEx_Calibration_Start(&obj->handle);
9896
}
9997
}
10098

101-
static inline uint16_t adc_read(analogin_t *obj) {
102-
ADC_ChannelConfTypeDef sConfig;
99+
uint16_t adc_read(analogin_t *obj)
100+
{
101+
ADC_ChannelConfTypeDef sConfig = {0};
103102

104103
// Configure ADC channel
105104
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
@@ -182,22 +181,10 @@ static inline uint16_t adc_read(analogin_t *obj) {
182181

183182
// Wait end of conversion and get value
184183
if (HAL_ADC_PollForConversion(&obj->handle, 10) == HAL_OK) {
185-
return (HAL_ADC_GetValue(&obj->handle));
184+
return (uint16_t)HAL_ADC_GetValue(&obj->handle);
186185
} else {
187186
return 0;
188187
}
189188
}
190189

191-
uint16_t analogin_read_u16(analogin_t *obj) {
192-
uint16_t value = adc_read(obj);
193-
// 12-bit to 16-bit conversion
194-
value = ((value << 4) & (uint16_t)0xFFF0) | ((value >> 8) & (uint16_t)0x000F);
195-
return value;
196-
}
197-
198-
float analogin_read(analogin_t *obj) {
199-
uint16_t value = adc_read(obj);
200-
return (float)value * (1.0f / (float)0xFFF); // 12 bits range
201-
}
202-
203190
#endif

targets/TARGET_STM/TARGET_STM32F1/analogin_api.c renamed to targets/TARGET_STM/TARGET_STM32F1/analogin_device.c

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@
3535
#include "pinmap.h"
3636
#include "mbed_error.h"
3737
#include "PeripheralPins.h"
38-
39-
int adc_inited = 0;
38+
#include <stdbool.h>
4039

4140
void analogin_init(analogin_t *obj, PinName pin)
4241
{
42+
static bool adc_calibrated = false;
4343
RCC_PeriphCLKInitTypeDef PeriphClkInit;
4444
uint32_t function = (uint32_t)NC;
4545

@@ -49,14 +49,14 @@ void analogin_init(analogin_t *obj, PinName pin)
4949
if ((pin < 0xF0) || (pin >= 0x100)) {
5050
// Normal channels
5151
// Get the peripheral name from the pin and assign it to the object
52-
obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC);
52+
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC);
5353
// Get the functions (adc channel) from the pin and assign it to the object
5454
function = pinmap_function(pin, PinMap_ADC);
5555
// Configure GPIO
5656
pinmap_pinout(pin, PinMap_ADC);
5757
} else {
5858
// Internal channels
59-
obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC_Internal);
59+
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC_Internal);
6060
function = pinmap_function(pin, PinMap_ADC_Internal);
6161
// No GPIO configuration for internal channels
6262
}
@@ -68,13 +68,26 @@ void analogin_init(analogin_t *obj, PinName pin)
6868
// Save pin number for the read function
6969
obj->pin = pin;
7070

71-
// The ADC initialization is done once
72-
if (adc_inited == 0) {
73-
adc_inited = 1;
74-
75-
// Enable ADC clock
76-
__HAL_RCC_ADC1_CLK_ENABLE();
71+
// Enable ADC clock
72+
__HAL_RCC_ADC1_CLK_ENABLE();
73+
74+
// Configure ADC object structures
75+
obj->handle.State = HAL_ADC_STATE_RESET;
76+
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
77+
obj->handle.Init.ScanConvMode = DISABLE;
78+
obj->handle.Init.ContinuousConvMode = DISABLE;
79+
obj->handle.Init.NbrOfConversion = 1;
80+
obj->handle.Init.DiscontinuousConvMode = DISABLE;
81+
obj->handle.Init.NbrOfDiscConversion = 0;
82+
obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
83+
84+
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
85+
error("Cannot initialize ADC");
86+
}
7787

88+
// This section is done only once
89+
if (!adc_calibrated) {
90+
adc_calibrated = true;
7891
// Configure ADC clock prescaler
7992
// Caution: On STM32F1, ADC clock frequency max is 14 MHz (refer to device datasheet).
8093
// Therefore, ADC clock prescaler must be configured in function
@@ -84,29 +97,14 @@ void analogin_init(analogin_t *obj, PinName pin)
8497
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
8598
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
8699
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
87-
88-
// Configure ADC
89-
obj->handle.State = HAL_ADC_STATE_RESET;
90-
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
91-
obj->handle.Init.ScanConvMode = DISABLE;
92-
obj->handle.Init.ContinuousConvMode = DISABLE;
93-
obj->handle.Init.NbrOfConversion = 1;
94-
obj->handle.Init.DiscontinuousConvMode = DISABLE;
95-
obj->handle.Init.NbrOfDiscConversion = 0;
96-
obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
97-
98-
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
99-
error("Cannot initialize ADC\n");
100-
}
101-
102-
// Calibrate ADC
100+
// Calibration
103101
HAL_ADCEx_Calibration_Start(&obj->handle);
104102
}
105103
}
106104

107-
static inline uint16_t adc_read(analogin_t *obj)
105+
uint16_t adc_read(analogin_t *obj)
108106
{
109-
ADC_ChannelConfTypeDef sConfig;
107+
ADC_ChannelConfTypeDef sConfig = {0};
110108

111109
// Configure ADC channel
112110
sConfig.Rank = 1;
@@ -177,24 +175,10 @@ static inline uint16_t adc_read(analogin_t *obj)
177175

178176
// Wait end of conversion and get value
179177
if (HAL_ADC_PollForConversion(&obj->handle, 10) == HAL_OK) {
180-
return (HAL_ADC_GetValue(&obj->handle));
178+
return (uint16_t)HAL_ADC_GetValue(&obj->handle);
181179
} else {
182180
return 0;
183181
}
184182
}
185183

186-
uint16_t analogin_read_u16(analogin_t *obj)
187-
{
188-
uint16_t value = adc_read(obj);
189-
// 12-bit to 16-bit conversion
190-
value = ((value << 4) & (uint16_t)0xFFF0) | ((value >> 8) & (uint16_t)0x000F);
191-
return value;
192-
}
193-
194-
float analogin_read(analogin_t *obj)
195-
{
196-
uint16_t value = adc_read(obj);
197-
return (float)value * (1.0f / (float)0xFFF); // 12 bits range
198-
}
199-
200184
#endif

targets/TARGET_STM/TARGET_STM32F2/analogin_api.c renamed to targets/TARGET_STM/TARGET_STM32F2/analogin_device.c

Lines changed: 25 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,29 +40,20 @@ void analogin_init(analogin_t *obj, PinName pin)
4040
{
4141
uint32_t function = (uint32_t)NC;
4242

43-
#if defined(ADC1)
44-
static int adc1_inited = 0;
45-
#endif
46-
#if defined(ADC2)
47-
static int adc2_inited = 0;
48-
#endif
49-
#if defined(ADC3)
50-
static int adc3_inited = 0;
51-
#endif
5243
// ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...)
5344
// are described in PinNames.h and PeripheralPins.c
5445
// Pin value must be between 0xF0 and 0xFF
5546
if ((pin < 0xF0) || (pin >= 0x100)) {
5647
// Normal channels
5748
// Get the peripheral name from the pin and assign it to the object
58-
obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC);
49+
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC);
5950
// Get the functions (adc channel) from the pin and assign it to the object
6051
function = pinmap_function(pin, PinMap_ADC);
6152
// Configure GPIO
6253
pinmap_pinout(pin, PinMap_ADC);
6354
} else {
6455
// Internal channels
65-
obj->handle.Instance = (ADC_TypeDef *) pinmap_peripheral(pin, PinMap_ADC_Internal);
56+
obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC_Internal);
6657
function = pinmap_function(pin, PinMap_ADC_Internal);
6758
// No GPIO configuration for internal channels
6859
}
@@ -74,55 +65,49 @@ void analogin_init(analogin_t *obj, PinName pin)
7465
// Save pin number for the read function
7566
obj->pin = pin;
7667

77-
// Check if ADC is already initialized
78-
// Enable ADC clock
68+
// Configure ADC object structures
69+
obj->handle.State = HAL_ADC_STATE_RESET;
70+
obj->handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
71+
obj->handle.Init.Resolution = ADC_RESOLUTION_12B;
72+
obj->handle.Init.ScanConvMode = DISABLE;
73+
obj->handle.Init.ContinuousConvMode = DISABLE;
74+
obj->handle.Init.DiscontinuousConvMode = DISABLE;
75+
obj->handle.Init.NbrOfDiscConversion = 0;
76+
obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
77+
obj->handle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
78+
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
79+
obj->handle.Init.NbrOfConversion = 1;
80+
obj->handle.Init.DMAContinuousRequests = DISABLE;
81+
obj->handle.Init.EOCSelection = DISABLE;
82+
7983
#if defined(ADC1)
80-
if (((ADCName)obj->handle.Instance == ADC_1) && adc1_inited) return;
8184
if ((ADCName)obj->handle.Instance == ADC_1) {
82-
__ADC1_CLK_ENABLE();
83-
adc1_inited = 1;
85+
__HAL_RCC_ADC1_CLK_ENABLE();
8486
}
8587
#endif
8688
#if defined(ADC2)
87-
if (((ADCName)obj->handle.Instance == ADC_2) && adc2_inited) return;
8889
if ((ADCName)obj->handle.Instance == ADC_2) {
89-
__ADC2_CLK_ENABLE();
90-
adc2_inited = 1;
90+
__HAL_RCC_ADC2_CLK_ENABLE();
9191
}
9292
#endif
9393
#if defined(ADC3)
94-
if (((ADCName)obj->handle.Instance == ADC_3) && adc3_inited) return;
9594
if ((ADCName)obj->handle.Instance == ADC_3) {
96-
__ADC3_CLK_ENABLE();
97-
adc3_inited = 1;
95+
__HAL_RCC_ADC3_CLK_ENABLE();
9896
}
9997
#endif
100-
// Configure ADC
101-
obj->handle.State = HAL_ADC_STATE_RESET;
102-
obj->handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
103-
obj->handle.Init.Resolution = ADC_RESOLUTION12b;
104-
obj->handle.Init.ScanConvMode = DISABLE;
105-
obj->handle.Init.ContinuousConvMode = DISABLE;
106-
obj->handle.Init.DiscontinuousConvMode = DISABLE;
107-
obj->handle.Init.NbrOfDiscConversion = 0;
108-
obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
109-
obj->handle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
110-
obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
111-
obj->handle.Init.NbrOfConversion = 1;
112-
obj->handle.Init.DMAContinuousRequests = DISABLE;
113-
obj->handle.Init.EOCSelection = DISABLE;
98+
11499
if (HAL_ADC_Init(&obj->handle) != HAL_OK) {
115-
error("Cannot initialize ADC\n");
100+
error("Cannot initialize ADC");
116101
}
117102
}
118103

119-
static inline uint16_t adc_read(analogin_t *obj)
104+
uint16_t adc_read(analogin_t *obj)
120105
{
121106
ADC_ChannelConfTypeDef sConfig = {0};
122107

123108
// Configure ADC channel
124109
sConfig.Rank = 1;
125-
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
110+
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
126111
sConfig.Offset = 0;
127112

128113
switch (obj->channel) {
@@ -193,24 +178,10 @@ static inline uint16_t adc_read(analogin_t *obj)
193178

194179
// Wait end of conversion and get value
195180
if (HAL_ADC_PollForConversion(&obj->handle, 10) == HAL_OK) {
196-
return (HAL_ADC_GetValue(&obj->handle));
181+
return (uint16_t)HAL_ADC_GetValue(&obj->handle);
197182
} else {
198183
return 0;
199184
}
200185
}
201186

202-
uint16_t analogin_read_u16(analogin_t *obj)
203-
{
204-
uint16_t value = adc_read(obj);
205-
// 12-bit to 16-bit conversion
206-
value = ((value << 4) & (uint16_t)0xFFF0) | ((value >> 8) & (uint16_t)0x000F);
207-
return value;
208-
}
209-
210-
float analogin_read(analogin_t *obj)
211-
{
212-
uint16_t value = adc_read(obj);
213-
return (float)value * (1.0f / (float)0xFFF); // 12 bits range
214-
}
215-
216187
#endif

0 commit comments

Comments
 (0)