rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
adc_onchip_fast.cpp
Go to the documentation of this file.
1/**
2 * @file adc_inputs_onchip.cpp
3 * @brief Low level ADC code
4 *
5 * rusEfi uses two ADC devices on the same 16 pins at the moment. Two ADC devices are used in order to distinguish between
6 * fast and slow devices. The idea is that but only having few channels in 'fast' mode we can sample those faster?
7 *
8 * Slow ADC group is used for IAT, CLT, AFR, VBATT etc - this one is currently sampled at 500Hz
9 *
10 * Fast ADC group is used for MAP, MAF HIP - this one is currently sampled at 10KHz
11 * We need frequent MAP for map_averaging.cpp
12 *
13 * 10KHz equals one measurement every 3.6 degrees at 6000 RPM
14 *
15 * PS: analog muxes allow to double number of analog inputs
16 * oh, and ADC3 is dedicated for knock
17 *
18 * @date Jan 14, 2013
19 * @author Andrey Belomutskiy, (c) 2012-2020
20 */
21
22#include "pch.h"
23
24#if HAL_USE_ADC
25
26#include "adc_device.h"
27#include "adc_subscription.h"
28#include "mpu_util.h"
30#include "protected_gpio.h"
31
32#ifndef ADC_MAX_CHANNELS_COUNT
33#define ADC_MAX_CHANNELS_COUNT 16
34#endif /* ADC_MAX_CHANNELS_COUNT */
35
36#if EFI_USE_FAST_ADC
37
38// is there a reason to have this configurable at runtime?
39#ifndef ADC_FAST_DEVICE
40#define ADC_FAST_DEVICE ADCD2
41#endif
42
43// Depth of the conversion buffer, channels are sampled X times each
44#ifndef ADC_BUF_DEPTH_FAST
45#define ADC_BUF_DEPTH_FAST 4
46#endif
47
48// See https://github.com/rusefi/rusefi/issues/976 for discussion on this value
49#ifndef ADC_SAMPLING_FAST
50#define ADC_SAMPLING_FAST ADC_SAMPLE_28
51#endif
52
53AdcDevice::AdcDevice(ADCDriver *p_adcp, ADCConversionGroup* p_hwConfig, volatile adcsample_t *p_buf, size_t p_depth) {
54 adcp = p_adcp;
55 depth = p_depth;
56 hwConfig = p_hwConfig;
57 samples = p_buf;
58
59 hwConfig->sqr1 = 0;
60 hwConfig->sqr2 = 0;
61 hwConfig->sqr3 = 0;
62#if ADC_MAX_CHANNELS_COUNT > 16
63 hwConfig->sqr4 = 0;
64 hwConfig->sqr5 = 0;
65#endif /* ADC_MAX_CHANNELS_COUNT */
67}
68
69static void fastAdcDoneCB(ADCDriver *adcp);
70static void fastAdcErrorCB(ADCDriver *, adcerror_t err);
71
72static ADCConversionGroup adcgrpcfgFast = {
73#if defined(EFI_INTERNAL_FAST_ADC_PWM)
74 .circular = TRUE,
75#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
76 .circular = FALSE,
77#endif
78 .num_channels = 0,
79 .end_cb = fastAdcDoneCB,
80 .error_cb = fastAdcErrorCB,
81 /* HW dependent part.*/
82 .cr1 = 0,
83#if defined(EFI_INTERNAL_FAST_ADC_PWM)
84 /* HW start using TIM8 CC 1 event rising edge
85 * See "External trigger for regular channels" for magic 13 number
86 * NOTE: Currently only TIM8 in PWM mode is supported */
87 .cr2 = ADC_CR2_EXTEN_0 | (13 << ADC_CR2_EXTSEL_Pos),
88#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
89 /* SW start through GPT callback and SW kick */
90 .cr2 = ADC_CR2_SWSTART,
91#endif
92 /**
93 * here we configure all possible channels for fast mode. Some channels would not actually
94 * be used hopefully that's fine to configure all possible channels.
95 *
96 */
97 // sample times for channels 10...18
98 .smpr1 =
99 ADC_SMPR1_SMP_AN10(ADC_SAMPLING_FAST) |
100 ADC_SMPR1_SMP_AN11(ADC_SAMPLING_FAST) |
101 ADC_SMPR1_SMP_AN12(ADC_SAMPLING_FAST) |
102 ADC_SMPR1_SMP_AN13(ADC_SAMPLING_FAST) |
103 ADC_SMPR1_SMP_AN14(ADC_SAMPLING_FAST) |
104 ADC_SMPR1_SMP_AN15(ADC_SAMPLING_FAST),
105 // In this field must be specified the sample times for channels 0...9
106 .smpr2 =
107 ADC_SMPR2_SMP_AN0(ADC_SAMPLING_FAST) |
108 ADC_SMPR2_SMP_AN1(ADC_SAMPLING_FAST) |
109 ADC_SMPR2_SMP_AN2(ADC_SAMPLING_FAST) |
110 ADC_SMPR2_SMP_AN3(ADC_SAMPLING_FAST) |
111 ADC_SMPR2_SMP_AN4(ADC_SAMPLING_FAST) |
112 ADC_SMPR2_SMP_AN5(ADC_SAMPLING_FAST) |
113 ADC_SMPR2_SMP_AN6(ADC_SAMPLING_FAST) |
114 ADC_SMPR2_SMP_AN7(ADC_SAMPLING_FAST) |
115 ADC_SMPR2_SMP_AN8(ADC_SAMPLING_FAST) |
116 ADC_SMPR2_SMP_AN9(ADC_SAMPLING_FAST),
117 .htr = 0,
118 .ltr = 0,
119 .sqr1 = 0, // Conversion group sequence 13...16 + sequence length
120 .sqr2 = 0, // Conversion group sequence 7...12
121 .sqr3 = 0, // Conversion group sequence 1...6
122#if ADC_MAX_CHANNELS_COUNT > 16
123 .sqr4 = 0, // Conversion group sequence 19...24
124 .sqr5 = 0 // Conversion group sequence 25...30
125#endif /* ADC_MAX_CHANNELS_COUNT */
126};
127
128static volatile NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST * ADC_MAX_CHANNELS_COUNT];
129
131
132static efitick_t lastTick = 0;
133
134static void fastAdcDoneCB(ADCDriver *adcp) {
135 // State may not be complete if we get a callback for "half done"
136 if (adcIsBufferComplete(adcp)) {
137 efitick_t nowTick = getTimeNowNt();
138 efitick_t diff = nowTick - lastTick;
139 lastTick = nowTick;
140
141 engine->outputChannels.fastAdcPeriod = (uint32_t)diff;
143
144 onFastAdcComplete(adcp->samples);
145 }
146
147 assertInterruptPriority(__func__, EFI_IRQ_ADC_PRIORITY);
148}
149
150static void fastAdcErrorCB(ADCDriver *, adcerror_t err) {
151 engine->outputChannels.fastAdcLastError = (uint8_t)err;
153 if (err == ADC_ERR_OVERFLOW) {
155 }
156 // TODO: restart?
157}
158
159#if defined(EFI_INTERNAL_FAST_ADC_PWM)
160
161static const PWMConfig pwmcfg = {
162 /* on each trigger event regular group of channels is converted,
163 * to get whole buffer filled we need ADC_BUF_DEPTH_FAST trigger events */
164 .frequency = GPT_FREQ_FAST * ADC_BUF_DEPTH_FAST,
165 .period = GPT_PERIOD_FAST,
166 .callback = nullptr,
167 .channels = {
168 {PWM_OUTPUT_ACTIVE_HIGH, nullptr},
169 {PWM_OUTPUT_ACTIVE_HIGH, nullptr},
170 {PWM_OUTPUT_ACTIVE_HIGH, nullptr},
171 {PWM_OUTPUT_ACTIVE_HIGH, nullptr}
172 },
173 .cr2 = 0,
174 .bdtr = 0,
175 .dier = 0,
176};
177
178#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
179
181{
182#if EFI_INTERNAL_ADC
183 /*
184 * Starts an asynchronous ADC conversion operation, the conversion
185 * will be executed in parallel to the current PWM cycle and will
186 * terminate before the next PWM cycle.
187 */
189#endif /* EFI_INTERNAL_ADC */
190 assertInterruptPriority(__func__, EFI_IRQ_ADC_PRIORITY);
191}
192
194 .frequency = GPT_FREQ_FAST,
195 .callback = fastAdcStartTrigger,
196 .cr2 = 0,
197 .dier = 0,
198};
199
200#else
201 #error Please define EFI_INTERNAL_FAST_ADC_PWM or EFI_INTERNAL_FAST_ADC_GPT for Fast ADC
202#endif
203
204int AdcDevice::size() const {
205 return channelCount;
206}
207
208void AdcDevice::init(void) {
209 hwConfig->num_channels = size();
210 /* driver does this internally */
211 //hwConfig->sqr1 += ADC_SQR1_NUM_CH(size());
212
213#if defined(EFI_INTERNAL_FAST_ADC_PWM)
214 // Start the timer running
215 pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg);
216 pwmEnableChannel(EFI_INTERNAL_FAST_ADC_PWM, 0, /* width */ 1);
217 adcStartConversion(adcp, hwConfig, (adcsample_t *)samples, depth);
218#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
219 gptStart(EFI_INTERNAL_FAST_ADC_GPT, &fast_adc_config);
220 gptStartContinuous(EFI_INTERNAL_FAST_ADC_GPT, GPT_PERIOD_FAST);
221#endif
222}
223
225 if ((channelCount + 1) >= ADC_MAX_CHANNELS_COUNT) {
226 criticalError("Too many ADC channels configured");
227 return -1;
228 }
229
230 int logicChannel = channelCount++;
231
232 /* TODO: following is correct for STM32 ADC1/2.
233 * ADC3 has another input to gpio mapping
234 * and should be handled separately */
235 size_t channelAdcIndex = hwChannel - EFI_ADC_0;
236
237 internalAdcIndexByHardwareIndex[hwChannel] = logicChannel;
238 if (logicChannel < 6) {
239 hwConfig->sqr3 |= channelAdcIndex << (5 * logicChannel);
240 } else if (logicChannel < 12) {
241 hwConfig->sqr2 |= channelAdcIndex << (5 * (logicChannel - 6));
242 } else if (logicChannel < 18) {
243 hwConfig->sqr1 |= channelAdcIndex << (5 * (logicChannel - 12));
244 }
245#if ADC_MAX_CHANNELS_COUNT > 16
246 else if (logicChannel < 24) {
247 hwConfig->sqr4 |= channelAdcIndex << (5 * (logicChannel - 18));
248 }
249 else if (logicChannel < 30) {
250 hwConfig->sqr5 |= channelAdcIndex << (5 * (logicChannel - 24));
251 }
252#endif /* ADC_MAX_CHANNELS_COUNT */
253
254 return channelAdcIndex;
255}
256
258{
259 chSysLockFromISR();
260 if ((ADC_FAST_DEVICE.state == ADC_READY) ||
261 (ADC_FAST_DEVICE.state == ADC_ERROR)) {
262 /* drop volatile type qualifier - this is safe */
263 adcStartConversionI(adcp, hwConfig, (adcsample_t *)samples, depth);
264 } else {
266 // todo: when? why? criticalError("ADC fast not ready?");
267 // see notes at https://github.com/rusefi/rusefi/issues/6399
268 }
269 chSysUnlockFromISR();
270}
271
273 uint32_t result = 0;
274 int numChannels = size();
275 int index = fastAdc.internalAdcIndexByHardwareIndex[hwChannel];
276 if (index == 0xff) {
277 criticalError("Fast ADC attempt to read unconfigured input %d.", hwChannel);
278 return 0;
279 }
280
281 for (size_t i = 0; i < depth; i++) {
282 adcsample_t sample = samples[index];
283 if (sample > ADC_MAX_VALUE) {
284 // 12bit ADC expected right now. An error here usually means major RAM corruption?
285 criticalError("ADC unexpected sample %d at %ld uptime.",
286 sample,
287 (uint32_t)getTimeNowS());
288 }
289 result += sample;
290 index += numChannels;
291 }
292
293 // this truncation is guaranteed to not be lossy - the average can't be larger than adcsample_t
294 return static_cast<adcsample_t>(result / depth);
295}
296
298 for (size_t idx = EFI_ADC_0; idx < EFI_ADC_TOTAL_CHANNELS; idx++) {
299 if (internalAdcIndexByHardwareIndex[idx] == hwChannel) {
300 return (adc_channel_e)idx;
301 }
302 }
303 return EFI_ADC_NONE;
304}
305
309
310#endif // EFI_USE_FAST_ADC
311
312#endif // HAL_USE_ADC
AdcDevice fastAdc
uint32_t AdcToken
Definition adc_inputs.h:98
static void fastAdcStartTrigger(GPTDriver *)
static const PWMConfig pwmcfg
AdcDevice fastAdc & ADC_FAST_DEVICE
static volatile NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST *ADC_MAX_CHANNELS_COUNT]
static efitick_t lastTick
static const GPTConfig fast_adc_config
static void fastAdcDoneCB(ADCDriver *adcp)
static void fastAdcErrorCB(ADCDriver *, adcerror_t err)
static ADCConversionGroup adcgrpcfgFast
void init(void)
void startConversionI(void)
size_t depth
Definition adc_device.h:35
uint8_t internalAdcIndexByHardwareIndex[EFI_ADC_TOTAL_CHANNELS]
Definition adc_device.h:36
int size() const
adc_channel_e getAdcChannelByInternalIndex(int index) const
AdcToken getAdcChannelToken(adc_channel_e hwChannel)
int enableChannel(adc_channel_e hwChannel)
ADCConversionGroup * hwConfig
Definition adc_device.h:33
size_t channelCount
Definition adc_device.h:40
adcsample_t getAvgAdcValue(adc_channel_e hwChannel)
AdcDevice(ADCDriver *p_adcp, ADCConversionGroup *p_hwConfig, volatile adcsample_t *p_buf, size_t p_depth)
volatile adcsample_t * samples
Definition adc_device.h:34
ADCDriver * adcp
Definition adc_device.h:32
TunerStudioOutputChannels outputChannels
Definition engine.h:109
efitick_t getTimeNowNt()
Definition efitime.cpp:19
efitimesec_t getTimeNowS()
Current system time in seconds (32 bits)
Definition efitime.cpp:42
static EngineAccessor engine
Definition engine.h:413
adcerror_t
Possible ADC failure causes.
uint16_t adcsample_t
ADC sample data type.
@ ADC_ERR_OVERFLOW
gptfreq_t frequency
Timer clock in Hz.
void onFastAdcComplete(adcsample_t *)
Definition hardware.cpp:278
static union @47 NO_CACHE
void assertInterruptPriority(const char *func, uint8_t expectedPrio)
Driver configuration structure.
Structure representing a GPT driver.
Type of a PWM driver configuration structure.
uint32_t frequency
Timer clock in Hz.