1 /**
2 ******************************************************************************
3 * @file stm32h5xx_ll_dlyb.c
4 * @author MCD Application Team
5 * @brief DelayBlock Low Layer HAL module driver.
6 *
7 * This file provides firmware functions to manage the following
8 * functionalities of the DelayBlock peripheral:
9 * + input clock frequency
10 * + up to 12 oversampling phases
11 *
12 ******************************************************************************
13 * @attention
14 *
15 * Copyright (c) 2023 STMicroelectronics.
16 * All rights reserved.
17 *
18 * This software is licensed under terms that can be found in the LICENSE file
19 * in the root directory of this software component.
20 * If no LICENSE file comes with this software, it is provided AS-IS.
21 *
22 ******************************************************************************
23 @verbatim
24 ==============================================================================
25 ##### DelayBlock peripheral features #####
26 ==============================================================================
27 [..] The DelayBlock is used to generate an Output clock which is de-phased from the Input
28 clock. The phase of the Output clock is programmed by FW. The Output clock is then used
29 to clock the receive data in i.e. a SDMMC, OSPI or QSPI interface.
30 The delay is Voltage and Temperature dependent, which may require FW to do re-tuning
31 and recenter the Output clock phase to the receive data.
32
33 [..] The DelayBlock features include the following:
34 (+) Input clock frequency.
35 (+) Up to 12 oversampling phases.
36
37 ##### How to use this driver #####
38 ==============================================================================
39 [..]
40 This driver is a considered as a driver of service for external devices drivers
41 that interfaces with the DELAY peripheral.
42 The LL_DLYB_SetDelay() function, configure the Delay value configured on SEL and UNIT.
43 The LL_DLYB_GetDelay() function, return the Delay value configured on SEL and UNIT.
44 The LL_DLYB_GetClockPeriod()function, get the clock period.
45
46
47 @endverbatim
48 ******************************************************************************
49 */
50
51 /* Includes ------------------------------------------------------------------*/
52 #include "stm32h5xx_hal.h"
53
54 /** @addtogroup STM32H5xx_LL_Driver
55 * @{
56 */
57
58 /** @defgroup DLYB_LL DLYB
59 * @brief DLYB LL module driver.
60 * @{
61 */
62
63 #if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_OSPI_MODULE_ENABLED) || defined(HAL_XSPI_MODULE_ENABLED)
64 #if defined (DLYB_SDMMC1) || defined (DLYB_SDMMC2) || defined (DLYB_OCTOSPI1) || defined (DLYB_OCTOSPI2)
65
66 /**
67 @cond 0
68 */
69
70 /* Private typedef -----------------------------------------------------------*/
71 /* Private define ------------------------------------------------------------*/
72 #define DLYB_TIMEOUT 0xFFU
73 #define DLYB_LNG_10_0_MASK 0x07FF0000U
74 #define DLYB_LNG_11_10_MASK 0x0C000000U
75 /* Private macro -------------------------------------------------------------*/
76 /* Private variables ---------------------------------------------------------*/
77 /* Private function prototypes -----------------------------------------------*/
78
79 /**
80 @endcond
81 */
82
83 /* Exported functions --------------------------------------------------------*/
84
85 /** @addtogroup DLYB_LL_Exported_Functions
86 * @brief Configuration and control functions
87 *
88 @verbatim
89 ===============================================================================
90 ##### Control functions #####
91 ===============================================================================
92 [..] This section provides functions allowing to
93 (+) Control the DLYB.
94 @endverbatim
95 * @{
96 */
97
98 /** @addtogroup DLYB_Control_Functions DLYB Control functions
99 * @{
100 */
101
102 /**
103 * @brief Set the Delay value configured on SEL and UNIT.
104 * @param DLYBx: Pointer to DLYB instance.
105 * @param pdlyb_cfg: Pointer to DLYB configuration structure.
106 * @retval An ErrorStatus enumeration value:
107 * - SUCCESS: the Delay value is set.
108 * - ERROR: the Delay value is not set.
109 */
LL_DLYB_SetDelay(DLYB_TypeDef * DLYBx,LL_DLYB_CfgTypeDef * pdlyb_cfg)110 void LL_DLYB_SetDelay(DLYB_TypeDef *DLYBx, LL_DLYB_CfgTypeDef *pdlyb_cfg)
111 {
112 /* Check the DelayBlock instance */
113 assert_param(IS_DLYB_ALL_INSTANCE(DLYBx));
114
115 /* Enable the length sampling */
116 SET_BIT(DLYBx->CR, DLYB_CR_SEN);
117
118 /* Update the UNIT and SEL field */
119 DLYBx->CFGR = (pdlyb_cfg->PhaseSel) | ((pdlyb_cfg->Units) << DLYB_CFGR_UNIT_Pos);
120
121 /* Disable the length sampling */
122 CLEAR_BIT(DLYBx->CR, DLYB_CR_SEN);
123 }
124
125 /**
126 * @brief Get the Delay value configured on SEL and UNIT.
127 * @param DLYBx: Pointer to DLYB instance.
128 * @param pdlyb_cfg: Pointer to DLYB configuration structure.
129 * @retval An ErrorStatus enumeration value:
130 * - SUCCESS: the Delay value is received.
131 * - ERROR: the Delay value is not received.
132 */
LL_DLYB_GetDelay(DLYB_TypeDef * DLYBx,LL_DLYB_CfgTypeDef * pdlyb_cfg)133 void LL_DLYB_GetDelay(DLYB_TypeDef *DLYBx, LL_DLYB_CfgTypeDef *pdlyb_cfg)
134 {
135 /* Check the DelayBlock instance */
136 assert_param(IS_DLYB_ALL_INSTANCE(DLYBx));
137
138 /* Fill the DelayBlock configuration structure with SEL and UNIT value */
139 pdlyb_cfg->Units = ((DLYBx->CFGR & DLYB_CFGR_UNIT) >> DLYB_CFGR_UNIT_Pos);
140 pdlyb_cfg->PhaseSel = (DLYBx->CFGR & DLYB_CFGR_SEL);
141 }
142
143 /**
144 * @brief Get the clock period.
145 * @param DLYBx: Pointer to DLYB instance.
146 * @param pdlyb_cfg: Pointer to DLYB configuration structure.
147 * @retval An ErrorStatus enumeration value:
148 * - SUCCESS: there is a valid period detected and stored in pdlyb_cfg.
149 * - ERROR: there is no valid period detected.
150 */
LL_DLYB_GetClockPeriod(DLYB_TypeDef * DLYBx,LL_DLYB_CfgTypeDef * pdlyb_cfg)151 uint32_t LL_DLYB_GetClockPeriod(DLYB_TypeDef *DLYBx, LL_DLYB_CfgTypeDef *pdlyb_cfg)
152 {
153 uint32_t i = 0U;
154 uint32_t nb ;
155 uint32_t lng ;
156 uint32_t tickstart;
157
158 /* Check the DelayBlock instance */
159 assert_param(IS_DLYB_ALL_INSTANCE(DLYBx));
160
161 /* Enable the length sampling */
162 SET_BIT(DLYBx->CR, DLYB_CR_SEN);
163
164 /* Delay line length detection */
165 while (i < DLYB_MAX_UNIT)
166 {
167 /* Set the Delay of the UNIT(s)*/
168 DLYBx->CFGR = DLYB_MAX_SELECT | (i << DLYB_CFGR_UNIT_Pos);
169
170 /* Waiting for a LNG valid value */
171 tickstart = HAL_GetTick();
172 while ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)
173 {
174 if ((HAL_GetTick() - tickstart) >= DLYB_TIMEOUT)
175 {
176 /* New check to avoid false timeout detection in case of preemption */
177 if ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)
178 {
179 return (uint32_t) HAL_TIMEOUT;
180 }
181 }
182 }
183
184 if ((DLYBx->CFGR & DLYB_LNG_10_0_MASK) != 0U)
185 {
186 if ((DLYBx->CFGR & (DLYB_CFGR_LNG_11 | DLYB_CFGR_LNG_10)) != DLYB_LNG_11_10_MASK)
187 {
188 /* Delay line length is configured to one input clock period*/
189 break;
190 }
191 }
192 i++;
193 }
194
195 if (DLYB_MAX_UNIT != i)
196 {
197 /* Determine how many unit delays (nb) span one input clock period */
198 lng = (DLYBx->CFGR & DLYB_CFGR_LNG) >> 16U;
199 nb = 10U;
200 while ((nb > 0U) && ((lng >> nb) == 0U))
201 {
202 nb--;
203 }
204 if (nb != 0U)
205 {
206 pdlyb_cfg->PhaseSel = nb ;
207 pdlyb_cfg->Units = i ;
208
209 /* Disable the length sampling */
210 DLYBx->CR = DLYB_CR_SEN;
211
212 return (uint32_t)SUCCESS;
213 }
214 }
215
216 /* Disable the length sampling */
217 DLYBx->CR = DLYB_CR_SEN;
218
219 return (uint32_t)ERROR;
220
221 }
222
223 /**
224 * @}
225 */
226
227 /**
228 * @}
229 */
230
231 /**
232 * @}
233 */
234 #endif /* DLYB_SDMMC1 || DLYB_SDMMC2 || DLYB_OCTOSPI1 || DLYB_OCTOSPI2 */
235 #endif /* HAL_SD_MODULE_ENABLED || HAL_OSPI_MODULE_ENABLED || HAL_XSPI_MODULE_ENABLED */
236
237 /**
238 * @}
239 */
240
241 /**
242 * @}
243 */
244