1
+ #include " stm32h7_hal.h"
2
+
3
+ #if defined(STM32H7xx)
4
+
5
+ // #define SIMPLEFOC_STM32_DEBUG
6
+
7
+ #include " ../../../../communication/SimpleFOCDebug.h"
8
+ #define _TRGO_NOT_AVAILABLE 12345
9
+
10
+ ADC_HandleTypeDef hadc;
11
+
12
+ /* *
13
+ * Function initializing the ADC and the injected channels for the low-side current sensing
14
+ *
15
+ * @param cs_params - current sense parameters
16
+ * @param driver_params - driver parameters
17
+ *
18
+ * @return int - 0 if success
19
+ */
20
+ int _adc_init (Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params)
21
+ {
22
+ ADC_InjectionConfTypeDef sConfigInjected ;
23
+
24
+ // check if all pins belong to the same ADC
25
+ ADC_TypeDef* adc_pin1 = _isset (cs_params->pins [0 ]) ? (ADC_TypeDef*)pinmap_peripheral (analogInputToPinName (cs_params->pins [0 ]), PinMap_ADC) : nullptr ;
26
+ ADC_TypeDef* adc_pin2 = _isset (cs_params->pins [1 ]) ? (ADC_TypeDef*)pinmap_peripheral (analogInputToPinName (cs_params->pins [1 ]), PinMap_ADC) : nullptr ;
27
+ ADC_TypeDef* adc_pin3 = _isset (cs_params->pins [2 ]) ? (ADC_TypeDef*)pinmap_peripheral (analogInputToPinName (cs_params->pins [2 ]), PinMap_ADC) : nullptr ;
28
+ if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) ||
29
+ ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) ||
30
+ ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3))
31
+ ){
32
+ #ifdef SIMPLEFOC_STM32_DEBUG
33
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: Analog pins dont belong to the same ADC!" );
34
+ #endif
35
+ return -1 ;
36
+ }
37
+
38
+
39
+ /* *Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
40
+ */
41
+ hadc.Instance = (ADC_TypeDef *)pinmap_peripheral (analogInputToPinName (cs_params->pins [0 ]), PinMap_ADC);
42
+
43
+ if (hadc.Instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE ();
44
+ #ifdef ADC2 // if defined ADC2
45
+ else if (hadc.Instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE ();
46
+ #endif
47
+ #ifdef ADC3 // if defined ADC3
48
+ else if (hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE ();
49
+ #endif
50
+ else {
51
+ #ifdef SIMPLEFOC_STM32_DEBUG
52
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: Pin does not belong to any ADC!" );
53
+ #endif
54
+ return -1 ; // error not a valid ADC instance
55
+ }
56
+
57
+ #ifdef SIMPLEFOC_STM32_DEBUG
58
+ SIMPLEFOC_DEBUG (" STM32-CS: Using ADC: " , _adcToIndex (&hadc)+1 );
59
+ #endif
60
+
61
+ hadc.Init .ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
62
+ hadc.Init .Resolution = ADC_RESOLUTION_12B;
63
+ hadc.Init .ScanConvMode = ENABLE;
64
+ hadc.Init .ContinuousConvMode = DISABLE;
65
+ hadc.Init .DiscontinuousConvMode = DISABLE;
66
+ hadc.Init .ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
67
+ hadc.Init .ExternalTrigConv = ADC_SOFTWARE_START; // for now
68
+ #if defined(ADC_VER_V5_V90)
69
+ // only for ADC3
70
+ if (hadc.Instance == ADC3){
71
+ hadc.Init .DataAlign = ADC3_DATAALIGN_RIGHT;
72
+ }
73
+ // more info here
74
+ // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L170C13-L170C27
75
+ hadc.Init .DMAContinuousRequests = DISABLE;
76
+ // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL
77
+ hadc.Init .SamplingMode = ADC_SAMPLING_MODE_TRIGGER_CONTROLED;
78
+ #endif
79
+ hadc.Init .NbrOfConversion = 1 ;
80
+ hadc.Init .EOCSelection = ADC_EOC_SINGLE_CONV;
81
+ if ( HAL_ADC_Init (&hadc) != HAL_OK){
82
+ #ifdef SIMPLEFOC_STM32_DEBUG
83
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: cannot init ADC!" );
84
+ #endif
85
+ return -1 ;
86
+ }
87
+
88
+ /* *Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
89
+ */
90
+ sConfigInjected .InjectedNbrOfConversion = _isset (cs_params->pins [2 ]) ? 3 : 2 ;
91
+ // if ADC1 or ADC2
92
+ if (hadc.Instance == ADC1 || hadc.Instance == ADC2){
93
+ // more info here: https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L658
94
+ sConfigInjected .InjectedNbrOfConversion = ADC_SAMPLETIME_2CYCLE_5;
95
+ }else {
96
+ // adc3
97
+ // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L673
98
+ sConfigInjected .InjectedNbrOfConversion = ADC3_SAMPLETIME_2CYCLES_5;
99
+ }
100
+ sConfigInjected .ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISINGFALLING;
101
+ sConfigInjected .AutoInjectedConv = DISABLE;
102
+ sConfigInjected .InjectedDiscontinuousConvMode = DISABLE;
103
+ sConfigInjected .InjectedOffset = 0 ;
104
+
105
+ // automating TRGO flag finding - hardware specific
106
+ uint8_t tim_num = 0 ;
107
+ for (size_t i=0 ; i<6 ; i++) {
108
+ TIM_HandleTypeDef *timer_to_check = driver_params->timers_handle [tim_num++];
109
+ TIM_TypeDef *instance_to_check = timer_to_check->Instance ;
110
+
111
+ uint32_t trigger_flag = _timerToInjectedTRGO (timer_to_check);
112
+ if (trigger_flag == _TRGO_NOT_AVAILABLE) continue ; // timer does not have valid trgo for injected channels
113
+
114
+ // check if TRGO used already - if yes use the next timer
115
+ if ((timer_to_check->Instance ->CR2 & LL_TIM_TRGO_ENABLE) || // if used for timer sync
116
+ (timer_to_check->Instance ->CR2 & LL_TIM_TRGO_UPDATE)) // if used for ADC sync
117
+ {
118
+ continue ;
119
+ }
120
+
121
+ // if the code comes here, it has found the timer available
122
+ // timer does have trgo flag for injected channels
123
+ sConfigInjected .ExternalTrigInjecConv = trigger_flag;
124
+
125
+ // this will be the timer with which the ADC will sync
126
+ cs_params->timer_handle = timer_to_check;
127
+ // done
128
+ break ;
129
+ }
130
+ if ( cs_params->timer_handle == NP ){
131
+ // not possible to use these timers for low-side current sense
132
+ #ifdef SIMPLEFOC_STM32_DEBUG
133
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: cannot sync any timer to injected channels!" );
134
+ #endif
135
+ return -1 ;
136
+ }else {
137
+ #ifdef SIMPLEFOC_STM32_DEBUG
138
+ SIMPLEFOC_DEBUG (" STM32-CS: Using timer: " , stm32_getTimerNumber (cs_params->timer_handle ->Instance ));
139
+ #endif
140
+ }
141
+
142
+ for (int i=0 ; i<3 ; i++){
143
+ // skip if not set
144
+ if (!_isset (cs_params->pins [i])) continue ;
145
+
146
+ sConfigInjected .InjectedRank = ADC_INJECTED_RANK_1 + i;
147
+ sConfigInjected .InjectedChannel = _getADCChannel (analogInputToPinName (cs_params->pins [i]));
148
+ if (HAL_ADCEx_InjectedConfigChannel (&hadc, &sConfigInjected ) != HAL_OK){
149
+ #ifdef SIMPLEFOC_STM32_DEBUG
150
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: cannot init injected channel: " , (int )_getADCChannel (analogInputToPinName (cs_params->pins [i])) );
151
+ #endif
152
+ return -1 ;
153
+ }
154
+ }
155
+
156
+ #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
157
+ // enable interrupt
158
+ HAL_NVIC_SetPriority (ADC_IRQn, 0 , 0 );
159
+ HAL_NVIC_EnableIRQ (ADC_IRQn);
160
+ #endif
161
+
162
+ cs_params->adc_handle = &hadc;
163
+ return 0 ;
164
+ }
165
+
166
+
167
+ /* *
168
+ * Function to initialize the ADC GPIO pins
169
+ *
170
+ * @param cs_params current sense parameters
171
+ * @param pinA pin number for phase A
172
+ * @param pinB pin number for phase B
173
+ * @param pinC pin number for phase C
174
+ * @return int 0 if success, -1 if error
175
+ */
176
+ int _adc_gpio_init (Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC)
177
+ {
178
+ int pins[3 ] = {pinA, pinB, pinC};
179
+ const char * port_names[3 ] = {" A" , " B" , " C" };
180
+ for (int i=0 ; i<3 ; i++){
181
+ if (_isset (pins[i])){
182
+ // check if pin is an analog pin
183
+ if (pinmap_peripheral (analogInputToPinName (pins[i]), PinMap_ADC) == NP){
184
+ #ifdef SIMPLEFOC_STM32_DEBUG
185
+ SimpleFOCDebug::print (" STM32-CS: ERR: Pin " );
186
+ SimpleFOCDebug::print (port_names[i]);
187
+ SimpleFOCDebug::println (" does not belong to any ADC!" );
188
+ #endif
189
+ return -1 ;
190
+ }
191
+ pinmap_pinout (analogInputToPinName (pins[i]), PinMap_ADC);
192
+ cs_params->pins [i] = pins[i];
193
+ }
194
+ }
195
+ return 0 ;
196
+ }
197
+
198
+ #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
199
+ extern " C" {
200
+ void ADC_IRQHandler (void )
201
+ {
202
+ HAL_ADC_IRQHandler (&hadc);
203
+ }
204
+ }
205
+ #endif
206
+
207
+ #endif
0 commit comments