MCAL.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: Beerware
2 /**
3  * @file MCAL.c
4  * @brief Microcontroller Abstraction Layer
5  * @details MCAL for STM32F1xx microcontroller
6  * @author Michael Fitzmayer
7  * @copyright "THE BEER-WARE LICENCE" (Revision 42)
8  */
9 
10 #include <stdbool.h>
11 #include <stdint.h>
12 #include "MCAL.h"
13 #include "stm32f1xx_hal.h"
14 #include "stm32f1xx_hal_i2c.h"
15 #include "stm32f1xx_hal_spi.h"
16 #include "stm32f1xx_hal_rtc.h"
17 #include "stm32f1xx_hal_tim.h"
18 
19 extern I2C_HandleTypeDef hi2c2;
20 extern SPI_HandleTypeDef hspi1;
21 extern RTC_HandleTypeDef hrtc;
22 extern TIM_HandleTypeDef htim1;
23 
24 static GPIO_TypeDef* _MCAL_ConvertGPIOPort(GPIOPort ePort);
25 
26 /**
27  * @brief Read current input pin state
28  * @param ePort
29  * GPIO port
30  * @param u16PinMask
31  * Pin mask
32  * @return Boolean state
33  * @retval true: Pin is high
34  * @retval false: Pin is low
35  */
36 bool GPIO_IsSet(GPIOPort ePort, uint16_t u16PinMask)
37 {
38  GPIO_TypeDef* phPort = _MCAL_ConvertGPIOPort(ePort);
39 
40  if (HAL_GPIO_ReadPin(phPort, u16PinMask))
41  {
42  return true;
43  }
44  else
45  {
46  return false;
47  }
48 }
49 
50 /**
51  * @brief Pull output pin(s) low
52  * @param ePort
53  * GPIO port
54  * @param u16PinMask
55  * Pin mask
56  */
57 void GPIO_PullDown(GPIOPort ePort, uint16_t u16PinMask)
58 {
59  GPIO_TypeDef* phPort = _MCAL_ConvertGPIOPort(ePort);
60  HAL_GPIO_WritePin(phPort, u16PinMask, GPIO_PIN_RESET);
61 }
62 
63 /**
64  * @brief Raise output pin(s) high
65  * @param ePort
66  * GPIO port
67  * @param u16PinMask
68  * Pin mask
69  */
70 void GPIO_RaiseHigh(GPIOPort ePort, uint16_t u16PinMask)
71 {
72  GPIO_TypeDef* phPort = _MCAL_ConvertGPIOPort(ePort);
73  HAL_GPIO_WritePin(phPort, u16PinMask, GPIO_PIN_SET);
74 }
75 
76 /**
77  * @brief Toggle output pin(s) between high and low
78  * @param ePort
79  * GPIO port
80  * @param u16PinMask
81  * Pin mask
82  */
83 void GPIO_Toggle(GPIOPort ePort, uint16_t u16PinMask)
84 {
85  GPIO_TypeDef* phPort = _MCAL_ConvertGPIOPort(ePort);
86  HAL_GPIO_TogglePin(phPort, u16PinMask);
87 }
88 
89 /**
90  * @brief Receive an amount via I²C
91  * @param u16DevAddress
92  * Target device address
93  * @param u16MemAddress
94  * Internal memory address
95  * @param eMemAddSize
96  * Memory address size
97  * @param pu8RxBuffer
98  * Pointer to data buffer
99  * @param u16Size
100  * Amount of data to be sent
101  * @return Error code
102  * @retval 0: OK
103  * @retval -1: Error
104  */
105 int I2C_Receive(uint16_t u16DevAddress, uint16_t u16MemAddress, I2CMemAddSize eMemAddSize, uint8_t* pu8RxBuffer, uint16_t u16Size)
106 {
107  uint16_t u16MemAddSize = 0;
108 
109  switch (eMemAddSize)
110  {
111  case I2C_MEMSIZE_8BIT:
112  u16MemAddSize = I2C_MEMADD_SIZE_8BIT;
113  break;
114  case I2C_MEMSIZE_16BIT:
115  u16MemAddSize = I2C_MEMADD_SIZE_16BIT;
116  break;
117  }
118 
119  if (HAL_OK != HAL_I2C_Mem_Read_IT(
120  &hi2c2,
121  u16DevAddress,
122  u16MemAddress,
123  u16MemAddSize,
124  pu8RxBuffer,
125  u16Size))
126  {
127  return -1;
128  }
129 
130  return 0;
131 }
132 
133 /**
134  * @brief Transmit an amount via I²C
135  * @param u16DevAddress
136  * Target device address
137  * @param u16MemAddress
138  * Internal memory address
139  * @param eMemAddSize
140  * Memory address size
141  * @param pu8TxBuffer
142  * Pointer to data buffer
143  * @param u16Size
144  * Amount of data to be sent
145  * @return Error code
146  * @retval 0: OK
147  * @retval -1: Error
148  */
149 int I2C_Transmit(uint16_t u16DevAddress, uint16_t u16MemAddress, I2CMemAddSize eMemAddSize, uint8_t* pu8TxBuffer, uint16_t u16Size)
150 {
151  uint16_t u16MemAddSize = 0;
152 
153  switch (eMemAddSize)
154  {
155  case I2C_MEMSIZE_8BIT:
156  u16MemAddSize = I2C_MEMADD_SIZE_8BIT;
157  break;
158  case I2C_MEMSIZE_16BIT:
159  u16MemAddSize = I2C_MEMADD_SIZE_16BIT;
160  break;
161  }
162 
163  if (HAL_OK != HAL_I2C_Mem_Write_IT(
164  &hi2c2,
165  u16DevAddress,
166  u16MemAddress,
167  u16MemAddSize,
168  pu8TxBuffer,
169  u16Size))
170  {
171  return -1;
172  }
173 
174  return 0;
175 }
176 
177 /**
178  * @brief Wait for the end of the transfer
179  * @details Before starting a new communication transfer, the CPU need
180  * to check the current state of the peripheral; if it's busy
181  * the CPU need to wait for the end of current transfer before
182  * starting a new one.
183  * @param u16DevAddress
184  * Target device address
185  */
186 void I2C_WaitUntilReady(uint16_t u16DevAddress)
187 {
188  while (HAL_I2C_STATE_READY != HAL_I2C_GetState(&hi2c2));
189 
190  while (HAL_TIMEOUT == HAL_I2C_IsDeviceReady(
191  &hi2c2,
192  u16DevAddress,
193  100,
194  100));
195 
196  while (HAL_I2C_STATE_READY != HAL_I2C_GetState(&hi2c2))
197  {
198  MCAL_Sleep(1);
199  }
200 }
201 
202 /**
203  * @brief Microsecond delay (blocking)
204  * @param u16DelayInUs
205  * Delay in microseconds
206  */
207 void MCAL_Sleep(uint16_t u16DelayInUs)
208 {
209  __HAL_TIM_SET_COUNTER(&htim1, 0);
210  while (u16DelayInUs > __HAL_TIM_GET_COUNTER(&htim1));
211 }
212 
213 /**
214  * @brief Get current time from RTC
215  * @param pu8Hours
216  * Pointer to hours
217  * @param pu8Minutes
218  * Pointer to minutes
219  * @param pu8Seconds
220  * Pointer to seconds
221  * @return Error code
222  * @retval 0: OK
223  * @retval -1: Error
224  */
225 int RTC_GetTime(uint8_t* pu8Hours, uint8_t* pu8Minutes, uint8_t* pu8Seconds)
226 {
227  RTC_TimeTypeDef stTime = { 0 };
228 
229  if (HAL_OK != HAL_RTC_GetTime(&hrtc, &stTime, RTC_FORMAT_BIN))
230  {
231  return -1;
232  }
233 
234  *pu8Hours = stTime.Hours;
235  *pu8Minutes = stTime.Minutes;
236  *pu8Seconds = stTime.Seconds;
237 
238  return 0;
239 }
240 
241 /**
242  * @brief Set current RTC time
243  * @param u8Hours
244  * Hours
245  * @param u8Minutes
246  * Minutes
247  * @param u8Seconds
248  * Seconds
249  * @return Error code
250  * @retval 0: OK
251  * @retval -1: Error
252  */
253 int RTC_SetTime(uint8_t u8Hours, uint8_t u8Minutes, uint8_t u8Seconds)
254 {
255  RTC_TimeTypeDef stTime = { 0 };
256 
257  stTime.Hours = u8Hours;
258  stTime.Minutes = u8Minutes;
259  stTime.Seconds = u8Seconds;
260 
261  if (HAL_OK != HAL_RTC_SetTime(&hrtc, &stTime, RTC_FORMAT_BIN))
262  {
263  return -1;
264  }
265 
266  return 0;
267 }
268 
269 /**
270  * @brief Transmit an amount via SPI
271  * @param pu8TxData
272  * Pointer to data buffer
273  * @param u16Size
274  * Amount of data to be sent
275  * @return Error code
276  * @retval 0: OK
277  * @retval -1: Error
278  */
279 int SPI_Transmit(uint8_t* pu8TxData, uint16_t u16Size)
280 {
281  if (HAL_OK != HAL_SPI_Transmit_IT(&hspi1, pu8TxData, u16Size))
282  {
283  return -1;
284  }
285 
286  return 0;
287 }
288 
289 /**
290  * @brief Receive an amount of data via SPI
291  * @param pu8RxData
292  * Pointer to data buffer
293  * @param u16Size
294  * Amount of data to be sent
295  * @return Error code
296  * @retval 0: OK
297  * @retval -1: Error
298  */
299 int SPI_Receive(uint8_t* pu8RxData, uint16_t u16Size)
300 {
301  if (HAL_OK != HAL_SPI_Receive_IT(&hspi1, pu8RxData, u16Size))
302  {
303  return -1;
304  }
305 
306  return 0;
307 }
308 
309 /**
310  * @brief Transmit and Receive an amount of data via SPI
311  * @param pu8TxData
312  * Pointer to transmission data buffer
313  * @param pu8RxData
314  * Pointer to reception data buffer
315  * @param u16Size
316  * Amount of data to be sent and received
317  * @return Error code
318  * @retval 0: OK
319  * @retval -1: Error
320  */
321 int SPI_TransmitReceive(uint8_t* pu8TxData, uint8_t* pu8RxData, uint16_t u16Size)
322 {
323  if (HAL_OK != HAL_SPI_TransmitReceive_IT(&hspi1, pu8TxData, pu8RxData, u16Size))
324  {
325  return -1;
326  }
327 
328  return 0;
329 }
330 
331 /**
332  * @brief Convert GPIOPort to STM32_HAL's GPIO_TypeDef
333  * @param ePort
334  * GPIO port
335  * @return Pointer to respective GPIO_TypeDef
336  */
337 static GPIO_TypeDef* _MCAL_ConvertGPIOPort(GPIOPort ePort)
338 {
339  GPIO_TypeDef* phPort = GPIOA;
340 
341  switch (ePort)
342  {
343  case GPIO_PORT_A:
344  phPort = GPIOA;
345  break;
346  case GPIO_PORT_B:
347  phPort = GPIOB;
348  break;
349  case GPIO_PORT_C:
350  phPort = GPIOC;
351  break;
352  case GPIO_PORT_D:
353  phPort = GPIOD;
354  break;
355  }
356 
357  return phPort;
358 }
int SPI_TransmitReceive(uint8_t *pu8TxData, uint8_t *pu8RxData, uint16_t u16Size)
Transmit and Receive an amount of data via SPI.
Definition: MCAL.c:321
TIM_HandleTypeDef htim1
Timer 1 handle.
Definition: System.c:49
@ GPIO_PORT_C
GPIO port C.
Definition: MCAL.h:21
I2C_HandleTypeDef hi2c2
I²C 2 handle.
Definition: System.c:46
void GPIO_Toggle(GPIOPort ePort, uint16_t u16PinMask)
Toggle output pin(s) between high and low.
Definition: MCAL.c:83
void GPIO_RaiseHigh(GPIOPort ePort, uint16_t u16PinMask)
Raise output pin(s) high.
Definition: MCAL.c:70
int RTC_GetTime(uint8_t *pu8Hours, uint8_t *pu8Minutes, uint8_t *pu8Seconds)
Get current time from RTC.
Definition: MCAL.c:225
void I2C_WaitUntilReady(uint16_t u16DevAddress)
Wait for the end of the transfer.
Definition: MCAL.c:186
void GPIO_PullDown(GPIOPort ePort, uint16_t u16PinMask)
Pull output pin(s) low.
Definition: MCAL.c:57
static GPIO_TypeDef * _MCAL_ConvertGPIOPort(GPIOPort ePort)
Convert GPIOPort to STM32_HAL's GPIO_TypeDef.
Definition: MCAL.c:337
I2CMemAddSize
I²C memory address size.
Definition: MCAL.h:30
@ GPIO_PORT_B
GPIO port B.
Definition: MCAL.h:20
void MCAL_Sleep(uint16_t u16DelayInUs)
Microsecond delay (blocking)
Definition: MCAL.c:207
int I2C_Receive(uint16_t u16DevAddress, uint16_t u16MemAddress, I2CMemAddSize eMemAddSize, uint8_t *pu8RxBuffer, uint16_t u16Size)
Receive an amount via I²C.
Definition: MCAL.c:105
RTC_HandleTypeDef hrtc
RTC handle.
Definition: System.c:48
Microcontroller Abstraction Layer.
bool GPIO_IsSet(GPIOPort ePort, uint16_t u16PinMask)
Read current input pin state.
Definition: MCAL.c:36
int RTC_SetTime(uint8_t u8Hours, uint8_t u8Minutes, uint8_t u8Seconds)
Set current RTC time.
Definition: MCAL.c:253
@ I2C_MEMSIZE_16BIT
I²C memory address size (16-Bit)
Definition: MCAL.h:33
int SPI_Receive(uint8_t *pu8RxData, uint16_t u16Size)
Receive an amount of data via SPI.
Definition: MCAL.c:299
GPIOPort
GPIO ports.
Definition: MCAL.h:17
int SPI_Transmit(uint8_t *pu8TxData, uint16_t u16Size)
Transmit an amount via SPI.
Definition: MCAL.c:279
@ GPIO_PORT_D
GPIO port D.
Definition: MCAL.h:22
int I2C_Transmit(uint16_t u16DevAddress, uint16_t u16MemAddress, I2CMemAddSize eMemAddSize, uint8_t *pu8TxBuffer, uint16_t u16Size)
Transmit an amount via I²C.
Definition: MCAL.c:149
@ I2C_MEMSIZE_8BIT
I²C memory address size (8-Bit)
Definition: MCAL.h:32
@ GPIO_PORT_A
GPIO port A.
Definition: MCAL.h:19
SPI_HandleTypeDef hspi1
SPI 1 handle.
Definition: System.c:47