-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This change adds initial support for ADC on STM32. For now, only STM32L4 is supported, STM32Fxxx have somewhat different ADC and need more work. CL: adc: Support for STM32L4
- Loading branch information
Showing
7 changed files
with
456 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* Copyright (c) 2019 Deomid "rojer" Ryabkov | ||
* All rights reserved | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
// Value of the internal voltage reference. | ||
#ifndef STM32_ADC_VREFINT_VALUE_MV | ||
#define STM32_ADC_VREFINT_VALUE_MV 1212 | ||
#endif | ||
|
||
struct stm32_adc_config { | ||
// Resolution, in bits; 6, 8, 10 or 12; default is 12. | ||
uint8_t resolution; | ||
}; | ||
|
||
// Configures and enabled the ADC. | ||
bool stm32_adc_configure(int unit_no, const struct stm32_adc_config *cfg); | ||
|
||
// Enable particular ADC input. | ||
bool stm32_adc_enable_input(int unit_no, int input_no); | ||
|
||
// Performs single conversion of a particular input (0-18) | ||
int stm32_adc_read(int unit_no, int input_no); | ||
|
||
/* Read the internal temperature sensor. | ||
* Returns temperature in degrees Celsius. */ | ||
int stm32_adc_read_temp_c(void); | ||
|
||
// Returns reference value used for mgos_adc_read_voltage calculation. | ||
int stm32_adc_get_vref(void); | ||
|
||
// Set reference voltage value, used in mgos_adc_read_voltage calculation. | ||
void stm32_adc_set_vref(int vref_mv); | ||
|
||
// Sets vref by measuring Vrefint. | ||
// Returns calculated value or -1 in case of error. | ||
int stm32_adc_set_vref_from_vrefint(void); | ||
|
||
// ADC "pseudo-pins" for internal sources. | ||
#define STM32_ADC_PIN_VREFINT 0xff0000 // Internal voltage reference | ||
#define STM32_ADC_PIN_TEMP 0xff0001 // Package temperature sensor | ||
#define STM32_ADC_PIN_VBAT 0xff0002 // Battery voltage rail | ||
|
||
#define STM32_ADC1_M (1 << 1) | ||
#define STM32_ADC2_M (1 << 2) | ||
#define STM32_ADC3_M (1 << 3) | ||
|
||
struct stm32_adc_input_def { | ||
int pin; // GPIO pin (port, number). | ||
uint8_t input_no; // Input number. | ||
uint8_t | ||
adc_m; // Which ADC units have it enabled, combination of STM32_ADCx_M. | ||
}; | ||
|
||
const struct stm32_adc_input_def *stm32_adc_get_input_def(int input_no); | ||
const struct stm32_adc_input_def *stm32_adc_get_input_def_by_pin(int pin); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/* | ||
* Copyright (c) 2019 Deomid "rojer" Ryabkov | ||
* All rights reserved | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "mgos_adc.h" | ||
|
||
#include "mgos.h" | ||
|
||
#include "stm32_sdk_hal.h" | ||
|
||
static int s_vref_mv = -1; | ||
|
||
static ADC_TypeDef *const s_regs[] = { | ||
NULL, | ||
#ifdef ADC1 | ||
ADC1, | ||
#else | ||
NULL, | ||
#endif | ||
|
||
#ifdef ADC2 | ||
ADC2, | ||
#else | ||
NULL, | ||
#endif | ||
|
||
#ifdef ADC3 | ||
ADC3, | ||
#else | ||
NULL, | ||
#endif | ||
}; | ||
|
||
// Vbat is connected to ADC through a divider. | ||
// The ratio is different for different device families. | ||
#if defined(STM32L4) | ||
#define STM32_ADC_VBAT_DIV 3 | ||
#endif | ||
#if defined(STM32F2) | ||
#define STM32_ADC_VBAT_DIV 2 | ||
#endif | ||
#if defined(STM32F4) || defined(STM32F7) | ||
#define STM32_ADC_VBAT_DIV 4 | ||
#endif | ||
#ifndef STM32_ADC_VBAT_DIV | ||
#error STM32_ADC_VBAT_DIV not defined for this device | ||
#endif | ||
|
||
volatile ADC_TypeDef *stm32_adc_get_regs(int unit_no) { | ||
if (unit_no >= (int) ARRAY_SIZE(s_regs)) return NULL; | ||
return s_regs[unit_no]; | ||
} | ||
|
||
bool mgos_adc_enable(int pin) { | ||
const struct stm32_adc_input_def *ind = stm32_adc_get_input_def_by_pin(pin); | ||
if (ind == NULL) return false; | ||
if ((ind->adc_m & STM32_ADC1_M) == 0) return false; | ||
struct stm32_adc_config cfg = {.resolution = 12}; | ||
if (!stm32_adc_configure(1, &cfg)) return false; | ||
return stm32_adc_enable_input(1, ind->input_no); | ||
} | ||
|
||
int mgos_adc_read(int pin) { | ||
const struct stm32_adc_input_def *ind = stm32_adc_get_input_def_by_pin(pin); | ||
if (ind == NULL) return -1; | ||
if ((ind->adc_m & STM32_ADC1_M) == 0) return false; | ||
return stm32_adc_read(1, ind->input_no); | ||
} | ||
|
||
int mgos_adc_read_voltage(int pin) { | ||
int mval = mgos_adc_read(pin); | ||
if (mval < 0) return mval; | ||
if (pin == STM32_ADC_PIN_VBAT) mval *= STM32_ADC_VBAT_DIV; | ||
return (s_vref_mv * mval) / 4095; | ||
} | ||
|
||
int stm32_adc_get_vref(void) { | ||
return s_vref_mv; | ||
} | ||
|
||
void stm32_adc_set_vref(int vref_mv) { | ||
s_vref_mv = vref_mv; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* Copyright (c) 2019 Deomid "rojer" Ryabkov | ||
* All rights reserved | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "stm32_adc.h" | ||
|
||
#include "mgos.h" | ||
|
||
// clang-format off | ||
|
||
#ifdef STM32F205xx | ||
static const struct stm32_adc_input_def s_stm32_adc_inputs[] = { | ||
// TODO | ||
{ .pin = 0, .input_no = 0, .adc_m = 0 }, | ||
}; | ||
#define STM32_INPUTS_DEFINED | ||
#endif | ||
|
||
#ifdef STM32F746xx | ||
static const struct stm32_adc_input_def s_stm32_adc_inputs[] = { | ||
{ .pin = STM32_GPIO('A', 0), .input_no = 0, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('A', 1), .input_no = 1, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('A', 2), .input_no = 2, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('A', 3), .input_no = 3, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('A', 4), .input_no = 4, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 5), .input_no = 5, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 6), .input_no = 6, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 7), .input_no = 7, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('B', 0), .input_no = 8, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('B', 1), .input_no = 9, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
|
||
{ .pin = STM32_GPIO('C', 0), .input_no = 10, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('C', 1), .input_no = 11, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('C', 2), .input_no = 12, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('C', 3), .input_no = 13, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
|
||
{ .pin = STM32_GPIO('F', 4), .input_no = 14, .adc_m = STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('F', 5), .input_no = 15, .adc_m = STM32_ADC3_M }, | ||
|
||
{ .pin = 0, .input_no = 16, .adc_m = 0 }, | ||
|
||
{ .pin = STM32_ADC_PIN_VREFINT, .input_no = 17, .adc_m = STM32_ADC1_M }, | ||
{ .pin = STM32_ADC_PIN_TEMP, .input_no = 18, .adc_m = STM32_ADC1_M }, // T sensor and Vbat share the same channel. | ||
{ .pin = STM32_ADC_PIN_VBAT, .input_no = 18, .adc_m = STM32_ADC1_M }, | ||
}; | ||
#define STM32_INPUTS_DEFINED | ||
#endif | ||
|
||
#ifdef STM32L475xx | ||
static const struct stm32_adc_input_def s_stm32_adc_inputs[] = { | ||
{ .pin = STM32_ADC_PIN_VREFINT, .input_no = 0, .adc_m = STM32_ADC1_M }, | ||
{ .pin = STM32_GPIO('C', 0), .input_no = 1, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('C', 1), .input_no = 2, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('C', 2), .input_no = 3, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('C', 3), .input_no = 4, .adc_m = STM32_ADC1_M | STM32_ADC2_M | STM32_ADC3_M }, | ||
{ .pin = STM32_GPIO('A', 0), .input_no = 5, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 1), .input_no = 6, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 2), .input_no = 7, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 3), .input_no = 8, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 4), .input_no = 9, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 5), .input_no = 10, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 6), .input_no = 11, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('A', 7), .input_no = 12, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('C', 4), .input_no = 13, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('C', 5), .input_no = 14, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('B', 0), .input_no = 15, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_GPIO('B', 1), .input_no = 16, .adc_m = STM32_ADC1_M | STM32_ADC2_M }, | ||
{ .pin = STM32_ADC_PIN_TEMP, .input_no = 17, .adc_m = STM32_ADC1_M | STM32_ADC3_M }, | ||
{ .pin = STM32_ADC_PIN_VBAT, .input_no = 18, .adc_m = STM32_ADC1_M | STM32_ADC3_M }, | ||
}; | ||
#define STM32_INPUTS_DEFINED | ||
#endif | ||
|
||
#ifndef STM32_INPUTS_DEFINED | ||
#error STM32 pin to ADC input mapping is not defined for this device | ||
#endif | ||
|
||
const struct stm32_adc_input_def *stm32_adc_get_input_def(int input_no) { | ||
if (input_no >= (int) ARRAY_SIZE(s_stm32_adc_inputs)) return NULL; | ||
return &s_stm32_adc_inputs[input_no]; | ||
} | ||
|
||
const struct stm32_adc_input_def *stm32_adc_get_input_def_by_pin(int pin) { | ||
for (int i = 0; i < (int) ARRAY_SIZE(s_stm32_adc_inputs); i++) { | ||
if (s_stm32_adc_inputs[i].pin == pin) return &s_stm32_adc_inputs[i]; | ||
} | ||
return NULL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright (c) 2019 Deomid "rojer" Ryabkov | ||
* All rights reserved | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "stm32_adc.h" | ||
|
||
#include "stm32_sdk_hal.h" | ||
|
||
extern volatile ADC_TypeDef *stm32_adc_get_regs(int unit_no); | ||
|
||
#if defined(STM32F2) || defined(STM32F4) || defined(STM32F7) | ||
|
||
// TODO | ||
|
||
bool mgos_adc_init(void) { | ||
return true; | ||
} | ||
#endif // defined(STM32F2) || defined(STM32F4) || defined(STM32F7) |
Oops, something went wrong.