1 /**
2   ******************************************************************************
3   * @file    stm32u5xx_hal_spi_ex.c
4   * @author  MCD Application Team
5   * @brief   Extended SPI HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          SPI peripheral extended functionalities :
8   *           + IO operation functions
9   *           + Peripheral Control functions
10   *
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2021 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22   */
23 
24 /* Includes ------------------------------------------------------------------*/
25 #include "stm32u5xx_hal.h"
26 
27 /** @addtogroup STM32U5xx_HAL_Driver
28   * @{
29   */
30 
31 /** @defgroup SPIEx SPIEx
32   * @brief SPI Extended HAL module driver
33   * @{
34   */
35 #ifdef HAL_SPI_MODULE_ENABLED
36 
37 /* Private typedef -----------------------------------------------------------*/
38 /* Private defines -----------------------------------------------------------*/
39 /* Private macros ------------------------------------------------------------*/
40 /* Private variables ---------------------------------------------------------*/
41 /* Private function prototypes -----------------------------------------------*/
42 /* Exported functions --------------------------------------------------------*/
43 
44 /** @defgroup SPIEx_Exported_Functions SPIEx Exported Functions
45   * @{
46   */
47 
48 /** @defgroup SPIEx_Exported_Functions_Group1 IO operation functions
49   *  @brief   Data transfers functions
50   *
51 @verbatim
52   ==============================================================================
53                       ##### IO operation functions #####
54  ===============================================================================
55  [..]
56     This subsection provides a set of extended functions to manage the SPI
57     data transfers.
58 
59     (#) SPIEx function:
60         (++) HAL_SPIEx_FlushRxFifo()
61         (++) HAL_SPIEx_EnableLockConfiguration()
62         (++) HAL_SPIEx_ConfigureUnderrun()
63 
64 @endverbatim
65   * @{
66   */
67 
68 /**
69   * @brief Flush the RX fifo.
70   * @param  hspi: pointer to a SPI_HandleTypeDef structure that contains
71   *               the configuration information for the specified SPI module.
72   * @retval HAL status
73   */
HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef * hspi)74 HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(const SPI_HandleTypeDef *hspi)
75 {
76   uint8_t  count  = 0;
77   uint32_t itflag = hspi->Instance->SR;
78   __IO uint32_t tmpreg;
79 
80   while (((hspi->Instance->SR & SPI_FLAG_FRLVL) !=  SPI_RX_FIFO_0PACKET) || ((itflag & SPI_FLAG_RXWNE) !=  0UL))
81   {
82     count += (uint8_t)4UL;
83     tmpreg = hspi->Instance->RXDR;
84     UNUSED(tmpreg); /* To avoid GCC warning */
85 
86     if (IS_SPI_FULL_INSTANCE(hspi->Instance))
87     {
88       if (count > SPI_HIGHEND_FIFO_SIZE)
89       {
90         return HAL_TIMEOUT;
91       }
92     }
93     else
94     {
95       if (count > SPI_LOWEND_FIFO_SIZE)
96       {
97         return HAL_TIMEOUT;
98       }
99     }
100   }
101   return HAL_OK;
102 }
103 
104 
105 /**
106   * @brief  Enable the Lock for the AF configuration of associated IOs
107   *         and write protect the Content of Configuration register 2
108   *         when SPI is enabled
109   * @param  hspi: pointer to a SPI_HandleTypeDef structure that contains
110   *               the configuration information for SPI module.
111   * @retval None
112   */
HAL_SPIEx_EnableLockConfiguration(SPI_HandleTypeDef * hspi)113 HAL_StatusTypeDef HAL_SPIEx_EnableLockConfiguration(SPI_HandleTypeDef *hspi)
114 {
115   HAL_StatusTypeDef errorcode = HAL_OK;
116 
117   /* Process Locked */
118   __HAL_LOCK(hspi);
119 
120   if (hspi->State != HAL_SPI_STATE_READY)
121   {
122     errorcode = HAL_BUSY;
123     hspi->State = HAL_SPI_STATE_READY;
124     /* Process Unlocked */
125     __HAL_UNLOCK(hspi);
126     return errorcode;
127   }
128 
129   /* Check if the SPI is disabled to edit IOLOCK bit */
130   if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
131   {
132     SET_BIT(hspi->Instance->CR1, SPI_CR1_IOLOCK);
133   }
134   else
135   {
136     /* Disable SPI peripheral */
137     __HAL_SPI_DISABLE(hspi);
138 
139     SET_BIT(hspi->Instance->CR1, SPI_CR1_IOLOCK);
140 
141     /* Enable SPI peripheral */
142     __HAL_SPI_ENABLE(hspi);
143   }
144 
145   hspi->State = HAL_SPI_STATE_READY;
146   /* Process Unlocked */
147   __HAL_UNLOCK(hspi);
148   return errorcode;
149 }
150 
151 /**
152   * @brief  Configure the UNDERRUN condition and behavior of slave transmitter.
153   * @param  hspi: pointer to a SPI_HandleTypeDef structure that contains
154   *               the configuration information for SPI module.
155   * @param  UnderrunDetection : Detection of underrun condition at slave transmitter
156   *                             This parameter is not supported in this SPI version.
157   *                             It is kept in order to not break the compatibility.
158   * @param  UnderrunBehaviour : Behavior of slave transmitter at underrun condition
159   *                             This parameter can be a value of @ref SPI_Underrun_Behaviour.
160   * @retval None
161   */
HAL_SPIEx_ConfigureUnderrun(SPI_HandleTypeDef * hspi,uint32_t UnderrunDetection,uint32_t UnderrunBehaviour)162 HAL_StatusTypeDef HAL_SPIEx_ConfigureUnderrun(SPI_HandleTypeDef *hspi, uint32_t UnderrunDetection,
163                                               uint32_t UnderrunBehaviour)
164 {
165   /* Prevent unused argument(s) compilation warning */
166   UNUSED(UnderrunDetection);
167 
168   HAL_StatusTypeDef errorcode = HAL_OK;
169 
170   /* Process Locked */
171   __HAL_LOCK(hspi);
172 
173   /* Check State and Insure that Underrun configuration is managed only by Salve */
174   if ((hspi->State != HAL_SPI_STATE_READY) || (hspi->Init.Mode != SPI_MODE_SLAVE))
175   {
176     errorcode = HAL_BUSY;
177     hspi->State = HAL_SPI_STATE_READY;
178     /* Process Unlocked */
179     __HAL_UNLOCK(hspi);
180     return errorcode;
181   }
182 
183   /* Check the parameters */
184   assert_param(IS_SPI_UNDERRUN_BEHAVIOUR(UnderrunBehaviour));
185 
186   /* Check if the SPI is disabled to edit CFG1 register */
187   if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
188   {
189     /* Configure Underrun fields */
190     MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRCFG, UnderrunBehaviour);
191   }
192   else
193   {
194     /* Disable SPI peripheral */
195     __HAL_SPI_DISABLE(hspi);
196 
197     /* Configure Underrun fields */
198     MODIFY_REG(hspi->Instance->CFG1, SPI_CFG1_UDRCFG, UnderrunBehaviour);
199 
200     /* Enable SPI peripheral */
201     __HAL_SPI_ENABLE(hspi);
202   }
203 
204 
205   hspi->State = HAL_SPI_STATE_READY;
206   /* Process Unlocked */
207   __HAL_UNLOCK(hspi);
208   return errorcode;
209 }
210 
211 /**
212   * @brief  Set Autonomous Mode configuration
213   * @param  hspi Pointer to a SPI_HandleTypeDef structure that contains
214   *                the configuration information for the specified SPIx peripheral.
215   * @param  sConfig Pointer to a SPI_HandleTypeDef structure that contains
216   *                the configuration information of the autonomous mode for the specified SPIx peripheral.
217   * @retval HAL status
218   */
HAL_SPIEx_SetConfigAutonomousMode(SPI_HandleTypeDef * hspi,const SPI_AutonomousModeConfTypeDef * sConfig)219 HAL_StatusTypeDef HAL_SPIEx_SetConfigAutonomousMode(SPI_HandleTypeDef *hspi,
220                                                     const SPI_AutonomousModeConfTypeDef *sConfig)
221 {
222   if (hspi->State == HAL_SPI_STATE_READY)
223   {
224     /* Process Locked */
225     __HAL_LOCK(hspi);
226 
227     hspi->State = HAL_SPI_STATE_BUSY;
228 
229     /* Check the parameters */
230     assert_param(IS_SPI_AUTONOMOUS_INSTANCE(hspi->Instance));
231     assert_param(IS_SPI_TRIG_SOURCE(hspi->Instance, sConfig->TriggerSelection));
232     assert_param(IS_SPI_AUTO_MODE_TRG_POL(sConfig->TriggerPolarity));
233 
234     /* Disable the selected SPI peripheral to be able to configure AUTOCR */
235     __HAL_SPI_DISABLE(hspi);
236 
237     /* SPIx AUTOCR Configuration */
238     WRITE_REG(hspi->Instance->AUTOCR, (sConfig->TriggerState | ((sConfig->TriggerSelection) & SPI_AUTOCR_TRIGSEL_Msk) |
239                                        sConfig->TriggerPolarity));
240 
241     hspi->State = HAL_SPI_STATE_READY;
242 
243     /* Process Unlocked */
244     __HAL_UNLOCK(hspi);
245 
246     return HAL_OK;
247   }
248   else
249   {
250     return HAL_ERROR;
251   }
252 }
253 
254 /**
255   * @brief  Get Autonomous Mode configuration
256   * @param  hspi Pointer to a SPI_HandleTypeDef structure that contains
257   *                the configuration information for the specified SPIx peripheral.
258   * @param  sConfig Pointer to a SPI_HandleTypeDef structure that contains
259   *                the configuration information of the autonomous mode for the specified SPIx peripheral.
260   * @retval HAL status
261   */
HAL_SPIEx_GetConfigAutonomousMode(const SPI_HandleTypeDef * hspi,SPI_AutonomousModeConfTypeDef * sConfig)262 HAL_StatusTypeDef HAL_SPIEx_GetConfigAutonomousMode(const SPI_HandleTypeDef *hspi,
263                                                     SPI_AutonomousModeConfTypeDef *sConfig)
264 {
265   uint32_t autocr_tmp;
266 
267   /* Check the parameters */
268   assert_param(IS_SPI_AUTONOMOUS_INSTANCE(hspi->Instance));
269 
270   autocr_tmp = hspi->Instance->AUTOCR;
271 
272   sConfig->TriggerState     = (autocr_tmp & SPI_AUTOCR_TRIGEN);
273 #if defined(SPI_TRIG_GRP2)
274   if (IS_SPI_GRP2_INSTANCE(hspi->Instance))
275   {
276     sConfig->TriggerSelection = ((autocr_tmp & SPI_AUTOCR_TRIGSEL) | SPI_TRIG_GRP2);
277   }
278   else
279   {
280     sConfig->TriggerSelection = ((autocr_tmp & SPI_AUTOCR_TRIGSEL) | SPI_TRIG_GRP1);
281   }
282 #else
283   sConfig->TriggerSelection = ((autocr_tmp & SPI_AUTOCR_TRIGSEL) | SPI_TRIG_GRP1);
284 #endif /* SPI_TRIG_GRP2 */
285   sConfig->TriggerPolarity  = (autocr_tmp & SPI_AUTOCR_TRIGPOL);
286 
287   return HAL_OK;
288 }
289 
290 /**
291   * @brief  Clear Autonomous Mode configuration
292   * @param  hspi Pointer to a SPI_HandleTypeDef structure that contains
293   *                the configuration information for the specified SPIx peripheral.
294   * @retval HAL status
295   */
HAL_SPIEx_ClearConfigAutonomousMode(SPI_HandleTypeDef * hspi)296 HAL_StatusTypeDef HAL_SPIEx_ClearConfigAutonomousMode(SPI_HandleTypeDef *hspi)
297 {
298   if (hspi->State == HAL_SPI_STATE_READY)
299   {
300     /* Process Locked */
301     __HAL_LOCK(hspi);
302 
303     hspi->State = HAL_SPI_STATE_BUSY;
304 
305     /* Check the parameters */
306     assert_param(IS_SPI_AUTONOMOUS_INSTANCE(hspi->Instance));
307 
308     /* Disable the selected SPI peripheral to be able to clear AUTOCR */
309     __HAL_SPI_DISABLE(hspi);
310 
311     CLEAR_REG(hspi->Instance->AUTOCR);
312 
313     /* Enable the selected SPI peripheral */
314     __HAL_SPI_ENABLE(hspi);
315 
316     hspi->State = HAL_SPI_STATE_READY;
317 
318     /* Process Unlocked */
319     __HAL_UNLOCK(hspi);
320 
321     return HAL_OK;
322   }
323   else
324   {
325     return HAL_ERROR;
326   }
327 }
328 
329 /**
330   * @}
331   */
332 
333 /**
334   * @}
335   */
336 
337 #endif /* HAL_SPI_MODULE_ENABLED */
338 
339 /**
340   * @}
341   */
342 
343 /**
344   * @}
345   */
346