1 /**
2 ******************************************************************************
3 * @file stm32u5xx_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) 2021 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 "stm32u5xx_hal.h"
53
54 /** @addtogroup STM32U5xx_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
65 /**
66 @cond 0
67 */
68
69 /* Private typedef -----------------------------------------------------------*/
70 /* Private define ------------------------------------------------------------*/
71 #define DLYB_TIMEOUT 0xFFU
72 #define DLYB_LNG_10_0_MASK 0x07FF0000U
73 #define DLYB_LNG_11_10_MASK 0x0C000000U
74 /* Private macro -------------------------------------------------------------*/
75 /* Private variables ---------------------------------------------------------*/
76 /* Private function prototypes -----------------------------------------------*/
77
78 /**
79 @endcond
80 */
81
82 /* Exported functions --------------------------------------------------------*/
83
84 /** @addtogroup DLYB_LL_Exported_Functions
85 * @brief Configuration and control functions
86 *
87 @verbatim
88 ===============================================================================
89 ##### Control functions #####
90 ===============================================================================
91 [..] This section provides functions allowing to
92 (+) Control the DLYB.
93 @endverbatim
94 * @{
95 */
96
97 /** @addtogroup DLYB_Control_Functions DLYB Control functions
98 * @{
99 */
100
101 /**
102 * @brief Set the Delay value configured on SEL and UNIT.
103 * @param DLYBx: Pointer to DLYB instance.
104 * @param pdlyb_cfg: Pointer to DLYB configuration structure.
105 * @retval An ErrorStatus enumeration value:
106 * - SUCCESS: the Delay value is set.
107 * - ERROR: the Delay value is not set.
108 */
LL_DLYB_SetDelay(DLYB_TypeDef * DLYBx,LL_DLYB_CfgTypeDef * pdlyb_cfg)109 void LL_DLYB_SetDelay(DLYB_TypeDef *DLYBx, LL_DLYB_CfgTypeDef *pdlyb_cfg)
110 {
111 /* Check the DelayBlock instance */
112 assert_param(IS_DLYB_ALL_INSTANCE(DLYBx));
113
114 /* Enable the length sampling */
115 SET_BIT(DLYBx->CR, DLYB_CR_SEN);
116
117 /* Update the UNIT and SEL field */
118 DLYBx->CFGR = (pdlyb_cfg->PhaseSel) | ((pdlyb_cfg->Units) << DLYB_CFGR_UNIT_Pos);
119
120 /* Disable the length sampling */
121 CLEAR_BIT(DLYBx->CR, DLYB_CR_SEN);
122 }
123
124 /**
125 * @brief Get the Delay value configured on SEL and UNIT.
126 * @param DLYBx: Pointer to DLYB instance.
127 * @param pdlyb_cfg: Pointer to DLYB configuration structure.
128 * @retval An ErrorStatus enumeration value:
129 * - SUCCESS: the Delay value is received.
130 * - ERROR: the Delay value is not received.
131 */
LL_DLYB_GetDelay(DLYB_TypeDef * DLYBx,LL_DLYB_CfgTypeDef * pdlyb_cfg)132 void LL_DLYB_GetDelay(DLYB_TypeDef *DLYBx, LL_DLYB_CfgTypeDef *pdlyb_cfg)
133 {
134 /* Check the DelayBlock instance */
135 assert_param(IS_DLYB_ALL_INSTANCE(DLYBx));
136
137 /* Fill the DelayBlock configuration structure with SEL and UNIT value */
138 pdlyb_cfg->Units = ((DLYBx->CFGR & DLYB_CFGR_UNIT) >> DLYB_CFGR_UNIT_Pos);
139 pdlyb_cfg->PhaseSel = (DLYBx->CFGR & DLYB_CFGR_SEL);
140 }
141
142 /**
143 * @brief Get the clock period.
144 * @param DLYBx: Pointer to DLYB instance.
145 * @param pdlyb_cfg: Pointer to DLYB configuration structure.
146 * @retval An ErrorStatus enumeration value:
147 * - SUCCESS: there is a valid period detected and stored in pdlyb_cfg.
148 * - ERROR: there is no valid period detected.
149 */
LL_DLYB_GetClockPeriod(DLYB_TypeDef * DLYBx,LL_DLYB_CfgTypeDef * pdlyb_cfg)150 uint32_t LL_DLYB_GetClockPeriod(DLYB_TypeDef *DLYBx, LL_DLYB_CfgTypeDef *pdlyb_cfg)
151 {
152 uint32_t i = 0U;
153 uint32_t nb ;
154 uint32_t lng ;
155 uint32_t tickstart;
156
157 /* Check the DelayBlock instance */
158 assert_param(IS_DLYB_ALL_INSTANCE(DLYBx));
159
160 /* Enable the length sampling */
161 SET_BIT(DLYBx->CR, DLYB_CR_SEN);
162
163 /* Delay line length detection */
164 while (i < DLYB_MAX_UNIT)
165 {
166 /* Set the Delay of the UNIT(s)*/
167 DLYBx->CFGR = DLYB_MAX_SELECT | (i << DLYB_CFGR_UNIT_Pos);
168
169 /* Waiting for a LNG valid value */
170 tickstart = HAL_GetTick();
171 while ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)
172 {
173 if ((HAL_GetTick() - tickstart) >= DLYB_TIMEOUT)
174 {
175 /* New check to avoid false timeout detection in case of preemption */
176 if ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)
177 {
178 return (uint32_t) HAL_TIMEOUT;
179 }
180 }
181 }
182
183 if ((DLYBx->CFGR & DLYB_LNG_10_0_MASK) != 0U)
184 {
185 if ((DLYBx->CFGR & (DLYB_CFGR_LNG_11 | DLYB_CFGR_LNG_10)) != DLYB_LNG_11_10_MASK)
186 {
187 /* Delay line length is configured to one input clock period*/
188 break;
189 }
190 }
191 i++;
192 }
193
194 if (DLYB_MAX_UNIT != i)
195 {
196 /* Determine how many unit delays (nb) span one input clock period */
197 lng = (DLYBx->CFGR & DLYB_CFGR_LNG) >> 16U;
198 nb = 10U;
199 while ((nb > 0U) && ((lng >> nb) == 0U))
200 {
201 nb--;
202 }
203 if (nb != 0U)
204 {
205 pdlyb_cfg->PhaseSel = nb ;
206 pdlyb_cfg->Units = i ;
207
208 /* Disable the length sampling */
209 DLYBx->CR = DLYB_CR_SEN;
210
211 return (uint32_t)SUCCESS;
212 }
213 }
214
215 /* Disable the length sampling */
216 DLYBx->CR = DLYB_CR_SEN;
217
218 return (uint32_t)ERROR;
219
220 }
221
222 /**
223 * @}
224 */
225
226 /**
227 * @}
228 */
229
230 /**
231 * @}
232 */
233 #endif /* HAL_SD_MODULE_ENABLED || HAL_OSPI_MODULE_ENABLED || HAL_XSPI_MODULE_ENABLED */
234
235 /**
236 * @}
237 */
238
239 /**
240 * @}
241 */
242