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