summaryrefslogtreecommitdiffstats
path: root/bsps/arm/stm32h7/hal/stm32h7xx_ll_delayblock.c
blob: 2c1f9696c378d6b3d5a8b4bdbade5aa24ea2bbb3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/**
  ******************************************************************************
  * @file    stm32h7xx_ll_delayblock.c
  * @author  MCD Application Team
  * @brief   DelayBlock Low Layer HAL module driver.
  *    
  *          This file provides firmware functions to manage the following 
  *          functionalities of the Delay Block peripheral:
  *           + input clock frequency range 25MHz to 208MHz
  *           + up to 12 oversampling phases
  *         
  @verbatim
  ==============================================================================
                       ##### DelayBlock peripheral features #####
  ==============================================================================        
    [..] The Delay block is used to generate an Output clock which is de-phased from the Input
          clock. The phase of the Output clock is programmed by FW. The Output clock is then used
          to clock the receive data in i.e. a SDMMC or QSPI interface.
         The delay is Voltage and Temperature dependent, which may require FW to do re-tuning
          and recenter the Output clock phase to the receive data.
    
    [..] The Delay Block features include the following:
         (+) Input clock frequency range 25MHz to 208MHz.
         (+) Up to 12 oversampling phases.
         
                           ##### How to use this driver #####
  ==============================================================================
    [..]
      This driver is a considered as a driver of service for external devices drivers
      that interfaces with the DELAY peripheral.
      The DelayBlock_Enable() function, enables the DelayBlock instance, configure the delay line length
      and configure the Output clock phase.
      The DelayBlock_Disable() function, disables the DelayBlock instance by setting DEN flag to 0.
      
  
  @endverbatim
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"

/** @addtogroup STM32H7xx_HAL_Driver
  * @{
  */

/** @defgroup DELAYBLOCK_LL DELAYBLOCK_LL
  * @ingroup RTEMSBSPsARMSTM32H7
  * @brief Low layer module for Delay Block
  * @{
  */

#if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_QSPI_MODULE_ENABLED)

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define DLYB_TIMEOUT 0xFFU
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

/** @defgroup DelayBlock_LL_Exported_Functions Delay Block Low Layer Exported Functions
  * @ingroup RTEMSBSPsARMSTM32H7
  * @{
  */

/** @defgroup HAL_DELAY_LL_Group1 Initialization de-initialization functions 
  * @ingroup RTEMSBSPsARMSTM32H7
 *  @brief    Initialization and Configuration functions 
 *
@verbatim    
 ===============================================================================
              ##### Initialization and de-initialization functions #####
 ===============================================================================
    [..]  This section provides functions allowing to:
 
@endverbatim
  * @{
  */


/**
  * @brief  Enable the Delay Block instance.
  * @param  DLYBx: Pointer to DLYB instance.
  * @retval HAL status
  */
HAL_StatusTypeDef DelayBlock_Enable(DLYB_TypeDef *DLYBx)
{
  uint32_t unit = 0U;
  uint32_t sel = 0U;
  uint32_t sel_current;
  uint32_t unit_current;
  uint32_t tuning;
  uint32_t lng_mask;
  uint32_t tickstart;

  DLYBx->CR = DLYB_CR_DEN | DLYB_CR_SEN;

  for (sel_current = 0U; sel_current < DLYB_MAX_SELECT; sel_current++)
  {
    /* lng_mask is the mask bit for the LNG field to check the output of the UNITx*/
    lng_mask = DLYB_CFGR_LNG_0 << sel_current;
    tuning = 0U;
    for (unit_current = 0U; unit_current < DLYB_MAX_UNIT; unit_current++)
    {
      /* Set the Delay of the UNIT(s)*/
      DLYBx->CFGR = DLYB_MAX_SELECT | (unit_current << DLYB_CFGR_UNIT_Pos);

      /* Waiting for a LNG valid value */
      tickstart =  HAL_GetTick();
      while ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)
      {
        if((HAL_GetTick() - tickstart) >=  DLYB_TIMEOUT)
        {
          return HAL_TIMEOUT;
        }
      }
      if (tuning == 0U)
      {
        if ((DLYBx->CFGR & lng_mask) != 0U)
        {
          /* 1/2 period HIGH is detected */
          tuning = 1U;
        }
      }
      else
      {
        /* 1/2 period LOW detected after the HIGH 1/2 period => FULL PERIOD passed*/
        if((DLYBx->CFGR & lng_mask ) == 0U)
        {
          /* Save the first result */
          if( unit == 0U )
          {
            unit = unit_current;
            sel  = sel_current + 1U;
          }
          break;
        }
      }
    }
  }

  /* Apply the Tuning settings */
  DLYBx->CR   = 0U;
  DLYBx->CR   = DLYB_CR_DEN | DLYB_CR_SEN;
  DLYBx->CFGR = sel | (unit << DLYB_CFGR_UNIT_Pos);
  DLYBx->CR   = DLYB_CR_DEN;

  return HAL_OK;
}

/**
  * @brief  Disable the Delay Block instance.
  * @param  DLYBx: Pointer to DLYB instance.
  * @retval HAL status
  */
HAL_StatusTypeDef DelayBlock_Disable(DLYB_TypeDef *DLYBx)
{
  /* Disable DLYB */
  DLYBx->CR = 0U;
  return HAL_OK;
}

/**
  * @brief  Configure the Delay Block instance.
  * @param  DLYBx: Pointer to DLYB instance.
  * @param  PhaseSel: Phase selection [0..11].
  * @param  Units: Delay units[0..127].
  * @retval HAL status
  */
HAL_StatusTypeDef DelayBlock_Configure(DLYB_TypeDef *DLYBx,uint32_t PhaseSel, uint32_t Units )
{
  /* Apply the delay settings */

  DLYBx->CR   = 0U;
  DLYBx->CR   = DLYB_CR_DEN | DLYB_CR_SEN;
  DLYBx->CFGR = PhaseSel | (Units << DLYB_CFGR_UNIT_Pos);
  DLYBx->CR   = DLYB_CR_DEN;

  return HAL_OK;
}


/**
  * @}
  */

/**
  * @}
  */

#endif /* (HAL_SD_MODULE_ENABLED) & (HAL_QSPI_MODULE_ENABLED)*/
/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/