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