FSM thermostat
port_system.c
Go to the documentation of this file.
1 
8 /* Includes ------------------------------------------------------------------*/
9 #include "port_system.h"
10 
11 /* Defines -------------------------------------------------------------------*/
12 #define HSI_VALUE ((uint32_t)16000000)
14 /* GLOBAL VARIABLES */
15 static volatile uint32_t msTicks = 0;
17 /* These variables are declared extern in CMSIS (system_stm32f4xx.h) */
19 const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
20 const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
22 //------------------------------------------------------
23 // SYSTEM CONFIGURATION
24 //------------------------------------------------------
32 void SystemInit(void)
33 {
34 /* FPU settings ------------------------------------------------------------*/
35 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
36  SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */
37 #endif
38 
39 #if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
40  SystemInit_ExtMemCtl();
41 #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
42 
43  /* Configure the Vector Table location -------------------------------------*/
44 #if defined(USER_VECT_TAB_ADDRESS)
45  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
46 #endif /* USER_VECT_TAB_ADDRESS */
47 }
48 
57 {
59  /* Power controller (PWR) */
60  /* Control the main internal voltage regulator output voltage to achieve a trade-off between performance and power consumption when the device does not operate at the maximum frequency */
61  PWR->CR &= ~PWR_CR_VOS; // Clean and set value
62  PWR->CR |= (PWR_CR_VOS & (POWER_REGULATOR_VOLTAGE_SCALE3 << PWR_CR_VOS_Pos));
63 
64  /* Initializes the RCC Oscillators. */
65  /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
66  RCC->CR &= ~RCC_CR_HSITRIM; // Clean and set value
67  RCC->CR |= (RCC_CR_HSITRIM & (RCC_HSI_CALIBRATION_DEFAULT << RCC_CR_HSITRIM_Pos));
68 
69  /* RCC Clock Config */
70  /* Initializes the CPU, AHB and APB buses clocks */
71  /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
72  must be correctly programmed according to the frequency of the CPU clock
73  (HCLK) and the supply voltage of the device. */
74 
75  /* Increasing the number of wait states because of higher CPU frequency */
76  FLASH->ACR = FLASH_ACR_LATENCY_2WS; /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
77 
78  /* Change in clock source is performed in 16 clock cycles after writing to CFGR */
79  RCC->CFGR &= ~RCC_CFGR_SW; // Clean and set value
80  RCC->CFGR |= (RCC_CFGR_SW & (RCC_CFGR_SW_HSI << RCC_CFGR_SW_Pos));
81 
82  /* Update the SystemCoreClock global variable */
83  SystemCoreClock = HSI_VALUE >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos];
84 
85  /* Configure the source of time base considering new system clocks settings */
86  SysTick_Config(SystemCoreClock / (1000U / TICK_FREQ_1KHZ)); /* Set Systick to 1 ms */
87 }
88 
90 {
91  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
92  /* Configure Flash prefetch, Instruction cache, Data cache */
93  /* Instruction cache enable */
94  FLASH->ACR |= FLASH_ACR_ICEN;
95 
96  /* Data cache enable */
97  FLASH->ACR |= FLASH_ACR_DCEN;
98 
99  /* Prefetch cache enable */
100  FLASH->ACR |= FLASH_ACR_PRFTEN;
101 
102  /* Set Interrupt Group Priority */
103  NVIC_SetPriorityGrouping(NVIC_PRIORITY_GROUP_4);
104 
105  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
106  /* Configure the SysTick IRQ priority. It must be the highest (lower number: 0)*/
107  NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0U, 0U)); /* Tick interrupt priority */
108 
109  /* Init the low level hardware */
110  /* Reset and clock control (RCC) */
111  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; /* Syscfg clock enabling */
112 
113  /* Peripheral clock enable register */
114  RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* PWREN: Power interface clock enable */
115 
116  /* Configure the system clock */
118 
119  return 0;
120 }
121 
122 //------------------------------------------------------
123 // TIMER RELATED FUNCTIONS
124 //------------------------------------------------------
126 {
127  return msTicks;
128 }
129 
130 void port_system_set_millis(uint32_t ms)
131 {
132  msTicks = ms;
133 }
134 
135 void port_system_delay_ms(uint32_t ms)
136 {
137  uint32_t tickstart = port_system_get_millis();
138 
139  while ((port_system_get_millis() - tickstart) < ms)
140  {
141  }
142 }
143 
144 void port_system_delay_until_ms(uint32_t *p_t, uint32_t ms)
145 {
146  uint32_t until = *p_t + ms;
147  uint32_t now = port_system_get_millis();
148  if (until > now)
149  {
150  port_system_delay_ms(until - now);
151  }
152  *p_t = port_system_get_millis();
153 }
154 
155 //------------------------------------------------------
156 // GPIO RELATED FUNCTIONS
157 //------------------------------------------------------
158 void port_system_gpio_config(GPIO_TypeDef *p_port, uint8_t pin, uint8_t mode, uint8_t pupd)
159 {
160  if (p_port == GPIOA)
161  {
162  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; /* GPIOA_CLK_ENABLE */
163  }
164  else if (p_port == GPIOB)
165  {
166  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; /* GPIOB_CLK_ENABLE */
167  }
168  else if (p_port == GPIOC)
169  {
170  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; /* GPIOC_CLK_ENABLE */
171  }
172 
173  /* Clean ( &=~ ) by displacing the base register and set the configuration ( |= ) */
174  p_port->MODER &= ~(GPIO_MODER_MODER0 << (pin * 2U));
175  p_port->MODER |= (mode << (pin * 2U));
176 
177  p_port->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (pin * 2U));
178  p_port->PUPDR |= (pupd << (pin * 2U));
179 }
180 
181 void port_system_gpio_config_exti(GPIO_TypeDef *p_port, uint8_t pin, uint32_t mode)
182 {
183  uint32_t port_selector = 0;
184 
185  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
186 
187  /* SYSCFG external interrupt configuration register */
188  if (p_port == GPIOA)
189  {
190  port_selector = 0;
191  }
192  else if (p_port == GPIOB)
193  {
194  port_selector = 1;
195  }
196  else if (p_port == GPIOC)
197  {
198  port_selector = 2;
199  }
200 
201  uint32_t base_mask = 0x0FU;
202  uint32_t displacement = (pin % 4) * 4;
203 
204  SYSCFG->EXTICR[pin / 4] &= ~(base_mask << displacement);
205  SYSCFG->EXTICR[pin / 4] |= (port_selector << displacement);
206 
207  /* Rising trigger selection register (EXTI_RTSR) */
208  EXTI->RTSR &= ~BIT_POS_TO_MASK(pin);
209  if (mode & TRIGGER_RISING_EDGE)
210  {
211  EXTI->RTSR |= BIT_POS_TO_MASK(pin);
212  }
213 
214  /* Falling trigger selection register (EXTI_FTSR) */
215  EXTI->FTSR &= ~BIT_POS_TO_MASK(pin);
216  if (mode & TRIGGER_FALLING_EDGE)
217  {
218  EXTI->FTSR |= BIT_POS_TO_MASK(pin);
219  }
220 
221  /* Event mask register (EXTI_EMR) */
222  EXTI->EMR &= ~BIT_POS_TO_MASK(pin);
223  if (mode & TRIGGER_ENABLE_EVENT_REQ)
224  {
225  EXTI->EMR |= BIT_POS_TO_MASK(pin);
226  }
227 
228  /* Clear EXTI line configuration */
229  EXTI->IMR &= ~BIT_POS_TO_MASK(pin);
230 
231  /* Interrupt mask register (EXTI_IMR) */
232  if (mode & TRIGGER_ENABLE_INTERR_REQ)
233  {
234  EXTI->IMR |= BIT_POS_TO_MASK(pin);
235  }
236 }
237 
238 void port_system_gpio_exti_enable(uint8_t pin, uint8_t priority, uint8_t subpriority)
239 {
240  NVIC_SetPriority(GET_PIN_IRQN(pin), NVIC_EncodePriority(NVIC_GetPriorityGrouping(), priority, subpriority));
241  NVIC_EnableIRQ(GET_PIN_IRQN(pin));
242 }
243 
245 {
246  NVIC_DisableIRQ(GET_PIN_IRQN(pin));
247 }
248 
249 void port_system_gpio_config_alternate(GPIO_TypeDef *p_port, uint8_t pin, uint8_t alternate)
250 {
251  uint32_t base_mask = 0x0FU;
252  uint32_t displacement = (pin % 8) * 4;
253 
254  p_port->AFR[(uint8_t)(pin / 8)] &= ~(base_mask << displacement);
255  p_port->AFR[(uint8_t)(pin / 8)] |= (alternate << displacement);
256 }
257 
258 //----------------------processing--------------------------------
259 // ADC RELATED FUNCTIONS
260 //------------------------------------------------------
261 void port_system_adc_single_ch_init(ADC_TypeDef *p_adc, uint8_t channel, uint32_t cr_mode)
262 {
263  // First of all, enable the source clock of the ADC before configuring any of its registers
264  if (p_adc == ADC1)
265  {
266  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* ADC1_CLK_ENABLE */
267  }
268  else if (p_adc == ADC2)
269  {
270  RCC->APB2ENR |= RCC_APB2ENR_ADC2EN; /* ADC2_CLK_ENABLE */
271  }
272  else if (p_adc == ADC3)
273  {
274  RCC->APB2ENR |= RCC_APB2ENR_ADC3EN; /* ADC3_CLK_ENABLE */
275  }
276 
277  //-------------------------------------------------------------------------------------------
278  // ADC common configuration (ADC common control register (ADC_CCR))
279  //-------------------------------------------------------------------------------------------
280  // Reset the ADC (common to all ADCs)
281  RCC->APB2RSTR |= RCC_APB2RSTR_ADCRST;
282 
283  // Short delay
284  __NOP(); // Also can be used (void)RCC->AHB2RSTR; as an example
285 
286  // Clear the reset of the ADC (common to all ADCs)
287  RCC->APB2RSTR &= ~RCC_APB2RSTR_ADCRST;
288 
289 #if defined(USE_ADC_TEMP_VREFINT)
290  // Temperature sensor and Vref internal channels enable
291  ADC123_COMMON->CCR |= ADC_CCR_TSVREFE;
292 #endif
293 
294  // ADC prescaler to select the frequency of the clock to the ADC. By default, input ADC clock PCLK2 divided by 2.
295  // The clock of the ADC (ADCCLK) is common to all the ADCs. The clock is generated from the APB2 clock divided by a programmable prescaler (ADCPRE) that allows the ADC to work at a frequencies of fPCLK2/2, fPCLK2/4, fPCLK2/6, or fPCLK2/8.
296  ADC123_COMMON->CCR &= ~ADC_CCR_ADCPRE;
297 
298  // DMA configuration (DMA mode). 0: DMA mode disabled by default.
299  ADC123_COMMON->CCR &= ~ADC_CCR_DMA;
300 
301  // Delay between 2 sampling phases. By default, 0000: 5*T_ADCCLK. This is used in dual and triple interleaved modes.
302  ADC123_COMMON->CCR &= ~ADC_CCR_DELAY;
303 
304  // Multi ADC mode selection. By default, 00000; All ADCs independent.
305  ADC123_COMMON->CCR &= ~ADC_CCR_MULTI;
306 
307  //-------------------------------------------------------------------------------------------
308  // ADC particular configuration (ADCx control register (ADC_CR1 and ADC_CR2))
309  //-------------------------------------------------------------------------------------------
310  // Disable the ADC
311  p_adc->CR2 &= ~ADC_CR2_ADON;
312 
313  // ADC continuous conversion mode. 0: Single conversion mode by default.
314  p_adc->CR2 &= ~ADC_CR2_CONT;
315 
316  // ADC DMA mode selection. 0: DMA mode disabled by default.
317  p_adc->CR2 &= ~ADC_CR2_DMA;
318 
319  // ADC End of conversion selection in single mode. 1: End of conversion by EOC bit by default.
320  p_adc->CR2 |= ADC_CR2_EOCS;
321 
322  // ADC alignment. 0: Right alignment by default.
323  p_adc->CR2 &= ~ADC_CR2_ALIGN;
324 
325  // ADC configuration register 1 (ADC_CR1)
326  p_adc->CR1 = 0;
327 
328  // Set some configuration bits of the ADC_CR1 register that are currently available to be set in this PORT implementation
329  // Interrupt enable (EOC, EOS, AWD, JEOC, JEOS)
330  p_adc->CR1 |= (cr_mode & ADC_CR1_EOCIE_Msk);
331 
332  // Resolution of the ADC. 00: 12-bit resolution by default.
333  p_adc->CR1 |= (cr_mode & ADC_CR1_RES_Msk);
334 
335  // Sampling time selection for the regular channels. 000: 3 cycles by default, for simplicity.
336  channel &= 0x1FU; // Only 16 channels are available
337 
338  if (channel < 10)
339  {
340  p_adc->SMPR2 &= ~(ADC_SMPR2_SMP0 << (channel * 3));
341  }
342  else
343  {
344  p_adc->SMPR1 &= ~(ADC_SMPR1_SMP10 << ((channel - 10) * 3));
345  }
346 
347  // Indicate how many channels are going to be converted in the sequence. 1 conversion by default.
348  p_adc->SQR1 &= ~ADC_SQR1_L;
349 }
350 
351 void port_system_adc_interrupt_enable(uint8_t priority, uint8_t subpriority)
352 {
353  NVIC_SetPriority(ADC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), priority, subpriority));
354  NVIC_EnableIRQ(ADC_IRQn);
355 }
356 
357 void port_system_adc_enable(ADC_TypeDef *p_adc)
358 {
359  // Enable the ADC
360  p_adc->CR2 |= ADC_CR2_ADON;
361 
362  // Wait for the ADC to be ready (approximately 10 us)
363  uint32_t delay = 10000;
364  while (delay--)
365  ;
366 }
367 
368 void port_system_adc_disable(ADC_TypeDef *p_adc)
369 {
370  // Disable the ADC
371  p_adc->CR2 &= ~ADC_CR2_ADON;
372 }
373 
374 void port_system_adc_start_conversion(ADC_TypeDef *p_adc, uint8_t channel)
375 {
376  channel &= 0x1FU; // Only 16 channels are available
377 
378  // Since we are going to convert only one channel, we are going to use the first sequence register
379  p_adc->SQR3 = 0;
380  p_adc->SQR3 = channel;
381 
382  // Clear the status register
383  p_adc->SR = 0;
384 
385  // Start the conversion
386  p_adc->CR2 |= ADC_CR2_SWSTART;
387 }
388 
389 // ------------------------------------------------------
390 // POWER RELATED FUNCTIONS
391 // ------------------------------------------------------
port_system_gpio_config
void port_system_gpio_config(GPIO_TypeDef *p_port, uint8_t pin, uint8_t mode, uint8_t pupd)
Configure the mode and pull of a GPIO.
Definition: port_system.c:158
TICK_FREQ_1KHZ
#define TICK_FREQ_1KHZ
Definition: port_system.h:29
RCC_HSI_CALIBRATION_DEFAULT
#define RCC_HSI_CALIBRATION_DEFAULT
Definition: port_system.h:28
APBPrescTable
const uint8_t APBPrescTable[8]
Definition: port_system.c:20
system_clock_config
void system_clock_config(void)
System Clock Configuration.
Definition: port_system.c:56
port_system_adc_single_ch_init
void port_system_adc_single_ch_init(ADC_TypeDef *p_adc, uint8_t channel, uint32_t cr_mode)
Configure the ADC peripheral for a single channel.
Definition: port_system.c:261
port_system_delay_until_ms
void port_system_delay_until_ms(uint32_t *p_t, uint32_t ms)
Wait for some milliseconds from a time reference.
Definition: port_system.c:144
port_system_gpio_config_alternate
void port_system_gpio_config_alternate(GPIO_TypeDef *p_port, uint8_t pin, uint8_t alternate)
Configure the alternate function of a GPIO.
Definition: port_system.c:249
port_system_adc_disable
void port_system_adc_disable(ADC_TypeDef *p_adc)
Disable the ADC peripheral.
Definition: port_system.c:368
SystemCoreClock
uint32_t SystemCoreClock
Definition: port_system.c:18
port_system_get_millis
uint32_t port_system_get_millis()
Get the count of the System tick in milliseconds.
Definition: port_system.c:125
TRIGGER_FALLING_EDGE
#define TRIGGER_FALLING_EDGE
Definition: port_system.h:53
port_system_gpio_config_exti
void port_system_gpio_config_exti(GPIO_TypeDef *p_port, uint8_t pin, uint32_t mode)
Configure the external interruption or event of a GPIO.
Definition: port_system.c:181
TRIGGER_RISING_EDGE
#define TRIGGER_RISING_EDGE
Definition: port_system.h:52
port_system_set_millis
void port_system_set_millis(uint32_t ms)
Sets the number of milliseconds since the system started.
Definition: port_system.c:130
TRIGGER_ENABLE_EVENT_REQ
#define TRIGGER_ENABLE_EVENT_REQ
Definition: port_system.h:55
NVIC_PRIORITY_GROUP_4
#define NVIC_PRIORITY_GROUP_4
Definition: port_system.h:32
SystemInit
void SystemInit(void)
Setup the microcontroller system Initialize the FPU setting, vector table location and External memor...
Definition: port_system.c:32
POWER_REGULATOR_VOLTAGE_SCALE3
#define POWER_REGULATOR_VOLTAGE_SCALE3
Definition: port_system.h:36
port_system_gpio_exti_enable
void port_system_gpio_exti_enable(uint8_t pin, uint8_t priority, uint8_t subpriority)
Enable interrupts of a GPIO line (pin)
Definition: port_system.c:238
port_system.h
Header for port_system.c file.
port_system_gpio_exti_disable
void port_system_gpio_exti_disable(uint8_t pin)
Disable interrupts of a GPIO line (pin)
Definition: port_system.c:244
port_system_adc_enable
void port_system_adc_enable(ADC_TypeDef *p_adc)
Enable the ADC peripheral to work.
Definition: port_system.c:357
port_system_init
size_t port_system_init()
This function is based on the initialization of the HAL Library; it must be the first thing to be exe...
Definition: port_system.c:89
TRIGGER_ENABLE_INTERR_REQ
#define TRIGGER_ENABLE_INTERR_REQ
Definition: port_system.h:56
GET_PIN_IRQN
#define GET_PIN_IRQN(pin)
Definition: port_system.h:24
BIT_POS_TO_MASK
#define BIT_POS_TO_MASK(x)
Definition: port_system.h:22
HSI_VALUE
#define HSI_VALUE
Definition: port_system.c:12
port_system_adc_start_conversion
void port_system_adc_start_conversion(ADC_TypeDef *p_adc, uint8_t channel)
Start the conversion of the ADC peripheral.
Definition: port_system.c:374
AHBPrescTable
const uint8_t AHBPrescTable[16]
Definition: port_system.c:19
port_system_delay_ms
void port_system_delay_ms(uint32_t ms)
Wait for some milliseconds.
Definition: port_system.c:135
port_system_adc_interrupt_enable
void port_system_adc_interrupt_enable(uint8_t priority, uint8_t subpriority)
Enable the ADC global interrupts in NVIC. ADC1, ADC2, and ADC3 share the same interrupt.
Definition: port_system.c:351
msTicks
static volatile uint32_t msTicks
Definition: port_system.c:15