Skip to content

Commit 3752ee4

Browse files
committed
inital support for g4
1 parent 6070149 commit 3752ee4

File tree

4 files changed

+189
-1
lines changed

4 files changed

+189
-1
lines changed

src/current_sense/hardware_specific/stm32/stm32_mcu.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#define _ADC_RESOLUTION 1024.0f
1010

1111
// function reading an ADC value and returning the read voltage
12-
void* _configureADCInline(const void* driver_params, const int pinA,const int pinB,const int pinC){
12+
__attribute__((weak)) void* _configureADCInline(const void* driver_params, const int pinA,const int pinB,const int pinC){
1313
_UNUSED(driver_params);
1414

1515
if( _isset(pinA) ) pinMode(pinA, INPUT);

src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,166 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive
183183
return 0;
184184
}
185185

186+
/**
187+
* Function initializing the ADC and the regular channels for inline current sensing
188+
* with continuous conversion mode
189+
*
190+
* @param cs_params - current sense parameters
191+
*
192+
* @return int - 0 if success
193+
*/
194+
int _adc_init_inline(Stm32CurrentSenseParams* cs_params)
195+
{
196+
ADC_ChannelConfTypeDef sConfig = {0};
197+
198+
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
199+
*/
200+
auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc);
201+
202+
if(adc_instance == ADC1) {
203+
#ifdef __HAL_RCC_ADC1_CLK_ENABLE
204+
__HAL_RCC_ADC1_CLK_ENABLE();
205+
#endif
206+
#ifdef __HAL_RCC_ADC12_CLK_ENABLE
207+
__HAL_RCC_ADC12_CLK_ENABLE();
208+
#endif
209+
}
210+
#ifdef ADC2
211+
else if (adc_instance == ADC2) {
212+
#ifdef __HAL_RCC_ADC2_CLK_ENABLE
213+
__HAL_RCC_ADC2_CLK_ENABLE();
214+
#endif
215+
#ifdef __HAL_RCC_ADC12_CLK_ENABLE
216+
__HAL_RCC_ADC12_CLK_ENABLE();
217+
#endif
218+
}
219+
#endif
220+
#ifdef ADC3
221+
else if (adc_instance == ADC3) {
222+
#ifdef __HAL_RCC_ADC3_CLK_ENABLE
223+
__HAL_RCC_ADC3_CLK_ENABLE();
224+
#endif
225+
#ifdef __HAL_RCC_ADC34_CLK_ENABLE
226+
__HAL_RCC_ADC34_CLK_ENABLE();
227+
#endif
228+
#if defined(ADC345_COMMON)
229+
__HAL_RCC_ADC345_CLK_ENABLE();
230+
#endif
231+
}
232+
#endif
233+
#ifdef ADC4
234+
else if (adc_instance == ADC4) {
235+
#ifdef __HAL_RCC_ADC4_CLK_ENABLE
236+
__HAL_RCC_ADC4_CLK_ENABLE();
237+
#endif
238+
#ifdef __HAL_RCC_ADC34_CLK_ENABLE
239+
__HAL_RCC_ADC34_CLK_ENABLE();
240+
#endif
241+
#if defined(ADC345_COMMON)
242+
__HAL_RCC_ADC345_CLK_ENABLE();
243+
#endif
244+
}
245+
#endif
246+
#ifdef ADC5
247+
else if (adc_instance == ADC5) {
248+
#if defined(ADC345_COMMON)
249+
__HAL_RCC_ADC345_CLK_ENABLE();
250+
#endif
251+
}
252+
#endif
253+
else{
254+
#ifdef SIMPLEFOC_STM32_DEBUG
255+
SIMPLEFOC_DEBUG("STM32-CS: ERR: Cannot find a common ADC for the pins!");
256+
#endif
257+
return -1; // error not a valid ADC instance
258+
}
259+
260+
int adc_num = _adcToIndex(adc_instance);
261+
262+
#ifdef SIMPLEFOC_STM32_DEBUG
263+
SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1);
264+
#endif
265+
266+
hadc[adc_num].Instance = adc_instance;
267+
268+
// Configure ADC for continuous conversion mode on regular channels
269+
hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
270+
hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B;
271+
hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; // Enable scan mode for multiple channels
272+
hadc[adc_num].Init.ContinuousConvMode = ENABLE; // Enable continuous conversion
273+
hadc[adc_num].Init.LowPowerAutoWait = DISABLE;
274+
hadc[adc_num].Init.GainCompensation = 0;
275+
hadc[adc_num].Init.DiscontinuousConvMode = DISABLE;
276+
hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
277+
hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START;
278+
hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT;
279+
280+
// Count number of channels to configure
281+
uint8_t num_channels = 0;
282+
for(int pin_no=0; pin_no<3; pin_no++){
283+
if(_isset(cs_params->pins[pin_no])){
284+
num_channels++;
285+
}
286+
}
287+
288+
hadc[adc_num].Init.NbrOfConversion = num_channels;
289+
hadc[adc_num].Init.DMAContinuousRequests = DISABLE;
290+
hadc[adc_num].Init.EOCSelection = ADC_EOC_SEQ_CONV; // End of sequence for multi-channel
291+
hadc[adc_num].Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // Overwrite old data in continuous mode
292+
293+
if (HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){
294+
#ifdef SIMPLEFOC_STM32_DEBUG
295+
SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!");
296+
#endif
297+
return -1;
298+
}
299+
300+
// Configure regular channels
301+
sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5; // Fast sampling for inline sensing
302+
sConfig.SingleDiff = ADC_SINGLE_ENDED;
303+
sConfig.OffsetNumber = ADC_OFFSET_NONE;
304+
sConfig.Offset = 0;
305+
306+
uint8_t rank = 1;
307+
for(int i=0; i<3; i++){
308+
// skip if not set
309+
if (!_isset(cs_params->pins[i])) continue;
310+
311+
sConfig.Rank = rank++;
312+
sConfig.Channel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance);
313+
314+
if (HAL_ADC_ConfigChannel(&hadc[adc_num], &sConfig) != HAL_OK){
315+
#ifdef SIMPLEFOC_STM32_DEBUG
316+
SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init regular channel: ", (int)sConfig.Channel);
317+
#endif
318+
return -1;
319+
}
320+
}
321+
322+
cs_params->adc_handle = &hadc[adc_num];
323+
324+
// Calibrate ADC
325+
if (HAL_ADCEx_Calibration_Start(&hadc[adc_num], ADC_SINGLE_ENDED) != HAL_OK){
326+
#ifdef SIMPLEFOC_STM32_DEBUG
327+
SIMPLEFOC_DEBUG("STM32-CS: WARN: ADC calibration failed");
328+
#endif
329+
}
330+
331+
// Start continuous conversion
332+
if (HAL_ADC_Start(&hadc[adc_num]) != HAL_OK){
333+
#ifdef SIMPLEFOC_STM32_DEBUG
334+
SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot start ADC continuous conversion");
335+
#endif
336+
return -1;
337+
}
338+
339+
#ifdef SIMPLEFOC_STM32_DEBUG
340+
SIMPLEFOC_DEBUG("STM32-CS: ADC continuous conversion on no.channels: ", (int)num_channels);
341+
#endif
342+
343+
return 0;
344+
}
345+
186346
/**
187347
* Function to initialize the ADC GPIO pins
188348
*

src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../stm32_adc_utils.h"
1111

1212
int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params);
13+
int _adc_init_inline(Stm32CurrentSenseParams* cs_params);
1314
int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC);
1415

1516
#endif

src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ void* _configureADCLowSide(const void* driver_params, const int pinA, const int
4646
return cs_params;
4747
}
4848

49+
void* _configureADCInline(const void* driver_params, const int pinA, const int pinB, const int pinC){
50+
_UNUSED(driver_params);
51+
52+
Stm32CurrentSenseParams* cs_params = new Stm32CurrentSenseParams {
53+
.pins={(int)NOT_SET, (int)NOT_SET, (int)NOT_SET},
54+
.adc_voltage_conv = (_ADC_VOLTAGE_G4) / (_ADC_RESOLUTION_G4)
55+
};
56+
57+
if(_adc_gpio_init(cs_params, pinA, pinB, pinC) != 0) return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED;
58+
if(_adc_init_inline(cs_params) != 0) return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED;
59+
60+
return cs_params;
61+
}
62+
4963

5064
void* _driverSyncLowSide(void* _driver_params, void* _cs_params){
5165
STM32DriverParams* driver_params = (STM32DriverParams*)_driver_params;
@@ -131,6 +145,19 @@ float _readADCVoltageLowSide(const int pin, const void* cs_params){
131145
return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]);
132146
}
133147

148+
// function reading an ADC value from regular channels (inline current sensing)
149+
float _readADCVoltageInline(const int pin, const void* cs_params){
150+
Stm32CurrentSenseParams* params = (Stm32CurrentSenseParams*)cs_params;
151+
ADC_HandleTypeDef* hadc = params->adc_handle;
152+
153+
// In continuous conversion mode, just read the latest value from the data register
154+
// No polling needed - the ADC is constantly updating this register
155+
uint32_t raw_adc = HAL_ADC_GetValue(hadc);
156+
157+
// Convert to voltage
158+
return raw_adc * params->adc_voltage_conv;
159+
}
160+
134161
extern "C" {
135162
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){
136163
uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle);

0 commit comments

Comments
 (0)