SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
stm32f7_hal.cpp
Go to the documentation of this file.
1#include "stm32f7_hal.h"
2
3#if defined(STM32F7xx)
4
5//#define SIMPLEFOC_STM32_DEBUG
6
7#include "../../../../communication/SimpleFOCDebug.h"
8
9// pointer to the ADC handles used in the project
10ADC_HandleTypeDef hadc[ADC_COUNT] = {0};
11
12ADC_HandleTypeDef* _get_adc_handles(){
13 return hadc;
14}
15
16
17
18/**
19 * Function initializing the ADC for the regular channels for the low-side current sensing
20 *
21 * @param adc_instance - ADC instance to initialize
22 *
23 * @return int - 0 if success
24 */
25int _adc_init_regular(ADC_TypeDef* adc_instance)
26{
27
28 if(adc_instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE();
29#ifdef ADC2 // if defined ADC2
30 else if(adc_instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE();
31#endif
32#ifdef ADC3 // if defined ADC3
33 else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE();
34#endif
35 else{
36#ifdef SIMPLEFOC_STM32_DEBUG
37 SIMPLEFOC_DEBUG("STM32-CS: ERR: Pin does not belong to any ADC!");
38#endif
39 return -1; // error not a valid ADC instance
40 }
41
42 int adc_num = _adcToIndex(adc_instance);
43
44#ifdef SIMPLEFOC_STM32_DEBUG
45 SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1);
46#endif
47
48 hadc[adc_num].Instance = adc_instance;
49 hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
50 hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B;
51 hadc[adc_num].Init.ScanConvMode = ENABLE;
52 hadc[adc_num].Init.ContinuousConvMode = DISABLE;
53 hadc[adc_num].Init.DiscontinuousConvMode = DISABLE;
54 hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
55 hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now
56 hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT;
57 hadc[adc_num].Init.NbrOfConversion = 1;
58 hadc[adc_num].Init.DMAContinuousRequests = DISABLE;
59 hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV;
60 if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){
61#ifdef SIMPLEFOC_STM32_DEBUG
62 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!");
63#endif
64 return -1;
65 }
66 return 0;
67}
68
69/**
70 * Function initializing the ADC and the injected channels for the low-side current sensing
71 *
72 * @param cs_params - current sense parameters
73 * @param driver_params - driver parameters
74 *
75 * @return int - 0 if success
76 */
77int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params)
78{
79
80 /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
81 */
82 auto adc_instance = _findBestADCForInjectedPins(3, cs_params->pins, hadc);
83 if(adc_instance == NP){
84#ifdef SIMPLEFOC_STM32_DEBUG
85 SIMPLEFOC_DEBUG("STM32-CS: ERR: Pin does not belong to any ADC!");
86#endif
87 return -1; // error not a valid ADC instance
88 }
89 if( _adc_init_regular(adc_instance) != 0){
90 return -1;
91 }
92 int adc_num = _adcToIndex(adc_instance);
93
94#ifdef SIMPLEFOC_STM32_DEBUG
95 SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1);
96#endif
97
98
99 ADC_InjectionConfTypeDef sConfigInjected;
100
101 /**Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
102 */
103 sConfigInjected.InjectedNbrOfConversion = 0;
104 for(int pin_no=0; pin_no<3; pin_no++){
105 if(_isset(cs_params->pins[pin_no])){
106 sConfigInjected.InjectedNbrOfConversion++;
107 }
108 }
109 sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_3CYCLES;
110 sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISINGFALLING;
111 sConfigInjected.AutoInjectedConv = DISABLE;
112 sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
113 sConfigInjected.InjectedOffset = 0;
114
115 // automating TRGO flag finding - hardware specific
116 uint8_t tim_num = 0;
117 for (size_t i=0; i<6; i++) {
118 TIM_HandleTypeDef *timer_to_check = driver_params->timers_handle[tim_num++];
119 TIM_TypeDef *instance_to_check = timer_to_check->Instance;
120
121 uint32_t trigger_flag = _timerToInjectedTRGO(timer_to_check);
122 if(trigger_flag == _TRGO_NOT_AVAILABLE) continue; // timer does not have valid trgo for injected channels
123
124 // check if TRGO used already - if yes use the next timer
125 if((timer_to_check->Instance->CR2 & LL_TIM_TRGO_ENABLE) || // if used for timer sync
126 (timer_to_check->Instance->CR2 & LL_TIM_TRGO_UPDATE)) // if used for ADC sync
127 {
128 continue;
129 }
130
131 // if the code comes here, it has found the timer available
132 // timer does have trgo flag for injected channels
133 sConfigInjected.ExternalTrigInjecConv = trigger_flag;
134
135 // this will be the timer with which the ADC will sync
136 cs_params->timer_handle = timer_to_check;
137 if (!IS_TIM_REPETITION_COUNTER_INSTANCE(instance_to_check)) {
138 // workaround for errata 2.2.1 in ES0290 Rev 7
139 // https://www.st.com/resource/en/errata_sheet/es0290-stm32f74xxx-and-stm32f75xxx-device-limitations-stmicroelectronics.pdf
140 __HAL_RCC_DAC_CLK_ENABLE();
141 }
142 // done
143 break;
144 }
145 if( cs_params->timer_handle == NP ){
146 // not possible to use these timers for low-side current sense
147 #ifdef SIMPLEFOC_STM32_DEBUG
148 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot sync any timer to injected channels!");
149 #endif
150 return -1;
151 }else{
152#ifdef SIMPLEFOC_STM32_DEBUG
153 SIMPLEFOC_DEBUG("STM32-CS: Using timer: ", stm32_getTimerNumber(cs_params->timer_handle->Instance));
154#endif
155 }
156
157 uint8_t channel_no = 0;
158 for(int i=0; i<3; i++){
159 // skip if not set
160 if (!_isset(cs_params->pins[i])) continue;
161
162 sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++);
163 sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance);
164#ifdef SIMPLEFOC_STM32_DEBUG
165 SIMPLEFOC_DEBUG("STM32-CS: ADC channel: ", (int)STM_PIN_CHANNEL(pinmap_function(PinMap_ADC[i].pin, PinMap_ADC)));
166#endif
167 if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){
168 #ifdef SIMPLEFOC_STM32_DEBUG
169 SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance));
170 #endif
171 return -1;
172 }
173 }
174
175 cs_params->adc_handle = &hadc[adc_num];
176 return 0;
177}
178
179
180/**
181 * Function to initialize the ADC GPIO pins
182 *
183 * @param cs_params current sense parameters
184 * @param pinA pin number for phase A
185 * @param pinB pin number for phase B
186 * @param pinC pin number for phase C
187 * @return int 0 if success, -1 if error
188 */
189int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC)
190{
191 int pins[3] = {pinA, pinB, pinC};
192 const char* port_names[3] = {"A", "B", "C"};
193 for(int i=0; i<3; i++){
194 if(_isset(pins[i])){
195 // check if pin is an analog pin
196 if(pinmap_peripheral(analogInputToPinName(pins[i]), PinMap_ADC) == NP){
197
198#if defined(SIMPLEFOC_STM32_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
199 SimpleFOCDebug::print("STM32-CS: ERR: Pin ");
200 SimpleFOCDebug::print(port_names[i]);
201 SimpleFOCDebug::println(" does not belong to any ADC!");
202#endif
203 return -1;
204 }
205 pinmap_pinout(analogInputToPinName(pins[i]), PinMap_ADC);
206 cs_params->pins[i] = pins[i];
207 }
208 }
209 return 0;
210}
211
212extern "C" {
213 void ADC_IRQHandler(void)
214 {
215 for(int adc_num=0; adc_num<ADC_COUNT; adc_num++){
216 if(hadc[adc_num].Instance == NP) continue;
217 HAL_ADC_IRQHandler(&hadc[adc_num]);
218 }
219 }
220}
221
222#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