SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
stm32g4_hal.cpp
Go to the documentation of this file.
1#include "stm32g4_hal.h"
2
3#if defined(STM32G4xx) && !defined(ARDUINO_B_G431B_ESC1)
4
5#include "../../../../communication/SimpleFOCDebug.h"
6
7#define SIMPLEFOC_STM32_DEBUG
8
9
10// pointer to the ADC handles used in the project
11ADC_HandleTypeDef hadc[ADC_COUNT] = {0};
12
13ADC_HandleTypeDef* _get_adc_handles(){
14 return hadc;
15}
16
17/**
18 * Function initializing the ADC for the regular channels for the low-side current sensing
19 *
20 * @param adc_instance - ADC instance to initialize
21 *
22 * @return int - 0 if success
23 */
24int _adc_init_regular(ADC_TypeDef* adc_instance){
25 ADC_InjectionConfTypeDef sConfigInjected;
26
27
28 if(adc_instance == ADC1) {
29#ifdef __HAL_RCC_ADC1_CLK_ENABLE
30 __HAL_RCC_ADC1_CLK_ENABLE();
31#endif
32#ifdef __HAL_RCC_ADC12_CLK_ENABLE
33 __HAL_RCC_ADC12_CLK_ENABLE();
34#endif
35 }
36#ifdef ADC2
37 else if (adc_instance == ADC2) {
38#ifdef __HAL_RCC_ADC2_CLK_ENABLE
39 __HAL_RCC_ADC2_CLK_ENABLE();
40#endif
41#ifdef __HAL_RCC_ADC12_CLK_ENABLE
42 __HAL_RCC_ADC12_CLK_ENABLE();
43#endif
44 }
45#endif
46#ifdef ADC3
47 else if (adc_instance == ADC3) {
48#ifdef __HAL_RCC_ADC3_CLK_ENABLE
49 __HAL_RCC_ADC3_CLK_ENABLE();
50#endif
51#ifdef __HAL_RCC_ADC34_CLK_ENABLE
52 __HAL_RCC_ADC34_CLK_ENABLE();
53#endif
54#if defined(ADC345_COMMON)
55 __HAL_RCC_ADC345_CLK_ENABLE();
56#endif
57 }
58#endif
59#ifdef ADC4
60 else if (adc_instance == ADC4) {
61#ifdef __HAL_RCC_ADC4_CLK_ENABLE
62 __HAL_RCC_ADC4_CLK_ENABLE();
63#endif
64#ifdef __HAL_RCC_ADC34_CLK_ENABLE
65 __HAL_RCC_ADC34_CLK_ENABLE();
66#endif
67#if defined(ADC345_COMMON)
68 __HAL_RCC_ADC345_CLK_ENABLE();
69#endif
70 }
71#endif
72#ifdef ADC5
73 else if (adc_instance == ADC5) {
74#if defined(ADC345_COMMON)
75 __HAL_RCC_ADC345_CLK_ENABLE();
76#endif
77 }
78#endif
79 else{
80#ifdef SIMPLEFOC_STM32_DEBUG
81 SIMPLEFOC_DEBUG("STM32-CS: ERR: Cannot find a common ADC for the pins!");
82#endif
83 return -1; // error not a valid ADC instance
84 }
85
86 int adc_num = _adcToIndex(adc_instance);
87
88#ifdef SIMPLEFOC_STM32_DEBUG
89 SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1);
90#endif
91
92 hadc[adc_num].Instance = adc_instance;
93
94 hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
95 hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B;
96 hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE;
97 hadc[adc_num].Init.ContinuousConvMode = DISABLE;
98 hadc[adc_num].Init.LowPowerAutoWait = DISABLE;
99 hadc[adc_num].Init.GainCompensation = 0;
100 hadc[adc_num].Init.DiscontinuousConvMode = DISABLE;
101 hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
102 hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now
103 hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT;
104 hadc[adc_num].Init.NbrOfConversion = 1;
105 hadc[adc_num].Init.DMAContinuousRequests = DISABLE;
106 hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV;
107 hadc[adc_num].Init.Overrun = ADC_OVR_DATA_PRESERVED;
108 if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){
109#ifdef SIMPLEFOC_STM32_DEBUG
110 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!");
111#endif
112 return -1;
113 }
114
115 return 0;
116}
117
118/**
119 * Function initializing the ADC and the injected channels for the low-side current sensing
120 *
121 * @param cs_params - current sense parameters
122 * @param driver_params - driver parameters
123 *
124 * @return int - 0 if success
125 */
126int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params)
127{
128
129 /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
130 */
131 auto adc_instance = _findBestADCForInjectedPins(3, cs_params->pins, hadc);
132 if(adc_instance == NP){
133#ifdef SIMPLEFOC_STM32_DEBUG
134 SIMPLEFOC_DEBUG("STM32-CS: ERR: No ADCs available!");
135#endif
136 return -1; // error not a valid ADC instance
137 }
138 if( _adc_init_regular(adc_instance) != 0){
139 return -1;
140 }
141 int adc_num = _adcToIndex(adc_instance);
142
143 /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
144 */
145 ADC_InjectionConfTypeDef sConfigInjected;
146 sConfigInjected.InjectedNbrOfConversion = 0;
147 for(int pin_no=0; pin_no<3; pin_no++){
148 if(_isset(cs_params->pins[pin_no])){
149 sConfigInjected.InjectedNbrOfConversion++;
150 }
151 }
152 sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5;
153 sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
154 sConfigInjected.AutoInjectedConv = DISABLE;
155 sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
156 sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
157 sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
158 sConfigInjected.InjectedOffset = 0;
159 sConfigInjected.InjecOversamplingMode = DISABLE;
160 sConfigInjected.QueueInjectedContext = DISABLE;
161
162 // automating TRGO flag finding - hardware specific
163 uint8_t tim_num = 0;
164 while(driver_params->timers_handle[tim_num] != NP && tim_num < 6){
165 uint32_t trigger_flag = _timerToInjectedTRGO(driver_params->timers_handle[tim_num++]);
166 if(trigger_flag == _TRGO_NOT_AVAILABLE) continue; // timer does not have valid trgo for injected channels
167
168 // check if TRGO used already - if yes use the next timer
169 if((driver_params->timers_handle[tim_num-1]->Instance->CR2 & LL_TIM_TRGO_ENABLE) || // if used for timer sync
170 (driver_params->timers_handle[tim_num-1]->Instance->CR2 & LL_TIM_TRGO_UPDATE)) // if used for ADC sync
171 {
172 continue;
173 }
174
175 // if the code comes here, it has found the timer available
176 // timer does have trgo flag for injected channels
177 sConfigInjected.ExternalTrigInjecConv = trigger_flag;
178
179 // this will be the timer with which the ADC will sync
180 cs_params->timer_handle = driver_params->timers_handle[tim_num-1];
181 // done
182 break;
183 }
184 if( cs_params->timer_handle == NP ){
185 // not possible to use these timers for low-side current sense
186#ifdef SIMPLEFOC_STM32_DEBUG
187 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot sync any timer to injected channels!");
188#endif
189 return -1;
190 }else{
191#ifdef SIMPLEFOC_STM32_DEBUG
192 SIMPLEFOC_DEBUG("STM32-CS: Using timer: ", stm32_getTimerNumber(cs_params->timer_handle->Instance));
193#endif
194 }
195
196 uint8_t channel_no = 0;
197 for(int i=0; i<3; i++){
198 // skip if not set
199 if (!_isset(cs_params->pins[i])) continue;
200
201 sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++);
202 sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance);
203#ifdef SIMPLEFOC_STM32_DEBUG
204 SIMPLEFOC_DEBUG("STM32-CS: ADC channel: ", (int)STM_PIN_CHANNEL(pinmap_function(PinMap_ADC[i].pin, PinMap_ADC)));
205#endif
206 if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){
207 #ifdef SIMPLEFOC_STM32_DEBUG
208 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)STM_PIN_CHANNEL(pinmap_function(PinMap_ADC[i].pin, PinMap_ADC)));
209 #endif
210 return -1;
211 }
212 }
213 cs_params->adc_handle = &hadc[adc_num];
214 return 0;
215}
216
217/**
218 * Function to initialize the ADC GPIO pins
219 *
220 * @param cs_params current sense parameters
221 * @param pinA pin number for phase A
222 * @param pinB pin number for phase B
223 * @param pinC pin number for phase C
224 * @return int 0 if success, -1 if error
225 */
226int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC)
227{
228 int pins[3] = {pinA, pinB, pinC};
229 const char* port_names[3] = {"A", "B", "C"};
230 for(int i=0; i<3; i++){
231 if(_isset(pins[i])){
232 // check if pin is an analog pin
233 if(pinmap_peripheral(analogInputToPinName(pins[i]), PinMap_ADC) == NP){
234
235#if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
236 SimpleFOCDebug::print("STM32-CS: ERR: Pin ");
237 SimpleFOCDebug::print(port_names[i]);
238 SimpleFOCDebug::println(" does not belong to any ADC!");
239#endif
240 return -1;
241 }
242 pinmap_pinout(analogInputToPinName(pins[i]), PinMap_ADC);
243 cs_params->pins[i] = pins[i];
244 }
245 }
246 return 0;
247}
248
249
250extern "C" {
251 void ADC1_2_IRQHandler(void)
252 {
253 if (hadc[0].Instance != NP)
254 HAL_ADC_IRQHandler(&hadc[0]);
255 if (hadc[1].Instance != NP)
256 HAL_ADC_IRQHandler(&hadc[1]);
257 }
258#ifdef ADC3
259 void ADC3_IRQHandler(void)
260 {
261 if (hadc[2].Instance != NP)
262 HAL_ADC_IRQHandler(&hadc[2]);
263 }
264#endif
265
266#ifdef ADC4
267 void ADC4_IRQHandler(void)
268 {
269 if (hadc[3].Instance != NP)
270 HAL_ADC_IRQHandler(&hadc[3]);
271 }
272#endif
273
274#ifdef ADC5
275 void ADC5_IRQHandler(void)
276 {
277 if (hadc[4].Instance != NP)
278 HAL_ADC_IRQHandler(&hadc[4]);
279 }
280#endif
281}
282#endif
#define SIMPLEFOC_DEBUG(msg,...)
static void print(const char *msg)
static void println()
const int const int const int pinC
#define _isset(a)
Definition foc_utils.h:13