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